aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-17 16:41:23 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-18 10:53:16 -0400
commit452c5eaa0d5162e02ffee742ea17540887bc2904 (patch)
tree7dbac625d69e3ff01445d7f1b1fa321aa35fcae5 /sound/soc/soc-dapm.c
parentaef908434cd24dd5529065bf5d781773fad21125 (diff)
ASoC: Integrate bias management with DAPM power management
Rather than managing the bias level of the system based on if there is an active audio stream manage it based on there being an active DAPM widget. This simplifies the code a little, moving the power handling into one place, and improves audio performance for bypass paths when no playbacks or captures are active. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d130602b3072..4ca5e56388a3 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -94,6 +94,30 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
94 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); 94 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
95} 95}
96 96
97/**
98 * snd_soc_dapm_set_bias_level - set the bias level for the system
99 * @socdev: audio device
100 * @level: level to configure
101 *
102 * Configure the bias (power) levels for the SoC audio device.
103 *
104 * Returns 0 for success else error.
105 */
106static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
107 enum snd_soc_bias_level level)
108{
109 struct snd_soc_card *card = socdev->card;
110 struct snd_soc_codec *codec = socdev->card->codec;
111 int ret = 0;
112
113 if (card->set_bias_level)
114 ret = card->set_bias_level(card, level);
115 if (ret == 0 && codec->set_bias_level)
116 ret = codec->set_bias_level(codec, level);
117
118 return ret;
119}
120
97/* set up initial codec paths */ 121/* set up initial codec paths */
98static void dapm_set_path_status(struct snd_soc_dapm_widget *w, 122static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
99 struct snd_soc_dapm_path *p, int i) 123 struct snd_soc_dapm_path *p, int i)
@@ -707,9 +731,11 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event,
707 */ 731 */
708static int dapm_power_widgets(struct snd_soc_codec *codec, int event) 732static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
709{ 733{
734 struct snd_soc_device *socdev = codec->socdev;
710 struct snd_soc_dapm_widget *w; 735 struct snd_soc_dapm_widget *w;
711 int ret = 0; 736 int ret = 0;
712 int i, power; 737 int i, power;
738 int sys_power = 0;
713 739
714 INIT_LIST_HEAD(&codec->up_list); 740 INIT_LIST_HEAD(&codec->up_list);
715 INIT_LIST_HEAD(&codec->down_list); 741 INIT_LIST_HEAD(&codec->down_list);
@@ -731,6 +757,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
731 continue; 757 continue;
732 758
733 power = w->power_check(w); 759 power = w->power_check(w);
760 if (power)
761 sys_power = 1;
762
734 if (w->power == power) 763 if (w->power == power)
735 continue; 764 continue;
736 765
@@ -745,6 +774,15 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
745 } 774 }
746 } 775 }
747 776
777 /* If we're changing to all on or all off then prepare */
778 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
779 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
780 ret = snd_soc_dapm_set_bias_level(socdev,
781 SND_SOC_BIAS_PREPARE);
782 if (ret != 0)
783 pr_err("Failed to prepare bias: %d\n", ret);
784 }
785
748 /* Power down widgets first; try to avoid amplifying pops. */ 786 /* Power down widgets first; try to avoid amplifying pops. */
749 for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) { 787 for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) {
750 list_for_each_entry(w, &codec->down_list, power_list) { 788 list_for_each_entry(w, &codec->down_list, power_list) {
@@ -773,6 +811,22 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
773 } 811 }
774 } 812 }
775 813
814 /* If we just powered the last thing off drop to standby bias */
815 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
816 ret = snd_soc_dapm_set_bias_level(socdev,
817 SND_SOC_BIAS_STANDBY);
818 if (ret != 0)
819 pr_err("Failed to apply standby bias: %d\n", ret);
820 }
821
822 /* If we just powered up then move to active bias */
823 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
824 ret = snd_soc_dapm_set_bias_level(socdev,
825 SND_SOC_BIAS_ON);
826 if (ret != 0)
827 pr_err("Failed to apply active bias: %d\n", ret);
828 }
829
776 return 0; 830 return 0;
777} 831}
778 832
@@ -1721,30 +1775,6 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1721EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); 1775EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1722 1776
1723/** 1777/**
1724 * snd_soc_dapm_set_bias_level - set the bias level for the system
1725 * @socdev: audio device
1726 * @level: level to configure
1727 *
1728 * Configure the bias (power) levels for the SoC audio device.
1729 *
1730 * Returns 0 for success else error.
1731 */
1732int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
1733 enum snd_soc_bias_level level)
1734{
1735 struct snd_soc_card *card = socdev->card;
1736 struct snd_soc_codec *codec = socdev->card->codec;
1737 int ret = 0;
1738
1739 if (card->set_bias_level)
1740 ret = card->set_bias_level(card, level);
1741 if (ret == 0 && codec->set_bias_level)
1742 ret = codec->set_bias_level(codec, level);
1743
1744 return ret;
1745}
1746
1747/**
1748 * snd_soc_dapm_enable_pin - enable pin. 1778 * snd_soc_dapm_enable_pin - enable pin.
1749 * @codec: SoC codec 1779 * @codec: SoC codec
1750 * @pin: pin name 1780 * @pin: pin name