diff options
author | Jaroslav Kysela <perex@perex.cz> | 2010-02-16 05:25:03 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2010-02-16 05:25:03 -0500 |
commit | b8f1f5983fbe751aa3d07d9ce7ebb0c23bf4b7e4 (patch) | |
tree | e9f11863f683a9f4eb03d76008740a36d6b4ff3c /sound/usb/usbaudio.c | |
parent | ba9341dfef6b0201cd30e3904dcd0a47d3dc35e0 (diff) | |
parent | 47b5d028fdce8f809bf22852ac900338fb90e8aa (diff) |
Merge branch 'topic/misc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6 into devel
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r-- | sound/usb/usbaudio.c | 256 |
1 files changed, 121 insertions, 135 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index d01ec188b602..8a8f62515b80 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/string.h> | 45 | #include <linux/string.h> |
46 | #include <linux/usb.h> | 46 | #include <linux/usb.h> |
47 | #include <linux/vmalloc.h> | ||
48 | #include <linux/moduleparam.h> | 47 | #include <linux/moduleparam.h> |
49 | #include <linux/mutex.h> | 48 | #include <linux/mutex.h> |
50 | #include <sound/core.h> | 49 | #include <sound/core.h> |
@@ -170,11 +169,12 @@ struct snd_usb_substream { | |||
170 | unsigned int curpacksize; /* current packet size in bytes (for capture) */ | 169 | unsigned int curpacksize; /* current packet size in bytes (for capture) */ |
171 | unsigned int curframesize; /* current packet size in frames (for capture) */ | 170 | unsigned int curframesize; /* current packet size in frames (for capture) */ |
172 | unsigned int fill_max: 1; /* fill max packet size always */ | 171 | unsigned int fill_max: 1; /* fill max packet size always */ |
172 | unsigned int txfr_quirk:1; /* allow sub-frame alignment */ | ||
173 | unsigned int fmt_type; /* USB audio format type (1-3) */ | 173 | unsigned int fmt_type; /* USB audio format type (1-3) */ |
174 | 174 | ||
175 | unsigned int running: 1; /* running status */ | 175 | unsigned int running: 1; /* running status */ |
176 | 176 | ||
177 | unsigned int hwptr_done; /* processed frame position in the buffer */ | 177 | unsigned int hwptr_done; /* processed byte position in the buffer */ |
178 | unsigned int transfer_done; /* processed frames since last period update */ | 178 | unsigned int transfer_done; /* processed frames since last period update */ |
179 | unsigned long active_mask; /* bitmask of active urbs */ | 179 | unsigned long active_mask; /* bitmask of active urbs */ |
180 | unsigned long unlink_mask; /* bitmask of unlinked urbs */ | 180 | unsigned long unlink_mask; /* bitmask of unlinked urbs */ |
@@ -343,7 +343,7 @@ static int retire_capture_urb(struct snd_usb_substream *subs, | |||
343 | unsigned long flags; | 343 | unsigned long flags; |
344 | unsigned char *cp; | 344 | unsigned char *cp; |
345 | int i; | 345 | int i; |
346 | unsigned int stride, len, oldptr; | 346 | unsigned int stride, frames, bytes, oldptr; |
347 | int period_elapsed = 0; | 347 | int period_elapsed = 0; |
348 | 348 | ||
349 | stride = runtime->frame_bits >> 3; | 349 | stride = runtime->frame_bits >> 3; |
@@ -354,29 +354,39 @@ static int retire_capture_urb(struct snd_usb_substream *subs, | |||
354 | snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status); | 354 | snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status); |
355 | // continue; | 355 | // continue; |
356 | } | 356 | } |
357 | len = urb->iso_frame_desc[i].actual_length / stride; | 357 | bytes = urb->iso_frame_desc[i].actual_length; |
358 | if (! len) | 358 | frames = bytes / stride; |
359 | continue; | 359 | if (!subs->txfr_quirk) |
360 | bytes = frames * stride; | ||
361 | if (bytes % (runtime->sample_bits >> 3) != 0) { | ||
362 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
363 | int oldbytes = bytes; | ||
364 | #endif | ||
365 | bytes = frames * stride; | ||
366 | snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n", | ||
367 | oldbytes, bytes); | ||
368 | } | ||
360 | /* update the current pointer */ | 369 | /* update the current pointer */ |
361 | spin_lock_irqsave(&subs->lock, flags); | 370 | spin_lock_irqsave(&subs->lock, flags); |
362 | oldptr = subs->hwptr_done; | 371 | oldptr = subs->hwptr_done; |
363 | subs->hwptr_done += len; | 372 | subs->hwptr_done += bytes; |
364 | if (subs->hwptr_done >= runtime->buffer_size) | 373 | if (subs->hwptr_done >= runtime->buffer_size * stride) |
365 | subs->hwptr_done -= runtime->buffer_size; | 374 | subs->hwptr_done -= runtime->buffer_size * stride; |
366 | subs->transfer_done += len; | 375 | frames = (bytes + (oldptr % stride)) / stride; |
376 | subs->transfer_done += frames; | ||
367 | if (subs->transfer_done >= runtime->period_size) { | 377 | if (subs->transfer_done >= runtime->period_size) { |
368 | subs->transfer_done -= runtime->period_size; | 378 | subs->transfer_done -= runtime->period_size; |
369 | period_elapsed = 1; | 379 | period_elapsed = 1; |
370 | } | 380 | } |
371 | spin_unlock_irqrestore(&subs->lock, flags); | 381 | spin_unlock_irqrestore(&subs->lock, flags); |
372 | /* copy a data chunk */ | 382 | /* copy a data chunk */ |
373 | if (oldptr + len > runtime->buffer_size) { | 383 | if (oldptr + bytes > runtime->buffer_size * stride) { |
374 | unsigned int cnt = runtime->buffer_size - oldptr; | 384 | unsigned int bytes1 = |
375 | unsigned int blen = cnt * stride; | 385 | runtime->buffer_size * stride - oldptr; |
376 | memcpy(runtime->dma_area + oldptr * stride, cp, blen); | 386 | memcpy(runtime->dma_area + oldptr, cp, bytes1); |
377 | memcpy(runtime->dma_area, cp + blen, len * stride - blen); | 387 | memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1); |
378 | } else { | 388 | } else { |
379 | memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); | 389 | memcpy(runtime->dma_area + oldptr, cp, bytes); |
380 | } | 390 | } |
381 | } | 391 | } |
382 | if (period_elapsed) | 392 | if (period_elapsed) |
@@ -563,24 +573,24 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, | |||
563 | struct snd_pcm_runtime *runtime, | 573 | struct snd_pcm_runtime *runtime, |
564 | struct urb *urb) | 574 | struct urb *urb) |
565 | { | 575 | { |
566 | int i, stride, offs; | 576 | int i, stride; |
567 | unsigned int counts; | 577 | unsigned int counts, frames, bytes; |
568 | unsigned long flags; | 578 | unsigned long flags; |
569 | int period_elapsed = 0; | 579 | int period_elapsed = 0; |
570 | struct snd_urb_ctx *ctx = urb->context; | 580 | struct snd_urb_ctx *ctx = urb->context; |
571 | 581 | ||
572 | stride = runtime->frame_bits >> 3; | 582 | stride = runtime->frame_bits >> 3; |
573 | 583 | ||
574 | offs = 0; | 584 | frames = 0; |
575 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 585 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
576 | urb->number_of_packets = 0; | 586 | urb->number_of_packets = 0; |
577 | spin_lock_irqsave(&subs->lock, flags); | 587 | spin_lock_irqsave(&subs->lock, flags); |
578 | for (i = 0; i < ctx->packets; i++) { | 588 | for (i = 0; i < ctx->packets; i++) { |
579 | counts = snd_usb_audio_next_packet_size(subs); | 589 | counts = snd_usb_audio_next_packet_size(subs); |
580 | /* set up descriptor */ | 590 | /* set up descriptor */ |
581 | urb->iso_frame_desc[i].offset = offs * stride; | 591 | urb->iso_frame_desc[i].offset = frames * stride; |
582 | urb->iso_frame_desc[i].length = counts * stride; | 592 | urb->iso_frame_desc[i].length = counts * stride; |
583 | offs += counts; | 593 | frames += counts; |
584 | urb->number_of_packets++; | 594 | urb->number_of_packets++; |
585 | subs->transfer_done += counts; | 595 | subs->transfer_done += counts; |
586 | if (subs->transfer_done >= runtime->period_size) { | 596 | if (subs->transfer_done >= runtime->period_size) { |
@@ -590,7 +600,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, | |||
590 | if (subs->transfer_done > 0) { | 600 | if (subs->transfer_done > 0) { |
591 | /* FIXME: fill-max mode is not | 601 | /* FIXME: fill-max mode is not |
592 | * supported yet */ | 602 | * supported yet */ |
593 | offs -= subs->transfer_done; | 603 | frames -= subs->transfer_done; |
594 | counts -= subs->transfer_done; | 604 | counts -= subs->transfer_done; |
595 | urb->iso_frame_desc[i].length = | 605 | urb->iso_frame_desc[i].length = |
596 | counts * stride; | 606 | counts * stride; |
@@ -600,7 +610,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, | |||
600 | if (i < ctx->packets) { | 610 | if (i < ctx->packets) { |
601 | /* add a transfer delimiter */ | 611 | /* add a transfer delimiter */ |
602 | urb->iso_frame_desc[i].offset = | 612 | urb->iso_frame_desc[i].offset = |
603 | offs * stride; | 613 | frames * stride; |
604 | urb->iso_frame_desc[i].length = 0; | 614 | urb->iso_frame_desc[i].length = 0; |
605 | urb->number_of_packets++; | 615 | urb->number_of_packets++; |
606 | } | 616 | } |
@@ -610,26 +620,25 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, | |||
610 | if (period_elapsed) /* finish at the period boundary */ | 620 | if (period_elapsed) /* finish at the period boundary */ |
611 | break; | 621 | break; |
612 | } | 622 | } |
613 | if (subs->hwptr_done + offs > runtime->buffer_size) { | 623 | bytes = frames * stride; |
624 | if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { | ||
614 | /* err, the transferred area goes over buffer boundary. */ | 625 | /* err, the transferred area goes over buffer boundary. */ |
615 | unsigned int len = runtime->buffer_size - subs->hwptr_done; | 626 | unsigned int bytes1 = |
627 | runtime->buffer_size * stride - subs->hwptr_done; | ||
616 | memcpy(urb->transfer_buffer, | 628 | memcpy(urb->transfer_buffer, |
617 | runtime->dma_area + subs->hwptr_done * stride, | 629 | runtime->dma_area + subs->hwptr_done, bytes1); |
618 | len * stride); | 630 | memcpy(urb->transfer_buffer + bytes1, |
619 | memcpy(urb->transfer_buffer + len * stride, | 631 | runtime->dma_area, bytes - bytes1); |
620 | runtime->dma_area, | ||
621 | (offs - len) * stride); | ||
622 | } else { | 632 | } else { |
623 | memcpy(urb->transfer_buffer, | 633 | memcpy(urb->transfer_buffer, |
624 | runtime->dma_area + subs->hwptr_done * stride, | 634 | runtime->dma_area + subs->hwptr_done, bytes); |
625 | offs * stride); | ||
626 | } | 635 | } |
627 | subs->hwptr_done += offs; | 636 | subs->hwptr_done += bytes; |
628 | if (subs->hwptr_done >= runtime->buffer_size) | 637 | if (subs->hwptr_done >= runtime->buffer_size * stride) |
629 | subs->hwptr_done -= runtime->buffer_size; | 638 | subs->hwptr_done -= runtime->buffer_size * stride; |
630 | runtime->delay += offs; | 639 | runtime->delay += frames; |
631 | spin_unlock_irqrestore(&subs->lock, flags); | 640 | spin_unlock_irqrestore(&subs->lock, flags); |
632 | urb->transfer_buffer_length = offs * stride; | 641 | urb->transfer_buffer_length = bytes; |
633 | if (period_elapsed) | 642 | if (period_elapsed) |
634 | snd_pcm_period_elapsed(subs->pcm_substream); | 643 | snd_pcm_period_elapsed(subs->pcm_substream); |
635 | return 0; | 644 | return 0; |
@@ -735,41 +744,6 @@ static void snd_complete_sync_urb(struct urb *urb) | |||
735 | } | 744 | } |
736 | 745 | ||
737 | 746 | ||
738 | /* get the physical page pointer at the given offset */ | ||
739 | static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, | ||
740 | unsigned long offset) | ||
741 | { | ||
742 | void *pageptr = subs->runtime->dma_area + offset; | ||
743 | return vmalloc_to_page(pageptr); | ||
744 | } | ||
745 | |||
746 | /* allocate virtual buffer; may be called more than once */ | ||
747 | static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size) | ||
748 | { | ||
749 | struct snd_pcm_runtime *runtime = subs->runtime; | ||
750 | if (runtime->dma_area) { | ||
751 | if (runtime->dma_bytes >= size) | ||
752 | return 0; /* already large enough */ | ||
753 | vfree(runtime->dma_area); | ||
754 | } | ||
755 | runtime->dma_area = vmalloc_user(size); | ||
756 | if (!runtime->dma_area) | ||
757 | return -ENOMEM; | ||
758 | runtime->dma_bytes = size; | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | /* free virtual buffer; may be called more than once */ | ||
763 | static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs) | ||
764 | { | ||
765 | struct snd_pcm_runtime *runtime = subs->runtime; | ||
766 | |||
767 | vfree(runtime->dma_area); | ||
768 | runtime->dma_area = NULL; | ||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | |||
773 | /* | 747 | /* |
774 | * unlink active urbs. | 748 | * unlink active urbs. |
775 | */ | 749 | */ |
@@ -937,18 +911,18 @@ static int wait_clear_urbs(struct snd_usb_substream *subs) | |||
937 | 911 | ||
938 | 912 | ||
939 | /* | 913 | /* |
940 | * return the current pcm pointer. just return the hwptr_done value. | 914 | * return the current pcm pointer. just based on the hwptr_done value. |
941 | */ | 915 | */ |
942 | static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) | 916 | static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) |
943 | { | 917 | { |
944 | struct snd_usb_substream *subs; | 918 | struct snd_usb_substream *subs; |
945 | snd_pcm_uframes_t hwptr_done; | 919 | unsigned int hwptr_done; |
946 | 920 | ||
947 | subs = (struct snd_usb_substream *)substream->runtime->private_data; | 921 | subs = (struct snd_usb_substream *)substream->runtime->private_data; |
948 | spin_lock(&subs->lock); | 922 | spin_lock(&subs->lock); |
949 | hwptr_done = subs->hwptr_done; | 923 | hwptr_done = subs->hwptr_done; |
950 | spin_unlock(&subs->lock); | 924 | spin_unlock(&subs->lock); |
951 | return hwptr_done; | 925 | return hwptr_done / (substream->runtime->frame_bits >> 3); |
952 | } | 926 | } |
953 | 927 | ||
954 | 928 | ||
@@ -1307,6 +1281,47 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface, | |||
1307 | } | 1281 | } |
1308 | 1282 | ||
1309 | /* | 1283 | /* |
1284 | * For E-Mu 0404USB/0202USB/TrackerPre sample rate should be set for device, | ||
1285 | * not for interface. | ||
1286 | */ | ||
1287 | static void set_format_emu_quirk(struct snd_usb_substream *subs, | ||
1288 | struct audioformat *fmt) | ||
1289 | { | ||
1290 | unsigned char emu_samplerate_id = 0; | ||
1291 | |||
1292 | /* When capture is active | ||
1293 | * sample rate shouldn't be changed | ||
1294 | * by playback substream | ||
1295 | */ | ||
1296 | if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { | ||
1297 | if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1) | ||
1298 | return; | ||
1299 | } | ||
1300 | |||
1301 | switch (fmt->rate_min) { | ||
1302 | case 48000: | ||
1303 | emu_samplerate_id = EMU_QUIRK_SR_48000HZ; | ||
1304 | break; | ||
1305 | case 88200: | ||
1306 | emu_samplerate_id = EMU_QUIRK_SR_88200HZ; | ||
1307 | break; | ||
1308 | case 96000: | ||
1309 | emu_samplerate_id = EMU_QUIRK_SR_96000HZ; | ||
1310 | break; | ||
1311 | case 176400: | ||
1312 | emu_samplerate_id = EMU_QUIRK_SR_176400HZ; | ||
1313 | break; | ||
1314 | case 192000: | ||
1315 | emu_samplerate_id = EMU_QUIRK_SR_192000HZ; | ||
1316 | break; | ||
1317 | default: | ||
1318 | emu_samplerate_id = EMU_QUIRK_SR_44100HZ; | ||
1319 | break; | ||
1320 | } | ||
1321 | snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id); | ||
1322 | } | ||
1323 | |||
1324 | /* | ||
1310 | * find a matching format and set up the interface | 1325 | * find a matching format and set up the interface |
1311 | */ | 1326 | */ |
1312 | static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | 1327 | static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) |
@@ -1419,6 +1434,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
1419 | 1434 | ||
1420 | subs->cur_audiofmt = fmt; | 1435 | subs->cur_audiofmt = fmt; |
1421 | 1436 | ||
1437 | switch (subs->stream->chip->usb_id) { | ||
1438 | case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */ | ||
1439 | case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */ | ||
1440 | case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */ | ||
1441 | set_format_emu_quirk(subs, fmt); | ||
1442 | break; | ||
1443 | } | ||
1444 | |||
1422 | #if 0 | 1445 | #if 0 |
1423 | printk(KERN_DEBUG | 1446 | printk(KERN_DEBUG |
1424 | "setting done: format = %d, rate = %d..%d, channels = %d\n", | 1447 | "setting done: format = %d, rate = %d..%d, channels = %d\n", |
@@ -1449,8 +1472,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
1449 | unsigned int channels, rate, format; | 1472 | unsigned int channels, rate, format; |
1450 | int ret, changed; | 1473 | int ret, changed; |
1451 | 1474 | ||
1452 | ret = snd_pcm_alloc_vmalloc_buffer(substream, | 1475 | ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, |
1453 | params_buffer_bytes(hw_params)); | 1476 | params_buffer_bytes(hw_params)); |
1454 | if (ret < 0) | 1477 | if (ret < 0) |
1455 | return ret; | 1478 | return ret; |
1456 | 1479 | ||
@@ -1507,7 +1530,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
1507 | subs->period_bytes = 0; | 1530 | subs->period_bytes = 0; |
1508 | if (!subs->stream->chip->shutdown) | 1531 | if (!subs->stream->chip->shutdown) |
1509 | release_substream_urbs(subs, 0); | 1532 | release_substream_urbs(subs, 0); |
1510 | return snd_pcm_free_vmalloc_buffer(substream); | 1533 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
1511 | } | 1534 | } |
1512 | 1535 | ||
1513 | /* | 1536 | /* |
@@ -1973,7 +1996,8 @@ static struct snd_pcm_ops snd_usb_playback_ops = { | |||
1973 | .prepare = snd_usb_pcm_prepare, | 1996 | .prepare = snd_usb_pcm_prepare, |
1974 | .trigger = snd_usb_pcm_playback_trigger, | 1997 | .trigger = snd_usb_pcm_playback_trigger, |
1975 | .pointer = snd_usb_pcm_pointer, | 1998 | .pointer = snd_usb_pcm_pointer, |
1976 | .page = snd_pcm_get_vmalloc_page, | 1999 | .page = snd_pcm_lib_get_vmalloc_page, |
2000 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
1977 | }; | 2001 | }; |
1978 | 2002 | ||
1979 | static struct snd_pcm_ops snd_usb_capture_ops = { | 2003 | static struct snd_pcm_ops snd_usb_capture_ops = { |
@@ -1985,7 +2009,8 @@ static struct snd_pcm_ops snd_usb_capture_ops = { | |||
1985 | .prepare = snd_usb_pcm_prepare, | 2009 | .prepare = snd_usb_pcm_prepare, |
1986 | .trigger = snd_usb_pcm_capture_trigger, | 2010 | .trigger = snd_usb_pcm_capture_trigger, |
1987 | .pointer = snd_usb_pcm_pointer, | 2011 | .pointer = snd_usb_pcm_pointer, |
1988 | .page = snd_pcm_get_vmalloc_page, | 2012 | .page = snd_pcm_lib_get_vmalloc_page, |
2013 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
1989 | }; | 2014 | }; |
1990 | 2015 | ||
1991 | 2016 | ||
@@ -2227,6 +2252,7 @@ static void init_substream(struct snd_usb_stream *as, int stream, struct audiofo | |||
2227 | subs->stream = as; | 2252 | subs->stream = as; |
2228 | subs->direction = stream; | 2253 | subs->direction = stream; |
2229 | subs->dev = as->chip->dev; | 2254 | subs->dev = as->chip->dev; |
2255 | subs->txfr_quirk = as->chip->txfr_quirk; | ||
2230 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) { | 2256 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) { |
2231 | subs->ops = audio_urb_ops[stream]; | 2257 | subs->ops = audio_urb_ops[stream]; |
2232 | } else { | 2258 | } else { |
@@ -3142,59 +3168,6 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip, | |||
3142 | return 0; | 3168 | return 0; |
3143 | } | 3169 | } |
3144 | 3170 | ||
3145 | /* | ||
3146 | * Create a stream for an Edirol UA-101 interface. | ||
3147 | * Copy, paste and modify from Edirol UA-1000 | ||
3148 | */ | ||
3149 | static int create_ua101_quirk(struct snd_usb_audio *chip, | ||
3150 | struct usb_interface *iface, | ||
3151 | const struct snd_usb_audio_quirk *quirk) | ||
3152 | { | ||
3153 | static const struct audioformat ua101_format = { | ||
3154 | .format = SNDRV_PCM_FORMAT_S32_LE, | ||
3155 | .fmt_type = USB_FORMAT_TYPE_I, | ||
3156 | .altsetting = 1, | ||
3157 | .altset_idx = 1, | ||
3158 | .attributes = 0, | ||
3159 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
3160 | }; | ||
3161 | struct usb_host_interface *alts; | ||
3162 | struct usb_interface_descriptor *altsd; | ||
3163 | struct audioformat *fp; | ||
3164 | int stream, err; | ||
3165 | |||
3166 | if (iface->num_altsetting != 2) | ||
3167 | return -ENXIO; | ||
3168 | alts = &iface->altsetting[1]; | ||
3169 | altsd = get_iface_desc(alts); | ||
3170 | if (alts->extralen != 18 || alts->extra[1] != USB_DT_CS_INTERFACE || | ||
3171 | altsd->bNumEndpoints != 1) | ||
3172 | return -ENXIO; | ||
3173 | |||
3174 | fp = kmemdup(&ua101_format, sizeof(*fp), GFP_KERNEL); | ||
3175 | if (!fp) | ||
3176 | return -ENOMEM; | ||
3177 | |||
3178 | fp->channels = alts->extra[11]; | ||
3179 | fp->iface = altsd->bInterfaceNumber; | ||
3180 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | ||
3181 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | ||
3182 | fp->datainterval = parse_datainterval(chip, alts); | ||
3183 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | ||
3184 | fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]); | ||
3185 | |||
3186 | stream = (fp->endpoint & USB_DIR_IN) | ||
3187 | ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | ||
3188 | err = add_audio_endpoint(chip, stream, fp); | ||
3189 | if (err < 0) { | ||
3190 | kfree(fp); | ||
3191 | return err; | ||
3192 | } | ||
3193 | /* FIXME: playback must be synchronized to capture */ | ||
3194 | usb_set_interface(chip->dev, fp->iface, 0); | ||
3195 | return 0; | ||
3196 | } | ||
3197 | |||
3198 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, | 3171 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, |
3199 | struct usb_interface *iface, | 3172 | struct usb_interface *iface, |
3200 | const struct snd_usb_audio_quirk *quirk); | 3173 | const struct snd_usb_audio_quirk *quirk); |
@@ -3232,6 +3205,18 @@ static int ignore_interface_quirk(struct snd_usb_audio *chip, | |||
3232 | return 0; | 3205 | return 0; |
3233 | } | 3206 | } |
3234 | 3207 | ||
3208 | /* | ||
3209 | * Allow alignment on audio sub-slot (channel samples) rather than | ||
3210 | * on audio slots (audio frames) | ||
3211 | */ | ||
3212 | static int create_align_transfer_quirk(struct snd_usb_audio *chip, | ||
3213 | struct usb_interface *iface, | ||
3214 | const struct snd_usb_audio_quirk *quirk) | ||
3215 | { | ||
3216 | chip->txfr_quirk = 1; | ||
3217 | return 1; /* Continue with creating streams and mixer */ | ||
3218 | } | ||
3219 | |||
3235 | 3220 | ||
3236 | /* | 3221 | /* |
3237 | * boot quirks | 3222 | * boot quirks |
@@ -3432,8 +3417,8 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
3432 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, | 3417 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, |
3433 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, | 3418 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
3434 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, | 3419 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, |
3435 | [QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk, | 3420 | [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, |
3436 | [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk | 3421 | [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk |
3437 | }; | 3422 | }; |
3438 | 3423 | ||
3439 | if (quirk->type < QUIRK_TYPE_COUNT) { | 3424 | if (quirk->type < QUIRK_TYPE_COUNT) { |
@@ -3693,6 +3678,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3693 | } | 3678 | } |
3694 | } | 3679 | } |
3695 | 3680 | ||
3681 | chip->txfr_quirk = 0; | ||
3696 | err = 1; /* continue */ | 3682 | err = 1; /* continue */ |
3697 | if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { | 3683 | if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { |
3698 | /* need some special handlings */ | 3684 | /* need some special handlings */ |