Skip to content

Commit f1040e8

Browse files
rfvirgilbroonie
authored andcommitted
ASoC: cs42l42: PLL must be running when changing MCLK_SRC_SEL
Both SCLK and PLL clocks must be running to drive the glitch-free mux behind MCLK_SRC_SEL and complete the switchover. This patch moves the writing of MCLK_SRC_SEL to when the PLL is started and stopped, so that it only transitions while the PLL is running. The unconditional write MCLK_SRC_SEL=0 in cs42l42_mute_stream() is safe because if the PLL is not running MCLK_SRC_SEL is already 0. Signed-off-by: Richard Fitzgerald <[email protected]> Fixes: 43fc357 ("ASoC: cs42l42: Set clock source for both ways of stream") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 8b353bb commit f1040e8

File tree

2 files changed

+19
-7
lines changed

2 files changed

+19
-7
lines changed

sound/soc/codecs/cs42l42.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,8 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
619619

620620
for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
621621
if (pll_ratio_table[i].sclk == clk) {
622+
cs42l42->pll_config = i;
623+
622624
/* Configure the internal sample rate */
623625
snd_soc_component_update_bits(component, CS42L42_MCLK_CTL,
624626
CS42L42_INTERNAL_FS_MASK,
@@ -627,14 +629,9 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
627629
(pll_ratio_table[i].mclk_int !=
628630
24000000)) <<
629631
CS42L42_INTERNAL_FS_SHIFT);
630-
/* Set the MCLK src (PLL or SCLK) and the divide
631-
* ratio
632-
*/
632+
633633
snd_soc_component_update_bits(component, CS42L42_MCLK_SRC_SEL,
634-
CS42L42_MCLK_SRC_SEL_MASK |
635634
CS42L42_MCLKDIV_MASK,
636-
(pll_ratio_table[i].mclk_src_sel
637-
<< CS42L42_MCLK_SRC_SEL_SHIFT) |
638635
(pll_ratio_table[i].mclk_div <<
639636
CS42L42_MCLKDIV_SHIFT));
640637
/* Set up the LRCLK */
@@ -892,13 +889,21 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
892889
*/
893890
regmap_multi_reg_write(cs42l42->regmap, cs42l42_to_osc_seq,
894891
ARRAY_SIZE(cs42l42_to_osc_seq));
892+
893+
/* Must disconnect PLL before stopping it */
894+
snd_soc_component_update_bits(component,
895+
CS42L42_MCLK_SRC_SEL,
896+
CS42L42_MCLK_SRC_SEL_MASK,
897+
0);
898+
usleep_range(100, 200);
899+
895900
snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
896901
CS42L42_PLL_START_MASK, 0);
897902
}
898903
} else {
899904
if (!cs42l42->stream_use) {
900905
/* SCLK must be running before codec unmute */
901-
if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) {
906+
if (pll_ratio_table[cs42l42->pll_config].mclk_src_sel) {
902907
snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
903908
CS42L42_PLL_START_MASK, 1);
904909

@@ -919,6 +924,12 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
919924
CS42L42_PLL_LOCK_TIMEOUT_US);
920925
if (ret < 0)
921926
dev_warn(component->dev, "PLL failed to lock: %d\n", ret);
927+
928+
/* PLL must be running to drive glitchless switch logic */
929+
snd_soc_component_update_bits(component,
930+
CS42L42_MCLK_SRC_SEL,
931+
CS42L42_MCLK_SRC_SEL_MASK,
932+
CS42L42_MCLK_SRC_SEL_MASK);
922933
}
923934

924935
/* Mark SCLK as present, turn off internal oscillator */

sound/soc/codecs/cs42l42.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ struct cs42l42_private {
775775
struct gpio_desc *reset_gpio;
776776
struct completion pdn_done;
777777
struct snd_soc_jack *jack;
778+
int pll_config;
778779
int bclk;
779780
u32 sclk;
780781
u32 srate;

0 commit comments

Comments
 (0)