Merge remote-tracking branches 'asoc/topic/sirf-audio', 'asoc/topic/sn95031', 'asoc...
[linux-2.6-block.git] / sound / soc / soc-dapm.c
index 92894d9cac19d54d835b6611c013b0ea527403a8..2d9709104ec55e026322f50d58d52b41a0bba4be 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -72,6 +73,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
 static int dapm_up_seq[] = {
        [snd_soc_dapm_pre] = 0,
        [snd_soc_dapm_regulator_supply] = 1,
+       [snd_soc_dapm_pinctrl] = 1,
        [snd_soc_dapm_clock_supply] = 1,
        [snd_soc_dapm_supply] = 2,
        [snd_soc_dapm_micbias] = 3,
@@ -121,6 +123,7 @@ static int dapm_down_seq[] = {
        [snd_soc_dapm_dai_link] = 11,
        [snd_soc_dapm_supply] = 12,
        [snd_soc_dapm_clock_supply] = 13,
+       [snd_soc_dapm_pinctrl] = 13,
        [snd_soc_dapm_regulator_supply] = 13,
        [snd_soc_dapm_post] = 14,
 };
@@ -1289,6 +1292,31 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
 }
 EXPORT_SYMBOL_GPL(dapm_regulator_event);
 
+/*
+ * Handler for pinctrl widget.
+ */
+int dapm_pinctrl_event(struct snd_soc_dapm_widget *w,
+                      struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_dapm_pinctrl_priv *priv = w->priv;
+       struct pinctrl *p = w->pinctrl;
+       struct pinctrl_state *s;
+
+       if (!p || !priv)
+               return -EIO;
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               s = pinctrl_lookup_state(p, priv->active_state);
+       else
+               s = pinctrl_lookup_state(p, priv->sleep_state);
+
+       if (IS_ERR(s))
+               return PTR_ERR(s);
+
+       return pinctrl_select_state(p, s);
+}
+EXPORT_SYMBOL_GPL(dapm_pinctrl_event);
+
 /*
  * Handler for clock supply widget.
  */
@@ -1902,6 +1930,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
                                break;
                        case snd_soc_dapm_supply:
                        case snd_soc_dapm_regulator_supply:
+                       case snd_soc_dapm_pinctrl:
                        case snd_soc_dapm_clock_supply:
                        case snd_soc_dapm_micbias:
                                if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
@@ -2315,6 +2344,7 @@ static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt,
                case snd_soc_dapm_mixer_named_ctl:
                case snd_soc_dapm_supply:
                case snd_soc_dapm_regulator_supply:
+               case snd_soc_dapm_pinctrl:
                case snd_soc_dapm_clock_supply:
                        if (w->name)
                                count += sprintf(buf + count, "%s: %s\n",
@@ -3165,7 +3195,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
        unsigned int invert = mc->invert;
        unsigned int val, rval = 0;
        int connect, rconnect = -1, change, reg_change = 0;
-       struct snd_soc_dapm_update update = { NULL };
+       struct snd_soc_dapm_update update = {};
        int ret = 0;
 
        val = (ucontrol->value.integer.value[0] & mask);
@@ -3292,7 +3322,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
        unsigned int *item = ucontrol->value.enumerated.item;
        unsigned int val, change, reg_change = 0;
        unsigned int mask;
-       struct snd_soc_dapm_update update = { NULL };
+       struct snd_soc_dapm_update update = {};
        int ret = 0;
 
        if (item[0] >= e->items)
@@ -3464,6 +3494,17 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
                                         w->name, ret);
                }
                break;
+       case snd_soc_dapm_pinctrl:
+               w->pinctrl = devm_pinctrl_get(dapm->dev);
+               if (IS_ERR_OR_NULL(w->pinctrl)) {
+                       ret = PTR_ERR(w->pinctrl);
+                       if (ret == -EPROBE_DEFER)
+                               return ERR_PTR(ret);
+                       dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
+                               w->name, ret);
+                       return NULL;
+               }
+               break;
        case snd_soc_dapm_clock_supply:
 #ifdef CONFIG_CLKDEV_LOOKUP
                w->clk = devm_clk_get(dapm->dev, w->name);
@@ -3543,6 +3584,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
                break;
        case snd_soc_dapm_supply:
        case snd_soc_dapm_regulator_supply:
+       case snd_soc_dapm_pinctrl:
        case snd_soc_dapm_clock_supply:
        case snd_soc_dapm_kcontrol:
                w->is_supply = 1;