diff options
author | Peter Ujfalusi <peter.ujfalusi@nokia.com> | 2009-01-05 09:54:57 +0200 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-01-05 17:47:17 +0000 |
commit | 2e72f8e3716bc3bbf4c9b5b987fb5ab3223f60bf (patch) | |
tree | f568500ae1737e5c11376ad9b65d706c9da18874 /sound/soc/soc-core.c | |
parent | 796123368871e4a838dc0dfd5dbc3cd8981ef429 (diff) |
ASoC: New enum type: value_enum
This patch introduces a new enum type.
In this enum type each enumerated items referred with a value.
This new enum type can handle enums encoded in bitfield, or any other
weird ways. twl4030 codec has several mux selection register, where the
input/output mux is coded in a bitfield. With the normal enum type this type
of mux can not be handled in a clean way.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f73c1341437c..6cbe7e82f238 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1585,6 +1585,113 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); /** + * snd_soc_info_value_enum_double - semi enumerated double mixer info callback + * @kcontrol: mixer control + * @uinfo: control element information + * + * Callback to provide information about a double semi enumerated + * mixer control. + * + * Semi enumerated mixer: the enumerated items are referred as values. Can be + * used for handling bitfield coded enumeration for example. + * + * Returns 0 for success. + */ +int snd_soc_info_value_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_value_enum *e = (struct soc_value_enum *) + kcontrol->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = e->shift_l == e->shift_r ? 1 : 2; + uinfo->value.enumerated.items = e->max; + + if (uinfo->value.enumerated.item > e->max - 1) + uinfo->value.enumerated.item = e->max - 1; + strcpy(uinfo->value.enumerated.name, + e->texts[uinfo->value.enumerated.item]); + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_info_value_enum_double); + +/** + * snd_soc_get_value_enum_double - semi enumerated double mixer get callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value of a double semi enumerated mixer. + * + * Semi enumerated mixer: the enumerated items are referred as values. Can be + * used for handling bitfield coded enumeration for example. + * + * Returns 0 for success. + */ +int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_value_enum *e = (struct soc_value_enum *) + kcontrol->private_value; + unsigned short reg_val, val, mux; + + reg_val = snd_soc_read(codec, e->reg); + val = (reg_val >> e->shift_l) & e->mask; + for (mux = 0; mux < e->max; mux++) { + if (val == e->values[mux]) + break; + } + ucontrol->value.enumerated.item[0] = mux; + if (e->shift_l != e->shift_r) { + val = (reg_val >> e->shift_r) & e->mask; + for (mux = 0; mux < e->max; mux++) { + if (val == e->values[mux]) + break; + } + ucontrol->value.enumerated.item[1] = mux; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double); + +/** + * snd_soc_put_value_enum_double - semi enumerated double mixer put callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to set the value of a double semi enumerated mixer. + * + * Semi enumerated mixer: the enumerated items are referred as values. Can be + * used for handling bitfield coded enumeration for example. + * + * Returns 0 for success. + */ +int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_value_enum *e = (struct soc_value_enum *) + kcontrol->private_value; + unsigned short val; + unsigned short mask; + + if (ucontrol->value.enumerated.item[0] > e->max - 1) + return -EINVAL; + val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; + mask = e->mask << e->shift_l; + if (e->shift_l != e->shift_r) { + if (ucontrol->value.enumerated.item[1] > e->max - 1) + return -EINVAL; + val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; + mask |= e->mask << e->shift_r; + } + + return snd_soc_update_bits(codec, e->reg, mask, val); +} +EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); + +/** * snd_soc_info_enum_ext - external enumerated single mixer info callback * @kcontrol: mixer control * @uinfo: control element information |