xref: /openbmc/linux/sound/soc/codecs/wm8770.c (revision 7490ca1e)
1 /*
2  * wm8770.c  --  WM8770 ALSA SoC Audio driver
3  *
4  * Copyright 2010 Wolfson Microelectronics plc
5  *
6  * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/init.h>
16 #include <linux/delay.h>
17 #include <linux/of_device.h>
18 #include <linux/pm.h>
19 #include <linux/spi/spi.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/slab.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 #include <sound/soc.h>
26 #include <sound/initval.h>
27 #include <sound/tlv.h>
28 
29 #include "wm8770.h"
30 
31 #define WM8770_NUM_SUPPLIES 3
32 static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
33 	"AVDD1",
34 	"AVDD2",
35 	"DVDD"
36 };
37 
38 static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = {
39 	0x7f, 0x7f, 0x7f, 0x7f,
40 	0x7f, 0x7f, 0x7f, 0x7f,
41 	0x7f, 0xff, 0xff, 0xff,
42 	0xff, 0xff, 0xff, 0xff,
43 	0xff, 0xff, 0, 0x90, 0,
44 	0, 0x22, 0x22, 0x3e,
45 	0xc, 0xc, 0x100, 0x189,
46 	0x189, 0x8770
47 };
48 
49 struct wm8770_priv {
50 	enum snd_soc_control_type control_type;
51 	struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
52 	struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
53 	struct snd_soc_codec *codec;
54 	int sysclk;
55 };
56 
57 static int vout12supply_event(struct snd_soc_dapm_widget *w,
58 	struct snd_kcontrol *kcontrol, int event);
59 static int vout34supply_event(struct snd_soc_dapm_widget *w,
60 	struct snd_kcontrol *kcontrol, int event);
61 
62 /*
63  * We can't use the same notifier block for more than one supply and
64  * there's no way I can see to get from a callback to the caller
65  * except container_of().
66  */
67 #define WM8770_REGULATOR_EVENT(n) \
68 static int wm8770_regulator_event_##n(struct notifier_block *nb, \
69 				      unsigned long event, void *data)    \
70 { \
71 	struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
72 				     disable_nb[n]); \
73 	if (event & REGULATOR_EVENT_DISABLE) { \
74 		wm8770->codec->cache_sync = 1; \
75 	} \
76 	return 0; \
77 }
78 
79 WM8770_REGULATOR_EVENT(0)
80 WM8770_REGULATOR_EVENT(1)
81 WM8770_REGULATOR_EVENT(2)
82 
83 static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 100, 0);
84 static const DECLARE_TLV_DB_SCALE(dac_dig_tlv, -12750, 50, 1);
85 static const DECLARE_TLV_DB_SCALE(dac_alg_tlv, -12700, 100, 1);
86 
87 static const char *dac_phase_text[][2] = {
88 	{ "DAC1 Normal", "DAC1 Inverted" },
89 	{ "DAC2 Normal", "DAC2 Inverted" },
90 	{ "DAC3 Normal", "DAC3 Inverted" },
91 	{ "DAC4 Normal", "DAC4 Inverted" },
92 };
93 
94 static const struct soc_enum dac_phase[] = {
95 	SOC_ENUM_DOUBLE(WM8770_DACPHASE, 0, 1, 2, dac_phase_text[0]),
96 	SOC_ENUM_DOUBLE(WM8770_DACPHASE, 2, 3, 2, dac_phase_text[1]),
97 	SOC_ENUM_DOUBLE(WM8770_DACPHASE, 4, 5, 2, dac_phase_text[2]),
98 	SOC_ENUM_DOUBLE(WM8770_DACPHASE, 6, 7, 2, dac_phase_text[3]),
99 };
100 
101 static const struct snd_kcontrol_new wm8770_snd_controls[] = {
102 	/* global DAC playback controls */
103 	SOC_SINGLE_TLV("DAC Playback Volume", WM8770_MSDIGVOL, 0, 255, 0,
104 		dac_dig_tlv),
105 	SOC_SINGLE("DAC Playback Switch", WM8770_DACMUTE, 4, 1, 1),
106 	SOC_SINGLE("DAC Playback ZC Switch", WM8770_DACCTRL1, 0, 1, 0),
107 
108 	/* global VOUT playback controls */
109 	SOC_SINGLE_TLV("VOUT Playback Volume", WM8770_MSALGVOL, 0, 127, 0,
110 		dac_alg_tlv),
111 	SOC_SINGLE("VOUT Playback ZC Switch", WM8770_MSALGVOL, 7, 1, 0),
112 
113 	/* VOUT1/2/3/4 specific controls */
114 	SOC_DOUBLE_R_TLV("VOUT1 Playback Volume", WM8770_VOUT1LVOL,
115 		WM8770_VOUT1RVOL, 0, 127, 0, dac_alg_tlv),
116 	SOC_DOUBLE_R("VOUT1 Playback ZC Switch", WM8770_VOUT1LVOL,
117 		WM8770_VOUT1RVOL, 7, 1, 0),
118 	SOC_DOUBLE_R_TLV("VOUT2 Playback Volume", WM8770_VOUT2LVOL,
119 		WM8770_VOUT2RVOL, 0, 127, 0, dac_alg_tlv),
120 	SOC_DOUBLE_R("VOUT2 Playback ZC Switch", WM8770_VOUT2LVOL,
121 		WM8770_VOUT2RVOL, 7, 1, 0),
122 	SOC_DOUBLE_R_TLV("VOUT3 Playback Volume", WM8770_VOUT3LVOL,
123 		WM8770_VOUT3RVOL, 0, 127, 0, dac_alg_tlv),
124 	SOC_DOUBLE_R("VOUT3 Playback ZC Switch", WM8770_VOUT3LVOL,
125 		WM8770_VOUT3RVOL, 7, 1, 0),
126 	SOC_DOUBLE_R_TLV("VOUT4 Playback Volume", WM8770_VOUT4LVOL,
127 		WM8770_VOUT4RVOL, 0, 127, 0, dac_alg_tlv),
128 	SOC_DOUBLE_R("VOUT4 Playback ZC Switch", WM8770_VOUT4LVOL,
129 		WM8770_VOUT4RVOL, 7, 1, 0),
130 
131 	/* DAC1/2/3/4 specific controls */
132 	SOC_DOUBLE_R_TLV("DAC1 Playback Volume", WM8770_DAC1LVOL,
133 		WM8770_DAC1RVOL, 0, 255, 0, dac_dig_tlv),
134 	SOC_SINGLE("DAC1 Deemphasis Switch", WM8770_DACCTRL2, 0, 1, 0),
135 	SOC_ENUM("DAC1 Phase", dac_phase[0]),
136 	SOC_DOUBLE_R_TLV("DAC2 Playback Volume", WM8770_DAC2LVOL,
137 		WM8770_DAC2RVOL, 0, 255, 0, dac_dig_tlv),
138 	SOC_SINGLE("DAC2 Deemphasis Switch", WM8770_DACCTRL2, 1, 1, 0),
139 	SOC_ENUM("DAC2 Phase", dac_phase[1]),
140 	SOC_DOUBLE_R_TLV("DAC3 Playback Volume", WM8770_DAC3LVOL,
141 		WM8770_DAC3RVOL, 0, 255, 0, dac_dig_tlv),
142 	SOC_SINGLE("DAC3 Deemphasis Switch", WM8770_DACCTRL2, 2, 1, 0),
143 	SOC_ENUM("DAC3 Phase", dac_phase[2]),
144 	SOC_DOUBLE_R_TLV("DAC4 Playback Volume", WM8770_DAC4LVOL,
145 		WM8770_DAC4RVOL, 0, 255, 0, dac_dig_tlv),
146 	SOC_SINGLE("DAC4 Deemphasis Switch", WM8770_DACCTRL2, 3, 1, 0),
147 	SOC_ENUM("DAC4 Phase", dac_phase[3]),
148 
149 	/* ADC specific controls */
150 	SOC_DOUBLE_R_TLV("Capture Volume", WM8770_ADCLCTRL, WM8770_ADCRCTRL,
151 		0, 31, 0, adc_tlv),
152 	SOC_DOUBLE_R("Capture Switch", WM8770_ADCLCTRL, WM8770_ADCRCTRL,
153 		5, 1, 1),
154 
155 	/* other controls */
156 	SOC_SINGLE("ADC 128x Oversampling Switch", WM8770_MSTRCTRL, 3, 1, 0),
157 	SOC_SINGLE("ADC Highpass Filter Switch", WM8770_IFACECTRL, 8, 1, 1)
158 };
159 
160 static const char *ain_text[] = {
161 	"AIN1", "AIN2", "AIN3", "AIN4",
162 	"AIN5", "AIN6", "AIN7", "AIN8"
163 };
164 
165 static const struct soc_enum ain_enum =
166 	SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text);
167 
168 static const struct snd_kcontrol_new ain_mux =
169 	SOC_DAPM_ENUM("Capture Mux", ain_enum);
170 
171 static const struct snd_kcontrol_new vout1_mix_controls[] = {
172 	SOC_DAPM_SINGLE("DAC1 Switch", WM8770_OUTMUX1, 0, 1, 0),
173 	SOC_DAPM_SINGLE("AUX1 Switch", WM8770_OUTMUX1, 1, 1, 0),
174 	SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 2, 1, 0)
175 };
176 
177 static const struct snd_kcontrol_new vout2_mix_controls[] = {
178 	SOC_DAPM_SINGLE("DAC2 Switch", WM8770_OUTMUX1, 3, 1, 0),
179 	SOC_DAPM_SINGLE("AUX2 Switch", WM8770_OUTMUX1, 4, 1, 0),
180 	SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 5, 1, 0)
181 };
182 
183 static const struct snd_kcontrol_new vout3_mix_controls[] = {
184 	SOC_DAPM_SINGLE("DAC3 Switch", WM8770_OUTMUX2, 0, 1, 0),
185 	SOC_DAPM_SINGLE("AUX3 Switch", WM8770_OUTMUX2, 1, 1, 0),
186 	SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 2, 1, 0)
187 };
188 
189 static const struct snd_kcontrol_new vout4_mix_controls[] = {
190 	SOC_DAPM_SINGLE("DAC4 Switch", WM8770_OUTMUX2, 3, 1, 0),
191 	SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 4, 1, 0)
192 };
193 
194 static const struct snd_soc_dapm_widget wm8770_dapm_widgets[] = {
195 	SND_SOC_DAPM_INPUT("AUX1"),
196 	SND_SOC_DAPM_INPUT("AUX2"),
197 	SND_SOC_DAPM_INPUT("AUX3"),
198 
199 	SND_SOC_DAPM_INPUT("AIN1"),
200 	SND_SOC_DAPM_INPUT("AIN2"),
201 	SND_SOC_DAPM_INPUT("AIN3"),
202 	SND_SOC_DAPM_INPUT("AIN4"),
203 	SND_SOC_DAPM_INPUT("AIN5"),
204 	SND_SOC_DAPM_INPUT("AIN6"),
205 	SND_SOC_DAPM_INPUT("AIN7"),
206 	SND_SOC_DAPM_INPUT("AIN8"),
207 
208 	SND_SOC_DAPM_MUX("Capture Mux", WM8770_ADCMUX, 8, 1, &ain_mux),
209 
210 	SND_SOC_DAPM_ADC("ADC", "Capture", WM8770_PWDNCTRL, 1, 1),
211 
212 	SND_SOC_DAPM_DAC("DAC1", "Playback", WM8770_PWDNCTRL, 2, 1),
213 	SND_SOC_DAPM_DAC("DAC2", "Playback", WM8770_PWDNCTRL, 3, 1),
214 	SND_SOC_DAPM_DAC("DAC3", "Playback", WM8770_PWDNCTRL, 4, 1),
215 	SND_SOC_DAPM_DAC("DAC4", "Playback", WM8770_PWDNCTRL, 5, 1),
216 
217 	SND_SOC_DAPM_SUPPLY("VOUT12 Supply", SND_SOC_NOPM, 0, 0,
218 		vout12supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
219 	SND_SOC_DAPM_SUPPLY("VOUT34 Supply", SND_SOC_NOPM, 0, 0,
220 		vout34supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
221 
222 	SND_SOC_DAPM_MIXER("VOUT1 Mixer", SND_SOC_NOPM, 0, 0,
223 		vout1_mix_controls, ARRAY_SIZE(vout1_mix_controls)),
224 	SND_SOC_DAPM_MIXER("VOUT2 Mixer", SND_SOC_NOPM, 0, 0,
225 		vout2_mix_controls, ARRAY_SIZE(vout2_mix_controls)),
226 	SND_SOC_DAPM_MIXER("VOUT3 Mixer", SND_SOC_NOPM, 0, 0,
227 		vout3_mix_controls, ARRAY_SIZE(vout3_mix_controls)),
228 	SND_SOC_DAPM_MIXER("VOUT4 Mixer", SND_SOC_NOPM, 0, 0,
229 		vout4_mix_controls, ARRAY_SIZE(vout4_mix_controls)),
230 
231 	SND_SOC_DAPM_OUTPUT("VOUT1"),
232 	SND_SOC_DAPM_OUTPUT("VOUT2"),
233 	SND_SOC_DAPM_OUTPUT("VOUT3"),
234 	SND_SOC_DAPM_OUTPUT("VOUT4")
235 };
236 
237 static const struct snd_soc_dapm_route wm8770_intercon[] = {
238 	{ "Capture Mux", "AIN1", "AIN1" },
239 	{ "Capture Mux", "AIN2", "AIN2" },
240 	{ "Capture Mux", "AIN3", "AIN3" },
241 	{ "Capture Mux", "AIN4", "AIN4" },
242 	{ "Capture Mux", "AIN5", "AIN5" },
243 	{ "Capture Mux", "AIN6", "AIN6" },
244 	{ "Capture Mux", "AIN7", "AIN7" },
245 	{ "Capture Mux", "AIN8", "AIN8" },
246 
247 	{ "ADC", NULL, "Capture Mux" },
248 
249 	{ "VOUT1 Mixer", NULL, "VOUT12 Supply" },
250 	{ "VOUT1 Mixer", "DAC1 Switch", "DAC1" },
251 	{ "VOUT1 Mixer", "AUX1 Switch", "AUX1" },
252 	{ "VOUT1 Mixer", "Bypass Switch", "Capture Mux" },
253 
254 	{ "VOUT2 Mixer", NULL, "VOUT12 Supply" },
255 	{ "VOUT2 Mixer", "DAC2 Switch", "DAC2" },
256 	{ "VOUT2 Mixer", "AUX2 Switch", "AUX2" },
257 	{ "VOUT2 Mixer", "Bypass Switch", "Capture Mux" },
258 
259 	{ "VOUT3 Mixer", NULL, "VOUT34 Supply" },
260 	{ "VOUT3 Mixer", "DAC3 Switch", "DAC3" },
261 	{ "VOUT3 Mixer", "AUX3 Switch", "AUX3" },
262 	{ "VOUT3 Mixer", "Bypass Switch", "Capture Mux" },
263 
264 	{ "VOUT4 Mixer", NULL, "VOUT34 Supply" },
265 	{ "VOUT4 Mixer", "DAC4 Switch", "DAC4" },
266 	{ "VOUT4 Mixer", "Bypass Switch", "Capture Mux" },
267 
268 	{ "VOUT1", NULL, "VOUT1 Mixer" },
269 	{ "VOUT2", NULL, "VOUT2 Mixer" },
270 	{ "VOUT3", NULL, "VOUT3 Mixer" },
271 	{ "VOUT4", NULL, "VOUT4 Mixer" }
272 };
273 
274 static int vout12supply_event(struct snd_soc_dapm_widget *w,
275 	struct snd_kcontrol *kcontrol, int event)
276 {
277 	struct snd_soc_codec *codec;
278 
279 	codec = w->codec;
280 
281 	switch (event) {
282 	case SND_SOC_DAPM_PRE_PMU:
283 		snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0);
284 		break;
285 	case SND_SOC_DAPM_POST_PMD:
286 		snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0x180);
287 		break;
288 	}
289 
290 	return 0;
291 }
292 
293 static int vout34supply_event(struct snd_soc_dapm_widget *w,
294 	struct snd_kcontrol *kcontrol, int event)
295 {
296 	struct snd_soc_codec *codec;
297 
298 	codec = w->codec;
299 
300 	switch (event) {
301 	case SND_SOC_DAPM_PRE_PMU:
302 		snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0);
303 		break;
304 	case SND_SOC_DAPM_POST_PMD:
305 		snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0x180);
306 		break;
307 	}
308 
309 	return 0;
310 }
311 
312 static int wm8770_reset(struct snd_soc_codec *codec)
313 {
314 	return snd_soc_write(codec, WM8770_RESET, 0);
315 }
316 
317 static int wm8770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
318 {
319 	struct snd_soc_codec *codec;
320 	int iface, master;
321 
322 	codec = dai->codec;
323 
324 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
325 	case SND_SOC_DAIFMT_CBM_CFM:
326 		master = 0x100;
327 		break;
328 	case SND_SOC_DAIFMT_CBS_CFS:
329 		master = 0;
330 		break;
331 	default:
332 		return -EINVAL;
333 	}
334 
335 	iface = 0;
336 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
337 	case SND_SOC_DAIFMT_I2S:
338 		iface |= 0x2;
339 		break;
340 	case SND_SOC_DAIFMT_RIGHT_J:
341 		break;
342 	case SND_SOC_DAIFMT_LEFT_J:
343 		iface |= 0x1;
344 		break;
345 	default:
346 		return -EINVAL;
347 	}
348 
349 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
350 	case SND_SOC_DAIFMT_NB_NF:
351 		break;
352 	case SND_SOC_DAIFMT_IB_IF:
353 		iface |= 0xc;
354 		break;
355 	case SND_SOC_DAIFMT_IB_NF:
356 		iface |= 0x8;
357 		break;
358 	case SND_SOC_DAIFMT_NB_IF:
359 		iface |= 0x4;
360 		break;
361 	default:
362 		return -EINVAL;
363 	}
364 
365 	snd_soc_update_bits(codec, WM8770_IFACECTRL, 0xf, iface);
366 	snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x100, master);
367 
368 	return 0;
369 }
370 
371 static const int mclk_ratios[] = {
372 	128,
373 	192,
374 	256,
375 	384,
376 	512,
377 	768
378 };
379 
380 static int wm8770_hw_params(struct snd_pcm_substream *substream,
381 			    struct snd_pcm_hw_params *params,
382 			    struct snd_soc_dai *dai)
383 {
384 	struct snd_soc_codec *codec;
385 	struct wm8770_priv *wm8770;
386 	int i;
387 	int iface;
388 	int shift;
389 	int ratio;
390 
391 	codec = dai->codec;
392 	wm8770 = snd_soc_codec_get_drvdata(codec);
393 
394 	iface = 0;
395 	switch (params_format(params)) {
396 	case SNDRV_PCM_FORMAT_S16_LE:
397 		break;
398 	case SNDRV_PCM_FORMAT_S20_3LE:
399 		iface |= 0x10;
400 		break;
401 	case SNDRV_PCM_FORMAT_S24_LE:
402 		iface |= 0x20;
403 		break;
404 	case SNDRV_PCM_FORMAT_S32_LE:
405 		iface |= 0x30;
406 		break;
407 	}
408 
409 	switch (substream->stream) {
410 	case SNDRV_PCM_STREAM_PLAYBACK:
411 		i = 0;
412 		shift = 4;
413 		break;
414 	case SNDRV_PCM_STREAM_CAPTURE:
415 		i = 2;
416 		shift = 0;
417 		break;
418 	default:
419 		return -EINVAL;
420 	}
421 
422 	/* Only need to set MCLK/LRCLK ratio if we're master */
423 	if (snd_soc_read(codec, WM8770_MSTRCTRL) & 0x100) {
424 		for (; i < ARRAY_SIZE(mclk_ratios); ++i) {
425 			ratio = wm8770->sysclk / params_rate(params);
426 			if (ratio == mclk_ratios[i])
427 				break;
428 		}
429 
430 		if (i == ARRAY_SIZE(mclk_ratios)) {
431 			dev_err(codec->dev,
432 				"Unable to configure MCLK ratio %d/%d\n",
433 				wm8770->sysclk, params_rate(params));
434 			return -EINVAL;
435 		}
436 
437 		dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]);
438 
439 		snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x7 << shift,
440 				    i << shift);
441 	}
442 
443 	snd_soc_update_bits(codec, WM8770_IFACECTRL, 0x30, iface);
444 
445 	return 0;
446 }
447 
448 static int wm8770_mute(struct snd_soc_dai *dai, int mute)
449 {
450 	struct snd_soc_codec *codec;
451 
452 	codec = dai->codec;
453 	return snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10,
454 				   !!mute << 4);
455 }
456 
457 static int wm8770_set_sysclk(struct snd_soc_dai *dai,
458 			     int clk_id, unsigned int freq, int dir)
459 {
460 	struct snd_soc_codec *codec;
461 	struct wm8770_priv *wm8770;
462 
463 	codec = dai->codec;
464 	wm8770 = snd_soc_codec_get_drvdata(codec);
465 	wm8770->sysclk = freq;
466 	return 0;
467 }
468 
469 static void wm8770_sync_cache(struct snd_soc_codec *codec)
470 {
471 	int i;
472 	u16 *cache;
473 
474 	if (!codec->cache_sync)
475 		return;
476 
477 	codec->cache_only = 0;
478 	cache = codec->reg_cache;
479 	for (i = 0; i < codec->driver->reg_cache_size; i++) {
480 		if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i])
481 			continue;
482 		snd_soc_write(codec, i, cache[i]);
483 	}
484 	codec->cache_sync = 0;
485 }
486 
487 static int wm8770_set_bias_level(struct snd_soc_codec *codec,
488 				 enum snd_soc_bias_level level)
489 {
490 	int ret;
491 	struct wm8770_priv *wm8770;
492 
493 	wm8770 = snd_soc_codec_get_drvdata(codec);
494 
495 	switch (level) {
496 	case SND_SOC_BIAS_ON:
497 		break;
498 	case SND_SOC_BIAS_PREPARE:
499 		break;
500 	case SND_SOC_BIAS_STANDBY:
501 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
502 			ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
503 						    wm8770->supplies);
504 			if (ret) {
505 				dev_err(codec->dev,
506 					"Failed to enable supplies: %d\n",
507 					ret);
508 				return ret;
509 			}
510 			wm8770_sync_cache(codec);
511 			/* global powerup */
512 			snd_soc_write(codec, WM8770_PWDNCTRL, 0);
513 		}
514 		break;
515 	case SND_SOC_BIAS_OFF:
516 		/* global powerdown */
517 		snd_soc_write(codec, WM8770_PWDNCTRL, 1);
518 		regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies),
519 				       wm8770->supplies);
520 		break;
521 	}
522 
523 	codec->dapm.bias_level = level;
524 	return 0;
525 }
526 
527 #define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
528 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
529 
530 static const struct snd_soc_dai_ops wm8770_dai_ops = {
531 	.digital_mute = wm8770_mute,
532 	.hw_params = wm8770_hw_params,
533 	.set_fmt = wm8770_set_fmt,
534 	.set_sysclk = wm8770_set_sysclk,
535 };
536 
537 static struct snd_soc_dai_driver wm8770_dai = {
538 	.name = "wm8770-hifi",
539 	.playback = {
540 		.stream_name = "Playback",
541 		.channels_min = 2,
542 		.channels_max = 2,
543 		.rates = SNDRV_PCM_RATE_8000_192000,
544 		.formats = WM8770_FORMATS
545 	},
546 	.capture = {
547 		.stream_name = "Capture",
548 		.channels_min = 2,
549 		.channels_max = 2,
550 		.rates = SNDRV_PCM_RATE_8000_96000,
551 		.formats = WM8770_FORMATS
552 	},
553 	.ops = &wm8770_dai_ops,
554 	.symmetric_rates = 1
555 };
556 
557 #ifdef CONFIG_PM
558 static int wm8770_suspend(struct snd_soc_codec *codec)
559 {
560 	wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
561 	return 0;
562 }
563 
564 static int wm8770_resume(struct snd_soc_codec *codec)
565 {
566 	wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
567 	return 0;
568 }
569 #else
570 #define wm8770_suspend NULL
571 #define wm8770_resume NULL
572 #endif
573 
574 static int wm8770_probe(struct snd_soc_codec *codec)
575 {
576 	struct wm8770_priv *wm8770;
577 	int ret;
578 	int i;
579 
580 	wm8770 = snd_soc_codec_get_drvdata(codec);
581 	wm8770->codec = codec;
582 
583 	codec->dapm.idle_bias_off = 1;
584 
585 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
586 	if (ret < 0) {
587 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
588 		return ret;
589 	}
590 
591 	for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
592 		wm8770->supplies[i].supply = wm8770_supply_names[i];
593 
594 	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
595 				 wm8770->supplies);
596 	if (ret) {
597 		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
598 		return ret;
599 	}
600 
601 	wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
602 	wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
603 	wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
604 
605 	/* This should really be moved into the regulator core */
606 	for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
607 		ret = regulator_register_notifier(wm8770->supplies[i].consumer,
608 						  &wm8770->disable_nb[i]);
609 		if (ret) {
610 			dev_err(codec->dev,
611 				"Failed to register regulator notifier: %d\n",
612 				ret);
613 		}
614 	}
615 
616 	ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
617 				    wm8770->supplies);
618 	if (ret) {
619 		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
620 		goto err_reg_get;
621 	}
622 
623 	ret = wm8770_reset(codec);
624 	if (ret < 0) {
625 		dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
626 		goto err_reg_enable;
627 	}
628 
629 	wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
630 
631 	/* latch the volume update bits */
632 	snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
633 	snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
634 	snd_soc_update_bits(codec, WM8770_VOUT1RVOL, 0x100, 0x100);
635 	snd_soc_update_bits(codec, WM8770_VOUT2RVOL, 0x100, 0x100);
636 	snd_soc_update_bits(codec, WM8770_VOUT3RVOL, 0x100, 0x100);
637 	snd_soc_update_bits(codec, WM8770_VOUT4RVOL, 0x100, 0x100);
638 	snd_soc_update_bits(codec, WM8770_DAC1RVOL, 0x100, 0x100);
639 	snd_soc_update_bits(codec, WM8770_DAC2RVOL, 0x100, 0x100);
640 	snd_soc_update_bits(codec, WM8770_DAC3RVOL, 0x100, 0x100);
641 	snd_soc_update_bits(codec, WM8770_DAC4RVOL, 0x100, 0x100);
642 
643 	/* mute all DACs */
644 	snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
645 
646 	snd_soc_add_controls(codec, wm8770_snd_controls,
647 			     ARRAY_SIZE(wm8770_snd_controls));
648 	snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
649 				  ARRAY_SIZE(wm8770_dapm_widgets));
650 	snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
651 				ARRAY_SIZE(wm8770_intercon));
652 	return 0;
653 
654 err_reg_enable:
655 	regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
656 err_reg_get:
657 	regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
658 	return ret;
659 }
660 
661 static int wm8770_remove(struct snd_soc_codec *codec)
662 {
663 	struct wm8770_priv *wm8770;
664 	int i;
665 
666 	wm8770 = snd_soc_codec_get_drvdata(codec);
667 	wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
668 
669 	for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
670 		regulator_unregister_notifier(wm8770->supplies[i].consumer,
671 					      &wm8770->disable_nb[i]);
672 	regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
673 	return 0;
674 }
675 
676 static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
677 	.probe = wm8770_probe,
678 	.remove = wm8770_remove,
679 	.suspend = wm8770_suspend,
680 	.resume = wm8770_resume,
681 	.set_bias_level = wm8770_set_bias_level,
682 	.reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
683 	.reg_word_size = sizeof (u16),
684 	.reg_cache_default = wm8770_reg_defs
685 };
686 
687 static const struct of_device_id wm8770_of_match[] = {
688 	{ .compatible = "wlf,wm8770", },
689 	{ }
690 };
691 MODULE_DEVICE_TABLE(of, wm8770_of_match);
692 
693 static int __devinit wm8770_spi_probe(struct spi_device *spi)
694 {
695 	struct wm8770_priv *wm8770;
696 	int ret;
697 
698 	wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
699 			      GFP_KERNEL);
700 	if (!wm8770)
701 		return -ENOMEM;
702 
703 	wm8770->control_type = SND_SOC_SPI;
704 	spi_set_drvdata(spi, wm8770);
705 
706 	ret = snd_soc_register_codec(&spi->dev,
707 				     &soc_codec_dev_wm8770, &wm8770_dai, 1);
708 
709 	return ret;
710 }
711 
712 static int __devexit wm8770_spi_remove(struct spi_device *spi)
713 {
714 	snd_soc_unregister_codec(&spi->dev);
715 	return 0;
716 }
717 
718 static struct spi_driver wm8770_spi_driver = {
719 	.driver = {
720 		.name = "wm8770",
721 		.owner = THIS_MODULE,
722 		.of_match_table = wm8770_of_match,
723 	},
724 	.probe = wm8770_spi_probe,
725 	.remove = __devexit_p(wm8770_spi_remove)
726 };
727 
728 static int __init wm8770_modinit(void)
729 {
730 	int ret = 0;
731 
732 	ret = spi_register_driver(&wm8770_spi_driver);
733 	if (ret) {
734 		printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n",
735 		       ret);
736 	}
737 	return ret;
738 }
739 module_init(wm8770_modinit);
740 
741 static void __exit wm8770_exit(void)
742 {
743 	spi_unregister_driver(&wm8770_spi_driver);
744 }
745 module_exit(wm8770_exit);
746 
747 MODULE_DESCRIPTION("ASoC WM8770 driver");
748 MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
749 MODULE_LICENSE("GPL");
750