Commit 9745e824a81e54ef009500e120e35b68e387b941

Authored by Mark Brown
1 parent 1593d7dd8c

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
... ... @@ -49,7 +49,7 @@
49 49 int ret;
50 50  
51 51 /* WM8731 has its own 12MHz crystal */
52   - snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
  52 + snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
53 53 12000000, SND_SOC_CLOCK_IN);
54 54  
55 55 /* codec is bitclock and lrclk master */
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
... ... @@ -31,7 +31,9 @@
31 31  
32 32 #define WM8731_CACHEREGNUM 10
33 33  
34   -#define WM8731_SYSCLK 0
  34 +#define WM8731_SYSCLK_XTAL 1
  35 +#define WM8731_SYSCLK_MCLK 2
  36 +
35 37 #define WM8731_DAI 0
36 38  
37 39 #endif
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;