Add tdm support for amd platforms. Signed-off-by: Venkata Prasad Potturu <venkataprasad.potturu@xxxxxxx> --- sound/soc/amd/acp/acp-legacy-mach.c | 5 ++ sound/soc/amd/acp/acp-mach-common.c | 130 +++++++++++++++++++++++++--- sound/soc/amd/acp/acp-mach.h | 3 + sound/soc/amd/acp/acp-sof-mach.c | 6 ++ 4 files changed, 133 insertions(+), 11 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c index 1f4878ff7d37..d508792dba4f 100644 --- a/sound/soc/amd/acp/acp-legacy-mach.c +++ b/sound/soc/amd/acp/acp-legacy-mach.c @@ -27,6 +27,7 @@ static struct acp_card_drvdata rt5682_rt1019_data = { .hs_codec_id = RT5682, .amp_codec_id = RT1019, .dmic_codec_id = DMIC, + .tdm_mode = false, }; static struct acp_card_drvdata rt5682s_max_data = { @@ -36,6 +37,7 @@ static struct acp_card_drvdata rt5682s_max_data = { .hs_codec_id = RT5682S, .amp_codec_id = MAX98360A, .dmic_codec_id = DMIC, + .tdm_mode = false, }; static struct acp_card_drvdata rt5682s_rt1019_data = { @@ -45,6 +47,7 @@ static struct acp_card_drvdata rt5682s_rt1019_data = { .hs_codec_id = RT5682S, .amp_codec_id = RT1019, .dmic_codec_id = DMIC, + .tdm_mode = false, }; static struct acp_card_drvdata max_nau8825_data = { @@ -56,6 +59,7 @@ static struct acp_card_drvdata max_nau8825_data = { .dmic_codec_id = DMIC, .soc_mclk = true, .platform = REMBRANDT, + .tdm_mode = false, }; static struct acp_card_drvdata rt5682s_rt1019_rmb_data = { @@ -67,6 +71,7 @@ static struct acp_card_drvdata rt5682s_rt1019_rmb_data = { .dmic_codec_id = DMIC, .soc_mclk = true, .platform = REMBRANDT, + .tdm_mode = false, }; static const struct snd_kcontrol_new acp_controls[] = { diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index 748cbefa8252..73a27f02b52b 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -183,10 +183,15 @@ static int acp_card_rt5682x_hw_params(struct snd_pcm_substream *substream, int ret; unsigned int fmt; + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + if (drvdata->soc_mclk) - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; else - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret && ret != -ENOTSUPP) { @@ -200,6 +205,23 @@ static int acp_card_rt5682x_hw_params(struct snd_pcm_substream *substream, return ret; } + if (drvdata->tdm_mode) { + /** + * As codec supports slot 0 and slot 1 for playback and capture. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 8, 16); + if (ret < 0) { + dev_warn(rtd->dev, "set TDM slot err:%d\n", ret); + return ret; + } + } + return 0; } @@ -364,10 +386,15 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream, if (drvdata->amp_codec_id != RT1019) return -EINVAL; + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + if (drvdata->soc_mclk) - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; else - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret && ret != -ENOTSUPP) { @@ -375,12 +402,27 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream, return ret; } + if (drvdata->tdm_mode) { + /** + * As codec supports slot 2 and slot 3 for playback. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + } for_each_rtd_codec_dais(rtd, i, codec_dai) { if (strcmp(codec_dai->name, "rt1019-aif")) continue; - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, - ch * format * srate, 256 * srate); + if (drvdata->tdm_mode) + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, + TDM_CHANNELS * format * srate, 256 * srate); + else + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, + ch * format * srate, 256 * srate); + if (ret < 0) return ret; @@ -388,8 +430,34 @@ static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream, 256 * srate, SND_SOC_CLOCK_IN); if (ret < 0) return ret; - } + if (drvdata->tdm_mode) { + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A + | SND_SOC_DAIFMT_NB_NF); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + + /** + * As codec supports slot 2 for left channel playback. + */ + if (!strcmp(codec_dai->component->name, "i2c-10EC1019:00")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x4, 8, 16); + if (ret < 0) + break; + } + + /** + * As codec supports slot 3 for right channel playback. + */ + if (!strcmp(codec_dai->component->name, "i2c-10EC1019:01")) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x8, 8, 16); + if (ret < 0) + break; + } + } + } return 0; } @@ -448,19 +516,38 @@ static int acp_card_maxim_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_card *card = rtd->card; + struct acp_card_drvdata *drvdata = card->drvdata; unsigned int fmt; int ret; + + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + if (drvdata->soc_mclk) - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; else - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret && ret != -ENOTSUPP) { dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret); return ret; } + + if (drvdata->tdm_mode) { + /** + * As codec supports slot 2 and slot 3 for playback. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + } return 0; } @@ -539,10 +626,15 @@ static int acp_nau8825_hw_params(struct snd_pcm_substream *substream, return ret; } + if (drvdata->tdm_mode) + fmt = SND_SOC_DAIFMT_DSP_A; + else + fmt = SND_SOC_DAIFMT_I2S; + if (drvdata->soc_mclk) - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; else - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret && ret != -ENOTSUPP) { @@ -556,6 +648,22 @@ static int acp_nau8825_hw_params(struct snd_pcm_substream *substream, return ret; } + if (drvdata->tdm_mode) { + /** + * As codec supports slot 4 and slot 5 for playback and slot 6 for capture. + */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x30, 0xC0, 8, 16); + if (ret && ret != -ENOTSUPP) { + dev_err(rtd->dev, "set TDM slot err: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x40, 0x30, 8, 16); + if (ret < 0) { + dev_warn(rtd->dev, "set TDM slot err:%d\n", ret); + return ret; + } + } return ret; } diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h index 20583ef902df..9f87439b3cfd 100644 --- a/sound/soc/amd/acp/acp-mach.h +++ b/sound/soc/amd/acp/acp-mach.h @@ -18,6 +18,8 @@ #include <linux/module.h> #include <sound/soc.h> +#define TDM_CHANNELS 8 + enum be_id { HEADSET_BE_ID = 0, AMP_BE_ID, @@ -58,6 +60,7 @@ struct acp_card_drvdata { struct clk *wclk; struct clk *bclk; bool soc_mclk; + bool tdm_mode; }; int acp_sofdsp_dai_links_create(struct snd_soc_card *card); diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c index f19f064a7527..f3ba22a25962 100644 --- a/sound/soc/amd/acp/acp-sof-mach.c +++ b/sound/soc/amd/acp/acp-sof-mach.c @@ -27,6 +27,7 @@ static struct acp_card_drvdata sof_rt5682_rt1019_data = { .hs_codec_id = RT5682, .amp_codec_id = RT1019, .dmic_codec_id = DMIC, + .tdm_mode = false, }; static struct acp_card_drvdata sof_rt5682_max_data = { @@ -36,6 +37,7 @@ static struct acp_card_drvdata sof_rt5682_max_data = { .hs_codec_id = RT5682, .amp_codec_id = MAX98360A, .dmic_codec_id = DMIC, + .tdm_mode = false, }; static struct acp_card_drvdata sof_rt5682s_rt1019_data = { @@ -45,6 +47,7 @@ static struct acp_card_drvdata sof_rt5682s_rt1019_data = { .hs_codec_id = RT5682S, .amp_codec_id = RT1019, .dmic_codec_id = DMIC, + .tdm_mode = false, }; static struct acp_card_drvdata sof_rt5682s_max_data = { @@ -54,6 +57,7 @@ static struct acp_card_drvdata sof_rt5682s_max_data = { .hs_codec_id = RT5682S, .amp_codec_id = MAX98360A, .dmic_codec_id = DMIC, + .tdm_mode = false, }; static struct acp_card_drvdata sof_nau8825_data = { @@ -64,6 +68,7 @@ static struct acp_card_drvdata sof_nau8825_data = { .amp_codec_id = MAX98360A, .dmic_codec_id = DMIC, .soc_mclk = true, + .tdm_mode = false, }; static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = { @@ -74,6 +79,7 @@ static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = { .amp_codec_id = RT1019, .dmic_codec_id = DMIC, .soc_mclk = true, + .tdm_mode = false, }; static const struct snd_kcontrol_new acp_controls[] = { -- 2.25.1