]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ASoC: fsl_sai: Add support for PLL switch at runtime
authorShengjiu Wang <shengjiu.wang@nxp.com>
Fri, 1 Jul 2022 09:32:39 +0000 (17:32 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 5 Jul 2022 12:00:40 +0000 (13:00 +0100)
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>
sound/soc/fsl/Kconfig
sound/soc/fsl/fsl_sai.c
sound/soc/fsl/fsl_sai.h

index 533937166b4af03588c64aa58d2a263d3f70a35a..614eceda6b9e3181b184beb16eb3c0c5612f787f 100644 (file)
@@ -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.
index a0ddaf7e9f6082d514dcdf9784473831cf30eaec..974ba0780b1987bfafef69ce86479fc8ac6c4821 100644 (file)
@@ -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) {
index 9bb8ced520c80977ca7ef539c3f4bbd70e21f557..17956b5731dc35d73066c292a7056a647bd16236 100644 (file)
@@ -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;