Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wm8770.c
Go to the documentation of this file.
1 /*
2  * wm8770.c -- WM8770 ALSA SoC Audio driver
3  *
4  * Copyright 2010 Wolfson Microelectronics plc
5  *
6  * Author: Dimitris Papastamos <[email protected]>
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>
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 {
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 
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 */
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) {
283  snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0);
284  break;
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) {
302  snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0);
303  break;
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) {
326  master = 0x100;
327  break;
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;
341  break;
343  iface |= 0x1;
344  break;
345  default:
346  return -EINVAL;
347  }
348 
349  switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
351  break;
353  iface |= 0xc;
354  break;
356  iface |= 0x8;
357  break;
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)) {
397  break;
399  iface |= 0x10;
400  break;
402  iface |= 0x20;
403  break;
405  iface |= 0x30;
406  break;
407  }
408 
409  switch (substream->stream) {
411  i = 0;
412  shift = 4;
413  break;
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,
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;
499  break;
501  if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
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);
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,
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  ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
584  if (ret < 0) {
585  dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
586  return ret;
587  }
588 
589  for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
590  wm8770->supplies[i].supply = wm8770_supply_names[i];
591 
592  ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
593  wm8770->supplies);
594  if (ret) {
595  dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
596  return ret;
597  }
598 
599  wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
600  wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
601  wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
602 
603  /* This should really be moved into the regulator core */
604  for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
605  ret = regulator_register_notifier(wm8770->supplies[i].consumer,
606  &wm8770->disable_nb[i]);
607  if (ret) {
608  dev_err(codec->dev,
609  "Failed to register regulator notifier: %d\n",
610  ret);
611  }
612  }
613 
615  wm8770->supplies);
616  if (ret) {
617  dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
618  goto err_reg_get;
619  }
620 
621  ret = wm8770_reset(codec);
622  if (ret < 0) {
623  dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
624  goto err_reg_enable;
625  }
626 
627  wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
628 
629  /* latch the volume update bits */
630  snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
631  snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
632  snd_soc_update_bits(codec, WM8770_VOUT1RVOL, 0x100, 0x100);
633  snd_soc_update_bits(codec, WM8770_VOUT2RVOL, 0x100, 0x100);
634  snd_soc_update_bits(codec, WM8770_VOUT3RVOL, 0x100, 0x100);
635  snd_soc_update_bits(codec, WM8770_VOUT4RVOL, 0x100, 0x100);
636  snd_soc_update_bits(codec, WM8770_DAC1RVOL, 0x100, 0x100);
637  snd_soc_update_bits(codec, WM8770_DAC2RVOL, 0x100, 0x100);
638  snd_soc_update_bits(codec, WM8770_DAC3RVOL, 0x100, 0x100);
639  snd_soc_update_bits(codec, WM8770_DAC4RVOL, 0x100, 0x100);
640 
641  /* mute all DACs */
642  snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
643 
644  snd_soc_add_codec_controls(codec, wm8770_snd_controls,
645  ARRAY_SIZE(wm8770_snd_controls));
646  snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
647  ARRAY_SIZE(wm8770_dapm_widgets));
648  snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
649  ARRAY_SIZE(wm8770_intercon));
650  return 0;
651 
652 err_reg_enable:
654 err_reg_get:
655  regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
656  return ret;
657 }
658 
659 static int wm8770_remove(struct snd_soc_codec *codec)
660 {
661  struct wm8770_priv *wm8770;
662  int i;
663 
664  wm8770 = snd_soc_codec_get_drvdata(codec);
665  wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
666 
667  for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
668  regulator_unregister_notifier(wm8770->supplies[i].consumer,
669  &wm8770->disable_nb[i]);
670  regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
671  return 0;
672 }
673 
674 static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
675  .probe = wm8770_probe,
676  .remove = wm8770_remove,
677  .suspend = wm8770_suspend,
678  .resume = wm8770_resume,
679  .set_bias_level = wm8770_set_bias_level,
680  .idle_bias_off = true,
681  .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
682  .reg_word_size = sizeof (u16),
683  .reg_cache_default = wm8770_reg_defs
684 };
685 
686 static const struct of_device_id wm8770_of_match[] = {
687  { .compatible = "wlf,wm8770", },
688  { }
689 };
690 MODULE_DEVICE_TABLE(of, wm8770_of_match);
691 
692 static int __devinit wm8770_spi_probe(struct spi_device *spi)
693 {
694  struct wm8770_priv *wm8770;
695  int ret;
696 
697  wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
698  GFP_KERNEL);
699  if (!wm8770)
700  return -ENOMEM;
701 
702  wm8770->control_type = SND_SOC_SPI;
703  spi_set_drvdata(spi, wm8770);
704 
705  ret = snd_soc_register_codec(&spi->dev,
706  &soc_codec_dev_wm8770, &wm8770_dai, 1);
707 
708  return ret;
709 }
710 
711 static int __devexit wm8770_spi_remove(struct spi_device *spi)
712 {
714  return 0;
715 }
716 
717 static struct spi_driver wm8770_spi_driver = {
718  .driver = {
719  .name = "wm8770",
720  .owner = THIS_MODULE,
721  .of_match_table = wm8770_of_match,
722  },
723  .probe = wm8770_spi_probe,
724  .remove = __devexit_p(wm8770_spi_remove)
725 };
726 
727 module_spi_driver(wm8770_spi_driver);
728 
729 MODULE_DESCRIPTION("ASoC WM8770 driver");
730 MODULE_AUTHOR("Dimitris Papastamos <[email protected]>");
731 MODULE_LICENSE("GPL");