diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-10-13 03:08:53 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-05-05 14:47:21 +0200 |
commit | ae1ec5e1e97f67d41e641a73380129e5905e41cc (patch) | |
tree | d6366e64044c20570724decdf2d6d10f1e476c97 /sound | |
parent | ALSA: Add extra delay count in PCM (diff) | |
download | linux-ae1ec5e1e97f67d41e641a73380129e5905e41cc.tar.xz linux-ae1ec5e1e97f67d41e641a73380129e5905e41cc.zip |
ALSA: usbaudio - Add delay account
Manage the PCM delay account based on the queued URBs.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/usbaudio.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 823296d7d578..6c25fa23f702 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -627,6 +627,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, subs->hwptr_done += offs; if (subs->hwptr_done >= runtime->buffer_size) subs->hwptr_done -= runtime->buffer_size; + runtime->delay += offs; spin_unlock_irqrestore(&subs->lock, flags); urb->transfer_buffer_length = offs * stride; if (period_elapsed) @@ -636,12 +637,22 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, /* * process after playback data complete - * - nothing to do + * - decrease the delay count again */ static int retire_playback_urb(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *urb) { + unsigned long flags; + int stride = runtime->frame_bits >> 3; + int processed = urb->transfer_buffer_length / stride; + + spin_lock_irqsave(&subs->lock, flags); + if (processed > runtime->delay) + runtime->delay = 0; + else + runtime->delay -= processed; + spin_unlock_irqrestore(&subs->lock, flags); return 0; } @@ -1520,6 +1531,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->hwptr_done = 0; subs->transfer_done = 0; subs->phase = 0; + runtime->delay = 0; /* clear urbs (to be sure) */ deactivate_urbs(subs, 0, 1); |