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