diff options
-rw-r--r-- | include/sound/soc-dapm.h | 10 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 38 |
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); |
328 | int dapm_regulator_event(struct snd_soc_dapm_widget *w, | 333 | int dapm_regulator_event(struct snd_soc_dapm_widget *w, |
329 | struct snd_kcontrol *kcontrol, int event); | 334 | struct snd_kcontrol *kcontrol, int event); |
335 | int dapm_clock_event(struct snd_soc_dapm_widget *w, | ||
336 | struct snd_kcontrol *kcontrol, int event); | ||
330 | 337 | ||
331 | /* dapm controls */ | 338 | /* dapm controls */ |
332 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | 339 | int 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 | ||
542 | struct snd_soc_dapm_update { | 552 | struct 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 | } |
997 | EXPORT_SYMBOL_GPL(dapm_regulator_event); | 1003 | EXPORT_SYMBOL_GPL(dapm_regulator_event); |
998 | 1004 | ||
1005 | /* | ||
1006 | * Handler for clock supply widget. | ||
1007 | */ | ||
1008 | int 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 | } | ||
1021 | EXPORT_SYMBOL_GPL(dapm_clock_event); | ||
1022 | |||
999 | static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) | 1023 | static 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: |