ALSA: hda - force use of SSYNC bits

SSYNC bits are typically used to start multiple
streams synchronously. It makes sense to use them
for a single stream for a more predictable startup
sequence. The transfers only start once the DMA and
FIFOs are ready. This results in a better correlation
between timestamps and number of samples played.

Credits to Kar Leong Wang for suggesting this
improvement.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Pierre-Louis Bossart 2012-09-21 18:39:05 -05:00 committed by Takashi Iwai
parent cf55e90451
commit 172d3b2096
1 changed files with 16 additions and 20 deletions

View File

@ -1986,14 +1986,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
} }
spin_lock(&chip->reg_lock); spin_lock(&chip->reg_lock);
if (nsync > 1) {
/* first, set SYNC bits of corresponding streams */ /* first, set SYNC bits of corresponding streams */
if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC)
azx_writel(chip, OLD_SSYNC, azx_writel(chip, OLD_SSYNC,
azx_readl(chip, OLD_SSYNC) | sbits); azx_readl(chip, OLD_SSYNC) | sbits);
else else
azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits); azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits);
}
snd_pcm_group_for_each_entry(s, substream) { snd_pcm_group_for_each_entry(s, substream) {
if (s->pcm->card != substream->pcm->card) if (s->pcm->card != substream->pcm->card)
continue; continue;
@ -2011,8 +2011,6 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
} }
spin_unlock(&chip->reg_lock); spin_unlock(&chip->reg_lock);
if (start) { if (start) {
if (nsync == 1)
return 0;
/* wait until all FIFOs get ready */ /* wait until all FIFOs get ready */
for (timeout = 5000; timeout; timeout--) { for (timeout = 5000; timeout; timeout--) {
nwait = 0; nwait = 0;
@ -2045,16 +2043,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
cpu_relax(); cpu_relax();
} }
} }
if (nsync > 1) { spin_lock(&chip->reg_lock);
spin_lock(&chip->reg_lock); /* reset SYNC bits */
/* reset SYNC bits */ if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC)
if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) azx_writel(chip, OLD_SSYNC,
azx_writel(chip, OLD_SSYNC, azx_readl(chip, OLD_SSYNC) & ~sbits);
azx_readl(chip, OLD_SSYNC) & ~sbits); else
else azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits);
azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); spin_unlock(&chip->reg_lock);
spin_unlock(&chip->reg_lock);
}
return 0; return 0;
} }