1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/pm.h>
25#include <linux/i2c.h>
26#include <linux/platform_device.h>
27#include <linux/regulator/consumer.h>
28
29#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/pcm_params.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34#include <sound/tlv.h>
35#include <sound/initval.h>
36#include <asm/div64.h>
37
38#include "wm8580.h"
39
40
41#define WM8580_PLLA1 0x00
42#define WM8580_PLLA2 0x01
43#define WM8580_PLLA3 0x02
44#define WM8580_PLLA4 0x03
45#define WM8580_PLLB1 0x04
46#define WM8580_PLLB2 0x05
47#define WM8580_PLLB3 0x06
48#define WM8580_PLLB4 0x07
49#define WM8580_CLKSEL 0x08
50#define WM8580_PAIF1 0x09
51#define WM8580_PAIF2 0x0A
52#define WM8580_SAIF1 0x0B
53#define WM8580_PAIF3 0x0C
54#define WM8580_PAIF4 0x0D
55#define WM8580_SAIF2 0x0E
56#define WM8580_DAC_CONTROL1 0x0F
57#define WM8580_DAC_CONTROL2 0x10
58#define WM8580_DAC_CONTROL3 0x11
59#define WM8580_DAC_CONTROL4 0x12
60#define WM8580_DAC_CONTROL5 0x13
61#define WM8580_DIGITAL_ATTENUATION_DACL1 0x14
62#define WM8580_DIGITAL_ATTENUATION_DACR1 0x15
63#define WM8580_DIGITAL_ATTENUATION_DACL2 0x16
64#define WM8580_DIGITAL_ATTENUATION_DACR2 0x17
65#define WM8580_DIGITAL_ATTENUATION_DACL3 0x18
66#define WM8580_DIGITAL_ATTENUATION_DACR3 0x19
67#define WM8580_MASTER_DIGITAL_ATTENUATION 0x1C
68#define WM8580_ADC_CONTROL1 0x1D
69#define WM8580_SPDTXCHAN0 0x1E
70#define WM8580_SPDTXCHAN1 0x1F
71#define WM8580_SPDTXCHAN2 0x20
72#define WM8580_SPDTXCHAN3 0x21
73#define WM8580_SPDTXCHAN4 0x22
74#define WM8580_SPDTXCHAN5 0x23
75#define WM8580_SPDMODE 0x24
76#define WM8580_INTMASK 0x25
77#define WM8580_GPO1 0x26
78#define WM8580_GPO2 0x27
79#define WM8580_GPO3 0x28
80#define WM8580_GPO4 0x29
81#define WM8580_GPO5 0x2A
82#define WM8580_INTSTAT 0x2B
83#define WM8580_SPDRXCHAN1 0x2C
84#define WM8580_SPDRXCHAN2 0x2D
85#define WM8580_SPDRXCHAN3 0x2E
86#define WM8580_SPDRXCHAN4 0x2F
87#define WM8580_SPDRXCHAN5 0x30
88#define WM8580_SPDSTAT 0x31
89#define WM8580_PWRDN1 0x32
90#define WM8580_PWRDN2 0x33
91#define WM8580_READBACK 0x34
92#define WM8580_RESET 0x35
93
94#define WM8580_MAX_REGISTER 0x35
95
96
97#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60
98#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20
99#define WM8580_PLLB4_MCLKOUTSRC_PLLB 0x40
100#define WM8580_PLLB4_MCLKOUTSRC_OSC 0x60
101
102#define WM8580_PLLB4_CLKOUTSRC_MASK 0x180
103#define WM8580_PLLB4_CLKOUTSRC_PLLACLK 0x080
104#define WM8580_PLLB4_CLKOUTSRC_PLLBCLK 0x100
105#define WM8580_PLLB4_CLKOUTSRC_OSCCLK 0x180
106
107
108#define WM8580_CLKSEL_DAC_CLKSEL_MASK 0x03
109#define WM8580_CLKSEL_DAC_CLKSEL_PLLA 0x01
110#define WM8580_CLKSEL_DAC_CLKSEL_PLLB 0x02
111
112
113#define WM8580_AIF_RATE_MASK 0x7
114#define WM8580_AIF_RATE_128 0x0
115#define WM8580_AIF_RATE_192 0x1
116#define WM8580_AIF_RATE_256 0x2
117#define WM8580_AIF_RATE_384 0x3
118#define WM8580_AIF_RATE_512 0x4
119#define WM8580_AIF_RATE_768 0x5
120#define WM8580_AIF_RATE_1152 0x6
121
122#define WM8580_AIF_BCLKSEL_MASK 0x18
123#define WM8580_AIF_BCLKSEL_64 0x00
124#define WM8580_AIF_BCLKSEL_128 0x08
125#define WM8580_AIF_BCLKSEL_256 0x10
126#define WM8580_AIF_BCLKSEL_SYSCLK 0x18
127
128#define WM8580_AIF_MS 0x20
129
130#define WM8580_AIF_CLKSRC_MASK 0xc0
131#define WM8580_AIF_CLKSRC_PLLA 0x40
132#define WM8580_AIF_CLKSRC_PLLB 0x40
133#define WM8580_AIF_CLKSRC_MCLK 0xc0
134
135
136#define WM8580_AIF_FMT_MASK 0x03
137#define WM8580_AIF_FMT_RIGHTJ 0x00
138#define WM8580_AIF_FMT_LEFTJ 0x01
139#define WM8580_AIF_FMT_I2S 0x02
140#define WM8580_AIF_FMT_DSP 0x03
141
142#define WM8580_AIF_LENGTH_MASK 0x0c
143#define WM8580_AIF_LENGTH_16 0x00
144#define WM8580_AIF_LENGTH_20 0x04
145#define WM8580_AIF_LENGTH_24 0x08
146#define WM8580_AIF_LENGTH_32 0x0c
147
148#define WM8580_AIF_LRP 0x10
149#define WM8580_AIF_BCP 0x20
150
151
152#define WM8580_PWRDN1_PWDN 0x001
153#define WM8580_PWRDN1_ALLDACPD 0x040
154
155
156#define WM8580_PWRDN2_OSSCPD 0x001
157#define WM8580_PWRDN2_PLLAPD 0x002
158#define WM8580_PWRDN2_PLLBPD 0x004
159#define WM8580_PWRDN2_SPDIFPD 0x008
160#define WM8580_PWRDN2_SPDIFTXD 0x010
161#define WM8580_PWRDN2_SPDIFRXD 0x020
162
163#define WM8580_DAC_CONTROL5_MUTEALL 0x10
164
165
166
167
168
169
170static const u16 wm8580_reg[] = {
171 0x0121, 0x017e, 0x007d, 0x0014,
172 0x0121, 0x017e, 0x007d, 0x0194,
173 0x001c, 0x0002, 0x0002, 0x00c2,
174 0x0182, 0x0082, 0x000a, 0x0024,
175 0x0009, 0x0000, 0x00ff, 0x0000,
176 0x00ff, 0x00ff, 0x00ff, 0x00ff,
177 0x00ff, 0x00ff, 0x00ff, 0x00ff,
178 0x01f0, 0x0040, 0x0000, 0x0000,
179 0x0000, 0x0000, 0x0031, 0x000b,
180 0x0039, 0x0000, 0x0010, 0x0032,
181 0x0054, 0x0076, 0x0098, 0x0000,
182 0x0000, 0x0000, 0x0000, 0x0000,
183 0x0000, 0x0000, 0x005e, 0x003e,
184 0x0000, 0x0000
185};
186
187struct pll_state {
188 unsigned int in;
189 unsigned int out;
190};
191
192#define WM8580_NUM_SUPPLIES 3
193static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
194 "AVDD",
195 "DVDD",
196 "PVDD",
197};
198
199
200struct wm8580_priv {
201 struct snd_soc_codec codec;
202 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
203 u16 reg_cache[WM8580_MAX_REGISTER + 1];
204 struct pll_state a;
205 struct pll_state b;
206};
207
208static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
209
210static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
211 struct snd_ctl_elem_value *ucontrol)
212{
213 struct soc_mixer_control *mc =
214 (struct soc_mixer_control *)kcontrol->private_value;
215 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
216 u16 *reg_cache = codec->reg_cache;
217 unsigned int reg = mc->reg;
218 unsigned int reg2 = mc->rreg;
219 int ret;
220
221
222 reg_cache[reg] = 0;
223 reg_cache[reg2] = 0;
224
225 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
226 if (ret < 0)
227 return ret;
228
229
230 snd_soc_update_bits(codec, reg, 0x100, 0x100);
231 snd_soc_update_bits(codec, reg2, 0x100, 0x100);
232
233 return 0;
234}
235
236#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
237 xinvert, tlv_array) \
238{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
239 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
240 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
241 .tlv.p = (tlv_array), \
242 .info = snd_soc_info_volsw_2r, \
243 .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \
244 .private_value = (unsigned long)&(struct soc_mixer_control) \
245 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
246 .max = xmax, .invert = xinvert} }
247
248static const struct snd_kcontrol_new wm8580_snd_controls[] = {
249SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume",
250 WM8580_DIGITAL_ATTENUATION_DACL1,
251 WM8580_DIGITAL_ATTENUATION_DACR1,
252 0, 0xff, 0, dac_tlv),
253SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume",
254 WM8580_DIGITAL_ATTENUATION_DACL2,
255 WM8580_DIGITAL_ATTENUATION_DACR2,
256 0, 0xff, 0, dac_tlv),
257SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume",
258 WM8580_DIGITAL_ATTENUATION_DACL3,
259 WM8580_DIGITAL_ATTENUATION_DACR3,
260 0, 0xff, 0, dac_tlv),
261
262SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),
263SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),
264SOC_SINGLE("DAC3 Deemphasis Switch", WM8580_DAC_CONTROL3, 2, 1, 0),
265
266SOC_DOUBLE("DAC1 Invert Switch", WM8580_DAC_CONTROL4, 0, 1, 1, 0),
267SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4, 2, 3, 1, 0),
268SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0),
269
270SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0),
271SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0),
272SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0),
273SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0),
274
275SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0),
276SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
277};
278
279static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
280SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1),
281SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1),
282SND_SOC_DAPM_DAC("DAC3", "Playback", WM8580_PWRDN1, 4, 1),
283
284SND_SOC_DAPM_OUTPUT("VOUT1L"),
285SND_SOC_DAPM_OUTPUT("VOUT1R"),
286SND_SOC_DAPM_OUTPUT("VOUT2L"),
287SND_SOC_DAPM_OUTPUT("VOUT2R"),
288SND_SOC_DAPM_OUTPUT("VOUT3L"),
289SND_SOC_DAPM_OUTPUT("VOUT3R"),
290
291SND_SOC_DAPM_ADC("ADC", "Capture", WM8580_PWRDN1, 1, 1),
292
293SND_SOC_DAPM_INPUT("AINL"),
294SND_SOC_DAPM_INPUT("AINR"),
295};
296
297static const struct snd_soc_dapm_route audio_map[] = {
298 { "VOUT1L", NULL, "DAC1" },
299 { "VOUT1R", NULL, "DAC1" },
300
301 { "VOUT2L", NULL, "DAC2" },
302 { "VOUT2R", NULL, "DAC2" },
303
304 { "VOUT3L", NULL, "DAC3" },
305 { "VOUT3R", NULL, "DAC3" },
306
307 { "ADC", NULL, "AINL" },
308 { "ADC", NULL, "AINR" },
309};
310
311static int wm8580_add_widgets(struct snd_soc_codec *codec)
312{
313 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets,
314 ARRAY_SIZE(wm8580_dapm_widgets));
315
316 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
317
318 snd_soc_dapm_new_widgets(codec);
319 return 0;
320}
321
322
323struct _pll_div {
324 u32 prescale:1;
325 u32 postscale:1;
326 u32 freqmode:2;
327 u32 n:4;
328 u32 k:24;
329};
330
331
332#define FIXED_PLL_SIZE (1 << 22)
333
334
335static struct {
336 unsigned int div;
337 unsigned int freqmode;
338 unsigned int postscale;
339} post_table[] = {
340 { 2, 0, 0 },
341 { 4, 0, 1 },
342 { 4, 1, 0 },
343 { 8, 1, 1 },
344 { 8, 2, 0 },
345 { 16, 2, 1 },
346 { 12, 3, 0 },
347 { 24, 3, 1 }
348};
349
350static int pll_factors(struct _pll_div *pll_div, unsigned int target,
351 unsigned int source)
352{
353 u64 Kpart;
354 unsigned int K, Ndiv, Nmod;
355 int i;
356
357 pr_debug("wm8580: PLL %uHz->%uHz\n", source, target);
358
359
360
361
362 for (i = 0; i < ARRAY_SIZE(post_table); i++) {
363 if (target * post_table[i].div >= 90000000 &&
364 target * post_table[i].div <= 100000000) {
365 pll_div->freqmode = post_table[i].freqmode;
366 pll_div->postscale = post_table[i].postscale;
367 target *= post_table[i].div;
368 break;
369 }
370 }
371
372 if (i == ARRAY_SIZE(post_table)) {
373 printk(KERN_ERR "wm8580: Unable to scale output frequency "
374 "%u\n", target);
375 return -EINVAL;
376 }
377
378 Ndiv = target / source;
379
380 if (Ndiv < 5) {
381 source /= 2;
382 pll_div->prescale = 1;
383 Ndiv = target / source;
384 } else
385 pll_div->prescale = 0;
386
387 if ((Ndiv < 5) || (Ndiv > 13)) {
388 printk(KERN_ERR
389 "WM8580 N=%u outside supported range\n", Ndiv);
390 return -EINVAL;
391 }
392
393 pll_div->n = Ndiv;
394 Nmod = target % source;
395 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
396
397 do_div(Kpart, source);
398
399 K = Kpart & 0xFFFFFFFF;
400
401 pll_div->k = K;
402
403 pr_debug("PLL %x.%x prescale %d freqmode %d postscale %d\n",
404 pll_div->n, pll_div->k, pll_div->prescale, pll_div->freqmode,
405 pll_div->postscale);
406
407 return 0;
408}
409
410static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
411 int pll_id, unsigned int freq_in, unsigned int freq_out)
412{
413 int offset;
414 struct snd_soc_codec *codec = codec_dai->codec;
415 struct wm8580_priv *wm8580 = codec->private_data;
416 struct pll_state *state;
417 struct _pll_div pll_div;
418 unsigned int reg;
419 unsigned int pwr_mask;
420 int ret;
421
422
423
424
425 memset(&pll_div, 0, sizeof(pll_div));
426
427 switch (pll_id) {
428 case WM8580_PLLA:
429 state = &wm8580->a;
430 offset = 0;
431 pwr_mask = WM8580_PWRDN2_PLLAPD;
432 break;
433 case WM8580_PLLB:
434 state = &wm8580->b;
435 offset = 4;
436 pwr_mask = WM8580_PWRDN2_PLLBPD;
437 break;
438 default:
439 return -ENODEV;
440 }
441
442 if (freq_in && freq_out) {
443 ret = pll_factors(&pll_div, freq_out, freq_in);
444 if (ret != 0)
445 return ret;
446 }
447
448 state->in = freq_in;
449 state->out = freq_out;
450
451
452
453
454 reg = snd_soc_read(codec, WM8580_PWRDN2);
455 snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
456
457 if (!freq_in || !freq_out)
458 return 0;
459
460 snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
461 snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0x1ff);
462 snd_soc_write(codec, WM8580_PLLA3 + offset,
463 (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));
464
465 reg = snd_soc_read(codec, WM8580_PLLA4 + offset);
466 reg &= ~0x1b;
467 reg |= pll_div.prescale | pll_div.postscale << 1 |
468 pll_div.freqmode << 3;
469
470 snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
471
472
473 reg = snd_soc_read(codec, WM8580_PWRDN2);
474 snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
475
476 return 0;
477}
478
479
480
481
482static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
483 struct snd_pcm_hw_params *params,
484 struct snd_soc_dai *dai)
485{
486 struct snd_soc_pcm_runtime *rtd = substream->private_data;
487 struct snd_soc_device *socdev = rtd->socdev;
488 struct snd_soc_codec *codec = socdev->card->codec;
489 u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id);
490
491 paifb &= ~WM8580_AIF_LENGTH_MASK;
492
493 switch (params_format(params)) {
494 case SNDRV_PCM_FORMAT_S16_LE:
495 break;
496 case SNDRV_PCM_FORMAT_S20_3LE:
497 paifb |= WM8580_AIF_LENGTH_20;
498 break;
499 case SNDRV_PCM_FORMAT_S24_LE:
500 paifb |= WM8580_AIF_LENGTH_24;
501 break;
502 case SNDRV_PCM_FORMAT_S32_LE:
503 paifb |= WM8580_AIF_LENGTH_24;
504 break;
505 default:
506 return -EINVAL;
507 }
508
509 snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb);
510 return 0;
511}
512
513static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
514 unsigned int fmt)
515{
516 struct snd_soc_codec *codec = codec_dai->codec;
517 unsigned int aifa;
518 unsigned int aifb;
519 int can_invert_lrclk;
520
521 aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id);
522 aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id);
523
524 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
525
526 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
527 case SND_SOC_DAIFMT_CBS_CFS:
528 aifa &= ~WM8580_AIF_MS;
529 break;
530 case SND_SOC_DAIFMT_CBM_CFM:
531 aifa |= WM8580_AIF_MS;
532 break;
533 default:
534 return -EINVAL;
535 }
536
537 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
538 case SND_SOC_DAIFMT_I2S:
539 can_invert_lrclk = 1;
540 aifb |= WM8580_AIF_FMT_I2S;
541 break;
542 case SND_SOC_DAIFMT_RIGHT_J:
543 can_invert_lrclk = 1;
544 aifb |= WM8580_AIF_FMT_RIGHTJ;
545 break;
546 case SND_SOC_DAIFMT_LEFT_J:
547 can_invert_lrclk = 1;
548 aifb |= WM8580_AIF_FMT_LEFTJ;
549 break;
550 case SND_SOC_DAIFMT_DSP_A:
551 can_invert_lrclk = 0;
552 aifb |= WM8580_AIF_FMT_DSP;
553 break;
554 case SND_SOC_DAIFMT_DSP_B:
555 can_invert_lrclk = 0;
556 aifb |= WM8580_AIF_FMT_DSP;
557 aifb |= WM8580_AIF_LRP;
558 break;
559 default:
560 return -EINVAL;
561 }
562
563 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
564 case SND_SOC_DAIFMT_NB_NF:
565 break;
566
567 case SND_SOC_DAIFMT_IB_IF:
568 if (!can_invert_lrclk)
569 return -EINVAL;
570 aifb |= WM8580_AIF_BCP;
571 aifb |= WM8580_AIF_LRP;
572 break;
573
574 case SND_SOC_DAIFMT_IB_NF:
575 aifb |= WM8580_AIF_BCP;
576 break;
577
578 case SND_SOC_DAIFMT_NB_IF:
579 if (!can_invert_lrclk)
580 return -EINVAL;
581 aifb |= WM8580_AIF_LRP;
582 break;
583
584 default:
585 return -EINVAL;
586 }
587
588 snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
589 snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
590
591 return 0;
592}
593
594static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
595 int div_id, int div)
596{
597 struct snd_soc_codec *codec = codec_dai->codec;
598 unsigned int reg;
599
600 switch (div_id) {
601 case WM8580_MCLK:
602 reg = snd_soc_read(codec, WM8580_PLLB4);
603 reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK;
604
605 switch (div) {
606 case WM8580_CLKSRC_MCLK:
607
608 break;
609
610 case WM8580_CLKSRC_PLLA:
611 reg |= WM8580_PLLB4_MCLKOUTSRC_PLLA;
612 break;
613 case WM8580_CLKSRC_PLLB:
614 reg |= WM8580_PLLB4_MCLKOUTSRC_PLLB;
615 break;
616
617 case WM8580_CLKSRC_OSC:
618 reg |= WM8580_PLLB4_MCLKOUTSRC_OSC;
619 break;
620
621 default:
622 return -EINVAL;
623 }
624 snd_soc_write(codec, WM8580_PLLB4, reg);
625 break;
626
627 case WM8580_DAC_CLKSEL:
628 reg = snd_soc_read(codec, WM8580_CLKSEL);
629 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
630
631 switch (div) {
632 case WM8580_CLKSRC_MCLK:
633 break;
634
635 case WM8580_CLKSRC_PLLA:
636 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA;
637 break;
638
639 case WM8580_CLKSRC_PLLB:
640 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB;
641 break;
642
643 default:
644 return -EINVAL;
645 }
646 snd_soc_write(codec, WM8580_CLKSEL, reg);
647 break;
648
649 case WM8580_CLKOUTSRC:
650 reg = snd_soc_read(codec, WM8580_PLLB4);
651 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
652
653 switch (div) {
654 case WM8580_CLKSRC_NONE:
655 break;
656
657 case WM8580_CLKSRC_PLLA:
658 reg |= WM8580_PLLB4_CLKOUTSRC_PLLACLK;
659 break;
660
661 case WM8580_CLKSRC_PLLB:
662 reg |= WM8580_PLLB4_CLKOUTSRC_PLLBCLK;
663 break;
664
665 case WM8580_CLKSRC_OSC:
666 reg |= WM8580_PLLB4_CLKOUTSRC_OSCCLK;
667 break;
668
669 default:
670 return -EINVAL;
671 }
672 snd_soc_write(codec, WM8580_PLLB4, reg);
673 break;
674
675 default:
676 return -EINVAL;
677 }
678
679 return 0;
680}
681
682static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
683{
684 struct snd_soc_codec *codec = codec_dai->codec;
685 unsigned int reg;
686
687 reg = snd_soc_read(codec, WM8580_DAC_CONTROL5);
688
689 if (mute)
690 reg |= WM8580_DAC_CONTROL5_MUTEALL;
691 else
692 reg &= ~WM8580_DAC_CONTROL5_MUTEALL;
693
694 snd_soc_write(codec, WM8580_DAC_CONTROL5, reg);
695
696 return 0;
697}
698
699static int wm8580_set_bias_level(struct snd_soc_codec *codec,
700 enum snd_soc_bias_level level)
701{
702 u16 reg;
703 switch (level) {
704 case SND_SOC_BIAS_ON:
705 case SND_SOC_BIAS_PREPARE:
706 break;
707
708 case SND_SOC_BIAS_STANDBY:
709 if (codec->bias_level == SND_SOC_BIAS_OFF) {
710
711 reg = snd_soc_read(codec, WM8580_PWRDN1);
712 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
713 snd_soc_write(codec, WM8580_PWRDN1, reg);
714
715
716 reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
717 reg &= ~0x100;
718 snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
719 }
720 break;
721
722 case SND_SOC_BIAS_OFF:
723 reg = snd_soc_read(codec, WM8580_PWRDN1);
724 snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
725 break;
726 }
727 codec->bias_level = level;
728 return 0;
729}
730
731#define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
732 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
733
734static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
735 .hw_params = wm8580_paif_hw_params,
736 .set_fmt = wm8580_set_paif_dai_fmt,
737 .set_clkdiv = wm8580_set_dai_clkdiv,
738 .set_pll = wm8580_set_dai_pll,
739 .digital_mute = wm8580_digital_mute,
740};
741
742static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
743 .hw_params = wm8580_paif_hw_params,
744 .set_fmt = wm8580_set_paif_dai_fmt,
745 .set_clkdiv = wm8580_set_dai_clkdiv,
746 .set_pll = wm8580_set_dai_pll,
747};
748
749struct snd_soc_dai wm8580_dai[] = {
750 {
751 .name = "WM8580 PAIFRX",
752 .id = 0,
753 .playback = {
754 .stream_name = "Playback",
755 .channels_min = 1,
756 .channels_max = 6,
757 .rates = SNDRV_PCM_RATE_8000_192000,
758 .formats = WM8580_FORMATS,
759 },
760 .ops = &wm8580_dai_ops_playback,
761 },
762 {
763 .name = "WM8580 PAIFTX",
764 .id = 1,
765 .capture = {
766 .stream_name = "Capture",
767 .channels_min = 2,
768 .channels_max = 2,
769 .rates = SNDRV_PCM_RATE_8000_192000,
770 .formats = WM8580_FORMATS,
771 },
772 .ops = &wm8580_dai_ops_capture,
773 },
774};
775EXPORT_SYMBOL_GPL(wm8580_dai);
776
777static struct snd_soc_codec *wm8580_codec;
778
779static int wm8580_probe(struct platform_device *pdev)
780{
781 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
782 struct snd_soc_codec *codec;
783 int ret = 0;
784
785 if (wm8580_codec == NULL) {
786 dev_err(&pdev->dev, "Codec device not registered\n");
787 return -ENODEV;
788 }
789
790 socdev->card->codec = wm8580_codec;
791 codec = wm8580_codec;
792
793
794 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
795 if (ret < 0) {
796 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
797 goto pcm_err;
798 }
799
800 snd_soc_add_controls(codec, wm8580_snd_controls,
801 ARRAY_SIZE(wm8580_snd_controls));
802 wm8580_add_widgets(codec);
803 ret = snd_soc_init_card(socdev);
804 if (ret < 0) {
805 dev_err(codec->dev, "failed to register card: %d\n", ret);
806 goto card_err;
807 }
808
809 return ret;
810
811card_err:
812 snd_soc_free_pcms(socdev);
813 snd_soc_dapm_free(socdev);
814pcm_err:
815 return ret;
816}
817
818
819static int wm8580_remove(struct platform_device *pdev)
820{
821 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
822
823 snd_soc_free_pcms(socdev);
824 snd_soc_dapm_free(socdev);
825
826 return 0;
827}
828
829struct snd_soc_codec_device soc_codec_dev_wm8580 = {
830 .probe = wm8580_probe,
831 .remove = wm8580_remove,
832};
833EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
834
835static int wm8580_register(struct wm8580_priv *wm8580,
836 enum snd_soc_control_type control)
837{
838 int ret, i;
839 struct snd_soc_codec *codec = &wm8580->codec;
840
841 if (wm8580_codec) {
842 dev_err(codec->dev, "Another WM8580 is registered\n");
843 ret = -EINVAL;
844 goto err;
845 }
846
847 mutex_init(&codec->mutex);
848 INIT_LIST_HEAD(&codec->dapm_widgets);
849 INIT_LIST_HEAD(&codec->dapm_paths);
850
851 codec->private_data = wm8580;
852 codec->name = "WM8580";
853 codec->owner = THIS_MODULE;
854 codec->bias_level = SND_SOC_BIAS_OFF;
855 codec->set_bias_level = wm8580_set_bias_level;
856 codec->dai = wm8580_dai;
857 codec->num_dai = ARRAY_SIZE(wm8580_dai);
858 codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache);
859 codec->reg_cache = &wm8580->reg_cache;
860
861 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
862
863 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
864 if (ret < 0) {
865 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
866 goto err;
867 }
868
869 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
870 wm8580->supplies[i].supply = wm8580_supply_names[i];
871
872 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies),
873 wm8580->supplies);
874 if (ret != 0) {
875 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
876 goto err;
877 }
878
879 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
880 wm8580->supplies);
881 if (ret != 0) {
882 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
883 goto err_regulator_get;
884 }
885
886
887 ret = snd_soc_write(codec, WM8580_RESET, 0);
888 if (ret != 0) {
889 dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
890 goto err_regulator_enable;
891 }
892
893 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
894 wm8580_dai[i].dev = codec->dev;
895
896 wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
897
898 wm8580_codec = codec;
899
900 ret = snd_soc_register_codec(codec);
901 if (ret != 0) {
902 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
903 goto err_regulator_enable;
904 }
905
906 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
907 if (ret != 0) {
908 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
909 goto err_codec;
910 }
911
912 return 0;
913
914err_codec:
915 snd_soc_unregister_codec(codec);
916err_regulator_enable:
917 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
918err_regulator_get:
919 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
920err:
921 kfree(wm8580);
922 return ret;
923}
924
925static void wm8580_unregister(struct wm8580_priv *wm8580)
926{
927 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
928 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
929 snd_soc_unregister_codec(&wm8580->codec);
930 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
931 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
932 kfree(wm8580);
933 wm8580_codec = NULL;
934}
935
936#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
937static int wm8580_i2c_probe(struct i2c_client *i2c,
938 const struct i2c_device_id *id)
939{
940 struct wm8580_priv *wm8580;
941 struct snd_soc_codec *codec;
942
943 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
944 if (wm8580 == NULL)
945 return -ENOMEM;
946
947 codec = &wm8580->codec;
948
949 i2c_set_clientdata(i2c, wm8580);
950 codec->control_data = i2c;
951
952 codec->dev = &i2c->dev;
953
954 return wm8580_register(wm8580, SND_SOC_I2C);
955}
956
957static int wm8580_i2c_remove(struct i2c_client *client)
958{
959 struct wm8580_priv *wm8580 = i2c_get_clientdata(client);
960 wm8580_unregister(wm8580);
961 return 0;
962}
963
964#ifdef CONFIG_PM
965static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
966{
967 return snd_soc_suspend_device(&client->dev);
968}
969
970static int wm8580_i2c_resume(struct i2c_client *client)
971{
972 return snd_soc_resume_device(&client->dev);
973}
974#else
975#define wm8580_i2c_suspend NULL
976#define wm8580_i2c_resume NULL
977#endif
978
979static const struct i2c_device_id wm8580_i2c_id[] = {
980 { "wm8580", 0 },
981 { }
982};
983MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
984
985static struct i2c_driver wm8580_i2c_driver = {
986 .driver = {
987 .name = "wm8580",
988 .owner = THIS_MODULE,
989 },
990 .probe = wm8580_i2c_probe,
991 .remove = wm8580_i2c_remove,
992 .suspend = wm8580_i2c_suspend,
993 .resume = wm8580_i2c_resume,
994 .id_table = wm8580_i2c_id,
995};
996#endif
997
998static int __init wm8580_modinit(void)
999{
1000 int ret;
1001
1002#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1003 ret = i2c_add_driver(&wm8580_i2c_driver);
1004 if (ret != 0) {
1005 pr_err("Failed to register WM8580 I2C driver: %d\n", ret);
1006 }
1007#endif
1008
1009 return 0;
1010}
1011module_init(wm8580_modinit);
1012
1013static void __exit wm8580_exit(void)
1014{
1015#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1016 i2c_del_driver(&wm8580_i2c_driver);
1017#endif
1018}
1019module_exit(wm8580_exit);
1020
1021MODULE_DESCRIPTION("ASoC WM8580 driver");
1022MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1023MODULE_LICENSE("GPL");
1024