summaryrefslogtreecommitdiff
path: root/sound/soc/fsl/imx-cs42888.c
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2018-11-22 16:18:04 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:50:45 +0800
commit4dcdcf9d6b562ae8a1f7c66ab337dd6c0a554a1d (patch)
treed38a7b82d946f0a86974aa43cf642dc311074ddb /sound/soc/fsl/imx-cs42888.c
parentfa2768aca5141e2bdd0552d46adc0bde0ac4af63 (diff)
MLK-20428-2: ASoC: imx-cs42xx8: The FMT should be same for tx and rx
If the FMT of tx and rx is different, there will be issue. for example tx is working at TDM mode, but rx want to work at I2S mode, this case is not supported in current ALSA driver, the best way to support this is to distinguish substream in set_fmt function. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Diffstat (limited to 'sound/soc/fsl/imx-cs42888.c')
-rw-r--r--sound/soc/fsl/imx-cs42888.c37
1 files changed, 31 insertions, 6 deletions
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;
+ u32 dai_format;
+ int ret = 0;
- 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);
+ 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);
- int ret = 0;
+ 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,
};