]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
[PATCH] usb-audio: don't use empty packets at start of playback
authorClemens Ladisch <clemens@ladisch.de>
Thu, 12 Jan 2006 08:44:29 +0000 (09:44 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 31 Jan 2006 06:13:17 +0000 (22:13 -0800)
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>
sound/usb/usbaudio.c

index 99dae024b640bfd9f3ddadbf4de227cd5daca95c..78b0316a29fd9749b156190f60dff6c4a4bf197d 100644 (file)
@@ -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;
 }