* add error handling in case register read fails * add support for clamping the values if the register value read is greater than max value
Signed-off-by: Niranjan H Y niranjan.hy@ti.com --- sound/soc/soc-ops.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index a629e0eac..59e91741b 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -111,10 +111,14 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val, - unsigned int mask, unsigned int shift, int max) + unsigned int mask, unsigned int shift, int max, + bool clamp) { int val = (reg_val >> shift) & mask;
+ if (clamp) + val = clamp(val, 0, mc->max); + if (mc->sign_bit) val = sign_extend32(val, mc->sign_bit);
@@ -245,29 +249,44 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol,
static int soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, - struct soc_mixer_control *mc, int mask, int max) + struct soc_mixer_control *mc, int mask, int max, + bool clamp) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); unsigned int reg_val; - int val; + int val, ret = 0;
reg_val = snd_soc_component_read(component, mc->reg); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); + val = reg_val; + if (val < 0) { + ret = val; + goto get_volsw_done; + } + + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max, clamp);
ucontrol->value.integer.value[0] = val;
if (snd_soc_volsw_is_stereo(mc)) { if (mc->reg == mc->rreg) { - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, max); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, + max, clamp); } else { reg_val = snd_soc_component_read(component, mc->rreg); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); + val = reg_val; + if (val < 0) { + ret = val; + goto get_volsw_done; + } + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, + mc->shift, max, clamp); }
ucontrol->value.integer.value[1] = val; }
- return 0; +get_volsw_done: + return ret; }
/** @@ -330,7 +349,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int mask = soc_mixer_mask(mc);
- return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max - mc->min); + return soc_get_volsw(kcontrol, ucontrol, mc, mask, + mc->max - mc->min, false); } EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
@@ -372,7 +392,7 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int mask = soc_mixer_sx_mask(mc);
- return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max); + return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max, false); } EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);