|
@@ -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:
|