ASoC: tegra: Add internal PLL support for RT5640

RT5640 codec has internal PLL which can be used to
derive SYSCLK and internal PLL can take I2S BCLK as a
reference clock

Bug 3520437

Signed-off-by: Sheetal <sheetal@nvidia.com>
Change-Id: I3b88d3bf75146532bda669d961c6ff6bb52603f5
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.10/+/2662478
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Sameer Pujar <spujar@nvidia.com>
Reviewed-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Sharad Gupta <sharadg@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
Sheetal
2022-02-01 17:19:34 +05:30
committed by Sameer Pujar
parent 0142517e63
commit 9841017f33

View File

@@ -2,7 +2,7 @@
// //
// tegra_codecs.c - External audio codec setup // tegra_codecs.c - External audio codec setup
// //
// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. // Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
#include <dt-bindings/sound/tas2552.h> #include <dt-bindings/sound/tas2552.h>
#include <linux/input.h> #include <linux/input.h>
@@ -123,12 +123,57 @@ static struct snd_soc_pcm_runtime *get_pcm_runtime(struct snd_soc_card *card,
return NULL; return NULL;
} }
static int set_pll_sysclk(struct device *dev, struct snd_soc_pcm_runtime *rtd,
int pll_src, int clk_id, unsigned int srate,
unsigned int channels)
{
struct snd_soc_pcm_stream *dai_params;
unsigned int bclk_rate;
int err;
dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params;
switch (dai_params->formats) {
case SNDRV_PCM_FMTBIT_S8:
bclk_rate = srate * channels * 8;
break;
case SNDRV_PCM_FMTBIT_S16_LE:
bclk_rate = srate * channels * 16;
break;
case SNDRV_PCM_FMTBIT_S24_LE:
bclk_rate = srate * channels * 24;
break;
case SNDRV_PCM_FMTBIT_S32_LE:
bclk_rate = srate * channels * 32;
break;
default:
dev_err(dev, "invalid format %llu\n",
dai_params->formats);
return -EINVAL;
}
err = snd_soc_dai_set_pll(rtd->dais[rtd->num_cpus], 0,
pll_src, bclk_rate, srate * 256);
if (err < 0) {
dev_err(dev, "failed to set codec pll\n");
return err;
}
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], clk_id,
srate * 256, SND_SOC_CLOCK_IN);
if (err < 0) {
dev_err(dev, "dais[%d] clock not set\n", rtd->num_cpus);
return err;
}
return 0;
}
int tegra_codecs_runtime_setup(struct snd_soc_card *card, int tegra_codecs_runtime_setup(struct snd_soc_card *card,
unsigned int srate, unsigned int srate,
unsigned int channels, unsigned int channels,
unsigned int aud_mclk) unsigned int aud_mclk)
{ {
struct snd_soc_pcm_stream *dai_params;
struct snd_soc_pcm_runtime *rtd; struct snd_soc_pcm_runtime *rtd;
int err; int err;
@@ -158,41 +203,20 @@ int tegra_codecs_runtime_setup(struct snd_soc_card *card,
rtd = get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1"); rtd = get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1");
if (rtd) { if (rtd) {
unsigned int bclk_rate; err = set_pll_sysclk(card->dev, rtd, RT5659_PLL1_S_BCLK1,
RT5659_SCLK_S_PLL1, srate, channels);
dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params;
switch (dai_params->formats) {
case SNDRV_PCM_FMTBIT_S8:
bclk_rate = srate * channels * 8;
break;
case SNDRV_PCM_FMTBIT_S16_LE:
bclk_rate = srate * channels * 16;
break;
case SNDRV_PCM_FMTBIT_S24_LE:
bclk_rate = srate * channels * 24;
break;
case SNDRV_PCM_FMTBIT_S32_LE:
bclk_rate = srate * channels * 32;
break;
default:
dev_err(card->dev, "invalid format %llu\n",
dai_params->formats);
return -EINVAL;
}
err = snd_soc_dai_set_pll(rtd->dais[rtd->num_cpus], 0,
RT5659_PLL1_S_BCLK1,
bclk_rate, srate * 256);
if (err < 0) { if (err < 0) {
dev_err(card->dev, "failed to set codec pll\n"); dev_err(card->dev, "failed to set pll clk\n");
return err; return err;
} }
}
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], RT5659_SCLK_S_PLL1, rtd = get_pcm_runtime(card, "rt5640-codec-sysclk-bclk1");
srate * 256, SND_SOC_CLOCK_IN); if (rtd) {
err = set_pll_sysclk(card->dev, rtd, RT5640_PLL1_S_BCLK1,
RT5640_SCLK_S_PLL1, srate, channels);
if (err < 0) { if (err < 0) {
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus); dev_err(card->dev, "failed to set pll clk\n");
return err; return err;
} }
} }
@@ -238,7 +262,8 @@ int tegra_codecs_init(struct snd_soc_card *card)
for (i = 0; i < card->num_links; i++) { for (i = 0; i < card->num_links; i++) {
if (strstr(dai_links[i].name, "rt565x-playback") || if (strstr(dai_links[i].name, "rt565x-playback") ||
strstr(dai_links[i].name, "rt5640-playback") || strstr(dai_links[i].name, "rt5640-playback") ||
strstr(dai_links[i].name, "rt565x-codec-sysclk-bclk1")) strstr(dai_links[i].name, "rt565x-codec-sysclk-bclk1") ||
strstr(dai_links[i].name, "rt5640-codec-sysclk-bclk1"))
dai_links[i].init = tegra_machine_rt56xx_init; dai_links[i].init = tegra_machine_rt56xx_init;
else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2")) else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2"))
dai_links[i].init = tegra_machine_fepi_init; dai_links[i].init = tegra_machine_fepi_init;