From 820bcaeb1ff5705ba907563e554f17d0deecc3fa Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Tue, 26 Nov 2024 20:54:37 +0900 Subject: [PATCH 1/4] ASoC: fsl_utils: Add function to constrain rates Platforms like i.MX93/91 only have one audio PLL. Some sample rates are not supported. Add common function to constrain rates according to different clock sources. Signed-off-by: Chancel Liu Link: https://patch.msgid.link/20241126115440.3929061-2-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_utils.c | 45 +++++++++++++++++++++++++++++++++++++++ sound/soc/fsl/fsl_utils.h | 5 +++++ 2 files changed, 50 insertions(+) diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index a5ab27c2f711..d69a6b9795bf 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c @@ -152,6 +152,51 @@ void fsl_asoc_reparent_pll_clocks(struct device *dev, struct clk *clk, } EXPORT_SYMBOL(fsl_asoc_reparent_pll_clocks); +/** + * fsl_asoc_constrain_rates - constrain rates according to clocks + * + * @target_constr: target constraint + * @original_constr: original constraint + * @pll8k_clk: PLL clock pointer for 8kHz + * @pll11k_clk: PLL clock pointer for 11kHz + * @ext_clk: External clock pointer + * @target_rates: target rates array + * + * This function constrain rates according to clocks + */ +void fsl_asoc_constrain_rates(struct snd_pcm_hw_constraint_list *target_constr, + const struct snd_pcm_hw_constraint_list *original_constr, + struct clk *pll8k_clk, struct clk *pll11k_clk, + struct clk *ext_clk, int *target_rates) +{ + int i, j, k = 0; + u64 clk_rate[3]; + + *target_constr = *original_constr; + if (pll8k_clk || pll11k_clk || ext_clk) { + target_constr->list = target_rates; + target_constr->count = 0; + for (i = 0; i < original_constr->count; i++) { + clk_rate[0] = clk_get_rate(pll8k_clk); + clk_rate[1] = clk_get_rate(pll11k_clk); + clk_rate[2] = clk_get_rate(ext_clk); + for (j = 0; j < 3; j++) { + if (clk_rate[j] != 0 && + do_div(clk_rate[j], original_constr->list[i]) == 0) { + target_rates[k++] = original_constr->list[i]; + target_constr->count++; + break; + } + } + } + + /* protection for if there is no proper rate found*/ + if (!target_constr->count) + *target_constr = *original_constr; + } +} +EXPORT_SYMBOL(fsl_asoc_constrain_rates); + MODULE_AUTHOR("Timur Tabi "); MODULE_DESCRIPTION("Freescale ASoC utility code"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_utils.h b/sound/soc/fsl/fsl_utils.h index 4d5f3d93bc81..21b25a11ecda 100644 --- a/sound/soc/fsl/fsl_utils.h +++ b/sound/soc/fsl/fsl_utils.h @@ -26,4 +26,9 @@ void fsl_asoc_get_pll_clocks(struct device *dev, struct clk **pll8k_clk, void fsl_asoc_reparent_pll_clocks(struct device *dev, struct clk *clk, struct clk *pll8k_clk, struct clk *pll11k_clk, u64 ratio); + +void fsl_asoc_constrain_rates(struct snd_pcm_hw_constraint_list *target_constr, + const struct snd_pcm_hw_constraint_list *original_constr, + struct clk *pll8k_clk, struct clk *pll11k_clk, + struct clk *ext_clk, int *target_rates); #endif /* _FSL_UTILS_H */ From daf7a173fc7c4b652f3fe69d3b5aa520976a7d63 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Tue, 26 Nov 2024 20:54:38 +0900 Subject: [PATCH 2/4] ASoC: fsl_micfil: Switch to common sample rate constraint function fsl_asoc_constrain_rates() is a common function to constrain rates. Let's switch to this function. Signed-off-by: Chancel Liu Link: https://patch.msgid.link/20241126115440.3929061-3-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 8c15389c9a04..e908cfb594ab 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -35,6 +35,15 @@ #define MICFIL_AUDIO_PLL2 1 #define MICFIL_CLK_EXT3 2 +static const unsigned int fsl_micfil_rates[] = { + 8000, 11025, 16000, 22050, 32000, 44100, 48000, +}; + +static const struct snd_pcm_hw_constraint_list fsl_micfil_rate_constraints = { + .count = ARRAY_SIZE(fsl_micfil_rates), + .list = fsl_micfil_rates, +}; + enum quality { QUALITY_HIGH, QUALITY_MEDIUM, @@ -486,29 +495,12 @@ static int fsl_micfil_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai); - unsigned int rates[MICFIL_NUM_RATES] = {8000, 11025, 16000, 22050, 32000, 44100, 48000}; - int i, j, k = 0; - u64 clk_rate; if (!micfil) { dev_err(dai->dev, "micfil dai priv_data not set\n"); return -EINVAL; } - micfil->constraint_rates.list = micfil->constraint_rates_list; - micfil->constraint_rates.count = 0; - - for (j = 0; j < MICFIL_NUM_RATES; j++) { - for (i = 0; i < MICFIL_CLK_SRC_NUM; i++) { - clk_rate = clk_get_rate(micfil->clk_src[i]); - if (clk_rate != 0 && do_div(clk_rate, rates[j]) == 0) { - micfil->constraint_rates_list[k++] = rates[j]; - micfil->constraint_rates.count++; - break; - } - } - } - if (micfil->constraint_rates.count > 0) snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, @@ -1239,6 +1231,13 @@ static int fsl_micfil_probe(struct platform_device *pdev) if (IS_ERR(micfil->clk_src[MICFIL_CLK_EXT3])) micfil->clk_src[MICFIL_CLK_EXT3] = NULL; + fsl_asoc_constrain_rates(&micfil->constraint_rates, + &fsl_micfil_rate_constraints, + micfil->clk_src[MICFIL_AUDIO_PLL1], + micfil->clk_src[MICFIL_AUDIO_PLL2], + micfil->clk_src[MICFIL_CLK_EXT3], + micfil->constraint_rates_list); + /* init regmap */ regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(regs)) From b622b677d255b41cbfce20b66535723933a6b640 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Tue, 26 Nov 2024 20:54:39 +0900 Subject: [PATCH 3/4] ASoC: fsl_xcvr: Add sample rate constraint Platforms like i.MX93/91 only have one audio PLL. Some sample rates are not supported. If the PLL source is used for 8kHz series rates, then 11kHz series rates can't be supported. Use fsl_asoc_constrain_rates() to constrain rates according to PLL sources. This constraint is merely applicable to playback cases on SPDIF only platforms. Signed-off-by: Chancel Liu Link: https://patch.msgid.link/20241126115440.3929061-4-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_xcvr.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 8150f877e1ae..051add793022 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -19,6 +19,7 @@ #include "imx-pcm.h" #define FSL_XCVR_CAPDS_SIZE 256 +#define SPDIF_NUM_RATES 7 enum fsl_xcvr_pll_verison { PLL_MX8MP, @@ -57,6 +58,8 @@ struct fsl_xcvr { u8 cap_ds[FSL_XCVR_CAPDS_SIZE]; struct work_struct work_rst; spinlock_t lock; /* Protect hw_reset and trigger */ + struct snd_pcm_hw_constraint_list spdif_constr_rates; + u32 spdif_constr_rates_list[SPDIF_NUM_RATES]; }; static const struct fsl_xcvr_pll_conf { @@ -640,8 +643,12 @@ static int fsl_xcvr_startup(struct snd_pcm_substream *substream, switch (xcvr->mode) { case FSL_XCVR_MODE_SPDIF: case FSL_XCVR_MODE_ARC: - ret = fsl_xcvr_constr(substream, &fsl_xcvr_spdif_channels_constr, - &fsl_xcvr_spdif_rates_constr); + if (xcvr->soc_data->spdif_only && tx) + ret = fsl_xcvr_constr(substream, &fsl_xcvr_spdif_channels_constr, + &xcvr->spdif_constr_rates); + else + ret = fsl_xcvr_constr(substream, &fsl_xcvr_spdif_channels_constr, + &fsl_xcvr_spdif_rates_constr); break; case FSL_XCVR_MODE_EARC: ret = fsl_xcvr_constr(substream, &fsl_xcvr_earc_channels_constr, @@ -1546,6 +1553,15 @@ static int fsl_xcvr_probe(struct platform_device *pdev) fsl_asoc_get_pll_clocks(dev, &xcvr->pll8k_clk, &xcvr->pll11k_clk); + if (xcvr->soc_data->spdif_only) { + if (!(xcvr->pll8k_clk || xcvr->pll11k_clk)) + xcvr->pll8k_clk = xcvr->phy_clk; + fsl_asoc_constrain_rates(&xcvr->spdif_constr_rates, + &fsl_xcvr_spdif_rates_constr, + xcvr->pll8k_clk, xcvr->pll11k_clk, NULL, + xcvr->spdif_constr_rates_list); + } + xcvr->ram_addr = devm_platform_ioremap_resource_byname(pdev, "ram"); if (IS_ERR(xcvr->ram_addr)) return PTR_ERR(xcvr->ram_addr); From 4edc98598be43634f87af5d3876ebec6c274d2cb Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Tue, 26 Nov 2024 20:54:40 +0900 Subject: [PATCH 4/4] ASoC: fsl_sai: Add sample rate constraint Platforms like i.MX93/91 only have one audio PLL. Some sample rates are not supported. If the PLL source is used for 8kHz series rates, then 11kHz series rates can't be supported. Use fsl_asoc_constrain_rates() to constrain rates according to PLL sources. Signed-off-by: Chancel Liu Link: https://patch.msgid.link/20241126115440.3929061-5-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 7 ++++++- sound/soc/fsl/fsl_sai.h | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 634168d2bb6e..c4eb87c5d39e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -885,7 +885,7 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, sai->dma_params_rx.maxburst); ret = snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &fsl_sai_rate_constraints); + SNDRV_PCM_HW_PARAM_RATE, &sai->constraint_rates); return ret; } @@ -1442,6 +1442,11 @@ static int fsl_sai_probe(struct platform_device *pdev) fsl_asoc_get_pll_clocks(&pdev->dev, &sai->pll8k_clk, &sai->pll11k_clk); + fsl_asoc_constrain_rates(&sai->constraint_rates, + &fsl_sai_rate_constraints, + sai->pll8k_clk, sai->pll11k_clk, NULL, + sai->constraint_rates_list); + /* Use Multi FIFO mode depending on the support from SDMA script */ ret = of_property_read_u32_array(np, "dmas", dmas, 4); if (!sai->soc_data->use_edma && !ret && dmas[2] == IMX_DMATYPE_MULTI_SAI) diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 9c4d19fe22c6..0e25e2fc7ce0 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -9,6 +9,7 @@ #include #include +#define FAL_SAI_NUM_RATES 20 #define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE |\ @@ -309,6 +310,8 @@ struct fsl_sai { struct pinctrl *pinctrl; struct pinctrl_state *pins_state; struct sdma_peripheral_config audio_config[2]; + struct snd_pcm_hw_constraint_list constraint_rates; + unsigned int constraint_rates_list[FAL_SAI_NUM_RATES]; }; #define TX 1