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