initial commit with v2.6.9
[linux-2.6.9-moxart.git] / sound / usb / usx2y / usbusx2yaudio.c
blobd860c7325af367e347badc7bc6a3e12cd6190e01
1 /*
2 * US-428 AUDIO
4 * Copyright (c) 2002-2003 by Karsten Wiese
6 * based on
8 * (Tentative) USB Audio Driver for ALSA
10 * Main and PCM part
12 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
14 * Many codes borrowed from audio.c by
15 * Alan Cox (alan@lxorguk.ukuu.org.uk)
16 * Thomas Sailer (sailer@ife.ee.ethz.ch)
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #include <sound/driver.h>
36 #include <linux/interrupt.h>
37 #include <linux/usb.h>
38 #include <sound/core.h>
39 #include <sound/info.h>
40 #include <sound/pcm.h>
41 #include <sound/pcm_params.h>
42 #include "usx2y.h"
43 #include "usbusx2y.h"
46 struct snd_usX2Y_substream {
47 usX2Ydev_t *usX2Y;
48 snd_pcm_substream_t *pcm_substream;
50 unsigned char endpoint;
51 unsigned int datapipe; /* the data i/o pipe */
52 unsigned int maxpacksize; /* max packet size in bytes */
54 char prepared,
55 running,
56 stalled;
58 int hwptr; /* free frame position in the buffer (only for playback) */
59 int hwptr_done; /* processed frame position in the buffer */
60 int transfer_done; /* processed frames since last period update */
62 struct urb *urb[NRURBS]; /* data urb table */
63 int next_urb_complete;
64 struct urb *completed_urb;
65 char *tmpbuf; /* temporary buffer for playback */
66 volatile int submitted_urbs;
67 wait_queue_head_t wait_queue;
75 static int usX2Y_urb_capt_retire(snd_usX2Y_substream_t *subs)
77 struct urb *urb = subs->completed_urb;
78 snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
79 unsigned char *cp;
80 int i, len, lens = 0, hwptr_done = subs->hwptr_done;
81 usX2Ydev_t *usX2Y = subs->usX2Y;
83 for (i = 0; i < NRPACKS; i++) {
84 cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
85 if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
86 snd_printdd("activ frame status %i\n", urb->iso_frame_desc[i].status);
87 return urb->iso_frame_desc[i].status;
89 len = urb->iso_frame_desc[i].actual_length / usX2Y->stride;
90 if (! len) {
91 snd_printk("0 == len ERROR!\n");
92 continue;
95 /* copy a data chunk */
96 if ((hwptr_done + len) > runtime->buffer_size) {
97 int cnt = runtime->buffer_size - hwptr_done;
98 int blen = cnt * usX2Y->stride;
99 memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen);
100 memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen);
101 } else {
102 memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, len * usX2Y->stride);
104 lens += len;
105 if ((hwptr_done += len) >= runtime->buffer_size)
106 hwptr_done -= runtime->buffer_size;
109 subs->hwptr_done = hwptr_done;
110 subs->transfer_done += lens;
111 /* update the pointer, call callback if necessary */
112 if (subs->transfer_done >= runtime->period_size) {
113 subs->transfer_done -= runtime->period_size;
114 snd_pcm_period_elapsed(subs->pcm_substream);
116 return 0;
119 * prepare urb for playback data pipe
121 * we copy the data directly from the pcm buffer.
122 * the current position to be copied is held in hwptr field.
123 * since a urb can handle only a single linear buffer, if the total
124 * transferred area overflows the buffer boundary, we cannot send
125 * it directly from the buffer. thus the data is once copied to
126 * a temporary buffer and urb points to that.
128 static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs,
129 struct urb *cap_urb,
130 struct urb *urb)
132 int count, counts, pack;
133 usX2Ydev_t* usX2Y = subs->usX2Y;
134 snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
136 count = 0;
137 for (pack = 0; pack < NRPACKS; pack++) {
138 /* calculate the size of a packet */
139 counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride;
140 count += counts;
141 if (counts < 43 || counts > 50) {
142 snd_printk("should not be here with counts=%i\n", counts);
143 return -EPIPE;
146 /* set up descriptor */
147 urb->iso_frame_desc[pack].offset = pack ? urb->iso_frame_desc[pack - 1].offset + urb->iso_frame_desc[pack - 1].length : 0;
148 urb->iso_frame_desc[pack].length = counts * usX2Y->stride;
150 if (subs->hwptr + count > runtime->buffer_size) {
151 /* err, the transferred area goes over buffer boundary.
152 * copy the data to the temp buffer.
154 int len;
155 len = runtime->buffer_size - subs->hwptr;
156 urb->transfer_buffer = subs->tmpbuf;
157 memcpy(subs->tmpbuf, runtime->dma_area + subs->hwptr * usX2Y->stride, len * usX2Y->stride);
158 memcpy(subs->tmpbuf + len * usX2Y->stride, runtime->dma_area, (count - len) * usX2Y->stride);
159 subs->hwptr += count;
160 subs->hwptr -= runtime->buffer_size;
161 } else {
162 /* set the buffer pointer */
163 urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride;
164 if ((subs->hwptr += count) >= runtime->buffer_size)
165 subs->hwptr -= runtime->buffer_size;
167 urb->transfer_buffer_length = count * usX2Y->stride;
168 return 0;
172 * process after playback data complete
174 * update the current position and call callback if a period is processed.
176 inline static int usX2Y_urb_play_retire(snd_usX2Y_substream_t *subs, struct urb *urb)
178 snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
179 int len = (urb->iso_frame_desc[0].actual_length
180 #if NRPACKS > 1
181 + urb->iso_frame_desc[1].actual_length
182 #endif
183 ) / subs->usX2Y->stride;
185 subs->transfer_done += len;
186 subs->hwptr_done += len;
187 if (subs->hwptr_done >= runtime->buffer_size)
188 subs->hwptr_done -= runtime->buffer_size;
189 if (subs->transfer_done >= runtime->period_size) {
190 subs->transfer_done -= runtime->period_size;
191 snd_pcm_period_elapsed(subs->pcm_substream);
193 return 0;
196 inline static int usX2Y_urb_submit(snd_usX2Y_substream_t *subs, struct urb *urb, int frame)
198 int err;
199 if (!urb)
200 return -ENODEV;
201 urb->start_frame = (frame + NRURBS*NRPACKS) & (1024 - 1);
202 urb->hcpriv = NULL;
203 urb->dev = subs->usX2Y->chip.dev; /* we need to set this at each time */
204 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
205 snd_printk("%i\n", err);
206 return err;
207 } else {
208 subs->submitted_urbs++;
209 if (subs->next_urb_complete < 0)
210 subs->next_urb_complete = 0;
212 return 0;
216 static inline int frame_distance(int from, int to)
218 int distance = to - from;
219 if (distance < -512)
220 distance += 1024;
221 else
222 if (distance > 511)
223 distance -= 1024;
224 return distance;
228 static void usX2Y_subs_set_next_urb_complete(snd_usX2Y_substream_t *subs)
230 int next_urb_complete = subs->next_urb_complete + 1;
231 int distance;
232 if (next_urb_complete >= NRURBS)
233 next_urb_complete = 0;
234 distance = frame_distance(subs->completed_urb->start_frame,
235 subs->urb[next_urb_complete]->start_frame);
236 if (1 == distance) {
237 subs->next_urb_complete = next_urb_complete;
238 } else {
239 snd_printdd("distance %i not set_nuc %i %i %i \n", distance, subs->endpoint, next_urb_complete, subs->urb[next_urb_complete]->status);
240 subs->next_urb_complete = -1;
245 static inline void usX2Y_usbframe_complete(snd_usX2Y_substream_t *capsubs, snd_usX2Y_substream_t *playbacksubs, int frame)
248 struct urb *urb;
249 if ((urb = playbacksubs->completed_urb)) {
250 if (playbacksubs->prepared)
251 usX2Y_urb_play_retire(playbacksubs, urb);
252 usX2Y_subs_set_next_urb_complete(playbacksubs);
254 if (playbacksubs->running) {
255 if (NULL == urb)
256 urb = playbacksubs->urb[playbacksubs->next_urb_complete + 1];
257 if (urb && 0 == usX2Y_urb_play_prepare(playbacksubs,
258 capsubs->completed_urb,
259 urb)) {
260 if (usX2Y_urb_submit(playbacksubs, urb, frame) < 0)
261 return;
262 } else
263 snd_pcm_stop(playbacksubs->pcm_substream, SNDRV_PCM_STATE_XRUN);
265 playbacksubs->completed_urb = NULL;
267 if (capsubs->running)
268 usX2Y_urb_capt_retire(capsubs);
269 usX2Y_subs_set_next_urb_complete(capsubs);
270 if (capsubs->prepared)
271 usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame);
272 capsubs->completed_urb = NULL;
276 static void usX2Y_clients_stop(snd_usX2Y_substream_t *subs)
278 usX2Ydev_t *usX2Y = subs->usX2Y;
279 int i;
280 for (i = 0; i < 4; i++) {
281 snd_usX2Y_substream_t *substream = usX2Y->substream[i];
282 if (substream && substream->running)
283 snd_pcm_stop(substream->pcm_substream, SNDRV_PCM_STATE_XRUN);
288 static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
290 snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t*)urb->context;
292 subs->submitted_urbs--;
293 if (urb->status) {
294 snd_printk("ep=%i stalled with status=%i\n", subs->endpoint, urb->status);
295 subs->stalled = 1;
296 usX2Y_clients_stop(subs);
297 urb->status = 0;
298 return;
300 if (urb == subs->urb[subs->next_urb_complete]) {
301 subs->completed_urb = urb;
302 } else {
303 snd_printk("Sequence Error!(ep=%i;nuc=%i,frame=%i)\n",
304 subs->endpoint, subs->next_urb_complete, urb->start_frame);
305 subs->stalled = 1;
306 usX2Y_clients_stop(subs);
307 return;
309 if (waitqueue_active(&subs->wait_queue))
310 wake_up(&subs->wait_queue);
312 snd_usX2Y_substream_t *capsubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE],
313 *playbacksubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
314 if (capsubs->completed_urb &&
315 (playbacksubs->completed_urb ||
316 !playbacksubs->prepared ||
317 (playbacksubs->prepared && (playbacksubs->next_urb_complete < 0 || // not started yet
318 frame_distance(capsubs->completed_urb->start_frame,
319 playbacksubs->urb[playbacksubs->next_urb_complete]->start_frame)
320 > 0 || // other expected later
321 playbacksubs->stalled))))
322 usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame);
327 static int usX2Y_urbs_capt_start(snd_usX2Y_substream_t *subs)
329 int i, err;
331 for (i = 0; i < NRURBS; i++) {
332 unsigned long pack;
333 struct urb *urb = subs->urb[i];
334 urb->dev = subs->usX2Y->chip.dev;
335 urb->transfer_flags = URB_ISO_ASAP;
336 for (pack = 0; pack < NRPACKS; pack++) {
337 urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
338 urb->iso_frame_desc[pack].length = subs->maxpacksize;
340 urb->transfer_buffer_length = subs->maxpacksize * NRPACKS;
341 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
342 snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
343 return -EPIPE;
344 } else {
345 subs->submitted_urbs++;
347 urb->transfer_flags = 0;
349 subs->stalled = 0;
350 subs->next_urb_complete = 0;
351 subs->prepared = 1;
352 return 0;
356 * wait until all urbs are processed.
358 static int usX2Y_urbs_wait_clear(snd_usX2Y_substream_t *subs)
360 int timeout = HZ;
362 do {
363 if (0 == subs->submitted_urbs)
364 break;
365 set_current_state(TASK_UNINTERRUPTIBLE);
366 snd_printdd("snd_usX2Y_urbs_wait_clear waiting\n");
367 schedule_timeout(1);
368 } while (--timeout > 0);
369 if (subs->submitted_urbs)
370 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", subs->submitted_urbs);
371 return 0;
374 * return the current pcm pointer. just return the hwptr_done value.
376 static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(snd_pcm_substream_t *substream)
378 snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
379 return subs->hwptr_done;
382 * start/stop substream
384 static int snd_usX2Y_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
386 snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
388 switch (cmd) {
389 case SNDRV_PCM_TRIGGER_START:
390 snd_printdd("snd_usX2Y_pcm_trigger(START)\n");
391 if (subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE]->stalled)
392 return -EPIPE;
393 else
394 subs->running = 1;
395 break;
396 case SNDRV_PCM_TRIGGER_STOP:
397 snd_printdd("snd_usX2Y_pcm_trigger(STOP)\n");
398 subs->running = 0;
399 break;
400 default:
401 return -EINVAL;
403 return 0;
408 static void usX2Y_urb_release(struct urb** urb, int free_tb)
410 if (*urb) {
411 if (free_tb)
412 kfree((*urb)->transfer_buffer);
413 usb_free_urb(*urb);
414 *urb = NULL;
418 * release a substream
420 static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
422 int i;
423 snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint);
424 usX2Y_urbs_wait_clear(subs);
425 for (i = 0; i < NRURBS; i++)
426 usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK]);
428 if (subs->tmpbuf) {
429 kfree(subs->tmpbuf);
430 subs->tmpbuf = NULL;
434 static void usX2Y_substream_prepare(snd_usX2Y_substream_t *subs)
436 snd_printdd("usX2Y_substream_prepare() ep=%i urb0=%p urb1=%p\n", subs->endpoint, subs->urb[0], subs->urb[1]);
437 /* reset the pointer */
438 subs->hwptr = 0;
439 subs->hwptr_done = 0;
440 subs->transfer_done = 0;
445 * initialize a substream's urbs
447 static int usX2Y_urbs_allocate(snd_usX2Y_substream_t *subs)
449 int i;
450 int is_playback = subs == subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
451 struct usb_device *dev = subs->usX2Y->chip.dev;
453 snd_assert(!subs->prepared, return 0);
455 if (is_playback) { /* allocate a temporary buffer for playback */
456 subs->datapipe = usb_sndisocpipe(dev, subs->endpoint);
457 subs->maxpacksize = dev->epmaxpacketout[subs->endpoint];
458 if (NULL == subs->tmpbuf) {
459 subs->tmpbuf = kcalloc(NRPACKS, subs->maxpacksize, GFP_KERNEL);
460 if (NULL == subs->tmpbuf) {
461 snd_printk(KERN_ERR "cannot malloc tmpbuf\n");
462 return -ENOMEM;
465 } else {
466 subs->datapipe = usb_rcvisocpipe(dev, subs->endpoint);
467 subs->maxpacksize = dev->epmaxpacketin[subs->endpoint];
470 /* allocate and initialize data urbs */
471 for (i = 0; i < NRURBS; i++) {
472 struct urb** purb = subs->urb + i;
473 if (*purb)
474 continue;
475 *purb = usb_alloc_urb(NRPACKS, GFP_KERNEL);
476 if (NULL == *purb) {
477 usX2Y_urbs_release(subs);
478 return -ENOMEM;
480 if (!is_playback && !(*purb)->transfer_buffer) {
481 /* allocate a capture buffer per urb */
482 (*purb)->transfer_buffer = kmalloc(subs->maxpacksize*NRPACKS, GFP_KERNEL);
483 if (NULL == (*purb)->transfer_buffer) {
484 usX2Y_urbs_release(subs);
485 return -ENOMEM;
488 (*purb)->dev = dev;
489 (*purb)->pipe = subs->datapipe;
490 (*purb)->number_of_packets = NRPACKS;
491 (*purb)->context = subs;
492 (*purb)->interval = 1;
493 (*purb)->complete = snd_usb_complete_callback(i_usX2Y_urb_complete);
495 return 0;
498 static void i_usX2Y_04Int(struct urb* urb, struct pt_regs *regs)
500 usX2Ydev_t* usX2Y = urb->context;
502 if (urb->status) {
503 snd_printk("snd_usX2Y_04Int() urb->status=%i\n", urb->status);
504 return;
506 if (0 == --usX2Y->US04->len)
507 wake_up(&usX2Y->In04WaitQueue);
510 * allocate a buffer, setup samplerate
512 * so far we use a physically linear buffer although packetize transfer
513 * doesn't need a continuous area.
514 * if sg buffer is supported on the later version of alsa, we'll follow
515 * that.
517 static struct s_c2
519 char c1, c2;
521 SetRate44100[] =
523 { 0x14, 0x08}, // this line sets 44100, well actually a little less
524 { 0x18, 0x40}, // only tascam / frontier design knows the further lines .......
525 { 0x18, 0x42},
526 { 0x18, 0x45},
527 { 0x18, 0x46},
528 { 0x18, 0x48},
529 { 0x18, 0x4A},
530 { 0x18, 0x4C},
531 { 0x18, 0x4E},
532 { 0x18, 0x50},
533 { 0x18, 0x52},
534 { 0x18, 0x54},
535 { 0x18, 0x56},
536 { 0x18, 0x58},
537 { 0x18, 0x5A},
538 { 0x18, 0x5C},
539 { 0x18, 0x5E},
540 { 0x18, 0x60},
541 { 0x18, 0x62},
542 { 0x18, 0x64},
543 { 0x18, 0x66},
544 { 0x18, 0x68},
545 { 0x18, 0x6A},
546 { 0x18, 0x6C},
547 { 0x18, 0x6E},
548 { 0x18, 0x70},
549 { 0x18, 0x72},
550 { 0x18, 0x74},
551 { 0x18, 0x76},
552 { 0x18, 0x78},
553 { 0x18, 0x7A},
554 { 0x18, 0x7C},
555 { 0x18, 0x7E}
557 static struct s_c2 SetRate48000[] =
559 { 0x14, 0x09}, // this line sets 48000, well actually a little less
560 { 0x18, 0x40}, // only tascam / frontier design knows the further lines .......
561 { 0x18, 0x42},
562 { 0x18, 0x45},
563 { 0x18, 0x46},
564 { 0x18, 0x48},
565 { 0x18, 0x4A},
566 { 0x18, 0x4C},
567 { 0x18, 0x4E},
568 { 0x18, 0x50},
569 { 0x18, 0x52},
570 { 0x18, 0x54},
571 { 0x18, 0x56},
572 { 0x18, 0x58},
573 { 0x18, 0x5A},
574 { 0x18, 0x5C},
575 { 0x18, 0x5E},
576 { 0x18, 0x60},
577 { 0x18, 0x62},
578 { 0x18, 0x64},
579 { 0x18, 0x66},
580 { 0x18, 0x68},
581 { 0x18, 0x6A},
582 { 0x18, 0x6C},
583 { 0x18, 0x6E},
584 { 0x18, 0x70},
585 { 0x18, 0x73},
586 { 0x18, 0x74},
587 { 0x18, 0x76},
588 { 0x18, 0x78},
589 { 0x18, 0x7A},
590 { 0x18, 0x7C},
591 { 0x18, 0x7E}
593 #define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000)
595 static int usX2Y_rate_set(usX2Ydev_t *usX2Y, int rate)
597 int err = 0, i;
598 snd_usX2Y_urbSeq_t *us = NULL;
599 int *usbdata = NULL;
600 DECLARE_WAITQUEUE(wait, current);
601 struct s_c2 *ra = rate == 48000 ? SetRate48000 : SetRate44100;
603 if (usX2Y->rate != rate) {
604 do {
605 us = kmalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL);
606 if (NULL == us) {
607 err = -ENOMEM;
608 break;
610 memset(us, 0, sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS);
611 usbdata = kmalloc(sizeof(int)*NOOF_SETRATE_URBS, GFP_KERNEL);
612 if (NULL == usbdata) {
613 err = -ENOMEM;
614 break;
616 for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
617 if (NULL == (us->urb[i] = usb_alloc_urb(0, GFP_KERNEL))) {
618 err = -ENOMEM;
619 break;
621 ((char*)(usbdata + i))[0] = ra[i].c1;
622 ((char*)(usbdata + i))[1] = ra[i].c2;
623 usb_fill_bulk_urb(us->urb[i], usX2Y->chip.dev, usb_sndbulkpipe(usX2Y->chip.dev, 4),
624 usbdata + i, 2, i_usX2Y_04Int, usX2Y);
625 #ifdef OLD_USB
626 us->urb[i]->transfer_flags = USB_QUEUE_BULK;
627 #endif
629 if (err)
630 break;
632 add_wait_queue(&usX2Y->In04WaitQueue, &wait);
633 set_current_state(TASK_INTERRUPTIBLE);
634 us->submitted = 0;
635 us->len = NOOF_SETRATE_URBS;
636 usX2Y->US04 = us;
638 do {
639 signed long timeout = schedule_timeout(HZ/2);
641 if (signal_pending(current)) {
642 err = -ERESTARTSYS;
643 break;
645 if (0 == timeout) {
646 err = -ENODEV;
647 break;
649 usX2Y->rate = rate;
650 usX2Y->refframes = rate == 48000 ? 47 : 44;
651 } while (0);
653 remove_wait_queue(&usX2Y->In04WaitQueue, &wait);
654 } while (0);
656 if (us) {
657 us->submitted = 2*NOOF_SETRATE_URBS;
658 for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
659 usb_unlink_urb(us->urb[i]);
660 usb_free_urb(us->urb[i]);
662 usX2Y->US04 = NULL;
663 kfree(usbdata);
664 kfree(us);
668 return err;
672 static int usX2Y_format_set(usX2Ydev_t *usX2Y, snd_pcm_format_t format)
674 int alternate, unlink_err, err;
675 struct list_head* p;
676 if (format == SNDRV_PCM_FORMAT_S24_3LE) {
677 alternate = 2;
678 usX2Y->stride = 6;
679 } else {
680 alternate = 1;
681 usX2Y->stride = 4;
683 list_for_each(p, &usX2Y->chip.midi_list) {
684 snd_usbmidi_input_stop(p);
686 unlink_err = usb_unlink_urb(usX2Y->In04urb);
687 if ((err = usb_set_interface(usX2Y->chip.dev, 0, alternate))) {
688 snd_printk("usb_set_interface error \n");
689 return err;
691 if (0 == unlink_err) {
692 usX2Y->In04urb->dev = usX2Y->chip.dev;
693 err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
695 list_for_each(p, &usX2Y->chip.midi_list) {
696 snd_usbmidi_input_start(p);
698 usX2Y->format = format;
699 usX2Y->rate = 0;
700 return err;
704 static int snd_usX2Y_pcm_hw_params(snd_pcm_substream_t *substream,
705 snd_pcm_hw_params_t *hw_params)
707 int err = 0;
708 unsigned int rate = params_rate(hw_params);
709 snd_pcm_format_t format = params_format(hw_params);
710 snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params);
712 { // all pcm substreams off one usX2Y have to operate at the same rate & format
713 snd_card_t *card = substream->pstr->pcm->card;
714 struct list_head *list;
715 list_for_each(list, &card->devices) {
716 snd_device_t *dev;
717 snd_pcm_t *pcm;
718 int s;
719 dev = snd_device(list);
720 if (dev->type != SNDRV_DEV_PCM)
721 continue;
722 pcm = dev->device_data;
723 for (s = 0; s < 2; ++s) {
724 snd_pcm_substream_t *test_substream;
725 test_substream = pcm->streams[s].substream;
726 if (test_substream && test_substream != substream &&
727 test_substream->runtime &&
728 ((test_substream->runtime->format &&
729 test_substream->runtime->format != format) ||
730 (test_substream->runtime->rate &&
731 test_substream->runtime->rate != rate)))
732 return -EINVAL;
736 if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) {
737 snd_printk("snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err);
738 return err;
740 return 0;
744 * free the buffer
746 static int snd_usX2Y_pcm_hw_free(snd_pcm_substream_t *substream)
748 snd_pcm_runtime_t *runtime = substream->runtime;
749 snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
750 snd_printdd("snd_usX2Y_hw_free(%p)\n", substream);
752 if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
753 snd_usX2Y_substream_t *cap_subs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE];
754 subs->prepared = 0;
755 usX2Y_urbs_release(subs);
756 if (!cap_subs->pcm_substream ||
757 !cap_subs->pcm_substream->runtime ||
758 !cap_subs->pcm_substream->runtime->status ||
759 cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
760 cap_subs->prepared = 0;
761 usX2Y_urbs_release(cap_subs);
763 } else {
764 snd_usX2Y_substream_t *playback_subs = subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
765 if (!playback_subs->prepared) {
766 subs->prepared = 0;
767 usX2Y_urbs_release(subs);
771 return snd_pcm_lib_free_pages(substream);
774 * prepare callback
776 * set format and initialize urbs
778 static int snd_usX2Y_pcm_prepare(snd_pcm_substream_t *substream)
780 snd_pcm_runtime_t *runtime = substream->runtime;
781 snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
782 snd_usX2Y_substream_t *capsubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE];
783 int err = 0;
784 snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
786 // Start hardware streams
787 // SyncStream first....
788 if (! capsubs->prepared) {
789 if (subs->usX2Y->format != runtime->format)
790 if ((err = usX2Y_format_set(subs->usX2Y, runtime->format)) < 0)
791 return err;
792 if (subs->usX2Y->rate != runtime->rate)
793 if ((err = usX2Y_rate_set(subs->usX2Y, runtime->rate)) < 0)
794 return err;
795 snd_printdd("starting capture pipe for playpipe\n");
796 usX2Y_urbs_allocate(capsubs);
797 capsubs->completed_urb = NULL;
799 DECLARE_WAITQUEUE(wait, current);
800 add_wait_queue(&capsubs->wait_queue, &wait);
801 if (0 <= (err = usX2Y_urbs_capt_start(capsubs))) {
802 signed long timeout;
803 set_current_state(TASK_INTERRUPTIBLE);
804 timeout = schedule_timeout(HZ/4);
805 if (signal_pending(current))
806 err = -ERESTARTSYS;
807 else {
808 snd_printdd("%li\n", HZ/4 - timeout);
809 if (0 == timeout)
810 err = -EPIPE;
813 remove_wait_queue(&capsubs->wait_queue, &wait);
814 if (0 > err)
815 return err;
819 if (subs != capsubs) {
820 int u;
821 if (!subs->prepared) {
822 if ((err = usX2Y_urbs_allocate(subs)) < 0)
823 return err;
824 subs->prepared = 1;
826 while (subs->submitted_urbs)
827 for (u = 0; u < NRURBS; u++) {
828 snd_printdd("%i\n", subs->urb[u]->status);
829 while(subs->urb[u]->status || NULL != subs->urb[u]->hcpriv) {
830 signed long timeout;
831 snd_printdd("ep=%i waiting for urb=%p status=%i hcpriv=%p\n",
832 subs->endpoint, subs->urb[u],
833 subs->urb[u]->status, subs->urb[u]->hcpriv);
834 set_current_state(TASK_INTERRUPTIBLE);
835 timeout = schedule_timeout(HZ/10);
836 if (signal_pending(current)) {
837 return -ERESTARTSYS;
841 subs->completed_urb = NULL;
842 subs->next_urb_complete = -1;
843 subs->stalled = 0;
846 usX2Y_substream_prepare(subs);
847 return err;
850 static snd_pcm_hardware_t snd_usX2Y_2c =
852 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
853 SNDRV_PCM_INFO_BLOCK_TRANSFER |
854 SNDRV_PCM_INFO_MMAP_VALID),
855 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
856 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
857 .rate_min = 44100,
858 .rate_max = 48000,
859 .channels_min = 2,
860 .channels_max = 2,
861 .buffer_bytes_max = (2*128*1024),
862 .period_bytes_min = 64,
863 .period_bytes_max = (128*1024),
864 .periods_min = 2,
865 .periods_max = 1024,
866 .fifo_size = 0
871 static int snd_usX2Y_pcm_open(snd_pcm_substream_t *substream)
873 snd_usX2Y_substream_t *subs = ((snd_usX2Y_substream_t **)
874 snd_pcm_substream_chip(substream))[substream->stream];
875 snd_pcm_runtime_t *runtime = substream->runtime;
877 runtime->hw = snd_usX2Y_2c;
878 runtime->private_data = subs;
879 subs->pcm_substream = substream;
880 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);
881 return 0;
886 static int snd_usX2Y_pcm_close(snd_pcm_substream_t *substream)
888 snd_pcm_runtime_t *runtime = substream->runtime;
889 snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
890 int err = 0;
892 subs->pcm_substream = NULL;
894 return err;
898 static snd_pcm_ops_t snd_usX2Y_pcm_ops =
900 .open = snd_usX2Y_pcm_open,
901 .close = snd_usX2Y_pcm_close,
902 .ioctl = snd_pcm_lib_ioctl,
903 .hw_params = snd_usX2Y_pcm_hw_params,
904 .hw_free = snd_usX2Y_pcm_hw_free,
905 .prepare = snd_usX2Y_pcm_prepare,
906 .trigger = snd_usX2Y_pcm_trigger,
907 .pointer = snd_usX2Y_pcm_pointer,
912 * free a usb stream instance
914 static void usX2Y_audio_stream_free(snd_usX2Y_substream_t **usX2Y_substream)
916 if (NULL != usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]) {
917 kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]);
918 usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL;
920 kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]);
921 usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL;
924 static void snd_usX2Y_pcm_private_free(snd_pcm_t *pcm)
926 snd_usX2Y_substream_t **usX2Y_stream = pcm->private_data;
927 if (usX2Y_stream) {
928 snd_pcm_lib_preallocate_free_for_all(pcm);
929 usX2Y_audio_stream_free(usX2Y_stream);
933 static int usX2Y_audio_stream_new(snd_card_t *card, int playback_endpoint, int capture_endpoint)
935 snd_pcm_t *pcm;
936 int err, i;
937 snd_usX2Y_substream_t **usX2Y_substream =
938 usX2Y(card)->substream + 2 * usX2Y(card)->chip.pcm_devs;
940 for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
941 i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
942 usX2Y_substream[i] = kcalloc(1, sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
943 if (NULL == usX2Y_substream[i]) {
944 snd_printk(KERN_ERR "cannot malloc\n");
945 return -ENOMEM;
947 init_waitqueue_head(&usX2Y_substream[i]->wait_queue);
948 usX2Y_substream[i]->usX2Y = usX2Y(card);
951 if (playback_endpoint)
952 usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint;
953 usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;
955 err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->chip.pcm_devs,
956 playback_endpoint ? 1 : 0, 1,
957 &pcm);
958 if (err < 0) {
959 usX2Y_audio_stream_free(usX2Y_substream);
960 return err;
963 if (playback_endpoint)
964 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_pcm_ops);
965 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_pcm_ops);
967 pcm->private_data = usX2Y_substream;
968 pcm->private_free = snd_usX2Y_pcm_private_free;
969 pcm->info_flags = 0;
971 sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->chip.pcm_devs);
973 if ((playback_endpoint &&
974 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
975 SNDRV_DMA_TYPE_CONTINUOUS,
976 snd_dma_continuous_data(GFP_KERNEL),
977 64*1024, 128*1024))) ||
978 0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
979 SNDRV_DMA_TYPE_CONTINUOUS,
980 snd_dma_continuous_data(GFP_KERNEL),
981 64*1024, 128*1024))) {
982 snd_usX2Y_pcm_private_free(pcm);
983 return err;
985 usX2Y(card)->chip.pcm_devs++;
987 return 0;
991 * free the chip instance
993 * here we have to do not much, since pcm and controls are already freed
996 static int snd_usX2Y_device_dev_free(snd_device_t *device)
998 return 0;
1003 * create a chip instance and set its names.
1005 int usX2Y_audio_create(snd_card_t* card)
1007 int err = 0;
1008 static snd_device_ops_t ops = {
1009 .dev_free = snd_usX2Y_device_dev_free,
1012 INIT_LIST_HEAD(&usX2Y(card)->chip.pcm_list);
1014 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, usX2Y(card), &ops)) < 0) {
1015 // snd_usX2Y_audio_free(usX2Y(card));
1016 return err;
1019 if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8)))
1020 return err;
1021 if (usX2Y(card)->chip.dev->descriptor.idProduct == USB_ID_US428)
1022 if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA)))
1023 return err;
1024 if (usX2Y(card)->chip.dev->descriptor.idProduct != USB_ID_US122)
1025 err = usX2Y_rate_set(usX2Y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122.
1026 return err;