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