Commit 3509a03f4dcf7fedb8880180fed3f7f791ce5598

Authored by Pierre-Louis Bossart
Committed by Takashi Iwai
1 parent 599ed4b0ae

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 }