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