aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-02-28 02:31:04 -0500
committerMark Brown <broonie@linaro.org>2014-02-28 22:03:34 -0500
commit3727b4968453dbab8fe18f979d67285eb6b66801 (patch)
tree65ea329261a29bd380b29fd24167a80375779a05
parent29ae2fa5533e607a7d97b7564dc015252f1e73f4 (diff)
ASoC: dapm: Consolidate MUXs and value MUXs
MUXs and value MUXs are almost identical, the only difference is that a value MUX uses a look-up table to map from the selected control item to a register value, while MUXs use a direct mapping. This patch uses snd_soc_enum_item_to_val() and snd_soc_enum_val_to_item(), which where earlier introduced during the consolidation of enum and value enum controls, to hide this difference. This allows us to use the same code path for both MUXs and value MUXs and a lot of nearly duplicated code can be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--include/sound/soc-dapm.h15
-rw-r--r--sound/soc/soc-dapm.c157
2 files changed, 21 insertions, 151 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 3b991766a8f2..2ec14cb3ff1e 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -112,9 +112,7 @@ struct device;
112 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ 112 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
113 .kcontrol_news = wcontrols, .num_kcontrols = 1} 113 .kcontrol_news = wcontrols, .num_kcontrols = 1}
114#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ 114#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
115{ .id = snd_soc_dapm_value_mux, .name = wname, \ 115 SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols)
116 SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
117 .kcontrol_news = wcontrols, .num_kcontrols = 1}
118 116
119/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ 117/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
120#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ 118#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
@@ -324,11 +322,7 @@ struct device;
324 .put = xput, \ 322 .put = xput, \
325 .private_value = (unsigned long)&xenum } 323 .private_value = (unsigned long)&xenum }
326#define SOC_DAPM_VALUE_ENUM(xname, xenum) \ 324#define SOC_DAPM_VALUE_ENUM(xname, xenum) \
327{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 325 SOC_DAPM_ENUM(xname, xenum)
328 .info = snd_soc_info_enum_double, \
329 .get = snd_soc_dapm_get_value_enum_double, \
330 .put = snd_soc_dapm_put_value_enum_double, \
331 .private_value = (unsigned long)&xenum }
332#define SOC_DAPM_PIN_SWITCH(xname) \ 326#define SOC_DAPM_PIN_SWITCH(xname) \
333{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \ 327{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \
334 .info = snd_soc_dapm_info_pin_switch, \ 328 .info = snd_soc_dapm_info_pin_switch, \
@@ -396,10 +390,6 @@ int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
396 struct snd_ctl_elem_value *ucontrol); 390 struct snd_ctl_elem_value *ucontrol);
397int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, 391int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
398 struct snd_ctl_elem_value *ucontrol); 392 struct snd_ctl_elem_value *ucontrol);
399int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
400 struct snd_ctl_elem_value *ucontrol);
401int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
402 struct snd_ctl_elem_value *ucontrol);
403int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, 393int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
404 struct snd_ctl_elem_info *uinfo); 394 struct snd_ctl_elem_info *uinfo);
405int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, 395int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
@@ -486,7 +476,6 @@ enum snd_soc_dapm_type {
486 snd_soc_dapm_output, /* output pin */ 476 snd_soc_dapm_output, /* output pin */
487 snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ 477 snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */
488 snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */ 478 snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */
489 snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */
490 snd_soc_dapm_mixer, /* mixes several analog signals together */ 479 snd_soc_dapm_mixer, /* mixes several analog signals together */
491 snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ 480 snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */
492 snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ 481 snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 96a97a3dfb68..f23eeeeaafc5 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -71,7 +71,6 @@ static int dapm_up_seq[] = {
71 [snd_soc_dapm_mic] = 5, 71 [snd_soc_dapm_mic] = 5,
72 [snd_soc_dapm_mux] = 6, 72 [snd_soc_dapm_mux] = 6,
73 [snd_soc_dapm_virt_mux] = 6, 73 [snd_soc_dapm_virt_mux] = 6,
74 [snd_soc_dapm_value_mux] = 6,
75 [snd_soc_dapm_dac] = 7, 74 [snd_soc_dapm_dac] = 7,
76 [snd_soc_dapm_switch] = 8, 75 [snd_soc_dapm_switch] = 8,
77 [snd_soc_dapm_mixer] = 8, 76 [snd_soc_dapm_mixer] = 8,
@@ -103,7 +102,6 @@ static int dapm_down_seq[] = {
103 [snd_soc_dapm_micbias] = 8, 102 [snd_soc_dapm_micbias] = 8,
104 [snd_soc_dapm_mux] = 9, 103 [snd_soc_dapm_mux] = 9,
105 [snd_soc_dapm_virt_mux] = 9, 104 [snd_soc_dapm_virt_mux] = 9,
106 [snd_soc_dapm_value_mux] = 9,
107 [snd_soc_dapm_aif_in] = 10, 105 [snd_soc_dapm_aif_in] = 10,
108 [snd_soc_dapm_aif_out] = 10, 106 [snd_soc_dapm_aif_out] = 10,
109 [snd_soc_dapm_dai_in] = 10, 107 [snd_soc_dapm_dai_in] = 10,
@@ -534,7 +532,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
534 unsigned int val, item; 532 unsigned int val, item;
535 533
536 soc_widget_read(w, e->reg, &val); 534 soc_widget_read(w, e->reg, &val);
537 item = (val >> e->shift_l) & e->mask; 535 val = (val >> e->shift_l) & e->mask;
536 item = snd_soc_enum_val_to_item(e, val);
538 537
539 if (item < e->items && !strcmp(p->name, e->texts[item])) 538 if (item < e->items && !strcmp(p->name, e->texts[item]))
540 p->connect = 1; 539 p->connect = 1;
@@ -557,24 +556,6 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
557 p->connect = 1; 556 p->connect = 1;
558 } 557 }
559 break; 558 break;
560 case snd_soc_dapm_value_mux: {
561 struct soc_enum *e = (struct soc_enum *)
562 w->kcontrol_news[i].private_value;
563 unsigned int val, item;
564
565 soc_widget_read(w, e->reg, &val);
566 val = (val >> e->shift_l) & e->mask;
567 for (item = 0; item < e->items; item++) {
568 if (val == e->values[item])
569 break;
570 }
571
572 if (item < e->items && !strcmp(p->name, e->texts[item]))
573 p->connect = 1;
574 else
575 p->connect = 0;
576 }
577 break;
578 /* does not affect routing - always connected */ 559 /* does not affect routing - always connected */
579 case snd_soc_dapm_pga: 560 case snd_soc_dapm_pga:
580 case snd_soc_dapm_out_drv: 561 case snd_soc_dapm_out_drv:
@@ -725,7 +706,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
725 break; 706 break;
726 case snd_soc_dapm_mux: 707 case snd_soc_dapm_mux:
727 case snd_soc_dapm_virt_mux: 708 case snd_soc_dapm_virt_mux:
728 case snd_soc_dapm_value_mux:
729 wname_in_long_name = true; 709 wname_in_long_name = true;
730 kcname_in_long_name = false; 710 kcname_in_long_name = false;
731 break; 711 break;
@@ -2463,7 +2443,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
2463 return 0; 2443 return 0;
2464 case snd_soc_dapm_mux: 2444 case snd_soc_dapm_mux:
2465 case snd_soc_dapm_virt_mux: 2445 case snd_soc_dapm_virt_mux:
2466 case snd_soc_dapm_value_mux:
2467 ret = dapm_connect_mux(dapm, wsource, wsink, path, control, 2446 ret = dapm_connect_mux(dapm, wsource, wsink, path, control,
2468 &wsink->kcontrol_news[0]); 2447 &wsink->kcontrol_news[0]);
2469 if (ret != 0) 2448 if (ret != 0)
@@ -2791,7 +2770,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
2791 break; 2770 break;
2792 case snd_soc_dapm_mux: 2771 case snd_soc_dapm_mux:
2793 case snd_soc_dapm_virt_mux: 2772 case snd_soc_dapm_virt_mux:
2794 case snd_soc_dapm_value_mux:
2795 dapm_new_mux(w); 2773 dapm_new_mux(w);
2796 break; 2774 break;
2797 case snd_soc_dapm_pga: 2775 case snd_soc_dapm_pga:
@@ -2953,13 +2931,16 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
2953{ 2931{
2954 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); 2932 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2955 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2933 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2956 unsigned int val; 2934 unsigned int reg_val, val;
2957 2935
2958 val = snd_soc_read(codec, e->reg); 2936 reg_val = snd_soc_read(codec, e->reg);
2959 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; 2937 val = (reg_val >> e->shift_l) & e->mask;
2960 if (e->shift_l != e->shift_r) 2938 ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
2961 ucontrol->value.enumerated.item[1] = 2939 if (e->shift_l != e->shift_r) {
2962 (val >> e->shift_r) & e->mask; 2940 val = (reg_val >> e->shift_r) & e->mask;
2941 val = snd_soc_enum_val_to_item(e, val);
2942 ucontrol->value.enumerated.item[1] = val;
2943 }
2963 2944
2964 return 0; 2945 return 0;
2965} 2946}
@@ -2980,20 +2961,21 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
2980 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); 2961 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
2981 struct snd_soc_card *card = codec->card; 2962 struct snd_soc_card *card = codec->card;
2982 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 2963 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2983 unsigned int val, mux, change; 2964 unsigned int *item = ucontrol->value.enumerated.item;
2965 unsigned int val, change;
2984 unsigned int mask; 2966 unsigned int mask;
2985 struct snd_soc_dapm_update update; 2967 struct snd_soc_dapm_update update;
2986 int ret = 0; 2968 int ret = 0;
2987 2969
2988 if (ucontrol->value.enumerated.item[0] >= e->items) 2970 if (item[0] >= e->items)
2989 return -EINVAL; 2971 return -EINVAL;
2990 mux = ucontrol->value.enumerated.item[0]; 2972
2991 val = mux << e->shift_l; 2973 val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
2992 mask = e->mask << e->shift_l; 2974 mask = e->mask << e->shift_l;
2993 if (e->shift_l != e->shift_r) { 2975 if (e->shift_l != e->shift_r) {
2994 if (ucontrol->value.enumerated.item[1] >= e->items) 2976 if (item[1] > e->items)
2995 return -EINVAL; 2977 return -EINVAL;
2996 val |= ucontrol->value.enumerated.item[1] << e->shift_r; 2978 val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l;
2997 mask |= e->mask << e->shift_r; 2979 mask |= e->mask << e->shift_r;
2998 } 2980 }
2999 2981
@@ -3007,7 +2989,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
3007 update.val = val; 2989 update.val = val;
3008 card->update = &update; 2990 card->update = &update;
3009 2991
3010 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); 2992 ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
3011 2993
3012 card->update = NULL; 2994 card->update = NULL;
3013 } 2995 }
@@ -3074,106 +3056,6 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
3074EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); 3056EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
3075 3057
3076/** 3058/**
3077 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
3078 * callback
3079 * @kcontrol: mixer control
3080 * @ucontrol: control element information
3081 *
3082 * Callback to get the value of a dapm semi enumerated double mixer control.
3083 *
3084 * Semi enumerated mixer: the enumerated items are referred as values. Can be
3085 * used for handling bitfield coded enumeration for example.
3086 *
3087 * Returns 0 for success.
3088 */
3089int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
3090 struct snd_ctl_elem_value *ucontrol)
3091{
3092 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
3093 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
3094 unsigned int reg_val, val, mux;
3095
3096 reg_val = snd_soc_read(codec, e->reg);
3097 val = (reg_val >> e->shift_l) & e->mask;
3098 for (mux = 0; mux < e->items; mux++) {
3099 if (val == e->values[mux])
3100 break;
3101 }
3102 ucontrol->value.enumerated.item[0] = mux;
3103 if (e->shift_l != e->shift_r) {
3104 val = (reg_val >> e->shift_r) & e->mask;
3105 for (mux = 0; mux < e->items; mux++) {
3106 if (val == e->values[mux])
3107 break;
3108 }
3109 ucontrol->value.enumerated.item[1] = mux;
3110 }
3111
3112 return 0;
3113}
3114EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
3115
3116/**
3117 * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set
3118 * callback
3119 * @kcontrol: mixer control
3120 * @ucontrol: control element information
3121 *
3122 * Callback to set the value of a dapm semi enumerated double mixer control.
3123 *
3124 * Semi enumerated mixer: the enumerated items are referred as values. Can be
3125 * used for handling bitfield coded enumeration for example.
3126 *
3127 * Returns 0 for success.
3128 */
3129int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
3130 struct snd_ctl_elem_value *ucontrol)
3131{
3132 struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
3133 struct snd_soc_card *card = codec->card;
3134 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
3135 unsigned int val, mux, change;
3136 unsigned int mask;
3137 struct snd_soc_dapm_update update;
3138 int ret = 0;
3139
3140 if (ucontrol->value.enumerated.item[0] >= e->items)
3141 return -EINVAL;
3142 mux = ucontrol->value.enumerated.item[0];
3143 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
3144 mask = e->mask << e->shift_l;
3145 if (e->shift_l != e->shift_r) {
3146 if (ucontrol->value.enumerated.item[1] >= e->items)
3147 return -EINVAL;
3148 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
3149 mask |= e->mask << e->shift_r;
3150 }
3151
3152 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3153
3154 change = snd_soc_test_bits(codec, e->reg, mask, val);
3155 if (change) {
3156 update.kcontrol = kcontrol;
3157 update.reg = e->reg;
3158 update.mask = mask;
3159 update.val = val;
3160 card->update = &update;
3161
3162 ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
3163
3164 card->update = NULL;
3165 }
3166
3167 mutex_unlock(&card->dapm_mutex);
3168
3169 if (ret > 0)
3170 soc_dpcm_runtime_update(card);
3171
3172 return change;
3173}
3174EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
3175
3176/**
3177 * snd_soc_dapm_info_pin_switch - Info for a pin switch 3059 * snd_soc_dapm_info_pin_switch - Info for a pin switch
3178 * 3060 *
3179 * @kcontrol: mixer control 3061 * @kcontrol: mixer control
@@ -3302,7 +3184,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3302 break; 3184 break;
3303 case snd_soc_dapm_mux: 3185 case snd_soc_dapm_mux:
3304 case snd_soc_dapm_virt_mux: 3186 case snd_soc_dapm_virt_mux:
3305 case snd_soc_dapm_value_mux:
3306 w->power_check = dapm_generic_check_power; 3187 w->power_check = dapm_generic_check_power;
3307 break; 3188 break;
3308 case snd_soc_dapm_dai_out: 3189 case snd_soc_dapm_dai_out: