diff options
author | Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> | 2012-05-22 15:54:02 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-05-22 19:50:29 -0400 |
commit | 3509a03f4dcf7fedb8880180fed3f7f791ce5598 (patch) | |
tree | 9be4d6f21e9fe84926b96b39fbb825c537168011 /sound | |
parent | 599ed4b0aeceb6d45ea33f64639e745e3da72766 (diff) |
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>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/pcm_lib.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index faedb1481b24..8f312fa6c282 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -313,9 +313,22 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
313 | snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; | 313 | snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; |
314 | snd_pcm_sframes_t hdelta, delta; | 314 | snd_pcm_sframes_t hdelta, delta; |
315 | unsigned long jdelta; | 315 | unsigned long jdelta; |
316 | unsigned long curr_jiffies; | ||
317 | struct timespec curr_tstamp; | ||
316 | 318 | ||
317 | old_hw_ptr = runtime->status->hw_ptr; | 319 | old_hw_ptr = runtime->status->hw_ptr; |
320 | |||
321 | /* | ||
322 | * group pointer, time and jiffies reads to allow for more | ||
323 | * accurate correlations/corrections. | ||
324 | * The values are stored at the end of this routine after | ||
325 | * corrections for hw_ptr position | ||
326 | */ | ||
318 | pos = substream->ops->pointer(substream); | 327 | pos = substream->ops->pointer(substream); |
328 | curr_jiffies = jiffies; | ||
329 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) | ||
330 | snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); | ||
331 | |||
319 | if (pos == SNDRV_PCM_POS_XRUN) { | 332 | if (pos == SNDRV_PCM_POS_XRUN) { |
320 | xrun(substream); | 333 | xrun(substream); |
321 | return -EPIPE; | 334 | return -EPIPE; |
@@ -343,7 +356,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
343 | delta = runtime->hw_ptr_interrupt + runtime->period_size; | 356 | delta = runtime->hw_ptr_interrupt + runtime->period_size; |
344 | if (delta > new_hw_ptr) { | 357 | if (delta > new_hw_ptr) { |
345 | /* check for double acknowledged interrupts */ | 358 | /* check for double acknowledged interrupts */ |
346 | hdelta = jiffies - runtime->hw_ptr_jiffies; | 359 | hdelta = curr_jiffies - runtime->hw_ptr_jiffies; |
347 | if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { | 360 | if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { |
348 | hw_base += runtime->buffer_size; | 361 | hw_base += runtime->buffer_size; |
349 | if (hw_base >= runtime->boundary) | 362 | if (hw_base >= runtime->boundary) |
@@ -388,7 +401,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
388 | * Without regular period interrupts, we have to check | 401 | * Without regular period interrupts, we have to check |
389 | * the elapsed time to detect xruns. | 402 | * the elapsed time to detect xruns. |
390 | */ | 403 | */ |
391 | jdelta = jiffies - runtime->hw_ptr_jiffies; | 404 | jdelta = curr_jiffies - runtime->hw_ptr_jiffies; |
392 | if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) | 405 | if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) |
393 | goto no_delta_check; | 406 | goto no_delta_check; |
394 | hdelta = jdelta - delta * HZ / runtime->rate; | 407 | hdelta = jdelta - delta * HZ / runtime->rate; |
@@ -430,7 +443,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
430 | if (hdelta < runtime->delay) | 443 | if (hdelta < runtime->delay) |
431 | goto no_jiffies_check; | 444 | goto no_jiffies_check; |
432 | hdelta -= runtime->delay; | 445 | hdelta -= runtime->delay; |
433 | jdelta = jiffies - runtime->hw_ptr_jiffies; | 446 | jdelta = curr_jiffies - runtime->hw_ptr_jiffies; |
434 | if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { | 447 | if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { |
435 | delta = jdelta / | 448 | delta = jdelta / |
436 | (((runtime->period_size * HZ) / runtime->rate) | 449 | (((runtime->period_size * HZ) / runtime->rate) |
@@ -492,9 +505,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
492 | } | 505 | } |
493 | runtime->hw_ptr_base = hw_base; | 506 | runtime->hw_ptr_base = hw_base; |
494 | runtime->status->hw_ptr = new_hw_ptr; | 507 | runtime->status->hw_ptr = new_hw_ptr; |
495 | runtime->hw_ptr_jiffies = jiffies; | 508 | runtime->hw_ptr_jiffies = curr_jiffies; |
496 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) | 509 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) |
497 | snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); | 510 | runtime->status->tstamp = curr_tstamp; |
498 | 511 | ||
499 | return snd_pcm_update_state(substream, runtime); | 512 | return snd_pcm_update_state(substream, runtime); |
500 | } | 513 | } |