]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
[ALSA] usb-audio: don't use empty packets at start of playback
authorClemens Ladisch <clemens@ladisch.de>
Thu, 12 Jan 2006 07:17:49 +0000 (08:17 +0100)
committerJaroslav Kysela <perex@suse.cz>
Sun, 22 Jan 2006 15:24:09 +0000 (16:24 +0100)
Modules: USB generic driver

Some widespread USB interface chips with adaptive iso endpoints hang
after receiving a series of empty packets when they expect data (ALSA
bug#1585).  To avoid this, we have to send packets containing silence
(zero samples) instead.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
sound/usb/usbaudio.c

index a1bd8040dea441a06a487ef9943a8e31997bb457..95729730bcdc2edd2bccde5868108695f020cd1d 100644 (file)
@@ -478,22 +478,38 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *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(struct snd_usb_substream *subs,
                                        struct snd_pcm_runtime *runtime,
                                        struct urb *urb)
 {
-       unsigned int i;
+       unsigned int i, offs, counts;
        struct snd_urb_ctx *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;
 }