ASoC: fsl_micfil: Add sample rate constraint

On some platforms, for example i.MX93, there is only one
audio PLL source, so some sample rate can't be supported.
If the PLL source is used for 8kHz series rates, then 11kHz
series rates can't be supported.

So add constraints according to the frequency of available
clock sources, then alsa-lib will help to convert the
unsupported rate for the driver.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Link: https://patch.msgid.link/1728884313-6778-1-git-send-email-shengjiu.wang@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Shengjiu Wang 2024-10-14 13:38:33 +08:00 committed by Mark Brown
parent 038fa6ddf5
commit b9a8ecf810
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -28,6 +28,13 @@
#define MICFIL_OSR_DEFAULT 16 #define MICFIL_OSR_DEFAULT 16
#define MICFIL_NUM_RATES 7
#define MICFIL_CLK_SRC_NUM 3
/* clock source ids */
#define MICFIL_AUDIO_PLL1 0
#define MICFIL_AUDIO_PLL2 1
#define MICFIL_CLK_EXT3 2
enum quality { enum quality {
QUALITY_HIGH, QUALITY_HIGH,
QUALITY_MEDIUM, QUALITY_MEDIUM,
@ -45,9 +52,12 @@ struct fsl_micfil {
struct clk *mclk; struct clk *mclk;
struct clk *pll8k_clk; struct clk *pll8k_clk;
struct clk *pll11k_clk; struct clk *pll11k_clk;
struct clk *clk_src[MICFIL_CLK_SRC_NUM];
struct snd_dmaengine_dai_dma_data dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_rx;
struct sdma_peripheral_config sdmacfg; struct sdma_peripheral_config sdmacfg;
struct snd_soc_card *card; struct snd_soc_card *card;
struct snd_pcm_hw_constraint_list constraint_rates;
unsigned int constraint_rates_list[MICFIL_NUM_RATES];
unsigned int dataline; unsigned int dataline;
char name[32]; char name[32];
int irq[MICFIL_IRQ_LINES]; int irq[MICFIL_IRQ_LINES];
@ -475,12 +485,34 @@ static int fsl_micfil_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(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) { if (!micfil) {
dev_err(dai->dev, "micfil dai priv_data not set\n"); dev_err(dai->dev, "micfil dai priv_data not set\n");
return -EINVAL; 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,
&micfil->constraint_rates);
return 0; return 0;
} }
@ -1175,6 +1207,12 @@ static int fsl_micfil_probe(struct platform_device *pdev)
fsl_asoc_get_pll_clocks(&pdev->dev, &micfil->pll8k_clk, fsl_asoc_get_pll_clocks(&pdev->dev, &micfil->pll8k_clk,
&micfil->pll11k_clk); &micfil->pll11k_clk);
micfil->clk_src[MICFIL_AUDIO_PLL1] = micfil->pll8k_clk;
micfil->clk_src[MICFIL_AUDIO_PLL2] = micfil->pll11k_clk;
micfil->clk_src[MICFIL_CLK_EXT3] = devm_clk_get(&pdev->dev, "clkext3");
if (IS_ERR(micfil->clk_src[MICFIL_CLK_EXT3]))
micfil->clk_src[MICFIL_CLK_EXT3] = NULL;
/* init regmap */ /* init regmap */
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(regs)) if (IS_ERR(regs))