summaryrefslogtreecommitdiff
path: root/sound/usb/usbaudio.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-06-10 09:26:40 +0400
committerTakashi Iwai <tiwai@suse.de>2009-06-10 09:26:40 +0400
commiteabaf0634a9034f2e487b0be347edc1460c026a4 (patch)
treee950df1ba10e0a29b25afdd446ac44988381a851 /sound/usb/usbaudio.c
parent9dea75c70965c240012251dc5845fe0c1a061180 (diff)
parentae1ec5e1e97f67d41e641a73380129e5905e41cc (diff)
downloadlinux-eabaf0634a9034f2e487b0be347edc1460c026a4.tar.xz
Merge branch 'topic/pcm-delay' into for-linus
* topic/pcm-delay: ALSA: usbaudio - Add delay account ALSA: Add extra delay count in PCM
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r--sound/usb/usbaudio.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index a6b88482637b..a8ef2cbcc03b 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);