summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/cs42l42.c
diff options
context:
space:
mode:
authorLucas Tanure <tanureal@opensource.cirrus.com>2021-05-25 10:08:19 +0100
committerMark Brown <broonie@sirena.org.uk>2021-05-25 16:45:03 +0100
commit1c52825c38fc4e44c61ed75a8ae32f5fa580383b (patch)
treeafa3df527c85efca7aac5e4f53105ba59d48baf1 /sound/soc/codecs/cs42l42.c
parentd4e9889b02014a07c8dba3fbbae7205ea4084350 (diff)
ASoC: cs42l42: Fix 1536000 Bit Clock instability
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>
Diffstat (limited to 'sound/soc/codecs/cs42l42.c')
-rw-r--r--sound/soc/codecs/cs42l42.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index b084acd1e86b..94788a55fa3b 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -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,