aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2006-01-12 09:44:29 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-30 22:13:17 -0800
commit6f416659e93354ad74b24dc49b0b15071b848c92 (patch)
tree79fdb96eb84fccb55b07c2bf036fece888344177
parent9a50e1ccd38517c04f16e96fdf4117a69c293af1 (diff)
downloadlinux-linaro-stable-6f416659e93354ad74b24dc49b0b15071b848c92.tar.gz
[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>
-rw-r--r--sound/usb/usbaudio.c26
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;
}