]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00156745 MX6Q ESAI: Playback and record can't start up concurrently
authorLionel Xu <Lionel.Xu@freescale.com>
Fri, 30 Sep 2011 06:47:31 +0000 (14:47 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:15 +0000 (08:33 +0200)
Proper flag setting and placement should be used to avoid function hw_param
called multiple times when playback and record startup concurrently.

Signed-off-by: Lionel Xu <Lionel.Xu@freescale.com>
sound/soc/codecs/cs42888.c
sound/soc/imx/imx-cs42888.c
sound/soc/imx/imx-esai.c
sound/soc/imx/imx-esai.h

index c810333b32848da3675e707a510a9186f580c6c4..f2480cc1490f7e081875190ce9c13e304256b9a7 100644 (file)
@@ -784,7 +784,6 @@ struct snd_soc_dai_driver cs42888_dai = {
                .formats = CS42888_FORMATS,
        },
        .ops = &cs42888_dai_ops,
-       .symmetric_rates = 1,
 };
 
 /**
index e9f6633f1b741d286fd05038b0619374f7beeb3f..d34be0a0e8f997ba065883ff2873f7adb5d7df07 100644 (file)
 #include "../codecs/cs42888.h"
 
 
-struct imx_3stack_pcm_state {
-       int lr_clk_active;
+struct imx_priv_state {
+       int hw;
 };
 
-static struct imx_3stack_pcm_state clk_state;
+static struct imx_priv_state hw_state;
 unsigned int mclk_freq;
 
 static int imx_3stack_startup(struct snd_pcm_substream *substream)
 {
-       clk_state.lr_clk_active++;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       if (!cpu_dai->active)
+               hw_state.hw = 0;
 
        return 0;
 }
 
 static void imx_3stack_shutdown(struct snd_pcm_substream *substream)
 {
-       clk_state.lr_clk_active--;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       if (!cpu_dai->active)
+               hw_state.hw = 0;
 }
 
 static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream,
@@ -62,8 +68,10 @@ static int imx_3stack_surround_hw_params(struct snd_pcm_substream *substream,
        unsigned int rate = params_rate(params);
        u32 dai_format;
        unsigned int lrclk_ratio = 0;
-       if (clk_state.lr_clk_active > 1)
+
+       if (hw_state.hw)
                return 0;
+       hw_state.hw = 1;
        if (cpu_is_mx53()) {
                switch (rate) {
                case 32000:
index ebd45ffa6ecfdd94456e0d56433b70ef8262ba95..a3c5c44983e705775a21a1e8862a677318d07910 100644 (file)
@@ -277,18 +277,23 @@ static int imx_esai_startup(struct snd_pcm_substream *substream,
 {
        struct imx_esai *esai = snd_soc_dai_get_drvdata(cpu_dai);
 
-       clk_enable(esai->clk);
+       if (!(local_esai->imx_esai_txrx_state & IMX_DAI_ESAI_TXRX)) {
+               clk_enable(esai->clk);
 
-       writel(ESAI_ECR_ERST, esai->base + ESAI_ECR);
-       writel(ESAI_ECR_ESAIEN, esai->base + ESAI_ECR);
+               writel(ESAI_ECR_ERST, esai->base + ESAI_ECR);
+               writel(ESAI_ECR_ESAIEN, esai->base + ESAI_ECR);
 
-       writel(ESAI_GPIO_ESAI, esai->base + ESAI_PRRC);
-       writel(ESAI_GPIO_ESAI, esai->base + ESAI_PCRC);
+               writel(ESAI_GPIO_ESAI, esai->base + ESAI_PRRC);
+               writel(ESAI_GPIO_ESAI, esai->base + ESAI_PCRC);
+       }
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               local_esai->imx_esai_txrx_state |= IMX_DAI_ESAI_TX;
                writel(ESAI_TCR_TPR, esai->base + ESAI_TCR);
-       else
+       } else {
+               local_esai->imx_esai_txrx_state |= IMX_DAI_ESAI_RX;
                writel(ESAI_RCR_RPR, esai->base + ESAI_RCR);
+       }
 
        ESAI_DUMP();
        return 0;
@@ -422,9 +427,14 @@ static void imx_esai_shutdown(struct snd_pcm_substream *substream,
 {
        struct imx_esai *esai = snd_soc_dai_get_drvdata(cpu_dai);
 
-       /* close easi clock */
-       clk_disable(esai->clk);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               local_esai->imx_esai_txrx_state &= ~IMX_DAI_ESAI_TX;
+       else
+               local_esai->imx_esai_txrx_state &= ~IMX_DAI_ESAI_RX;
 
+       if (!(local_esai->imx_esai_txrx_state & IMX_DAI_ESAI_TXRX))
+               /* close easi clock */
+               clk_disable(esai->clk);
 }
 
 static int imx_esai_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -532,6 +542,7 @@ static struct snd_soc_dai_ops imx_esai_dai_ops = {
 static int imx_esai_dai_probe(struct snd_soc_dai *dai)
 {
        struct imx_esai *esai = dev_get_drvdata(dai->dev);
+       local_esai->imx_esai_txrx_state = 0;
        snd_soc_dai_set_drvdata(dai, esai);
        return 0;
 }
index e8f2a71a6e71a6a47c3490db5230d5f9bff1b35b..97cf1c44c00451f24633efa761338646054e5ad5 100644 (file)
 #include <linux/dmaengine.h>
 #include <mach/dma.h>
 
+#define IMX_DAI_ESAI_TX 0x04
+#define IMX_DAI_ESAI_RX 0x08
+#define IMX_DAI_ESAI_TXRX (IMX_DAI_ESAI_TX | IMX_DAI_ESAI_RX)
+
 struct imx_esai {
        struct platform_device *ac97_dev;
        struct snd_soc_dai *imx_ac97;
@@ -322,6 +326,7 @@ struct imx_esai {
        struct imx_pcm_dma_params dma_params_tx;
 
        int enabled;
+       int imx_esai_txrx_state;
 
        struct platform_device *soc_platform_pdev;
        struct platform_device *soc_platform_pdev_fiq;