]> rtime.felk.cvut.cz Git - linux-imx.git/commitdiff
ALSA: core: group read of pointer, tstamp and jiffies
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Tue, 22 May 2012 19:54:02 +0000 (14:54 -0500)
committerTakashi Iwai <tiwai@suse.de>
Tue, 22 May 2012 23:50:29 +0000 (01:50 +0200)
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>
sound/core/pcm_lib.c

index faedb1481b240d9195b097f1448f98df3dcb6912..8f312fa6c282c88db2cd0c84389096228fe70fc4 100644 (file)
@@ -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_sframes_t hdelta, delta;
        unsigned long jdelta;
+       unsigned long curr_jiffies;
+       struct timespec curr_tstamp;
 
        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);
+       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) {
                xrun(substream);
                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;
                if (delta > new_hw_ptr) {
                        /* 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) {
                                hw_base += runtime->buffer_size;
                                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
                 * 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)
                        goto no_delta_check;
                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)
                goto no_jiffies_check;
        hdelta -= runtime->delay;
-       jdelta = jiffies - runtime->hw_ptr_jiffies;
+       jdelta = curr_jiffies - runtime->hw_ptr_jiffies;
        if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
                delta = jdelta /
                        (((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->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)
-               snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
+               runtime->status->tstamp = curr_tstamp;
 
        return snd_pcm_update_state(substream, runtime);
 }