aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-06-06 14:03:23 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-06-07 08:02:27 -0400
commit38357ab2c83631728afa37a783c9b1bd474a0739 (patch)
tree847afc9a3a88ac21ecfa4c7c4e79f3950da3d26c /sound/soc/soc-dapm.c
parent74b8f955a73d20b1e22403fd1ef85834fbf38d98 (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.c109
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 */
54static int dapm_up_seq[] = { 54static 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
62static int dapm_down_seq[] = { 71static 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
70static void pop_wait(u32 pop_time) 88static 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
759static 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. */
770static 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 */