.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
        .private_value = (unsigned long)&xenum }
 #define SOC_VALUE_ENUM(xname, xenum) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
-       .info = snd_soc_info_enum_double, \
-       .get = snd_soc_get_value_enum_double, \
-       .put = snd_soc_put_value_enum_double, \
-       .private_value = (unsigned long)&xenum }
+       SOC_ENUM(xname, xenum)
 #define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
         xhandler_get, xhandler_put) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
-int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol);
-int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol);
 int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo);
 #define snd_soc_info_bool_ext          snd_ctl_boolean_mono_info
        return 1;
 }
 
+static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e,
+       unsigned int val)
+{
+       unsigned int i;
+
+       if (!e->values)
+               return val;
+
+       for (i = 0; i < e->items; i++)
+               if (val == e->values[i])
+                       return i;
+
+       return 0;
+}
+
+static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e,
+       unsigned int item)
+{
+       if (!e->values)
+               return item;
+
+       return e->values[item];
+}
+
 int snd_soc_util_init(void);
 void snd_soc_util_exit(void);
 
 
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned int val;
+       unsigned int val, item;
+       unsigned int reg_val;
 
-       val = snd_soc_read(codec, e->reg);
-       ucontrol->value.enumerated.item[0]
-               = (val >> e->shift_l) & e->mask;
-       if (e->shift_l != e->shift_r)
-               ucontrol->value.enumerated.item[1] =
-                       (val >> e->shift_r) & e->mask;
+       reg_val = snd_soc_read(codec, e->reg);
+       val = (reg_val >> e->shift_l) & e->mask;
+       item = snd_soc_enum_val_to_item(e, val);
+       ucontrol->value.enumerated.item[0] = item;
+       if (e->shift_l != e->shift_r) {
+               val = (reg_val >> e->shift_l) & e->mask;
+               item = snd_soc_enum_val_to_item(e, val);
+               ucontrol->value.enumerated.item[1] = item;
+       }
 
        return 0;
 }
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       unsigned int *item = ucontrol->value.enumerated.item;
        unsigned int val;
        unsigned int mask;
 
-       if (ucontrol->value.enumerated.item[0] >= e->items)
+       if (item[0] >= e->items)
                return -EINVAL;
-       val = ucontrol->value.enumerated.item[0] << e->shift_l;
+       val = snd_soc_enum_item_to_val(e, 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->items)
+               if (item[1] >= e->items)
                        return -EINVAL;
-               val |= ucontrol->value.enumerated.item[1] << e->shift_r;
+               val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
                mask |= e->mask << e->shift_r;
        }
 
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_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_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned int 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->items; 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->items; 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_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned int val;
-       unsigned int mask;
-
-       if (ucontrol->value.enumerated.item[0] >= e->items)
-               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->items)
-                       return -EINVAL;
-               val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
-               mask |= e->mask << e->shift_r;
-       }
-
-       return snd_soc_update_bits_locked(codec, e->reg, mask, val);
-}
-EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
-
 /**
  * snd_soc_read_signed - Read a codec register and interprete as signed value
  * @codec: codec