aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-19 13:50:05 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-20 07:56:53 -0400
commitded71dcb77ae0dee71fdb9c4e2d2b3dc3d1b7693 (patch)
tree5988d7568cc771a417ade4c7206e20eec874e8d6
parentc9d023adb62e17569f714669c93d3da07be49e3f (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.c45
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
670static 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
682static 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
669static int bg_event(struct snd_soc_dapm_widget *w, 692static 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),
1014SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), 1041SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
1015SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), 1042SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
1016SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, 1043SND_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), 1045SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
1019SND_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),
1021SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), 1047SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
1022SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0), 1048SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0),
1023SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0), 1049SND_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