aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-08-17 18:40:24 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-08-17 18:40:24 -0400
commit9745e824a81e54ef009500e120e35b68e387b941 (patch)
tree4d096a73b785863fc1f2a0fe49ba55a2e72b4c17
parent1593d7dd8c7b939e31b9d637307b26ada3e3c514 (diff)
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>
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c2
-rw-r--r--sound/soc/au1x/db1200.c2
-rw-r--r--sound/soc/codecs/wm8731.c31
-rw-r--r--sound/soc/codecs/wm8731.h4
-rw-r--r--sound/soc/pxa/corgi.c2
-rw-r--r--sound/soc/pxa/poodle.c2
6 files changed, 36 insertions, 7 deletions
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 66a6f1879689..8399ac46cb33 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -146,7 +146,7 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
146 "at91sam9g20ek_wm8731 " 146 "at91sam9g20ek_wm8731 "
147 ": at91sam9g20ek_wm8731_init() called\n"); 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 MCLK_RATE, SND_SOC_CLOCK_IN); 150 MCLK_RATE, SND_SOC_CLOCK_IN);
151 if (ret < 0) { 151 if (ret < 0) {
152 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); 152 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
index 8780c90107fc..d8dc8225576a 100644
--- a/sound/soc/au1x/db1200.c
+++ b/sound/soc/au1x/db1200.c
@@ -49,7 +49,7 @@ static int db1200_i2s_startup(struct snd_pcm_substream *substream)
49 int ret; 49 int ret;
50 50
51 /* WM8731 has its own 12MHz crystal */ 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 12000000, SND_SOC_CLOCK_IN); 53 12000000, SND_SOC_CLOCK_IN);
54 54
55 /* codec is bitclock and lrclk master */ 55 /* codec is bitclock and lrclk master */
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 19844fc8cb1d..56f540838745 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -46,6 +46,7 @@ struct wm8731_priv {
46 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; 46 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
47 u16 reg_cache[WM8731_CACHEREGNUM]; 47 u16 reg_cache[WM8731_CACHEREGNUM];
48 unsigned int sysclk; 48 unsigned int sysclk;
49 int sysclk_type;
49}; 50};
50 51
51 52
@@ -110,6 +111,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls =
110SOC_DAPM_ENUM("Input Select", wm8731_enum[0]); 111SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
111 112
112static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { 113static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
114SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0),
113SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, 115SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
114 &wm8731_output_mixer_controls[0], 116 &wm8731_output_mixer_controls[0],
115 ARRAY_SIZE(wm8731_output_mixer_controls)), 117 ARRAY_SIZE(wm8731_output_mixer_controls)),
@@ -127,7 +129,18 @@ SND_SOC_DAPM_INPUT("RLINEIN"),
127SND_SOC_DAPM_INPUT("LLINEIN"), 129SND_SOC_DAPM_INPUT("LLINEIN"),
128}; 130};
129 131
132static 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
130static const struct snd_soc_dapm_route intercon[] = { 140static const struct snd_soc_dapm_route intercon[] = {
141 {"DAC", NULL, "OSC", wm8731_check_osc},
142 {"ADC", NULL, "OSC", wm8731_check_osc},
143
131 /* output mixer */ 144 /* output mixer */
132 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 145 {"Output Mixer", "Line Bypass Switch", "Line Input"},
133 {"Output Mixer", "HiFi Playback Switch", "DAC"}, 146 {"Output Mixer", "HiFi Playback Switch", "DAC"},
@@ -285,6 +298,15 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
285 struct snd_soc_codec *codec = codec_dai->codec; 298 struct snd_soc_codec *codec = codec_dai->codec;
286 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 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 switch (freq) { 310 switch (freq) {
289 case 11289600: 311 case 11289600:
290 case 12000000: 312 case 12000000:
@@ -292,9 +314,14 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
292 case 16934400: 314 case 16934400:
293 case 18432000: 315 case 18432000:
294 wm8731->sysclk = freq; 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
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
index 73a70e206ba9..e9c0c76ab73b 100644
--- a/sound/soc/codecs/wm8731.h
+++ b/sound/soc/codecs/wm8731.h
@@ -31,7 +31,9 @@
31 31
32#define WM8731_CACHEREGNUM 10 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#define WM8731_DAI 0 37#define WM8731_DAI 0
36 38
37#endif 39#endif
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 555689cf6727..97e9423615c9 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -149,7 +149,7 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
149 return ret; 149 return ret;
150 150
151 /* set the codec system clock for DAC and ADC */ 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 SND_SOC_CLOCK_IN); 153 SND_SOC_CLOCK_IN);
154 if (ret < 0) 154 if (ret < 0)
155 return ret; 155 return ret;
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index add0e1c25bc8..fa752f6ec37d 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -128,7 +128,7 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
128 return ret; 128 return ret;
129 129
130 /* set the codec system clock for DAC and ADC */ 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 SND_SOC_CLOCK_IN); 132 SND_SOC_CLOCK_IN);
133 if (ret < 0) 133 if (ret < 0)
134 return ret; 134 return ret;