diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-06-06 14:03:23 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-06-07 08:02:27 -0400 |
commit | 38357ab2c83631728afa37a783c9b1bd474a0739 (patch) | |
tree | 847afc9a3a88ac21ecfa4c7c4e79f3950da3d26c /sound/soc/soc-dapm.c | |
parent | 74b8f955a73d20b1e22403fd1ef85834fbf38d98 (diff) |
ASoC: Sort DAPM power sequences while building lists
In the past the DAPM power sequencing was done by iterating over the list
of widgets once for each widget type and powering widgets of that type.
Instead of doing that do the sorting at the time we insert the widgets
into the lists of widgets to apply power changes to. This reduces the
amount of computation required for seqencing still further, though the
costs are generally dwarfed by the costs of the register writes
implementing them.
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 | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 21c69074aa17..1b38e2195596 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -52,19 +52,37 @@ | |||
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_supply, snd_soc_dapm_micbias, | 55 | [snd_soc_dapm_pre] = 0, |
56 | snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux, | 56 | [snd_soc_dapm_supply] = 1, |
57 | snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, | 57 | [snd_soc_dapm_micbias] = 2, |
58 | snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, | 58 | [snd_soc_dapm_mic] = 3, |
59 | snd_soc_dapm_post | 59 | [snd_soc_dapm_mux] = 4, |
60 | [snd_soc_dapm_value_mux] = 5, | ||
61 | [snd_soc_dapm_dac] = 6, | ||
62 | [snd_soc_dapm_mixer] = 7, | ||
63 | [snd_soc_dapm_mixer_named_ctl] = 8, | ||
64 | [snd_soc_dapm_pga] = 9, | ||
65 | [snd_soc_dapm_adc] = 10, | ||
66 | [snd_soc_dapm_hp] = 11, | ||
67 | [snd_soc_dapm_spk] = 12, | ||
68 | [snd_soc_dapm_post] = 13, | ||
60 | }; | 69 | }; |
61 | 70 | ||
62 | static int dapm_down_seq[] = { | 71 | static int dapm_down_seq[] = { |
63 | snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, | 72 | [snd_soc_dapm_pre] = 0, |
64 | snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, | 73 | [snd_soc_dapm_adc] = 1, |
65 | snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, | 74 | [snd_soc_dapm_hp] = 2, |
66 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply, | 75 | [snd_soc_dapm_spk] = 3, |
67 | snd_soc_dapm_post | 76 | [snd_soc_dapm_pga] = 4, |
77 | [snd_soc_dapm_mixer_named_ctl] = 5, | ||
78 | [snd_soc_dapm_mixer] = 6, | ||
79 | [snd_soc_dapm_dac] = 7, | ||
80 | [snd_soc_dapm_mic] = 8, | ||
81 | [snd_soc_dapm_micbias] = 9, | ||
82 | [snd_soc_dapm_mux] = 10, | ||
83 | [snd_soc_dapm_value_mux] = 11, | ||
84 | [snd_soc_dapm_supply] = 12, | ||
85 | [snd_soc_dapm_post] = 13, | ||
68 | }; | 86 | }; |
69 | 87 | ||
70 | static void pop_wait(u32 pop_time) | 88 | static void pop_wait(u32 pop_time) |
@@ -738,6 +756,32 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event, | |||
738 | } | 756 | } |
739 | } | 757 | } |
740 | 758 | ||
759 | static int dapm_seq_compare(struct snd_soc_dapm_widget *a, | ||
760 | struct snd_soc_dapm_widget *b, | ||
761 | int sort[]) | ||
762 | { | ||
763 | if (sort[a->id] != sort[b->id]) | ||
764 | return sort[a->id] - sort[b->id]; | ||
765 | |||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | /* Insert a widget in order into a DAPM power sequence. */ | ||
770 | static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, | ||
771 | struct list_head *list, | ||
772 | int sort[]) | ||
773 | { | ||
774 | struct snd_soc_dapm_widget *w; | ||
775 | |||
776 | list_for_each_entry(w, list, power_list) | ||
777 | if (dapm_seq_compare(new_widget, w, sort) < 0) { | ||
778 | list_add_tail(&new_widget->power_list, &w->power_list); | ||
779 | return; | ||
780 | } | ||
781 | |||
782 | list_add_tail(&new_widget->power_list, list); | ||
783 | } | ||
784 | |||
741 | /* | 785 | /* |
742 | * Scan each dapm widget for complete audio path. | 786 | * Scan each dapm widget for complete audio path. |
743 | * A complete path is a route that has valid endpoints i.e.:- | 787 | * A complete path is a route that has valid endpoints i.e.:- |
@@ -752,7 +796,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
752 | struct snd_soc_device *socdev = codec->socdev; | 796 | struct snd_soc_device *socdev = codec->socdev; |
753 | struct snd_soc_dapm_widget *w; | 797 | struct snd_soc_dapm_widget *w; |
754 | int ret = 0; | 798 | int ret = 0; |
755 | int i, power; | 799 | int power; |
756 | int sys_power = 0; | 800 | int sys_power = 0; |
757 | 801 | ||
758 | INIT_LIST_HEAD(&codec->up_list); | 802 | INIT_LIST_HEAD(&codec->up_list); |
@@ -764,10 +808,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
764 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 808 | list_for_each_entry(w, &codec->dapm_widgets, list) { |
765 | switch (w->id) { | 809 | switch (w->id) { |
766 | case snd_soc_dapm_pre: | 810 | case snd_soc_dapm_pre: |
767 | list_add_tail(&codec->down_list, &w->power_list); | 811 | dapm_seq_insert(w, &codec->down_list, dapm_down_seq); |
768 | break; | 812 | break; |
769 | case snd_soc_dapm_post: | 813 | case snd_soc_dapm_post: |
770 | list_add_tail(&codec->up_list, &w->power_list); | 814 | dapm_seq_insert(w, &codec->up_list, dapm_up_seq); |
771 | break; | 815 | break; |
772 | 816 | ||
773 | default: | 817 | default: |
@@ -782,10 +826,11 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
782 | continue; | 826 | continue; |
783 | 827 | ||
784 | if (power) | 828 | if (power) |
785 | list_add_tail(&w->power_list, &codec->up_list); | 829 | dapm_seq_insert(w, &codec->up_list, |
830 | dapm_up_seq); | ||
786 | else | 831 | else |
787 | list_add_tail(&w->power_list, | 832 | dapm_seq_insert(w, &codec->down_list, |
788 | &codec->down_list); | 833 | dapm_down_seq); |
789 | 834 | ||
790 | w->power = power; | 835 | w->power = power; |
791 | break; | 836 | break; |
@@ -802,31 +847,19 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
802 | } | 847 | } |
803 | 848 | ||
804 | /* Power down widgets first; try to avoid amplifying pops. */ | 849 | /* Power down widgets first; try to avoid amplifying pops. */ |
805 | for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) { | 850 | list_for_each_entry(w, &codec->down_list, power_list) { |
806 | list_for_each_entry(w, &codec->down_list, power_list) { | 851 | ret = dapm_power_widget(codec, event, w); |
807 | /* is widget in stream order */ | 852 | if (ret != 0) |
808 | if (w->id != dapm_down_seq[i]) | 853 | pr_err("Failed to power down %s: %d\n", |
809 | continue; | 854 | w->name, ret); |
810 | |||
811 | ret = dapm_power_widget(codec, event, w); | ||
812 | if (ret != 0) | ||
813 | pr_err("Failed to power down %s: %d\n", | ||
814 | w->name, ret); | ||
815 | } | ||
816 | } | 855 | } |
817 | 856 | ||
818 | /* Now power up. */ | 857 | /* Now power up. */ |
819 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) { | 858 | list_for_each_entry(w, &codec->up_list, power_list) { |
820 | list_for_each_entry(w, &codec->up_list, power_list) { | 859 | ret = dapm_power_widget(codec, event, w); |
821 | /* is widget in stream order */ | 860 | if (ret != 0) |
822 | if (w->id != dapm_up_seq[i]) | 861 | pr_err("Failed to power up %s: %d\n", |
823 | continue; | 862 | w->name, ret); |
824 | |||
825 | ret = dapm_power_widget(codec, event, w); | ||
826 | if (ret != 0) | ||
827 | pr_err("Failed to power up %s: %d\n", | ||
828 | w->name, ret); | ||
829 | } | ||
830 | } | 863 | } |
831 | 864 | ||
832 | /* If we just powered the last thing off drop to standby bias */ | 865 | /* If we just powered the last thing off drop to standby bias */ |