ASoC: Always syncronize audio transfers on frames
authorEero Nurkkala <ext-eero.nurkkala@nokia.com>
Thu, 20 Aug 2009 13:18:24 +0000 (16:18 +0300)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 20 Aug 2009 19:10:29 +0000 (20:10 +0100)
All these steps are required for ASoC to behave correctly.
rccr and xccr are format dependent, for example TDM audio
has different values than I2S or DSP_A. Also the
omap_mcbsp_xmit_enable and/or omap_mcbsp_recv_enable must
be called right after the DMA has started.
This provides no longer L and R channels switching at random.

Signed-off-by: Eero Nurkkala <ext-eero.nurkkala@nokia.com>
Acked-by: Jarkko Nikula <jhnikula@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/omap/omap-mcbsp.c

index a7b09614734d7be84834824e56de921b96b992b3..6e855080e6eaa40be5894bf902b5e513b1f5a615 100644 (file)
@@ -191,6 +191,11 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                mcbsp_data->active++;
                omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
+               /* Make sure data transfer is frame synchronized */
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       omap_mcbsp_xmit_enable(mcbsp_data->bus_id, 1);
+               else
+                       omap_mcbsp_recv_enable(mcbsp_data->bus_id, 1);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
@@ -336,11 +341,15 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                /* 1-bit data delay */
                regs->rcr2      |= RDATDLY(1);
                regs->xcr2      |= XDATDLY(1);
+               regs->rccr      |= RFULL_CYCLE | RDMAEN | RDISABLE;
+               regs->xccr      |= (DXENDLY(1) | XDMAEN | XDISABLE);
                break;
        case SND_SOC_DAIFMT_DSP_A:
                /* 1-bit data delay */
                regs->rcr2      |= RDATDLY(1);
                regs->xcr2      |= XDATDLY(1);
+               regs->rccr      |= RFULL_CYCLE | RDMAEN | RDISABLE;
+               regs->xccr      |= (DXENDLY(1) | XDMAEN | XDISABLE);
                /* Invert FS polarity configuration */
                temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
                break;