diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-05-12 07:35:44 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-05-12 07:54:06 -0400 |
commit | 68a02db415d13f2fde571b131deb91de67719a27 (patch) | |
tree | 80ce8a7c7efeb5c1622272c40b309746d5868eb7 | |
parent | e968194b45c4e8077dada75c5bae5660b37628fe (diff) |
ASoC: littlemill: Use a widget to keep track of AIF2 clocking
Since we only need to clock AIF2 when it's actively in use start up the
FLL for it using a supply widget which supplies AIF2CLK. This both makes
the sequencing more robust and ensures we minimise power consumption.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | sound/soc/samsung/littlemill.c | 86 |
1 files changed, 53 insertions, 33 deletions
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index fd5ac47371a1..c82c646b8a08 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c | |||
@@ -67,7 +67,6 @@ static int littlemill_set_bias_level_post(struct snd_soc_card *card, | |||
67 | enum snd_soc_bias_level level) | 67 | enum snd_soc_bias_level level) |
68 | { | 68 | { |
69 | struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; | 69 | struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; |
70 | struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; | ||
71 | int ret; | 70 | int ret; |
72 | 71 | ||
73 | if (dapm->dev != aif1_dai->dev) | 72 | if (dapm->dev != aif1_dai->dev) |
@@ -75,20 +74,6 @@ static int littlemill_set_bias_level_post(struct snd_soc_card *card, | |||
75 | 74 | ||
76 | switch (level) { | 75 | switch (level) { |
77 | case SND_SOC_BIAS_STANDBY: | 76 | case SND_SOC_BIAS_STANDBY: |
78 | ret = snd_soc_dai_set_sysclk(aif2_dai, WM8994_SYSCLK_MCLK2, | ||
79 | 32768, SND_SOC_CLOCK_IN); | ||
80 | if (ret < 0) { | ||
81 | pr_err("Failed to switch away from FLL2: %d\n", ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | ret = snd_soc_dai_set_pll(aif2_dai, WM8994_FLL2, | ||
86 | 0, 0, 0); | ||
87 | if (ret < 0) { | ||
88 | pr_err("Failed to stop FLL2: %d\n", ret); | ||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, | 77 | ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, |
93 | 32768, SND_SOC_CLOCK_IN); | 78 | 32768, SND_SOC_CLOCK_IN); |
94 | if (ret < 0) { | 79 | if (ret < 0) { |
@@ -104,24 +89,6 @@ static int littlemill_set_bias_level_post(struct snd_soc_card *card, | |||
104 | } | 89 | } |
105 | break; | 90 | break; |
106 | 91 | ||
107 | case SND_SOC_BIAS_PREPARE: | ||
108 | ret = snd_soc_dai_set_pll(aif2_dai, WM8994_FLL2, | ||
109 | WM8994_FLL_SRC_BCLK, 64 * 8000, | ||
110 | 8000 * 256); | ||
111 | if (ret < 0) { | ||
112 | pr_err("Failed to start FLL: %d\n", ret); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | ret = snd_soc_dai_set_sysclk(aif2_dai, WM8994_SYSCLK_FLL2, | ||
117 | 8000 * 256, | ||
118 | SND_SOC_CLOCK_IN); | ||
119 | if (ret < 0) { | ||
120 | pr_err("Failed to set SYSCLK: %d\n", ret); | ||
121 | return ret; | ||
122 | } | ||
123 | break; | ||
124 | |||
125 | default: | 92 | default: |
126 | break; | 93 | break; |
127 | } | 94 | } |
@@ -197,11 +164,62 @@ static struct snd_soc_dai_link littlemill_dai[] = { | |||
197 | }, | 164 | }, |
198 | }; | 165 | }; |
199 | 166 | ||
167 | static int bbclk_ev(struct snd_soc_dapm_widget *w, | ||
168 | struct snd_kcontrol *kcontrol, int event) | ||
169 | { | ||
170 | struct snd_soc_card *card = w->dapm->card; | ||
171 | struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; | ||
172 | int ret; | ||
173 | |||
174 | switch (event) { | ||
175 | case SND_SOC_DAPM_PRE_PMU: | ||
176 | ret = snd_soc_dai_set_pll(aif2_dai, WM8994_FLL2, | ||
177 | WM8994_FLL_SRC_BCLK, 64 * 8000, | ||
178 | 8000 * 256); | ||
179 | if (ret < 0) { | ||
180 | pr_err("Failed to start FLL: %d\n", ret); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | ret = snd_soc_dai_set_sysclk(aif2_dai, WM8994_SYSCLK_FLL2, | ||
185 | 8000 * 256, | ||
186 | SND_SOC_CLOCK_IN); | ||
187 | if (ret < 0) { | ||
188 | pr_err("Failed to set SYSCLK: %d\n", ret); | ||
189 | return ret; | ||
190 | } | ||
191 | break; | ||
192 | case SND_SOC_DAPM_POST_PMD: | ||
193 | ret = snd_soc_dai_set_sysclk(aif2_dai, WM8994_SYSCLK_MCLK2, | ||
194 | 32768, SND_SOC_CLOCK_IN); | ||
195 | if (ret < 0) { | ||
196 | pr_err("Failed to switch away from FLL2: %d\n", ret); | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | ret = snd_soc_dai_set_pll(aif2_dai, WM8994_FLL2, | ||
201 | 0, 0, 0); | ||
202 | if (ret < 0) { | ||
203 | pr_err("Failed to stop FLL2: %d\n", ret); | ||
204 | return ret; | ||
205 | } | ||
206 | break; | ||
207 | default: | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
200 | static struct snd_soc_dapm_widget widgets[] = { | 214 | static struct snd_soc_dapm_widget widgets[] = { |
201 | SND_SOC_DAPM_HP("Headphone", NULL), | 215 | SND_SOC_DAPM_HP("Headphone", NULL), |
202 | 216 | ||
203 | SND_SOC_DAPM_MIC("AMIC", NULL), | 217 | SND_SOC_DAPM_MIC("AMIC", NULL), |
204 | SND_SOC_DAPM_MIC("DMIC", NULL), | 218 | SND_SOC_DAPM_MIC("DMIC", NULL), |
219 | |||
220 | SND_SOC_DAPM_SUPPLY_S("Baseband Clock", -1, SND_SOC_NOPM, 0, 0, | ||
221 | bbclk_ev, | ||
222 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
205 | }; | 223 | }; |
206 | 224 | ||
207 | static struct snd_soc_dapm_route audio_paths[] = { | 225 | static struct snd_soc_dapm_route audio_paths[] = { |
@@ -214,6 +232,8 @@ static struct snd_soc_dapm_route audio_paths[] = { | |||
214 | { "DMIC", NULL, "MICBIAS2" }, /* Default for DMICBIAS jumper */ | 232 | { "DMIC", NULL, "MICBIAS2" }, /* Default for DMICBIAS jumper */ |
215 | { "DMIC1DAT", NULL, "DMIC" }, | 233 | { "DMIC1DAT", NULL, "DMIC" }, |
216 | { "DMIC2DAT", NULL, "DMIC" }, | 234 | { "DMIC2DAT", NULL, "DMIC" }, |
235 | |||
236 | { "AIF2CLK", NULL, "Baseband Clock" }, | ||
217 | }; | 237 | }; |
218 | 238 | ||
219 | static struct snd_soc_jack littlemill_headset; | 239 | static struct snd_soc_jack littlemill_headset; |