From: Kristoffer KARLSSON kristoffer.karlsson@stericsson.com
Added get/put accessors for controls that maps a range of consecutive registers exposed as a multiple value control.
This is specifically useful for hardware that exposes for instance a range of filter parameters as a range of registers that with this could be written and read back in one single ioctl operation.
snd_soc_get_m1r_sx snd_soc_put_m1r_sx
Signed-off-by: Kristoffer KARLSSON kristoffer.karlsson@stericsson.com --- include/sound/soc.h | 4 +++ sound/soc/soc-core.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index d2e1d07..66953a6 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -436,6 +436,10 @@ int snd_soc_get_xr8_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_xr8_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_get_m1r_sx(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_soc_put_m1r_sx(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol);
/** * struct snd_soc_reg_access - Describes whether a given register is diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b72f238..bacc465 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2726,6 +2726,78 @@ int snd_soc_put_xr8_sx(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_xr8_sx);
/** + * snd_soc_get_m1r_sx - multiple register get callback + * @kcontrol: mreg control + * @ucontrol: control element information + * + * Callback to get the all values of a control + * from a chunk of registers. + * + * Returns 0 for success. + */ +int snd_soc_get_m1r_sx(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mreg_control *mc = + (struct soc_mreg_control *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = *mc->reg; + unsigned int count = mc->count; + unsigned int invert = mc->invert; + unsigned int idx; + long value; + + for (idx = 0; idx < count; idx++) { + value = snd_soc_read(codec, reg + idx); + if (invert) + value = ~value; + ucontrol->value.integer.value[idx] = value; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_get_m1r_sx); + +/** + * snd_soc_put_m1r_sx - multiple register get callback + * @kcontrol: mreg control + * @ucontrol: control element information + * + * Callback to set the all values of a control + * from a chunk of registers. + * + * Returns 0 for success. + */ +int snd_soc_put_m1r_sx(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mreg_control *mc = + (struct soc_mreg_control *) kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned int reg = *mc->reg; + unsigned int count = mc->count; + long min = mc->min; + long max = mc->max; + unsigned int invert = mc->invert; + unsigned int idx; + long value; + + for (idx = 0; idx < count; idx++) { + value = ucontrol->value.integer.value[idx]; + if (value > max) + value = max; + else if (value < min) + value = min; + if (invert) + value = ~value; + snd_soc_write(codec, reg + idx, value); + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_put_m1r_sx); + +/** * snd_soc_dai_set_sysclk - configure DAI system or master clock. * @dai: DAI * @clk_id: DAI specific clock ID