From d4f7d5a9a0f963dc895c18084425ce332a80d3a8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 25 Feb 2026 14:01:17 +0000 Subject: [PATCH] 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 --- sound/soc/sdca/sdca_asoc.c | 6 ++---- sound/soc/soc-ops.c | 12 ++---------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c index b6536eeecf58..e6f7c2778bec 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 f966d4e13c7f..8ae6609ca961 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,