1
0
Fork 0

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>
(cherry picked from commit 897e9e8b4e7a59d81048d05f9377b8c68fc7cd64)
pull/10/head
Shengjiu Wang 2018-11-22 16:18:04 +08:00
parent 323d176850
commit 78014408cd
1 changed files with 32 additions and 7 deletions

View File

@ -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,
};