Commit 3a638ff2 authored by Timur Tabi's avatar Timur Tabi Committed by Mark Brown

ASoC: Improve pause/unpause performance in Freescale 8610 drivers

Add support for true pause and unpause.  Without this, mplayer will drop some
audio (less than one second, but still noticeable) when pausing playback.

Remove support for PM suspend and resume from the trigger function, since the
driver doesn't support PM anyway.

Optimize the delay after starting capture.  Instead of delaying 1ms, the driver
now polls the hardware.  The new delay is shorter by over 90% yet still
effective.
Signed-off-by: default avatarTimur Tabi <timur@freescale.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 96deff6b
...@@ -142,7 +142,8 @@ static const struct snd_pcm_hardware fsl_dma_hardware = { ...@@ -142,7 +142,8 @@ static const struct snd_pcm_hardware fsl_dma_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED | .info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_JOINT_DUPLEX, SNDRV_PCM_INFO_JOINT_DUPLEX |
SNDRV_PCM_INFO_PAUSE,
.formats = FSLDMA_PCM_FORMATS, .formats = FSLDMA_PCM_FORMATS,
.rates = FSLDMA_PCM_RATES, .rates = FSLDMA_PCM_RATES,
.rate_min = 5512, .rate_min = 5512,
......
...@@ -464,28 +464,33 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -464,28 +464,33 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME: clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
setbits32(&ssi->scr, setbits32(&ssi->scr,
CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
} else { } else {
clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); long timeout = jiffies + 10;
setbits32(&ssi->scr, setbits32(&ssi->scr,
CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
/* /* Wait until the SSI has filled its FIFO. Without this
* I think we need this delay to allow time for the SSI * delay, ALSA complains about overruns. When the FIFO
* to put data into its FIFO. Without it, ALSA starts * is full, the DMA controller initiates its first
* to complain about overruns. * transfer. Until then, however, the DMA's DAR
* register is zero, which translates to an
* out-of-bounds pointer. This makes ALSA think an
* overrun has occurred.
*/ */
mdelay(1); while (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0) &&
(jiffies < timeout));
if (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0))
return -EIO;
} }
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); clrbits32(&ssi->scr, CCSR_SSI_SCR_TE);
......
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