}
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,
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;
}
}
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)
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);
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;
}
}
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;