aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-10-26 11:14:41 -0400
committerTakashi Iwai <tiwai@suse.de>2010-10-27 03:17:41 -0400
commit89e1e66d6be8a520cdcd26043cda2cc870a34015 (patch)
treec9056471d3edf7eea0c665f0aaea10fbdda4e228 /sound/usb
parent0d040df9984c8fcb6a777a8f6d5dc513eaefd2de (diff)
ALSA: usb-audio: automatically detect feedback format
There are two USB Audio Class specifications (v1 and v2), but neither of them clearly defines the feedback format for high-speed UAC v1 devices. Add to this whatever the Creative and M-Audio firmware writers have been smoking, and it becomes impossible to predict the exact feedback format used by a particular device. Therefore, automatically detect the feedback format by looking at the magnitude of the first received feedback value. Also, this allows us to get rid of some special cases for E-Mu devices. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/pcm.c2
-rw-r--r--sound/usb/proc.c5
-rw-r--r--sound/usb/urb.c170
4 files changed, 67 insertions, 112 deletions
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 1febf2f23754..ae4251d5abf7 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -62,12 +62,14 @@ struct snd_usb_substream {
62 unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ 62 unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
63 unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ 63 unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */
64 unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ 64 unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */
65 int freqshift; /* how much to shift the feedback value to get Q16.16 */
65 unsigned int freqmax; /* maximum sampling rate, used for buffer management */ 66 unsigned int freqmax; /* maximum sampling rate, used for buffer management */
66 unsigned int phase; /* phase accumulator */ 67 unsigned int phase; /* phase accumulator */
67 unsigned int maxpacksize; /* max packet size in bytes */ 68 unsigned int maxpacksize; /* max packet size in bytes */
68 unsigned int maxframesize; /* max packet size in frames */ 69 unsigned int maxframesize; /* max packet size in frames */
69 unsigned int curpacksize; /* current packet size in bytes (for capture) */ 70 unsigned int curpacksize; /* current packet size in bytes (for capture) */
70 unsigned int curframesize; /* current packet size in frames (for capture) */ 71 unsigned int curframesize; /* current packet size in frames (for capture) */
72 unsigned int syncmaxsize; /* sync endpoint packet size */
71 unsigned int fill_max: 1; /* fill max packet size always */ 73 unsigned int fill_max: 1; /* fill max packet size always */
72 unsigned int txfr_quirk:1; /* allow sub-frame alignment */ 74 unsigned int txfr_quirk:1; /* allow sub-frame alignment */
73 unsigned int fmt_type; /* USB audio format type (1-3) */ 75 unsigned int fmt_type; /* USB audio format type (1-3) */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index f49756c1b837..cff3a3c465d7 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -237,6 +237,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
237 subs->datainterval = fmt->datainterval; 237 subs->datainterval = fmt->datainterval;
238 subs->syncpipe = subs->syncinterval = 0; 238 subs->syncpipe = subs->syncinterval = 0;
239 subs->maxpacksize = fmt->maxpacksize; 239 subs->maxpacksize = fmt->maxpacksize;
240 subs->syncmaxsize = 0;
240 subs->fill_max = 0; 241 subs->fill_max = 0;
241 242
242 /* we need a sync pipe in async OUT or adaptive IN mode */ 243 /* we need a sync pipe in async OUT or adaptive IN mode */
@@ -283,6 +284,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
283 subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; 284 subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
284 else 285 else
285 subs->syncinterval = 3; 286 subs->syncinterval = 3;
287 subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
286 } 288 }
287 289
288 /* always fill max packet size */ 290 /* always fill max packet size */
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index 3c650ab3c91d..961c9a250686 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -132,6 +132,11 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn
132 ? get_full_speed_hz(subs->freqm) 132 ? get_full_speed_hz(subs->freqm)
133 : get_high_speed_hz(subs->freqm), 133 : get_high_speed_hz(subs->freqm),
134 subs->freqm >> 16, subs->freqm & 0xffff); 134 subs->freqm >> 16, subs->freqm & 0xffff);
135 if (subs->freqshift != INT_MIN)
136 snd_iprintf(buffer, " Feedback Format = %d.%d\n",
137 (subs->syncmaxsize > 3 ? 32 : 24)
138 - (16 - subs->freqshift),
139 16 - subs->freqshift);
135 } else { 140 } else {
136 snd_iprintf(buffer, " Status: Stop\n"); 141 snd_iprintf(buffer, " Status: Stop\n");
137 } 142 }
diff --git a/sound/usb/urb.c b/sound/usb/urb.c
index 8deeaad10f10..e184349aee83 100644
--- a/sound/usb/urb.c
+++ b/sound/usb/urb.c
@@ -225,6 +225,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
225 else 225 else
226 subs->freqn = get_usb_high_speed_rate(rate); 226 subs->freqn = get_usb_high_speed_rate(rate);
227 subs->freqm = subs->freqn; 227 subs->freqm = subs->freqn;
228 subs->freqshift = INT_MIN;
228 /* calculate max. frequency */ 229 /* calculate max. frequency */
229 if (subs->maxpacksize) { 230 if (subs->maxpacksize) {
230 /* whatever fits into a max. size packet */ 231 /* whatever fits into a max. size packet */
@@ -513,11 +514,10 @@ static int retire_paused_capture_urb(struct snd_usb_substream *subs,
513 514
514 515
515/* 516/*
516 * prepare urb for full speed playback sync pipe 517 * prepare urb for playback sync pipe
517 * 518 *
518 * set up the offset and length to receive the current frequency. 519 * set up the offset and length to receive the current frequency.
519 */ 520 */
520
521static int prepare_playback_sync_urb(struct snd_usb_substream *subs, 521static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
522 struct snd_pcm_runtime *runtime, 522 struct snd_pcm_runtime *runtime,
523 struct urb *urb) 523 struct urb *urb)
@@ -525,103 +525,78 @@ static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
525 struct snd_urb_ctx *ctx = urb->context; 525 struct snd_urb_ctx *ctx = urb->context;
526 526
527 urb->dev = ctx->subs->dev; /* we need to set this at each time */ 527 urb->dev = ctx->subs->dev; /* we need to set this at each time */
528 urb->iso_frame_desc[0].length = 3; 528 urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
529 urb->iso_frame_desc[0].offset = 0; 529 urb->iso_frame_desc[0].offset = 0;
530 return 0; 530 return 0;
531} 531}
532 532
533/* 533/*
534 * prepare urb for high speed playback sync pipe 534 * process after playback sync complete
535 * 535 *
536 * set up the offset and length to receive the current frequency. 536 * Full speed devices report feedback values in 10.14 format as samples per
537 */ 537 * frame, high speed devices in 16.16 format as samples per microframe.
538 538 * Because the Audio Class 1 spec was written before USB 2.0, many high speed
539static int prepare_playback_sync_urb_hs(struct snd_usb_substream *subs, 539 * devices use a wrong interpretation, some others use an entirely different
540 struct snd_pcm_runtime *runtime, 540 * format. Therefore, we cannot predict what format any particular device uses
541 struct urb *urb) 541 * and must detect it automatically.
542{
543 struct snd_urb_ctx *ctx = urb->context;
544
545 urb->dev = ctx->subs->dev; /* we need to set this at each time */
546 urb->iso_frame_desc[0].length = 4;
547 urb->iso_frame_desc[0].offset = 0;
548 return 0;
549}
550
551/*
552 * process after full speed playback sync complete
553 *
554 * retrieve the current 10.14 frequency from pipe, and set it.
555 * the value is referred in prepare_playback_urb().
556 */ 542 */
557static int retire_playback_sync_urb(struct snd_usb_substream *subs, 543static int retire_playback_sync_urb(struct snd_usb_substream *subs,
558 struct snd_pcm_runtime *runtime, 544 struct snd_pcm_runtime *runtime,
559 struct urb *urb) 545 struct urb *urb)
560{ 546{
561 unsigned int f; 547 unsigned int f;
548 int shift;
562 unsigned long flags; 549 unsigned long flags;
563 550
564 if (urb->iso_frame_desc[0].status == 0 && 551 if (urb->iso_frame_desc[0].status != 0 ||
565 urb->iso_frame_desc[0].actual_length == 3) { 552 urb->iso_frame_desc[0].actual_length < 3)
566 f = combine_triple((u8*)urb->transfer_buffer) << 2; 553 return 0;
567 if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
568 spin_lock_irqsave(&subs->lock, flags);
569 subs->freqm = f;
570 spin_unlock_irqrestore(&subs->lock, flags);
571 }
572 }
573
574 return 0;
575}
576 554
577/* 555 f = le32_to_cpup(urb->transfer_buffer);
578 * process after high speed playback sync complete 556 if (urb->iso_frame_desc[0].actual_length == 3)
579 * 557 f &= 0x00ffffff;
580 * retrieve the current 12.13 frequency from pipe, and set it. 558 else
581 * the value is referred in prepare_playback_urb(). 559 f &= 0x0fffffff;
582 */ 560 if (f == 0)
583static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs, 561 return 0;
584 struct snd_pcm_runtime *runtime,
585 struct urb *urb)
586{
587 unsigned int f;
588 unsigned long flags;
589 562
590 if (urb->iso_frame_desc[0].status == 0 && 563 if (unlikely(subs->freqshift == INT_MIN)) {
591 urb->iso_frame_desc[0].actual_length == 4) { 564 /*
592 f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff; 565 * The first time we see a feedback value, determine its format
593 if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) { 566 * by shifting it left or right until it matches the nominal
594 spin_lock_irqsave(&subs->lock, flags); 567 * frequency value. This assumes that the feedback does not
595 subs->freqm = f; 568 * differ from the nominal value more than +50% or -25%.
596 spin_unlock_irqrestore(&subs->lock, flags); 569 */
570 shift = 0;
571 while (f < subs->freqn - subs->freqn / 4) {
572 f <<= 1;
573 shift++;
574 }
575 while (f > subs->freqn + subs->freqn / 2) {
576 f >>= 1;
577 shift--;
597 } 578 }
579 subs->freqshift = shift;
598 } 580 }
581 else if (subs->freqshift >= 0)
582 f <<= subs->freqshift;
583 else
584 f >>= -subs->freqshift;
599 585
600 return 0; 586 if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
601} 587 /*
602 588 * If the frequency looks valid, set it.
603/* 589 * This value is referred to in prepare_playback_urb().
604 * process after E-Mu 0202/0404/Tracker Pre high speed playback sync complete 590 */
605 * 591 spin_lock_irqsave(&subs->lock, flags);
606 * These devices return the number of samples per packet instead of the number 592 subs->freqm = f;
607 * of samples per microframe. 593 spin_unlock_irqrestore(&subs->lock, flags);
608 */ 594 } else {
609static int retire_playback_sync_urb_hs_emu(struct snd_usb_substream *subs, 595 /*
610 struct snd_pcm_runtime *runtime, 596 * Out of range; maybe the shift value is wrong.
611 struct urb *urb) 597 * Reset it so that we autodetect again the next time.
612{ 598 */
613 unsigned int f; 599 subs->freqshift = INT_MIN;
614 unsigned long flags;
615
616 if (urb->iso_frame_desc[0].status == 0 &&
617 urb->iso_frame_desc[0].actual_length == 4) {
618 f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
619 f >>= subs->datainterval;
620 if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
621 spin_lock_irqsave(&subs->lock, flags);
622 subs->freqm = f;
623 spin_unlock_irqrestore(&subs->lock, flags);
624 }
625 } 600 }
626 601
627 return 0; 602 return 0;
@@ -878,21 +853,6 @@ static struct snd_urb_ops audio_urb_ops[2] = {
878 }, 853 },
879}; 854};
880 855
881static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
882 {
883 .prepare = prepare_nodata_playback_urb,
884 .retire = retire_playback_urb,
885 .prepare_sync = prepare_playback_sync_urb_hs,
886 .retire_sync = retire_playback_sync_urb_hs,
887 },
888 {
889 .prepare = prepare_capture_urb,
890 .retire = retire_capture_urb,
891 .prepare_sync = prepare_capture_sync_urb_hs,
892 .retire_sync = retire_capture_sync_urb,
893 },
894};
895
896/* 856/*
897 * initialize the substream instance. 857 * initialize the substream instance.
898 */ 858 */
@@ -909,23 +869,9 @@ void snd_usb_init_substream(struct snd_usb_stream *as,
909 subs->direction = stream; 869 subs->direction = stream;
910 subs->dev = as->chip->dev; 870 subs->dev = as->chip->dev;
911 subs->txfr_quirk = as->chip->txfr_quirk; 871 subs->txfr_quirk = as->chip->txfr_quirk;
912 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) { 872 subs->ops = audio_urb_ops[stream];
913 subs->ops = audio_urb_ops[stream]; 873 if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
914 } else { 874 subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
915 subs->ops = audio_urb_ops_high_speed[stream];
916 switch (as->chip->usb_id) {
917 case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
918 case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */
919 case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */
920 subs->ops.retire_sync = retire_playback_sync_urb_hs_emu;
921 break;
922 case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra 8 */
923 case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
924 subs->ops.prepare_sync = prepare_playback_sync_urb;
925 subs->ops.retire_sync = retire_playback_sync_urb;
926 break;
927 }
928 }
929 875
930 snd_usb_set_pcm_ops(as->pcm, stream); 876 snd_usb_set_pcm_ops(as->pcm, stream);
931 877