diff options
author | Lionel Xu <Lionel.Xu@freescale.com> | 2011-09-30 14:47:31 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-01-09 20:23:54 +0800 |
commit | 4b74139aabf51937618be40075c9b2a5dc170a78 (patch) | |
tree | 525b788f09b2ca4e50175e636f50904349825d13 /sound | |
parent | 2eed0e206a89760cc7d1de78c89a2ee5dfb21c41 (diff) |
ENGR00156745 MX6Q ESAI: Playback and record can't start up concurrently
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>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/cs42888.c | 1 | ||||
-rw-r--r-- | sound/soc/imx/imx-cs42888.c | 20 | ||||
-rw-r--r-- | sound/soc/imx/imx-esai.c | 29 | ||||
-rw-r--r-- | sound/soc/imx/imx-esai.h | 5 |
4 files changed, 39 insertions, 16 deletions
diff --git a/sound/soc/codecs/cs42888.c b/sound/soc/codecs/cs42888.c index c810333b3284..f2480cc1490f 100644 --- a/sound/soc/codecs/cs42888.c +++ b/sound/soc/codecs/cs42888.c @@ -784,7 +784,6 @@ struct snd_soc_dai_driver cs42888_dai = { .formats = CS42888_FORMATS, }, .ops = &cs42888_dai_ops, - .symmetric_rates = 1, }; /** diff --git a/sound/soc/imx/imx-cs42888.c b/sound/soc/imx/imx-cs42888.c index e9f6633f1b74..d34be0a0e8f9 100644 --- a/sound/soc/imx/imx-cs42888.c +++ b/sound/soc/imx/imx-cs42888.c @@ -34,23 +34,29 @@ #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: diff --git a/sound/soc/imx/imx-esai.c b/sound/soc/imx/imx-esai.c index ebd45ffa6ecf..a3c5c44983e7 100644 --- a/sound/soc/imx/imx-esai.c +++ b/sound/soc/imx/imx-esai.c @@ -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; } diff --git a/sound/soc/imx/imx-esai.h b/sound/soc/imx/imx-esai.h index e8f2a71a6e71..97cf1c44c004 100644 --- a/sound/soc/imx/imx-esai.h +++ b/sound/soc/imx/imx-esai.h @@ -304,6 +304,10 @@ #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; |