aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8955.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-12-18 07:00:22 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-12-18 08:06:47 -0500
commitb35a28af0a64a1e8e389bc009b76253256d8fe7b (patch)
treef4f7113bb7654d8b8dc732ed099e7aaa0cf4e905 /sound/soc/codecs/wm8955.c
parentc2151433847e88ba05c6bb539d9397ea90d755e6 (diff)
ASoC: Add initial WM8955 CODEC driver
The WM8955 is a low power, high quality stereo DAC with integrated headphone and loudspeaker amplifiers, designed to reduce external component requirements in portable digital audio applications. This is an initial driver implementing support for the majority of the functionality in the device, currently OUT3 is not supported. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/wm8955.c')
-rw-r--r--sound/soc/codecs/wm8955.c1151
1 files changed, 1151 insertions, 0 deletions
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
new file mode 100644
index 000000000000..615dab2b62ef
--- /dev/null
+++ b/sound/soc/codecs/wm8955.c
@@ -0,0 +1,1151 @@
1/*
2 * wm8955.c -- WM8955 ALSA SoC Audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/i2c.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/consumer.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28#include <sound/wm8955.h>
29
30#include "wm8955.h"
31
32static struct snd_soc_codec *wm8955_codec;
33struct snd_soc_codec_device soc_codec_dev_wm8955;
34
35#define WM8955_NUM_SUPPLIES 4
36static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
37 "DCVDD",
38 "DBVDD",
39 "HPVDD",
40 "AVDD",
41};
42
43/* codec private data */
44struct wm8955_priv {
45 struct snd_soc_codec codec;
46 u16 reg_cache[WM8955_MAX_REGISTER + 1];
47
48 unsigned int mclk_rate;
49
50 int deemph;
51 int fs;
52
53 struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
54
55 struct wm8955_pdata *pdata;
56};
57
58static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
59 0x0000, /* R0 */
60 0x0000, /* R1 */
61 0x0079, /* R2 - LOUT1 volume */
62 0x0079, /* R3 - ROUT1 volume */
63 0x0000, /* R4 */
64 0x0008, /* R5 - DAC Control */
65 0x0000, /* R6 */
66 0x000A, /* R7 - Audio Interface */
67 0x0000, /* R8 - Sample Rate */
68 0x0000, /* R9 */
69 0x00FF, /* R10 - Left DAC volume */
70 0x00FF, /* R11 - Right DAC volume */
71 0x000F, /* R12 - Bass control */
72 0x000F, /* R13 - Treble control */
73 0x0000, /* R14 */
74 0x0000, /* R15 - Reset */
75 0x0000, /* R16 */
76 0x0000, /* R17 */
77 0x0000, /* R18 */
78 0x0000, /* R19 */
79 0x0000, /* R20 */
80 0x0000, /* R21 */
81 0x0000, /* R22 */
82 0x00C1, /* R23 - Additional control (1) */
83 0x0000, /* R24 - Additional control (2) */
84 0x0000, /* R25 - Power Management (1) */
85 0x0000, /* R26 - Power Management (2) */
86 0x0000, /* R27 - Additional Control (3) */
87 0x0000, /* R28 */
88 0x0000, /* R29 */
89 0x0000, /* R30 */
90 0x0000, /* R31 */
91 0x0000, /* R32 */
92 0x0000, /* R33 */
93 0x0050, /* R34 - Left out Mix (1) */
94 0x0050, /* R35 - Left out Mix (2) */
95 0x0050, /* R36 - Right out Mix (1) */
96 0x0050, /* R37 - Right Out Mix (2) */
97 0x0050, /* R38 - Mono out Mix (1) */
98 0x0050, /* R39 - Mono out Mix (2) */
99 0x0079, /* R40 - LOUT2 volume */
100 0x0079, /* R41 - ROUT2 volume */
101 0x0079, /* R42 - MONOOUT volume */
102 0x0000, /* R43 - Clocking / PLL */
103 0x0103, /* R44 - PLL Control 1 */
104 0x0024, /* R45 - PLL Control 2 */
105 0x01BA, /* R46 - PLL Control 3 */
106 0x0000, /* R47 */
107 0x0000, /* R48 */
108 0x0000, /* R49 */
109 0x0000, /* R50 */
110 0x0000, /* R51 */
111 0x0000, /* R52 */
112 0x0000, /* R53 */
113 0x0000, /* R54 */
114 0x0000, /* R55 */
115 0x0000, /* R56 */
116 0x0000, /* R57 */
117 0x0000, /* R58 */
118 0x0000, /* R59 - PLL Control 4 */
119};
120
121static int wm8955_reset(struct snd_soc_codec *codec)
122{
123 return snd_soc_write(codec, WM8955_RESET, 0);
124}
125
126struct pll_factors {
127 int n;
128 int k;
129 int outdiv;
130};
131
132/* The size in bits of the FLL divide multiplied by 10
133 * to allow rounding later */
134#define FIXED_FLL_SIZE ((1 << 22) * 10)
135
136static int wm8995_pll_factors(struct device *dev,
137 int Fref, int Fout, struct pll_factors *pll)
138{
139 u64 Kpart;
140 unsigned int K, Ndiv, Nmod, target;
141
142 dev_dbg(dev, "Fref=%u Fout=%u\n", Fref, Fout);
143
144 /* The oscilator should run at should be 90-100MHz, and
145 * there's a divide by 4 plus an optional divide by 2 in the
146 * output path to generate the system clock. The clock table
147 * is sortd so we should always generate a suitable target. */
148 target = Fout * 4;
149 if (target < 90000000) {
150 pll->outdiv = 1;
151 target *= 2;
152 } else {
153 pll->outdiv = 0;
154 }
155
156 WARN_ON(target < 90000000 || target > 100000000);
157
158 dev_dbg(dev, "Fvco=%dHz\n", target);
159
160 /* Now, calculate N.K */
161 Ndiv = target / Fref;
162
163 pll->n = Ndiv;
164 Nmod = target % Fref;
165 dev_dbg(dev, "Nmod=%d\n", Nmod);
166
167 /* Calculate fractional part - scale up so we can round. */
168 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
169
170 do_div(Kpart, Fref);
171
172 K = Kpart & 0xFFFFFFFF;
173
174 if ((K % 10) >= 5)
175 K += 5;
176
177 /* Move down to proper range now rounding is done */
178 pll->k = K / 10;
179
180 dev_dbg(dev, "N=%x K=%x OUTDIV=%x\n", pll->n, pll->k, pll->outdiv);
181
182 return 0;
183}
184
185/* Lookup table specifiying SRATE (table 25 in datasheet); some of the
186 * output frequencies have been rounded to the standard frequencies
187 * they are intended to match where the error is slight. */
188static struct {
189 int mclk;
190 int fs;
191 int usb;
192 int sr;
193} clock_cfgs[] = {
194 { 18432000, 8000, 0, 3, },
195 { 18432000, 12000, 0, 9, },
196 { 18432000, 16000, 0, 11, },
197 { 18432000, 24000, 0, 29, },
198 { 18432000, 32000, 0, 13, },
199 { 18432000, 48000, 0, 1, },
200 { 18432000, 96000, 0, 15, },
201
202 { 16934400, 8018, 0, 19, },
203 { 16934400, 11025, 0, 25, },
204 { 16934400, 22050, 0, 27, },
205 { 16934400, 44100, 0, 17, },
206 { 16934400, 88200, 0, 31, },
207
208 { 12000000, 8000, 1, 2, },
209 { 12000000, 11025, 1, 25, },
210 { 12000000, 12000, 1, 8, },
211 { 12000000, 16000, 1, 10, },
212 { 12000000, 22050, 1, 27, },
213 { 12000000, 24000, 1, 28, },
214 { 12000000, 32000, 1, 12, },
215 { 12000000, 44100, 1, 17, },
216 { 12000000, 48000, 1, 0, },
217 { 12000000, 88200, 1, 31, },
218 { 12000000, 96000, 1, 14, },
219
220 { 12288000, 8000, 0, 2, },
221 { 12288000, 12000, 0, 8, },
222 { 12288000, 16000, 0, 10, },
223 { 12288000, 24000, 0, 28, },
224 { 12288000, 32000, 0, 12, },
225 { 12288000, 48000, 0, 0, },
226 { 12288000, 96000, 0, 14, },
227
228 { 12289600, 8018, 0, 18, },
229 { 12289600, 11025, 0, 24, },
230 { 12289600, 22050, 0, 26, },
231 { 11289600, 44100, 0, 16, },
232 { 11289600, 88200, 0, 31, },
233};
234
235static int wm8955_configure_clocking(struct snd_soc_codec *codec)
236{
237 struct wm8955_priv *wm8955 = codec->private_data;
238 int i, ret, val;
239 int clocking = 0;
240 int srate = 0;
241 int sr = -1;
242 struct pll_factors pll;
243
244 /* If we're not running a sample rate currently just pick one */
245 if (wm8955->fs == 0)
246 wm8955->fs = 8000;
247
248 /* Can we generate an exact output? */
249 for (i = 0; i < ARRAY_SIZE(clock_cfgs); i++) {
250 if (wm8955->fs != clock_cfgs[i].fs)
251 continue;
252 sr = i;
253
254 if (wm8955->mclk_rate == clock_cfgs[i].mclk)
255 break;
256 }
257
258 /* We should never get here with an unsupported sample rate */
259 if (sr == -1) {
260 dev_err(codec->dev, "Sample rate %dHz unsupported\n",
261 wm8955->fs);
262 WARN_ON(sr == -1);
263 return -EINVAL;
264 }
265
266 if (i == ARRAY_SIZE(clock_cfgs)) {
267 /* If we can't generate the right clock from MCLK then
268 * we should configure the PLL to supply us with an
269 * appropriate clock.
270 */
271 clocking |= WM8955_MCLKSEL;
272
273 /* Use the last divider configuration we saw for the
274 * sample rate. */
275 ret = wm8995_pll_factors(codec->dev, wm8955->mclk_rate,
276 clock_cfgs[sr].mclk, &pll);
277 if (ret != 0) {
278 dev_err(codec->dev,
279 "Unable to generate %dHz from %dHz MCLK\n",
280 wm8955->fs, wm8955->mclk_rate);
281 return -EINVAL;
282 }
283
284 snd_soc_update_bits(codec, WM8955_PLL_CONTROL_1,
285 WM8955_N_MASK | WM8955_K_21_18_MASK,
286 (pll.n << WM8955_N_SHIFT) |
287 pll.k >> 18);
288 snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2,
289 WM8955_K_17_9_MASK,
290 (pll.k >> 9) & WM8955_K_17_9_MASK);
291 snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2,
292 WM8955_K_8_0_MASK,
293 pll.k & WM8955_K_8_0_MASK);
294 if (pll.k)
295 snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4,
296 WM8955_KEN, WM8955_KEN);
297 else
298 snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4,
299 WM8955_KEN, 0);
300
301 if (pll.outdiv)
302 val = WM8955_PLL_RB | WM8955_PLLOUTDIV2;
303 else
304 val = WM8955_PLL_RB;
305
306 /* Now start the PLL running */
307 snd_soc_update_bits(codec, WM8955_CLOCKING_PLL,
308 WM8955_PLL_RB | WM8955_PLLOUTDIV2, val);
309 snd_soc_update_bits(codec, WM8955_CLOCKING_PLL,
310 WM8955_PLLEN, WM8955_PLLEN);
311 }
312
313 srate = clock_cfgs[sr].usb | (clock_cfgs[sr].sr << WM8955_SR_SHIFT);
314
315 snd_soc_update_bits(codec, WM8955_SAMPLE_RATE,
316 WM8955_USB | WM8955_SR_MASK, srate);
317 snd_soc_update_bits(codec, WM8955_CLOCKING_PLL,
318 WM8955_MCLKSEL, clocking);
319
320 return 0;
321}
322
323static int wm8955_sysclk(struct snd_soc_dapm_widget *w,
324 struct snd_kcontrol *kcontrol, int event)
325{
326 struct snd_soc_codec *codec = w->codec;
327 int ret = 0;
328
329 /* Always disable the clocks - if we're doing reconfiguration this
330 * avoids misclocking.
331 */
332 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
333 WM8955_DIGENB, 0);
334 snd_soc_update_bits(codec, WM8955_CLOCKING_PLL,
335 WM8955_PLL_RB | WM8955_PLLEN, 0);
336
337 switch (event) {
338 case SND_SOC_DAPM_POST_PMD:
339 break;
340 case SND_SOC_DAPM_PRE_PMU:
341 ret = wm8955_configure_clocking(codec);
342 break;
343 default:
344 ret = -EINVAL;
345 break;
346 }
347
348 return ret;
349}
350
351static int deemph_settings[] = { 0, 32000, 44100, 48000 };
352
353static int wm8955_set_deemph(struct snd_soc_codec *codec)
354{
355 struct wm8955_priv *wm8955 = codec->private_data;
356 int val, i, best;
357
358 /* If we're using deemphasis select the nearest available sample
359 * rate.
360 */
361 if (wm8955->deemph) {
362 best = 1;
363 for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) {
364 if (abs(deemph_settings[i] - wm8955->fs) <
365 abs(deemph_settings[best] - wm8955->fs))
366 best = i;
367 }
368
369 val = best << WM8955_DEEMPH_SHIFT;
370 } else {
371 val = 0;
372 }
373
374 dev_dbg(codec->dev, "Set deemphasis %d\n", val);
375
376 return snd_soc_update_bits(codec, WM8955_DAC_CONTROL,
377 WM8955_DEEMPH_MASK, val);
378}
379
380static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
381 struct snd_ctl_elem_value *ucontrol)
382{
383 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
384 struct wm8955_priv *wm8955 = codec->private_data;
385
386 return wm8955->deemph;
387}
388
389static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
390 struct snd_ctl_elem_value *ucontrol)
391{
392 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
393 struct wm8955_priv *wm8955 = codec->private_data;
394 int deemph = ucontrol->value.enumerated.item[0];
395
396 if (deemph > 1)
397 return -EINVAL;
398
399 wm8955->deemph = deemph;
400
401 return wm8955_set_deemph(codec);
402}
403
404static const char *bass_mode_text[] = {
405 "Linear", "Adaptive",
406};
407
408static const struct soc_enum bass_mode =
409 SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text);
410
411static const char *bass_cutoff_text[] = {
412 "Low", "High"
413};
414
415static const struct soc_enum bass_cutoff =
416 SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text);
417
418static const char *treble_cutoff_text[] = {
419 "High", "Low"
420};
421
422static const struct soc_enum treble_cutoff =
423 SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text);
424
425static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
426static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0);
427static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
428static const DECLARE_TLV_DB_SCALE(mono_tlv, -2100, 300, 0);
429static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
430static const DECLARE_TLV_DB_SCALE(treble_tlv, -1200, 150, 1);
431
432static const struct snd_kcontrol_new wm8955_snd_controls[] = {
433SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8955_LEFT_DAC_VOLUME,
434 WM8955_RIGHT_DAC_VOLUME, 0, 255, 0, digital_tlv),
435SOC_SINGLE_TLV("Playback Attenuation Volume", WM8955_DAC_CONTROL, 7, 1, 1,
436 atten_tlv),
437SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0,
438 wm8955_get_deemph, wm8955_put_deemph),
439
440SOC_ENUM("Bass Mode", bass_mode),
441SOC_ENUM("Bass Cutoff", bass_cutoff),
442SOC_SINGLE("Bass Volume", WM8955_BASS_CONTROL, 0, 15, 1),
443
444SOC_ENUM("Treble Cutoff", treble_cutoff),
445SOC_SINGLE_TLV("Treble Volume", WM8955_TREBLE_CONTROL, 0, 14, 1, treble_tlv),
446
447SOC_SINGLE_TLV("Left Bypass Volume", WM8955_LEFT_OUT_MIX_1, 4, 7, 1,
448 bypass_tlv),
449SOC_SINGLE_TLV("Left Mono Volume", WM8955_LEFT_OUT_MIX_2, 4, 7, 1,
450 bypass_tlv),
451
452SOC_SINGLE_TLV("Right Mono Volume", WM8955_RIGHT_OUT_MIX_1, 4, 7, 1,
453 bypass_tlv),
454SOC_SINGLE_TLV("Right Bypass Volume", WM8955_RIGHT_OUT_MIX_2, 4, 7, 1,
455 bypass_tlv),
456
457/* Not a stereo pair so they line up with the DAPM switches */
458SOC_SINGLE_TLV("Mono Left Bypass Volume", WM8955_MONO_OUT_MIX_1, 4, 7, 1,
459 mono_tlv),
460SOC_SINGLE_TLV("Mono Right Bypass Volume", WM8955_MONO_OUT_MIX_2, 4, 7, 1,
461 mono_tlv),
462
463SOC_DOUBLE_R_TLV("Headphone Volume", WM8955_LOUT1_VOLUME,
464 WM8955_ROUT1_VOLUME, 0, 127, 0, out_tlv),
465SOC_DOUBLE_R("Headphone ZC Switch", WM8955_LOUT1_VOLUME,
466 WM8955_ROUT1_VOLUME, 7, 1, 0),
467
468SOC_DOUBLE_R_TLV("Speaker Volume", WM8955_LOUT2_VOLUME,
469 WM8955_ROUT2_VOLUME, 0, 127, 0, out_tlv),
470SOC_DOUBLE_R("Speaker ZC Switch", WM8955_LOUT2_VOLUME,
471 WM8955_ROUT2_VOLUME, 7, 1, 0),
472
473SOC_SINGLE_TLV("Mono Volume", WM8955_MONOOUT_VOLUME, 0, 127, 0, out_tlv),
474SOC_SINGLE("Mono ZC Switch", WM8955_MONOOUT_VOLUME, 7, 1, 0),
475};
476
477static const struct snd_kcontrol_new lmixer[] = {
478SOC_DAPM_SINGLE("Playback Switch", WM8955_LEFT_OUT_MIX_1, 8, 1, 0),
479SOC_DAPM_SINGLE("Bypass Switch", WM8955_LEFT_OUT_MIX_1, 7, 1, 0),
480SOC_DAPM_SINGLE("Right Playback Switch", WM8955_LEFT_OUT_MIX_2, 8, 1, 0),
481SOC_DAPM_SINGLE("Mono Switch", WM8955_LEFT_OUT_MIX_2, 7, 1, 0),
482};
483
484static const struct snd_kcontrol_new rmixer[] = {
485SOC_DAPM_SINGLE("Left Playback Switch", WM8955_RIGHT_OUT_MIX_1, 8, 1, 0),
486SOC_DAPM_SINGLE("Mono Switch", WM8955_RIGHT_OUT_MIX_1, 7, 1, 0),
487SOC_DAPM_SINGLE("Playback Switch", WM8955_RIGHT_OUT_MIX_2, 8, 1, 0),
488SOC_DAPM_SINGLE("Bypass Switch", WM8955_RIGHT_OUT_MIX_2, 7, 1, 0),
489};
490
491static const struct snd_kcontrol_new mmixer[] = {
492SOC_DAPM_SINGLE("Left Playback Switch", WM8955_MONO_OUT_MIX_1, 8, 1, 0),
493SOC_DAPM_SINGLE("Left Bypass Switch", WM8955_MONO_OUT_MIX_1, 7, 1, 0),
494SOC_DAPM_SINGLE("Right Playback Switch", WM8955_MONO_OUT_MIX_2, 8, 1, 0),
495SOC_DAPM_SINGLE("Right Bypass Switch", WM8955_MONO_OUT_MIX_2, 7, 1, 0),
496};
497
498static const struct snd_soc_dapm_widget wm8955_dapm_widgets[] = {
499SND_SOC_DAPM_INPUT("MONOIN-"),
500SND_SOC_DAPM_INPUT("MONOIN+"),
501SND_SOC_DAPM_INPUT("LINEINR"),
502SND_SOC_DAPM_INPUT("LINEINL"),
503
504SND_SOC_DAPM_PGA("Mono Input", SND_SOC_NOPM, 0, 0, NULL, 0),
505
506SND_SOC_DAPM_SUPPLY("SYSCLK", WM8955_POWER_MANAGEMENT_1, 0, 1, wm8955_sysclk,
507 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
508SND_SOC_DAPM_SUPPLY("TSDEN", WM8955_ADDITIONAL_CONTROL_1, 8, 0, NULL, 0),
509
510SND_SOC_DAPM_DAC("DACL", "Playback", WM8955_POWER_MANAGEMENT_2, 8, 0),
511SND_SOC_DAPM_DAC("DACR", "Playback", WM8955_POWER_MANAGEMENT_2, 7, 0),
512
513SND_SOC_DAPM_PGA("LOUT1 PGA", WM8955_POWER_MANAGEMENT_2, 6, 0, NULL, 0),
514SND_SOC_DAPM_PGA("ROUT1 PGA", WM8955_POWER_MANAGEMENT_2, 5, 0, NULL, 0),
515SND_SOC_DAPM_PGA("LOUT2 PGA", WM8955_POWER_MANAGEMENT_2, 4, 0, NULL, 0),
516SND_SOC_DAPM_PGA("ROUT2 PGA", WM8955_POWER_MANAGEMENT_2, 3, 0, NULL, 0),
517SND_SOC_DAPM_PGA("MOUT PGA", WM8955_POWER_MANAGEMENT_2, 2, 0, NULL, 0),
518SND_SOC_DAPM_PGA("OUT3 PGA", WM8955_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
519
520/* The names are chosen to make the control names nice */
521SND_SOC_DAPM_MIXER("Left", SND_SOC_NOPM, 0, 0,
522 lmixer, ARRAY_SIZE(lmixer)),
523SND_SOC_DAPM_MIXER("Right", SND_SOC_NOPM, 0, 0,
524 rmixer, ARRAY_SIZE(rmixer)),
525SND_SOC_DAPM_MIXER("Mono", SND_SOC_NOPM, 0, 0,
526 mmixer, ARRAY_SIZE(mmixer)),
527
528SND_SOC_DAPM_OUTPUT("LOUT1"),
529SND_SOC_DAPM_OUTPUT("ROUT1"),
530SND_SOC_DAPM_OUTPUT("LOUT2"),
531SND_SOC_DAPM_OUTPUT("ROUT2"),
532SND_SOC_DAPM_OUTPUT("MONOOUT"),
533SND_SOC_DAPM_OUTPUT("OUT3"),
534};
535
536static const struct snd_soc_dapm_route wm8955_intercon[] = {
537 { "DACL", NULL, "SYSCLK" },
538 { "DACR", NULL, "SYSCLK" },
539
540 { "Mono Input", NULL, "MONOIN-" },
541 { "Mono Input", NULL, "MONOIN+" },
542
543 { "Left", "Playback Switch", "DACL" },
544 { "Left", "Right Playback Switch", "DACR" },
545 { "Left", "Bypass Switch", "LINEINL" },
546 { "Left", "Mono Switch", "Mono Input" },
547
548 { "Right", "Playback Switch", "DACR" },
549 { "Right", "Left Playback Switch", "DACL" },
550 { "Right", "Bypass Switch", "LINEINR" },
551 { "Right", "Mono Switch", "Mono Input" },
552
553 { "Mono", "Left Playback Switch", "DACL" },
554 { "Mono", "Right Playback Switch", "DACR" },
555 { "Mono", "Left Bypass Switch", "LINEINL" },
556 { "Mono", "Right Bypass Switch", "LINEINR" },
557
558 { "LOUT1 PGA", NULL, "Left" },
559 { "LOUT1", NULL, "TSDEN" },
560 { "LOUT1", NULL, "LOUT1 PGA" },
561
562 { "ROUT1 PGA", NULL, "Right" },
563 { "ROUT1", NULL, "TSDEN" },
564 { "ROUT1", NULL, "ROUT1 PGA" },
565
566 { "LOUT2 PGA", NULL, "Left" },
567 { "LOUT2", NULL, "TSDEN" },
568 { "LOUT2", NULL, "LOUT2 PGA" },
569
570 { "ROUT2 PGA", NULL, "Right" },
571 { "ROUT2", NULL, "TSDEN" },
572 { "ROUT2", NULL, "ROUT2 PGA" },
573
574 { "MOUT PGA", NULL, "Mono" },
575 { "MONOOUT", NULL, "MOUT PGA" },
576
577 /* OUT3 not currently implemented */
578 { "OUT3", NULL, "OUT3 PGA" },
579};
580
581static int wm8955_add_widgets(struct snd_soc_codec *codec)
582{
583 snd_soc_add_controls(codec, wm8955_snd_controls,
584 ARRAY_SIZE(wm8955_snd_controls));
585
586 snd_soc_dapm_new_controls(codec, wm8955_dapm_widgets,
587 ARRAY_SIZE(wm8955_dapm_widgets));
588
589 snd_soc_dapm_add_routes(codec, wm8955_intercon,
590 ARRAY_SIZE(wm8955_intercon));
591
592 return 0;
593}
594
595static int wm8955_hw_params(struct snd_pcm_substream *substream,
596 struct snd_pcm_hw_params *params,
597 struct snd_soc_dai *dai)
598{
599 struct snd_soc_codec *codec = dai->codec;
600 struct wm8955_priv *wm8955 = codec->private_data;
601 int ret;
602 int wl;
603
604 switch (params_format(params)) {
605 case SNDRV_PCM_FORMAT_S16_LE:
606 wl = 0;
607 break;
608 case SNDRV_PCM_FORMAT_S20_3LE:
609 wl = 0x4;
610 break;
611 case SNDRV_PCM_FORMAT_S24_LE:
612 wl = 0x8;
613 break;
614 case SNDRV_PCM_FORMAT_S32_LE:
615 wl = 0xc;
616 break;
617 default:
618 return -EINVAL;
619 }
620 snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE,
621 WM8955_WL_MASK, wl);
622
623 wm8955->fs = params_rate(params);
624 wm8955_set_deemph(codec);
625
626 /* If the chip is clocked then disable the clocks and force a
627 * reconfiguration, otherwise DAPM will power up the
628 * clocks for us later. */
629 ret = snd_soc_read(codec, WM8955_POWER_MANAGEMENT_1);
630 if (ret < 0)
631 return ret;
632 if (ret & WM8955_DIGENB) {
633 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
634 WM8955_DIGENB, 0);
635 snd_soc_update_bits(codec, WM8955_CLOCKING_PLL,
636 WM8955_PLL_RB | WM8955_PLLEN, 0);
637
638 wm8955_configure_clocking(codec);
639 }
640
641 return 0;
642}
643
644
645static int wm8955_set_sysclk(struct snd_soc_dai *dai, int clk_id,
646 unsigned int freq, int dir)
647{
648 struct snd_soc_codec *codec = dai->codec;
649 struct wm8955_priv *priv = codec->private_data;
650 int div;
651
652 switch (clk_id) {
653 case WM8955_CLK_MCLK:
654 if (freq > 15000000) {
655 priv->mclk_rate = freq /= 2;
656 div = WM8955_MCLKDIV2;
657 } else {
658 priv->mclk_rate = freq;
659 div = 0;
660 }
661
662 snd_soc_update_bits(codec, WM8955_SAMPLE_RATE,
663 WM8955_MCLKDIV2, div);
664 break;
665
666 default:
667 return -EINVAL;
668 }
669
670 dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq);
671
672 return 0;
673}
674
675static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
676{
677 struct snd_soc_codec *codec = dai->codec;
678 u16 aif = 0;
679
680 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
681 case SND_SOC_DAIFMT_CBS_CFS:
682 break;
683 case SND_SOC_DAIFMT_CBM_CFM:
684 aif |= WM8955_MS;
685 break;
686 default:
687 return -EINVAL;
688 }
689
690 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
691 case SND_SOC_DAIFMT_DSP_B:
692 aif |= WM8955_LRP;
693 case SND_SOC_DAIFMT_DSP_A:
694 aif |= 0x3;
695 break;
696 case SND_SOC_DAIFMT_I2S:
697 aif |= 0x2;
698 break;
699 case SND_SOC_DAIFMT_RIGHT_J:
700 break;
701 case SND_SOC_DAIFMT_LEFT_J:
702 aif |= 0x1;
703 break;
704 default:
705 return -EINVAL;
706 }
707
708 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
709 case SND_SOC_DAIFMT_DSP_A:
710 case SND_SOC_DAIFMT_DSP_B:
711 /* frame inversion not valid for DSP modes */
712 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
713 case SND_SOC_DAIFMT_NB_NF:
714 break;
715 case SND_SOC_DAIFMT_IB_NF:
716 aif |= WM8955_BCLKINV;
717 break;
718 default:
719 return -EINVAL;
720 }
721 break;
722
723 case SND_SOC_DAIFMT_I2S:
724 case SND_SOC_DAIFMT_RIGHT_J:
725 case SND_SOC_DAIFMT_LEFT_J:
726 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
727 case SND_SOC_DAIFMT_NB_NF:
728 break;
729 case SND_SOC_DAIFMT_IB_IF:
730 aif |= WM8955_BCLKINV | WM8955_LRP;
731 break;
732 case SND_SOC_DAIFMT_IB_NF:
733 aif |= WM8955_BCLKINV;
734 break;
735 case SND_SOC_DAIFMT_NB_IF:
736 aif |= WM8955_LRP;
737 break;
738 default:
739 return -EINVAL;
740 }
741 break;
742 default:
743 return -EINVAL;
744 }
745
746 snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE,
747 WM8955_MS | WM8955_FORMAT_MASK | WM8955_BCLKINV |
748 WM8955_LRP, aif);
749
750 return 0;
751}
752
753
754static int wm8955_digital_mute(struct snd_soc_dai *codec_dai, int mute)
755{
756 struct snd_soc_codec *codec = codec_dai->codec;
757 int val;
758
759 if (mute)
760 val = WM8955_DACMU;
761 else
762 val = 0;
763
764 snd_soc_update_bits(codec, WM8955_DAC_CONTROL, WM8955_DACMU, val);
765
766 return 0;
767}
768
769static int wm8955_set_bias_level(struct snd_soc_codec *codec,
770 enum snd_soc_bias_level level)
771{
772 struct wm8955_priv *wm8955 = codec->private_data;
773 int ret, i;
774
775 switch (level) {
776 case SND_SOC_BIAS_ON:
777 break;
778
779 case SND_SOC_BIAS_PREPARE:
780 /* VMID resistance 2*50k */
781 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
782 WM8955_VMIDSEL_MASK,
783 0x1 << WM8955_VMIDSEL_SHIFT);
784
785 /* Default bias current */
786 snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1,
787 WM8955_VSEL_MASK,
788 0x2 << WM8955_VSEL_SHIFT);
789 break;
790
791 case SND_SOC_BIAS_STANDBY:
792 if (codec->bias_level == SND_SOC_BIAS_OFF) {
793 ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies),
794 wm8955->supplies);
795 if (ret != 0) {
796 dev_err(codec->dev,
797 "Failed to enable supplies: %d\n",
798 ret);
799 return ret;
800 }
801
802 /* Sync back cached values if they're
803 * different from the hardware default.
804 */
805 for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) {
806 if (i == WM8955_RESET)
807 continue;
808
809 if (wm8955->reg_cache[i] == wm8955_reg[i])
810 continue;
811
812 snd_soc_write(codec, i, wm8955->reg_cache[i]);
813 }
814
815 /* Enable VREF and VMID */
816 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
817 WM8955_VREF |
818 WM8955_VMIDSEL_MASK,
819 WM8955_VREF |
820 0x3 << WM8955_VREF_SHIFT);
821
822 /* Let VMID ramp */
823 msleep(500);
824
825 /* High resistance VROI to maintain outputs */
826 snd_soc_update_bits(codec,
827 WM8955_ADDITIONAL_CONTROL_3,
828 WM8955_VROI, WM8955_VROI);
829 }
830
831 /* Maintain VMID with 2*250k */
832 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
833 WM8955_VMIDSEL_MASK,
834 0x2 << WM8955_VMIDSEL_SHIFT);
835
836 /* Minimum bias current */
837 snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1,
838 WM8955_VSEL_MASK, 0);
839 break;
840
841 case SND_SOC_BIAS_OFF:
842 /* Low resistance VROI to help discharge */
843 snd_soc_update_bits(codec,
844 WM8955_ADDITIONAL_CONTROL_3,
845 WM8955_VROI, 0);
846
847 /* Turn off VMID and VREF */
848 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
849 WM8955_VREF |
850 WM8955_VMIDSEL_MASK, 0);
851
852 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies),
853 wm8955->supplies);
854 break;
855 }
856 codec->bias_level = level;
857 return 0;
858}
859
860#define WM8955_RATES SNDRV_PCM_RATE_8000_96000
861
862#define WM8955_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
863 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
864
865static struct snd_soc_dai_ops wm8955_dai_ops = {
866 .set_sysclk = wm8955_set_sysclk,
867 .set_fmt = wm8955_set_fmt,
868 .hw_params = wm8955_hw_params,
869 .digital_mute = wm8955_digital_mute,
870};
871
872struct snd_soc_dai wm8955_dai = {
873 .name = "WM8955",
874 .playback = {
875 .stream_name = "Playback",
876 .channels_min = 2,
877 .channels_max = 2,
878 .rates = WM8955_RATES,
879 .formats = WM8955_FORMATS,
880 },
881 .ops = &wm8955_dai_ops,
882};
883EXPORT_SYMBOL_GPL(wm8955_dai);
884
885#ifdef CONFIG_PM
886static int wm8955_suspend(struct platform_device *pdev, pm_message_t state)
887{
888 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
889 struct snd_soc_codec *codec = socdev->card->codec;
890
891 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
892
893 return 0;
894}
895
896static int wm8955_resume(struct platform_device *pdev)
897{
898 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
899 struct snd_soc_codec *codec = socdev->card->codec;
900
901 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
902
903 return 0;
904}
905#else
906#define wm8955_suspend NULL
907#define wm8955_resume NULL
908#endif
909
910static int wm8955_probe(struct platform_device *pdev)
911{
912 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
913 struct snd_soc_codec *codec;
914 int ret = 0;
915
916 if (wm8955_codec == NULL) {
917 dev_err(&pdev->dev, "Codec device not registered\n");
918 return -ENODEV;
919 }
920
921 socdev->card->codec = wm8955_codec;
922 codec = wm8955_codec;
923
924 /* register pcms */
925 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
926 if (ret < 0) {
927 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
928 goto pcm_err;
929 }
930
931 wm8955_add_widgets(codec);
932
933 return ret;
934
935pcm_err:
936 return ret;
937}
938
939static int wm8955_remove(struct platform_device *pdev)
940{
941 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
942
943 snd_soc_free_pcms(socdev);
944 snd_soc_dapm_free(socdev);
945
946 return 0;
947}
948
949struct snd_soc_codec_device soc_codec_dev_wm8955 = {
950 .probe = wm8955_probe,
951 .remove = wm8955_remove,
952 .suspend = wm8955_suspend,
953 .resume = wm8955_resume,
954};
955EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955);
956
957static int wm8955_register(struct wm8955_priv *wm8955,
958 enum snd_soc_control_type control)
959{
960 int ret;
961 struct snd_soc_codec *codec = &wm8955->codec;
962 int i;
963
964 if (wm8955_codec) {
965 dev_err(codec->dev, "Another WM8955 is registered\n");
966 return -EINVAL;
967 }
968
969 mutex_init(&codec->mutex);
970 INIT_LIST_HEAD(&codec->dapm_widgets);
971 INIT_LIST_HEAD(&codec->dapm_paths);
972
973 codec->private_data = wm8955;
974 codec->name = "WM8955";
975 codec->owner = THIS_MODULE;
976 codec->bias_level = SND_SOC_BIAS_OFF;
977 codec->set_bias_level = wm8955_set_bias_level;
978 codec->dai = &wm8955_dai;
979 codec->num_dai = 1;
980 codec->reg_cache_size = WM8955_MAX_REGISTER;
981 codec->reg_cache = &wm8955->reg_cache;
982
983 memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg));
984
985 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
986 if (ret != 0) {
987 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
988 goto err;
989 }
990
991 for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++)
992 wm8955->supplies[i].supply = wm8955_supply_names[i];
993
994 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8955->supplies),
995 wm8955->supplies);
996 if (ret != 0) {
997 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
998 goto err;
999 }
1000
1001 ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies),
1002 wm8955->supplies);
1003 if (ret != 0) {
1004 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1005 goto err_get;
1006 }
1007
1008 ret = wm8955_reset(codec);
1009 if (ret < 0) {
1010 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
1011 goto err_enable;
1012 }
1013
1014 wm8955_dai.dev = codec->dev;
1015
1016 /* Change some default settings - latch VU and enable ZC */
1017 wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
1018 wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
1019 wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
1020 wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
1021 wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
1022 wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
1023 wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
1024
1025 /* Also enable adaptive bass boost by default */
1026 wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
1027
1028 /* Set platform data values */
1029 if (wm8955->pdata) {
1030 if (wm8955->pdata->out2_speaker)
1031 wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
1032 |= WM8955_ROUT2INV;
1033
1034 if (wm8955->pdata->monoin_diff)
1035 wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
1036 |= WM8955_DMEN;
1037 }
1038
1039 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1040
1041 /* Bias level configuration will have done an extra enable */
1042 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1043
1044 wm8955_codec = codec;
1045
1046 ret = snd_soc_register_codec(codec);
1047 if (ret != 0) {
1048 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1049 return ret;
1050 }
1051
1052 ret = snd_soc_register_dai(&wm8955_dai);
1053 if (ret != 0) {
1054 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1055 snd_soc_unregister_codec(codec);
1056 return ret;
1057 }
1058
1059 return 0;
1060
1061err_enable:
1062 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1063err_get:
1064 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1065err:
1066 kfree(wm8955);
1067 return ret;
1068}
1069
1070static void wm8955_unregister(struct wm8955_priv *wm8955)
1071{
1072 wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF);
1073 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1074 snd_soc_unregister_dai(&wm8955_dai);
1075 snd_soc_unregister_codec(&wm8955->codec);
1076 kfree(wm8955);
1077 wm8955_codec = NULL;
1078}
1079
1080#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1081static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
1082 const struct i2c_device_id *id)
1083{
1084 struct wm8955_priv *wm8955;
1085 struct snd_soc_codec *codec;
1086
1087 wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
1088 if (wm8955 == NULL)
1089 return -ENOMEM;
1090
1091 codec = &wm8955->codec;
1092 codec->hw_write = (hw_write_t)i2c_master_send;
1093
1094 i2c_set_clientdata(i2c, wm8955);
1095 codec->control_data = i2c;
1096 wm8955->pdata = i2c->dev.platform_data;
1097
1098 codec->dev = &i2c->dev;
1099
1100 return wm8955_register(wm8955, SND_SOC_I2C);
1101}
1102
1103static __devexit int wm8955_i2c_remove(struct i2c_client *client)
1104{
1105 struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
1106 wm8955_unregister(wm8955);
1107 return 0;
1108}
1109
1110static const struct i2c_device_id wm8955_i2c_id[] = {
1111 { "wm8955", 0 },
1112 { }
1113};
1114MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
1115
1116static struct i2c_driver wm8955_i2c_driver = {
1117 .driver = {
1118 .name = "wm8955",
1119 .owner = THIS_MODULE,
1120 },
1121 .probe = wm8955_i2c_probe,
1122 .remove = __devexit_p(wm8955_i2c_remove),
1123 .id_table = wm8955_i2c_id,
1124};
1125#endif
1126
1127static int __init wm8955_modinit(void)
1128{
1129 int ret;
1130#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1131 ret = i2c_add_driver(&wm8955_i2c_driver);
1132 if (ret != 0) {
1133 printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n",
1134 ret);
1135 }
1136#endif
1137 return 0;
1138}
1139module_init(wm8955_modinit);
1140
1141static void __exit wm8955_exit(void)
1142{
1143#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1144 i2c_del_driver(&wm8955_i2c_driver);
1145#endif
1146}
1147module_exit(wm8955_exit);
1148
1149MODULE_DESCRIPTION("ASoC WM8955 driver");
1150MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1151MODULE_LICENSE("GPL");