ALSA: core: group read of pointer, tstamp and jiffies
Group read of hw_ptr, tstamp and jiffies in a sequence for better correlation. Previous code took timestamp at the end, which could introduce delays between audio time and system time. Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
599ed4b0ae
commit
3509a03f4d
|
@ -313,9 +313,22 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||||
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
|
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
|
||||||
snd_pcm_sframes_t hdelta, delta;
|
snd_pcm_sframes_t hdelta, delta;
|
||||||
unsigned long jdelta;
|
unsigned long jdelta;
|
||||||
|
unsigned long curr_jiffies;
|
||||||
|
struct timespec curr_tstamp;
|
||||||
|
|
||||||
old_hw_ptr = runtime->status->hw_ptr;
|
old_hw_ptr = runtime->status->hw_ptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* group pointer, time and jiffies reads to allow for more
|
||||||
|
* accurate correlations/corrections.
|
||||||
|
* The values are stored at the end of this routine after
|
||||||
|
* corrections for hw_ptr position
|
||||||
|
*/
|
||||||
pos = substream->ops->pointer(substream);
|
pos = substream->ops->pointer(substream);
|
||||||
|
curr_jiffies = jiffies;
|
||||||
|
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
|
||||||
|
snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
|
||||||
|
|
||||||
if (pos == SNDRV_PCM_POS_XRUN) {
|
if (pos == SNDRV_PCM_POS_XRUN) {
|
||||||
xrun(substream);
|
xrun(substream);
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
|
@ -343,7 +356,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||||
delta = runtime->hw_ptr_interrupt + runtime->period_size;
|
delta = runtime->hw_ptr_interrupt + runtime->period_size;
|
||||||
if (delta > new_hw_ptr) {
|
if (delta > new_hw_ptr) {
|
||||||
/* check for double acknowledged interrupts */
|
/* check for double acknowledged interrupts */
|
||||||
hdelta = jiffies - runtime->hw_ptr_jiffies;
|
hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
|
||||||
if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
|
if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
|
||||||
hw_base += runtime->buffer_size;
|
hw_base += runtime->buffer_size;
|
||||||
if (hw_base >= runtime->boundary)
|
if (hw_base >= runtime->boundary)
|
||||||
|
@ -388,7 +401,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||||
* Without regular period interrupts, we have to check
|
* Without regular period interrupts, we have to check
|
||||||
* the elapsed time to detect xruns.
|
* the elapsed time to detect xruns.
|
||||||
*/
|
*/
|
||||||
jdelta = jiffies - runtime->hw_ptr_jiffies;
|
jdelta = curr_jiffies - runtime->hw_ptr_jiffies;
|
||||||
if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
|
if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
|
||||||
goto no_delta_check;
|
goto no_delta_check;
|
||||||
hdelta = jdelta - delta * HZ / runtime->rate;
|
hdelta = jdelta - delta * HZ / runtime->rate;
|
||||||
|
@ -430,7 +443,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||||
if (hdelta < runtime->delay)
|
if (hdelta < runtime->delay)
|
||||||
goto no_jiffies_check;
|
goto no_jiffies_check;
|
||||||
hdelta -= runtime->delay;
|
hdelta -= runtime->delay;
|
||||||
jdelta = jiffies - runtime->hw_ptr_jiffies;
|
jdelta = curr_jiffies - runtime->hw_ptr_jiffies;
|
||||||
if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
|
if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
|
||||||
delta = jdelta /
|
delta = jdelta /
|
||||||
(((runtime->period_size * HZ) / runtime->rate)
|
(((runtime->period_size * HZ) / runtime->rate)
|
||||||
|
@ -492,9 +505,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
||||||
}
|
}
|
||||||
runtime->hw_ptr_base = hw_base;
|
runtime->hw_ptr_base = hw_base;
|
||||||
runtime->status->hw_ptr = new_hw_ptr;
|
runtime->status->hw_ptr = new_hw_ptr;
|
||||||
runtime->hw_ptr_jiffies = jiffies;
|
runtime->hw_ptr_jiffies = curr_jiffies;
|
||||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
|
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
|
||||||
snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
|
runtime->status->tstamp = curr_tstamp;
|
||||||
|
|
||||||
return snd_pcm_update_state(substream, runtime);
|
return snd_pcm_update_state(substream, runtime);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue