diff --git a/sound/soc/fsl/imx-cs42888.c b/sound/soc/fsl/imx-cs42888.c index 3ae2cddb08b4..8793fa034d6d 100644 --- a/sound/soc/fsl/imx-cs42888.c +++ b/sound/soc/fsl/imx-cs42888.c @@ -42,6 +42,8 @@ struct imx_priv { u32 asrc_format; bool is_codec_master; bool is_codec_rpmsg; + bool is_stream_in_use[2]; + bool is_stream_tdm[2]; }; static struct imx_priv card_priv; @@ -54,21 +56,32 @@ static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->codec_dai; struct imx_priv *priv = &card_priv; struct device *dev = &priv->pdev->dev; + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; u32 channels = params_channels(params); u32 max_tdm_rate; - - bool enable_tdm = channels > 1 && channels % 2; - u32 dai_format = SND_SOC_DAIFMT_NB_NF | - (enable_tdm ? SND_SOC_DAIFMT_DSP_A : SND_SOC_DAIFMT_LEFT_J); - + u32 dai_format; int ret = 0; + priv->is_stream_tdm[tx] = channels > 1 && channels % 2; + dai_format = SND_SOC_DAIFMT_NB_NF | + (priv->is_stream_tdm[tx] ? SND_SOC_DAIFMT_DSP_A : + SND_SOC_DAIFMT_LEFT_J); + + priv->is_stream_in_use[tx] = true; + + if (priv->is_stream_in_use[!tx] && + (priv->is_stream_tdm[tx] != priv->is_stream_tdm[!tx])) { + + dev_err(dev, "Don't support different fmt for tx & rx\n"); + return -EINVAL; + } + priv->mclk_freq = clk_get_rate(priv->codec_clk); priv->esai_freq = clk_get_rate(priv->esai_clk); if (priv->is_codec_master) { /* TDM is not supported by codec in master mode */ - if (enable_tdm) { + if (priv->is_stream_tdm[tx]) { dev_err(dev, "%d channels are not supported in codec master mode\n", channels); return -EINVAL; @@ -120,7 +133,7 @@ static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream, return ret; } /* set i.MX active slot mask */ - if (enable_tdm) { + if (priv->is_stream_tdm[tx]) { /* 2 required by ESAI BCLK divisors, 8 slots, 32 width */ if (priv->is_codec_master) max_tdm_rate = priv->mclk_freq / (8*32); @@ -152,6 +165,16 @@ static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream, return 0; } +static int imx_cs42888_surround_hw_free(struct snd_pcm_substream *substream) +{ + struct imx_priv *priv = &card_priv; + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + priv->is_stream_in_use[tx] = false; + + return 0; +} + static int imx_cs42888_surround_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -183,6 +206,7 @@ static int imx_cs42888_surround_startup(struct snd_pcm_substream *substream) static struct snd_soc_ops imx_cs42888_surround_ops = { .startup = imx_cs42888_surround_startup, .hw_params = imx_cs42888_surround_hw_params, + .hw_free = imx_cs42888_surround_hw_free, }; /** @@ -192,6 +216,7 @@ static struct snd_soc_ops imx_cs42888_surround_ops = { */ static struct snd_soc_ops imx_cs42888_surround_ops_be = { .hw_params = imx_cs42888_surround_hw_params, + .hw_free = imx_cs42888_surround_hw_free, };