Merge branch 'fix/pcm-jiffies-check' into for-linus
* fix/pcm-jiffies-check: ALSA: Enable PCM hw_ptr_jiffies check only in xrun_debug mode ALSA: Fix invalid jiffies check after pause
This commit is contained in:
commit
f5219b6195
3 changed files with 19 additions and 2 deletions
|
@ -104,6 +104,11 @@ card*/pcm*/xrun_debug
|
||||||
When this value is greater than 1, the driver will show the
|
When this value is greater than 1, the driver will show the
|
||||||
stack trace additionally. This may help the debugging.
|
stack trace additionally. This may help the debugging.
|
||||||
|
|
||||||
|
Since 2.6.30, this option also enables the hwptr check using
|
||||||
|
jiffies. This detects spontaneous invalid pointer callback
|
||||||
|
values, but can be lead to too much corrections for a (mostly
|
||||||
|
buggy) hardware that doesn't give smooth pointer updates.
|
||||||
|
|
||||||
card*/pcm*/sub*/info
|
card*/pcm*/sub*/info
|
||||||
The general information of this PCM sub-stream.
|
The general information of this PCM sub-stream.
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
|
||||||
new_hw_ptr = hw_base + pos;
|
new_hw_ptr = hw_base + pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do jiffies check only in xrun_debug mode */
|
||||||
|
if (!xrun_debug(substream))
|
||||||
|
goto no_jiffies_check;
|
||||||
|
|
||||||
/* Skip the jiffies check for hardwares with BATCH flag.
|
/* Skip the jiffies check for hardwares with BATCH flag.
|
||||||
* Such hardware usually just increases the position at each IRQ,
|
* Such hardware usually just increases the position at each IRQ,
|
||||||
* thus it can't give any strange position.
|
* thus it can't give any strange position.
|
||||||
|
@ -336,7 +341,9 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
|
||||||
hw_base = 0;
|
hw_base = 0;
|
||||||
new_hw_ptr = hw_base + pos;
|
new_hw_ptr = hw_base + pos;
|
||||||
}
|
}
|
||||||
if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
|
/* Do jiffies check only in xrun_debug mode */
|
||||||
|
if (xrun_debug(substream) &&
|
||||||
|
((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
|
||||||
hw_ptr_error(substream,
|
hw_ptr_error(substream,
|
||||||
"hw_ptr skipping! "
|
"hw_ptr skipping! "
|
||||||
"(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
|
"(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
|
||||||
|
@ -1478,7 +1485,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
|
||||||
runtime->status->hw_ptr %= runtime->buffer_size;
|
runtime->status->hw_ptr %= runtime->buffer_size;
|
||||||
else
|
else
|
||||||
runtime->status->hw_ptr = 0;
|
runtime->status->hw_ptr = 0;
|
||||||
runtime->hw_ptr_jiffies = jiffies;
|
|
||||||
snd_pcm_stream_unlock_irqrestore(substream, flags);
|
snd_pcm_stream_unlock_irqrestore(substream, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -848,6 +848,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
snd_pcm_trigger_tstamp(substream);
|
snd_pcm_trigger_tstamp(substream);
|
||||||
|
runtime->hw_ptr_jiffies = jiffies;
|
||||||
runtime->status->state = state;
|
runtime->status->state = state;
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
|
||||||
runtime->silence_size > 0)
|
runtime->silence_size > 0)
|
||||||
|
@ -961,6 +962,11 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
|
||||||
{
|
{
|
||||||
if (substream->runtime->trigger_master != substream)
|
if (substream->runtime->trigger_master != substream)
|
||||||
return 0;
|
return 0;
|
||||||
|
/* The jiffies check in snd_pcm_update_hw_ptr*() is done by
|
||||||
|
* a delta betwen the current jiffies, this gives a large enough
|
||||||
|
* delta, effectively to skip the check once.
|
||||||
|
*/
|
||||||
|
substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
|
||||||
return substream->ops->trigger(substream,
|
return substream->ops->trigger(substream,
|
||||||
push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
|
push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
|
||||||
SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
|
SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
|
||||||
|
|
Loading…
Add table
Reference in a new issue