aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
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