diff options
author | Charles Keepax <ckeepax@opensource.cirrus.com> | 2025-03-18 17:14:56 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2025-03-19 12:48:07 +0000 |
commit | 318e8794e05ca1879441a602e78c74f9d7e18309 (patch) | |
tree | ff90241b69aeb616c5469914d93fd6c27d975609 /sound | |
parent | 9dfcafe2037acc14265cead8d8a937a8bc4e01d8 (diff) |
ASoC: ops: Factor out common code from put callbacks
There are only two differences between snd_soc_put_volsw() and
snd_soc_put_volsw_sx(). The maximum field is handled differently, and
snd_soc_put_volsw() supports double controls with both values in the
same register.
Factor out the common code into a new helper and pass in the
appropriate max value such that it is handled correctly for each
control.
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20250318171459.3203730-13-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/soc-ops.c | 138 |
1 files changed, 53 insertions, 85 deletions
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 29537dd3a063..0b62ffb2e222 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -192,6 +192,57 @@ static int soc_info_volsw(struct snd_kcontrol *kcontrol, return 0; } +static int soc_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + struct soc_mixer_control *mc, int mask, int max) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + unsigned int val1, val_mask; + unsigned int val2 = 0; + bool double_r = false; + int ret; + + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], max); + if (ret) + return ret; + + 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); + if (ret) + return ret; + + if (mc->reg == mc->rreg) { + val1 |= soc_mixer_ctl_to_reg(mc, + ucontrol->value.integer.value[1], + mask, mc->rshift, max); + val_mask |= mask << mc->rshift; + } else { + val2 = soc_mixer_ctl_to_reg(mc, + ucontrol->value.integer.value[1], + mask, mc->shift, max); + double_r = true; + } + } + + ret = snd_soc_component_update_bits(component, mc->reg, val_mask, val1); + if (ret < 0) + return ret; + + if (double_r) { + int err = snd_soc_component_update_bits(component, mc->rreg, + val_mask, val2); + /* Don't drop change flag */ + if (err) + return err; + } + + return ret; +} + /** * snd_soc_info_volsw - single mixer info callback with range. * @kcontrol: mixer control @@ -289,57 +340,11 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - int max = mc->max - mc->min; unsigned int mask = soc_mixer_mask(mc); - int err, ret; - bool type_2r = false; - unsigned int val2 = 0; - unsigned int val, val_mask; - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], max); - if (ret) - return ret; - - val = 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); - if (ret) - return ret; - - if (reg == reg2) { - val |= soc_mixer_ctl_to_reg(mc, - ucontrol->value.integer.value[1], - mask, mc->rshift, max); - val_mask |= mask << mc->rshift; - } else { - val2 = soc_mixer_ctl_to_reg(mc, - ucontrol->value.integer.value[1], - mask, mc->shift, max); - type_2r = true; - } - } - err = snd_soc_component_update_bits(component, reg, val_mask, val); - if (err < 0) - return err; - ret = err; - - if (type_2r) { - err = snd_soc_component_update_bits(component, reg2, val_mask, - val2); - /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) - ret = err; - } - - return ret; + return soc_put_volsw(kcontrol, ucontrol, mc, mask, mc->max - mc->min); } EXPORT_SYMBOL_GPL(snd_soc_put_volsw); @@ -393,48 +398,11 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int val, val_mask; unsigned int mask = soc_mixer_sx_mask(mc); - int err = 0; - int ret; - - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], mc->max); - if (ret) - return ret; - - val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], - mask, mc->shift, mc->max); - val_mask = mask << mc->shift; - - err = snd_soc_component_update_bits(component, reg, val_mask, val); - if (err < 0) - return err; - ret = err; - if (snd_soc_volsw_is_stereo(mc)) { - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], - mc->max); - if (ret) - return ret; - - val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[1], - mask, mc->rshift, mc->max); - val_mask = mask << mc->rshift; - - err = snd_soc_component_update_bits(component, reg2, val_mask, - val); - - /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) - ret = err; - } - - return ret; + return soc_put_volsw(kcontrol, ucontrol, mc, mask, mc->max); } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); |