diff options
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 31a06b2b4442..30f9b5c71eee 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -40,6 +40,7 @@ #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> @@ -55,6 +56,7 @@ 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, @@ -90,6 +92,7 @@ static int dapm_down_seq[] = { [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, }; @@ -352,6 +355,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, 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: @@ -680,8 +684,13 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) 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: @@ -745,8 +754,13 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) 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) { @@ -828,6 +842,19 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, } 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) @@ -1308,6 +1335,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, } 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: @@ -1411,6 +1439,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) */ 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; @@ -1769,6 +1798,7 @@ static ssize_t dapm_widget_show(struct device *dev, 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"); @@ -2007,6 +2037,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, 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); @@ -2673,10 +2704,25 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, { 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); @@ -2722,6 +2768,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, 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: |