ALSA: snd-usb: restore delay information
Parts of commit 294c4fb8
("ALSA: usb: refine delay information with USB
frame counter") were unfortunately lost during the refactoring of the
snd-usb driver in 3.5.
This patch adds them back, restoring the correct delay information
behaviour.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Cc: stable@kernel.org [3.5+]
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
03d2f44e96
commit
fbcfbf5f67
|
@ -1091,7 +1091,16 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
|
||||||
subs->hwptr_done += bytes;
|
subs->hwptr_done += bytes;
|
||||||
if (subs->hwptr_done >= runtime->buffer_size * stride)
|
if (subs->hwptr_done >= runtime->buffer_size * stride)
|
||||||
subs->hwptr_done -= runtime->buffer_size * stride;
|
subs->hwptr_done -= runtime->buffer_size * stride;
|
||||||
|
|
||||||
|
/* update delay with exact number of samples queued */
|
||||||
|
runtime->delay = subs->last_delay;
|
||||||
runtime->delay += frames;
|
runtime->delay += frames;
|
||||||
|
subs->last_delay = runtime->delay;
|
||||||
|
|
||||||
|
/* realign last_frame_number */
|
||||||
|
subs->last_frame_number = usb_get_current_frame_number(subs->dev);
|
||||||
|
subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
|
||||||
|
|
||||||
spin_unlock_irqrestore(&subs->lock, flags);
|
spin_unlock_irqrestore(&subs->lock, flags);
|
||||||
urb->transfer_buffer_length = bytes;
|
urb->transfer_buffer_length = bytes;
|
||||||
if (period_elapsed)
|
if (period_elapsed)
|
||||||
|
@ -1109,12 +1118,26 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
|
||||||
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
|
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
|
||||||
int stride = runtime->frame_bits >> 3;
|
int stride = runtime->frame_bits >> 3;
|
||||||
int processed = urb->transfer_buffer_length / stride;
|
int processed = urb->transfer_buffer_length / stride;
|
||||||
|
int est_delay;
|
||||||
|
|
||||||
spin_lock_irqsave(&subs->lock, flags);
|
spin_lock_irqsave(&subs->lock, flags);
|
||||||
if (processed > runtime->delay)
|
est_delay = snd_usb_pcm_delay(subs, runtime->rate);
|
||||||
runtime->delay = 0;
|
/* update delay with exact number of samples played */
|
||||||
|
if (processed > subs->last_delay)
|
||||||
|
subs->last_delay = 0;
|
||||||
else
|
else
|
||||||
runtime->delay -= processed;
|
subs->last_delay -= processed;
|
||||||
|
runtime->delay = subs->last_delay;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Report when delay estimate is off by more than 2ms.
|
||||||
|
* The error should be lower than 2ms since the estimate relies
|
||||||
|
* on two reads of a counter updated every ms.
|
||||||
|
*/
|
||||||
|
if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
|
||||||
|
snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
|
||||||
|
est_delay, subs->last_delay);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&subs->lock, flags);
|
spin_unlock_irqrestore(&subs->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue