At Fri, 22 May 2009 16:27:09 -0400, Chuck Ebbert wrote:
Bug report: https://bugzilla.redhat.com/show_bug.cgi?id=498858
To reproduce, pause a video in mplayer and then hit play:
ALSA sound/core/pcm_lib.c:263: hda_codec: hw_ptr skipping! [Q] (pos=11263, delta=17400, period=1024, jdelta=21/362/0)
Does the patch fix the problem?
thanks,
Takashi
--- diff --git a/include/sound/pcm.h b/include/sound/pcm.h index c172968..7366910 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -266,6 +266,7 @@ struct snd_pcm_runtime { struct snd_pcm_substream *trigger_master; struct timespec trigger_tstamp; /* trigger timestamp */ int overrange; + unsigned int jiffies_set:1; /* hw_ptr_jiffies is set */ snd_pcm_uframes_t avail_max; snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a2a792c..78edd6e 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -249,6 +249,8 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; } } + if (!runtime->jiffies_set) + goto no_jiffies_check; /* Skip the jiffies check for hardwares with BATCH flag. * Such hardware usually just increases the position at each IRQ, * thus it can't give any strange position. @@ -296,6 +298,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; runtime->hw_ptr_jiffies = jiffies; + runtime->jiffies_set = 1; runtime->hw_ptr_interrupt = hw_ptr_interrupt;
return snd_pcm_update_hw_ptr_post(substream, runtime); @@ -336,7 +339,8 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) hw_base = 0; new_hw_ptr = hw_base + pos; } - if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) { + if (runtime->jiffies_set && + ((delta * HZ) / runtime->rate) > jdelta + HZ/100) { hw_ptr_error(substream, "hw_ptr skipping! " "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n", @@ -352,6 +356,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; runtime->hw_ptr_jiffies = jiffies; + runtime->jiffies_set = 1;
return snd_pcm_update_hw_ptr_post(substream, runtime); } @@ -1478,7 +1483,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, runtime->status->hw_ptr %= runtime->buffer_size; else runtime->status->hw_ptr = 0; - runtime->hw_ptr_jiffies = jiffies; snd_pcm_stream_unlock_irqrestore(substream, flags); return 0; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index fc6f98e..5cf67a5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -978,6 +978,7 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); + runtime->jiffies_set = 0; if (push) { runtime->status->state = SNDRV_PCM_STATE_PAUSED; if (substream->timer) @@ -1041,6 +1042,7 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state) &runtime->trigger_tstamp); runtime->status->suspended_state = runtime->status->state; runtime->status->state = SNDRV_PCM_STATE_SUSPENDED; + runtime->jiffies_set = 0; wake_up(&runtime->sleep); }
@@ -1234,6 +1236,7 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state) runtime->status->hw_ptr % runtime->period_size; runtime->silence_start = runtime->status->hw_ptr; runtime->silence_filled = 0; + runtime->jiffies_set = 0; return 0; }