diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-04-22 13:24:55 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-04-22 14:10:13 -0400 |
commit | 246d0a17f5e09af0794960164269fc8988a8811c (patch) | |
tree | 3c10da44183691038959ba0b53d5598ac1aaabc4 /sound/soc/soc-dapm.c | |
parent | 1b4246a1fc487370665bf6c55aac8eae379642c0 (diff) |
ASoC: Add power supply widget to DAPM
Many modern CODECs have shared resources on chip which must be enabled
for portions of the chip to work but which can be disabled at other times
in order to achieve power savings. Examples of such resources include
power supplies and some internal clocks.
Since these widgets are dependencies for the audio path but do not carry
audio signals they require slightly different handling to most widgets -
they do not contribute to the audio path and so should not be counted as
either inputs or outputs during path walks.
Cases where one supply provides a supply for another will require
additional work. There is also room for more optimisation of the graph
walking to avoid repeated checks for the same thing.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 44 |
1 files changed, 39 insertions, 5 deletions
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: |