mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 21:52:29 -04:00
ASoC: SDCA: Pull the Q7.8 volume helpers out of soc-ops
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@linux.dev> Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Link: https://patch.msgid.link/20260225140118.402695-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
d4f7d5a9a0
commit
501efdcb3b
@@ -1239,7 +1239,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
|
||||
|
||||
@@ -805,6 +805,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,
|
||||
@@ -845,10 +909,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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user