Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wm8510.c
Go to the documentation of this file.
1 /*
2  * wm8510.c -- WM8510 ALSA Soc Audio driver
3  *
4  * Copyright 2006 Wolfson Microelectronics PLC.
5  *
6  * Author: Liam Girdwood <[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/kernel.h>
16 #include <linux/init.h>
17 #include <linux/delay.h>
18 #include <linux/pm.h>
19 #include <linux/i2c.h>
20 #include <linux/spi/spi.h>
21 #include <linux/slab.h>
22 #include <linux/of_device.h>
23 #include <linux/regmap.h>
24 #include <sound/core.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/soc.h>
28 #include <sound/initval.h>
29 
30 #include "wm8510.h"
31 
32 /*
33  * wm8510 register cache
34  * We can't read the WM8510 register space when we are
35  * using 2 wire for device control, so we cache them instead.
36  */
37 static const struct reg_default wm8510_reg_defaults[] = {
38  { 1, 0x0000 },
39  { 2, 0x0000 },
40  { 3, 0x0000 },
41  { 4, 0x0050 },
42  { 5, 0x0000 },
43  { 6, 0x0140 },
44  { 7, 0x0000 },
45  { 8, 0x0000 },
46  { 9, 0x0000 },
47  { 10, 0x0000 },
48  { 11, 0x00ff },
49  { 12, 0x0000 },
50  { 13, 0x0000 },
51  { 14, 0x0100 },
52  { 15, 0x00ff },
53  { 16, 0x0000 },
54  { 17, 0x0000 },
55  { 18, 0x012c },
56  { 19, 0x002c },
57  { 20, 0x002c },
58  { 21, 0x002c },
59  { 22, 0x002c },
60  { 23, 0x0000 },
61  { 24, 0x0032 },
62  { 25, 0x0000 },
63  { 26, 0x0000 },
64  { 27, 0x0000 },
65  { 28, 0x0000 },
66  { 29, 0x0000 },
67  { 30, 0x0000 },
68  { 31, 0x0000 },
69  { 32, 0x0038 },
70  { 33, 0x000b },
71  { 34, 0x0032 },
72  { 35, 0x0000 },
73  { 36, 0x0008 },
74  { 37, 0x000c },
75  { 38, 0x0093 },
76  { 39, 0x00e9 },
77  { 40, 0x0000 },
78  { 41, 0x0000 },
79  { 42, 0x0000 },
80  { 43, 0x0000 },
81  { 44, 0x0003 },
82  { 45, 0x0010 },
83  { 46, 0x0000 },
84  { 47, 0x0000 },
85  { 48, 0x0000 },
86  { 49, 0x0002 },
87  { 50, 0x0001 },
88  { 51, 0x0000 },
89  { 52, 0x0000 },
90  { 53, 0x0000 },
91  { 54, 0x0039 },
92  { 55, 0x0000 },
93  { 56, 0x0001 },
94 };
95 
96 static bool wm8510_volatile(struct device *dev, unsigned int reg)
97 {
98  switch (reg) {
99  case WM8510_RESET:
100  return true;
101  default:
102  return false;
103  }
104 }
105 
106 #define WM8510_POWER1_BIASEN 0x08
107 #define WM8510_POWER1_BUFIOEN 0x10
108 
109 #define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
110 
111 /* codec private data */
112 struct wm8510_priv {
113  struct regmap *regmap;
114 };
115 
116 static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
117 static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
118 static const char *wm8510_alc[] = { "ALC", "Limiter" };
119 
120 static const struct soc_enum wm8510_enum[] = {
121  SOC_ENUM_SINGLE(WM8510_COMP, 1, 4, wm8510_companding), /* adc */
122  SOC_ENUM_SINGLE(WM8510_COMP, 3, 4, wm8510_companding), /* dac */
123  SOC_ENUM_SINGLE(WM8510_DAC, 4, 4, wm8510_deemp),
124  SOC_ENUM_SINGLE(WM8510_ALC3, 8, 2, wm8510_alc),
125 };
126 
127 static const struct snd_kcontrol_new wm8510_snd_controls[] = {
128 
129 SOC_SINGLE("Digital Loopback Switch", WM8510_COMP, 0, 1, 0),
130 
131 SOC_ENUM("DAC Companding", wm8510_enum[1]),
132 SOC_ENUM("ADC Companding", wm8510_enum[0]),
133 
134 SOC_ENUM("Playback De-emphasis", wm8510_enum[2]),
135 SOC_SINGLE("DAC Inversion Switch", WM8510_DAC, 0, 1, 0),
136 
137 SOC_SINGLE("Master Playback Volume", WM8510_DACVOL, 0, 127, 0),
138 
139 SOC_SINGLE("High Pass Filter Switch", WM8510_ADC, 8, 1, 0),
140 SOC_SINGLE("High Pass Cut Off", WM8510_ADC, 4, 7, 0),
141 SOC_SINGLE("ADC Inversion Switch", WM8510_COMP, 0, 1, 0),
142 
143 SOC_SINGLE("Capture Volume", WM8510_ADCVOL, 0, 127, 0),
144 
145 SOC_SINGLE("DAC Playback Limiter Switch", WM8510_DACLIM1, 8, 1, 0),
146 SOC_SINGLE("DAC Playback Limiter Decay", WM8510_DACLIM1, 4, 15, 0),
147 SOC_SINGLE("DAC Playback Limiter Attack", WM8510_DACLIM1, 0, 15, 0),
148 
149 SOC_SINGLE("DAC Playback Limiter Threshold", WM8510_DACLIM2, 4, 7, 0),
150 SOC_SINGLE("DAC Playback Limiter Boost", WM8510_DACLIM2, 0, 15, 0),
151 
152 SOC_SINGLE("ALC Enable Switch", WM8510_ALC1, 8, 1, 0),
153 SOC_SINGLE("ALC Capture Max Gain", WM8510_ALC1, 3, 7, 0),
154 SOC_SINGLE("ALC Capture Min Gain", WM8510_ALC1, 0, 7, 0),
155 
156 SOC_SINGLE("ALC Capture ZC Switch", WM8510_ALC2, 8, 1, 0),
157 SOC_SINGLE("ALC Capture Hold", WM8510_ALC2, 4, 7, 0),
158 SOC_SINGLE("ALC Capture Target", WM8510_ALC2, 0, 15, 0),
159 
160 SOC_ENUM("ALC Capture Mode", wm8510_enum[3]),
161 SOC_SINGLE("ALC Capture Decay", WM8510_ALC3, 4, 15, 0),
162 SOC_SINGLE("ALC Capture Attack", WM8510_ALC3, 0, 15, 0),
163 
164 SOC_SINGLE("ALC Capture Noise Gate Switch", WM8510_NGATE, 3, 1, 0),
165 SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8510_NGATE, 0, 7, 0),
166 
167 SOC_SINGLE("Capture PGA ZC Switch", WM8510_INPPGA, 7, 1, 0),
168 SOC_SINGLE("Capture PGA Volume", WM8510_INPPGA, 0, 63, 0),
169 
170 SOC_SINGLE("Speaker Playback ZC Switch", WM8510_SPKVOL, 7, 1, 0),
171 SOC_SINGLE("Speaker Playback Switch", WM8510_SPKVOL, 6, 1, 1),
172 SOC_SINGLE("Speaker Playback Volume", WM8510_SPKVOL, 0, 63, 0),
173 SOC_SINGLE("Speaker Boost", WM8510_OUTPUT, 2, 1, 0),
174 
175 SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST, 8, 1, 0),
176 SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1),
177 };
178 
179 /* Speaker Output Mixer */
180 static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = {
181 SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0),
182 SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_SPKMIX, 5, 1, 0),
183 SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_SPKMIX, 0, 1, 0),
184 };
185 
186 /* Mono Output Mixer */
187 static const struct snd_kcontrol_new wm8510_mono_mixer_controls[] = {
188 SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_MONOMIX, 1, 1, 0),
189 SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_MONOMIX, 2, 1, 0),
190 SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_MONOMIX, 0, 1, 0),
191 };
192 
193 static const struct snd_kcontrol_new wm8510_boost_controls[] = {
194 SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA, 6, 1, 1),
195 SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0),
196 SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0),
197 };
198 
199 static const struct snd_kcontrol_new wm8510_micpga_controls[] = {
200 SOC_DAPM_SINGLE("MICP Switch", WM8510_INPUT, 0, 1, 0),
201 SOC_DAPM_SINGLE("MICN Switch", WM8510_INPUT, 1, 1, 0),
202 SOC_DAPM_SINGLE("AUX Switch", WM8510_INPUT, 2, 1, 0),
203 };
204 
205 static const struct snd_soc_dapm_widget wm8510_dapm_widgets[] = {
206 SND_SOC_DAPM_MIXER("Speaker Mixer", WM8510_POWER3, 2, 0,
207  &wm8510_speaker_mixer_controls[0],
208  ARRAY_SIZE(wm8510_speaker_mixer_controls)),
209 SND_SOC_DAPM_MIXER("Mono Mixer", WM8510_POWER3, 3, 0,
210  &wm8510_mono_mixer_controls[0],
211  ARRAY_SIZE(wm8510_mono_mixer_controls)),
212 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8510_POWER3, 0, 0),
213 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8510_POWER2, 0, 0),
214 SND_SOC_DAPM_PGA("Aux Input", WM8510_POWER1, 6, 0, NULL, 0),
215 SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
216 SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
217 SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
218 
219 SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0,
220  &wm8510_micpga_controls[0],
221  ARRAY_SIZE(wm8510_micpga_controls)),
222 SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
223  &wm8510_boost_controls[0],
224  ARRAY_SIZE(wm8510_boost_controls)),
225 
226 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8510_POWER1, 4, 0),
227 
228 SND_SOC_DAPM_INPUT("MICN"),
229 SND_SOC_DAPM_INPUT("MICP"),
230 SND_SOC_DAPM_INPUT("AUX"),
231 SND_SOC_DAPM_OUTPUT("MONOOUT"),
232 SND_SOC_DAPM_OUTPUT("SPKOUTP"),
233 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
234 };
235 
236 static const struct snd_soc_dapm_route wm8510_dapm_routes[] = {
237  /* Mono output mixer */
238  {"Mono Mixer", "PCM Playback Switch", "DAC"},
239  {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
240  {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
241 
242  /* Speaker output mixer */
243  {"Speaker Mixer", "PCM Playback Switch", "DAC"},
244  {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
245  {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
246 
247  /* Outputs */
248  {"Mono Out", NULL, "Mono Mixer"},
249  {"MONOOUT", NULL, "Mono Out"},
250  {"SpkN Out", NULL, "Speaker Mixer"},
251  {"SpkP Out", NULL, "Speaker Mixer"},
252  {"SPKOUTN", NULL, "SpkN Out"},
253  {"SPKOUTP", NULL, "SpkP Out"},
254 
255  /* Microphone PGA */
256  {"Mic PGA", "MICN Switch", "MICN"},
257  {"Mic PGA", "MICP Switch", "MICP"},
258  { "Mic PGA", "AUX Switch", "Aux Input" },
259 
260  /* Boost Mixer */
261  {"Boost Mixer", "Mic PGA Switch", "Mic PGA"},
262  {"Boost Mixer", "Mic Volume", "MICP"},
263  {"Boost Mixer", "Aux Volume", "Aux Input"},
264 
265  {"ADC", NULL, "Boost Mixer"},
266 };
267 
268 struct pll_ {
269  unsigned int pre_div:4; /* prescale - 1 */
270  unsigned int n:4;
271  unsigned int k;
272 };
273 
274 static struct pll_ pll_div;
275 
276 /* The size in bits of the pll divide multiplied by 10
277  * to allow rounding later */
278 #define FIXED_PLL_SIZE ((1 << 24) * 10)
279 
280 static void pll_factors(unsigned int target, unsigned int source)
281 {
282  unsigned long long Kpart;
283  unsigned int K, Ndiv, Nmod;
284 
285  Ndiv = target / source;
286  if (Ndiv < 6) {
287  source >>= 1;
288  pll_div.pre_div = 1;
289  Ndiv = target / source;
290  } else
291  pll_div.pre_div = 0;
292 
293  if ((Ndiv < 6) || (Ndiv > 12))
295  "WM8510 N value %u outwith recommended range!d\n",
296  Ndiv);
297 
298  pll_div.n = Ndiv;
299  Nmod = target % source;
300  Kpart = FIXED_PLL_SIZE * (long long)Nmod;
301 
302  do_div(Kpart, source);
303 
304  K = Kpart & 0xFFFFFFFF;
305 
306  /* Check if we need to round */
307  if ((K % 10) >= 5)
308  K += 5;
309 
310  /* Move down to proper range now rounding is done */
311  K /= 10;
312 
313  pll_div.k = K;
314 }
315 
316 static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
317  int source, unsigned int freq_in, unsigned int freq_out)
318 {
319  struct snd_soc_codec *codec = codec_dai->codec;
320  u16 reg;
321 
322  if (freq_in == 0 || freq_out == 0) {
323  /* Clock CODEC directly from MCLK */
324  reg = snd_soc_read(codec, WM8510_CLOCK);
325  snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff);
326 
327  /* Turn off PLL */
328  reg = snd_soc_read(codec, WM8510_POWER1);
329  snd_soc_write(codec, WM8510_POWER1, reg & 0x1df);
330  return 0;
331  }
332 
333  pll_factors(freq_out*4, freq_in);
334 
335  snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
336  snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18);
337  snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
338  snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
339  reg = snd_soc_read(codec, WM8510_POWER1);
340  snd_soc_write(codec, WM8510_POWER1, reg | 0x020);
341 
342  /* Run CODEC from PLL instead of MCLK */
343  reg = snd_soc_read(codec, WM8510_CLOCK);
344  snd_soc_write(codec, WM8510_CLOCK, reg | 0x100);
345 
346  return 0;
347 }
348 
349 /*
350  * Configure WM8510 clock dividers.
351  */
352 static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
353  int div_id, int div)
354 {
355  struct snd_soc_codec *codec = codec_dai->codec;
356  u16 reg;
357 
358  switch (div_id) {
359  case WM8510_OPCLKDIV:
360  reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf;
361  snd_soc_write(codec, WM8510_GPIO, reg | div);
362  break;
363  case WM8510_MCLKDIV:
364  reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f;
365  snd_soc_write(codec, WM8510_CLOCK, reg | div);
366  break;
367  case WM8510_ADCCLK:
368  reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7;
369  snd_soc_write(codec, WM8510_ADC, reg | div);
370  break;
371  case WM8510_DACCLK:
372  reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7;
373  snd_soc_write(codec, WM8510_DAC, reg | div);
374  break;
375  case WM8510_BCLKDIV:
376  reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3;
377  snd_soc_write(codec, WM8510_CLOCK, reg | div);
378  break;
379  default:
380  return -EINVAL;
381  }
382 
383  return 0;
384 }
385 
386 static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
387  unsigned int fmt)
388 {
389  struct snd_soc_codec *codec = codec_dai->codec;
390  u16 iface = 0;
391  u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe;
392 
393  /* set master/slave audio interface */
394  switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
396  clk |= 0x0001;
397  break;
399  break;
400  default:
401  return -EINVAL;
402  }
403 
404  /* interface format */
405  switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
406  case SND_SOC_DAIFMT_I2S:
407  iface |= 0x0010;
408  break;
410  break;
412  iface |= 0x0008;
413  break;
415  iface |= 0x00018;
416  break;
417  default:
418  return -EINVAL;
419  }
420 
421  /* clock inversion */
422  switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
424  break;
426  iface |= 0x0180;
427  break;
429  iface |= 0x0100;
430  break;
432  iface |= 0x0080;
433  break;
434  default:
435  return -EINVAL;
436  }
437 
438  snd_soc_write(codec, WM8510_IFACE, iface);
439  snd_soc_write(codec, WM8510_CLOCK, clk);
440  return 0;
441 }
442 
443 static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
444  struct snd_pcm_hw_params *params,
445  struct snd_soc_dai *dai)
446 {
447  struct snd_soc_codec *codec = dai->codec;
448  u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
449  u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
450 
451  /* bit size */
452  switch (params_format(params)) {
454  break;
456  iface |= 0x0020;
457  break;
459  iface |= 0x0040;
460  break;
462  iface |= 0x0060;
463  break;
464  }
465 
466  /* filter coefficient */
467  switch (params_rate(params)) {
468  case 8000:
469  adn |= 0x5 << 1;
470  break;
471  case 11025:
472  adn |= 0x4 << 1;
473  break;
474  case 16000:
475  adn |= 0x3 << 1;
476  break;
477  case 22050:
478  adn |= 0x2 << 1;
479  break;
480  case 32000:
481  adn |= 0x1 << 1;
482  break;
483  case 44100:
484  case 48000:
485  break;
486  }
487 
488  snd_soc_write(codec, WM8510_IFACE, iface);
489  snd_soc_write(codec, WM8510_ADD, adn);
490  return 0;
491 }
492 
493 static int wm8510_mute(struct snd_soc_dai *dai, int mute)
494 {
495  struct snd_soc_codec *codec = dai->codec;
496  u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf;
497 
498  if (mute)
499  snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40);
500  else
501  snd_soc_write(codec, WM8510_DAC, mute_reg);
502  return 0;
503 }
504 
505 /* liam need to make this lower power with dapm */
506 static int wm8510_set_bias_level(struct snd_soc_codec *codec,
508 {
509  struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
510  u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3;
511 
512  switch (level) {
513  case SND_SOC_BIAS_ON:
515  power1 |= 0x1; /* VMID 50k */
516  snd_soc_write(codec, WM8510_POWER1, power1);
517  break;
518 
521 
522  if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
523  regcache_sync(wm8510->regmap);
524 
525  /* Initial cap charge at VMID 5k */
526  snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
527  mdelay(100);
528  }
529 
530  power1 |= 0x2; /* VMID 500k */
531  snd_soc_write(codec, WM8510_POWER1, power1);
532  break;
533 
534  case SND_SOC_BIAS_OFF:
535  snd_soc_write(codec, WM8510_POWER1, 0);
536  snd_soc_write(codec, WM8510_POWER2, 0);
537  snd_soc_write(codec, WM8510_POWER3, 0);
538  break;
539  }
540 
541  codec->dapm.bias_level = level;
542  return 0;
543 }
544 
545 #define WM8510_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
546  SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
547  SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
548 
549 #define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
550  SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
551 
552 static const struct snd_soc_dai_ops wm8510_dai_ops = {
553  .hw_params = wm8510_pcm_hw_params,
554  .digital_mute = wm8510_mute,
555  .set_fmt = wm8510_set_dai_fmt,
556  .set_clkdiv = wm8510_set_dai_clkdiv,
557  .set_pll = wm8510_set_dai_pll,
558 };
559 
560 static struct snd_soc_dai_driver wm8510_dai = {
561  .name = "wm8510-hifi",
562  .playback = {
563  .stream_name = "Playback",
564  .channels_min = 2,
565  .channels_max = 2,
566  .rates = WM8510_RATES,
567  .formats = WM8510_FORMATS,},
568  .capture = {
569  .stream_name = "Capture",
570  .channels_min = 2,
571  .channels_max = 2,
572  .rates = WM8510_RATES,
573  .formats = WM8510_FORMATS,},
574  .ops = &wm8510_dai_ops,
575  .symmetric_rates = 1,
576 };
577 
578 static int wm8510_suspend(struct snd_soc_codec *codec)
579 {
580  wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
581  return 0;
582 }
583 
584 static int wm8510_resume(struct snd_soc_codec *codec)
585 {
586  wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
587  return 0;
588 }
589 
590 static int wm8510_probe(struct snd_soc_codec *codec)
591 {
592  int ret;
593 
594  ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
595  if (ret < 0) {
596  printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret);
597  return ret;
598  }
599 
600  wm8510_reset(codec);
601 
602  /* power on device */
603  wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
604 
605  return ret;
606 }
607 
608 /* power down chip */
609 static int wm8510_remove(struct snd_soc_codec *codec)
610 {
611  struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
612 
613  wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
614  kfree(wm8510);
615  return 0;
616 }
617 
618 static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
619  .probe = wm8510_probe,
620  .remove = wm8510_remove,
621  .suspend = wm8510_suspend,
622  .resume = wm8510_resume,
623  .set_bias_level = wm8510_set_bias_level,
624 
625  .controls = wm8510_snd_controls,
626  .num_controls = ARRAY_SIZE(wm8510_snd_controls),
627  .dapm_widgets = wm8510_dapm_widgets,
628  .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets),
629  .dapm_routes = wm8510_dapm_routes,
630  .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes),
631 };
632 
633 static const struct of_device_id wm8510_of_match[] = {
634  { .compatible = "wlf,wm8510" },
635  { },
636 };
637 
638 static const struct regmap_config wm8510_regmap = {
639  .reg_bits = 7,
640  .val_bits = 9,
641  .max_register = WM8510_MONOMIX,
642 
643  .reg_defaults = wm8510_reg_defaults,
644  .num_reg_defaults = ARRAY_SIZE(wm8510_reg_defaults),
645  .cache_type = REGCACHE_RBTREE,
646 
647  .volatile_reg = wm8510_volatile,
648 };
649 
650 #if defined(CONFIG_SPI_MASTER)
651 static int __devinit wm8510_spi_probe(struct spi_device *spi)
652 {
653  struct wm8510_priv *wm8510;
654  int ret;
655 
656  wm8510 = devm_kzalloc(&spi->dev, sizeof(struct wm8510_priv),
657  GFP_KERNEL);
658  if (wm8510 == NULL)
659  return -ENOMEM;
660 
661  wm8510->regmap = devm_regmap_init_spi(spi, &wm8510_regmap);
662  if (IS_ERR(wm8510->regmap))
663  return PTR_ERR(wm8510->regmap);
664 
665  spi_set_drvdata(spi, wm8510);
666 
667  ret = snd_soc_register_codec(&spi->dev,
668  &soc_codec_dev_wm8510, &wm8510_dai, 1);
669 
670  return ret;
671 }
672 
673 static int __devexit wm8510_spi_remove(struct spi_device *spi)
674 {
676  return 0;
677 }
678 
679 static struct spi_driver wm8510_spi_driver = {
680  .driver = {
681  .name = "wm8510",
682  .owner = THIS_MODULE,
683  .of_match_table = wm8510_of_match,
684  },
685  .probe = wm8510_spi_probe,
686  .remove = __devexit_p(wm8510_spi_remove),
687 };
688 #endif /* CONFIG_SPI_MASTER */
689 
690 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
691 static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
692  const struct i2c_device_id *id)
693 {
694  struct wm8510_priv *wm8510;
695  int ret;
696 
697  wm8510 = devm_kzalloc(&i2c->dev, sizeof(struct wm8510_priv),
698  GFP_KERNEL);
699  if (wm8510 == NULL)
700  return -ENOMEM;
701 
702  wm8510->regmap = devm_regmap_init_i2c(i2c, &wm8510_regmap);
703  if (IS_ERR(wm8510->regmap))
704  return PTR_ERR(wm8510->regmap);
705 
706  i2c_set_clientdata(i2c, wm8510);
707 
708  ret = snd_soc_register_codec(&i2c->dev,
709  &soc_codec_dev_wm8510, &wm8510_dai, 1);
710 
711  return ret;
712 }
713 
714 static __devexit int wm8510_i2c_remove(struct i2c_client *client)
715 {
716  snd_soc_unregister_codec(&client->dev);
717  return 0;
718 }
719 
720 static const struct i2c_device_id wm8510_i2c_id[] = {
721  { "wm8510", 0 },
722  { }
723 };
724 MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
725 
726 static struct i2c_driver wm8510_i2c_driver = {
727  .driver = {
728  .name = "wm8510",
729  .owner = THIS_MODULE,
730  .of_match_table = wm8510_of_match,
731  },
732  .probe = wm8510_i2c_probe,
733  .remove = __devexit_p(wm8510_i2c_remove),
734  .id_table = wm8510_i2c_id,
735 };
736 #endif
737 
738 static int __init wm8510_modinit(void)
739 {
740  int ret = 0;
741 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
742  ret = i2c_add_driver(&wm8510_i2c_driver);
743  if (ret != 0) {
744  printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n",
745  ret);
746  }
747 #endif
748 #if defined(CONFIG_SPI_MASTER)
749  ret = spi_register_driver(&wm8510_spi_driver);
750  if (ret != 0) {
751  printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n",
752  ret);
753  }
754 #endif
755  return ret;
756 }
757 module_init(wm8510_modinit);
758 
759 static void __exit wm8510_exit(void)
760 {
761 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
762  i2c_del_driver(&wm8510_i2c_driver);
763 #endif
764 #if defined(CONFIG_SPI_MASTER)
765  spi_unregister_driver(&wm8510_spi_driver);
766 #endif
767 }
768 module_exit(wm8510_exit);
769 
770 MODULE_DESCRIPTION("ASoC WM8510 driver");
771 MODULE_AUTHOR("Liam Girdwood");
772 MODULE_LICENSE("GPL");