Commit e8648e5e authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Ignore small negative LPIB delay correction

Sometimes the hardware reports LPIB being advanced than POSBUF.
When this happens, the driver adjusts to a positive value by adding
the buffer size.  Then the driver detects it as an error (greater than
the period size), and stops the LPIB delay account from this point
on.

When I took a close look at these conditions, the values shown are all
very small numbers, and it'd be better to just ignore these values
instead of discontinuing the LPIB delay correction.

In this patch, the driver checks a negative delay value and ignores if
it's a significantly small error.  Currently the threshold is set to
64 frames, but could be smaller.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4f7f67fb
...@@ -431,6 +431,8 @@ struct azx_dev { ...@@ -431,6 +431,8 @@ struct azx_dev {
struct timecounter azx_tc; struct timecounter azx_tc;
struct cyclecounter azx_cc; struct cyclecounter azx_cc;
int delay_negative_threshold;
#ifdef CONFIG_SND_HDA_DSP_LOADER #ifdef CONFIG_SND_HDA_DSP_LOADER
struct mutex dsp_mutex; struct mutex dsp_mutex;
#endif #endif
...@@ -2195,6 +2197,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -2195,6 +2197,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
goto unlock; goto unlock;
} }
/* when LPIB delay correction gives a small negative value,
* we ignore it; currently set the threshold statically to
* 64 frames
*/
if (runtime->period_size > 64)
azx_dev->delay_negative_threshold = -frames_to_bytes(runtime, 64);
else
azx_dev->delay_negative_threshold = 0;
/* wallclk has 24Mhz clock source */ /* wallclk has 24Mhz clock source */
azx_dev->period_wallclk = (((runtime->period_size * 24000) / azx_dev->period_wallclk = (((runtime->period_size * 24000) /
runtime->rate) * 1000); runtime->rate) * 1000);
...@@ -2447,8 +2458,12 @@ static unsigned int azx_get_position(struct azx *chip, ...@@ -2447,8 +2458,12 @@ static unsigned int azx_get_position(struct azx *chip,
delay = pos - lpib_pos; delay = pos - lpib_pos;
else else
delay = lpib_pos - pos; delay = lpib_pos - pos;
if (delay < 0) if (delay < 0) {
if (delay >= azx_dev->delay_negative_threshold)
delay = 0;
else
delay += azx_dev->bufsize; delay += azx_dev->bufsize;
}
if (delay >= azx_dev->period_bytes) { if (delay >= azx_dev->period_bytes) {
snd_printk(KERN_WARNING SFX snd_printk(KERN_WARNING SFX
"%s: Unstable LPIB (%d >= %d); " "%s: Unstable LPIB (%d >= %d); "
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment