[PATCH v3 3/3] ASoC: cs42l43: Improve pop performance of the input power up
From: Charles Keepax
Date: Wed Nov 04 2026 - 06:26:07 EST
cs42l43's decimator is particularly susceptible to discontinuities
during startup. To help reduce the pop noises adjust the high
pass filter settings whilst powering up the microphones and add
a sizable delay to let that filter settle, then restore the user
settings.
Signed-off-by: Charles Keepax <ckeepax@xxxxxxxxxxxxxxxxxxxxx>
---
Changes since v2:
- Added dapm locking to Decimator 5/6 controls.
sound/soc/codecs/cs42l43.c | 87 +++++++++++++++++++++++++++++---------
sound/soc/codecs/cs42l43.h | 3 +-
2 files changed, 68 insertions(+), 22 deletions(-)
diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c
index 8fccddf7a1b22..f31f448484d65 100644
--- a/sound/soc/codecs/cs42l43.c
+++ b/sound/soc/codecs/cs42l43.c
@@ -1345,19 +1345,27 @@ static const struct snd_kcontrol_new cs42l43_controls[] = {
SOC_ENUM("Decimator 3 WNF Corner Frequency", cs42l43_dec3_wnf_corner),
SOC_ENUM("Decimator 4 WNF Corner Frequency", cs42l43_dec4_wnf_corner),
- SOC_SINGLE("Decimator 1 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL1,
- CS42L43_DECIM_HPF_EN_SHIFT, 1, 0),
- SOC_SINGLE("Decimator 2 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL2,
- CS42L43_DECIM_HPF_EN_SHIFT, 1, 0),
- SOC_SINGLE("Decimator 3 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL3,
- CS42L43_DECIM_HPF_EN_SHIFT, 1, 0),
- SOC_SINGLE("Decimator 4 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL4,
- CS42L43_DECIM_HPF_EN_SHIFT, 1, 0),
-
- SOC_ENUM("Decimator 1 HPF Corner Frequency", cs42l43_dec1_hpf_corner),
- SOC_ENUM("Decimator 2 HPF Corner Frequency", cs42l43_dec2_hpf_corner),
- SOC_ENUM("Decimator 3 HPF Corner Frequency", cs42l43_dec3_hpf_corner),
- SOC_ENUM("Decimator 4 HPF Corner Frequency", cs42l43_dec4_hpf_corner),
+ SOC_SINGLE_EXT("Decimator 1 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL1,
+ CS42L43_DECIM_HPF_EN_SHIFT, 1, 0,
+ cs42l43_dapm_get_volsw, cs42l43_dapm_put_volsw),
+ SOC_SINGLE_EXT("Decimator 2 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL2,
+ CS42L43_DECIM_HPF_EN_SHIFT, 1, 0,
+ cs42l43_dapm_get_volsw, cs42l43_dapm_put_volsw),
+ SOC_SINGLE_EXT("Decimator 3 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL3,
+ CS42L43_DECIM_HPF_EN_SHIFT, 1, 0,
+ cs42l43_dapm_get_volsw, cs42l43_dapm_put_volsw),
+ SOC_SINGLE_EXT("Decimator 4 HPF Switch", CS42L43_DECIM_HPF_WNF_CTRL4,
+ CS42L43_DECIM_HPF_EN_SHIFT, 1, 0,
+ cs42l43_dapm_get_volsw, cs42l43_dapm_put_volsw),
+
+ SOC_ENUM_EXT("Decimator 1 HPF Corner Frequency", cs42l43_dec1_hpf_corner,
+ cs42l43_dapm_get_enum, cs42l43_dapm_put_enum),
+ SOC_ENUM_EXT("Decimator 2 HPF Corner Frequency", cs42l43_dec2_hpf_corner,
+ cs42l43_dapm_get_enum, cs42l43_dapm_put_enum),
+ SOC_ENUM_EXT("Decimator 3 HPF Corner Frequency", cs42l43_dec3_hpf_corner,
+ cs42l43_dapm_get_enum, cs42l43_dapm_put_enum),
+ SOC_ENUM_EXT("Decimator 4 HPF Corner Frequency", cs42l43_dec4_hpf_corner,
+ cs42l43_dapm_get_enum, cs42l43_dapm_put_enum),
SOC_DOUBLE_R_EXT("Speaker Digital Switch",
CS42L43_INTP_VOLUME_CTRL1, CS42L43_INTP_VOLUME_CTRL2,
@@ -1737,32 +1745,39 @@ static int cs42l43_hp_ev(struct snd_soc_dapm_widget *w,
}
struct decim_info {
+ unsigned int freg;
unsigned int vreg;
unsigned int vmask;
};
static const struct decim_info cs42l43_decim_info[] = {
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL1,
.vreg = CS42L43_DECIM_VOL_CTRL_CH1_CH2,
.vmask = CS42L43_DECIM1_VD_RAMP_MASK | CS42L43_DECIM1_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL2,
.vreg = CS42L43_DECIM_VOL_CTRL_CH1_CH2,
.vmask = CS42L43_DECIM2_VD_RAMP_MASK | CS42L43_DECIM2_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL1,
.vreg = CS42L43_DECIM_VOL_CTRL_CH1_CH2,
.vmask = CS42L43_DECIM1_VD_RAMP_MASK | CS42L43_DECIM1_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL2,
.vreg = CS42L43_DECIM_VOL_CTRL_CH1_CH2,
.vmask = CS42L43_DECIM2_VD_RAMP_MASK | CS42L43_DECIM2_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL3,
.vreg = CS42L43_DECIM_VOL_CTRL_CH3_CH4,
.vmask = CS42L43_DECIM3_VD_RAMP_MASK | CS42L43_DECIM3_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL4,
.vreg = CS42L43_DECIM_VOL_CTRL_CH3_CH4,
.vmask = CS42L43_DECIM4_VD_RAMP_MASK | CS42L43_DECIM4_MUTE_MASK,
}
@@ -1770,26 +1785,32 @@ static const struct decim_info cs42l43_decim_info[] = {
static const struct decim_info cs42l43b_decim_info[] = {
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL1,
.vreg = CS42L43B_DECIM_VOL_CTRL_CH1_CH2,
.vmask = CS42L43_DECIM1_VD_RAMP_MASK | CS42L43_DECIM1_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL2,
.vreg = CS42L43B_DECIM_VOL_CTRL_CH1_CH2,
.vmask = CS42L43_DECIM2_VD_RAMP_MASK | CS42L43_DECIM2_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL3,
.vreg = CS42L43B_DECIM_VOL_CTRL_CH3_CH4,
.vmask = CS42L43_DECIM3_VD_RAMP_MASK | CS42L43_DECIM3_MUTE_MASK,
},
{
+ .freg = CS42L43_DECIM_HPF_WNF_CTRL4,
.vreg = CS42L43B_DECIM_VOL_CTRL_CH3_CH4,
.vmask = CS42L43_DECIM4_VD_RAMP_MASK | CS42L43_DECIM4_MUTE_MASK,
},
{
+ .freg = CS42L43B_DECIM_HPF_WNF_CTRL5,
.vreg = CS42L43B_DECIM_VOL_CTRL_CH5_CH6,
.vmask = CS42L43B_DECIM5_PATH1_VOL_FALL_RATE_MASK | CS42L43B_DECIM5_MUTE_MASK,
},
{
+ .freg = CS42L43B_DECIM_HPF_WNF_CTRL6,
.vreg = CS42L43B_DECIM_VOL_CTRL_CH5_CH6,
.vmask = CS42L43B_DECIM6_PATH1_VOL_FALL_RATE_MASK | CS42L43B_DECIM6_MUTE_MASK,
}
@@ -1802,6 +1823,8 @@ static int cs42l43_mic_ev(struct snd_soc_dapm_widget *w,
struct cs42l43_codec *priv = snd_soc_component_get_drvdata(component);
const struct decim_info *info = &cs42l43_decim_info[w->shift];
struct cs42l43 *cs42l43 = priv->core;
+ unsigned int fmask = CS42L43_DECIM_HPF_EN_MASK | CS42L43_DECIM_HPF_CF_MASK;
+ unsigned int fval = CS42L43_DECIM_HPF_EN_MASK | 3 << CS42L43_DECIM_HPF_CF_SHIFT;
unsigned int vval = CS42L43_DECIM1_MUTE_MASK | CS42L43_DECIM2_MUTE_MASK;
int ret;
@@ -1810,8 +1833,10 @@ static int cs42l43_mic_ev(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ priv->decim_pre_pmu = true;
+
ret = regmap_read(cs42l43->regmap, info->vreg,
- &priv->decim_cache[w->shift]);
+ &priv->decim_cache[w->shift][0]);
if (ret) {
dev_err(priv->dev,
"Failed to cache decimator settings: %d\n",
@@ -1819,11 +1844,27 @@ static int cs42l43_mic_ev(struct snd_soc_dapm_widget *w,
return ret;
}
+ ret = regmap_read(cs42l43->regmap, info->freg,
+ &priv->decim_cache[w->shift][1]);
+ if (ret) {
+ dev_err(priv->dev,
+ "Failed to cache decimator filter settings: %d\n", ret);
+ return ret;
+ }
+
regmap_update_bits(cs42l43->regmap, info->vreg, info->vmask, vval);
+ regmap_update_bits(cs42l43->regmap, info->freg, fmask, fval);
break;
case SND_SOC_DAPM_POST_PMU:
+ if (priv->decim_pre_pmu) {
+ msleep(150);
+ priv->decim_pre_pmu = false;
+ }
+
+ regmap_update_bits(cs42l43->regmap, info->freg, fmask,
+ priv->decim_cache[w->shift][1]);
regmap_update_bits(cs42l43->regmap, info->vreg, info->vmask,
- priv->decim_cache[w->shift]);
+ priv->decim_cache[w->shift][0]);
break;
default:
break;
@@ -2282,13 +2323,17 @@ static const struct snd_kcontrol_new cs42l43_b_controls[] = {
SOC_ENUM("Decimator 5 WNF Corner Frequency", cs42l43b_dec5_wnf_corner),
SOC_ENUM("Decimator 6 WNF Corner Frequency", cs42l43b_dec6_wnf_corner),
- SOC_SINGLE("Decimator 5 HPF Switch", CS42L43B_DECIM_HPF_WNF_CTRL5,
- CS42L43_DECIM_HPF_EN_SHIFT, 1, 0),
- SOC_SINGLE("Decimator 6 HPF Switch", CS42L43B_DECIM_HPF_WNF_CTRL6,
- CS42L43_DECIM_HPF_EN_SHIFT, 1, 0),
+ SOC_SINGLE_EXT("Decimator 5 HPF Switch", CS42L43B_DECIM_HPF_WNF_CTRL5,
+ CS42L43_DECIM_HPF_EN_SHIFT, 1, 0,
+ cs42l43_dapm_get_volsw, cs42l43_dapm_put_volsw),
+ SOC_SINGLE_EXT("Decimator 6 HPF Switch", CS42L43B_DECIM_HPF_WNF_CTRL6,
+ CS42L43_DECIM_HPF_EN_SHIFT, 1, 0,
+ cs42l43_dapm_get_volsw, cs42l43_dapm_put_volsw),
- SOC_ENUM("Decimator 5 HPF Corner Frequency", cs42l43b_dec5_hpf_corner),
- SOC_ENUM("Decimator 6 HPF Corner Frequency", cs42l43b_dec6_hpf_corner),
+ SOC_ENUM_EXT("Decimator 5 HPF Corner Frequency", cs42l43b_dec5_hpf_corner,
+ cs42l43_dapm_get_enum, cs42l43_dapm_put_enum),
+ SOC_ENUM_EXT("Decimator 6 HPF Corner Frequency", cs42l43b_dec6_hpf_corner,
+ cs42l43_dapm_get_enum, cs42l43_dapm_put_enum),
};
static const struct snd_soc_dapm_widget cs42l43_a_widgets[] = {
diff --git a/sound/soc/codecs/cs42l43.h b/sound/soc/codecs/cs42l43.h
index fd50feb26ae99..2dc8d530a1fc0 100644
--- a/sound/soc/codecs/cs42l43.h
+++ b/sound/soc/codecs/cs42l43.h
@@ -61,7 +61,8 @@ struct cs42l43_codec {
unsigned int refclk_freq;
struct completion pll_ready;
- unsigned int decim_cache[6];
+ bool decim_pre_pmu;
+ unsigned int decim_cache[6][2];
unsigned int adc_ena;
unsigned int hp_ena;
--
2.47.3