aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/usbaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r--sound/usb/usbaudio.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 8fa935665702..f48838a078cb 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -479,6 +479,33 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
479 return 0; 479 return 0;
480} 480}
481 481
482/*
483 * process after E-Mu 0202/0404 high speed playback sync complete
484 *
485 * These devices return the number of samples per packet instead of the number
486 * of samples per microframe.
487 */
488static int retire_playback_sync_urb_hs_emu(struct snd_usb_substream *subs,
489 struct snd_pcm_runtime *runtime,
490 struct urb *urb)
491{
492 unsigned int f;
493 unsigned long flags;
494
495 if (urb->iso_frame_desc[0].status == 0 &&
496 urb->iso_frame_desc[0].actual_length == 4) {
497 f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
498 f >>= subs->datainterval;
499 if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
500 spin_lock_irqsave(&subs->lock, flags);
501 subs->freqm = f;
502 spin_unlock_irqrestore(&subs->lock, flags);
503 }
504 }
505
506 return 0;
507}
508
482/* determine the number of frames in the next packet */ 509/* determine the number of frames in the next packet */
483static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) 510static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
484{ 511{
@@ -1735,6 +1762,8 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
1735 1762
1736 channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL); 1763 channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
1737 rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL); 1764 rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
1765 if (!channels || !rates)
1766 goto __out;
1738 1767
1739 list_for_each(p, &subs->fmt_list) { 1768 list_for_each(p, &subs->fmt_list) {
1740 struct audioformat *f; 1769 struct audioformat *f;
@@ -2219,10 +2248,17 @@ static void init_substream(struct snd_usb_stream *as, int stream, struct audiofo
2219 subs->stream = as; 2248 subs->stream = as;
2220 subs->direction = stream; 2249 subs->direction = stream;
2221 subs->dev = as->chip->dev; 2250 subs->dev = as->chip->dev;
2222 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) 2251 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) {
2223 subs->ops = audio_urb_ops[stream]; 2252 subs->ops = audio_urb_ops[stream];
2224 else 2253 } else {
2225 subs->ops = audio_urb_ops_high_speed[stream]; 2254 subs->ops = audio_urb_ops_high_speed[stream];
2255 switch (as->chip->usb_id) {
2256 case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
2257 case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */
2258 subs->ops.retire_sync = retire_playback_sync_urb_hs_emu;
2259 break;
2260 }
2261 }
2226 snd_pcm_set_ops(as->pcm, stream, 2262 snd_pcm_set_ops(as->pcm, stream,
2227 stream == SNDRV_PCM_STREAM_PLAYBACK ? 2263 stream == SNDRV_PCM_STREAM_PLAYBACK ?
2228 &snd_usb_playback_ops : &snd_usb_capture_ops); 2264 &snd_usb_playback_ops : &snd_usb_capture_ops);