summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Alonso <adrian.alonso@nxp.com>2020-06-27 16:56:47 -0500
committerAdrian Alonso <adrian.alonso@nxp.com>2020-07-20 11:02:44 -0500
commitcdfd304a32248295f7d77f61d32137f1bb5bf64e (patch)
treea110f41936ce7b6484791df315ee8f82bf7e458c
parentde79414d59918132220fa9ada8ad4342b1574986 (diff)
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>
-rw-r--r--sound/soc/fsl/imx-pdm.c68
1 files changed, 67 insertions, 1 deletions
diff --git a/sound/soc/fsl/imx-pdm.c b/sound/soc/fsl/imx-pdm.c
index b6db88db39dd..6627227e0161 100644
--- a/sound/soc/fsl/imx-pdm.c
+++ b/sound/soc/fsl/imx-pdm.c
@@ -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];