ASoC: Improve pause/unpause performance in Freescale 8610 drivers
authorTimur Tabi <timur@freescale.com>
Sat, 7 Mar 2009 00:39:34 +0000 (18:39 -0600)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 7 Mar 2009 11:01:49 +0000 (11:01 +0000)
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: Timur Tabi <timur@freescale.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_ssi.c

index 58a3fa497503179f6caea3fdcb7e6f8b8b9c1902..b3eb8570cd7bf4a4073082fffdc9f3dbb71d9521 100644 (file)
@@ -142,7 +142,8 @@ static const struct snd_pcm_hardware fsl_dma_hardware = {
        .info                   = SNDRV_PCM_INFO_INTERLEAVED |
                                  SNDRV_PCM_INFO_MMAP |
                                  SNDRV_PCM_INFO_MMAP_VALID |
-                                 SNDRV_PCM_INFO_JOINT_DUPLEX,
+                                 SNDRV_PCM_INFO_JOINT_DUPLEX |
+                                 SNDRV_PCM_INFO_PAUSE,
        .formats                = FSLDMA_PCM_FORMATS,
        .rates                  = FSLDMA_PCM_RATES,
        .rate_min               = 5512,
index 8cb6bcf2c00f7aef9c1550d574323c18fea301ba..b7733e6be192fe0bf0d2792c4bb7e086695ddc5c 100644 (file)
@@ -464,28 +464,33 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
+               clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
                        setbits32(&ssi->scr,
                                CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
                } else {
-                       clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
+                       long timeout = jiffies + 10;
+
                        setbits32(&ssi->scr,
                                CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
 
-                       /*
-                        * I think we need this delay to allow time for the SSI
-                        * to put data into its FIFO.  Without it, ALSA starts
-                        * to complain about overruns.
+                       /* Wait until the SSI has filled its FIFO. Without this
+                        * delay, ALSA complains about overruns.  When the FIFO
+                        * is full, the DMA controller initiates its first
+                        * 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;
 
        case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        clrbits32(&ssi->scr, CCSR_SSI_SCR_TE);