From: Charles Keepax Date: Wed, 25 Feb 2026 14:01:17 +0000 (+0000) Subject: ASoC: SDCA: Improve mapping of Q7.8 SDCA volumes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4f7d5a9a0f963dc895c18084425ce332a80d3a8;p=thirdparty%2Flinux.git ASoC: SDCA: Improve mapping of Q7.8 SDCA volumes SDCA measures volumes in 256ths of a dB, whereas ALSA measures volumes in 100ths of a dB. Currently the SDCA volume controls are mapped to ALSA controls by mapping the step size and working out the number of steps for this mapped step size. Due to quantization of the step size this means the number of steps in the ALSA control will rarely match the number of steps in the SDCA control, leading to skipped values and multiple values that map to the same volume. This is not a huge problem, the volume is still increasing and the differences will be small but it is not really desirable. It is simpler and more accurate to count the number of steps based on the SDCA volume levels. This gives a 1-to-1 mapping between control values and register volumes. The TLV is based on a minimum and maximum volume so still accurately specifies the volume range. Tested-by: Richard Fitzgerald Reviewed-by: Pierre-Louis Bossart Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260225140118.402695-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c index b6536eeecf58f..e6f7c2778bec5 100644 --- a/sound/soc/sdca/sdca_asoc.c +++ b/sound/soc/sdca/sdca_asoc.c @@ -841,10 +841,8 @@ static int control_limit_kctl(struct device *dev, tlv[2] = (min * 100) >> 8; tlv[3] = (max * 100) >> 8; - step = (step * 100) >> 8; - - mc->min = ((int)tlv[2] / step); - mc->max = ((int)tlv[3] / step); + mc->min = min / step; + mc->max = max / step; mc->shift = step; mc->sign_bit = 15; mc->sdca_q78 = 1; diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index f966d4e13c7fc..8ae6609ca9618 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -120,25 +120,17 @@ static int sdca_soc_q78_reg_to_ctl(struct soc_mixer_control *mc, unsigned int re return -EINVAL; val = sign_extend32(val, mc->sign_bit); - val = (((val * 100) >> 8) / (int)mc->shift); - val -= mc->min; - return val & mask; + 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) { - unsigned int ret_val; - int reg_val; - if (WARN_ON(!mc->shift)) return -EINVAL; - reg_val = val + mc->min; - ret_val = (int)((reg_val * mc->shift) << 8) / 100; - - return ret_val & mask; + return ((val + mc->min) * mc->shift) & mask; } static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val,