{      .id = snd_soc_dapm_supply, .name = wname, .reg = wreg,  \
        .shift = wshift, .invert = winvert, .event = wevent, \
        .event_flags = wflags}
+#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay) \
+{      .id = snd_soc_dapm_regulator_supply, .name = wname, \
+       .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
+       .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
 
 /* dapm kcontrol types */
 #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
 
 int dapm_reg_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event);
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol, int event);
 
 /* dapm controls */
 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
        snd_soc_dapm_pre,                       /* machine specific pre widget - exec first */
        snd_soc_dapm_post,                      /* machine specific post widget - exec last */
        snd_soc_dapm_supply,            /* power/clock supply */
+       snd_soc_dapm_regulator_supply,  /* external regulator */
        snd_soc_dapm_aif_in,            /* audio interface input */
        snd_soc_dapm_aif_out,           /* audio interface output */
        snd_soc_dapm_siggen,            /* signal generator */
        struct list_head list;
        struct snd_soc_dapm_context *dapm;
 
+       void *priv;                             /* widget specific data */
+
        /* dapm control */
        short reg;                                              /* negative reg = no direct dapm */
        unsigned char shift;                    /* bits to shift */
 
 #include <linux/jiffies.h>
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 static int dapm_up_seq[] = {
        [snd_soc_dapm_pre] = 0,
        [snd_soc_dapm_supply] = 1,
+       [snd_soc_dapm_regulator_supply] = 1,
        [snd_soc_dapm_micbias] = 2,
        [snd_soc_dapm_aif_in] = 3,
        [snd_soc_dapm_aif_out] = 3,
        [snd_soc_dapm_value_mux] = 9,
        [snd_soc_dapm_aif_in] = 10,
        [snd_soc_dapm_aif_out] = 10,
+       [snd_soc_dapm_regulator_supply] = 11,
        [snd_soc_dapm_supply] = 11,
        [snd_soc_dapm_post] = 12,
 };
        case snd_soc_dapm_micbias:
        case snd_soc_dapm_vmid:
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
        case snd_soc_dapm_aif_in:
        case snd_soc_dapm_aif_out:
        case snd_soc_dapm_hp:
 
        DAPM_UPDATE_STAT(widget, path_checks);
 
-       if (widget->id == snd_soc_dapm_supply)
+       switch (widget->id) {
+       case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                return 0;
+       default:
+               break;
+       }
 
        switch (widget->id) {
        case snd_soc_dapm_adc:
 
        DAPM_UPDATE_STAT(widget, path_checks);
 
-       if (widget->id == snd_soc_dapm_supply)
+       switch (widget->id) {
+       case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                return 0;
+       default:
+               break;
+       }
 
        /* active stream ? */
        switch (widget->id) {
 }
 EXPORT_SYMBOL_GPL(dapm_reg_event);
 
+/*
+ * Handler for regulator supply widget.
+ */
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               return regulator_enable(w->priv);
+       else
+               return regulator_disable_deferred(w->priv, w->shift);
+}
+EXPORT_SYMBOL_GPL(dapm_regulator_event);
+
 static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
 {
        if (w->power_checked)
        }
        switch (w->id) {
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                /* Supplies can't affect their outputs, only their inputs */
                break;
        default:
                         */
                        switch (w->id) {
                        case snd_soc_dapm_supply:
+                       case snd_soc_dapm_regulator_supply:
                        case snd_soc_dapm_micbias:
                                if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
                                        d->target_bias_level = SND_SOC_BIAS_STANDBY;
                case snd_soc_dapm_mixer:
                case snd_soc_dapm_mixer_named_ctl:
                case snd_soc_dapm_supply:
+               case snd_soc_dapm_regulator_supply:
                        if (w->name)
                                count += sprintf(buf + count, "%s: %s\n",
                                        w->name, w->power ? "On":"Off");
        case snd_soc_dapm_pre:
        case snd_soc_dapm_post:
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
        case snd_soc_dapm_aif_in:
        case snd_soc_dapm_aif_out:
                list_add(&path->list, &dapm->card->paths);
 {
        struct snd_soc_dapm_widget *w;
        size_t name_len;
+       int ret;
 
        if ((w = dapm_cnew_widget(widget)) == NULL)
                return -ENOMEM;
 
+       switch (w->id) {
+       case snd_soc_dapm_regulator_supply:
+               w->priv = devm_regulator_get(dapm->dev, w->name);
+               if (IS_ERR(w->priv)) {
+                       ret = PTR_ERR(w->priv);
+                       dev_err(dapm->dev, "Failed to request %s: %d\n",
+                               w->name, ret);
+                       return ret;
+               }
+               break;
+       default:
+               break;
+       }
+
        name_len = strlen(widget->name) + 1;
        if (dapm->codec && dapm->codec->name_prefix)
                name_len += 1 + strlen(dapm->codec->name_prefix);
                w->power_check = dapm_generic_check_power;
                break;
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                w->power_check = dapm_supply_check_power;
                break;
        default: