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 be9781ad8849..79ef4e269bc9 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -24,6 +24,7 @@ #include #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; @@ -264,6 +267,27 @@ 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; + + /* Get root clock */ + clk = micfil->mclk; + + /* 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) @@ -287,6 +311,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; @@ -591,6 +619,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))