aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-02-28 02:31:03 -0500
committerMark Brown <broonie@linaro.org>2014-02-28 22:03:33 -0500
commit29ae2fa5533e607a7d97b7564dc015252f1e73f4 (patch)
treed0d301930177438179ffb297f15c6555e1ed694d
parent8303d769ea9e9626c4f0c3bd13e35e904a1253ab (diff)
ASoC: Consolidate enum and value enum controls
The implementations for enum and value enum controls are almost identical. The only difference is that the value enum uses an additional look-up table to map the control value to the register value, while the enum control uses a direct mapping. Enums and value enums can easily be distinguished at runtime, for value enums the values field of the snd_soc_enum struct contains the look-up table, while for enums it is NULL. This patch adds two new small helper functions called snd_soc_enum_item_to_val() and snd_soc_enum_val_to_item() which map between register value and control item. If the items field of the snd_soc_enum struct is NULL the function will do a direct mapping otherwise they'll use the look-up table to do the mapping. Using these small helper functions it is possible to use the same kcontrol handlers for both enums and value enums. The functions are added a inline functions in soc.h so they can also be used by the DAPM code to accomplish similar consolidation. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--include/sound/soc.h34
-rw-r--r--sound/soc/soc-core.c101
2 files changed, 41 insertions, 94 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 49d6c10f4612..60c700ccc518 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -195,11 +195,7 @@
195 .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \ 195 .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
196 .private_value = (unsigned long)&xenum } 196 .private_value = (unsigned long)&xenum }
197#define SOC_VALUE_ENUM(xname, xenum) \ 197#define SOC_VALUE_ENUM(xname, xenum) \
198{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ 198 SOC_ENUM(xname, xenum)
199 .info = snd_soc_info_enum_double, \
200 .get = snd_soc_get_value_enum_double, \
201 .put = snd_soc_put_value_enum_double, \
202 .private_value = (unsigned long)&xenum }
203#define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\ 199#define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
204 xhandler_get, xhandler_put) \ 200 xhandler_get, xhandler_put) \
205{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 201{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -510,10 +506,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
510 struct snd_ctl_elem_value *ucontrol); 506 struct snd_ctl_elem_value *ucontrol);
511int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, 507int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
512 struct snd_ctl_elem_value *ucontrol); 508 struct snd_ctl_elem_value *ucontrol);
513int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
514 struct snd_ctl_elem_value *ucontrol);
515int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
516 struct snd_ctl_elem_value *ucontrol);
517int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, 509int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
518 struct snd_ctl_elem_info *uinfo); 510 struct snd_ctl_elem_info *uinfo);
519#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info 511#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
@@ -1182,6 +1174,30 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
1182 return 1; 1174 return 1;
1183} 1175}
1184 1176
1177static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e,
1178 unsigned int val)
1179{
1180 unsigned int i;
1181
1182 if (!e->values)
1183 return val;
1184
1185 for (i = 0; i < e->items; i++)
1186 if (val == e->values[i])
1187 return i;
1188
1189 return 0;
1190}
1191
1192static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e,
1193 unsigned int item)
1194{
1195 if (!e->values)
1196 return item;
1197
1198 return e->values[item];
1199}
1200
1185int snd_soc_util_init(void); 1201int snd_soc_util_init(void);
1186void snd_soc_util_exit(void); 1202void snd_soc_util_exit(void);
1187 1203
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 851733897206..2ddc7a4939d2 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2596,14 +2596,18 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
2596{ 2596{
2597 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2597 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2598 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2598 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2599 unsigned int val; 2599 unsigned int val, item;
2600 unsigned int reg_val;
2600 2601
2601 val = snd_soc_read(codec, e->reg); 2602 reg_val = snd_soc_read(codec, e->reg);
2602 ucontrol->value.enumerated.item[0] 2603 val = (reg_val >> e->shift_l) & e->mask;
2603 = (val >> e->shift_l) & e->mask; 2604 item = snd_soc_enum_val_to_item(e, val);
2604 if (e->shift_l != e->shift_r) 2605 ucontrol->value.enumerated.item[0] = item;
2605 ucontrol->value.enumerated.item[1] = 2606 if (e->shift_l != e->shift_r) {
2606 (val >> e->shift_r) & e->mask; 2607 val = (reg_val >> e->shift_l) & e->mask;
2608 item = snd_soc_enum_val_to_item(e, val);
2609 ucontrol->value.enumerated.item[1] = item;
2610 }
2607 2611
2608 return 0; 2612 return 0;
2609} 2613}
@@ -2623,17 +2627,18 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
2623{ 2627{
2624 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2628 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2625 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2629 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2630 unsigned int *item = ucontrol->value.enumerated.item;
2626 unsigned int val; 2631 unsigned int val;
2627 unsigned int mask; 2632 unsigned int mask;
2628 2633
2629 if (ucontrol->value.enumerated.item[0] >= e->items) 2634 if (item[0] >= e->items)
2630 return -EINVAL; 2635 return -EINVAL;
2631 val = ucontrol->value.enumerated.item[0] << e->shift_l; 2636 val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
2632 mask = e->mask << e->shift_l; 2637 mask = e->mask << e->shift_l;
2633 if (e->shift_l != e->shift_r) { 2638 if (e->shift_l != e->shift_r) {
2634 if (ucontrol->value.enumerated.item[1] >= e->items) 2639 if (item[1] >= e->items)
2635 return -EINVAL; 2640 return -EINVAL;
2636 val |= ucontrol->value.enumerated.item[1] << e->shift_r; 2641 val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
2637 mask |= e->mask << e->shift_r; 2642 mask |= e->mask << e->shift_r;
2638 } 2643 }
2639 2644
@@ -2642,80 +2647,6 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
2642EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); 2647EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
2643 2648
2644/** 2649/**
2645 * snd_soc_get_value_enum_double - semi enumerated double mixer get callback
2646 * @kcontrol: mixer control
2647 * @ucontrol: control element information
2648 *
2649 * Callback to get the value of a double semi enumerated mixer.
2650 *
2651 * Semi enumerated mixer: the enumerated items are referred as values. Can be
2652 * used for handling bitfield coded enumeration for example.
2653 *
2654 * Returns 0 for success.
2655 */
2656int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
2657 struct snd_ctl_elem_value *ucontrol)
2658{
2659 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2660 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2661 unsigned int reg_val, val, mux;
2662
2663 reg_val = snd_soc_read(codec, e->reg);
2664 val = (reg_val >> e->shift_l) & e->mask;
2665 for (mux = 0; mux < e->items; mux++) {
2666 if (val == e->values[mux])
2667 break;
2668 }
2669 ucontrol->value.enumerated.item[0] = mux;
2670 if (e->shift_l != e->shift_r) {
2671 val = (reg_val >> e->shift_r) & e->mask;
2672 for (mux = 0; mux < e->items; mux++) {
2673 if (val == e->values[mux])
2674 break;
2675 }
2676 ucontrol->value.enumerated.item[1] = mux;
2677 }
2678
2679 return 0;
2680}
2681EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double);
2682
2683/**
2684 * snd_soc_put_value_enum_double - semi enumerated double mixer put callback
2685 * @kcontrol: mixer control
2686 * @ucontrol: control element information
2687 *
2688 * Callback to set the value of a double semi enumerated mixer.
2689 *
2690 * Semi enumerated mixer: the enumerated items are referred as values. Can be
2691 * used for handling bitfield coded enumeration for example.
2692 *
2693 * Returns 0 for success.
2694 */
2695int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
2696 struct snd_ctl_elem_value *ucontrol)
2697{
2698 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2699 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2700 unsigned int val;
2701 unsigned int mask;
2702
2703 if (ucontrol->value.enumerated.item[0] >= e->items)
2704 return -EINVAL;
2705 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
2706 mask = e->mask << e->shift_l;
2707 if (e->shift_l != e->shift_r) {
2708 if (ucontrol->value.enumerated.item[1] >= e->items)
2709 return -EINVAL;
2710 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
2711 mask |= e->mask << e->shift_r;
2712 }
2713
2714 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
2715}
2716EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
2717
2718/**
2719 * snd_soc_read_signed - Read a codec register and interprete as signed value 2650 * snd_soc_read_signed - Read a codec register and interprete as signed value
2720 * @codec: codec 2651 * @codec: codec
2721 * @reg: Register to read 2652 * @reg: Register to read