1
0
Fork 0

MLK-24423: sound: soc: fsl: imx pdm: fixed mclk improve voice

Add fixed sai mclk for PDM software decimation improve
libimxswpdm conversion algorithm performance for
voice applications by using exact division ratios for
clock configurations mclk, bitclk.

Signed-off-by: Adrian Alonso <adrian.alonso@nxp.com>
Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Adrian Alonso 2020-06-27 16:56:47 -05:00
parent de79414d59
commit cdfd304a32
1 changed files with 67 additions and 1 deletions

View File

@ -25,6 +25,9 @@ struct imx_pdm_data {
struct snd_soc_dai_link dai;
struct snd_soc_card card;
unsigned int decimation;
unsigned long mclk_11k;
unsigned long mclk_8k;
bool fixed_mclk;
int osr_id;
};
@ -37,6 +40,21 @@ static const struct imx_pdm_mic_fs_mul {
{ .min = 16000, .max = 64000, .mul = 16 }, /* performance */
};
/* Ratio based on default Audio PLLs
* Audio PLL1 = 393216000 Hz
* Audio PLL2 = 361267200 Hz
*/
static const struct imx_pdm_mic_mclk_fixed {
unsigned long mclk_11k;
unsigned long mclk_8k;
unsigned int ratio;
} mclk_fixed[] = {
{ .mclk_11k = 11289600, .mclk_8k = 12288000, .ratio = 32 },
{ .mclk_11k = 15052800, .mclk_8k = 16384000, .ratio = 24 },
{ .mclk_11k = 22579200, .mclk_8k = 24576000, .ratio = 16 },
{ .mclk_11k = 45158400, .mclk_8k = 49152000, .ratio = 8 },
};
static const unsigned int imx_pdm_mic_rates[] = {
8000, 11025, 16000, 22050,
32000, 44100, 48000, 64000,
@ -143,6 +161,21 @@ static unsigned long imx_pdm_mic_mclk_freq(unsigned int decimation,
return 0;
}
static int imx_pdm_mic_get_mclk_fixed(struct imx_pdm_data *data,
unsigned int ratio)
{
int i;
for (i = 0; i < ARRAY_SIZE(mclk_fixed); i++) {
if (mclk_fixed[i].ratio == ratio) {
data->mclk_11k = mclk_fixed[i].mclk_11k;
data->mclk_8k = mclk_fixed[i].mclk_8k;
return 0;
}
}
return -EINVAL;
}
static int imx_pdm_mic_startup(struct snd_pcm_substream *substream)
{
@ -203,8 +236,15 @@ static int imx_pdm_mic_hw_params(struct snd_pcm_substream *substream,
dev_err(card->dev, "fail to set cpu sysclk: %d\n", ret);
return ret;
}
if (data->fixed_mclk) {
mclk_freq = (do_div(sample_rate, 8000) ?
data->mclk_11k : data->mclk_8k);
} else {
mclk_freq = imx_pdm_mic_mclk_freq(data->decimation,
sample_rate);
}
/* set mclk freq */
mclk_freq = imx_pdm_mic_mclk_freq(data->decimation, sample_rate);
ret = snd_soc_dai_set_sysclk(cpu_dai, FSL_SAI_CLK_MAST1,
mclk_freq, SND_SOC_CLOCK_OUT);
if (ret) {
@ -213,6 +253,9 @@ static int imx_pdm_mic_hw_params(struct snd_pcm_substream *substream,
return ret;
}
dev_dbg(card->dev, "mclk: %lu, bclk ratio: %u\n",
mclk_freq, data->decimation);
return 0;
}
@ -228,6 +271,9 @@ static int imx_pdm_mic_probe(struct platform_device *pdev)
struct platform_device *cpu_pdev;
struct imx_pdm_data *data;
struct snd_soc_dai_link_component *dlc;
unsigned long sai_mclk, sai_pll8k;
struct fsl_sai *sai;
unsigned int ratio;
int ret;
dlc = devm_kzalloc(&pdev->dev, 3 * sizeof(*dlc), GFP_KERNEL);
@ -266,6 +312,26 @@ static int imx_pdm_mic_probe(struct platform_device *pdev)
goto fail;
}
if (of_find_property(np, "fixed-mclk", NULL))
data->fixed_mclk = true;
if (data->fixed_mclk) {
sai = dev_get_drvdata(&cpu_pdev->dev);
/* Get SAI clock settings */
sai_mclk = clk_get_rate(sai->mclk_clk[FSL_SAI_CLK_MAST1]);
sai_pll8k = clk_get_rate(sai->pll8k_clk);
ratio = sai_pll8k / sai_mclk;
ret = imx_pdm_mic_get_mclk_fixed(data, ratio);
if (ret) {
dev_err(&pdev->dev, "fail to set fixed mclk: %d\n", ret);
return ret;
}
dev_dbg(&pdev->dev, "sai_pll8k: %lu, sai_mclk: %lu, ratio: %u\n",
sai_pll8k, sai_mclk, ratio);
}
data->dai.cpus = &dlc[0];
data->dai.num_cpus = 1;
data->dai.platforms = &dlc[1];