diff mbox series

[3/6] ASoC: fsl_micfil: Add support for PLL switch at runtime

Message ID 1656567554-32122-4-git-send-email-shengjiu.wang@nxp.com
State New
Headers show
Series Add support of two Audio PLL source | expand

Commit Message

Shengjiu Wang June 30, 2022, 5:39 a.m. UTC
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 audio file rate.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
 sound/soc/fsl/Kconfig      |  1 +
 sound/soc/fsl/fsl_micfil.c | 41 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

Comments

Shengjiu Wang June 30, 2022, 12:15 p.m. UTC | #1
On Thu, Jun 30, 2022 at 6:37 PM Mark Brown <broonie@kernel.org> wrote:

> On Thu, Jun 30, 2022 at 01:39:11PM +0800, Shengjiu Wang wrote:
>
> > +static int fsl_micfil_reparent_rootclk(struct fsl_micfil *micfil,
> unsigned int sample_rate)
> > +{
> > +     struct device *dev = &micfil->pdev->dev;
> > +     u64 ratio = sample_rate;
> > +     struct clk *clk;
> > +     int ret;
> > +
> > +     /* Reparent clock if required condition is true */
> > +     if (!micfil->pll8k_clk || !micfil->pll11k_clk)
> > +             return 0;
> > +
> > +     ratio = do_div(ratio, 8000) ? CLK_11K_FREQ : CLK_8K_FREQ;
> > +
> > +     /* Get root clock */
> > +     clk = micfil->mclk;
> > +     if (IS_ERR_OR_NULL(clk)) {
> > +             dev_err(dev, "no mclk clock in devicetree\n");
> > +             return PTR_ERR(clk);
> > +     }
> > +
> > +     /* Disable clock first, for it was enabled by pm_runtime */
> > +     clk_disable_unprepare(clk);
> > +     fsl_asoc_reparent_pll_clocks(dev, clk, micfil->pll8k_clk,
> > +                                  micfil->pll11k_clk, ratio);
> > +     ret = clk_prepare_enable(clk);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
>
> Seems like more of this logic could be factored out into the reparent
> function if the target sample rate is passed in?
>

Yes, let me update.

Best regards
Wang Shengjiu
diff mbox series

Patch

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 910b8747b6bd..533937166b4a 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -81,6 +81,7 @@  config SND_SOC_FSL_MICFIL
 	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 Pulse Density Modulation microphone
 	  interface (MICFIL) support for NXP.
diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index 18ab80b68752..9b4baeb0f41d 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -24,6 +24,7 @@ 
 #include <sound/core.h>
 
 #include "fsl_micfil.h"
+#include "fsl_utils.h"
 
 #define MICFIL_OSR_DEFAULT	16
 
@@ -42,6 +43,8 @@  struct fsl_micfil {
 	const struct fsl_micfil_soc_data *soc;
 	struct clk *busclk;
 	struct clk *mclk;
+	struct clk *pll8k_clk;
+	struct clk *pll11k_clk;
 	struct snd_dmaengine_dai_dma_data dma_params_rx;
 	struct sdma_peripheral_config sdmacfg;
 	unsigned int dataline;
@@ -283,6 +286,37 @@  static int fsl_micfil_trigger(struct snd_pcm_substream *substream, int cmd,
 	return 0;
 }
 
+static int fsl_micfil_reparent_rootclk(struct fsl_micfil *micfil, unsigned int sample_rate)
+{
+	struct device *dev = &micfil->pdev->dev;
+	u64 ratio = sample_rate;
+	struct clk *clk;
+	int ret;
+
+	/* Reparent clock if required condition is true */
+	if (!micfil->pll8k_clk || !micfil->pll11k_clk)
+		return 0;
+
+	ratio = do_div(ratio, 8000) ? CLK_11K_FREQ : CLK_8K_FREQ;
+
+	/* Get root clock */
+	clk = micfil->mclk;
+	if (IS_ERR_OR_NULL(clk)) {
+		dev_err(dev, "no mclk clock in devicetree\n");
+		return PTR_ERR(clk);
+	}
+
+	/* Disable clock first, for it was enabled by pm_runtime */
+	clk_disable_unprepare(clk);
+	fsl_asoc_reparent_pll_clocks(dev, clk, micfil->pll8k_clk,
+				     micfil->pll11k_clk, ratio);
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params,
 				struct snd_soc_dai *dai)
@@ -306,6 +340,10 @@  static int fsl_micfil_hw_params(struct snd_pcm_substream *substream,
 	if (ret)
 		return ret;
 
+	ret = fsl_micfil_reparent_rootclk(micfil, rate);
+	if (ret)
+		return ret;
+
 	ret = clk_set_rate(micfil->mclk, rate * clk_div * osr * 8);
 	if (ret)
 		return ret;
@@ -610,6 +648,9 @@  static int fsl_micfil_probe(struct platform_device *pdev)
 		return PTR_ERR(micfil->busclk);
 	}
 
+	fsl_asoc_get_pll_clocks(&pdev->dev, &micfil->pll8k_clk,
+				&micfil->pll11k_clk);
+
 	/* init regmap */
 	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(regs))