diff options
| -rw-r--r-- | sound/usb/card.h | 2 | ||||
| -rw-r--r-- | sound/usb/pcm.c | 2 | ||||
| -rw-r--r-- | sound/usb/proc.c | 5 | ||||
| -rw-r--r-- | sound/usb/urb.c | 170 |
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 | |||
| 521 | static int prepare_playback_sync_urb(struct snd_usb_substream *subs, | 521 | static 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 | |
| 539 | static 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 | */ |
| 557 | static int retire_playback_sync_urb(struct snd_usb_substream *subs, | 543 | static 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) |
| 583 | static 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 { |
| 609 | static 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 | ||
| 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 | * 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 | ||
