summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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,
};