diff options
author | Markus Bollinger <bollinger@digigram.com> | 2012-06-20 08:32:48 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-06-20 08:35:28 +0200 |
commit | d7dc9e32ae64b5db777017344da61a285c2347f8 (patch) | |
tree | 2f06b4dade77082cefce0f06491f12d5bfbd692c /sound | |
parent | e0815f35ccd276a903298ad4c3d8d10b65933b86 (diff) | |
download | linux-d7dc9e32ae64b5db777017344da61a285c2347f8.tar.gz |
ALSA: pcxhr: Fix a counter wrap
fix a counter wrap to avoid resynchronization of stream positions every several
minutes. The resynchronization may create stream position jitter
Signed-off-by: Markus Bollinger <bollinger@digigram.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/pcxhr/pcxhr_core.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 304411c1fe4b..841703b5c52a 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c @@ -1133,13 +1133,12 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; hw_sample_count += (u_int64_t)rmh.stat[1]; - snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n", + snd_printdd("stream %c%d : abs samples real(%llu) timer(%llu)\n", stream->pipe->is_capture ? 'C' : 'P', stream->substream->number, - (long unsigned int)hw_sample_count, - (long unsigned int)(stream->timer_abs_periods + - stream->timer_period_frag + - mgr->granularity)); + hw_sample_count, + stream->timer_abs_periods + stream->timer_period_frag + + mgr->granularity); return hw_sample_count; } @@ -1243,10 +1242,18 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) if ((dsp_time_diff < 0) && (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { - snd_printdd("ERROR DSP TIME old(%d) new(%d) -> " - "resynchronize all streams\n", + /* handle dsp counter wraparound without resync */ + int tmp_diff = dsp_time_diff + PCXHR_DSP_TIME_MASK + 1; + snd_printdd("WARNING DSP timestamp old(%d) new(%d)", mgr->dsp_time_last, dsp_time_new); - mgr->dsp_time_err++; + if (tmp_diff > 0 && tmp_diff <= (2*mgr->granularity)) { + snd_printdd("-> timestamp wraparound OK: " + "diff=%d\n", tmp_diff); + dsp_time_diff = tmp_diff; + } else { + snd_printdd("-> resynchronize all streams\n"); + mgr->dsp_time_err++; + } } #ifdef CONFIG_SND_DEBUG_VERBOSE if (dsp_time_diff == 0) |