Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Shengjiu Wang and committed by
Mark Brown
7cb7f07d 93f54100

+41
+1
sound/soc/fsl/Kconfig
··· 19 19 select REGMAP_MMIO 20 20 select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n 21 21 select SND_SOC_GENERIC_DMAENGINE_PCM 22 + select SND_SOC_FSL_UTILS 22 23 help 23 24 Say Y if you want to add Synchronous Audio Interface (SAI) 24 25 support for the Freescale CPUs.
+38
sound/soc/fsl/fsl_sai.c
··· 23 23 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 24 24 25 25 #include "fsl_sai.h" 26 + #include "fsl_utils.h" 26 27 #include "imx-pcm.h" 27 28 28 29 #define FSL_SAI_FLAGS (FSL_SAI_CSR_SEIE |\ ··· 221 220 return 0; 222 221 } 223 222 223 + static int fsl_sai_set_mclk_rate(struct snd_soc_dai *dai, int clk_id, unsigned int freq) 224 + { 225 + struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai); 226 + int ret; 227 + 228 + fsl_asoc_reparent_pll_clocks(dai->dev, sai->mclk_clk[clk_id], 229 + sai->pll8k_clk, sai->pll11k_clk, freq); 230 + 231 + ret = clk_set_rate(sai->mclk_clk[clk_id], freq); 232 + if (ret < 0) 233 + dev_err(dai->dev, "failed to set clock rate (%u): %d\n", freq, ret); 234 + 235 + return ret; 236 + } 237 + 224 238 static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 225 239 int clk_id, unsigned int freq, int dir) 226 240 { 241 + struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); 227 242 int ret; 228 243 229 244 if (dir == SND_SOC_CLOCK_IN) 230 245 return 0; 246 + 247 + if (freq > 0 && clk_id != FSL_SAI_CLK_BUS) { 248 + if (clk_id < 0 || clk_id >= FSL_SAI_MCLK_MAX) { 249 + dev_err(cpu_dai->dev, "Unknown clock id: %d\n", clk_id); 250 + return -EINVAL; 251 + } 252 + 253 + if (IS_ERR_OR_NULL(sai->mclk_clk[clk_id])) { 254 + dev_err(cpu_dai->dev, "Unassigned clock: %d\n", clk_id); 255 + return -EINVAL; 256 + } 257 + 258 + if (sai->mclk_streams == 0) { 259 + ret = fsl_sai_set_mclk_rate(cpu_dai, clk_id, freq); 260 + if (ret < 0) 261 + return ret; 262 + } 263 + } 231 264 232 265 ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, true); 233 266 if (ret) { ··· 1315 1280 sai->mclk_clk[0] = sai->mclk_clk[1]; 1316 1281 else 1317 1282 sai->mclk_clk[0] = sai->bus_clk; 1283 + 1284 + fsl_asoc_get_pll_clocks(&pdev->dev, &sai->pll8k_clk, 1285 + &sai->pll11k_clk); 1318 1286 1319 1287 /* read dataline mask for rx and tx*/ 1320 1288 ret = fsl_sai_read_dlcfg(sai);
+2
sound/soc/fsl/fsl_sai.h
··· 273 273 struct regmap *regmap; 274 274 struct clk *bus_clk; 275 275 struct clk *mclk_clk[FSL_SAI_MCLK_MAX]; 276 + struct clk *pll8k_clk; 277 + struct clk *pll11k_clk; 276 278 struct resource *res; 277 279 278 280 bool is_consumer_mode;