Commit 3509a03f4dcf7fedb8880180fed3f7f791ce5598
Committed by
Takashi Iwai
1 parent
599ed4b0ae
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 1 changed file with 18 additions and 5 deletions Side-by-side Diff
sound/core/pcm_lib.c
... | ... | @@ -313,9 +313,22 @@ |
313 | 313 | snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; |
314 | 314 | snd_pcm_sframes_t hdelta, delta; |
315 | 315 | unsigned long jdelta; |
316 | + unsigned long curr_jiffies; | |
317 | + struct timespec curr_tstamp; | |
316 | 318 | |
317 | 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 | 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 | 332 | if (pos == SNDRV_PCM_POS_XRUN) { |
320 | 333 | xrun(substream); |
321 | 334 | return -EPIPE; |
... | ... | @@ -343,7 +356,7 @@ |
343 | 356 | delta = runtime->hw_ptr_interrupt + runtime->period_size; |
344 | 357 | if (delta > new_hw_ptr) { |
345 | 358 | /* check for double acknowledged interrupts */ |
346 | - hdelta = jiffies - runtime->hw_ptr_jiffies; | |
359 | + hdelta = curr_jiffies - runtime->hw_ptr_jiffies; | |
347 | 360 | if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { |
348 | 361 | hw_base += runtime->buffer_size; |
349 | 362 | if (hw_base >= runtime->boundary) |
... | ... | @@ -388,7 +401,7 @@ |
388 | 401 | * Without regular period interrupts, we have to check |
389 | 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 | 405 | if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) |
393 | 406 | goto no_delta_check; |
394 | 407 | hdelta = jdelta - delta * HZ / runtime->rate; |
... | ... | @@ -430,7 +443,7 @@ |
430 | 443 | if (hdelta < runtime->delay) |
431 | 444 | goto no_jiffies_check; |
432 | 445 | hdelta -= runtime->delay; |
433 | - jdelta = jiffies - runtime->hw_ptr_jiffies; | |
446 | + jdelta = curr_jiffies - runtime->hw_ptr_jiffies; | |
434 | 447 | if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { |
435 | 448 | delta = jdelta / |
436 | 449 | (((runtime->period_size * HZ) / runtime->rate) |
437 | 450 | |
... | ... | @@ -492,9 +505,9 @@ |
492 | 505 | } |
493 | 506 | runtime->hw_ptr_base = hw_base; |
494 | 507 | runtime->status->hw_ptr = new_hw_ptr; |
495 | - runtime->hw_ptr_jiffies = jiffies; | |
508 | + runtime->hw_ptr_jiffies = curr_jiffies; | |
496 | 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 | 512 | return snd_pcm_update_state(substream, runtime); |
500 | 513 | } |