]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ASoC: cs42l42: Set correct SRC MCLK
authorRichard Fitzgerald <rf@opensource.cirrus.com>
Fri, 15 Oct 2021 13:36:16 +0000 (14:36 +0100)
committerMark Brown <broonie@kernel.org>
Fri, 15 Oct 2021 15:14:20 +0000 (16:14 +0100)
According to the datasheet the SRC MCLK must be as near as possible to
(125 * sample rate). This means it should be ~6MHz for rates up to 48k
and ~12MHz for rates above that. As per datasheet table 4-21.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20211015133619.4698-14-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cs42l42.h

index d6d74a7bbde9ab27a3676662359667165854f08a..d62272d0ab8c06d95a57b0f40292ac110539ffc7 100644 (file)
@@ -678,22 +678,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
                                        CS42L42_FSYNC_PULSE_WIDTH_MASK,
                                        CS42L42_FRAC1_VAL(fsync - 1) <<
                                        CS42L42_FSYNC_PULSE_WIDTH_SHIFT);
-                       /* Set the sample rates (96k or lower) */
-                       snd_soc_component_update_bits(component, CS42L42_FS_RATE_EN,
-                                       CS42L42_FS_EN_MASK,
-                                       (CS42L42_FS_EN_IASRC_96K |
-                                       CS42L42_FS_EN_OASRC_96K) <<
-                                       CS42L42_FS_EN_SHIFT);
-                       /* Set the input/output internal MCLK clock ~12 MHz */
-                       snd_soc_component_update_bits(component, CS42L42_IN_ASRC_CLK,
-                                       CS42L42_CLK_IASRC_SEL_MASK,
-                                       CS42L42_CLK_IASRC_SEL_12 <<
-                                       CS42L42_CLK_IASRC_SEL_SHIFT);
-                       snd_soc_component_update_bits(component,
-                                       CS42L42_OUT_ASRC_CLK,
-                                       CS42L42_CLK_OASRC_SEL_MASK,
-                                       CS42L42_CLK_OASRC_SEL_12 <<
-                                       CS42L42_CLK_OASRC_SEL_SHIFT);
                        if (pll_ratio_table[i].mclk_src_sel == 0) {
                                /* Pass the clock straight through */
                                snd_soc_component_update_bits(component,
@@ -756,6 +740,39 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
        return -EINVAL;
 }
 
+static void cs42l42_src_config(struct snd_soc_component *component, unsigned int sample_rate)
+{
+       struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
+       unsigned int fs;
+
+       /* Don't reconfigure if there is an audio stream running */
+       if (cs42l42->stream_use)
+               return;
+
+       /* SRC MCLK must be as close as possible to 125 * sample rate */
+       if (sample_rate <= 48000)
+               fs = CS42L42_CLK_IASRC_SEL_6;
+       else
+               fs = CS42L42_CLK_IASRC_SEL_12;
+
+       /* Set the sample rates (96k or lower) */
+       snd_soc_component_update_bits(component,
+                                     CS42L42_FS_RATE_EN,
+                                     CS42L42_FS_EN_MASK,
+                                     (CS42L42_FS_EN_IASRC_96K |
+                                      CS42L42_FS_EN_OASRC_96K) <<
+                                     CS42L42_FS_EN_SHIFT);
+
+       snd_soc_component_update_bits(component,
+                                     CS42L42_IN_ASRC_CLK,
+                                     CS42L42_CLK_IASRC_SEL_MASK,
+                                     fs << CS42L42_CLK_IASRC_SEL_SHIFT);
+       snd_soc_component_update_bits(component,
+                                     CS42L42_OUT_ASRC_CLK,
+                                     CS42L42_CLK_OASRC_SEL_MASK,
+                                     fs << CS42L42_CLK_OASRC_SEL_SHIFT);
+}
+
 static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_component *component = codec_dai->component;
@@ -846,6 +863,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
        unsigned int channels = params_channels(params);
        unsigned int width = (params_width(params) / 8) - 1;
        unsigned int val = 0;
+       int ret;
 
        cs42l42->srate = params_rate(params);
        cs42l42->bclk = snd_soc_params_to_bclk(params);
@@ -899,7 +917,13 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       return cs42l42_pll_config(component);
+       ret = cs42l42_pll_config(component);
+       if (ret)
+               return ret;
+
+       cs42l42_src_config(component, params_rate(params));
+
+       return 0;
 }
 
 static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
index ded61af6ea8b6ab40b829b36a24c4d6e05b84da7..d13749e9d8c5742be257b4ebc81c082a234a26d2 100644 (file)
 #define CS42L42_IN_ASRC_CLK            (CS42L42_PAGE_12 + 0x0A)
 #define CS42L42_CLK_IASRC_SEL_SHIFT    0
 #define CS42L42_CLK_IASRC_SEL_MASK     (1 << CS42L42_CLK_IASRC_SEL_SHIFT)
+#define CS42L42_CLK_IASRC_SEL_6                0
 #define CS42L42_CLK_IASRC_SEL_12       1
 
 #define CS42L42_OUT_ASRC_CLK           (CS42L42_PAGE_12 + 0x0B)