ASoC: Improve pause/unpause performance in Freescale 8610 drivers
[deliverable/linux.git] / sound / soc / fsl / fsl_ssi.c
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);
This page took 0.042111 seconds and 5 git commands to generate.