2 * wm8960.c -- WM8960 ALSA SoC Audio driver
4 * Author: Liam Girdwood
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/init.h>
14 #include <linux/delay.h>
16 #include <linux/i2c.h>
17 #include <linux/platform_device.h>
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include <sound/soc-dapm.h>
23 #include <sound/initval.h>
24 #include <sound/tlv.h>
28 #define AUDIO_NAME "wm8960"
30 struct snd_soc_codec_device soc_codec_dev_wm8960
;
33 #define WM8960_VREF 0x40
35 /* R28 - Anti-pop 1 */
36 #define WM8960_POBCTRL 0x80
37 #define WM8960_BUFDCOPEN 0x10
38 #define WM8960_BUFIOEN 0x08
39 #define WM8960_SOFT_ST 0x04
40 #define WM8960_HPSTBY 0x01
42 /* R29 - Anti-pop 2 */
43 #define WM8960_DISOP 0x40
46 * wm8960 register cache
47 * We can't read the WM8960 register space when we are
48 * using 2 wire for device control, so we cache them instead.
50 static const u16 wm8960_reg
[WM8960_CACHEREGNUM
] = {
51 0x0097, 0x0097, 0x0000, 0x0000,
52 0x0000, 0x0008, 0x0000, 0x000a,
53 0x01c0, 0x0000, 0x00ff, 0x00ff,
54 0x0000, 0x0000, 0x0000, 0x0000,
55 0x0000, 0x007b, 0x0100, 0x0032,
56 0x0000, 0x00c3, 0x00c3, 0x01c0,
57 0x0000, 0x0000, 0x0000, 0x0000,
58 0x0000, 0x0000, 0x0000, 0x0000,
59 0x0100, 0x0100, 0x0050, 0x0050,
60 0x0050, 0x0050, 0x0000, 0x0000,
61 0x0000, 0x0000, 0x0040, 0x0000,
62 0x0000, 0x0050, 0x0050, 0x0000,
63 0x0002, 0x0037, 0x004d, 0x0080,
64 0x0008, 0x0031, 0x0026, 0x00e9,
68 u16 reg_cache
[WM8960_CACHEREGNUM
];
69 struct snd_soc_codec codec
;
73 * read wm8960 register cache
75 static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec
*codec
,
78 u16
*cache
= codec
->reg_cache
;
79 if (reg
== WM8960_RESET
)
81 if (reg
>= WM8960_CACHEREGNUM
)
87 * write wm8960 register cache
89 static inline void wm8960_write_reg_cache(struct snd_soc_codec
*codec
,
90 u16 reg
, unsigned int value
)
92 u16
*cache
= codec
->reg_cache
;
93 if (reg
>= WM8960_CACHEREGNUM
)
98 static inline unsigned int wm8960_read(struct snd_soc_codec
*codec
,
101 return wm8960_read_reg_cache(codec
, reg
);
105 * write to the WM8960 register space
107 static int wm8960_write(struct snd_soc_codec
*codec
, unsigned int reg
,
113 * D15..D9 WM8960 register offset
114 * D8...D0 register data
116 data
[0] = (reg
<< 1) | ((value
>> 8) & 0x0001);
117 data
[1] = value
& 0x00ff;
119 wm8960_write_reg_cache(codec
, reg
, value
);
120 if (codec
->hw_write(codec
->control_data
, data
, 2) == 2)
126 #define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0)
128 /* enumerated controls */
129 static const char *wm8960_deemph
[] = {"None", "32Khz", "44.1Khz", "48Khz"};
130 static const char *wm8960_polarity
[] = {"No Inversion", "Left Inverted",
131 "Right Inverted", "Stereo Inversion"};
132 static const char *wm8960_3d_upper_cutoff
[] = {"High", "Low"};
133 static const char *wm8960_3d_lower_cutoff
[] = {"Low", "High"};
134 static const char *wm8960_alcfunc
[] = {"Off", "Right", "Left", "Stereo"};
135 static const char *wm8960_alcmode
[] = {"ALC", "Limiter"};
137 static const struct soc_enum wm8960_enum
[] = {
138 SOC_ENUM_SINGLE(WM8960_DACCTL1
, 1, 4, wm8960_deemph
),
139 SOC_ENUM_SINGLE(WM8960_DACCTL1
, 5, 4, wm8960_polarity
),
140 SOC_ENUM_SINGLE(WM8960_DACCTL2
, 5, 4, wm8960_polarity
),
141 SOC_ENUM_SINGLE(WM8960_3D
, 6, 2, wm8960_3d_upper_cutoff
),
142 SOC_ENUM_SINGLE(WM8960_3D
, 5, 2, wm8960_3d_lower_cutoff
),
143 SOC_ENUM_SINGLE(WM8960_ALC1
, 7, 4, wm8960_alcfunc
),
144 SOC_ENUM_SINGLE(WM8960_ALC3
, 8, 2, wm8960_alcmode
),
147 static const DECLARE_TLV_DB_SCALE(adc_tlv
, -9700, 50, 0);
148 static const DECLARE_TLV_DB_SCALE(dac_tlv
, -12700, 50, 1);
149 static const DECLARE_TLV_DB_SCALE(bypass_tlv
, -2100, 300, 0);
150 static const DECLARE_TLV_DB_SCALE(out_tlv
, -12100, 100, 1);
152 static const struct snd_kcontrol_new wm8960_snd_controls
[] = {
153 SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL
, WM8960_RINVOL
,
155 SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL
, WM8960_RINVOL
,
157 SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL
, WM8960_RINVOL
,
160 SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC
, WM8960_RDAC
,
163 SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1
, WM8960_ROUT1
,
165 SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1
, WM8960_ROUT1
,
168 SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2
, WM8960_ROUT2
,
170 SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2
, WM8960_ROUT2
,
172 SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3
, 3, 5, 0),
173 SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3
, 0, 5, 0),
175 SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1
, 7, 1, 0),
176 SOC_ENUM("ADC Polarity", wm8960_enum
[1]),
177 SOC_ENUM("Playback De-emphasis", wm8960_enum
[0]),
178 SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1
, 0, 1, 0),
180 SOC_ENUM("DAC Polarity", wm8960_enum
[2]),
182 SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum
[3]),
183 SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum
[4]),
184 SOC_SINGLE("3D Volume", WM8960_3D
, 1, 15, 0),
185 SOC_SINGLE("3D Switch", WM8960_3D
, 0, 1, 0),
187 SOC_ENUM("ALC Function", wm8960_enum
[5]),
188 SOC_SINGLE("ALC Max Gain", WM8960_ALC1
, 4, 7, 0),
189 SOC_SINGLE("ALC Target", WM8960_ALC1
, 0, 15, 1),
190 SOC_SINGLE("ALC Min Gain", WM8960_ALC2
, 4, 7, 0),
191 SOC_SINGLE("ALC Hold Time", WM8960_ALC2
, 0, 15, 0),
192 SOC_ENUM("ALC Mode", wm8960_enum
[6]),
193 SOC_SINGLE("ALC Decay", WM8960_ALC3
, 4, 15, 0),
194 SOC_SINGLE("ALC Attack", WM8960_ALC3
, 0, 15, 0),
196 SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG
, 3, 31, 0),
197 SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG
, 0, 1, 0),
199 SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH
, WM8960_RINPATH
,
202 SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",
203 WM8960_BYPASS1
, 4, 7, 1, bypass_tlv
),
204 SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume",
205 WM8960_LOUTMIX
, 4, 7, 1, bypass_tlv
),
206 SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
207 WM8960_BYPASS2
, 4, 7, 1, bypass_tlv
),
208 SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
209 WM8960_ROUTMIX
, 4, 7, 1, bypass_tlv
),
212 static const struct snd_kcontrol_new wm8960_lin_boost
[] = {
213 SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH
, 6, 1, 0),
214 SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH
, 7, 1, 0),
215 SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH
, 8, 1, 0),
218 static const struct snd_kcontrol_new wm8960_lin
[] = {
219 SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH
, 3, 1, 0),
222 static const struct snd_kcontrol_new wm8960_rin_boost
[] = {
223 SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH
, 6, 1, 0),
224 SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH
, 7, 1, 0),
225 SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH
, 8, 1, 0),
228 static const struct snd_kcontrol_new wm8960_rin
[] = {
229 SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH
, 3, 1, 0),
232 static const struct snd_kcontrol_new wm8960_loutput_mixer
[] = {
233 SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX
, 8, 1, 0),
234 SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX
, 7, 1, 0),
235 SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1
, 7, 1, 0),
238 static const struct snd_kcontrol_new wm8960_routput_mixer
[] = {
239 SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX
, 8, 1, 0),
240 SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX
, 7, 1, 0),
241 SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2
, 7, 1, 0),
244 static const struct snd_kcontrol_new wm8960_mono_out
[] = {
245 SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1
, 7, 1, 0),
246 SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2
, 7, 1, 0),
249 static const struct snd_soc_dapm_widget wm8960_dapm_widgets
[] = {
250 SND_SOC_DAPM_INPUT("LINPUT1"),
251 SND_SOC_DAPM_INPUT("RINPUT1"),
252 SND_SOC_DAPM_INPUT("LINPUT2"),
253 SND_SOC_DAPM_INPUT("RINPUT2"),
254 SND_SOC_DAPM_INPUT("LINPUT3"),
255 SND_SOC_DAPM_INPUT("RINPUT3"),
257 SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1
, 1, 0),
259 SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1
, 5, 0,
260 wm8960_lin_boost
, ARRAY_SIZE(wm8960_lin_boost
)),
261 SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1
, 4, 0,
262 wm8960_rin_boost
, ARRAY_SIZE(wm8960_rin_boost
)),
264 SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3
, 5, 0,
265 wm8960_lin
, ARRAY_SIZE(wm8960_lin
)),
266 SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3
, 4, 0,
267 wm8960_rin
, ARRAY_SIZE(wm8960_rin
)),
269 SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2
, 3, 0),
270 SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2
, 2, 0),
272 SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2
, 8, 0),
273 SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2
, 7, 0),
275 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3
, 3, 0,
276 &wm8960_loutput_mixer
[0],
277 ARRAY_SIZE(wm8960_loutput_mixer
)),
278 SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3
, 2, 0,
279 &wm8960_routput_mixer
[0],
280 ARRAY_SIZE(wm8960_routput_mixer
)),
282 SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2
, 1, 0,
284 ARRAY_SIZE(wm8960_mono_out
)),
286 SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2
, 6, 0, NULL
, 0),
287 SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2
, 5, 0, NULL
, 0),
289 SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2
, 4, 0, NULL
, 0),
290 SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2
, 3, 0, NULL
, 0),
292 SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1
, 7, 0, NULL
, 0),
293 SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1
, 6, 0, NULL
, 0),
295 SND_SOC_DAPM_OUTPUT("SPK_LP"),
296 SND_SOC_DAPM_OUTPUT("SPK_LN"),
297 SND_SOC_DAPM_OUTPUT("HP_L"),
298 SND_SOC_DAPM_OUTPUT("HP_R"),
299 SND_SOC_DAPM_OUTPUT("SPK_RP"),
300 SND_SOC_DAPM_OUTPUT("SPK_RN"),
301 SND_SOC_DAPM_OUTPUT("OUT3"),
304 static const struct snd_soc_dapm_route audio_paths
[] = {
305 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
306 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
307 { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
309 { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", },
310 { "Left Input Mixer", NULL
, "LINPUT1", }, /* Really Boost Switch */
311 { "Left Input Mixer", NULL
, "LINPUT2" },
312 { "Left Input Mixer", NULL
, "LINPUT3" },
314 { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" },
315 { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
316 { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
318 { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", },
319 { "Right Input Mixer", NULL
, "RINPUT1", }, /* Really Boost Switch */
320 { "Right Input Mixer", NULL
, "RINPUT2" },
321 { "Right Input Mixer", NULL
, "LINPUT3" },
323 { "Left ADC", NULL
, "Left Input Mixer" },
324 { "Right ADC", NULL
, "Right Input Mixer" },
326 { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },
327 { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} ,
328 { "Left Output Mixer", "PCM Playback Switch", "Left DAC" },
330 { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },
331 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
332 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
334 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
335 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
337 { "LOUT1 PGA", NULL
, "Left Output Mixer" },
338 { "ROUT1 PGA", NULL
, "Right Output Mixer" },
340 { "HP_L", NULL
, "LOUT1 PGA" },
341 { "HP_R", NULL
, "ROUT1 PGA" },
343 { "Left Speaker PGA", NULL
, "Left Output Mixer" },
344 { "Right Speaker PGA", NULL
, "Right Output Mixer" },
346 { "Left Speaker Output", NULL
, "Left Speaker PGA" },
347 { "Right Speaker Output", NULL
, "Right Speaker PGA" },
349 { "SPK_LN", NULL
, "Left Speaker Output" },
350 { "SPK_LP", NULL
, "Left Speaker Output" },
351 { "SPK_RN", NULL
, "Right Speaker Output" },
352 { "SPK_RP", NULL
, "Right Speaker Output" },
354 { "OUT3", NULL
, "Mono Output Mixer", }
357 static int wm8960_add_widgets(struct snd_soc_codec
*codec
)
359 snd_soc_dapm_new_controls(codec
, wm8960_dapm_widgets
,
360 ARRAY_SIZE(wm8960_dapm_widgets
));
362 snd_soc_dapm_add_routes(codec
, audio_paths
, ARRAY_SIZE(audio_paths
));
364 snd_soc_dapm_new_widgets(codec
);
368 static int wm8960_set_dai_fmt(struct snd_soc_dai
*codec_dai
,
371 struct snd_soc_codec
*codec
= codec_dai
->codec
;
374 /* set master/slave audio interface */
375 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
376 case SND_SOC_DAIFMT_CBM_CFM
:
379 case SND_SOC_DAIFMT_CBS_CFS
:
385 /* interface format */
386 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
387 case SND_SOC_DAIFMT_I2S
:
390 case SND_SOC_DAIFMT_RIGHT_J
:
392 case SND_SOC_DAIFMT_LEFT_J
:
395 case SND_SOC_DAIFMT_DSP_A
:
398 case SND_SOC_DAIFMT_DSP_B
:
405 /* clock inversion */
406 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
407 case SND_SOC_DAIFMT_NB_NF
:
409 case SND_SOC_DAIFMT_IB_IF
:
412 case SND_SOC_DAIFMT_IB_NF
:
415 case SND_SOC_DAIFMT_NB_IF
:
423 wm8960_write(codec
, WM8960_IFACE1
, iface
);
427 static int wm8960_hw_params(struct snd_pcm_substream
*substream
,
428 struct snd_pcm_hw_params
*params
,
429 struct snd_soc_dai
*dai
)
431 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
432 struct snd_soc_device
*socdev
= rtd
->socdev
;
433 struct snd_soc_codec
*codec
= socdev
->card
->codec
;
434 u16 iface
= wm8960_read(codec
, WM8960_IFACE1
) & 0xfff3;
437 switch (params_format(params
)) {
438 case SNDRV_PCM_FORMAT_S16_LE
:
440 case SNDRV_PCM_FORMAT_S20_3LE
:
443 case SNDRV_PCM_FORMAT_S24_LE
:
449 wm8960_write(codec
, WM8960_IFACE1
, iface
);
453 static int wm8960_mute(struct snd_soc_dai
*dai
, int mute
)
455 struct snd_soc_codec
*codec
= dai
->codec
;
456 u16 mute_reg
= wm8960_read(codec
, WM8960_DACCTL1
) & 0xfff7;
459 wm8960_write(codec
, WM8960_DACCTL1
, mute_reg
| 0x8);
461 wm8960_write(codec
, WM8960_DACCTL1
, mute_reg
);
465 static int wm8960_set_bias_level(struct snd_soc_codec
*codec
,
466 enum snd_soc_bias_level level
)
468 struct wm8960_data
*pdata
= codec
->dev
->platform_data
;
472 case SND_SOC_BIAS_ON
:
475 case SND_SOC_BIAS_PREPARE
:
476 /* Set VMID to 2x50k */
477 reg
= wm8960_read(codec
, WM8960_POWER1
);
480 wm8960_write(codec
, WM8960_POWER1
, reg
);
483 case SND_SOC_BIAS_STANDBY
:
484 if (codec
->bias_level
== SND_SOC_BIAS_OFF
) {
485 /* Enable anti-pop features */
486 wm8960_write(codec
, WM8960_APOP1
,
487 WM8960_POBCTRL
| WM8960_SOFT_ST
|
488 WM8960_BUFDCOPEN
| WM8960_BUFIOEN
);
490 /* Discharge HP output */
493 reg
|= pdata
->dres
<< 4;
494 wm8960_write(codec
, WM8960_APOP2
, reg
);
498 wm8960_write(codec
, WM8960_APOP2
, 0);
500 /* Enable & ramp VMID at 2x50k */
501 reg
= wm8960_read(codec
, WM8960_POWER1
);
503 wm8960_write(codec
, WM8960_POWER1
, reg
);
507 wm8960_write(codec
, WM8960_POWER1
, reg
| WM8960_VREF
);
509 /* Disable anti-pop features */
510 wm8960_write(codec
, WM8960_APOP1
, WM8960_BUFIOEN
);
513 /* Set VMID to 2x250k */
514 reg
= wm8960_read(codec
, WM8960_POWER1
);
517 wm8960_write(codec
, WM8960_POWER1
, reg
);
520 case SND_SOC_BIAS_OFF
:
521 /* Enable anti-pop features */
522 wm8960_write(codec
, WM8960_APOP1
,
523 WM8960_POBCTRL
| WM8960_SOFT_ST
|
524 WM8960_BUFDCOPEN
| WM8960_BUFIOEN
);
526 /* Disable VMID and VREF, let them discharge */
527 wm8960_write(codec
, WM8960_POWER1
, 0);
530 wm8960_write(codec
, WM8960_APOP1
, 0);
534 codec
->bias_level
= level
;
546 /* The size in bits of the pll divide multiplied by 10
547 * to allow rounding later */
548 #define FIXED_PLL_SIZE ((1 << 24) * 10)
550 static int pll_factors(unsigned int source
, unsigned int target
,
551 struct _pll_div
*pll_div
)
553 unsigned long long Kpart
;
554 unsigned int K
, Ndiv
, Nmod
;
556 pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source
, target
);
558 /* Scale up target to PLL operating frequency */
561 Ndiv
= target
/ source
;
564 pll_div
->pre_div
= 1;
565 Ndiv
= target
/ source
;
567 pll_div
->pre_div
= 0;
569 if ((Ndiv
< 6) || (Ndiv
> 12)) {
570 pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv
);
575 Nmod
= target
% source
;
576 Kpart
= FIXED_PLL_SIZE
* (long long)Nmod
;
578 do_div(Kpart
, source
);
580 K
= Kpart
& 0xFFFFFFFF;
582 /* Check if we need to round */
586 /* Move down to proper range now rounding is done */
591 pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n",
592 pll_div
->n
, pll_div
->k
, pll_div
->pre_div
);
597 static int wm8960_set_dai_pll(struct snd_soc_dai
*codec_dai
,
598 int pll_id
, unsigned int freq_in
, unsigned int freq_out
)
600 struct snd_soc_codec
*codec
= codec_dai
->codec
;
602 static struct _pll_div pll_div
;
605 if (freq_in
&& freq_out
) {
606 ret
= pll_factors(freq_in
, freq_out
, &pll_div
);
611 /* Disable the PLL: even if we are changing the frequency the
612 * PLL needs to be disabled while we do so. */
613 wm8960_write(codec
, WM8960_CLOCK1
,
614 wm8960_read(codec
, WM8960_CLOCK1
) & ~1);
615 wm8960_write(codec
, WM8960_POWER2
,
616 wm8960_read(codec
, WM8960_POWER2
) & ~1);
618 if (!freq_in
|| !freq_out
)
621 reg
= wm8960_read(codec
, WM8960_PLL1
) & ~0x3f;
622 reg
|= pll_div
.pre_div
<< 4;
628 wm8960_write(codec
, WM8960_PLL2
, (pll_div
.k
>> 18) & 0x3f);
629 wm8960_write(codec
, WM8960_PLL3
, (pll_div
.k
>> 9) & 0x1ff);
630 wm8960_write(codec
, WM8960_PLL4
, pll_div
.k
& 0x1ff);
632 wm8960_write(codec
, WM8960_PLL1
, reg
);
635 wm8960_write(codec
, WM8960_POWER2
,
636 wm8960_read(codec
, WM8960_POWER2
) | 1);
638 wm8960_write(codec
, WM8960_CLOCK1
,
639 wm8960_read(codec
, WM8960_CLOCK1
) | 1);
644 static int wm8960_set_dai_clkdiv(struct snd_soc_dai
*codec_dai
,
647 struct snd_soc_codec
*codec
= codec_dai
->codec
;
651 case WM8960_SYSCLKSEL
:
652 reg
= wm8960_read(codec
, WM8960_CLOCK1
) & 0x1fe;
653 wm8960_write(codec
, WM8960_CLOCK1
, reg
| div
);
655 case WM8960_SYSCLKDIV
:
656 reg
= wm8960_read(codec
, WM8960_CLOCK1
) & 0x1f9;
657 wm8960_write(codec
, WM8960_CLOCK1
, reg
| div
);
660 reg
= wm8960_read(codec
, WM8960_CLOCK1
) & 0x1c7;
661 wm8960_write(codec
, WM8960_CLOCK1
, reg
| div
);
663 case WM8960_OPCLKDIV
:
664 reg
= wm8960_read(codec
, WM8960_PLL1
) & 0x03f;
665 wm8960_write(codec
, WM8960_PLL1
, reg
| div
);
668 reg
= wm8960_read(codec
, WM8960_CLOCK2
) & 0x03f;
669 wm8960_write(codec
, WM8960_CLOCK2
, reg
| div
);
671 case WM8960_TOCLKSEL
:
672 reg
= wm8960_read(codec
, WM8960_ADDCTL1
) & 0x1fd;
673 wm8960_write(codec
, WM8960_ADDCTL1
, reg
| div
);
682 #define WM8960_RATES SNDRV_PCM_RATE_8000_48000
684 #define WM8960_FORMATS \
685 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
686 SNDRV_PCM_FMTBIT_S24_LE)
688 static struct snd_soc_dai_ops wm8960_dai_ops
= {
689 .hw_params
= wm8960_hw_params
,
690 .digital_mute
= wm8960_mute
,
691 .set_fmt
= wm8960_set_dai_fmt
,
692 .set_clkdiv
= wm8960_set_dai_clkdiv
,
693 .set_pll
= wm8960_set_dai_pll
,
696 struct snd_soc_dai wm8960_dai
= {
699 .stream_name
= "Playback",
702 .rates
= WM8960_RATES
,
703 .formats
= WM8960_FORMATS
,},
705 .stream_name
= "Capture",
708 .rates
= WM8960_RATES
,
709 .formats
= WM8960_FORMATS
,},
710 .ops
= &wm8960_dai_ops
,
711 .symmetric_rates
= 1,
713 EXPORT_SYMBOL_GPL(wm8960_dai
);
715 static int wm8960_suspend(struct platform_device
*pdev
, pm_message_t state
)
717 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
718 struct snd_soc_codec
*codec
= socdev
->card
->codec
;
720 wm8960_set_bias_level(codec
, SND_SOC_BIAS_OFF
);
724 static int wm8960_resume(struct platform_device
*pdev
)
726 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
727 struct snd_soc_codec
*codec
= socdev
->card
->codec
;
730 u16
*cache
= codec
->reg_cache
;
732 /* Sync reg_cache with the hardware */
733 for (i
= 0; i
< ARRAY_SIZE(wm8960_reg
); i
++) {
734 data
[0] = (i
<< 1) | ((cache
[i
] >> 8) & 0x0001);
735 data
[1] = cache
[i
] & 0x00ff;
736 codec
->hw_write(codec
->control_data
, data
, 2);
739 wm8960_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
740 wm8960_set_bias_level(codec
, codec
->suspend_bias_level
);
744 static struct snd_soc_codec
*wm8960_codec
;
746 static int wm8960_probe(struct platform_device
*pdev
)
748 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
749 struct snd_soc_codec
*codec
;
752 if (wm8960_codec
== NULL
) {
753 dev_err(&pdev
->dev
, "Codec device not registered\n");
757 socdev
->card
->codec
= wm8960_codec
;
758 codec
= wm8960_codec
;
761 ret
= snd_soc_new_pcms(socdev
, SNDRV_DEFAULT_IDX1
, SNDRV_DEFAULT_STR1
);
763 dev_err(codec
->dev
, "failed to create pcms: %d\n", ret
);
767 snd_soc_add_controls(codec
, wm8960_snd_controls
,
768 ARRAY_SIZE(wm8960_snd_controls
));
769 wm8960_add_widgets(codec
);
770 ret
= snd_soc_init_card(socdev
);
772 dev_err(codec
->dev
, "failed to register card: %d\n", ret
);
779 snd_soc_free_pcms(socdev
);
780 snd_soc_dapm_free(socdev
);
785 /* power down chip */
786 static int wm8960_remove(struct platform_device
*pdev
)
788 struct snd_soc_device
*socdev
= platform_get_drvdata(pdev
);
790 snd_soc_free_pcms(socdev
);
791 snd_soc_dapm_free(socdev
);
796 struct snd_soc_codec_device soc_codec_dev_wm8960
= {
797 .probe
= wm8960_probe
,
798 .remove
= wm8960_remove
,
799 .suspend
= wm8960_suspend
,
800 .resume
= wm8960_resume
,
802 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960
);
804 static int wm8960_register(struct wm8960_priv
*wm8960
)
806 struct wm8960_data
*pdata
= wm8960
->codec
.dev
->platform_data
;
807 struct snd_soc_codec
*codec
= &wm8960
->codec
;
812 dev_err(codec
->dev
, "Another WM8960 is registered\n");
817 dev_warn(codec
->dev
, "No platform data supplied\n");
819 if (pdata
->dres
> WM8960_DRES_MAX
) {
820 dev_err(codec
->dev
, "Invalid DRES: %d\n", pdata
->dres
);
825 mutex_init(&codec
->mutex
);
826 INIT_LIST_HEAD(&codec
->dapm_widgets
);
827 INIT_LIST_HEAD(&codec
->dapm_paths
);
829 codec
->private_data
= wm8960
;
830 codec
->name
= "WM8960";
831 codec
->owner
= THIS_MODULE
;
832 codec
->read
= wm8960_read_reg_cache
;
833 codec
->write
= wm8960_write
;
834 codec
->bias_level
= SND_SOC_BIAS_OFF
;
835 codec
->set_bias_level
= wm8960_set_bias_level
;
836 codec
->dai
= &wm8960_dai
;
838 codec
->reg_cache_size
= WM8960_CACHEREGNUM
;
839 codec
->reg_cache
= &wm8960
->reg_cache
;
841 memcpy(codec
->reg_cache
, wm8960_reg
, sizeof(wm8960_reg
));
843 ret
= wm8960_reset(codec
);
845 dev_err(codec
->dev
, "Failed to issue reset\n");
849 wm8960_dai
.dev
= codec
->dev
;
851 wm8960_set_bias_level(codec
, SND_SOC_BIAS_STANDBY
);
853 /* Latch the update bits */
854 reg
= wm8960_read(codec
, WM8960_LINVOL
);
855 wm8960_write(codec
, WM8960_LINVOL
, reg
| 0x100);
856 reg
= wm8960_read(codec
, WM8960_RINVOL
);
857 wm8960_write(codec
, WM8960_RINVOL
, reg
| 0x100);
858 reg
= wm8960_read(codec
, WM8960_LADC
);
859 wm8960_write(codec
, WM8960_LADC
, reg
| 0x100);
860 reg
= wm8960_read(codec
, WM8960_RADC
);
861 wm8960_write(codec
, WM8960_RADC
, reg
| 0x100);
862 reg
= wm8960_read(codec
, WM8960_LDAC
);
863 wm8960_write(codec
, WM8960_LDAC
, reg
| 0x100);
864 reg
= wm8960_read(codec
, WM8960_RDAC
);
865 wm8960_write(codec
, WM8960_RDAC
, reg
| 0x100);
866 reg
= wm8960_read(codec
, WM8960_LOUT1
);
867 wm8960_write(codec
, WM8960_LOUT1
, reg
| 0x100);
868 reg
= wm8960_read(codec
, WM8960_ROUT1
);
869 wm8960_write(codec
, WM8960_ROUT1
, reg
| 0x100);
870 reg
= wm8960_read(codec
, WM8960_LOUT2
);
871 wm8960_write(codec
, WM8960_LOUT2
, reg
| 0x100);
872 reg
= wm8960_read(codec
, WM8960_ROUT2
);
873 wm8960_write(codec
, WM8960_ROUT2
, reg
| 0x100);
875 wm8960_codec
= codec
;
877 ret
= snd_soc_register_codec(codec
);
879 dev_err(codec
->dev
, "Failed to register codec: %d\n", ret
);
883 ret
= snd_soc_register_dai(&wm8960_dai
);
885 dev_err(codec
->dev
, "Failed to register DAI: %d\n", ret
);
886 snd_soc_unregister_codec(codec
);
893 static void wm8960_unregister(struct wm8960_priv
*wm8960
)
895 wm8960_set_bias_level(&wm8960
->codec
, SND_SOC_BIAS_OFF
);
896 snd_soc_unregister_dai(&wm8960_dai
);
897 snd_soc_unregister_codec(&wm8960
->codec
);
902 static __devinit
int wm8960_i2c_probe(struct i2c_client
*i2c
,
903 const struct i2c_device_id
*id
)
905 struct wm8960_priv
*wm8960
;
906 struct snd_soc_codec
*codec
;
908 wm8960
= kzalloc(sizeof(struct wm8960_priv
), GFP_KERNEL
);
912 codec
= &wm8960
->codec
;
913 codec
->hw_write
= (hw_write_t
)i2c_master_send
;
915 i2c_set_clientdata(i2c
, wm8960
);
916 codec
->control_data
= i2c
;
918 codec
->dev
= &i2c
->dev
;
920 return wm8960_register(wm8960
);
923 static __devexit
int wm8960_i2c_remove(struct i2c_client
*client
)
925 struct wm8960_priv
*wm8960
= i2c_get_clientdata(client
);
926 wm8960_unregister(wm8960
);
930 static const struct i2c_device_id wm8960_i2c_id
[] = {
934 MODULE_DEVICE_TABLE(i2c
, wm8960_i2c_id
);
936 static struct i2c_driver wm8960_i2c_driver
= {
938 .name
= "WM8960 I2C Codec",
939 .owner
= THIS_MODULE
,
941 .probe
= wm8960_i2c_probe
,
942 .remove
= __devexit_p(wm8960_i2c_remove
),
943 .id_table
= wm8960_i2c_id
,
946 static int __init
wm8960_modinit(void)
950 ret
= i2c_add_driver(&wm8960_i2c_driver
);
952 printk(KERN_ERR
"Failed to register WM8960 I2C driver: %d\n",
958 module_init(wm8960_modinit
);
960 static void __exit
wm8960_exit(void)
962 i2c_del_driver(&wm8960_i2c_driver
);
964 module_exit(wm8960_exit
);
967 MODULE_DESCRIPTION("ASoC WM8960 driver");
968 MODULE_AUTHOR("Liam Girdwood");
969 MODULE_LICENSE("GPL");