mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
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 <rf@opensource.cirrus.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Link: https://patch.msgid.link/20260225140118.402695-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
1fb720d33e
commit
d4f7d5a9a0
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user