Commit 89e1e66d6be8a520cdcd26043cda2cc870a34015

Authored by Clemens Ladisch
Committed by Takashi Iwai
1 parent 0d040df998

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>

Showing 4 changed files with 67 additions and 112 deletions Side-by-side Diff

... ... @@ -62,12 +62,14 @@
62 62 unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
63 63 unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */
64 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 66 unsigned int freqmax; /* maximum sampling rate, used for buffer management */
66 67 unsigned int phase; /* phase accumulator */
67 68 unsigned int maxpacksize; /* max packet size in bytes */
68 69 unsigned int maxframesize; /* max packet size in frames */
69 70 unsigned int curpacksize; /* current packet size in bytes (for capture) */
70 71 unsigned int curframesize; /* current packet size in frames (for capture) */
  72 + unsigned int syncmaxsize; /* sync endpoint packet size */
71 73 unsigned int fill_max: 1; /* fill max packet size always */
72 74 unsigned int txfr_quirk:1; /* allow sub-frame alignment */
73 75 unsigned int fmt_type; /* USB audio format type (1-3) */
... ... @@ -237,6 +237,7 @@
237 237 subs->datainterval = fmt->datainterval;
238 238 subs->syncpipe = subs->syncinterval = 0;
239 239 subs->maxpacksize = fmt->maxpacksize;
  240 + subs->syncmaxsize = 0;
240 241 subs->fill_max = 0;
241 242  
242 243 /* we need a sync pipe in async OUT or adaptive IN mode */
... ... @@ -283,6 +284,7 @@
283 284 subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
284 285 else
285 286 subs->syncinterval = 3;
  287 + subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
286 288 }
287 289  
288 290 /* always fill max packet size */
... ... @@ -132,6 +132,11 @@
132 132 ? get_full_speed_hz(subs->freqm)
133 133 : get_high_speed_hz(subs->freqm),
134 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 140 } else {
136 141 snd_iprintf(buffer, " Status: Stop\n");
137 142 }
... ... @@ -225,6 +225,7 @@
225 225 else
226 226 subs->freqn = get_usb_high_speed_rate(rate);
227 227 subs->freqm = subs->freqn;
  228 + subs->freqshift = INT_MIN;
228 229 /* calculate max. frequency */
229 230 if (subs->maxpacksize) {
230 231 /* whatever fits into a max. size packet */
231 232  
... ... @@ -513,11 +514,10 @@
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 519 * set up the offset and length to receive the current frequency.
519 520 */
520   -
521 521 static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
522 522 struct snd_pcm_runtime *runtime,
523 523 struct urb *urb)
524 524  
525 525  
526 526  
527 527  
528 528  
529 529  
530 530  
531 531  
532 532  
533 533  
... ... @@ -525,103 +525,78 @@
525 525 struct snd_urb_ctx *ctx = urb->context;
526 526  
527 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 529 urb->iso_frame_desc[0].offset = 0;
530 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 + * frame, high speed devices in 16.16 format as samples per microframe.
  538 + * Because the Audio Class 1 spec was written before USB 2.0, many high speed
  539 + * devices use a wrong interpretation, some others use an entirely different
  540 + * format. Therefore, we cannot predict what format any particular device uses
  541 + * and must detect it automatically.
537 542 */
538   -
539   -static int prepare_playback_sync_urb_hs(struct snd_usb_substream *subs,
540   - struct snd_pcm_runtime *runtime,
541   - struct urb *urb)
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   - */
557 543 static int retire_playback_sync_urb(struct snd_usb_substream *subs,
558 544 struct snd_pcm_runtime *runtime,
559 545 struct urb *urb)
560 546 {
561 547 unsigned int f;
  548 + int shift;
562 549 unsigned long flags;
563 550  
564   - if (urb->iso_frame_desc[0].status == 0 &&
565   - urb->iso_frame_desc[0].actual_length == 3) {
566   - f = combine_triple((u8*)urb->transfer_buffer) << 2;
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   - }
  551 + if (urb->iso_frame_desc[0].status != 0 ||
  552 + urb->iso_frame_desc[0].actual_length < 3)
  553 + return 0;
573 554  
574   - return 0;
575   -}
  555 + f = le32_to_cpup(urb->transfer_buffer);
  556 + if (urb->iso_frame_desc[0].actual_length == 3)
  557 + f &= 0x00ffffff;
  558 + else
  559 + f &= 0x0fffffff;
  560 + if (f == 0)
  561 + return 0;
576 562  
577   -/*
578   - * process after high speed playback sync complete
579   - *
580   - * retrieve the current 12.13 frequency from pipe, and set it.
581   - * the value is referred in prepare_playback_urb().
582   - */
583   -static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
584   - struct snd_pcm_runtime *runtime,
585   - struct urb *urb)
586   -{
587   - unsigned int f;
588   - unsigned long flags;
589   -
590   - if (urb->iso_frame_desc[0].status == 0 &&
591   - urb->iso_frame_desc[0].actual_length == 4) {
592   - f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
593   - if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
594   - spin_lock_irqsave(&subs->lock, flags);
595   - subs->freqm = f;
596   - spin_unlock_irqrestore(&subs->lock, flags);
  563 + if (unlikely(subs->freqshift == INT_MIN)) {
  564 + /*
  565 + * The first time we see a feedback value, determine its format
  566 + * by shifting it left or right until it matches the nominal
  567 + * frequency value. This assumes that the feedback does not
  568 + * differ from the nominal value more than +50% or -25%.
  569 + */
  570 + shift = 0;
  571 + while (f < subs->freqn - subs->freqn / 4) {
  572 + f <<= 1;
  573 + shift++;
597 574 }
  575 + while (f > subs->freqn + subs->freqn / 2) {
  576 + f >>= 1;
  577 + shift--;
  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;
601   -}
602   -
603   -/*
604   - * process after E-Mu 0202/0404/Tracker Pre high speed playback sync complete
605   - *
606   - * These devices return the number of samples per packet instead of the number
607   - * of samples per microframe.
608   - */
609   -static int retire_playback_sync_urb_hs_emu(struct snd_usb_substream *subs,
610   - struct snd_pcm_runtime *runtime,
611   - struct urb *urb)
612   -{
613   - unsigned int f;
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   - }
  586 + if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
  587 + /*
  588 + * If the frequency looks valid, set it.
  589 + * This value is referred to in prepare_playback_urb().
  590 + */
  591 + spin_lock_irqsave(&subs->lock, flags);
  592 + subs->freqm = f;
  593 + spin_unlock_irqrestore(&subs->lock, flags);
  594 + } else {
  595 + /*
  596 + * Out of range; maybe the shift value is wrong.
  597 + * Reset it so that we autodetect again the next time.
  598 + */
  599 + subs->freqshift = INT_MIN;
625 600 }
626 601  
627 602 return 0;
... ... @@ -878,21 +853,6 @@
878 853 },
879 854 };
880 855  
881   -static 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 857 * initialize the substream instance.
898 858 */
... ... @@ -909,23 +869,9 @@
909 869 subs->direction = stream;
910 870 subs->dev = as->chip->dev;
911 871 subs->txfr_quirk = as->chip->txfr_quirk;
912   - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) {
913   - subs->ops = audio_urb_ops[stream];
914   - } else {
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   - }
  872 + subs->ops = audio_urb_ops[stream];
  873 + if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
  874 + subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
929 875  
930 876 snd_usb_set_pcm_ops(as->pcm, stream);
931 877