aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-dapm.h10
-rw-r--r--sound/soc/soc-dapm.c38
2 files changed, 48 insertions, 0 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index e3833d9f1914..05559e571d44 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -229,6 +229,10 @@ struct device;
229{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ 229{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
230 .shift = wshift, .invert = winvert, \ 230 .shift = wshift, .invert = winvert, \
231 .event = wevent, .event_flags = wflags} 231 .event = wevent, .event_flags = wflags}
232#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
233{ .id = snd_soc_dapm_clock_supply, .name = wname, \
234 .reg = SND_SOC_NOPM, .event = dapm_clock_event, \
235 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
232 236
233/* generic widgets */ 237/* generic widgets */
234#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ 238#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \
@@ -245,6 +249,7 @@ struct device;
245 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ 249 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
246 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } 250 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
247 251
252
248/* dapm kcontrol types */ 253/* dapm kcontrol types */
249#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ 254#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
250{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 255{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -327,6 +332,8 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
327 struct snd_kcontrol *kcontrol, int event); 332 struct snd_kcontrol *kcontrol, int event);
328int dapm_regulator_event(struct snd_soc_dapm_widget *w, 333int dapm_regulator_event(struct snd_soc_dapm_widget *w,
329 struct snd_kcontrol *kcontrol, int event); 334 struct snd_kcontrol *kcontrol, int event);
335int dapm_clock_event(struct snd_soc_dapm_widget *w,
336 struct snd_kcontrol *kcontrol, int event);
330 337
331/* dapm controls */ 338/* dapm controls */
332int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, 339int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
@@ -432,6 +439,7 @@ enum snd_soc_dapm_type {
432 snd_soc_dapm_post, /* machine specific post widget - exec last */ 439 snd_soc_dapm_post, /* machine specific post widget - exec last */
433 snd_soc_dapm_supply, /* power/clock supply */ 440 snd_soc_dapm_supply, /* power/clock supply */
434 snd_soc_dapm_regulator_supply, /* external regulator */ 441 snd_soc_dapm_regulator_supply, /* external regulator */
442 snd_soc_dapm_clock_supply, /* external clock */
435 snd_soc_dapm_aif_in, /* audio interface input */ 443 snd_soc_dapm_aif_in, /* audio interface input */
436 snd_soc_dapm_aif_out, /* audio interface output */ 444 snd_soc_dapm_aif_out, /* audio interface output */
437 snd_soc_dapm_siggen, /* signal generator */ 445 snd_soc_dapm_siggen, /* signal generator */
@@ -537,6 +545,8 @@ struct snd_soc_dapm_widget {
537 struct list_head dirty; 545 struct list_head dirty;
538 int inputs; 546 int inputs;
539 int outputs; 547 int outputs;
548
549 struct clk *clk;
540}; 550};
541 551
542struct snd_soc_dapm_update { 552struct snd_soc_dapm_update {
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 90ee77d2409d..3bb7a6f058d0 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -35,6 +35,7 @@
35#include <linux/debugfs.h> 35#include <linux/debugfs.h>
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37#include <linux/regulator/consumer.h> 37#include <linux/regulator/consumer.h>
38#include <linux/clk.h>
38#include <linux/slab.h> 39#include <linux/slab.h>
39#include <sound/core.h> 40#include <sound/core.h>
40#include <sound/pcm.h> 41#include <sound/pcm.h>
@@ -51,6 +52,7 @@ static int dapm_up_seq[] = {
51 [snd_soc_dapm_pre] = 0, 52 [snd_soc_dapm_pre] = 0,
52 [snd_soc_dapm_supply] = 1, 53 [snd_soc_dapm_supply] = 1,
53 [snd_soc_dapm_regulator_supply] = 1, 54 [snd_soc_dapm_regulator_supply] = 1,
55 [snd_soc_dapm_clock_supply] = 1,
54 [snd_soc_dapm_micbias] = 2, 56 [snd_soc_dapm_micbias] = 2,
55 [snd_soc_dapm_dai_link] = 2, 57 [snd_soc_dapm_dai_link] = 2,
56 [snd_soc_dapm_dai] = 3, 58 [snd_soc_dapm_dai] = 3,
@@ -92,6 +94,7 @@ static int dapm_down_seq[] = {
92 [snd_soc_dapm_aif_out] = 10, 94 [snd_soc_dapm_aif_out] = 10,
93 [snd_soc_dapm_dai] = 10, 95 [snd_soc_dapm_dai] = 10,
94 [snd_soc_dapm_dai_link] = 11, 96 [snd_soc_dapm_dai_link] = 11,
97 [snd_soc_dapm_clock_supply] = 12,
95 [snd_soc_dapm_regulator_supply] = 12, 98 [snd_soc_dapm_regulator_supply] = 12,
96 [snd_soc_dapm_supply] = 12, 99 [snd_soc_dapm_supply] = 12,
97 [snd_soc_dapm_post] = 13, 100 [snd_soc_dapm_post] = 13,
@@ -391,6 +394,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
391 case snd_soc_dapm_vmid: 394 case snd_soc_dapm_vmid:
392 case snd_soc_dapm_supply: 395 case snd_soc_dapm_supply:
393 case snd_soc_dapm_regulator_supply: 396 case snd_soc_dapm_regulator_supply:
397 case snd_soc_dapm_clock_supply:
394 case snd_soc_dapm_aif_in: 398 case snd_soc_dapm_aif_in:
395 case snd_soc_dapm_aif_out: 399 case snd_soc_dapm_aif_out:
396 case snd_soc_dapm_dai: 400 case snd_soc_dapm_dai:
@@ -764,6 +768,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
764 switch (widget->id) { 768 switch (widget->id) {
765 case snd_soc_dapm_supply: 769 case snd_soc_dapm_supply:
766 case snd_soc_dapm_regulator_supply: 770 case snd_soc_dapm_regulator_supply:
771 case snd_soc_dapm_clock_supply:
767 return 0; 772 return 0;
768 default: 773 default:
769 break; 774 break;
@@ -850,6 +855,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
850 switch (widget->id) { 855 switch (widget->id) {
851 case snd_soc_dapm_supply: 856 case snd_soc_dapm_supply:
852 case snd_soc_dapm_regulator_supply: 857 case snd_soc_dapm_regulator_supply:
858 case snd_soc_dapm_clock_supply:
853 return 0; 859 return 0;
854 default: 860 default:
855 break; 861 break;
@@ -996,6 +1002,24 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
996} 1002}
997EXPORT_SYMBOL_GPL(dapm_regulator_event); 1003EXPORT_SYMBOL_GPL(dapm_regulator_event);
998 1004
1005/*
1006 * Handler for clock supply widget.
1007 */
1008int dapm_clock_event(struct snd_soc_dapm_widget *w,
1009 struct snd_kcontrol *kcontrol, int event)
1010{
1011 if (!w->clk)
1012 return -EIO;
1013
1014 if (SND_SOC_DAPM_EVENT_ON(event)) {
1015 return clk_enable(w->clk);
1016 } else {
1017 clk_disable(w->clk);
1018 return 0;
1019 }
1020}
1021EXPORT_SYMBOL_GPL(dapm_clock_event);
1022
999static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) 1023static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
1000{ 1024{
1001 if (w->power_checked) 1025 if (w->power_checked)
@@ -1487,6 +1511,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1487 switch (w->id) { 1511 switch (w->id) {
1488 case snd_soc_dapm_supply: 1512 case snd_soc_dapm_supply:
1489 case snd_soc_dapm_regulator_supply: 1513 case snd_soc_dapm_regulator_supply:
1514 case snd_soc_dapm_clock_supply:
1490 /* Supplies can't affect their outputs, only their inputs */ 1515 /* Supplies can't affect their outputs, only their inputs */
1491 break; 1516 break;
1492 default: 1517 default:
@@ -1587,6 +1612,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1587 break; 1612 break;
1588 case snd_soc_dapm_supply: 1613 case snd_soc_dapm_supply:
1589 case snd_soc_dapm_regulator_supply: 1614 case snd_soc_dapm_regulator_supply:
1615 case snd_soc_dapm_clock_supply:
1590 case snd_soc_dapm_micbias: 1616 case snd_soc_dapm_micbias:
1591 if (d->target_bias_level < SND_SOC_BIAS_STANDBY) 1617 if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
1592 d->target_bias_level = SND_SOC_BIAS_STANDBY; 1618 d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1941,6 +1967,7 @@ static ssize_t dapm_widget_show(struct device *dev,
1941 case snd_soc_dapm_mixer_named_ctl: 1967 case snd_soc_dapm_mixer_named_ctl:
1942 case snd_soc_dapm_supply: 1968 case snd_soc_dapm_supply:
1943 case snd_soc_dapm_regulator_supply: 1969 case snd_soc_dapm_regulator_supply:
1970 case snd_soc_dapm_clock_supply:
1944 if (w->name) 1971 if (w->name)
1945 count += sprintf(buf + count, "%s: %s\n", 1972 count += sprintf(buf + count, "%s: %s\n",
1946 w->name, w->power ? "On":"Off"); 1973 w->name, w->power ? "On":"Off");
@@ -2187,6 +2214,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2187 case snd_soc_dapm_post: 2214 case snd_soc_dapm_post:
2188 case snd_soc_dapm_supply: 2215 case snd_soc_dapm_supply:
2189 case snd_soc_dapm_regulator_supply: 2216 case snd_soc_dapm_regulator_supply:
2217 case snd_soc_dapm_clock_supply:
2190 case snd_soc_dapm_aif_in: 2218 case snd_soc_dapm_aif_in:
2191 case snd_soc_dapm_aif_out: 2219 case snd_soc_dapm_aif_out:
2192 case snd_soc_dapm_dai: 2220 case snd_soc_dapm_dai:
@@ -2873,6 +2901,15 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2873 return NULL; 2901 return NULL;
2874 } 2902 }
2875 break; 2903 break;
2904 case snd_soc_dapm_clock_supply:
2905 w->clk = clk_get(dapm->dev, w->name);
2906 if (IS_ERR(w->clk)) {
2907 ret = PTR_ERR(w->clk);
2908 dev_err(dapm->dev, "Failed to request %s: %d\n",
2909 w->name, ret);
2910 return NULL;
2911 }
2912 break;
2876 default: 2913 default:
2877 break; 2914 break;
2878 } 2915 }
@@ -2924,6 +2961,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2924 break; 2961 break;
2925 case snd_soc_dapm_supply: 2962 case snd_soc_dapm_supply:
2926 case snd_soc_dapm_regulator_supply: 2963 case snd_soc_dapm_regulator_supply:
2964 case snd_soc_dapm_clock_supply:
2927 w->power_check = dapm_supply_check_power; 2965 w->power_check = dapm_supply_check_power;
2928 break; 2966 break;
2929 case snd_soc_dapm_dai: 2967 case snd_soc_dapm_dai: