ASoC: cs42l42: Fix 1536000 Bit Clock instability
authorLucas Tanure <tanureal@opensource.cirrus.com>
Tue, 25 May 2021 09:08:19 +0000 (10:08 +0100)
committerMark Brown <broonie@sirena.org.uk>
Tue, 25 May 2021 15:45:03 +0000 (16:45 +0100)
The 16 Bits, 2 channels, 48K sample rate use case needs
to configure a safer pll_divout during the start of PLL
After 800us from the start of PLL the correct pll_divout
can be set

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Message-Id: <20210525090822.64577-1-tanureal@opensource.cirrus.com>
Signed-off-by: Mark Brown <broonie@sirena.org.uk>
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cs42l42.h

index b084acd1e86b6f28c5ce4cda33c4d5a7a5d4d226..94788a55fa3b303a5611c177c18d575653a22ed9 100644 (file)
@@ -589,6 +589,7 @@ struct cs42l42_pll_params {
        u8 pll_divout;
        u32 mclk_int;
        u8 pll_cal_ratio;
+       u8 n;
 };
 
 /*
@@ -596,21 +597,21 @@ struct cs42l42_pll_params {
  * Table 4-5 from the Datasheet
  */
 static const struct cs42l42_pll_params pll_ratio_table[] = {
-       { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125 },
-       { 2822400, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 },
-       { 3000000, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 },
-       { 3072000, 0, 1, 0x00, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 },
-       { 4000000, 0, 1, 0x00, 0x30, 0x800000, 0x03, 0x10, 12000000, 96 },
-       { 4096000, 0, 1, 0x00, 0x2E, 0xE00000, 0x03, 0x10, 12000000, 94 },
-       { 5644800, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 },
-       { 6000000, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 },
-       { 6144000, 0, 1, 0x01, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 },
-       { 11289600, 0, 0, 0, 0, 0, 0, 0, 11289600, 0 },
-       { 12000000, 0, 0, 0, 0, 0, 0, 0, 12000000, 0 },
-       { 12288000, 0, 0, 0, 0, 0, 0, 0, 12288000, 0 },
-       { 22579200, 1, 0, 0, 0, 0, 0, 0, 22579200, 0 },
-       { 24000000, 1, 0, 0, 0, 0, 0, 0, 24000000, 0 },
-       { 24576000, 1, 0, 0, 0, 0, 0, 0, 24576000, 0 }
+       { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125, 2},
+       { 2822400, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 11289600, 128, 1},
+       { 3000000, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 12000000, 128, 1},
+       { 3072000, 0, 1, 0x00, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125, 1},
+       { 4000000, 0, 1, 0x00, 0x30, 0x800000, 0x03, 0x10, 12000000,  96, 1},
+       { 4096000, 0, 1, 0x00, 0x2E, 0xE00000, 0x03, 0x10, 12000000,  94, 1},
+       { 5644800, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 11289600, 128, 1},
+       { 6000000, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 12000000, 128, 1},
+       { 6144000, 0, 1, 0x01, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125, 1},
+       { 11289600, 0, 0, 0, 0, 0, 0, 0, 11289600, 0, 1},
+       { 12000000, 0, 0, 0, 0, 0, 0, 0, 12000000, 0, 1},
+       { 12288000, 0, 0, 0, 0, 0, 0, 0, 12288000, 0, 1},
+       { 22579200, 1, 0, 0, 0, 0, 0, 0, 22579200, 0, 1},
+       { 24000000, 1, 0, 0, 0, 0, 0, 0, 24000000, 0, 1},
+       { 24576000, 1, 0, 0, 0, 0, 0, 0, 24576000, 0, 1}
 };
 
 static int cs42l42_pll_config(struct snd_soc_component *component)
@@ -746,8 +747,12 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
                                snd_soc_component_update_bits(component,
                                        CS42L42_PLL_CTL3,
                                        CS42L42_PLL_DIVOUT_MASK,
-                                       pll_ratio_table[i].pll_divout
+                                       (pll_ratio_table[i].pll_divout * pll_ratio_table[i].n)
                                        << CS42L42_PLL_DIVOUT_SHIFT);
+                               if (pll_ratio_table[i].n != 1)
+                                       cs42l42->pll_divout = pll_ratio_table[i].pll_divout;
+                               else
+                                       cs42l42->pll_divout = 0;
                                snd_soc_component_update_bits(component,
                                        CS42L42_PLL_CAL_RATIO,
                                        CS42L42_PLL_CAL_RATIO_MASK,
@@ -902,6 +907,16 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
                        if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) {
                                snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
                                                              CS42L42_PLL_START_MASK, 1);
+
+                               if (cs42l42->pll_divout) {
+                                       usleep_range(CS42L42_PLL_DIVOUT_TIME_US,
+                                                    CS42L42_PLL_DIVOUT_TIME_US * 2);
+                                       snd_soc_component_update_bits(component, CS42L42_PLL_CTL3,
+                                                                     CS42L42_PLL_DIVOUT_MASK,
+                                                                     cs42l42->pll_divout <<
+                                                                     CS42L42_PLL_DIVOUT_SHIFT);
+                               }
+
                                ret = regmap_read_poll_timeout(cs42l42->regmap,
                                                               CS42L42_PLL_LOCK_STATUS,
                                                               regval,
index 24f7be228d5f9b73de39ef8f032f63f9fdd5c106..7bf05ff05f74151c5e5ae7b94844e8196c22499a 100644 (file)
 
 #define CS42L42_NUM_SUPPLIES   5
 #define CS42L42_BOOT_TIME_US   3000
+#define CS42L42_PLL_DIVOUT_TIME_US     800
 #define CS42L42_CLOCK_SWITCH_DELAY_US 150
 #define CS42L42_PLL_LOCK_POLL_US       250
 #define CS42L42_PLL_LOCK_TIMEOUT_US    1250
@@ -777,6 +778,7 @@ struct  cs42l42_private {
        int bclk;
        u32 sclk;
        u32 srate;
+       u8 pll_divout;
        u8 plug_state;
        u8 hs_type;
        u8 ts_inv;