From 6f416659e93354ad74b24dc49b0b15071b848c92 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 12 Jan 2006 09:44:29 +0100 Subject: [PATCH] [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 --- sound/usb/usbaudio.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) 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; } -- 2.47.2