summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 89eae93445cf..c2206bc835da 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -35,6 +35,7 @@
#include <linux/debugfs.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -51,6 +52,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_clock_supply] = 1,
[snd_soc_dapm_micbias] = 2,
[snd_soc_dapm_dai_link] = 2,
[snd_soc_dapm_dai] = 3,
@@ -92,6 +94,7 @@ static int dapm_down_seq[] = {
[snd_soc_dapm_aif_out] = 10,
[snd_soc_dapm_dai] = 10,
[snd_soc_dapm_dai_link] = 11,
+ [snd_soc_dapm_clock_supply] = 12,
[snd_soc_dapm_regulator_supply] = 12,
[snd_soc_dapm_supply] = 12,
[snd_soc_dapm_post] = 13,
@@ -391,6 +394,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_vmid:
case snd_soc_dapm_supply:
case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_clock_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
case snd_soc_dapm_dai:
@@ -764,6 +768,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
switch (widget->id) {
case snd_soc_dapm_supply:
case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_clock_supply:
return 0;
default:
break;
@@ -850,6 +855,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
switch (widget->id) {
case snd_soc_dapm_supply:
case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_clock_supply:
return 0;
default:
break;
@@ -996,6 +1002,26 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
}
EXPORT_SYMBOL_GPL(dapm_regulator_event);
+/*
+ * Handler for clock supply widget.
+ */
+int dapm_clock_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (!w->clk)
+ return -EIO;
+
+#ifdef CONFIG_HAVE_CLK
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ return clk_enable(w->clk);
+ } else {
+ clk_disable(w->clk);
+ return 0;
+ }
+#endif
+}
+EXPORT_SYMBOL_GPL(dapm_clock_event);
+
static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
{
if (w->power_checked)
@@ -1487,6 +1513,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:
+ case snd_soc_dapm_clock_supply:
/* Supplies can't affect their outputs, only their inputs */
break;
default:
@@ -1587,6 +1614,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
break;
case snd_soc_dapm_supply:
case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_clock_supply:
case snd_soc_dapm_micbias:
if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1941,6 +1969,7 @@ static ssize_t dapm_widget_show(struct device *dev,
case snd_soc_dapm_mixer_named_ctl:
case snd_soc_dapm_supply:
case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_clock_supply:
if (w->name)
count += sprintf(buf + count, "%s: %s\n",
w->name, w->power ? "On":"Off");
@@ -2187,6 +2216,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
case snd_soc_dapm_post:
case snd_soc_dapm_supply:
case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_clock_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
case snd_soc_dapm_dai:
@@ -2246,15 +2276,15 @@ err:
int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_route *route, int num)
{
- int i, ret = 0;
+ int i, r, ret = 0;
mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
for (i = 0; i < num; i++) {
- ret = snd_soc_dapm_add_route(dapm, route);
- if (ret < 0) {
+ r = snd_soc_dapm_add_route(dapm, route);
+ if (r < 0) {
dev_err(dapm->dev, "Failed to add route %s->%s\n",
route->source, route->sink);
- break;
+ ret = r;
}
route++;
}
@@ -2873,6 +2903,19 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
return NULL;
}
break;
+ case snd_soc_dapm_clock_supply:
+#ifdef CONFIG_CLKDEV_LOOKUP
+ w->clk = devm_clk_get(dapm->dev, w->name);
+ if (IS_ERR(w->clk)) {
+ ret = PTR_ERR(w->clk);
+ dev_err(dapm->dev, "Failed to request %s: %d\n",
+ w->name, ret);
+ return NULL;
+ }
+#else
+ return NULL;
+#endif
+ break;
default:
break;
}
@@ -2924,6 +2967,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
break;
case snd_soc_dapm_supply:
case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_clock_supply:
w->power_check = dapm_supply_check_power;
break;
case snd_soc_dapm_dai: