Commit 9745e824a81e54ef009500e120e35b68e387b941
1 parent
1593d7dd8c
Exists in
master
and in
7 other branches
ASoC: Support non-crystal master clocks for WM8731
Instead of unconditionally enabling the crystal oscillator on the WM8731 only enable it when explicitly selected via set_sysclk(), allowing machine drivers to specify that they drive a clock into MCLK alone. This avoids any conflicts between the oscillator and the external MCLK source and saves power for systems which do not need the oscillator. This should also deliver a small power saving on systems using the crystal since the oscillator will only be enabled when the ADC or DAC is active. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Showing 6 changed files with 36 additions and 7 deletions Side-by-side Diff
sound/soc/atmel/sam9g20_wm8731.c
... | ... | @@ -146,7 +146,7 @@ |
146 | 146 | "at91sam9g20ek_wm8731 " |
147 | 147 | ": at91sam9g20ek_wm8731_init() called\n"); |
148 | 148 | |
149 | - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, | |
149 | + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, | |
150 | 150 | MCLK_RATE, SND_SOC_CLOCK_IN); |
151 | 151 | if (ret < 0) { |
152 | 152 | printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); |
sound/soc/au1x/db1200.c
sound/soc/codecs/wm8731.c
... | ... | @@ -46,6 +46,7 @@ |
46 | 46 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; |
47 | 47 | u16 reg_cache[WM8731_CACHEREGNUM]; |
48 | 48 | unsigned int sysclk; |
49 | + int sysclk_type; | |
49 | 50 | }; |
50 | 51 | |
51 | 52 | |
... | ... | @@ -110,6 +111,7 @@ |
110 | 111 | SOC_DAPM_ENUM("Input Select", wm8731_enum[0]); |
111 | 112 | |
112 | 113 | static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { |
114 | +SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0), | |
113 | 115 | SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, |
114 | 116 | &wm8731_output_mixer_controls[0], |
115 | 117 | ARRAY_SIZE(wm8731_output_mixer_controls)), |
116 | 118 | |
... | ... | @@ -127,7 +129,18 @@ |
127 | 129 | SND_SOC_DAPM_INPUT("LLINEIN"), |
128 | 130 | }; |
129 | 131 | |
132 | +static int wm8731_check_osc(struct snd_soc_dapm_widget *source, | |
133 | + struct snd_soc_dapm_widget *sink) | |
134 | +{ | |
135 | + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec); | |
136 | + | |
137 | + return wm8731->sysclk_type == WM8731_SYSCLK_MCLK; | |
138 | +} | |
139 | + | |
130 | 140 | static const struct snd_soc_dapm_route intercon[] = { |
141 | + {"DAC", NULL, "OSC", wm8731_check_osc}, | |
142 | + {"ADC", NULL, "OSC", wm8731_check_osc}, | |
143 | + | |
131 | 144 | /* output mixer */ |
132 | 145 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, |
133 | 146 | {"Output Mixer", "HiFi Playback Switch", "DAC"}, |
... | ... | @@ -285,6 +298,15 @@ |
285 | 298 | struct snd_soc_codec *codec = codec_dai->codec; |
286 | 299 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
287 | 300 | |
301 | + switch (clk_id) { | |
302 | + case WM8731_SYSCLK_XTAL: | |
303 | + case WM8731_SYSCLK_MCLK: | |
304 | + wm8731->sysclk_type = clk_id; | |
305 | + break; | |
306 | + default: | |
307 | + return -EINVAL; | |
308 | + } | |
309 | + | |
288 | 310 | switch (freq) { |
289 | 311 | case 11289600: |
290 | 312 | case 12000000: |
291 | 313 | |
... | ... | @@ -292,9 +314,14 @@ |
292 | 314 | case 16934400: |
293 | 315 | case 18432000: |
294 | 316 | wm8731->sysclk = freq; |
295 | - return 0; | |
317 | + break; | |
318 | + default: | |
319 | + return -EINVAL; | |
296 | 320 | } |
297 | - return -EINVAL; | |
321 | + | |
322 | + snd_soc_dapm_sync(codec); | |
323 | + | |
324 | + return 0; | |
298 | 325 | } |
299 | 326 | |
300 | 327 |
sound/soc/codecs/wm8731.h
sound/soc/pxa/corgi.c
... | ... | @@ -149,7 +149,7 @@ |
149 | 149 | return ret; |
150 | 150 | |
151 | 151 | /* set the codec system clock for DAC and ADC */ |
152 | - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, | |
152 | + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk, | |
153 | 153 | SND_SOC_CLOCK_IN); |
154 | 154 | if (ret < 0) |
155 | 155 | return ret; |
sound/soc/pxa/poodle.c
... | ... | @@ -128,7 +128,7 @@ |
128 | 128 | return ret; |
129 | 129 | |
130 | 130 | /* set the codec system clock for DAC and ADC */ |
131 | - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, | |
131 | + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk, | |
132 | 132 | SND_SOC_CLOCK_IN); |
133 | 133 | if (ret < 0) |
134 | 134 | return ret; |