blob: f6b6ea8980226f76f02ec4a53f1382f3ce6f9ee8 [file] [log] [blame]
Mark Brown6d4baf02011-09-20 15:44:21 +01001/*
2 * wm5100.c -- WM5100 ALSA SoC Audio driver
3 *
4 * Copyright 2011 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/gcd.h>
19#include <linux/gpio.h>
20#include <linux/i2c.h>
Mark Brown62c1c402012-01-26 17:28:49 +000021#include <linux/pm_runtime.h>
Mark Brown6d4baf02011-09-20 15:44:21 +010022#include <linux/regulator/consumer.h>
23#include <linux/regulator/fixed.h>
24#include <linux/slab.h>
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
Mark Brownba896ed2011-09-27 17:39:50 +010029#include <sound/jack.h>
Mark Brown6d4baf02011-09-20 15:44:21 +010030#include <sound/initval.h>
31#include <sound/tlv.h>
32#include <sound/wm5100.h>
33
34#include "wm5100.h"
35
36#define WM5100_NUM_CORE_SUPPLIES 2
37static const char *wm5100_core_supply_names[WM5100_NUM_CORE_SUPPLIES] = {
38 "DBVDD1",
39 "LDOVDD", /* If DCVDD is supplied externally specify as LDOVDD */
40};
41
42#define WM5100_AIFS 3
43#define WM5100_SYNC_SRS 3
44
45struct wm5100_fll {
46 int fref;
47 int fout;
48 int src;
49 struct completion lock;
50};
51
52/* codec private data */
53struct wm5100_priv {
Mark Brown46c1a872012-01-18 14:53:08 +000054 struct device *dev;
Mark Brownbd132ec2011-10-23 11:10:45 +010055 struct regmap *regmap;
Mark Brown6d4baf02011-09-20 15:44:21 +010056 struct snd_soc_codec *codec;
57
58 struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
Mark Brown6d4baf02011-09-20 15:44:21 +010059
60 int rev;
61
62 int sysclk;
63 int asyncclk;
64
65 bool aif_async[WM5100_AIFS];
66 bool aif_symmetric[WM5100_AIFS];
67 int sr_ref[WM5100_SYNC_SRS];
68
69 bool out_ena[2];
70
Mark Brownba896ed2011-09-27 17:39:50 +010071 struct snd_soc_jack *jack;
72 bool jack_detecting;
73 bool jack_mic;
74 int jack_mode;
Mark Brown2633f732012-01-26 17:43:09 +000075 int jack_flips;
Mark Brownba896ed2011-09-27 17:39:50 +010076
Mark Brown6d4baf02011-09-20 15:44:21 +010077 struct wm5100_fll fll[2];
78
79 struct wm5100_pdata pdata;
80
81#ifdef CONFIG_GPIOLIB
82 struct gpio_chip gpio_chip;
83#endif
84};
85
86static int wm5100_sr_code[] = {
87 0,
88 12000,
89 24000,
90 48000,
91 96000,
92 192000,
93 384000,
94 768000,
95 0,
96 11025,
97 22050,
98 44100,
99 88200,
100 176400,
101 352800,
102 705600,
103 4000,
104 8000,
105 16000,
106 32000,
107 64000,
108 128000,
109 256000,
110 512000,
111};
112
113static int wm5100_sr_regs[WM5100_SYNC_SRS] = {
114 WM5100_CLOCKING_4,
115 WM5100_CLOCKING_5,
116 WM5100_CLOCKING_6,
117};
118
119static int wm5100_alloc_sr(struct snd_soc_codec *codec, int rate)
120{
121 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
122 int sr_code, sr_free, i;
123
124 for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
125 if (wm5100_sr_code[i] == rate)
126 break;
127 if (i == ARRAY_SIZE(wm5100_sr_code)) {
128 dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
129 return -EINVAL;
130 }
131 sr_code = i;
132
133 if ((wm5100->sysclk % rate) == 0) {
134 /* Is this rate already in use? */
135 sr_free = -1;
136 for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
137 if (!wm5100->sr_ref[i] && sr_free == -1) {
138 sr_free = i;
139 continue;
140 }
141 if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
142 WM5100_SAMPLE_RATE_1_MASK) == sr_code)
143 break;
144 }
145
146 if (i < ARRAY_SIZE(wm5100_sr_regs)) {
147 wm5100->sr_ref[i]++;
148 dev_dbg(codec->dev, "SR %dHz, slot %d, ref %d\n",
149 rate, i, wm5100->sr_ref[i]);
150 return i;
151 }
152
153 if (sr_free == -1) {
154 dev_err(codec->dev, "All SR slots already in use\n");
155 return -EBUSY;
156 }
157
158 dev_dbg(codec->dev, "Allocating SR slot %d for %dHz\n",
159 sr_free, rate);
160 wm5100->sr_ref[sr_free]++;
161 snd_soc_update_bits(codec, wm5100_sr_regs[sr_free],
162 WM5100_SAMPLE_RATE_1_MASK,
163 sr_code);
164
165 return sr_free;
166
167 } else {
168 dev_err(codec->dev,
169 "SR %dHz incompatible with %dHz SYSCLK and %dHz ASYNCCLK\n",
170 rate, wm5100->sysclk, wm5100->asyncclk);
171 return -EINVAL;
172 }
173}
174
175static void wm5100_free_sr(struct snd_soc_codec *codec, int rate)
176{
177 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
178 int i, sr_code;
179
180 for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
181 if (wm5100_sr_code[i] == rate)
182 break;
183 if (i == ARRAY_SIZE(wm5100_sr_code)) {
184 dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
185 return;
186 }
187 sr_code = wm5100_sr_code[i];
188
189 for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
190 if (!wm5100->sr_ref[i])
191 continue;
192
193 if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
194 WM5100_SAMPLE_RATE_1_MASK) == sr_code)
195 break;
196 }
197 if (i < ARRAY_SIZE(wm5100_sr_regs)) {
198 wm5100->sr_ref[i]--;
199 dev_dbg(codec->dev, "Dereference SR %dHz, count now %d\n",
200 rate, wm5100->sr_ref[i]);
201 } else {
202 dev_warn(codec->dev, "Freeing unreferenced sample rate %dHz\n",
203 rate);
204 }
205}
206
Mark Brown588ac5e2011-11-09 16:12:04 +0000207static int wm5100_reset(struct wm5100_priv *wm5100)
Mark Brown6d4baf02011-09-20 15:44:21 +0100208{
Mark Brown6d4baf02011-09-20 15:44:21 +0100209 if (wm5100->pdata.reset) {
210 gpio_set_value_cansleep(wm5100->pdata.reset, 0);
211 gpio_set_value_cansleep(wm5100->pdata.reset, 1);
212
213 return 0;
214 } else {
Mark Brown588ac5e2011-11-09 16:12:04 +0000215 return regmap_write(wm5100->regmap, WM5100_SOFTWARE_RESET, 0);
Mark Brown6d4baf02011-09-20 15:44:21 +0100216 }
217}
218
219static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
220static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
221static DECLARE_TLV_DB_SCALE(mixer_tlv, -3200, 100, 0);
222static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
223static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
224
225static const char *wm5100_mixer_texts[] = {
226 "None",
227 "Tone Generator 1",
228 "Tone Generator 2",
229 "AEC loopback",
230 "IN1L",
231 "IN1R",
232 "IN2L",
233 "IN2R",
234 "IN3L",
235 "IN3R",
236 "IN4L",
237 "IN4R",
238 "AIF1RX1",
239 "AIF1RX2",
240 "AIF1RX3",
241 "AIF1RX4",
242 "AIF1RX5",
243 "AIF1RX6",
244 "AIF1RX7",
245 "AIF1RX8",
246 "AIF2RX1",
247 "AIF2RX2",
248 "AIF3RX1",
249 "AIF3RX2",
250 "EQ1",
251 "EQ2",
252 "EQ3",
253 "EQ4",
254 "DRC1L",
255 "DRC1R",
256 "LHPF1",
257 "LHPF2",
258 "LHPF3",
259 "LHPF4",
260 "DSP1.1",
261 "DSP1.2",
262 "DSP1.3",
263 "DSP1.4",
264 "DSP1.5",
265 "DSP1.6",
266 "DSP2.1",
267 "DSP2.2",
268 "DSP2.3",
269 "DSP2.4",
270 "DSP2.5",
271 "DSP2.6",
272 "DSP3.1",
273 "DSP3.2",
274 "DSP3.3",
275 "DSP3.4",
276 "DSP3.5",
277 "DSP3.6",
278 "ASRC1L",
279 "ASRC1R",
280 "ASRC2L",
281 "ASRC2R",
282 "ISRC1INT1",
283 "ISRC1INT2",
284 "ISRC1INT3",
285 "ISRC1INT4",
286 "ISRC2INT1",
287 "ISRC2INT2",
288 "ISRC2INT3",
289 "ISRC2INT4",
290 "ISRC1DEC1",
291 "ISRC1DEC2",
292 "ISRC1DEC3",
293 "ISRC1DEC4",
294 "ISRC2DEC1",
295 "ISRC2DEC2",
296 "ISRC2DEC3",
297 "ISRC2DEC4",
298};
299
300static int wm5100_mixer_values[] = {
301 0x00,
302 0x04, /* Tone */
303 0x05,
304 0x08, /* AEC */
305 0x10, /* Input */
306 0x11,
307 0x12,
308 0x13,
309 0x14,
310 0x15,
311 0x16,
312 0x17,
313 0x20, /* AIF */
314 0x21,
315 0x22,
316 0x23,
317 0x24,
318 0x25,
319 0x26,
320 0x27,
321 0x28,
322 0x29,
323 0x30, /* AIF3 - check */
324 0x31,
325 0x50, /* EQ */
326 0x51,
327 0x52,
328 0x53,
329 0x54,
330 0x58, /* DRC */
331 0x59,
332 0x60, /* LHPF1 */
333 0x61, /* LHPF2 */
334 0x62, /* LHPF3 */
335 0x63, /* LHPF4 */
336 0x68, /* DSP1 */
337 0x69,
338 0x6a,
339 0x6b,
340 0x6c,
341 0x6d,
342 0x70, /* DSP2 */
343 0x71,
344 0x72,
345 0x73,
346 0x74,
347 0x75,
348 0x78, /* DSP3 */
349 0x79,
350 0x7a,
351 0x7b,
352 0x7c,
353 0x7d,
354 0x90, /* ASRC1 */
355 0x91,
356 0x92, /* ASRC2 */
357 0x93,
358 0xa0, /* ISRC1DEC1 */
359 0xa1,
360 0xa2,
361 0xa3,
362 0xa4, /* ISRC1INT1 */
363 0xa5,
364 0xa6,
365 0xa7,
366 0xa8, /* ISRC2DEC1 */
367 0xa9,
368 0xaa,
369 0xab,
370 0xac, /* ISRC2INT1 */
371 0xad,
372 0xae,
373 0xaf,
374};
375
376#define WM5100_MIXER_CONTROLS(name, base) \
377 SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
378 WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
379 SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
380 WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
381 SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
382 WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
383 SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
384 WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
385
386#define WM5100_MUX_ENUM_DECL(name, reg) \
387 SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
388 wm5100_mixer_texts, wm5100_mixer_values)
389
390#define WM5100_MUX_CTL_DECL(name) \
391 const struct snd_kcontrol_new name##_mux = \
392 SOC_DAPM_VALUE_ENUM("Route", name##_enum)
393
394#define WM5100_MIXER_ENUMS(name, base_reg) \
395 static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
396 static WM5100_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
397 static WM5100_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
398 static WM5100_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
399 static WM5100_MUX_CTL_DECL(name##_in1); \
400 static WM5100_MUX_CTL_DECL(name##_in2); \
401 static WM5100_MUX_CTL_DECL(name##_in3); \
402 static WM5100_MUX_CTL_DECL(name##_in4)
403
404WM5100_MIXER_ENUMS(HPOUT1L, WM5100_OUT1LMIX_INPUT_1_SOURCE);
405WM5100_MIXER_ENUMS(HPOUT1R, WM5100_OUT1RMIX_INPUT_1_SOURCE);
406WM5100_MIXER_ENUMS(HPOUT2L, WM5100_OUT2LMIX_INPUT_1_SOURCE);
407WM5100_MIXER_ENUMS(HPOUT2R, WM5100_OUT2RMIX_INPUT_1_SOURCE);
408WM5100_MIXER_ENUMS(HPOUT3L, WM5100_OUT3LMIX_INPUT_1_SOURCE);
409WM5100_MIXER_ENUMS(HPOUT3R, WM5100_OUT3RMIX_INPUT_1_SOURCE);
410
411WM5100_MIXER_ENUMS(SPKOUTL, WM5100_OUT4LMIX_INPUT_1_SOURCE);
412WM5100_MIXER_ENUMS(SPKOUTR, WM5100_OUT4RMIX_INPUT_1_SOURCE);
413WM5100_MIXER_ENUMS(SPKDAT1L, WM5100_OUT5LMIX_INPUT_1_SOURCE);
414WM5100_MIXER_ENUMS(SPKDAT1R, WM5100_OUT5RMIX_INPUT_1_SOURCE);
415WM5100_MIXER_ENUMS(SPKDAT2L, WM5100_OUT6LMIX_INPUT_1_SOURCE);
416WM5100_MIXER_ENUMS(SPKDAT2R, WM5100_OUT6RMIX_INPUT_1_SOURCE);
417
418WM5100_MIXER_ENUMS(PWM1, WM5100_PWM1MIX_INPUT_1_SOURCE);
419WM5100_MIXER_ENUMS(PWM2, WM5100_PWM1MIX_INPUT_1_SOURCE);
420
421WM5100_MIXER_ENUMS(AIF1TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
422WM5100_MIXER_ENUMS(AIF1TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
423WM5100_MIXER_ENUMS(AIF1TX3, WM5100_AIF1TX3MIX_INPUT_1_SOURCE);
424WM5100_MIXER_ENUMS(AIF1TX4, WM5100_AIF1TX4MIX_INPUT_1_SOURCE);
425WM5100_MIXER_ENUMS(AIF1TX5, WM5100_AIF1TX5MIX_INPUT_1_SOURCE);
426WM5100_MIXER_ENUMS(AIF1TX6, WM5100_AIF1TX6MIX_INPUT_1_SOURCE);
427WM5100_MIXER_ENUMS(AIF1TX7, WM5100_AIF1TX7MIX_INPUT_1_SOURCE);
428WM5100_MIXER_ENUMS(AIF1TX8, WM5100_AIF1TX8MIX_INPUT_1_SOURCE);
429
430WM5100_MIXER_ENUMS(AIF2TX1, WM5100_AIF2TX1MIX_INPUT_1_SOURCE);
431WM5100_MIXER_ENUMS(AIF2TX2, WM5100_AIF2TX2MIX_INPUT_1_SOURCE);
432
433WM5100_MIXER_ENUMS(AIF3TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
434WM5100_MIXER_ENUMS(AIF3TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
435
436WM5100_MIXER_ENUMS(EQ1, WM5100_EQ1MIX_INPUT_1_SOURCE);
437WM5100_MIXER_ENUMS(EQ2, WM5100_EQ2MIX_INPUT_1_SOURCE);
438WM5100_MIXER_ENUMS(EQ3, WM5100_EQ3MIX_INPUT_1_SOURCE);
439WM5100_MIXER_ENUMS(EQ4, WM5100_EQ4MIX_INPUT_1_SOURCE);
440
441WM5100_MIXER_ENUMS(DRC1L, WM5100_DRC1LMIX_INPUT_1_SOURCE);
442WM5100_MIXER_ENUMS(DRC1R, WM5100_DRC1RMIX_INPUT_1_SOURCE);
443
444WM5100_MIXER_ENUMS(LHPF1, WM5100_HPLP1MIX_INPUT_1_SOURCE);
445WM5100_MIXER_ENUMS(LHPF2, WM5100_HPLP2MIX_INPUT_1_SOURCE);
446WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE);
447WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE);
448
449#define WM5100_MUX(name, ctrl) \
450 SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
451
452#define WM5100_MIXER_WIDGETS(name, name_str) \
453 WM5100_MUX(name_str " Input 1", &name##_in1_mux), \
454 WM5100_MUX(name_str " Input 2", &name##_in2_mux), \
455 WM5100_MUX(name_str " Input 3", &name##_in3_mux), \
456 WM5100_MUX(name_str " Input 4", &name##_in4_mux), \
457 SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
458
459#define WM5100_MIXER_INPUT_ROUTES(name) \
460 { name, "Tone Generator 1", "Tone Generator 1" }, \
461 { name, "Tone Generator 2", "Tone Generator 2" }, \
462 { name, "IN1L", "IN1L PGA" }, \
463 { name, "IN1R", "IN1R PGA" }, \
464 { name, "IN2L", "IN2L PGA" }, \
465 { name, "IN2R", "IN2R PGA" }, \
466 { name, "IN3L", "IN3L PGA" }, \
467 { name, "IN3R", "IN3R PGA" }, \
468 { name, "IN4L", "IN4L PGA" }, \
469 { name, "IN4R", "IN4R PGA" }, \
470 { name, "AIF1RX1", "AIF1RX1" }, \
471 { name, "AIF1RX2", "AIF1RX2" }, \
472 { name, "AIF1RX3", "AIF1RX3" }, \
473 { name, "AIF1RX4", "AIF1RX4" }, \
474 { name, "AIF1RX5", "AIF1RX5" }, \
475 { name, "AIF1RX6", "AIF1RX6" }, \
476 { name, "AIF1RX7", "AIF1RX7" }, \
477 { name, "AIF1RX8", "AIF1RX8" }, \
478 { name, "AIF2RX1", "AIF2RX1" }, \
479 { name, "AIF2RX2", "AIF2RX2" }, \
480 { name, "AIF3RX1", "AIF3RX1" }, \
481 { name, "AIF3RX2", "AIF3RX2" }, \
482 { name, "EQ1", "EQ1" }, \
483 { name, "EQ2", "EQ2" }, \
484 { name, "EQ3", "EQ3" }, \
485 { name, "EQ4", "EQ4" }, \
486 { name, "DRC1L", "DRC1L" }, \
487 { name, "DRC1R", "DRC1R" }, \
488 { name, "LHPF1", "LHPF1" }, \
489 { name, "LHPF2", "LHPF2" }, \
490 { name, "LHPF3", "LHPF3" }, \
491 { name, "LHPF4", "LHPF4" }
492
493#define WM5100_MIXER_ROUTES(widget, name) \
494 { widget, NULL, name " Mixer" }, \
495 { name " Mixer", NULL, name " Input 1" }, \
496 { name " Mixer", NULL, name " Input 2" }, \
497 { name " Mixer", NULL, name " Input 3" }, \
498 { name " Mixer", NULL, name " Input 4" }, \
499 WM5100_MIXER_INPUT_ROUTES(name " Input 1"), \
500 WM5100_MIXER_INPUT_ROUTES(name " Input 2"), \
501 WM5100_MIXER_INPUT_ROUTES(name " Input 3"), \
502 WM5100_MIXER_INPUT_ROUTES(name " Input 4")
503
504static const char *wm5100_lhpf_mode_text[] = {
505 "Low-pass", "High-pass"
506};
507
508static const struct soc_enum wm5100_lhpf1_mode =
509 SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2,
510 wm5100_lhpf_mode_text);
511
512static const struct soc_enum wm5100_lhpf2_mode =
513 SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2,
514 wm5100_lhpf_mode_text);
515
516static const struct soc_enum wm5100_lhpf3_mode =
517 SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2,
518 wm5100_lhpf_mode_text);
519
520static const struct soc_enum wm5100_lhpf4_mode =
521 SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2,
522 wm5100_lhpf_mode_text);
523
524static const struct snd_kcontrol_new wm5100_snd_controls[] = {
525SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL,
526 WM5100_IN1_OSR_SHIFT, 1, 0),
527SOC_SINGLE("IN2 High Performance Switch", WM5100_IN2L_CONTROL,
528 WM5100_IN2_OSR_SHIFT, 1, 0),
529SOC_SINGLE("IN3 High Performance Switch", WM5100_IN3L_CONTROL,
530 WM5100_IN3_OSR_SHIFT, 1, 0),
531SOC_SINGLE("IN4 High Performance Switch", WM5100_IN4L_CONTROL,
532 WM5100_IN4_OSR_SHIFT, 1, 0),
533
534/* Only applicable for analogue inputs */
535SOC_DOUBLE_R_TLV("IN1 Volume", WM5100_IN1L_CONTROL, WM5100_IN1R_CONTROL,
536 WM5100_IN1L_PGA_VOL_SHIFT, 94, 0, in_tlv),
537SOC_DOUBLE_R_TLV("IN2 Volume", WM5100_IN2L_CONTROL, WM5100_IN2R_CONTROL,
538 WM5100_IN2L_PGA_VOL_SHIFT, 94, 0, in_tlv),
539SOC_DOUBLE_R_TLV("IN3 Volume", WM5100_IN3L_CONTROL, WM5100_IN3R_CONTROL,
540 WM5100_IN3L_PGA_VOL_SHIFT, 94, 0, in_tlv),
541SOC_DOUBLE_R_TLV("IN4 Volume", WM5100_IN4L_CONTROL, WM5100_IN4R_CONTROL,
542 WM5100_IN4L_PGA_VOL_SHIFT, 94, 0, in_tlv),
543
544SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_1L,
545 WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_VOL_SHIFT, 191,
546 0, digital_tlv),
547SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_2L,
548 WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_VOL_SHIFT, 191,
549 0, digital_tlv),
550SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_3L,
551 WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_VOL_SHIFT, 191,
552 0, digital_tlv),
553SOC_DOUBLE_R_TLV("IN4 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_4L,
554 WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_VOL_SHIFT, 191,
555 0, digital_tlv),
556
557SOC_DOUBLE_R("IN1 Switch", WM5100_ADC_DIGITAL_VOLUME_1L,
558 WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_MUTE_SHIFT, 1, 1),
559SOC_DOUBLE_R("IN2 Switch", WM5100_ADC_DIGITAL_VOLUME_2L,
560 WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_MUTE_SHIFT, 1, 1),
561SOC_DOUBLE_R("IN3 Switch", WM5100_ADC_DIGITAL_VOLUME_3L,
562 WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_MUTE_SHIFT, 1, 1),
563SOC_DOUBLE_R("IN4 Switch", WM5100_ADC_DIGITAL_VOLUME_4L,
564 WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_MUTE_SHIFT, 1, 1),
565
566SOC_SINGLE("HPOUT1 High Performance Switch", WM5100_OUT_VOLUME_1L,
567 WM5100_OUT1_OSR_SHIFT, 1, 0),
568SOC_SINGLE("HPOUT2 High Performance Switch", WM5100_OUT_VOLUME_2L,
569 WM5100_OUT2_OSR_SHIFT, 1, 0),
570SOC_SINGLE("HPOUT3 High Performance Switch", WM5100_OUT_VOLUME_3L,
571 WM5100_OUT3_OSR_SHIFT, 1, 0),
572SOC_SINGLE("SPKOUT High Performance Switch", WM5100_OUT_VOLUME_4L,
573 WM5100_OUT4_OSR_SHIFT, 1, 0),
574SOC_SINGLE("SPKDAT1 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_5L,
575 WM5100_OUT5_OSR_SHIFT, 1, 0),
576SOC_SINGLE("SPKDAT2 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_6L,
577 WM5100_OUT6_OSR_SHIFT, 1, 0),
578
579SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_1L,
580 WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_VOL_SHIFT, 159, 0,
581 digital_tlv),
582SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_2L,
583 WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_VOL_SHIFT, 159, 0,
584 digital_tlv),
585SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_3L,
586 WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_VOL_SHIFT, 159, 0,
587 digital_tlv),
588SOC_DOUBLE_R_TLV("SPKOUT Digital Volume", WM5100_DAC_DIGITAL_VOLUME_4L,
589 WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_VOL_SHIFT, 159, 0,
590 digital_tlv),
591SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_5L,
592 WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_VOL_SHIFT, 159, 0,
593 digital_tlv),
594SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_6L,
595 WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_VOL_SHIFT, 159, 0,
596 digital_tlv),
597
598SOC_DOUBLE_R("HPOUT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_1L,
599 WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_MUTE_SHIFT, 1, 1),
600SOC_DOUBLE_R("HPOUT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_2L,
601 WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_MUTE_SHIFT, 1, 1),
602SOC_DOUBLE_R("HPOUT3 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_3L,
603 WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_MUTE_SHIFT, 1, 1),
604SOC_DOUBLE_R("SPKOUT Digital Switch", WM5100_DAC_DIGITAL_VOLUME_4L,
605 WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_MUTE_SHIFT, 1, 1),
606SOC_DOUBLE_R("SPKDAT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_5L,
607 WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_MUTE_SHIFT, 1, 1),
608SOC_DOUBLE_R("SPKDAT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_6L,
609 WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_MUTE_SHIFT, 1, 1),
610
611/* FIXME: Only valid from -12dB to 0dB (52-64) */
612SOC_DOUBLE_R_TLV("HPOUT1 Volume", WM5100_OUT_VOLUME_1L, WM5100_OUT_VOLUME_1R,
613 WM5100_OUT1L_PGA_VOL_SHIFT, 64, 0, out_tlv),
614SOC_DOUBLE_R_TLV("HPOUT2 Volume", WM5100_OUT_VOLUME_2L, WM5100_OUT_VOLUME_2R,
615 WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
616SOC_DOUBLE_R_TLV("HPOUT3 Volume", WM5100_OUT_VOLUME_3L, WM5100_OUT_VOLUME_3R,
617 WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
618
619SOC_DOUBLE("SPKDAT1 Switch", WM5100_PDM_SPK1_CTRL_1, WM5100_SPK1L_MUTE_SHIFT,
620 WM5100_SPK1R_MUTE_SHIFT, 1, 1),
621SOC_DOUBLE("SPKDAT2 Switch", WM5100_PDM_SPK2_CTRL_1, WM5100_SPK2L_MUTE_SHIFT,
622 WM5100_SPK2R_MUTE_SHIFT, 1, 1),
623
624SOC_SINGLE_TLV("EQ1 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ1_B1_GAIN_SHIFT,
625 24, 0, eq_tlv),
626SOC_SINGLE_TLV("EQ1 Band 2 Volume", WM5100_EQ1_1, WM5100_EQ1_B2_GAIN_SHIFT,
627 24, 0, eq_tlv),
628SOC_SINGLE_TLV("EQ1 Band 3 Volume", WM5100_EQ1_1, WM5100_EQ1_B3_GAIN_SHIFT,
629 24, 0, eq_tlv),
630SOC_SINGLE_TLV("EQ1 Band 4 Volume", WM5100_EQ1_2, WM5100_EQ1_B4_GAIN_SHIFT,
631 24, 0, eq_tlv),
632SOC_SINGLE_TLV("EQ1 Band 5 Volume", WM5100_EQ1_2, WM5100_EQ1_B5_GAIN_SHIFT,
633 24, 0, eq_tlv),
634
635SOC_SINGLE_TLV("EQ2 Band 1 Volume", WM5100_EQ2_1, WM5100_EQ2_B1_GAIN_SHIFT,
636 24, 0, eq_tlv),
637SOC_SINGLE_TLV("EQ2 Band 2 Volume", WM5100_EQ2_1, WM5100_EQ2_B2_GAIN_SHIFT,
638 24, 0, eq_tlv),
639SOC_SINGLE_TLV("EQ2 Band 3 Volume", WM5100_EQ2_1, WM5100_EQ2_B3_GAIN_SHIFT,
640 24, 0, eq_tlv),
641SOC_SINGLE_TLV("EQ2 Band 4 Volume", WM5100_EQ2_2, WM5100_EQ2_B4_GAIN_SHIFT,
642 24, 0, eq_tlv),
643SOC_SINGLE_TLV("EQ2 Band 5 Volume", WM5100_EQ2_2, WM5100_EQ2_B5_GAIN_SHIFT,
644 24, 0, eq_tlv),
645
646SOC_SINGLE_TLV("EQ3 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ3_B1_GAIN_SHIFT,
647 24, 0, eq_tlv),
648SOC_SINGLE_TLV("EQ3 Band 2 Volume", WM5100_EQ3_1, WM5100_EQ3_B2_GAIN_SHIFT,
649 24, 0, eq_tlv),
650SOC_SINGLE_TLV("EQ3 Band 3 Volume", WM5100_EQ3_1, WM5100_EQ3_B3_GAIN_SHIFT,
651 24, 0, eq_tlv),
652SOC_SINGLE_TLV("EQ3 Band 4 Volume", WM5100_EQ3_2, WM5100_EQ3_B4_GAIN_SHIFT,
653 24, 0, eq_tlv),
654SOC_SINGLE_TLV("EQ3 Band 5 Volume", WM5100_EQ3_2, WM5100_EQ3_B5_GAIN_SHIFT,
655 24, 0, eq_tlv),
656
657SOC_SINGLE_TLV("EQ4 Band 1 Volume", WM5100_EQ4_1, WM5100_EQ4_B1_GAIN_SHIFT,
658 24, 0, eq_tlv),
659SOC_SINGLE_TLV("EQ4 Band 2 Volume", WM5100_EQ4_1, WM5100_EQ4_B2_GAIN_SHIFT,
660 24, 0, eq_tlv),
661SOC_SINGLE_TLV("EQ4 Band 3 Volume", WM5100_EQ4_1, WM5100_EQ4_B3_GAIN_SHIFT,
662 24, 0, eq_tlv),
663SOC_SINGLE_TLV("EQ4 Band 4 Volume", WM5100_EQ4_2, WM5100_EQ4_B4_GAIN_SHIFT,
664 24, 0, eq_tlv),
665SOC_SINGLE_TLV("EQ4 Band 5 Volume", WM5100_EQ4_2, WM5100_EQ4_B5_GAIN_SHIFT,
666 24, 0, eq_tlv),
667
668SOC_ENUM("LHPF1 Mode", wm5100_lhpf1_mode),
669SOC_ENUM("LHPF2 Mode", wm5100_lhpf2_mode),
670SOC_ENUM("LHPF3 Mode", wm5100_lhpf3_mode),
671SOC_ENUM("LHPF4 Mode", wm5100_lhpf4_mode),
672
673WM5100_MIXER_CONTROLS("HPOUT1L", WM5100_OUT1LMIX_INPUT_1_SOURCE),
674WM5100_MIXER_CONTROLS("HPOUT1R", WM5100_OUT1RMIX_INPUT_1_SOURCE),
675WM5100_MIXER_CONTROLS("HPOUT2L", WM5100_OUT2LMIX_INPUT_1_SOURCE),
676WM5100_MIXER_CONTROLS("HPOUT2R", WM5100_OUT2RMIX_INPUT_1_SOURCE),
677WM5100_MIXER_CONTROLS("HPOUT3L", WM5100_OUT3LMIX_INPUT_1_SOURCE),
678WM5100_MIXER_CONTROLS("HPOUT3R", WM5100_OUT3RMIX_INPUT_1_SOURCE),
679
680WM5100_MIXER_CONTROLS("SPKOUTL", WM5100_OUT4LMIX_INPUT_1_SOURCE),
681WM5100_MIXER_CONTROLS("SPKOUTR", WM5100_OUT4RMIX_INPUT_1_SOURCE),
682WM5100_MIXER_CONTROLS("SPKDAT1L", WM5100_OUT5LMIX_INPUT_1_SOURCE),
683WM5100_MIXER_CONTROLS("SPKDAT1R", WM5100_OUT5RMIX_INPUT_1_SOURCE),
684WM5100_MIXER_CONTROLS("SPKDAT2L", WM5100_OUT6LMIX_INPUT_1_SOURCE),
685WM5100_MIXER_CONTROLS("SPKDAT2R", WM5100_OUT6RMIX_INPUT_1_SOURCE),
686
687WM5100_MIXER_CONTROLS("PWM1", WM5100_PWM1MIX_INPUT_1_SOURCE),
688WM5100_MIXER_CONTROLS("PWM2", WM5100_PWM2MIX_INPUT_1_SOURCE),
689
690WM5100_MIXER_CONTROLS("AIF1TX1", WM5100_AIF1TX1MIX_INPUT_1_SOURCE),
691WM5100_MIXER_CONTROLS("AIF1TX2", WM5100_AIF1TX2MIX_INPUT_1_SOURCE),
692WM5100_MIXER_CONTROLS("AIF1TX3", WM5100_AIF1TX3MIX_INPUT_1_SOURCE),
693WM5100_MIXER_CONTROLS("AIF1TX4", WM5100_AIF1TX4MIX_INPUT_1_SOURCE),
694WM5100_MIXER_CONTROLS("AIF1TX5", WM5100_AIF1TX5MIX_INPUT_1_SOURCE),
695WM5100_MIXER_CONTROLS("AIF1TX6", WM5100_AIF1TX6MIX_INPUT_1_SOURCE),
696WM5100_MIXER_CONTROLS("AIF1TX7", WM5100_AIF1TX7MIX_INPUT_1_SOURCE),
697WM5100_MIXER_CONTROLS("AIF1TX8", WM5100_AIF1TX8MIX_INPUT_1_SOURCE),
698
699WM5100_MIXER_CONTROLS("AIF2TX1", WM5100_AIF2TX1MIX_INPUT_1_SOURCE),
700WM5100_MIXER_CONTROLS("AIF2TX2", WM5100_AIF2TX2MIX_INPUT_1_SOURCE),
701
702WM5100_MIXER_CONTROLS("AIF3TX1", WM5100_AIF3TX1MIX_INPUT_1_SOURCE),
703WM5100_MIXER_CONTROLS("AIF3TX2", WM5100_AIF3TX2MIX_INPUT_1_SOURCE),
704
705WM5100_MIXER_CONTROLS("EQ1", WM5100_EQ1MIX_INPUT_1_SOURCE),
706WM5100_MIXER_CONTROLS("EQ2", WM5100_EQ2MIX_INPUT_1_SOURCE),
707WM5100_MIXER_CONTROLS("EQ3", WM5100_EQ3MIX_INPUT_1_SOURCE),
708WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
709
710WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
711WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
712
713WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
714WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
715WM5100_MIXER_CONTROLS("LHPF3", WM5100_HPLP3MIX_INPUT_1_SOURCE),
716WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE),
717};
718
719static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm,
720 enum snd_soc_dapm_type event, int subseq)
721{
722 struct snd_soc_codec *codec = container_of(dapm,
723 struct snd_soc_codec, dapm);
724 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
725 u16 val, expect, i;
726
727 /* Wait for the outputs to flag themselves as enabled */
728 if (wm5100->out_ena[0]) {
729 expect = snd_soc_read(codec, WM5100_CHANNEL_ENABLES_1);
730 for (i = 0; i < 200; i++) {
731 val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_1);
732 if (val == expect) {
733 wm5100->out_ena[0] = false;
734 break;
735 }
736 }
737 if (i == 200) {
738 dev_err(codec->dev, "Timeout waiting for OUTPUT1 %x\n",
739 expect);
740 }
741 }
742
743 if (wm5100->out_ena[1]) {
744 expect = snd_soc_read(codec, WM5100_OUTPUT_ENABLES_2);
745 for (i = 0; i < 200; i++) {
746 val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_2);
747 if (val == expect) {
748 wm5100->out_ena[1] = false;
749 break;
750 }
751 }
752 if (i == 200) {
753 dev_err(codec->dev, "Timeout waiting for OUTPUT2 %x\n",
754 expect);
755 }
756 }
757}
758
759static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
760 struct snd_kcontrol *kcontrol,
761 int event)
762{
763 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec);
764
765 switch (w->reg) {
766 case WM5100_CHANNEL_ENABLES_1:
767 wm5100->out_ena[0] = true;
768 break;
769 case WM5100_OUTPUT_ENABLES_2:
770 wm5100->out_ena[0] = true;
771 break;
772 default:
773 break;
774 }
775
776 return 0;
777}
778
Mark Brown46c1a872012-01-18 14:53:08 +0000779static void wm5100_log_status3(struct wm5100_priv *wm5100, int val)
Mark Brown6d4baf02011-09-20 15:44:21 +0100780{
781 if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000782 dev_crit(wm5100->dev, "Speaker shutdown warning\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100783 if (val & WM5100_SPK_SHUTDOWN_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000784 dev_crit(wm5100->dev, "Speaker shutdown\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100785 if (val & WM5100_CLKGEN_ERR_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000786 dev_crit(wm5100->dev, "SYSCLK underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100787 if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000788 dev_crit(wm5100->dev, "ASYNCCLK underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100789}
790
Mark Brown46c1a872012-01-18 14:53:08 +0000791static void wm5100_log_status4(struct wm5100_priv *wm5100, int val)
Mark Brown6d4baf02011-09-20 15:44:21 +0100792{
793 if (val & WM5100_AIF3_ERR_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000794 dev_err(wm5100->dev, "AIF3 configuration error\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100795 if (val & WM5100_AIF2_ERR_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000796 dev_err(wm5100->dev, "AIF2 configuration error\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100797 if (val & WM5100_AIF1_ERR_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000798 dev_err(wm5100->dev, "AIF1 configuration error\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100799 if (val & WM5100_CTRLIF_ERR_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000800 dev_err(wm5100->dev, "Control interface error\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100801 if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000802 dev_err(wm5100->dev, "ISRC2 underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100803 if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000804 dev_err(wm5100->dev, "ISRC1 underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100805 if (val & WM5100_FX_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000806 dev_err(wm5100->dev, "FX underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100807 if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000808 dev_err(wm5100->dev, "AIF3 underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100809 if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000810 dev_err(wm5100->dev, "AIF2 underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100811 if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000812 dev_err(wm5100->dev, "AIF1 underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100813 if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000814 dev_err(wm5100->dev, "ASRC underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100815 if (val & WM5100_DAC_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000816 dev_err(wm5100->dev, "DAC underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100817 if (val & WM5100_ADC_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000818 dev_err(wm5100->dev, "ADC underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100819 if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +0000820 dev_err(wm5100->dev, "Mixer underclocked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +0100821}
822
823static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
824 struct snd_kcontrol *kcontrol,
825 int event)
826{
827 struct snd_soc_codec *codec = w->codec;
Mark Brown46c1a872012-01-18 14:53:08 +0000828 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
Mark Brown6d4baf02011-09-20 15:44:21 +0100829 int ret;
830
831 ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
832 ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
833 WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
834 WM5100_CLKGEN_ERR_ASYNC_STS;
Mark Brown46c1a872012-01-18 14:53:08 +0000835 wm5100_log_status3(wm5100, ret);
Mark Brown6d4baf02011-09-20 15:44:21 +0100836
837 ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
Mark Brown46c1a872012-01-18 14:53:08 +0000838 wm5100_log_status4(wm5100, ret);
Mark Brown6d4baf02011-09-20 15:44:21 +0100839
840 return 0;
841}
842
843static const struct snd_soc_dapm_widget wm5100_dapm_widgets[] = {
844SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
845 NULL, 0),
846SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
847 0, NULL, 0),
848
Mark Brown1cf73352012-01-21 22:10:24 +0000849SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
850SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
851SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
852
Mark Brown6d4baf02011-09-20 15:44:21 +0100853SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
Mark Brown1cf73352012-01-21 22:10:24 +0000854 NULL, 0),
Mark Brown6d4baf02011-09-20 15:44:21 +0100855SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
856 NULL, 0),
857SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
Mark Brown1cf73352012-01-21 22:10:24 +0000858 WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0),
Mark Brown6d4baf02011-09-20 15:44:21 +0100859
860SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
861 0, NULL, 0),
862SND_SOC_DAPM_SUPPLY("MICBIAS2", WM5100_MIC_BIAS_CTRL_2, WM5100_MICB2_ENA_SHIFT,
863 0, NULL, 0),
864SND_SOC_DAPM_SUPPLY("MICBIAS3", WM5100_MIC_BIAS_CTRL_3, WM5100_MICB3_ENA_SHIFT,
865 0, NULL, 0),
866
867SND_SOC_DAPM_INPUT("IN1L"),
868SND_SOC_DAPM_INPUT("IN1R"),
869SND_SOC_DAPM_INPUT("IN2L"),
870SND_SOC_DAPM_INPUT("IN2R"),
871SND_SOC_DAPM_INPUT("IN3L"),
872SND_SOC_DAPM_INPUT("IN3R"),
873SND_SOC_DAPM_INPUT("IN4L"),
874SND_SOC_DAPM_INPUT("IN4R"),
Mark Browndea8e232011-11-27 16:24:05 +0000875SND_SOC_DAPM_SIGGEN("TONE"),
Mark Brown6d4baf02011-09-20 15:44:21 +0100876
877SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0,
878 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
879SND_SOC_DAPM_PGA_E("IN1R PGA", WM5100_INPUT_ENABLES, WM5100_IN1R_ENA_SHIFT, 0,
880 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
881SND_SOC_DAPM_PGA_E("IN2L PGA", WM5100_INPUT_ENABLES, WM5100_IN2L_ENA_SHIFT, 0,
882 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
883SND_SOC_DAPM_PGA_E("IN2R PGA", WM5100_INPUT_ENABLES, WM5100_IN2R_ENA_SHIFT, 0,
884 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
885SND_SOC_DAPM_PGA_E("IN3L PGA", WM5100_INPUT_ENABLES, WM5100_IN3L_ENA_SHIFT, 0,
886 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
887SND_SOC_DAPM_PGA_E("IN3R PGA", WM5100_INPUT_ENABLES, WM5100_IN3R_ENA_SHIFT, 0,
888 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
889SND_SOC_DAPM_PGA_E("IN4L PGA", WM5100_INPUT_ENABLES, WM5100_IN4L_ENA_SHIFT, 0,
890 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
891SND_SOC_DAPM_PGA_E("IN4R PGA", WM5100_INPUT_ENABLES, WM5100_IN4R_ENA_SHIFT, 0,
892 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
893
894SND_SOC_DAPM_PGA("Tone Generator 1", WM5100_TONE_GENERATOR_1,
895 WM5100_TONE1_ENA_SHIFT, 0, NULL, 0),
896SND_SOC_DAPM_PGA("Tone Generator 2", WM5100_TONE_GENERATOR_1,
897 WM5100_TONE2_ENA_SHIFT, 0, NULL, 0),
898
899SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 0,
900 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX1_ENA_SHIFT, 0),
901SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 1,
902 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX2_ENA_SHIFT, 0),
903SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 2,
904 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX3_ENA_SHIFT, 0),
905SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 3,
906 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX4_ENA_SHIFT, 0),
907SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 4,
908 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX5_ENA_SHIFT, 0),
909SND_SOC_DAPM_AIF_IN("AIF1RX6", "AIF1 Playback", 5,
910 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX6_ENA_SHIFT, 0),
911SND_SOC_DAPM_AIF_IN("AIF1RX7", "AIF1 Playback", 6,
912 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX7_ENA_SHIFT, 0),
913SND_SOC_DAPM_AIF_IN("AIF1RX8", "AIF1 Playback", 7,
914 WM5100_AUDIO_IF_1_27, WM5100_AIF1RX8_ENA_SHIFT, 0),
915
916SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
917 WM5100_AUDIO_IF_2_27, WM5100_AIF2RX1_ENA_SHIFT, 0),
918SND_SOC_DAPM_AIF_IN("AIF2RX2", "AIF2 Playback", 1,
919 WM5100_AUDIO_IF_2_27, WM5100_AIF2RX2_ENA_SHIFT, 0),
920
921SND_SOC_DAPM_AIF_IN("AIF3RX1", "AIF3 Playback", 0,
922 WM5100_AUDIO_IF_3_27, WM5100_AIF3RX1_ENA_SHIFT, 0),
923SND_SOC_DAPM_AIF_IN("AIF3RX2", "AIF3 Playback", 1,
924 WM5100_AUDIO_IF_3_27, WM5100_AIF3RX2_ENA_SHIFT, 0),
925
926SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 0,
927 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX1_ENA_SHIFT, 0),
928SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 1,
929 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX2_ENA_SHIFT, 0),
930SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 2,
931 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX3_ENA_SHIFT, 0),
932SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 3,
933 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX4_ENA_SHIFT, 0),
934SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 4,
935 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX5_ENA_SHIFT, 0),
936SND_SOC_DAPM_AIF_OUT("AIF1TX6", "AIF1 Capture", 5,
937 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX6_ENA_SHIFT, 0),
938SND_SOC_DAPM_AIF_OUT("AIF1TX7", "AIF1 Capture", 6,
939 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX7_ENA_SHIFT, 0),
940SND_SOC_DAPM_AIF_OUT("AIF1TX8", "AIF1 Capture", 7,
941 WM5100_AUDIO_IF_1_26, WM5100_AIF1TX8_ENA_SHIFT, 0),
942
943SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
944 WM5100_AUDIO_IF_2_26, WM5100_AIF2TX1_ENA_SHIFT, 0),
945SND_SOC_DAPM_AIF_OUT("AIF2TX2", "AIF2 Capture", 1,
946 WM5100_AUDIO_IF_2_26, WM5100_AIF2TX2_ENA_SHIFT, 0),
947
948SND_SOC_DAPM_AIF_OUT("AIF3TX1", "AIF3 Capture", 0,
949 WM5100_AUDIO_IF_3_26, WM5100_AIF3TX1_ENA_SHIFT, 0),
950SND_SOC_DAPM_AIF_OUT("AIF3TX2", "AIF3 Capture", 1,
951 WM5100_AUDIO_IF_3_26, WM5100_AIF3TX2_ENA_SHIFT, 0),
952
953SND_SOC_DAPM_PGA_E("OUT6L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6L_ENA_SHIFT, 0,
954 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
955SND_SOC_DAPM_PGA_E("OUT6R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6R_ENA_SHIFT, 0,
956 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
957SND_SOC_DAPM_PGA_E("OUT5L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5L_ENA_SHIFT, 0,
958 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
959SND_SOC_DAPM_PGA_E("OUT5R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5R_ENA_SHIFT, 0,
960 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
961SND_SOC_DAPM_PGA_E("OUT4L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4L_ENA_SHIFT, 0,
962 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
963SND_SOC_DAPM_PGA_E("OUT4R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4R_ENA_SHIFT, 0,
964 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
965SND_SOC_DAPM_PGA_E("OUT3L", WM5100_CHANNEL_ENABLES_1, WM5100_HP3L_ENA_SHIFT, 0,
966 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
967SND_SOC_DAPM_PGA_E("OUT3R", WM5100_CHANNEL_ENABLES_1, WM5100_HP3R_ENA_SHIFT, 0,
968 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
969SND_SOC_DAPM_PGA_E("OUT2L", WM5100_CHANNEL_ENABLES_1, WM5100_HP2L_ENA_SHIFT, 0,
970 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
971SND_SOC_DAPM_PGA_E("OUT2R", WM5100_CHANNEL_ENABLES_1, WM5100_HP2R_ENA_SHIFT, 0,
972 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
973SND_SOC_DAPM_PGA_E("OUT1L", WM5100_CHANNEL_ENABLES_1, WM5100_HP1L_ENA_SHIFT, 0,
974 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
975SND_SOC_DAPM_PGA_E("OUT1R", WM5100_CHANNEL_ENABLES_1, WM5100_HP1R_ENA_SHIFT, 0,
976 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
977SND_SOC_DAPM_PGA_E("PWM1 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM1_ENA_SHIFT, 0,
978 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
979SND_SOC_DAPM_PGA_E("PWM2 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM2_ENA_SHIFT, 0,
980 NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
981
982SND_SOC_DAPM_PGA("EQ1", WM5100_EQ1_1, WM5100_EQ1_ENA_SHIFT, 0, NULL, 0),
983SND_SOC_DAPM_PGA("EQ2", WM5100_EQ2_1, WM5100_EQ2_ENA_SHIFT, 0, NULL, 0),
984SND_SOC_DAPM_PGA("EQ3", WM5100_EQ3_1, WM5100_EQ3_ENA_SHIFT, 0, NULL, 0),
985SND_SOC_DAPM_PGA("EQ4", WM5100_EQ4_1, WM5100_EQ4_ENA_SHIFT, 0, NULL, 0),
986
987SND_SOC_DAPM_PGA("DRC1L", WM5100_DRC1_CTRL1, WM5100_DRCL_ENA_SHIFT, 0,
988 NULL, 0),
989SND_SOC_DAPM_PGA("DRC1R", WM5100_DRC1_CTRL1, WM5100_DRCR_ENA_SHIFT, 0,
990 NULL, 0),
991
992SND_SOC_DAPM_PGA("LHPF1", WM5100_HPLPF1_1, WM5100_LHPF1_ENA_SHIFT, 0,
993 NULL, 0),
994SND_SOC_DAPM_PGA("LHPF2", WM5100_HPLPF2_1, WM5100_LHPF2_ENA_SHIFT, 0,
995 NULL, 0),
996SND_SOC_DAPM_PGA("LHPF3", WM5100_HPLPF3_1, WM5100_LHPF3_ENA_SHIFT, 0,
997 NULL, 0),
998SND_SOC_DAPM_PGA("LHPF4", WM5100_HPLPF4_1, WM5100_LHPF4_ENA_SHIFT, 0,
999 NULL, 0),
1000
1001WM5100_MIXER_WIDGETS(EQ1, "EQ1"),
1002WM5100_MIXER_WIDGETS(EQ2, "EQ2"),
1003WM5100_MIXER_WIDGETS(EQ3, "EQ3"),
1004WM5100_MIXER_WIDGETS(EQ4, "EQ4"),
1005
1006WM5100_MIXER_WIDGETS(DRC1L, "DRC1L"),
1007WM5100_MIXER_WIDGETS(DRC1R, "DRC1R"),
1008
1009WM5100_MIXER_WIDGETS(LHPF1, "LHPF1"),
1010WM5100_MIXER_WIDGETS(LHPF2, "LHPF2"),
1011WM5100_MIXER_WIDGETS(LHPF3, "LHPF3"),
1012WM5100_MIXER_WIDGETS(LHPF4, "LHPF4"),
1013
1014WM5100_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
1015WM5100_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
1016WM5100_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
1017WM5100_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
1018WM5100_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
1019WM5100_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
1020WM5100_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
1021WM5100_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
1022
1023WM5100_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
1024WM5100_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
1025
1026WM5100_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
1027WM5100_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
1028
1029WM5100_MIXER_WIDGETS(HPOUT1L, "HPOUT1L"),
1030WM5100_MIXER_WIDGETS(HPOUT1R, "HPOUT1R"),
1031WM5100_MIXER_WIDGETS(HPOUT2L, "HPOUT2L"),
1032WM5100_MIXER_WIDGETS(HPOUT2R, "HPOUT2R"),
1033WM5100_MIXER_WIDGETS(HPOUT3L, "HPOUT3L"),
1034WM5100_MIXER_WIDGETS(HPOUT3R, "HPOUT3R"),
1035
1036WM5100_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
1037WM5100_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
1038WM5100_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
1039WM5100_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
1040WM5100_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
1041WM5100_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
1042
1043WM5100_MIXER_WIDGETS(PWM1, "PWM1"),
1044WM5100_MIXER_WIDGETS(PWM2, "PWM2"),
1045
1046SND_SOC_DAPM_OUTPUT("HPOUT1L"),
1047SND_SOC_DAPM_OUTPUT("HPOUT1R"),
1048SND_SOC_DAPM_OUTPUT("HPOUT2L"),
1049SND_SOC_DAPM_OUTPUT("HPOUT2R"),
1050SND_SOC_DAPM_OUTPUT("HPOUT3L"),
1051SND_SOC_DAPM_OUTPUT("HPOUT3R"),
1052SND_SOC_DAPM_OUTPUT("SPKOUTL"),
1053SND_SOC_DAPM_OUTPUT("SPKOUTR"),
1054SND_SOC_DAPM_OUTPUT("SPKDAT1"),
1055SND_SOC_DAPM_OUTPUT("SPKDAT2"),
1056SND_SOC_DAPM_OUTPUT("PWM1"),
1057SND_SOC_DAPM_OUTPUT("PWM2"),
1058};
1059
1060/* We register a _POST event if we don't have IRQ support so we can
1061 * look at the error status from the CODEC - if we've got the IRQ
1062 * hooked up then we will get prompted to look by an interrupt.
1063 */
1064static const struct snd_soc_dapm_widget wm5100_dapm_widgets_noirq[] = {
1065SND_SOC_DAPM_POST("Post", wm5100_post_ev),
1066};
1067
1068static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
Mark Brown1cf73352012-01-21 22:10:24 +00001069 { "CP1", NULL, "CPVDD" },
1070 { "CP2 Active", NULL, "CPVDD" },
1071
Mark Brown6d4baf02011-09-20 15:44:21 +01001072 { "IN1L", NULL, "SYSCLK" },
1073 { "IN1R", NULL, "SYSCLK" },
1074 { "IN2L", NULL, "SYSCLK" },
1075 { "IN2R", NULL, "SYSCLK" },
1076 { "IN3L", NULL, "SYSCLK" },
1077 { "IN3R", NULL, "SYSCLK" },
1078 { "IN4L", NULL, "SYSCLK" },
1079 { "IN4R", NULL, "SYSCLK" },
1080
1081 { "OUT1L", NULL, "SYSCLK" },
1082 { "OUT1R", NULL, "SYSCLK" },
1083 { "OUT2L", NULL, "SYSCLK" },
1084 { "OUT2R", NULL, "SYSCLK" },
1085 { "OUT3L", NULL, "SYSCLK" },
1086 { "OUT3R", NULL, "SYSCLK" },
1087 { "OUT4L", NULL, "SYSCLK" },
1088 { "OUT4R", NULL, "SYSCLK" },
1089 { "OUT5L", NULL, "SYSCLK" },
1090 { "OUT5R", NULL, "SYSCLK" },
1091 { "OUT6L", NULL, "SYSCLK" },
1092 { "OUT6R", NULL, "SYSCLK" },
1093
1094 { "AIF1RX1", NULL, "SYSCLK" },
1095 { "AIF1RX2", NULL, "SYSCLK" },
1096 { "AIF1RX3", NULL, "SYSCLK" },
1097 { "AIF1RX4", NULL, "SYSCLK" },
1098 { "AIF1RX5", NULL, "SYSCLK" },
1099 { "AIF1RX6", NULL, "SYSCLK" },
1100 { "AIF1RX7", NULL, "SYSCLK" },
1101 { "AIF1RX8", NULL, "SYSCLK" },
1102
1103 { "AIF2RX1", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001104 { "AIF2RX1", NULL, "DBVDD2" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001105 { "AIF2RX2", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001106 { "AIF2RX2", NULL, "DBVDD2" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001107
1108 { "AIF3RX1", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001109 { "AIF3RX1", NULL, "DBVDD3" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001110 { "AIF3RX2", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001111 { "AIF3RX2", NULL, "DBVDD3" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001112
1113 { "AIF1TX1", NULL, "SYSCLK" },
1114 { "AIF1TX2", NULL, "SYSCLK" },
1115 { "AIF1TX3", NULL, "SYSCLK" },
1116 { "AIF1TX4", NULL, "SYSCLK" },
1117 { "AIF1TX5", NULL, "SYSCLK" },
1118 { "AIF1TX6", NULL, "SYSCLK" },
1119 { "AIF1TX7", NULL, "SYSCLK" },
1120 { "AIF1TX8", NULL, "SYSCLK" },
1121
1122 { "AIF2TX1", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001123 { "AIF2TX1", NULL, "DBVDD2" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001124 { "AIF2TX2", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001125 { "AIF2TX2", NULL, "DBVDD2" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001126
1127 { "AIF3TX1", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001128 { "AIF3TX1", NULL, "DBVDD3" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001129 { "AIF3TX2", NULL, "SYSCLK" },
Mark Brown7aefb082011-09-21 17:59:02 +01001130 { "AIF3TX2", NULL, "DBVDD3" },
Mark Brown6d4baf02011-09-20 15:44:21 +01001131
1132 { "MICBIAS1", NULL, "CP2" },
1133 { "MICBIAS2", NULL, "CP2" },
1134 { "MICBIAS3", NULL, "CP2" },
1135
1136 { "IN1L PGA", NULL, "CP2" },
1137 { "IN1R PGA", NULL, "CP2" },
1138 { "IN2L PGA", NULL, "CP2" },
1139 { "IN2R PGA", NULL, "CP2" },
1140 { "IN3L PGA", NULL, "CP2" },
1141 { "IN3R PGA", NULL, "CP2" },
1142 { "IN4L PGA", NULL, "CP2" },
1143 { "IN4R PGA", NULL, "CP2" },
1144
1145 { "IN1L PGA", NULL, "CP2 Active" },
1146 { "IN1R PGA", NULL, "CP2 Active" },
1147 { "IN2L PGA", NULL, "CP2 Active" },
1148 { "IN2R PGA", NULL, "CP2 Active" },
1149 { "IN3L PGA", NULL, "CP2 Active" },
1150 { "IN3R PGA", NULL, "CP2 Active" },
1151 { "IN4L PGA", NULL, "CP2 Active" },
1152 { "IN4R PGA", NULL, "CP2 Active" },
1153
1154 { "OUT1L", NULL, "CP1" },
1155 { "OUT1R", NULL, "CP1" },
1156 { "OUT2L", NULL, "CP1" },
1157 { "OUT2R", NULL, "CP1" },
1158 { "OUT3L", NULL, "CP1" },
1159 { "OUT3R", NULL, "CP1" },
1160
1161 { "Tone Generator 1", NULL, "TONE" },
1162 { "Tone Generator 2", NULL, "TONE" },
1163
1164 { "IN1L PGA", NULL, "IN1L" },
1165 { "IN1R PGA", NULL, "IN1R" },
1166 { "IN2L PGA", NULL, "IN2L" },
1167 { "IN2R PGA", NULL, "IN2R" },
1168 { "IN3L PGA", NULL, "IN3L" },
1169 { "IN3R PGA", NULL, "IN3R" },
1170 { "IN4L PGA", NULL, "IN4L" },
1171 { "IN4R PGA", NULL, "IN4R" },
1172
1173 WM5100_MIXER_ROUTES("OUT1L", "HPOUT1L"),
1174 WM5100_MIXER_ROUTES("OUT1R", "HPOUT1R"),
1175 WM5100_MIXER_ROUTES("OUT2L", "HPOUT2L"),
1176 WM5100_MIXER_ROUTES("OUT2R", "HPOUT2R"),
1177 WM5100_MIXER_ROUTES("OUT3L", "HPOUT3L"),
1178 WM5100_MIXER_ROUTES("OUT3R", "HPOUT3R"),
1179
1180 WM5100_MIXER_ROUTES("OUT4L", "SPKOUTL"),
1181 WM5100_MIXER_ROUTES("OUT4R", "SPKOUTR"),
1182 WM5100_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
1183 WM5100_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
1184 WM5100_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
1185 WM5100_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
1186
1187 WM5100_MIXER_ROUTES("PWM1 Driver", "PWM1"),
1188 WM5100_MIXER_ROUTES("PWM2 Driver", "PWM2"),
1189
1190 WM5100_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
1191 WM5100_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
1192 WM5100_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
1193 WM5100_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
1194 WM5100_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
1195 WM5100_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
1196 WM5100_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
1197 WM5100_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
1198
1199 WM5100_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
1200 WM5100_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
1201
1202 WM5100_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
1203 WM5100_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
1204
1205 WM5100_MIXER_ROUTES("EQ1", "EQ1"),
1206 WM5100_MIXER_ROUTES("EQ2", "EQ2"),
1207 WM5100_MIXER_ROUTES("EQ3", "EQ3"),
1208 WM5100_MIXER_ROUTES("EQ4", "EQ4"),
1209
1210 WM5100_MIXER_ROUTES("DRC1L", "DRC1L"),
1211 WM5100_MIXER_ROUTES("DRC1R", "DRC1R"),
1212
1213 WM5100_MIXER_ROUTES("LHPF1", "LHPF1"),
1214 WM5100_MIXER_ROUTES("LHPF2", "LHPF2"),
1215 WM5100_MIXER_ROUTES("LHPF3", "LHPF3"),
1216 WM5100_MIXER_ROUTES("LHPF4", "LHPF4"),
1217
1218 { "HPOUT1L", NULL, "OUT1L" },
1219 { "HPOUT1R", NULL, "OUT1R" },
1220 { "HPOUT2L", NULL, "OUT2L" },
1221 { "HPOUT2R", NULL, "OUT2R" },
1222 { "HPOUT3L", NULL, "OUT3L" },
1223 { "HPOUT3R", NULL, "OUT3R" },
1224 { "SPKOUTL", NULL, "OUT4L" },
1225 { "SPKOUTR", NULL, "OUT4R" },
1226 { "SPKDAT1", NULL, "OUT5L" },
1227 { "SPKDAT1", NULL, "OUT5R" },
1228 { "SPKDAT2", NULL, "OUT6L" },
1229 { "SPKDAT2", NULL, "OUT6R" },
1230 { "PWM1", NULL, "PWM1 Driver" },
1231 { "PWM2", NULL, "PWM2 Driver" },
1232};
1233
Mark Brown15b52f12012-01-21 12:14:53 +00001234static const __devinitdata struct reg_default wm5100_reva_patches[] = {
Mark Brown6d4baf02011-09-20 15:44:21 +01001235 { WM5100_AUDIO_IF_1_10, 0 },
1236 { WM5100_AUDIO_IF_1_11, 1 },
1237 { WM5100_AUDIO_IF_1_12, 2 },
1238 { WM5100_AUDIO_IF_1_13, 3 },
1239 { WM5100_AUDIO_IF_1_14, 4 },
1240 { WM5100_AUDIO_IF_1_15, 5 },
1241 { WM5100_AUDIO_IF_1_16, 6 },
1242 { WM5100_AUDIO_IF_1_17, 7 },
1243
1244 { WM5100_AUDIO_IF_1_18, 0 },
1245 { WM5100_AUDIO_IF_1_19, 1 },
1246 { WM5100_AUDIO_IF_1_20, 2 },
1247 { WM5100_AUDIO_IF_1_21, 3 },
1248 { WM5100_AUDIO_IF_1_22, 4 },
1249 { WM5100_AUDIO_IF_1_23, 5 },
1250 { WM5100_AUDIO_IF_1_24, 6 },
1251 { WM5100_AUDIO_IF_1_25, 7 },
1252
1253 { WM5100_AUDIO_IF_2_10, 0 },
1254 { WM5100_AUDIO_IF_2_11, 1 },
1255
1256 { WM5100_AUDIO_IF_2_18, 0 },
1257 { WM5100_AUDIO_IF_2_19, 1 },
1258
1259 { WM5100_AUDIO_IF_3_10, 0 },
1260 { WM5100_AUDIO_IF_3_11, 1 },
1261
1262 { WM5100_AUDIO_IF_3_18, 0 },
1263 { WM5100_AUDIO_IF_3_19, 1 },
1264};
1265
Mark Brown6d4baf02011-09-20 15:44:21 +01001266static int wm5100_dai_to_base(struct snd_soc_dai *dai)
1267{
1268 switch (dai->id) {
1269 case 0:
1270 return WM5100_AUDIO_IF_1_1 - 1;
1271 case 1:
1272 return WM5100_AUDIO_IF_2_1 - 1;
1273 case 2:
1274 return WM5100_AUDIO_IF_3_1 - 1;
1275 default:
1276 BUG();
1277 return -EINVAL;
1278 }
1279}
1280
1281static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1282{
1283 struct snd_soc_codec *codec = dai->codec;
1284 int lrclk, bclk, mask, base;
1285
1286 base = wm5100_dai_to_base(dai);
1287 if (base < 0)
1288 return base;
1289
1290 lrclk = 0;
1291 bclk = 0;
1292
1293 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1294 case SND_SOC_DAIFMT_DSP_A:
1295 mask = 0;
1296 break;
1297 case SND_SOC_DAIFMT_DSP_B:
1298 mask = 1;
1299 break;
1300 case SND_SOC_DAIFMT_I2S:
1301 mask = 2;
1302 break;
1303 case SND_SOC_DAIFMT_LEFT_J:
1304 mask = 3;
1305 break;
1306 default:
1307 dev_err(codec->dev, "Unsupported DAI format %d\n",
1308 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1309 return -EINVAL;
1310 }
1311
1312 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1313 case SND_SOC_DAIFMT_CBS_CFS:
1314 break;
1315 case SND_SOC_DAIFMT_CBS_CFM:
1316 lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
1317 break;
1318 case SND_SOC_DAIFMT_CBM_CFS:
1319 bclk |= WM5100_AIF1_BCLK_MSTR;
1320 break;
1321 case SND_SOC_DAIFMT_CBM_CFM:
1322 lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
1323 bclk |= WM5100_AIF1_BCLK_MSTR;
1324 break;
1325 default:
1326 dev_err(codec->dev, "Unsupported master mode %d\n",
1327 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1328 return -EINVAL;
1329 }
1330
1331 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1332 case SND_SOC_DAIFMT_NB_NF:
1333 break;
1334 case SND_SOC_DAIFMT_IB_IF:
1335 bclk |= WM5100_AIF1_BCLK_INV;
1336 lrclk |= WM5100_AIF1TX_LRCLK_INV;
1337 break;
1338 case SND_SOC_DAIFMT_IB_NF:
1339 bclk |= WM5100_AIF1_BCLK_INV;
1340 break;
1341 case SND_SOC_DAIFMT_NB_IF:
1342 lrclk |= WM5100_AIF1TX_LRCLK_INV;
1343 break;
1344 default:
1345 return -EINVAL;
1346 }
1347
1348 snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_MSTR |
1349 WM5100_AIF1_BCLK_INV, bclk);
1350 snd_soc_update_bits(codec, base + 2, WM5100_AIF1TX_LRCLK_MSTR |
1351 WM5100_AIF1TX_LRCLK_INV, lrclk);
1352 snd_soc_update_bits(codec, base + 3, WM5100_AIF1TX_LRCLK_MSTR |
1353 WM5100_AIF1TX_LRCLK_INV, lrclk);
1354 snd_soc_update_bits(codec, base + 5, WM5100_AIF1_FMT_MASK, mask);
1355
1356 return 0;
1357}
1358
1359#define WM5100_NUM_BCLK_RATES 19
1360
1361static int wm5100_bclk_rates_dat[WM5100_NUM_BCLK_RATES] = {
1362 32000,
1363 48000,
1364 64000,
1365 96000,
1366 128000,
1367 192000,
Mark Brownd73ec752011-09-22 17:48:01 +01001368 256000,
Mark Brown6d4baf02011-09-20 15:44:21 +01001369 384000,
1370 512000,
1371 768000,
1372 1024000,
1373 1536000,
1374 2048000,
1375 3072000,
1376 4096000,
1377 6144000,
1378 8192000,
1379 12288000,
1380 24576000,
1381};
1382
1383static int wm5100_bclk_rates_cd[WM5100_NUM_BCLK_RATES] = {
1384 29400,
1385 44100,
1386 58800,
1387 88200,
1388 117600,
1389 176400,
1390 235200,
1391 352800,
1392 470400,
1393 705600,
1394 940800,
1395 1411200,
1396 1881600,
1397 2882400,
1398 3763200,
1399 5644800,
1400 7526400,
1401 11289600,
1402 22579600,
1403};
1404
1405static int wm5100_hw_params(struct snd_pcm_substream *substream,
1406 struct snd_pcm_hw_params *params,
1407 struct snd_soc_dai *dai)
1408{
1409 struct snd_soc_codec *codec = dai->codec;
1410 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
1411 bool async = wm5100->aif_async[dai->id];
1412 int i, base, bclk, aif_rate, lrclk, wl, fl, sr;
1413 int *bclk_rates;
1414
1415 base = wm5100_dai_to_base(dai);
1416 if (base < 0)
1417 return base;
1418
1419 /* Data sizes if not using TDM */
1420 wl = snd_pcm_format_width(params_format(params));
1421 if (wl < 0)
1422 return wl;
1423 fl = snd_soc_params_to_frame_size(params);
1424 if (fl < 0)
1425 return fl;
1426
1427 dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
1428 wl, fl);
1429
1430 /* Target BCLK rate */
1431 bclk = snd_soc_params_to_bclk(params);
1432 if (bclk < 0)
1433 return bclk;
1434
1435 /* Root for BCLK depends on SYS/ASYNCCLK */
1436 if (!async) {
1437 aif_rate = wm5100->sysclk;
1438 sr = wm5100_alloc_sr(codec, params_rate(params));
1439 if (sr < 0)
1440 return sr;
1441 } else {
1442 /* If we're in ASYNCCLK set the ASYNC sample rate */
1443 aif_rate = wm5100->asyncclk;
1444 sr = 3;
1445
1446 for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
1447 if (params_rate(params) == wm5100_sr_code[i])
1448 break;
1449 if (i == ARRAY_SIZE(wm5100_sr_code)) {
1450 dev_err(codec->dev, "Invalid rate %dHzn",
1451 params_rate(params));
1452 return -EINVAL;
1453 }
1454
1455 /* TODO: We should really check for symmetry */
1456 snd_soc_update_bits(codec, WM5100_CLOCKING_8,
1457 WM5100_ASYNC_SAMPLE_RATE_MASK, i);
1458 }
1459
1460 if (!aif_rate) {
1461 dev_err(codec->dev, "%s has no rate set\n",
1462 async ? "ASYNCCLK" : "SYSCLK");
1463 return -EINVAL;
1464 }
1465
1466 dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz %s\n",
1467 bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
1468
1469 if (aif_rate % 4000)
1470 bclk_rates = wm5100_bclk_rates_cd;
1471 else
1472 bclk_rates = wm5100_bclk_rates_dat;
1473
1474 for (i = 0; i < WM5100_NUM_BCLK_RATES; i++)
1475 if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
1476 break;
1477 if (i == WM5100_NUM_BCLK_RATES) {
1478 dev_err(codec->dev,
1479 "No valid BCLK for %dHz found from %dHz %s\n",
1480 bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
1481 return -EINVAL;
1482 }
1483
1484 bclk = i;
1485 dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
1486 snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_FREQ_MASK, bclk);
1487
1488 lrclk = bclk_rates[bclk] / params_rate(params);
1489 dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
1490 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
1491 wm5100->aif_symmetric[dai->id])
1492 snd_soc_update_bits(codec, base + 7,
1493 WM5100_AIF1RX_BCPF_MASK, lrclk);
1494 else
1495 snd_soc_update_bits(codec, base + 6,
1496 WM5100_AIF1TX_BCPF_MASK, lrclk);
1497
1498 i = (wl << WM5100_AIF1TX_WL_SHIFT) | fl;
1499 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1500 snd_soc_update_bits(codec, base + 9,
1501 WM5100_AIF1RX_WL_MASK |
1502 WM5100_AIF1RX_SLOT_LEN_MASK, i);
1503 else
1504 snd_soc_update_bits(codec, base + 8,
1505 WM5100_AIF1TX_WL_MASK |
1506 WM5100_AIF1TX_SLOT_LEN_MASK, i);
1507
1508 snd_soc_update_bits(codec, base + 4, WM5100_AIF1_RATE_MASK, sr);
1509
1510 return 0;
1511}
1512
Lars-Peter Clausen85e76522011-11-23 11:40:40 +01001513static const struct snd_soc_dai_ops wm5100_dai_ops = {
Mark Brown6d4baf02011-09-20 15:44:21 +01001514 .set_fmt = wm5100_set_fmt,
1515 .hw_params = wm5100_hw_params,
1516};
1517
1518static int wm5100_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1519 int source, unsigned int freq, int dir)
1520{
1521 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
1522 int *rate_store;
1523 int fval, audio_rate, ret, reg;
1524
1525 switch (clk_id) {
1526 case WM5100_CLK_SYSCLK:
1527 reg = WM5100_CLOCKING_3;
1528 rate_store = &wm5100->sysclk;
1529 break;
1530 case WM5100_CLK_ASYNCCLK:
1531 reg = WM5100_CLOCKING_7;
1532 rate_store = &wm5100->asyncclk;
1533 break;
1534 case WM5100_CLK_32KHZ:
1535 /* The 32kHz clock is slightly different to the others */
1536 switch (source) {
1537 case WM5100_CLKSRC_MCLK1:
1538 case WM5100_CLKSRC_MCLK2:
1539 case WM5100_CLKSRC_SYSCLK:
1540 snd_soc_update_bits(codec, WM5100_CLOCKING_1,
1541 WM5100_CLK_32K_SRC_MASK,
1542 source);
1543 break;
1544 default:
1545 return -EINVAL;
1546 }
1547 return 0;
1548
1549 case WM5100_CLK_AIF1:
1550 case WM5100_CLK_AIF2:
1551 case WM5100_CLK_AIF3:
1552 /* Not real clocks, record which clock domain they're in */
1553 switch (source) {
1554 case WM5100_CLKSRC_SYSCLK:
1555 wm5100->aif_async[clk_id - 1] = false;
1556 break;
1557 case WM5100_CLKSRC_ASYNCCLK:
1558 wm5100->aif_async[clk_id - 1] = true;
1559 break;
1560 default:
1561 dev_err(codec->dev, "Invalid source %d\n", source);
1562 return -EINVAL;
1563 }
1564 return 0;
1565
1566 case WM5100_CLK_OPCLK:
1567 switch (freq) {
1568 case 5644800:
1569 case 6144000:
1570 snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
1571 WM5100_OPCLK_SEL_MASK, 0);
1572 break;
1573 case 11289600:
1574 case 12288000:
1575 snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
1576 WM5100_OPCLK_SEL_MASK, 0);
1577 break;
1578 case 22579200:
1579 case 24576000:
1580 snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
1581 WM5100_OPCLK_SEL_MASK, 0);
1582 break;
1583 default:
1584 dev_err(codec->dev, "Unsupported OPCLK %dHz\n",
1585 freq);
1586 return -EINVAL;
1587 }
1588 return 0;
1589
1590 default:
1591 dev_err(codec->dev, "Unknown clock %d\n", clk_id);
1592 return -EINVAL;
1593 }
1594
1595 switch (source) {
1596 case WM5100_CLKSRC_SYSCLK:
1597 case WM5100_CLKSRC_ASYNCCLK:
1598 dev_err(codec->dev, "Invalid source %d\n", source);
1599 return -EINVAL;
1600 }
1601
1602 switch (freq) {
1603 case 5644800:
1604 case 6144000:
1605 fval = 0;
1606 break;
1607 case 11289600:
1608 case 12288000:
1609 fval = 1;
1610 break;
1611 case 22579200:
Mark Brown11c2b5f2011-10-03 21:07:06 +01001612 case 24576000:
Mark Brown6d4baf02011-09-20 15:44:21 +01001613 fval = 2;
1614 break;
1615 default:
1616 dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
1617 return -EINVAL;
1618 }
1619
1620 switch (freq) {
1621 case 5644800:
1622 case 11289600:
1623 case 22579200:
1624 audio_rate = 44100;
1625 break;
1626
1627 case 6144000:
1628 case 12288000:
Mark Brown11c2b5f2011-10-03 21:07:06 +01001629 case 24576000:
Mark Brown6d4baf02011-09-20 15:44:21 +01001630 audio_rate = 48000;
1631 break;
1632
1633 default:
1634 BUG();
1635 audio_rate = 0;
1636 break;
1637 }
1638
1639 /* TODO: Check if MCLKs are in use and enable/disable pulls to
1640 * match.
1641 */
1642
1643 snd_soc_update_bits(codec, reg, WM5100_SYSCLK_FREQ_MASK |
1644 WM5100_SYSCLK_SRC_MASK,
1645 fval << WM5100_SYSCLK_FREQ_SHIFT | source);
1646
1647 /* If this is SYSCLK then configure the clock rate for the
1648 * internal audio functions to the natural sample rate for
1649 * this clock rate.
1650 */
1651 if (clk_id == WM5100_CLK_SYSCLK) {
1652 dev_dbg(codec->dev, "Setting primary audio rate to %dHz",
1653 audio_rate);
1654 if (0 && *rate_store)
1655 wm5100_free_sr(codec, audio_rate);
1656 ret = wm5100_alloc_sr(codec, audio_rate);
1657 if (ret != 0)
1658 dev_warn(codec->dev, "Primary audio slot is %d\n",
1659 ret);
1660 }
1661
1662 *rate_store = freq;
1663
1664 return 0;
1665}
1666
1667struct _fll_div {
1668 u16 fll_fratio;
1669 u16 fll_outdiv;
1670 u16 fll_refclk_div;
1671 u16 n;
1672 u16 theta;
1673 u16 lambda;
1674};
1675
1676static struct {
1677 unsigned int min;
1678 unsigned int max;
1679 u16 fll_fratio;
1680 int ratio;
1681} fll_fratios[] = {
1682 { 0, 64000, 4, 16 },
1683 { 64000, 128000, 3, 8 },
1684 { 128000, 256000, 2, 4 },
1685 { 256000, 1000000, 1, 2 },
1686 { 1000000, 13500000, 0, 1 },
1687};
1688
1689static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
1690 unsigned int Fout)
1691{
1692 unsigned int target;
1693 unsigned int div;
1694 unsigned int fratio, gcd_fll;
1695 int i;
1696
1697 /* Fref must be <=13.5MHz */
1698 div = 1;
1699 fll_div->fll_refclk_div = 0;
1700 while ((Fref / div) > 13500000) {
1701 div *= 2;
1702 fll_div->fll_refclk_div++;
1703
1704 if (div > 8) {
1705 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
1706 Fref);
1707 return -EINVAL;
1708 }
1709 }
1710
1711 pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
1712
1713 /* Apply the division for our remaining calculations */
1714 Fref /= div;
1715
1716 /* Fvco should be 90-100MHz; don't check the upper bound */
1717 div = 2;
1718 while (Fout * div < 90000000) {
1719 div++;
1720 if (div > 64) {
1721 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
1722 Fout);
1723 return -EINVAL;
1724 }
1725 }
1726 target = Fout * div;
1727 fll_div->fll_outdiv = div - 1;
1728
1729 pr_debug("FLL Fvco=%dHz\n", target);
1730
1731 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1732 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1733 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1734 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
1735 fratio = fll_fratios[i].ratio;
1736 break;
1737 }
1738 }
1739 if (i == ARRAY_SIZE(fll_fratios)) {
1740 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
1741 return -EINVAL;
1742 }
1743
1744 fll_div->n = target / (fratio * Fref);
1745
1746 if (target % Fref == 0) {
1747 fll_div->theta = 0;
1748 fll_div->lambda = 0;
1749 } else {
1750 gcd_fll = gcd(target, fratio * Fref);
1751
1752 fll_div->theta = (target - (fll_div->n * fratio * Fref))
1753 / gcd_fll;
1754 fll_div->lambda = (fratio * Fref) / gcd_fll;
1755 }
1756
1757 pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
1758 fll_div->n, fll_div->theta, fll_div->lambda);
1759 pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
1760 fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
1761 fll_div->fll_refclk_div);
1762
1763 return 0;
1764}
1765
1766static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
1767 unsigned int Fref, unsigned int Fout)
1768{
1769 struct i2c_client *i2c = to_i2c_client(codec->dev);
1770 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
1771 struct _fll_div factors;
1772 struct wm5100_fll *fll;
1773 int ret, base, lock, i, timeout;
1774
1775 switch (fll_id) {
1776 case WM5100_FLL1:
1777 fll = &wm5100->fll[0];
1778 base = WM5100_FLL1_CONTROL_1 - 1;
1779 lock = WM5100_FLL1_LOCK_STS;
1780 break;
1781 case WM5100_FLL2:
1782 fll = &wm5100->fll[1];
1783 base = WM5100_FLL2_CONTROL_2 - 1;
1784 lock = WM5100_FLL2_LOCK_STS;
1785 break;
1786 default:
1787 dev_err(codec->dev, "Unknown FLL %d\n",fll_id);
1788 return -EINVAL;
1789 }
1790
1791 if (!Fout) {
1792 dev_dbg(codec->dev, "FLL%d disabled", fll_id);
Mark Brown62c1c402012-01-26 17:28:49 +00001793 if (fll->fout)
1794 pm_runtime_put(codec->dev);
Mark Brown6d4baf02011-09-20 15:44:21 +01001795 fll->fout = 0;
1796 snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
1797 return 0;
1798 }
1799
1800 switch (source) {
1801 case WM5100_FLL_SRC_MCLK1:
1802 case WM5100_FLL_SRC_MCLK2:
1803 case WM5100_FLL_SRC_FLL1:
1804 case WM5100_FLL_SRC_FLL2:
1805 case WM5100_FLL_SRC_AIF1BCLK:
1806 case WM5100_FLL_SRC_AIF2BCLK:
1807 case WM5100_FLL_SRC_AIF3BCLK:
1808 break;
1809 default:
1810 dev_err(codec->dev, "Invalid FLL source %d\n", source);
1811 return -EINVAL;
1812 }
1813
1814 ret = fll_factors(&factors, Fref, Fout);
1815 if (ret < 0)
1816 return ret;
1817
1818 /* Disable the FLL while we reconfigure */
1819 snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
1820
1821 snd_soc_update_bits(codec, base + 2,
1822 WM5100_FLL1_OUTDIV_MASK | WM5100_FLL1_FRATIO_MASK,
1823 (factors.fll_outdiv << WM5100_FLL1_OUTDIV_SHIFT) |
1824 factors.fll_fratio);
1825 snd_soc_update_bits(codec, base + 3, WM5100_FLL1_THETA_MASK,
1826 factors.theta);
1827 snd_soc_update_bits(codec, base + 5, WM5100_FLL1_N_MASK, factors.n);
1828 snd_soc_update_bits(codec, base + 6,
1829 WM5100_FLL1_REFCLK_DIV_MASK |
1830 WM5100_FLL1_REFCLK_SRC_MASK,
1831 (factors.fll_refclk_div
1832 << WM5100_FLL1_REFCLK_DIV_SHIFT) | source);
1833 snd_soc_update_bits(codec, base + 7, WM5100_FLL1_LAMBDA_MASK,
1834 factors.lambda);
1835
1836 /* Clear any pending completions */
1837 try_wait_for_completion(&fll->lock);
1838
Mark Brown62c1c402012-01-26 17:28:49 +00001839 pm_runtime_get_sync(codec->dev);
1840
Mark Brown6d4baf02011-09-20 15:44:21 +01001841 snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
1842
1843 if (i2c->irq)
1844 timeout = 2;
1845 else
1846 timeout = 50;
1847
Mark Brownbd132ec2011-10-23 11:10:45 +01001848 snd_soc_update_bits(codec, WM5100_CLOCKING_3, WM5100_SYSCLK_ENA,
1849 WM5100_SYSCLK_ENA);
1850
Mark Brown6d4baf02011-09-20 15:44:21 +01001851 /* Poll for the lock; will use interrupt when we can test */
1852 for (i = 0; i < timeout; i++) {
1853 if (i2c->irq) {
1854 ret = wait_for_completion_timeout(&fll->lock,
1855 msecs_to_jiffies(25));
1856 if (ret > 0)
1857 break;
1858 } else {
1859 msleep(1);
1860 }
1861
1862 ret = snd_soc_read(codec,
1863 WM5100_INTERRUPT_RAW_STATUS_3);
1864 if (ret < 0) {
1865 dev_err(codec->dev,
1866 "Failed to read FLL status: %d\n",
1867 ret);
1868 continue;
1869 }
1870 if (ret & lock)
1871 break;
1872 }
1873 if (i == timeout) {
1874 dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
Mark Brown62c1c402012-01-26 17:28:49 +00001875 pm_runtime_put(codec->dev);
Mark Brown6d4baf02011-09-20 15:44:21 +01001876 return -ETIMEDOUT;
1877 }
1878
1879 fll->src = source;
1880 fll->fref = Fref;
1881 fll->fout = Fout;
1882
1883 dev_dbg(codec->dev, "FLL%d running %dHz->%dHz\n", fll_id,
1884 Fref, Fout);
1885
1886 return 0;
1887}
1888
1889/* Actually go much higher */
1890#define WM5100_RATES SNDRV_PCM_RATE_8000_192000
1891
1892#define WM5100_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1893 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1894
1895static struct snd_soc_dai_driver wm5100_dai[] = {
1896 {
1897 .name = "wm5100-aif1",
1898 .playback = {
1899 .stream_name = "AIF1 Playback",
1900 .channels_min = 2,
1901 .channels_max = 2,
1902 .rates = WM5100_RATES,
1903 .formats = WM5100_FORMATS,
1904 },
1905 .capture = {
1906 .stream_name = "AIF1 Capture",
1907 .channels_min = 2,
1908 .channels_max = 2,
1909 .rates = WM5100_RATES,
1910 .formats = WM5100_FORMATS,
1911 },
1912 .ops = &wm5100_dai_ops,
1913 },
1914 {
1915 .name = "wm5100-aif2",
1916 .id = 1,
1917 .playback = {
1918 .stream_name = "AIF2 Playback",
1919 .channels_min = 2,
1920 .channels_max = 2,
1921 .rates = WM5100_RATES,
1922 .formats = WM5100_FORMATS,
1923 },
1924 .capture = {
1925 .stream_name = "AIF2 Capture",
1926 .channels_min = 2,
1927 .channels_max = 2,
1928 .rates = WM5100_RATES,
1929 .formats = WM5100_FORMATS,
1930 },
1931 .ops = &wm5100_dai_ops,
1932 },
1933 {
1934 .name = "wm5100-aif3",
1935 .id = 2,
1936 .playback = {
1937 .stream_name = "AIF3 Playback",
1938 .channels_min = 2,
1939 .channels_max = 2,
1940 .rates = WM5100_RATES,
1941 .formats = WM5100_FORMATS,
1942 },
1943 .capture = {
1944 .stream_name = "AIF3 Capture",
1945 .channels_min = 2,
1946 .channels_max = 2,
1947 .rates = WM5100_RATES,
1948 .formats = WM5100_FORMATS,
1949 },
1950 .ops = &wm5100_dai_ops,
1951 },
1952};
1953
1954static int wm5100_dig_vu[] = {
1955 WM5100_ADC_DIGITAL_VOLUME_1L,
1956 WM5100_ADC_DIGITAL_VOLUME_1R,
1957 WM5100_ADC_DIGITAL_VOLUME_2L,
1958 WM5100_ADC_DIGITAL_VOLUME_2R,
1959 WM5100_ADC_DIGITAL_VOLUME_3L,
1960 WM5100_ADC_DIGITAL_VOLUME_3R,
1961 WM5100_ADC_DIGITAL_VOLUME_4L,
1962 WM5100_ADC_DIGITAL_VOLUME_4R,
1963
1964 WM5100_DAC_DIGITAL_VOLUME_1L,
1965 WM5100_DAC_DIGITAL_VOLUME_1R,
1966 WM5100_DAC_DIGITAL_VOLUME_2L,
1967 WM5100_DAC_DIGITAL_VOLUME_2R,
1968 WM5100_DAC_DIGITAL_VOLUME_3L,
1969 WM5100_DAC_DIGITAL_VOLUME_3R,
1970 WM5100_DAC_DIGITAL_VOLUME_4L,
1971 WM5100_DAC_DIGITAL_VOLUME_4R,
1972 WM5100_DAC_DIGITAL_VOLUME_5L,
1973 WM5100_DAC_DIGITAL_VOLUME_5R,
1974 WM5100_DAC_DIGITAL_VOLUME_6L,
1975 WM5100_DAC_DIGITAL_VOLUME_6R,
1976};
1977
Mark Brown46c1a872012-01-18 14:53:08 +00001978static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
Mark Brownba896ed2011-09-27 17:39:50 +01001979{
Mark Brownba896ed2011-09-27 17:39:50 +01001980 struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
1981
1982 BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
1983
1984 gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
Mark Brown46c1a872012-01-18 14:53:08 +00001985 regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
1986 WM5100_ACCDET_BIAS_SRC_MASK |
1987 WM5100_ACCDET_SRC,
1988 (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
1989 mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
1990 regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL,
1991 WM5100_HPCOM_SRC,
1992 mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
Mark Brownba896ed2011-09-27 17:39:50 +01001993
1994 wm5100->jack_mode = the_mode;
1995
Mark Brown46c1a872012-01-18 14:53:08 +00001996 dev_dbg(wm5100->dev, "Set microphone polarity to %d\n",
Mark Brownba896ed2011-09-27 17:39:50 +01001997 wm5100->jack_mode);
1998}
1999
Mark Brown2633f732012-01-26 17:43:09 +00002000static void wm5100_report_headphone(struct wm5100_priv *wm5100)
2001{
2002 dev_dbg(wm5100->dev, "Headphone detected\n");
2003 wm5100->jack_detecting = false;
2004 snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
2005 SND_JACK_HEADPHONE);
2006
2007 /* Increase the detection rate a bit for responsiveness. */
2008 regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
2009 WM5100_ACCDET_RATE_MASK,
2010 7 << WM5100_ACCDET_RATE_SHIFT);
2011}
2012
Mark Brown46c1a872012-01-18 14:53:08 +00002013static void wm5100_micd_irq(struct wm5100_priv *wm5100)
Mark Brownba896ed2011-09-27 17:39:50 +01002014{
Mark Brown46c1a872012-01-18 14:53:08 +00002015 unsigned int val;
2016 int ret;
Mark Brownba896ed2011-09-27 17:39:50 +01002017
Mark Brown46c1a872012-01-18 14:53:08 +00002018 ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val);
2019 if (ret != 0) {
2020 dev_err(wm5100->dev, "Failed to read micropone status: %d\n",
2021 ret);
2022 return;
2023 }
Mark Brownba896ed2011-09-27 17:39:50 +01002024
Mark Brown46c1a872012-01-18 14:53:08 +00002025 dev_dbg(wm5100->dev, "Microphone event: %x\n", val);
Mark Brownba896ed2011-09-27 17:39:50 +01002026
2027 if (!(val & WM5100_ACCDET_VALID)) {
Mark Brown46c1a872012-01-18 14:53:08 +00002028 dev_warn(wm5100->dev, "Microphone detection state invalid\n");
Mark Brownba896ed2011-09-27 17:39:50 +01002029 return;
2030 }
2031
2032 /* No accessory, reset everything and report removal */
2033 if (!(val & WM5100_ACCDET_STS)) {
Mark Brown46c1a872012-01-18 14:53:08 +00002034 dev_dbg(wm5100->dev, "Jack removal detected\n");
Mark Brownba896ed2011-09-27 17:39:50 +01002035 wm5100->jack_mic = false;
2036 wm5100->jack_detecting = true;
Mark Brown2633f732012-01-26 17:43:09 +00002037 wm5100->jack_flips = 0;
Mark Brownba896ed2011-09-27 17:39:50 +01002038 snd_soc_jack_report(wm5100->jack, 0,
2039 SND_JACK_LINEOUT | SND_JACK_HEADSET |
2040 SND_JACK_BTN_0);
2041
Mark Brown46c1a872012-01-18 14:53:08 +00002042 regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
2043 WM5100_ACCDET_RATE_MASK,
2044 WM5100_ACCDET_RATE_MASK);
Mark Brownba896ed2011-09-27 17:39:50 +01002045 return;
2046 }
2047
2048 /* If the measurement is very high we've got a microphone,
2049 * either we just detected one or if we already reported then
2050 * we've got a button release event.
2051 */
2052 if (val & 0x400) {
2053 if (wm5100->jack_detecting) {
Mark Brown46c1a872012-01-18 14:53:08 +00002054 dev_dbg(wm5100->dev, "Microphone detected\n");
Mark Brownba896ed2011-09-27 17:39:50 +01002055 wm5100->jack_mic = true;
2056 snd_soc_jack_report(wm5100->jack,
2057 SND_JACK_HEADSET,
2058 SND_JACK_HEADSET | SND_JACK_BTN_0);
2059
2060 /* Increase poll rate to give better responsiveness
2061 * for buttons */
Mark Brown46c1a872012-01-18 14:53:08 +00002062 regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
2063 WM5100_ACCDET_RATE_MASK,
2064 5 << WM5100_ACCDET_RATE_SHIFT);
Mark Brownba896ed2011-09-27 17:39:50 +01002065 } else {
Mark Brown46c1a872012-01-18 14:53:08 +00002066 dev_dbg(wm5100->dev, "Mic button up\n");
Mark Brownba896ed2011-09-27 17:39:50 +01002067 snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
2068 }
2069
2070 return;
2071 }
2072
2073 /* If we detected a lower impedence during initial startup
2074 * then we probably have the wrong polarity, flip it. Don't
2075 * do this for the lowest impedences to speed up detection of
Mark Brown2633f732012-01-26 17:43:09 +00002076 * plain headphones and give up if neither polarity looks
2077 * sensible.
Mark Brownba896ed2011-09-27 17:39:50 +01002078 */
2079 if (wm5100->jack_detecting && (val & 0x3f8)) {
Mark Brown2633f732012-01-26 17:43:09 +00002080 wm5100->jack_flips++;
2081
2082 if (wm5100->jack_flips > 1)
2083 wm5100_report_headphone(wm5100);
2084 else
2085 wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
Mark Brownba896ed2011-09-27 17:39:50 +01002086
2087 return;
2088 }
2089
2090 /* Don't distinguish between buttons, just report any low
2091 * impedence as BTN_0.
2092 */
2093 if (val & 0x3fc) {
2094 if (wm5100->jack_mic) {
Mark Brown46c1a872012-01-18 14:53:08 +00002095 dev_dbg(wm5100->dev, "Mic button detected\n");
Mark Brownba896ed2011-09-27 17:39:50 +01002096 snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
2097 SND_JACK_BTN_0);
2098 } else if (wm5100->jack_detecting) {
Mark Brown2633f732012-01-26 17:43:09 +00002099 wm5100_report_headphone(wm5100);
Mark Brownba896ed2011-09-27 17:39:50 +01002100 }
2101 }
2102}
2103
2104int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
2105{
2106 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
2107
2108 if (jack) {
2109 wm5100->jack = jack;
2110 wm5100->jack_detecting = true;
Mark Brown2633f732012-01-26 17:43:09 +00002111 wm5100->jack_flips = 0;
Mark Brownba896ed2011-09-27 17:39:50 +01002112
Mark Brown46c1a872012-01-18 14:53:08 +00002113 wm5100_set_detect_mode(wm5100, 0);
Mark Brownba896ed2011-09-27 17:39:50 +01002114
2115 /* Slowest detection rate, gives debounce for initial
2116 * detection */
2117 snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
2118 WM5100_ACCDET_BIAS_STARTTIME_MASK |
2119 WM5100_ACCDET_RATE_MASK,
2120 (7 << WM5100_ACCDET_BIAS_STARTTIME_SHIFT) |
2121 WM5100_ACCDET_RATE_MASK);
2122
2123 /* We need the charge pump to power MICBIAS */
2124 snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2");
2125 snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
2126 snd_soc_dapm_sync(&codec->dapm);
2127
2128 /* We start off just enabling microphone detection - even a
2129 * plain headphone will trigger detection.
2130 */
2131 snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
2132 WM5100_ACCDET_ENA, WM5100_ACCDET_ENA);
2133
2134 snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
2135 WM5100_IM_ACCDET_EINT, 0);
2136 } else {
2137 snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
2138 WM5100_IM_HPDET_EINT |
2139 WM5100_IM_ACCDET_EINT,
2140 WM5100_IM_HPDET_EINT |
2141 WM5100_IM_ACCDET_EINT);
2142 snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
2143 WM5100_ACCDET_ENA, 0);
2144 wm5100->jack = NULL;
2145 }
2146
2147 return 0;
2148}
2149
Mark Brown6d4baf02011-09-20 15:44:21 +01002150static irqreturn_t wm5100_irq(int irq, void *data)
2151{
Mark Brown46c1a872012-01-18 14:53:08 +00002152 struct wm5100_priv *wm5100 = data;
Mark Brown6d4baf02011-09-20 15:44:21 +01002153 irqreturn_t status = IRQ_NONE;
Mark Brown46c1a872012-01-18 14:53:08 +00002154 unsigned int irq_val, mask_val;
2155 int ret;
Mark Brown6d4baf02011-09-20 15:44:21 +01002156
Mark Brown46c1a872012-01-18 14:53:08 +00002157 ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val);
2158 if (ret < 0) {
2159 dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n",
2160 ret);
Mark Brown6d4baf02011-09-20 15:44:21 +01002161 irq_val = 0;
2162 }
Mark Brown6d4baf02011-09-20 15:44:21 +01002163
Mark Brown46c1a872012-01-18 14:53:08 +00002164 ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK,
2165 &mask_val);
2166 if (ret < 0) {
2167 dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n",
2168 ret);
2169 mask_val = 0xffff;
2170 }
2171
2172 irq_val &= ~mask_val;
2173
2174 regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val);
Mark Brown6d4baf02011-09-20 15:44:21 +01002175
2176 if (irq_val)
2177 status = IRQ_HANDLED;
2178
Mark Brown46c1a872012-01-18 14:53:08 +00002179 wm5100_log_status3(wm5100, irq_val);
Mark Brown6d4baf02011-09-20 15:44:21 +01002180
2181 if (irq_val & WM5100_FLL1_LOCK_EINT) {
Mark Brown46c1a872012-01-18 14:53:08 +00002182 dev_dbg(wm5100->dev, "FLL1 locked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +01002183 complete(&wm5100->fll[0].lock);
2184 }
2185 if (irq_val & WM5100_FLL2_LOCK_EINT) {
Mark Brown46c1a872012-01-18 14:53:08 +00002186 dev_dbg(wm5100->dev, "FLL2 locked\n");
Mark Brown6d4baf02011-09-20 15:44:21 +01002187 complete(&wm5100->fll[1].lock);
2188 }
2189
Mark Brownba896ed2011-09-27 17:39:50 +01002190 if (irq_val & WM5100_ACCDET_EINT)
Mark Brown46c1a872012-01-18 14:53:08 +00002191 wm5100_micd_irq(wm5100);
Mark Brownba896ed2011-09-27 17:39:50 +01002192
Mark Brown46c1a872012-01-18 14:53:08 +00002193 ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val);
2194 if (ret < 0) {
2195 dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n",
2196 ret);
Mark Brown6d4baf02011-09-20 15:44:21 +01002197 irq_val = 0;
2198 }
Mark Brown46c1a872012-01-18 14:53:08 +00002199
2200 ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK,
2201 &mask_val);
2202 if (ret < 0) {
2203 dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n",
2204 ret);
2205 mask_val = 0xffff;
2206 }
2207
2208 irq_val &= ~mask_val;
Mark Brown6d4baf02011-09-20 15:44:21 +01002209
2210 if (irq_val)
2211 status = IRQ_HANDLED;
2212
Mark Brown46c1a872012-01-18 14:53:08 +00002213 regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val);
Mark Brown6d4baf02011-09-20 15:44:21 +01002214
Mark Brown46c1a872012-01-18 14:53:08 +00002215 wm5100_log_status4(wm5100, irq_val);
Mark Brown6d4baf02011-09-20 15:44:21 +01002216
2217 return status;
2218}
2219
2220static irqreturn_t wm5100_edge_irq(int irq, void *data)
2221{
2222 irqreturn_t ret = IRQ_NONE;
2223 irqreturn_t val;
2224
2225 do {
2226 val = wm5100_irq(irq, data);
2227 if (val != IRQ_NONE)
2228 ret = val;
2229 } while (val != IRQ_NONE);
2230
2231 return ret;
2232}
2233
2234#ifdef CONFIG_GPIOLIB
2235static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip)
2236{
2237 return container_of(chip, struct wm5100_priv, gpio_chip);
2238}
2239
2240static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
2241{
2242 struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
Mark Brown6d4baf02011-09-20 15:44:21 +01002243
Mark Brown9db16e42011-11-09 17:27:28 +00002244 regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
2245 WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT);
Mark Brown6d4baf02011-09-20 15:44:21 +01002246}
2247
2248static int wm5100_gpio_direction_out(struct gpio_chip *chip,
2249 unsigned offset, int value)
2250{
2251 struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
Mark Brown64964e82011-10-31 19:02:13 +00002252 int val, ret;
Mark Brown6d4baf02011-09-20 15:44:21 +01002253
2254 val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
2255
Mark Brown9db16e42011-11-09 17:27:28 +00002256 ret = regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
2257 WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
2258 WM5100_GP1_LVL, val);
Mark Brown64964e82011-10-31 19:02:13 +00002259 if (ret < 0)
2260 return ret;
2261 else
2262 return 0;
Mark Brown6d4baf02011-09-20 15:44:21 +01002263}
2264
2265static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset)
2266{
2267 struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
Mark Brown9db16e42011-11-09 17:27:28 +00002268 unsigned int reg;
Mark Brown6d4baf02011-09-20 15:44:21 +01002269 int ret;
2270
Mark Brown9db16e42011-11-09 17:27:28 +00002271 ret = regmap_read(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, &reg);
Mark Brown6d4baf02011-09-20 15:44:21 +01002272 if (ret < 0)
2273 return ret;
2274
Mark Brown9db16e42011-11-09 17:27:28 +00002275 return (reg & WM5100_GP1_LVL) != 0;
Mark Brown6d4baf02011-09-20 15:44:21 +01002276}
2277
2278static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
2279{
2280 struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
Mark Brown6d4baf02011-09-20 15:44:21 +01002281
Mark Brown9db16e42011-11-09 17:27:28 +00002282 return regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
2283 WM5100_GP1_FN_MASK | WM5100_GP1_DIR,
2284 (1 << WM5100_GP1_FN_SHIFT) |
2285 (1 << WM5100_GP1_DIR_SHIFT));
Mark Brown6d4baf02011-09-20 15:44:21 +01002286}
2287
2288static struct gpio_chip wm5100_template_chip = {
2289 .label = "wm5100",
2290 .owner = THIS_MODULE,
2291 .direction_output = wm5100_gpio_direction_out,
2292 .set = wm5100_gpio_set,
2293 .direction_input = wm5100_gpio_direction_in,
2294 .get = wm5100_gpio_get,
2295 .can_sleep = 1,
2296};
2297
Mark Brown9db16e42011-11-09 17:27:28 +00002298static void wm5100_init_gpio(struct i2c_client *i2c)
Mark Brown6d4baf02011-09-20 15:44:21 +01002299{
Mark Brown9db16e42011-11-09 17:27:28 +00002300 struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
Mark Brown6d4baf02011-09-20 15:44:21 +01002301 int ret;
2302
2303 wm5100->gpio_chip = wm5100_template_chip;
2304 wm5100->gpio_chip.ngpio = 6;
Mark Brown9db16e42011-11-09 17:27:28 +00002305 wm5100->gpio_chip.dev = &i2c->dev;
Mark Brown6d4baf02011-09-20 15:44:21 +01002306
2307 if (wm5100->pdata.gpio_base)
2308 wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
2309 else
2310 wm5100->gpio_chip.base = -1;
2311
2312 ret = gpiochip_add(&wm5100->gpio_chip);
2313 if (ret != 0)
Mark Brown9db16e42011-11-09 17:27:28 +00002314 dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret);
Mark Brown6d4baf02011-09-20 15:44:21 +01002315}
2316
Mark Brown9db16e42011-11-09 17:27:28 +00002317static void wm5100_free_gpio(struct i2c_client *i2c)
Mark Brown6d4baf02011-09-20 15:44:21 +01002318{
Mark Brown9db16e42011-11-09 17:27:28 +00002319 struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
Mark Brown6d4baf02011-09-20 15:44:21 +01002320 int ret;
2321
2322 ret = gpiochip_remove(&wm5100->gpio_chip);
2323 if (ret != 0)
Mark Brown9db16e42011-11-09 17:27:28 +00002324 dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret);
Mark Brown6d4baf02011-09-20 15:44:21 +01002325}
2326#else
Mark Brown9db16e42011-11-09 17:27:28 +00002327static void wm5100_init_gpio(struct i2c_client *i2c)
Mark Brown6d4baf02011-09-20 15:44:21 +01002328{
2329}
2330
Mark Brown9db16e42011-11-09 17:27:28 +00002331static void wm5100_free_gpio(struct i2c_client *i2c)
Mark Brown6d4baf02011-09-20 15:44:21 +01002332{
2333}
2334#endif
2335
2336static int wm5100_probe(struct snd_soc_codec *codec)
2337{
2338 struct i2c_client *i2c = to_i2c_client(codec->dev);
2339 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
Mark Brown09452f22012-01-18 15:05:46 +00002340 int ret, i;
Mark Brown6d4baf02011-09-20 15:44:21 +01002341
2342 wm5100->codec = codec;
Mark Brownbd132ec2011-10-23 11:10:45 +01002343 codec->control_data = wm5100->regmap;
Mark Brown6d4baf02011-09-20 15:44:21 +01002344
Mark Brownbd132ec2011-10-23 11:10:45 +01002345 ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
Mark Brown6d4baf02011-09-20 15:44:21 +01002346 if (ret != 0) {
2347 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
2348 return ret;
2349 }
2350
Mark Brown6d4baf02011-09-20 15:44:21 +01002351 for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
2352 snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
2353 WM5100_OUT_VU);
2354
Mark Brown6d4baf02011-09-20 15:44:21 +01002355 /* Don't debounce interrupts to support use of SYSCLK only */
2356 snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0);
2357 snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0);
2358
2359 /* TODO: check if we're symmetric */
2360
Mark Brown09452f22012-01-18 15:05:46 +00002361 if (i2c->irq)
Mark Brown6d4baf02011-09-20 15:44:21 +01002362 snd_soc_dapm_new_controls(&codec->dapm,
2363 wm5100_dapm_widgets_noirq,
2364 ARRAY_SIZE(wm5100_dapm_widgets_noirq));
Mark Brown6d4baf02011-09-20 15:44:21 +01002365
2366 if (wm5100->pdata.hp_pol) {
2367 ret = gpio_request_one(wm5100->pdata.hp_pol,
2368 GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL");
2369 if (ret < 0) {
2370 dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n",
2371 wm5100->pdata.hp_pol, ret);
2372 goto err_gpio;
2373 }
2374 }
2375
Mark Brown6d4baf02011-09-20 15:44:21 +01002376 return 0;
2377
2378err_gpio:
Mark Brown6d4baf02011-09-20 15:44:21 +01002379
2380 return ret;
2381}
2382
2383static int wm5100_remove(struct snd_soc_codec *codec)
2384{
2385 struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
2386
Mark Brown6d4baf02011-09-20 15:44:21 +01002387 if (wm5100->pdata.hp_pol) {
2388 gpio_free(wm5100->pdata.hp_pol);
2389 }
Mark Brown46c1a872012-01-18 14:53:08 +00002390
Mark Brown6d4baf02011-09-20 15:44:21 +01002391 return 0;
2392}
2393
Mark Brown1b39bf32011-12-29 12:18:53 +00002394static int wm5100_soc_volatile(struct snd_soc_codec *codec,
2395 unsigned int reg)
2396{
2397 return true;
2398}
2399
2400
Mark Brown6d4baf02011-09-20 15:44:21 +01002401static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
2402 .probe = wm5100_probe,
2403 .remove = wm5100_remove,
2404
2405 .set_sysclk = wm5100_set_sysclk,
2406 .set_pll = wm5100_set_fll,
Mark Brown6d4baf02011-09-20 15:44:21 +01002407 .idle_bias_off = 1,
Mark Brown1b39bf32011-12-29 12:18:53 +00002408 .reg_cache_size = WM5100_MAX_REGISTER,
2409 .volatile_register = wm5100_soc_volatile,
Mark Brown6d4baf02011-09-20 15:44:21 +01002410
2411 .seq_notifier = wm5100_seq_notifier,
2412 .controls = wm5100_snd_controls,
2413 .num_controls = ARRAY_SIZE(wm5100_snd_controls),
2414 .dapm_widgets = wm5100_dapm_widgets,
2415 .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets),
2416 .dapm_routes = wm5100_dapm_routes,
2417 .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes),
Mark Brownbd132ec2011-10-23 11:10:45 +01002418};
Mark Brown6d4baf02011-09-20 15:44:21 +01002419
Mark Brownbd132ec2011-10-23 11:10:45 +01002420static const struct regmap_config wm5100_regmap = {
2421 .reg_bits = 16,
2422 .val_bits = 16,
Mark Brown6d4baf02011-09-20 15:44:21 +01002423
Mark Brownbd132ec2011-10-23 11:10:45 +01002424 .max_register = WM5100_MAX_REGISTER,
2425 .reg_defaults = wm5100_reg_defaults,
2426 .num_reg_defaults = ARRAY_SIZE(wm5100_reg_defaults),
2427 .volatile_reg = wm5100_volatile_register,
2428 .readable_reg = wm5100_readable_register,
2429 .cache_type = REGCACHE_RBTREE,
Mark Brown6d4baf02011-09-20 15:44:21 +01002430};
2431
2432static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
2433 const struct i2c_device_id *id)
2434{
2435 struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
2436 struct wm5100_priv *wm5100;
Mark Brown588ac5e2011-11-09 16:12:04 +00002437 unsigned int reg;
Mark Brown09452f22012-01-18 15:05:46 +00002438 int ret, i, irq_flags;
Mark Brown6d4baf02011-09-20 15:44:21 +01002439
Mark Browna81b82c2011-11-24 18:28:51 +00002440 wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv),
2441 GFP_KERNEL);
Mark Brown6d4baf02011-09-20 15:44:21 +01002442 if (wm5100 == NULL)
2443 return -ENOMEM;
2444
Mark Brown46c1a872012-01-18 14:53:08 +00002445 wm5100->dev = &i2c->dev;
2446
Mark Brownbd132ec2011-10-23 11:10:45 +01002447 wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
2448 if (IS_ERR(wm5100->regmap)) {
2449 ret = PTR_ERR(wm5100->regmap);
2450 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
2451 ret);
Mark Browna81b82c2011-11-24 18:28:51 +00002452 goto err;
Mark Brownbd132ec2011-10-23 11:10:45 +01002453 }
2454
Mark Brown6d4baf02011-09-20 15:44:21 +01002455 for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++)
2456 init_completion(&wm5100->fll[i].lock);
2457
2458 if (pdata)
2459 wm5100->pdata = *pdata;
2460
2461 i2c_set_clientdata(i2c, wm5100);
2462
Mark Brown588ac5e2011-11-09 16:12:04 +00002463 for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
2464 wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
2465
Mark Brown17e3e572012-01-23 15:00:17 +00002466 ret = devm_regulator_bulk_get(&i2c->dev,
2467 ARRAY_SIZE(wm5100->core_supplies),
2468 wm5100->core_supplies);
Mark Brown588ac5e2011-11-09 16:12:04 +00002469 if (ret != 0) {
2470 dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
2471 ret);
2472 goto err_regmap;
2473 }
2474
Mark Brown588ac5e2011-11-09 16:12:04 +00002475 ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
2476 wm5100->core_supplies);
2477 if (ret != 0) {
2478 dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
2479 ret);
Mark Brown17e3e572012-01-23 15:00:17 +00002480 goto err_regmap;
Mark Brown588ac5e2011-11-09 16:12:04 +00002481 }
2482
2483 if (wm5100->pdata.ldo_ena) {
2484 ret = gpio_request_one(wm5100->pdata.ldo_ena,
2485 GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
2486 if (ret < 0) {
2487 dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
2488 wm5100->pdata.ldo_ena, ret);
2489 goto err_enable;
2490 }
2491 msleep(2);
2492 }
2493
2494 if (wm5100->pdata.reset) {
2495 ret = gpio_request_one(wm5100->pdata.reset,
2496 GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
2497 if (ret < 0) {
2498 dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
2499 wm5100->pdata.reset, ret);
2500 goto err_ldo;
2501 }
2502 }
2503
2504 ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
2505 if (ret < 0) {
Mark Brown01326152012-01-17 19:27:04 +00002506 dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
Mark Brown588ac5e2011-11-09 16:12:04 +00002507 goto err_reset;
2508 }
2509 switch (reg) {
2510 case 0x8997:
2511 case 0x5100:
2512 break;
2513
2514 default:
2515 dev_err(&i2c->dev, "Device is not a WM5100, ID is %x\n", reg);
2516 ret = -EINVAL;
2517 goto err_reset;
2518 }
2519
2520 ret = regmap_read(wm5100->regmap, WM5100_DEVICE_REVISION, &reg);
2521 if (ret < 0) {
2522 dev_err(&i2c->dev, "Failed to read revision register\n");
2523 goto err_reset;
2524 }
2525 wm5100->rev = reg & WM5100_DEVICE_REVISION_MASK;
2526
2527 dev_info(&i2c->dev, "revision %c\n", wm5100->rev + 'A');
2528
2529 ret = wm5100_reset(wm5100);
2530 if (ret < 0) {
2531 dev_err(&i2c->dev, "Failed to issue reset\n");
2532 goto err_reset;
2533 }
2534
Mark Brown15b52f12012-01-21 12:14:53 +00002535 switch (wm5100->rev) {
2536 case 0:
2537 ret = regmap_register_patch(wm5100->regmap,
2538 wm5100_reva_patches,
2539 ARRAY_SIZE(wm5100_reva_patches));
2540 if (ret != 0) {
2541 dev_err(&i2c->dev, "Failed to register patches: %d\n",
2542 ret);
2543 goto err_reset;
2544 }
2545 break;
2546 default:
2547 break;
2548 }
2549
2550
Mark Brown9db16e42011-11-09 17:27:28 +00002551 wm5100_init_gpio(i2c);
2552
Mark Brownd9b5e9c2011-11-10 16:14:04 +00002553 for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
2554 if (!wm5100->pdata.gpio_defaults[i])
2555 continue;
2556
2557 regmap_write(wm5100->regmap, WM5100_GPIO_CTRL_1 + i,
2558 wm5100->pdata.gpio_defaults[i]);
2559 }
2560
2561 for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
2562 regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL,
2563 WM5100_IN1_MODE_MASK |
2564 WM5100_IN1_DMIC_SUP_MASK,
2565 (wm5100->pdata.in_mode[i] <<
2566 WM5100_IN1_MODE_SHIFT) |
2567 (wm5100->pdata.dmic_sup[i] <<
2568 WM5100_IN1_DMIC_SUP_SHIFT));
2569 }
2570
Mark Brown09452f22012-01-18 15:05:46 +00002571 if (i2c->irq) {
2572 if (wm5100->pdata.irq_flags)
2573 irq_flags = wm5100->pdata.irq_flags;
2574 else
2575 irq_flags = IRQF_TRIGGER_LOW;
2576
2577 irq_flags |= IRQF_ONESHOT;
2578
2579 if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
2580 ret = request_threaded_irq(i2c->irq, NULL,
2581 wm5100_edge_irq, irq_flags,
2582 "wm5100", wm5100);
2583 else
2584 ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
2585 irq_flags, "wm5100",
2586 wm5100);
2587
2588 if (ret != 0) {
2589 dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
2590 i2c->irq, ret);
2591 } else {
2592 /* Enable default interrupts */
2593 regmap_update_bits(wm5100->regmap,
2594 WM5100_INTERRUPT_STATUS_3_MASK,
2595 WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
2596 WM5100_IM_SPK_SHUTDOWN_EINT |
2597 WM5100_IM_ASRC2_LOCK_EINT |
2598 WM5100_IM_ASRC1_LOCK_EINT |
2599 WM5100_IM_FLL2_LOCK_EINT |
2600 WM5100_IM_FLL1_LOCK_EINT |
2601 WM5100_CLKGEN_ERR_EINT |
2602 WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
2603
2604 regmap_update_bits(wm5100->regmap,
2605 WM5100_INTERRUPT_STATUS_4_MASK,
2606 WM5100_AIF3_ERR_EINT |
2607 WM5100_AIF2_ERR_EINT |
2608 WM5100_AIF1_ERR_EINT |
2609 WM5100_CTRLIF_ERR_EINT |
2610 WM5100_ISRC2_UNDERCLOCKED_EINT |
2611 WM5100_ISRC1_UNDERCLOCKED_EINT |
2612 WM5100_FX_UNDERCLOCKED_EINT |
2613 WM5100_AIF3_UNDERCLOCKED_EINT |
2614 WM5100_AIF2_UNDERCLOCKED_EINT |
2615 WM5100_AIF1_UNDERCLOCKED_EINT |
2616 WM5100_ASRC_UNDERCLOCKED_EINT |
2617 WM5100_DAC_UNDERCLOCKED_EINT |
2618 WM5100_ADC_UNDERCLOCKED_EINT |
2619 WM5100_MIXER_UNDERCLOCKED_EINT, 0);
2620 }
2621 }
2622
Mark Brown62c1c402012-01-26 17:28:49 +00002623 pm_runtime_set_active(&i2c->dev);
2624 pm_runtime_enable(&i2c->dev);
2625 pm_request_idle(&i2c->dev);
2626
Mark Brown6d4baf02011-09-20 15:44:21 +01002627 ret = snd_soc_register_codec(&i2c->dev,
2628 &soc_codec_dev_wm5100, wm5100_dai,
2629 ARRAY_SIZE(wm5100_dai));
2630 if (ret < 0) {
2631 dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret);
Mark Brown588ac5e2011-11-09 16:12:04 +00002632 goto err_reset;
Mark Brown6d4baf02011-09-20 15:44:21 +01002633 }
2634
2635 return ret;
Mark Brownbd132ec2011-10-23 11:10:45 +01002636
Mark Brown588ac5e2011-11-09 16:12:04 +00002637err_reset:
Mark Brown09452f22012-01-18 15:05:46 +00002638 if (i2c->irq)
2639 free_irq(i2c->irq, wm5100);
Mark Brown9db16e42011-11-09 17:27:28 +00002640 wm5100_free_gpio(i2c);
Mark Brown588ac5e2011-11-09 16:12:04 +00002641 if (wm5100->pdata.reset) {
Mark Brown26887382012-01-17 19:18:27 +00002642 gpio_set_value_cansleep(wm5100->pdata.reset, 0);
Mark Brown588ac5e2011-11-09 16:12:04 +00002643 gpio_free(wm5100->pdata.reset);
2644 }
2645err_ldo:
2646 if (wm5100->pdata.ldo_ena) {
2647 gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
2648 gpio_free(wm5100->pdata.ldo_ena);
2649 }
2650err_enable:
2651 regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
2652 wm5100->core_supplies);
Mark Brownbd132ec2011-10-23 11:10:45 +01002653err_regmap:
2654 regmap_exit(wm5100->regmap);
Mark Browna81b82c2011-11-24 18:28:51 +00002655err:
Mark Brownbd132ec2011-10-23 11:10:45 +01002656 return ret;
Mark Brown6d4baf02011-09-20 15:44:21 +01002657}
2658
Mark Brown09452f22012-01-18 15:05:46 +00002659static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
Mark Brown6d4baf02011-09-20 15:44:21 +01002660{
Mark Brown09452f22012-01-18 15:05:46 +00002661 struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
Mark Brownbd132ec2011-10-23 11:10:45 +01002662
Mark Brown09452f22012-01-18 15:05:46 +00002663 snd_soc_unregister_codec(&i2c->dev);
2664 if (i2c->irq)
2665 free_irq(i2c->irq, wm5100);
2666 wm5100_free_gpio(i2c);
Mark Brown588ac5e2011-11-09 16:12:04 +00002667 if (wm5100->pdata.reset) {
Mark Brown26887382012-01-17 19:18:27 +00002668 gpio_set_value_cansleep(wm5100->pdata.reset, 0);
Mark Brown588ac5e2011-11-09 16:12:04 +00002669 gpio_free(wm5100->pdata.reset);
2670 }
2671 if (wm5100->pdata.ldo_ena) {
2672 gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
2673 gpio_free(wm5100->pdata.ldo_ena);
2674 }
Mark Brownbd132ec2011-10-23 11:10:45 +01002675 regmap_exit(wm5100->regmap);
Mark Brownbd132ec2011-10-23 11:10:45 +01002676
Mark Brown6d4baf02011-09-20 15:44:21 +01002677 return 0;
2678}
2679
Mark Brown62c1c402012-01-26 17:28:49 +00002680#ifdef CONFIG_PM_RUNTIME
2681static int wm5100_runtime_suspend(struct device *dev)
2682{
2683 struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
2684
2685 regcache_cache_only(wm5100->regmap, true);
2686 regcache_mark_dirty(wm5100->regmap);
2687 if (wm5100->pdata.ldo_ena)
2688 gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
2689 regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
2690 wm5100->core_supplies);
2691
2692 return 0;
2693}
2694
2695static int wm5100_runtime_resume(struct device *dev)
2696{
2697 struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
2698 int ret;
2699
2700 ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
2701 wm5100->core_supplies);
2702 if (ret != 0) {
2703 dev_err(dev, "Failed to enable supplies: %d\n",
2704 ret);
2705 return ret;
2706 }
2707
2708 if (wm5100->pdata.ldo_ena) {
2709 gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1);
2710 msleep(2);
2711 }
2712
2713 regcache_cache_only(wm5100->regmap, false);
2714 regcache_sync(wm5100->regmap);
2715
2716 return 0;
2717}
2718#endif
2719
2720static struct dev_pm_ops wm5100_pm = {
2721 SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume,
2722 NULL)
2723};
2724
Mark Brown6d4baf02011-09-20 15:44:21 +01002725static const struct i2c_device_id wm5100_i2c_id[] = {
2726 { "wm5100", 0 },
2727 { }
2728};
2729MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id);
2730
2731static struct i2c_driver wm5100_i2c_driver = {
2732 .driver = {
2733 .name = "wm5100",
2734 .owner = THIS_MODULE,
Mark Brown62c1c402012-01-26 17:28:49 +00002735 .pm = &wm5100_pm,
Mark Brown6d4baf02011-09-20 15:44:21 +01002736 },
2737 .probe = wm5100_i2c_probe,
2738 .remove = __devexit_p(wm5100_i2c_remove),
2739 .id_table = wm5100_i2c_id,
2740};
2741
2742static int __init wm5100_modinit(void)
2743{
2744 return i2c_add_driver(&wm5100_i2c_driver);
2745}
2746module_init(wm5100_modinit);
2747
2748static void __exit wm5100_exit(void)
2749{
2750 i2c_del_driver(&wm5100_i2c_driver);
2751}
2752module_exit(wm5100_exit);
2753
2754MODULE_DESCRIPTION("ASoC WM5100 driver");
2755MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2756MODULE_LICENSE("GPL");