diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-09-19 13:50:05 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-09-20 07:56:53 -0400 |
commit | ded71dcb77ae0dee71fdb9c4e2d2b3dc3d1b7693 (patch) | |
tree | 5988d7568cc771a417ade4c7206e20eec874e8d6 | |
parent | c9d023adb62e17569f714669c93d3da07be49e3f (diff) |
ASoC: Refcount WM8996 bandgap from FLL too
For digital only paths we need to make sure the bandgap is enabled prior
to starting the FLL which isn't tied into DAPM.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
-rw-r--r-- | sound/soc/codecs/wm8996.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1fe676c7aead..833df74c5584 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -71,6 +71,7 @@ struct wm8996_priv { | |||
71 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; | 71 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; |
72 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; | 72 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; |
73 | struct regulator *cpvdd; | 73 | struct regulator *cpvdd; |
74 | int bg_ena; | ||
74 | 75 | ||
75 | struct wm8996_pdata pdata; | 76 | struct wm8996_pdata pdata; |
76 | 77 | ||
@@ -666,14 +667,40 @@ SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0, | |||
666 | eq_tlv), | 667 | eq_tlv), |
667 | }; | 668 | }; |
668 | 669 | ||
670 | static void wm8996_bg_enable(struct snd_soc_codec *codec) | ||
671 | { | ||
672 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
673 | |||
674 | wm8996->bg_ena++; | ||
675 | if (wm8996->bg_ena == 1) { | ||
676 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
677 | WM8996_BG_ENA, WM8996_BG_ENA); | ||
678 | msleep(2); | ||
679 | } | ||
680 | } | ||
681 | |||
682 | static void wm8996_bg_disable(struct snd_soc_codec *codec) | ||
683 | { | ||
684 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
685 | |||
686 | wm8996->bg_ena--; | ||
687 | if (!wm8996->bg_ena) | ||
688 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
689 | WM8996_BG_ENA, 0); | ||
690 | } | ||
691 | |||
669 | static int bg_event(struct snd_soc_dapm_widget *w, | 692 | static int bg_event(struct snd_soc_dapm_widget *w, |
670 | struct snd_kcontrol *kcontrol, int event) | 693 | struct snd_kcontrol *kcontrol, int event) |
671 | { | 694 | { |
695 | struct snd_soc_codec *codec = w->codec; | ||
672 | int ret = 0; | 696 | int ret = 0; |
673 | 697 | ||
674 | switch (event) { | 698 | switch (event) { |
675 | case SND_SOC_DAPM_POST_PMU: | 699 | case SND_SOC_DAPM_PRE_PMU: |
676 | msleep(2); | 700 | wm8996_bg_enable(codec); |
701 | break; | ||
702 | case SND_SOC_DAPM_POST_PMD: | ||
703 | wm8996_bg_disable(codec); | ||
677 | break; | 704 | break; |
678 | default: | 705 | default: |
679 | BUG(); | 706 | BUG(); |
@@ -1014,10 +1041,9 @@ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), | |||
1014 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), | 1041 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), |
1015 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), | 1042 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), |
1016 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, | 1043 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, |
1017 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 1044 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1018 | SND_SOC_DAPM_POST_PMD), | 1045 | SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, |
1019 | SND_SOC_DAPM_SUPPLY("Bandgap", WM8996_POWER_MANAGEMENT_1, WM8996_BG_ENA_SHIFT, | 1046 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1020 | 0, bg_event, SND_SOC_DAPM_POST_PMU), | ||
1021 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), | 1047 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), |
1022 | SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0), | 1048 | SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0), |
1023 | SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0), | 1049 | SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0), |
@@ -2096,6 +2122,8 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2096 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, | 2122 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, |
2097 | WM8996_FLL_ENA, 0); | 2123 | WM8996_FLL_ENA, 0); |
2098 | 2124 | ||
2125 | wm8996_bg_disable(codec); | ||
2126 | |||
2099 | return 0; | 2127 | return 0; |
2100 | } | 2128 | } |
2101 | 2129 | ||
@@ -2150,6 +2178,11 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2150 | 2178 | ||
2151 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); | 2179 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); |
2152 | 2180 | ||
2181 | /* Enable the bandgap if it's not already enabled */ | ||
2182 | ret = snd_soc_read(codec, WM8996_FLL_CONTROL_1); | ||
2183 | if (!(ret & WM8996_FLL_ENA)) | ||
2184 | wm8996_bg_enable(codec); | ||
2185 | |||
2153 | /* Clear any pending completions (eg, from failed startups) */ | 2186 | /* Clear any pending completions (eg, from failed startups) */ |
2154 | try_wait_for_completion(&wm8996->fll_lock); | 2187 | try_wait_for_completion(&wm8996->fll_lock); |
2155 | 2188 | ||