ASoC: fsl_sai: Add support for PLL switch at runtime
i.MX8MQ/MN/MM/MP platforms typically have 2 AUDIO PLLs being configured to handle 8kHz and 11kHz series audio rates. The patch implements the functionality to select at runtime the appropriate AUDIO PLL as function of sysclk rate. Signed-off-by: Viorel Suman <viorel.suman@nxp.com> Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Link: https://lore.kernel.org/r/1656667961-1799-5-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
93f54100fb
commit
7cb7f07d24
|
@ -19,6 +19,7 @@ config SND_SOC_FSL_SAI
|
|||
select REGMAP_MMIO
|
||||
select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
|
||||
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||
select SND_SOC_FSL_UTILS
|
||||
help
|
||||
Say Y if you want to add Synchronous Audio Interface (SAI)
|
||||
support for the Freescale CPUs.
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||
|
||||
#include "fsl_sai.h"
|
||||
#include "fsl_utils.h"
|
||||
#include "imx-pcm.h"
|
||||
|
||||
#define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\
|
||||
|
@ -220,14 +221,48 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fsl_sai_set_mclk_rate(struct snd_soc_dai *dai, int clk_id, unsigned int freq)
|
||||
{
|
||||
struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
|
||||
int ret;
|
||||
|
||||
fsl_asoc_reparent_pll_clocks(dai->dev, sai->mclk_clk[clk_id],
|
||||
sai->pll8k_clk, sai->pll11k_clk, freq);
|
||||
|
||||
ret = clk_set_rate(sai->mclk_clk[clk_id], freq);
|
||||
if (ret < 0)
|
||||
dev_err(dai->dev, "failed to set clock rate (%u): %d\n", freq, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
int ret;
|
||||
|
||||
if (dir == SND_SOC_CLOCK_IN)
|
||||
return 0;
|
||||
|
||||
if (freq > 0 && clk_id != FSL_SAI_CLK_BUS) {
|
||||
if (clk_id < 0 || clk_id >= FSL_SAI_MCLK_MAX) {
|
||||
dev_err(cpu_dai->dev, "Unknown clock id: %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ERR_OR_NULL(sai->mclk_clk[clk_id])) {
|
||||
dev_err(cpu_dai->dev, "Unassigned clock: %d\n", clk_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sai->mclk_streams == 0) {
|
||||
ret = fsl_sai_set_mclk_rate(cpu_dai, clk_id, freq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, true);
|
||||
if (ret) {
|
||||
dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
|
||||
|
@ -1281,6 +1316,9 @@ static int fsl_sai_probe(struct platform_device *pdev)
|
|||
else
|
||||
sai->mclk_clk[0] = sai->bus_clk;
|
||||
|
||||
fsl_asoc_get_pll_clocks(&pdev->dev, &sai->pll8k_clk,
|
||||
&sai->pll11k_clk);
|
||||
|
||||
/* read dataline mask for rx and tx*/
|
||||
ret = fsl_sai_read_dlcfg(sai);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -273,6 +273,8 @@ struct fsl_sai {
|
|||
struct regmap *regmap;
|
||||
struct clk *bus_clk;
|
||||
struct clk *mclk_clk[FSL_SAI_MCLK_MAX];
|
||||
struct clk *pll8k_clk;
|
||||
struct clk *pll11k_clk;
|
||||
struct resource *res;
|
||||
|
||||
bool is_consumer_mode;
|
||||
|
|
Loading…
Reference in New Issue