diff options
-rw-r--r-- | Documentation/sound/alsa/soc/dapm.txt | 1 | ||||
-rw-r--r-- | include/sound/soc-dapm.h | 7 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 44 |
3 files changed, 46 insertions, 6 deletions
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt index 9e6763264a2e..9ac842be9b4f 100644 --- a/Documentation/sound/alsa/soc/dapm.txt +++ b/Documentation/sound/alsa/soc/dapm.txt | |||
@@ -62,6 +62,7 @@ Audio DAPM widgets fall into a number of types:- | |||
62 | o Mic - Mic (and optional Jack) | 62 | o Mic - Mic (and optional Jack) |
63 | o Line - Line Input/Output (and optional Jack) | 63 | o Line - Line Input/Output (and optional Jack) |
64 | o Speaker - Speaker | 64 | o Speaker - Speaker |
65 | o Supply - Power or clock supply widget used by other widgets. | ||
65 | o Pre - Special PRE widget (exec before all others) | 66 | o Pre - Special PRE widget (exec before all others) |
66 | o Post - Special POST widget (exec after all others) | 67 | o Post - Special POST widget (exec after all others) |
67 | 68 | ||
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 839a97b63269..533f9f256496 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -154,12 +154,16 @@ | |||
154 | .shift = wshift, .invert = winvert, \ | 154 | .shift = wshift, .invert = winvert, \ |
155 | .event = wevent, .event_flags = wflags} | 155 | .event = wevent, .event_flags = wflags} |
156 | 156 | ||
157 | /* generic register modifier widget */ | 157 | /* generic widgets */ |
158 | #define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ | 158 | #define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ |
159 | { .id = wid, .name = wname, .kcontrols = NULL, .num_kcontrols = 0, \ | 159 | { .id = wid, .name = wname, .kcontrols = NULL, .num_kcontrols = 0, \ |
160 | .reg = -((wreg) + 1), .shift = wshift, .mask = wmask, \ | 160 | .reg = -((wreg) + 1), .shift = wshift, .mask = wmask, \ |
161 | .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \ | 161 | .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \ |
162 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} | 162 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} |
163 | #define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ | ||
164 | { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ | ||
165 | .shift = wshift, .invert = winvert, .event = wevent, \ | ||
166 | .event_flags = wflags} | ||
163 | 167 | ||
164 | /* dapm kcontrol types */ | 168 | /* dapm kcontrol types */ |
165 | #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ | 169 | #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ |
@@ -308,6 +312,7 @@ enum snd_soc_dapm_type { | |||
308 | snd_soc_dapm_vmid, /* codec bias/vmid - to minimise pops */ | 312 | snd_soc_dapm_vmid, /* codec bias/vmid - to minimise pops */ |
309 | snd_soc_dapm_pre, /* machine specific pre widget - exec first */ | 313 | snd_soc_dapm_pre, /* machine specific pre widget - exec first */ |
310 | snd_soc_dapm_post, /* machine specific post widget - exec last */ | 314 | snd_soc_dapm_post, /* machine specific post widget - exec last */ |
315 | snd_soc_dapm_supply, /* power/clock supply */ | ||
311 | }; | 316 | }; |
312 | 317 | ||
313 | /* | 318 | /* |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d3d17354e76c..7847f80e96d1 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -52,17 +52,19 @@ | |||
52 | 52 | ||
53 | /* dapm power sequences - make this per codec in the future */ | 53 | /* dapm power sequences - make this per codec in the future */ |
54 | static int dapm_up_seq[] = { | 54 | static int dapm_up_seq[] = { |
55 | snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, | 55 | snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias, |
56 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, | 56 | snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux, |
57 | snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, | 57 | snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, |
58 | snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post | 58 | snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, |
59 | snd_soc_dapm_post | ||
59 | }; | 60 | }; |
60 | 61 | ||
61 | static int dapm_down_seq[] = { | 62 | static int dapm_down_seq[] = { |
62 | snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, | 63 | snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, |
63 | snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, | 64 | snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, |
64 | snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, | 65 | snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, |
65 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post | 66 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply, |
67 | snd_soc_dapm_post | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | static int dapm_status = 1; | 70 | static int dapm_status = 1; |
@@ -165,6 +167,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
165 | case snd_soc_dapm_dac: | 167 | case snd_soc_dapm_dac: |
166 | case snd_soc_dapm_micbias: | 168 | case snd_soc_dapm_micbias: |
167 | case snd_soc_dapm_vmid: | 169 | case snd_soc_dapm_vmid: |
170 | case snd_soc_dapm_supply: | ||
168 | p->connect = 1; | 171 | p->connect = 1; |
169 | break; | 172 | break; |
170 | /* does effect routing - dynamically connected */ | 173 | /* does effect routing - dynamically connected */ |
@@ -435,6 +438,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) | |||
435 | struct snd_soc_dapm_path *path; | 438 | struct snd_soc_dapm_path *path; |
436 | int con = 0; | 439 | int con = 0; |
437 | 440 | ||
441 | if (widget->id == snd_soc_dapm_supply) | ||
442 | return 0; | ||
443 | |||
438 | if (widget->id == snd_soc_dapm_adc && widget->active) | 444 | if (widget->id == snd_soc_dapm_adc && widget->active) |
439 | return 1; | 445 | return 1; |
440 | 446 | ||
@@ -471,6 +477,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) | |||
471 | struct snd_soc_dapm_path *path; | 477 | struct snd_soc_dapm_path *path; |
472 | int con = 0; | 478 | int con = 0; |
473 | 479 | ||
480 | if (widget->id == snd_soc_dapm_supply) | ||
481 | return 0; | ||
482 | |||
474 | /* active stream ? */ | 483 | /* active stream ? */ |
475 | if (widget->id == snd_soc_dapm_dac && widget->active) | 484 | if (widget->id == snd_soc_dapm_dac && widget->active) |
476 | return 1; | 485 | return 1; |
@@ -622,6 +631,26 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w) | |||
622 | } | 631 | } |
623 | } | 632 | } |
624 | 633 | ||
634 | /* Check to see if a power supply is needed */ | ||
635 | static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | ||
636 | { | ||
637 | struct snd_soc_dapm_path *path; | ||
638 | int power = 0; | ||
639 | |||
640 | /* Check if one of our outputs is connected */ | ||
641 | list_for_each_entry(path, &w->sinks, list_source) { | ||
642 | if (path->sink && path->sink->power_check && | ||
643 | path->sink->power_check(path->sink)) { | ||
644 | power = 1; | ||
645 | break; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | dapm_clear_walk(w->codec); | ||
650 | |||
651 | return power; | ||
652 | } | ||
653 | |||
625 | /* | 654 | /* |
626 | * Scan a single DAPM widget for a complete audio path and update the | 655 | * Scan a single DAPM widget for a complete audio path and update the |
627 | * power status appropriately. | 656 | * power status appropriately. |
@@ -752,6 +781,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) | |||
752 | case snd_soc_dapm_pga: | 781 | case snd_soc_dapm_pga: |
753 | case snd_soc_dapm_mixer: | 782 | case snd_soc_dapm_mixer: |
754 | case snd_soc_dapm_mixer_named_ctl: | 783 | case snd_soc_dapm_mixer_named_ctl: |
784 | case snd_soc_dapm_supply: | ||
755 | if (w->name) { | 785 | if (w->name) { |
756 | in = is_connected_input_ep(w); | 786 | in = is_connected_input_ep(w); |
757 | dapm_clear_walk(w->codec); | 787 | dapm_clear_walk(w->codec); |
@@ -880,6 +910,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
880 | case snd_soc_dapm_pga: | 910 | case snd_soc_dapm_pga: |
881 | case snd_soc_dapm_mixer: | 911 | case snd_soc_dapm_mixer: |
882 | case snd_soc_dapm_mixer_named_ctl: | 912 | case snd_soc_dapm_mixer_named_ctl: |
913 | case snd_soc_dapm_supply: | ||
883 | if (w->name) | 914 | if (w->name) |
884 | count += sprintf(buf + count, "%s: %s\n", | 915 | count += sprintf(buf + count, "%s: %s\n", |
885 | w->name, w->power ? "On":"Off"); | 916 | w->name, w->power ? "On":"Off"); |
@@ -1044,6 +1075,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
1044 | case snd_soc_dapm_vmid: | 1075 | case snd_soc_dapm_vmid: |
1045 | case snd_soc_dapm_pre: | 1076 | case snd_soc_dapm_pre: |
1046 | case snd_soc_dapm_post: | 1077 | case snd_soc_dapm_post: |
1078 | case snd_soc_dapm_supply: | ||
1047 | list_add(&path->list, &codec->dapm_paths); | 1079 | list_add(&path->list, &codec->dapm_paths); |
1048 | list_add(&path->list_sink, &wsink->sources); | 1080 | list_add(&path->list_sink, &wsink->sources); |
1049 | list_add(&path->list_source, &wsource->sinks); | 1081 | list_add(&path->list_source, &wsource->sinks); |
@@ -1164,6 +1196,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
1164 | case snd_soc_dapm_line: | 1196 | case snd_soc_dapm_line: |
1165 | w->power_check = dapm_generic_check_power; | 1197 | w->power_check = dapm_generic_check_power; |
1166 | break; | 1198 | break; |
1199 | case snd_soc_dapm_supply: | ||
1200 | w->power_check = dapm_supply_check_power; | ||
1167 | case snd_soc_dapm_vmid: | 1201 | case snd_soc_dapm_vmid: |
1168 | case snd_soc_dapm_pre: | 1202 | case snd_soc_dapm_pre: |
1169 | case snd_soc_dapm_post: | 1203 | case snd_soc_dapm_post: |