From: Clemens Ladisch Date: Thu, 12 Jan 2006 08:44:29 +0000 (+0100) Subject: [PATCH] usb-audio: don't use empty packets at start of playback X-Git-Tag: v2.6.15.2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f416659e93354ad74b24dc49b0b15071b848c92;p=thirdparty%2Fkernel%2Fstable.git [PATCH] usb-audio: don't use empty packets at start of playback Some widespread USB interface chips with adaptive iso endpoints hang after receiving a series of empty packets when they expect data. This completely disables audio playback on those devices. To avoid this, we have to send packets containing silence (zero samples) instead. ALSA bug: http://bugtrack.alsa-project.org/alsa-bug/view.php?id=1585 Signed-off-by: Clemens Ladisch Signed-off-by: Chris Wright Signed-off-by: Greg Kroah-Hartman --- diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 99dae024b640b..78b0316a29fd9 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -480,22 +480,38 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs, /* * Prepare urb for streaming before playback starts. * - * We don't care about (or have) any data, so we just send a transfer delimiter. + * We don't yet have data, so we send a frame of silence. */ static int prepare_startup_playback_urb(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *urb) { - unsigned int i; + unsigned int i, offs, counts; snd_urb_ctx_t *ctx = urb->context; + int stride = runtime->frame_bits >> 3; + offs = 0; urb->dev = ctx->subs->dev; urb->number_of_packets = subs->packs_per_ms; for (i = 0; i < subs->packs_per_ms; ++i) { - urb->iso_frame_desc[i].offset = 0; - urb->iso_frame_desc[i].length = 0; + /* calculate the size of a packet */ + if (subs->fill_max) + counts = subs->maxframesize; /* fixed */ + else { + subs->phase = (subs->phase & 0xffff) + + (subs->freqm << subs->datainterval); + counts = subs->phase >> 16; + if (counts > subs->maxframesize) + counts = subs->maxframesize; + } + urb->iso_frame_desc[i].offset = offs * stride; + urb->iso_frame_desc[i].length = counts * stride; + offs += counts; } - urb->transfer_buffer_length = 0; + urb->transfer_buffer_length = offs * stride; + memset(urb->transfer_buffer, + subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, + offs * stride); return 0; }