ASoC: dapm: Allow regulators to bypass as well as disable when idle
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Fri, 7 Sep 2012 04:57:11 +0000 (12:57 +0800)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 26 Sep 2012 11:29:59 +0000 (12:29 +0100)
Allow regulators managed via DAPM to make use of the bypass support that
has recently been added to the regulator API by setting a flag
SND_SOC_DAPM_REGULATOR_BYPASS. When this flag is set the regulator will
be put into bypass mode before being disabled, allowing the regulator to
fall into bypass mode if it can't be disabled due to other users.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
include/sound/soc-dapm.h
sound/soc/soc-dapm.c

index c96bf5ae80a63d91a794df490b37c8b530f31e5d..e1ef63d4a5c453b17630b279d5780b32f1e722c3 100644 (file)
@@ -320,6 +320,9 @@ struct device;
 #define SND_SOC_DAPM_EVENT_OFF(e)      \
        (e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD))
 
+/* regulator widget flags */
+#define SND_SOC_DAPM_REGULATOR_BYPASS     0x1     /* bypass when disabled */
+
 struct snd_soc_dapm_widget;
 enum snd_soc_dapm_type;
 struct snd_soc_dapm_path;
index 873e6e76ee8774c854eb397e7023e374dab3f815..d0a4be38dc0f0473bdafe38d6b18ca30b11de61b 100644 (file)
@@ -1017,10 +1017,29 @@ EXPORT_SYMBOL_GPL(dapm_reg_event);
 int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event)
 {
-       if (SND_SOC_DAPM_EVENT_ON(event))
+       int ret;
+
+       if (SND_SOC_DAPM_EVENT_ON(event)) {
+               if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
+                       ret = regulator_allow_bypass(w->regulator, true);
+                       if (ret != 0)
+                               dev_warn(w->dapm->dev,
+                                        "Failed to bypass %s: %d\n",
+                                        w->name, ret);
+               }
+
                return regulator_enable(w->regulator);
-       else
+       } else {
+               if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
+                       ret = regulator_allow_bypass(w->regulator, false);
+                       if (ret != 0)
+                               dev_warn(w->dapm->dev,
+                                        "Failed to unbypass %s: %d\n",
+                                        w->name, ret);
+               }
+
                return regulator_disable_deferred(w->regulator, w->shift);
+       }
 }
 EXPORT_SYMBOL_GPL(dapm_regulator_event);