diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2006-01-12 09:44:29 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-30 22:13:17 -0800 |
commit | 6f416659e93354ad74b24dc49b0b15071b848c92 (patch) | |
tree | 79fdb96eb84fccb55b07c2bf036fece888344177 /sound | |
parent | 9a50e1ccd38517c04f16e96fdf4117a69c293af1 (diff) |
[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 <clemens@ladisch.de>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/usbaudio.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 99dae024b640..78b0316a29fd 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; } |