[PATCH] ASoC: cpcap: Fix event generation for mux controls

Haotian Zhang posted 1 patch 2 months, 1 week ago
sound/soc/codecs/cpcap.c | 29 ++++++++++++++++-------------
1 file changed, 16 insertions(+), 13 deletions(-)
[PATCH] ASoC: cpcap: Fix event generation for mux controls
Posted by Haotian Zhang 2 months, 1 week ago
The mux put callbacks unconditionally return 0, failing to
notify the ALSA core when control values change. This prevents
userspace applications from receiving events.

Use regmap_update_bits_check() instead of regmap_update_bits()
to detect actual register changes, and return 1 when the mux value
has changed to generate proper events for userspace applications.

Fixes: f6cdf2d3445d ("ASoC: cpcap: new codec")
Signed-off-by: Haotian Zhang <vulab@iscas.ac.cn>
---
 sound/soc/codecs/cpcap.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c
index 3eb862643b53..40b33a0acc52 100644
--- a/sound/soc/codecs/cpcap.c
+++ b/sound/soc/codecs/cpcap.c
@@ -432,6 +432,7 @@ static int cpcap_output_mux_put_enum(struct snd_kcontrol *kcontrol,
 	unsigned int mask = BIT(e->shift_l);
 	u16 reg_voice = 0x00, reg_hifi = 0x00, reg_ext = 0x00;
 	int err;
+	bool change = false;
 
 	switch (muxval) {
 	case 1:
@@ -447,22 +448,22 @@ static int cpcap_output_mux_put_enum(struct snd_kcontrol *kcontrol,
 		break;
 	}
 
-	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,
-				 mask, reg_voice);
+	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_RXCOA,
+				 mask, reg_voice, &change);
 	if (err)
 		return err;
-	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXSDOA,
-				 mask, reg_hifi);
+	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_RXSDOA,
+				 mask, reg_hifi, &change);
 	if (err)
 		return err;
-	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXEPOA,
-				 mask, reg_ext);
+	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_RXEPOA,
+				 mask, reg_ext, &change);
 	if (err)
 		return err;
 
 	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
 
-	return 0;
+	return change ? 1 : 0;
 }
 
 static int cpcap_input_right_mux_get_enum(struct snd_kcontrol *kcontrol,
@@ -515,6 +516,7 @@ static int cpcap_input_right_mux_put_enum(struct snd_kcontrol *kcontrol,
 	unsigned int muxval = ucontrol->value.enumerated.item[0];
 	int regval = 0, mask;
 	int err;
+	bool change = false;
 
 	mask = 0;
 	mask |= BIT(CPCAP_BIT_MIC1_MUX);
@@ -539,14 +541,14 @@ static int cpcap_input_right_mux_put_enum(struct snd_kcontrol *kcontrol,
 		break;
 	}
 
-	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
-				 mask, regval);
+	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_TXI,
+				 mask, regval, &change);
 	if (err)
 		return err;
 
 	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
 
-	return 0;
+	return change ? 1 : 0;
 }
 
 static int cpcap_input_left_mux_get_enum(struct snd_kcontrol *kcontrol,
@@ -591,6 +593,7 @@ static int cpcap_input_left_mux_put_enum(struct snd_kcontrol *kcontrol,
 	unsigned int muxval = ucontrol->value.enumerated.item[0];
 	int regval = 0, mask;
 	int err;
+	bool change = false;
 
 	mask = 0;
 	mask |= BIT(CPCAP_BIT_MIC2_MUX);
@@ -607,14 +610,14 @@ static int cpcap_input_left_mux_put_enum(struct snd_kcontrol *kcontrol,
 		break;
 	}
 
-	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
-				 mask, regval);
+	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_TXI,
+				 mask, regval, &change);
 	if (err)
 		return err;
 
 	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
 
-	return 0;
+	return change ? 1 : 0;
 }
 
 static const struct snd_kcontrol_new cpcap_input_left_mux =
-- 
2.50.1.windows.1
Re: [PATCH] ASoC: cpcap: Fix event generation for mux controls
Posted by Mark Brown 2 months ago
On Mon, Dec 01, 2025 at 11:03:54AM +0800, Haotian Zhang wrote:

> -	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,
> -				 mask, reg_voice);
> +	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_RXCOA,
> +				 mask, reg_voice, &change);
>  	if (err)
>  		return err;
> -	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXSDOA,
> -				 mask, reg_hifi);
> +	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_RXSDOA,
> +				 mask, reg_hifi, &change);
>  	if (err)
>  		return err;
> -	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXEPOA,
> -				 mask, reg_ext);
> +	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_RXEPOA,
> +				 mask, reg_ext, &change);

This will only flag a change if it happens as part of the last update,
each regmap call will overwrite the change flag.

>  	if (err)
>  		return err;
>  
>  	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
>  
> -	return 0;
> +	return change ? 1 : 0;
>  }
>  
>  static int cpcap_input_right_mux_get_enum(struct snd_kcontrol *kcontrol,
> @@ -515,6 +516,7 @@ static int cpcap_input_right_mux_put_enum(struct snd_kcontrol *kcontrol,
>  	unsigned int muxval = ucontrol->value.enumerated.item[0];
>  	int regval = 0, mask;
>  	int err;
> +	bool change = false;
>  
>  	mask = 0;
>  	mask |= BIT(CPCAP_BIT_MIC1_MUX);
> @@ -539,14 +541,14 @@ static int cpcap_input_right_mux_put_enum(struct snd_kcontrol *kcontrol,
>  		break;
>  	}
>  
> -	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
> -				 mask, regval);
> +	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_TXI,
> +				 mask, regval, &change);
>  	if (err)
>  		return err;
>  
>  	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
>  
> -	return 0;
> +	return change ? 1 : 0;
>  }
>  
>  static int cpcap_input_left_mux_get_enum(struct snd_kcontrol *kcontrol,
> @@ -591,6 +593,7 @@ static int cpcap_input_left_mux_put_enum(struct snd_kcontrol *kcontrol,
>  	unsigned int muxval = ucontrol->value.enumerated.item[0];
>  	int regval = 0, mask;
>  	int err;
> +	bool change = false;
>  
>  	mask = 0;
>  	mask |= BIT(CPCAP_BIT_MIC2_MUX);
> @@ -607,14 +610,14 @@ static int cpcap_input_left_mux_put_enum(struct snd_kcontrol *kcontrol,
>  		break;
>  	}
>  
> -	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
> -				 mask, regval);
> +	err = regmap_update_bits_check(cpcap->regmap, CPCAP_REG_TXI,
> +				 mask, regval, &change);
>  	if (err)
>  		return err;
>  
>  	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
>  
> -	return 0;
> +	return change ? 1 : 0;
>  }
>  
>  static const struct snd_kcontrol_new cpcap_input_left_mux =
> -- 
> 2.50.1.windows.1
>