[SRU][R][PATCH 4/7] ASoC: SDCA: Pull the Q7.8 volume helpers out of soc-ops

Chris Chiu chris.chiu at canonical.com
Tue Mar 17 03:44:35 UTC 2026


From: Charles Keepax <ckeepax at opensource.cirrus.com>

BugLink: https://bugs.launchpad.net/bugs/2143902

It is cleaner to keep the SDCA code contained and not update the core
code for things that are unlikely to see reuse outside of SDCA. Move the
Q7.8 volume helpers back into the SDCA core code.

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.dev>
Signed-off-by: Charles Keepax <ckeepax at opensource.cirrus.com>
Link: https://patch.msgid.link/20260225140118.402695-5-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie at kernel.org>
(cherry picked from commit 501efdcb3b3ab099fc0ce2f6e668b1c4095dd476)
Signed-off-by: Chris Chiu <chris.chiu at canonical.com>
---
 include/sound/soc.h        |  1 -
 sound/soc/sdca/sdca_asoc.c | 67 +++++++++++++++++++++++++++++++++++++-
 sound/soc/soc-ops.c        | 56 +++++++------------------------
 3 files changed, 77 insertions(+), 47 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 34365d0e0ed3..1fffef311c41 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1220,7 +1220,6 @@ struct soc_mixer_control {
 	unsigned int sign_bit;
 	unsigned int invert:1;
 	unsigned int autodisable:1;
-	unsigned int sdca_q78:1;
 #ifdef CONFIG_SND_SOC_TOPOLOGY
 	struct snd_soc_dobj dobj;
 #endif
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index beee024622a5..a590dcb6e993 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -769,6 +769,70 @@ int sdca_asoc_populate_dapm(struct device *dev, struct sdca_function_data *funct
 }
 EXPORT_SYMBOL_NS(sdca_asoc_populate_dapm, "SND_SOC_SDCA");
 
+static int q78_write(struct snd_soc_component *component,
+		     struct soc_mixer_control *mc,
+		     unsigned int reg, const int val)
+{
+	unsigned int mask = GENMASK(mc->sign_bit, 0);
+	unsigned int reg_val;
+
+	if (val < 0 || val > mc->max - mc->min)
+		return -EINVAL;
+
+	reg_val = (val + mc->min) * mc->shift;
+
+	return snd_soc_component_update_bits(component, reg, mask, reg_val);
+}
+
+static int q78_put_volsw(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	int ret;
+
+	ret = q78_write(component, mc, mc->reg, ucontrol->value.integer.value[0]);
+	if (ret < 0)
+		return ret;
+
+	if (snd_soc_volsw_is_stereo(mc)) {
+		int err; /* Don't drop change flag */
+
+		err = q78_write(component, mc, mc->rreg, ucontrol->value.integer.value[1]);
+		if (err)
+			return err;
+	}
+
+	return ret;
+}
+
+static int q78_read(struct snd_soc_component *component,
+		    struct soc_mixer_control *mc, unsigned int reg)
+{
+	unsigned int reg_val;
+	int val;
+
+	reg_val = snd_soc_component_read(component, reg);
+
+	val = (sign_extend32(reg_val, mc->sign_bit) / mc->shift) - mc->min;
+
+	return val & GENMASK(mc->sign_bit, 0);
+}
+
+static int q78_get_volsw(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = q78_read(component, mc, mc->reg);
+
+	if (snd_soc_volsw_is_stereo(mc))
+		ucontrol->value.integer.value[1] = q78_read(component, mc, mc->rreg);
+
+	return 0;
+}
+
 static int control_limit_kctl(struct device *dev,
 			      struct sdca_entity *entity,
 			      struct sdca_control *control,
@@ -809,10 +873,11 @@ static int control_limit_kctl(struct device *dev,
 	mc->max = max / step;
 	mc->shift = step;
 	mc->sign_bit = 15;
-	mc->sdca_q78 = 1;
 
 	kctl->tlv.p = tlv;
 	kctl->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+	kctl->get = q78_get_volsw;
+	kctl->put = q78_put_volsw;
 
 	return 0;
 }
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 133a2e6fbd7a..e2fb1b4595e0 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -110,29 +110,6 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
 
-static int sdca_soc_q78_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val,
-				   unsigned int mask, unsigned int shift, int max,
-				   bool sx)
-{
-	int val = reg_val;
-
-	if (WARN_ON(!mc->shift))
-		return -EINVAL;
-
-	val = sign_extend32(val, mc->sign_bit);
-
-	return ((val / mc->shift) - mc->min) & mask;
-}
-
-static unsigned int sdca_soc_q78_ctl_to_reg(struct soc_mixer_control *mc, int val,
-					 unsigned int mask, unsigned int shift, int max)
-{
-	if (WARN_ON(!mc->shift))
-		return -EINVAL;
-
-	return ((val + mc->min) * mc->shift) & mask;
-}
-
 static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val,
 				unsigned int mask, unsigned int shift, int max,
 				bool sx)
@@ -226,27 +203,19 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol,
 			 struct soc_mixer_control *mc, int mask, int max)
 {
-	unsigned int (*ctl_to_reg)(struct soc_mixer_control *, int, unsigned int, unsigned int, int);
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	unsigned int val1, val_mask;
 	unsigned int val2 = 0;
 	bool double_r = false;
 	int ret;
 
-	if (mc->sdca_q78) {
-		ctl_to_reg = sdca_soc_q78_ctl_to_reg;
-		val_mask = mask;
-	} else {
-		ctl_to_reg = soc_mixer_ctl_to_reg;
-		val_mask = mask << mc->shift;
-	}
-
 	ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], max);
 	if (ret)
 		return ret;
 
-	val1 = ctl_to_reg(mc, ucontrol->value.integer.value[0],
+	val1 = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0],
 				    mask, mc->shift, max);
+	val_mask = mask << mc->shift;
 
 	if (snd_soc_volsw_is_stereo(mc)) {
 		ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], max);
@@ -254,10 +223,14 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol,
 			return ret;
 
 		if (mc->reg == mc->rreg) {
-			val1 |= ctl_to_reg(mc, ucontrol->value.integer.value[1], mask, mc->rshift, max);
+			val1 |= soc_mixer_ctl_to_reg(mc,
+						     ucontrol->value.integer.value[1],
+						     mask, mc->rshift, max);
 			val_mask |= mask << mc->rshift;
 		} else {
-			val2 = ctl_to_reg(mc, ucontrol->value.integer.value[1], mask, mc->shift, max);
+			val2 = soc_mixer_ctl_to_reg(mc,
+						    ucontrol->value.integer.value[1],
+						    mask, mc->shift, max);
 			double_r = true;
 		}
 	}
@@ -281,28 +254,21 @@ static int soc_get_volsw(struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol,
 			 struct soc_mixer_control *mc, int mask, int max, bool sx)
 {
-	int (*reg_to_ctl)(struct soc_mixer_control *, unsigned int, unsigned int,
-			  unsigned int, int, bool);
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	unsigned int reg_val;
 	int val;
 
-	if (mc->sdca_q78)
-		reg_to_ctl = sdca_soc_q78_reg_to_ctl;
-	else
-		reg_to_ctl = soc_mixer_reg_to_ctl;
-
 	reg_val = snd_soc_component_read(component, mc->reg);
-	val = reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);
+	val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);
 
 	ucontrol->value.integer.value[0] = val;
 
 	if (snd_soc_volsw_is_stereo(mc)) {
 		if (mc->reg == mc->rreg) {
-			val = reg_to_ctl(mc, reg_val, mask, mc->rshift, max, sx);
+			val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, max, sx);
 		} else {
 			reg_val = snd_soc_component_read(component, mc->rreg);
-			val = reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);
+			val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);
 		}
 
 		ucontrol->value.integer.value[1] = val;
-- 
2.43.0




More information about the kernel-team mailing list