blob: 1eafaae7d589852cc8478aa1c65ee9a059e55b46 [file] [log] [blame]
Mark Brownd5315a22012-01-25 19:29:41 +00001/*
2 * wm2200.c -- WM2200 ALSA SoC Audio driver
3 *
4 * Copyright 2012 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>
21#include <linux/pm_runtime.h>
22#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>
29#include <sound/jack.h>
30#include <sound/initval.h>
31#include <sound/tlv.h>
32#include <sound/wm2200.h>
33
34#include "wm2200.h"
35
36/* The code assumes DCVDD is generated internally */
37#define WM2200_NUM_CORE_SUPPLIES 2
38static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = {
39 "DBVDD",
40 "LDOVDD",
41};
42
43struct wm2200_fll {
44 int fref;
45 int fout;
46 int src;
47 struct completion lock;
48};
49
50/* codec private data */
51struct wm2200_priv {
52 struct regmap *regmap;
53 struct device *dev;
54 struct snd_soc_codec *codec;
55 struct wm2200_pdata pdata;
56 struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES];
57
58 struct completion fll_lock;
59 int fll_fout;
60 int fll_fref;
61 int fll_src;
62
63 int rev;
64 int sysclk;
65};
66
Mark Browneae23282012-10-02 20:14:49 +010067#define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1)
68#define WM2200_DSP_SPACING 12288
69
70#define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING))
71#define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING))
72#define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING))
73#define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING))
74#define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING))
75#define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING))
76
77static const struct regmap_range_cfg wm2200_ranges[] = {
78 /* DSP1 DM */
79 { .range_min = WM2200_DSP1_DM_BASE,
80 .range_max = WM2200_DSP1_DM_BASE + 12287,
81 .selector_reg = WM2200_DSP1_CONTROL_3,
82 .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK,
83 .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT,
84 .window_start = WM2200_DSP1_DM_0, .window_len = 2048, },
85
86 /* DSP1 PM */
87 { .range_min = WM2200_DSP1_PM_BASE,
88 .range_max = WM2200_DSP1_PM_BASE + 12287,
89 .selector_reg = WM2200_DSP1_CONTROL_2,
90 .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK,
91 .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT,
92 .window_start = WM2200_DSP1_PM_0, .window_len = 768, },
93
94 /* DSP1 ZM */
95 { .range_min = WM2200_DSP1_ZM_BASE,
96 .range_max = WM2200_DSP1_ZM_BASE + 2047,
97 .selector_reg = WM2200_DSP1_CONTROL_4,
98 .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK,
99 .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT,
100 .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, },
101
102 /* DSP2 DM */
103 { .range_min = WM2200_DSP2_DM_BASE,
104 .range_max = WM2200_DSP2_DM_BASE + 4095,
105 .selector_reg = WM2200_DSP2_CONTROL_3,
106 .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK,
107 .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT,
108 .window_start = WM2200_DSP2_DM_0, .window_len = 2048, },
109
110 /* DSP2 PM */
111 { .range_min = WM2200_DSP2_PM_BASE,
112 .range_max = WM2200_DSP2_PM_BASE + 11287,
113 .selector_reg = WM2200_DSP2_CONTROL_2,
114 .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK,
115 .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT,
116 .window_start = WM2200_DSP2_PM_0, .window_len = 768, },
117
118 /* DSP2 ZM */
119 { .range_min = WM2200_DSP2_ZM_BASE,
120 .range_max = WM2200_DSP2_ZM_BASE + 2047,
121 .selector_reg = WM2200_DSP2_CONTROL_4,
122 .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK,
123 .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT,
124 .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, },
125};
126
Mark Brownd5315a22012-01-25 19:29:41 +0000127static struct reg_default wm2200_reg_defaults[] = {
Mark Brownffa8d9d2012-01-29 21:45:31 +0000128 { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */
129 { 0x0102, 0x0000 }, /* R258 - Clocking 3 */
130 { 0x0103, 0x0011 }, /* R259 - Clocking 4 */
131 { 0x0111, 0x0000 }, /* R273 - FLL Control 1 */
132 { 0x0112, 0x0000 }, /* R274 - FLL Control 2 */
133 { 0x0113, 0x0000 }, /* R275 - FLL Control 3 */
134 { 0x0114, 0x0000 }, /* R276 - FLL Control 4 */
135 { 0x0116, 0x0177 }, /* R278 - FLL Control 6 */
136 { 0x0117, 0x0004 }, /* R279 - FLL Control 7 */
137 { 0x0119, 0x0000 }, /* R281 - FLL EFS 1 */
138 { 0x011A, 0x0002 }, /* R282 - FLL EFS 2 */
139 { 0x0200, 0x0000 }, /* R512 - Mic Charge Pump 1 */
140 { 0x0201, 0x03FF }, /* R513 - Mic Charge Pump 2 */
141 { 0x0202, 0x9BDE }, /* R514 - DM Charge Pump 1 */
142 { 0x020C, 0x0000 }, /* R524 - Mic Bias Ctrl 1 */
143 { 0x020D, 0x0000 }, /* R525 - Mic Bias Ctrl 2 */
144 { 0x020F, 0x0000 }, /* R527 - Ear Piece Ctrl 1 */
145 { 0x0210, 0x0000 }, /* R528 - Ear Piece Ctrl 2 */
146 { 0x0301, 0x0000 }, /* R769 - Input Enables */
147 { 0x0302, 0x2240 }, /* R770 - IN1L Control */
148 { 0x0303, 0x0040 }, /* R771 - IN1R Control */
149 { 0x0304, 0x2240 }, /* R772 - IN2L Control */
150 { 0x0305, 0x0040 }, /* R773 - IN2R Control */
151 { 0x0306, 0x2240 }, /* R774 - IN3L Control */
152 { 0x0307, 0x0040 }, /* R775 - IN3R Control */
153 { 0x030A, 0x0000 }, /* R778 - RXANC_SRC */
154 { 0x030B, 0x0022 }, /* R779 - Input Volume Ramp */
155 { 0x030C, 0x0180 }, /* R780 - ADC Digital Volume 1L */
156 { 0x030D, 0x0180 }, /* R781 - ADC Digital Volume 1R */
157 { 0x030E, 0x0180 }, /* R782 - ADC Digital Volume 2L */
158 { 0x030F, 0x0180 }, /* R783 - ADC Digital Volume 2R */
159 { 0x0310, 0x0180 }, /* R784 - ADC Digital Volume 3L */
160 { 0x0311, 0x0180 }, /* R785 - ADC Digital Volume 3R */
161 { 0x0400, 0x0000 }, /* R1024 - Output Enables */
162 { 0x0401, 0x0000 }, /* R1025 - DAC Volume Limit 1L */
163 { 0x0402, 0x0000 }, /* R1026 - DAC Volume Limit 1R */
164 { 0x0403, 0x0000 }, /* R1027 - DAC Volume Limit 2L */
165 { 0x0404, 0x0000 }, /* R1028 - DAC Volume Limit 2R */
166 { 0x0409, 0x0000 }, /* R1033 - DAC AEC Control 1 */
167 { 0x040A, 0x0022 }, /* R1034 - Output Volume Ramp */
168 { 0x040B, 0x0180 }, /* R1035 - DAC Digital Volume 1L */
169 { 0x040C, 0x0180 }, /* R1036 - DAC Digital Volume 1R */
170 { 0x040D, 0x0180 }, /* R1037 - DAC Digital Volume 2L */
171 { 0x040E, 0x0180 }, /* R1038 - DAC Digital Volume 2R */
172 { 0x0417, 0x0069 }, /* R1047 - PDM 1 */
173 { 0x0418, 0x0000 }, /* R1048 - PDM 2 */
174 { 0x0500, 0x0000 }, /* R1280 - Audio IF 1_1 */
175 { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */
176 { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */
177 { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */
178 { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */
179 { 0x0505, 0x0001 }, /* R1285 - Audio IF 1_6 */
180 { 0x0506, 0x0001 }, /* R1286 - Audio IF 1_7 */
181 { 0x0507, 0x0000 }, /* R1287 - Audio IF 1_8 */
182 { 0x0508, 0x0000 }, /* R1288 - Audio IF 1_9 */
183 { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */
184 { 0x050A, 0x0000 }, /* R1290 - Audio IF 1_11 */
185 { 0x050B, 0x0000 }, /* R1291 - Audio IF 1_12 */
186 { 0x050C, 0x0000 }, /* R1292 - Audio IF 1_13 */
187 { 0x050D, 0x0000 }, /* R1293 - Audio IF 1_14 */
188 { 0x050E, 0x0000 }, /* R1294 - Audio IF 1_15 */
189 { 0x050F, 0x0000 }, /* R1295 - Audio IF 1_16 */
190 { 0x0510, 0x0000 }, /* R1296 - Audio IF 1_17 */
191 { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */
192 { 0x0512, 0x0000 }, /* R1298 - Audio IF 1_19 */
193 { 0x0513, 0x0000 }, /* R1299 - Audio IF 1_20 */
194 { 0x0514, 0x0000 }, /* R1300 - Audio IF 1_21 */
195 { 0x0515, 0x0001 }, /* R1301 - Audio IF 1_22 */
196 { 0x0600, 0x0000 }, /* R1536 - OUT1LMIX Input 1 Source */
197 { 0x0601, 0x0080 }, /* R1537 - OUT1LMIX Input 1 Volume */
198 { 0x0602, 0x0000 }, /* R1538 - OUT1LMIX Input 2 Source */
199 { 0x0603, 0x0080 }, /* R1539 - OUT1LMIX Input 2 Volume */
200 { 0x0604, 0x0000 }, /* R1540 - OUT1LMIX Input 3 Source */
201 { 0x0605, 0x0080 }, /* R1541 - OUT1LMIX Input 3 Volume */
202 { 0x0606, 0x0000 }, /* R1542 - OUT1LMIX Input 4 Source */
203 { 0x0607, 0x0080 }, /* R1543 - OUT1LMIX Input 4 Volume */
204 { 0x0608, 0x0000 }, /* R1544 - OUT1RMIX Input 1 Source */
205 { 0x0609, 0x0080 }, /* R1545 - OUT1RMIX Input 1 Volume */
206 { 0x060A, 0x0000 }, /* R1546 - OUT1RMIX Input 2 Source */
207 { 0x060B, 0x0080 }, /* R1547 - OUT1RMIX Input 2 Volume */
208 { 0x060C, 0x0000 }, /* R1548 - OUT1RMIX Input 3 Source */
209 { 0x060D, 0x0080 }, /* R1549 - OUT1RMIX Input 3 Volume */
210 { 0x060E, 0x0000 }, /* R1550 - OUT1RMIX Input 4 Source */
211 { 0x060F, 0x0080 }, /* R1551 - OUT1RMIX Input 4 Volume */
212 { 0x0610, 0x0000 }, /* R1552 - OUT2LMIX Input 1 Source */
213 { 0x0611, 0x0080 }, /* R1553 - OUT2LMIX Input 1 Volume */
214 { 0x0612, 0x0000 }, /* R1554 - OUT2LMIX Input 2 Source */
215 { 0x0613, 0x0080 }, /* R1555 - OUT2LMIX Input 2 Volume */
216 { 0x0614, 0x0000 }, /* R1556 - OUT2LMIX Input 3 Source */
217 { 0x0615, 0x0080 }, /* R1557 - OUT2LMIX Input 3 Volume */
218 { 0x0616, 0x0000 }, /* R1558 - OUT2LMIX Input 4 Source */
219 { 0x0617, 0x0080 }, /* R1559 - OUT2LMIX Input 4 Volume */
220 { 0x0618, 0x0000 }, /* R1560 - OUT2RMIX Input 1 Source */
221 { 0x0619, 0x0080 }, /* R1561 - OUT2RMIX Input 1 Volume */
222 { 0x061A, 0x0000 }, /* R1562 - OUT2RMIX Input 2 Source */
223 { 0x061B, 0x0080 }, /* R1563 - OUT2RMIX Input 2 Volume */
224 { 0x061C, 0x0000 }, /* R1564 - OUT2RMIX Input 3 Source */
225 { 0x061D, 0x0080 }, /* R1565 - OUT2RMIX Input 3 Volume */
226 { 0x061E, 0x0000 }, /* R1566 - OUT2RMIX Input 4 Source */
227 { 0x061F, 0x0080 }, /* R1567 - OUT2RMIX Input 4 Volume */
228 { 0x0620, 0x0000 }, /* R1568 - AIF1TX1MIX Input 1 Source */
229 { 0x0621, 0x0080 }, /* R1569 - AIF1TX1MIX Input 1 Volume */
230 { 0x0622, 0x0000 }, /* R1570 - AIF1TX1MIX Input 2 Source */
231 { 0x0623, 0x0080 }, /* R1571 - AIF1TX1MIX Input 2 Volume */
232 { 0x0624, 0x0000 }, /* R1572 - AIF1TX1MIX Input 3 Source */
233 { 0x0625, 0x0080 }, /* R1573 - AIF1TX1MIX Input 3 Volume */
234 { 0x0626, 0x0000 }, /* R1574 - AIF1TX1MIX Input 4 Source */
235 { 0x0627, 0x0080 }, /* R1575 - AIF1TX1MIX Input 4 Volume */
236 { 0x0628, 0x0000 }, /* R1576 - AIF1TX2MIX Input 1 Source */
237 { 0x0629, 0x0080 }, /* R1577 - AIF1TX2MIX Input 1 Volume */
238 { 0x062A, 0x0000 }, /* R1578 - AIF1TX2MIX Input 2 Source */
239 { 0x062B, 0x0080 }, /* R1579 - AIF1TX2MIX Input 2 Volume */
240 { 0x062C, 0x0000 }, /* R1580 - AIF1TX2MIX Input 3 Source */
241 { 0x062D, 0x0080 }, /* R1581 - AIF1TX2MIX Input 3 Volume */
242 { 0x062E, 0x0000 }, /* R1582 - AIF1TX2MIX Input 4 Source */
243 { 0x062F, 0x0080 }, /* R1583 - AIF1TX2MIX Input 4 Volume */
244 { 0x0630, 0x0000 }, /* R1584 - AIF1TX3MIX Input 1 Source */
245 { 0x0631, 0x0080 }, /* R1585 - AIF1TX3MIX Input 1 Volume */
246 { 0x0632, 0x0000 }, /* R1586 - AIF1TX3MIX Input 2 Source */
247 { 0x0633, 0x0080 }, /* R1587 - AIF1TX3MIX Input 2 Volume */
248 { 0x0634, 0x0000 }, /* R1588 - AIF1TX3MIX Input 3 Source */
249 { 0x0635, 0x0080 }, /* R1589 - AIF1TX3MIX Input 3 Volume */
250 { 0x0636, 0x0000 }, /* R1590 - AIF1TX3MIX Input 4 Source */
251 { 0x0637, 0x0080 }, /* R1591 - AIF1TX3MIX Input 4 Volume */
252 { 0x0638, 0x0000 }, /* R1592 - AIF1TX4MIX Input 1 Source */
253 { 0x0639, 0x0080 }, /* R1593 - AIF1TX4MIX Input 1 Volume */
254 { 0x063A, 0x0000 }, /* R1594 - AIF1TX4MIX Input 2 Source */
255 { 0x063B, 0x0080 }, /* R1595 - AIF1TX4MIX Input 2 Volume */
256 { 0x063C, 0x0000 }, /* R1596 - AIF1TX4MIX Input 3 Source */
257 { 0x063D, 0x0080 }, /* R1597 - AIF1TX4MIX Input 3 Volume */
258 { 0x063E, 0x0000 }, /* R1598 - AIF1TX4MIX Input 4 Source */
259 { 0x063F, 0x0080 }, /* R1599 - AIF1TX4MIX Input 4 Volume */
260 { 0x0640, 0x0000 }, /* R1600 - AIF1TX5MIX Input 1 Source */
261 { 0x0641, 0x0080 }, /* R1601 - AIF1TX5MIX Input 1 Volume */
262 { 0x0642, 0x0000 }, /* R1602 - AIF1TX5MIX Input 2 Source */
263 { 0x0643, 0x0080 }, /* R1603 - AIF1TX5MIX Input 2 Volume */
264 { 0x0644, 0x0000 }, /* R1604 - AIF1TX5MIX Input 3 Source */
265 { 0x0645, 0x0080 }, /* R1605 - AIF1TX5MIX Input 3 Volume */
266 { 0x0646, 0x0000 }, /* R1606 - AIF1TX5MIX Input 4 Source */
267 { 0x0647, 0x0080 }, /* R1607 - AIF1TX5MIX Input 4 Volume */
268 { 0x0648, 0x0000 }, /* R1608 - AIF1TX6MIX Input 1 Source */
269 { 0x0649, 0x0080 }, /* R1609 - AIF1TX6MIX Input 1 Volume */
270 { 0x064A, 0x0000 }, /* R1610 - AIF1TX6MIX Input 2 Source */
271 { 0x064B, 0x0080 }, /* R1611 - AIF1TX6MIX Input 2 Volume */
272 { 0x064C, 0x0000 }, /* R1612 - AIF1TX6MIX Input 3 Source */
273 { 0x064D, 0x0080 }, /* R1613 - AIF1TX6MIX Input 3 Volume */
274 { 0x064E, 0x0000 }, /* R1614 - AIF1TX6MIX Input 4 Source */
275 { 0x064F, 0x0080 }, /* R1615 - AIF1TX6MIX Input 4 Volume */
276 { 0x0650, 0x0000 }, /* R1616 - EQLMIX Input 1 Source */
277 { 0x0651, 0x0080 }, /* R1617 - EQLMIX Input 1 Volume */
278 { 0x0652, 0x0000 }, /* R1618 - EQLMIX Input 2 Source */
279 { 0x0653, 0x0080 }, /* R1619 - EQLMIX Input 2 Volume */
280 { 0x0654, 0x0000 }, /* R1620 - EQLMIX Input 3 Source */
281 { 0x0655, 0x0080 }, /* R1621 - EQLMIX Input 3 Volume */
282 { 0x0656, 0x0000 }, /* R1622 - EQLMIX Input 4 Source */
283 { 0x0657, 0x0080 }, /* R1623 - EQLMIX Input 4 Volume */
284 { 0x0658, 0x0000 }, /* R1624 - EQRMIX Input 1 Source */
285 { 0x0659, 0x0080 }, /* R1625 - EQRMIX Input 1 Volume */
286 { 0x065A, 0x0000 }, /* R1626 - EQRMIX Input 2 Source */
287 { 0x065B, 0x0080 }, /* R1627 - EQRMIX Input 2 Volume */
288 { 0x065C, 0x0000 }, /* R1628 - EQRMIX Input 3 Source */
289 { 0x065D, 0x0080 }, /* R1629 - EQRMIX Input 3 Volume */
290 { 0x065E, 0x0000 }, /* R1630 - EQRMIX Input 4 Source */
291 { 0x065F, 0x0080 }, /* R1631 - EQRMIX Input 4 Volume */
292 { 0x0660, 0x0000 }, /* R1632 - LHPF1MIX Input 1 Source */
293 { 0x0661, 0x0080 }, /* R1633 - LHPF1MIX Input 1 Volume */
294 { 0x0662, 0x0000 }, /* R1634 - LHPF1MIX Input 2 Source */
295 { 0x0663, 0x0080 }, /* R1635 - LHPF1MIX Input 2 Volume */
296 { 0x0664, 0x0000 }, /* R1636 - LHPF1MIX Input 3 Source */
297 { 0x0665, 0x0080 }, /* R1637 - LHPF1MIX Input 3 Volume */
298 { 0x0666, 0x0000 }, /* R1638 - LHPF1MIX Input 4 Source */
299 { 0x0667, 0x0080 }, /* R1639 - LHPF1MIX Input 4 Volume */
300 { 0x0668, 0x0000 }, /* R1640 - LHPF2MIX Input 1 Source */
301 { 0x0669, 0x0080 }, /* R1641 - LHPF2MIX Input 1 Volume */
302 { 0x066A, 0x0000 }, /* R1642 - LHPF2MIX Input 2 Source */
303 { 0x066B, 0x0080 }, /* R1643 - LHPF2MIX Input 2 Volume */
304 { 0x066C, 0x0000 }, /* R1644 - LHPF2MIX Input 3 Source */
305 { 0x066D, 0x0080 }, /* R1645 - LHPF2MIX Input 3 Volume */
306 { 0x066E, 0x0000 }, /* R1646 - LHPF2MIX Input 4 Source */
307 { 0x066F, 0x0080 }, /* R1647 - LHPF2MIX Input 4 Volume */
308 { 0x0670, 0x0000 }, /* R1648 - DSP1LMIX Input 1 Source */
309 { 0x0671, 0x0080 }, /* R1649 - DSP1LMIX Input 1 Volume */
310 { 0x0672, 0x0000 }, /* R1650 - DSP1LMIX Input 2 Source */
311 { 0x0673, 0x0080 }, /* R1651 - DSP1LMIX Input 2 Volume */
312 { 0x0674, 0x0000 }, /* R1652 - DSP1LMIX Input 3 Source */
313 { 0x0675, 0x0080 }, /* R1653 - DSP1LMIX Input 3 Volume */
314 { 0x0676, 0x0000 }, /* R1654 - DSP1LMIX Input 4 Source */
315 { 0x0677, 0x0080 }, /* R1655 - DSP1LMIX Input 4 Volume */
316 { 0x0678, 0x0000 }, /* R1656 - DSP1RMIX Input 1 Source */
317 { 0x0679, 0x0080 }, /* R1657 - DSP1RMIX Input 1 Volume */
318 { 0x067A, 0x0000 }, /* R1658 - DSP1RMIX Input 2 Source */
319 { 0x067B, 0x0080 }, /* R1659 - DSP1RMIX Input 2 Volume */
320 { 0x067C, 0x0000 }, /* R1660 - DSP1RMIX Input 3 Source */
321 { 0x067D, 0x0080 }, /* R1661 - DSP1RMIX Input 3 Volume */
322 { 0x067E, 0x0000 }, /* R1662 - DSP1RMIX Input 4 Source */
323 { 0x067F, 0x0080 }, /* R1663 - DSP1RMIX Input 4 Volume */
324 { 0x0680, 0x0000 }, /* R1664 - DSP1AUX1MIX Input 1 Source */
325 { 0x0681, 0x0000 }, /* R1665 - DSP1AUX2MIX Input 1 Source */
326 { 0x0682, 0x0000 }, /* R1666 - DSP1AUX3MIX Input 1 Source */
327 { 0x0683, 0x0000 }, /* R1667 - DSP1AUX4MIX Input 1 Source */
328 { 0x0684, 0x0000 }, /* R1668 - DSP1AUX5MIX Input 1 Source */
329 { 0x0685, 0x0000 }, /* R1669 - DSP1AUX6MIX Input 1 Source */
330 { 0x0686, 0x0000 }, /* R1670 - DSP2LMIX Input 1 Source */
331 { 0x0687, 0x0080 }, /* R1671 - DSP2LMIX Input 1 Volume */
332 { 0x0688, 0x0000 }, /* R1672 - DSP2LMIX Input 2 Source */
333 { 0x0689, 0x0080 }, /* R1673 - DSP2LMIX Input 2 Volume */
334 { 0x068A, 0x0000 }, /* R1674 - DSP2LMIX Input 3 Source */
335 { 0x068B, 0x0080 }, /* R1675 - DSP2LMIX Input 3 Volume */
336 { 0x068C, 0x0000 }, /* R1676 - DSP2LMIX Input 4 Source */
337 { 0x068D, 0x0080 }, /* R1677 - DSP2LMIX Input 4 Volume */
338 { 0x068E, 0x0000 }, /* R1678 - DSP2RMIX Input 1 Source */
339 { 0x068F, 0x0080 }, /* R1679 - DSP2RMIX Input 1 Volume */
340 { 0x0690, 0x0000 }, /* R1680 - DSP2RMIX Input 2 Source */
341 { 0x0691, 0x0080 }, /* R1681 - DSP2RMIX Input 2 Volume */
342 { 0x0692, 0x0000 }, /* R1682 - DSP2RMIX Input 3 Source */
343 { 0x0693, 0x0080 }, /* R1683 - DSP2RMIX Input 3 Volume */
344 { 0x0694, 0x0000 }, /* R1684 - DSP2RMIX Input 4 Source */
345 { 0x0695, 0x0080 }, /* R1685 - DSP2RMIX Input 4 Volume */
346 { 0x0696, 0x0000 }, /* R1686 - DSP2AUX1MIX Input 1 Source */
347 { 0x0697, 0x0000 }, /* R1687 - DSP2AUX2MIX Input 1 Source */
348 { 0x0698, 0x0000 }, /* R1688 - DSP2AUX3MIX Input 1 Source */
349 { 0x0699, 0x0000 }, /* R1689 - DSP2AUX4MIX Input 1 Source */
350 { 0x069A, 0x0000 }, /* R1690 - DSP2AUX5MIX Input 1 Source */
351 { 0x069B, 0x0000 }, /* R1691 - DSP2AUX6MIX Input 1 Source */
352 { 0x0700, 0xA101 }, /* R1792 - GPIO CTRL 1 */
353 { 0x0701, 0xA101 }, /* R1793 - GPIO CTRL 2 */
354 { 0x0702, 0xA101 }, /* R1794 - GPIO CTRL 3 */
355 { 0x0703, 0xA101 }, /* R1795 - GPIO CTRL 4 */
356 { 0x0709, 0x0000 }, /* R1801 - Misc Pad Ctrl 1 */
357 { 0x0801, 0x00FF }, /* R2049 - Interrupt Status 1 Mask */
358 { 0x0804, 0xFFFF }, /* R2052 - Interrupt Status 2 Mask */
359 { 0x0808, 0x0000 }, /* R2056 - Interrupt Control */
360 { 0x0900, 0x0000 }, /* R2304 - EQL_1 */
361 { 0x0901, 0x0000 }, /* R2305 - EQL_2 */
362 { 0x0902, 0x0000 }, /* R2306 - EQL_3 */
363 { 0x0903, 0x0000 }, /* R2307 - EQL_4 */
364 { 0x0904, 0x0000 }, /* R2308 - EQL_5 */
365 { 0x0905, 0x0000 }, /* R2309 - EQL_6 */
366 { 0x0906, 0x0000 }, /* R2310 - EQL_7 */
367 { 0x0907, 0x0000 }, /* R2311 - EQL_8 */
368 { 0x0908, 0x0000 }, /* R2312 - EQL_9 */
369 { 0x0909, 0x0000 }, /* R2313 - EQL_10 */
370 { 0x090A, 0x0000 }, /* R2314 - EQL_11 */
371 { 0x090B, 0x0000 }, /* R2315 - EQL_12 */
372 { 0x090C, 0x0000 }, /* R2316 - EQL_13 */
373 { 0x090D, 0x0000 }, /* R2317 - EQL_14 */
374 { 0x090E, 0x0000 }, /* R2318 - EQL_15 */
375 { 0x090F, 0x0000 }, /* R2319 - EQL_16 */
376 { 0x0910, 0x0000 }, /* R2320 - EQL_17 */
377 { 0x0911, 0x0000 }, /* R2321 - EQL_18 */
378 { 0x0912, 0x0000 }, /* R2322 - EQL_19 */
379 { 0x0913, 0x0000 }, /* R2323 - EQL_20 */
380 { 0x0916, 0x0000 }, /* R2326 - EQR_1 */
381 { 0x0917, 0x0000 }, /* R2327 - EQR_2 */
382 { 0x0918, 0x0000 }, /* R2328 - EQR_3 */
383 { 0x0919, 0x0000 }, /* R2329 - EQR_4 */
384 { 0x091A, 0x0000 }, /* R2330 - EQR_5 */
385 { 0x091B, 0x0000 }, /* R2331 - EQR_6 */
386 { 0x091C, 0x0000 }, /* R2332 - EQR_7 */
387 { 0x091D, 0x0000 }, /* R2333 - EQR_8 */
388 { 0x091E, 0x0000 }, /* R2334 - EQR_9 */
389 { 0x091F, 0x0000 }, /* R2335 - EQR_10 */
390 { 0x0920, 0x0000 }, /* R2336 - EQR_11 */
391 { 0x0921, 0x0000 }, /* R2337 - EQR_12 */
392 { 0x0922, 0x0000 }, /* R2338 - EQR_13 */
393 { 0x0923, 0x0000 }, /* R2339 - EQR_14 */
394 { 0x0924, 0x0000 }, /* R2340 - EQR_15 */
395 { 0x0925, 0x0000 }, /* R2341 - EQR_16 */
396 { 0x0926, 0x0000 }, /* R2342 - EQR_17 */
397 { 0x0927, 0x0000 }, /* R2343 - EQR_18 */
398 { 0x0928, 0x0000 }, /* R2344 - EQR_19 */
399 { 0x0929, 0x0000 }, /* R2345 - EQR_20 */
400 { 0x093E, 0x0000 }, /* R2366 - HPLPF1_1 */
401 { 0x093F, 0x0000 }, /* R2367 - HPLPF1_2 */
402 { 0x0942, 0x0000 }, /* R2370 - HPLPF2_1 */
403 { 0x0943, 0x0000 }, /* R2371 - HPLPF2_2 */
404 { 0x0A00, 0x0000 }, /* R2560 - DSP1 Control 1 */
405 { 0x0A02, 0x0000 }, /* R2562 - DSP1 Control 2 */
406 { 0x0A03, 0x0000 }, /* R2563 - DSP1 Control 3 */
407 { 0x0A04, 0x0000 }, /* R2564 - DSP1 Control 4 */
408 { 0x0A06, 0x0000 }, /* R2566 - DSP1 Control 5 */
409 { 0x0A07, 0x0000 }, /* R2567 - DSP1 Control 6 */
410 { 0x0A08, 0x0000 }, /* R2568 - DSP1 Control 7 */
411 { 0x0A09, 0x0000 }, /* R2569 - DSP1 Control 8 */
412 { 0x0A0A, 0x0000 }, /* R2570 - DSP1 Control 9 */
413 { 0x0A0B, 0x0000 }, /* R2571 - DSP1 Control 10 */
414 { 0x0A0C, 0x0000 }, /* R2572 - DSP1 Control 11 */
415 { 0x0A0D, 0x0000 }, /* R2573 - DSP1 Control 12 */
416 { 0x0A0F, 0x0000 }, /* R2575 - DSP1 Control 13 */
417 { 0x0A10, 0x0000 }, /* R2576 - DSP1 Control 14 */
418 { 0x0A11, 0x0000 }, /* R2577 - DSP1 Control 15 */
419 { 0x0A12, 0x0000 }, /* R2578 - DSP1 Control 16 */
420 { 0x0A13, 0x0000 }, /* R2579 - DSP1 Control 17 */
421 { 0x0A14, 0x0000 }, /* R2580 - DSP1 Control 18 */
422 { 0x0A16, 0x0000 }, /* R2582 - DSP1 Control 19 */
423 { 0x0A17, 0x0000 }, /* R2583 - DSP1 Control 20 */
424 { 0x0A18, 0x0000 }, /* R2584 - DSP1 Control 21 */
425 { 0x0A1A, 0x1800 }, /* R2586 - DSP1 Control 22 */
426 { 0x0A1B, 0x1000 }, /* R2587 - DSP1 Control 23 */
427 { 0x0A1C, 0x0400 }, /* R2588 - DSP1 Control 24 */
428 { 0x0A1E, 0x0000 }, /* R2590 - DSP1 Control 25 */
429 { 0x0A20, 0x0000 }, /* R2592 - DSP1 Control 26 */
430 { 0x0A21, 0x0000 }, /* R2593 - DSP1 Control 27 */
431 { 0x0A22, 0x0000 }, /* R2594 - DSP1 Control 28 */
432 { 0x0A23, 0x0000 }, /* R2595 - DSP1 Control 29 */
433 { 0x0A24, 0x0000 }, /* R2596 - DSP1 Control 30 */
434 { 0x0A26, 0x0000 }, /* R2598 - DSP1 Control 31 */
435 { 0x0B00, 0x0000 }, /* R2816 - DSP2 Control 1 */
436 { 0x0B02, 0x0000 }, /* R2818 - DSP2 Control 2 */
437 { 0x0B03, 0x0000 }, /* R2819 - DSP2 Control 3 */
438 { 0x0B04, 0x0000 }, /* R2820 - DSP2 Control 4 */
439 { 0x0B06, 0x0000 }, /* R2822 - DSP2 Control 5 */
440 { 0x0B07, 0x0000 }, /* R2823 - DSP2 Control 6 */
441 { 0x0B08, 0x0000 }, /* R2824 - DSP2 Control 7 */
442 { 0x0B09, 0x0000 }, /* R2825 - DSP2 Control 8 */
443 { 0x0B0A, 0x0000 }, /* R2826 - DSP2 Control 9 */
444 { 0x0B0B, 0x0000 }, /* R2827 - DSP2 Control 10 */
445 { 0x0B0C, 0x0000 }, /* R2828 - DSP2 Control 11 */
446 { 0x0B0D, 0x0000 }, /* R2829 - DSP2 Control 12 */
447 { 0x0B0F, 0x0000 }, /* R2831 - DSP2 Control 13 */
448 { 0x0B10, 0x0000 }, /* R2832 - DSP2 Control 14 */
449 { 0x0B11, 0x0000 }, /* R2833 - DSP2 Control 15 */
450 { 0x0B12, 0x0000 }, /* R2834 - DSP2 Control 16 */
451 { 0x0B13, 0x0000 }, /* R2835 - DSP2 Control 17 */
452 { 0x0B14, 0x0000 }, /* R2836 - DSP2 Control 18 */
453 { 0x0B16, 0x0000 }, /* R2838 - DSP2 Control 19 */
454 { 0x0B17, 0x0000 }, /* R2839 - DSP2 Control 20 */
455 { 0x0B18, 0x0000 }, /* R2840 - DSP2 Control 21 */
456 { 0x0B1A, 0x0800 }, /* R2842 - DSP2 Control 22 */
457 { 0x0B1B, 0x1000 }, /* R2843 - DSP2 Control 23 */
458 { 0x0B1C, 0x0400 }, /* R2844 - DSP2 Control 24 */
459 { 0x0B1E, 0x0000 }, /* R2846 - DSP2 Control 25 */
460 { 0x0B20, 0x0000 }, /* R2848 - DSP2 Control 26 */
461 { 0x0B21, 0x0000 }, /* R2849 - DSP2 Control 27 */
462 { 0x0B22, 0x0000 }, /* R2850 - DSP2 Control 28 */
463 { 0x0B23, 0x0000 }, /* R2851 - DSP2 Control 29 */
464 { 0x0B24, 0x0000 }, /* R2852 - DSP2 Control 30 */
465 { 0x0B26, 0x0000 }, /* R2854 - DSP2 Control 31 */
Mark Brownd5315a22012-01-25 19:29:41 +0000466};
467
468static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
469{
Mark Browneae23282012-10-02 20:14:49 +0100470 int i;
471
472 for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
473 if ((reg >= wm2200_ranges[i].window_start &&
474 reg <= wm2200_ranges[i].window_start +
475 wm2200_ranges[i].window_len) ||
476 (reg >= wm2200_ranges[i].range_min &&
477 reg <= wm2200_ranges[i].range_max))
478 return true;
479
Mark Brownd5315a22012-01-25 19:29:41 +0000480 switch (reg) {
481 case WM2200_SOFTWARE_RESET:
482 case WM2200_DEVICE_REVISION:
483 case WM2200_ADPS1_IRQ0:
484 case WM2200_ADPS1_IRQ1:
485 case WM2200_INTERRUPT_STATUS_1:
486 case WM2200_INTERRUPT_STATUS_2:
487 case WM2200_INTERRUPT_RAW_STATUS_2:
488 return true;
489 default:
490 return false;
491 }
492}
493
494static bool wm2200_readable_register(struct device *dev, unsigned int reg)
495{
Mark Browneae23282012-10-02 20:14:49 +0100496 int i;
497
498 for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
499 if ((reg >= wm2200_ranges[i].window_start &&
500 reg <= wm2200_ranges[i].window_start +
501 wm2200_ranges[i].window_len) ||
502 (reg >= wm2200_ranges[i].range_min &&
503 reg <= wm2200_ranges[i].range_max))
504 return true;
505
Mark Brownd5315a22012-01-25 19:29:41 +0000506 switch (reg) {
507 case WM2200_SOFTWARE_RESET:
508 case WM2200_DEVICE_REVISION:
509 case WM2200_TONE_GENERATOR_1:
510 case WM2200_CLOCKING_3:
511 case WM2200_CLOCKING_4:
512 case WM2200_FLL_CONTROL_1:
513 case WM2200_FLL_CONTROL_2:
514 case WM2200_FLL_CONTROL_3:
515 case WM2200_FLL_CONTROL_4:
516 case WM2200_FLL_CONTROL_6:
517 case WM2200_FLL_CONTROL_7:
518 case WM2200_FLL_EFS_1:
519 case WM2200_FLL_EFS_2:
520 case WM2200_MIC_CHARGE_PUMP_1:
521 case WM2200_MIC_CHARGE_PUMP_2:
522 case WM2200_DM_CHARGE_PUMP_1:
523 case WM2200_MIC_BIAS_CTRL_1:
524 case WM2200_MIC_BIAS_CTRL_2:
525 case WM2200_EAR_PIECE_CTRL_1:
526 case WM2200_EAR_PIECE_CTRL_2:
527 case WM2200_INPUT_ENABLES:
528 case WM2200_IN1L_CONTROL:
529 case WM2200_IN1R_CONTROL:
530 case WM2200_IN2L_CONTROL:
531 case WM2200_IN2R_CONTROL:
532 case WM2200_IN3L_CONTROL:
533 case WM2200_IN3R_CONTROL:
534 case WM2200_RXANC_SRC:
535 case WM2200_INPUT_VOLUME_RAMP:
536 case WM2200_ADC_DIGITAL_VOLUME_1L:
537 case WM2200_ADC_DIGITAL_VOLUME_1R:
538 case WM2200_ADC_DIGITAL_VOLUME_2L:
539 case WM2200_ADC_DIGITAL_VOLUME_2R:
540 case WM2200_ADC_DIGITAL_VOLUME_3L:
541 case WM2200_ADC_DIGITAL_VOLUME_3R:
542 case WM2200_OUTPUT_ENABLES:
543 case WM2200_DAC_VOLUME_LIMIT_1L:
544 case WM2200_DAC_VOLUME_LIMIT_1R:
545 case WM2200_DAC_VOLUME_LIMIT_2L:
546 case WM2200_DAC_VOLUME_LIMIT_2R:
547 case WM2200_DAC_AEC_CONTROL_1:
548 case WM2200_OUTPUT_VOLUME_RAMP:
549 case WM2200_DAC_DIGITAL_VOLUME_1L:
550 case WM2200_DAC_DIGITAL_VOLUME_1R:
551 case WM2200_DAC_DIGITAL_VOLUME_2L:
552 case WM2200_DAC_DIGITAL_VOLUME_2R:
553 case WM2200_PDM_1:
554 case WM2200_PDM_2:
555 case WM2200_AUDIO_IF_1_1:
556 case WM2200_AUDIO_IF_1_2:
557 case WM2200_AUDIO_IF_1_3:
558 case WM2200_AUDIO_IF_1_4:
559 case WM2200_AUDIO_IF_1_5:
560 case WM2200_AUDIO_IF_1_6:
561 case WM2200_AUDIO_IF_1_7:
562 case WM2200_AUDIO_IF_1_8:
563 case WM2200_AUDIO_IF_1_9:
564 case WM2200_AUDIO_IF_1_10:
565 case WM2200_AUDIO_IF_1_11:
566 case WM2200_AUDIO_IF_1_12:
567 case WM2200_AUDIO_IF_1_13:
568 case WM2200_AUDIO_IF_1_14:
569 case WM2200_AUDIO_IF_1_15:
570 case WM2200_AUDIO_IF_1_16:
571 case WM2200_AUDIO_IF_1_17:
572 case WM2200_AUDIO_IF_1_18:
573 case WM2200_AUDIO_IF_1_19:
574 case WM2200_AUDIO_IF_1_20:
575 case WM2200_AUDIO_IF_1_21:
576 case WM2200_AUDIO_IF_1_22:
577 case WM2200_OUT1LMIX_INPUT_1_SOURCE:
578 case WM2200_OUT1LMIX_INPUT_1_VOLUME:
579 case WM2200_OUT1LMIX_INPUT_2_SOURCE:
580 case WM2200_OUT1LMIX_INPUT_2_VOLUME:
581 case WM2200_OUT1LMIX_INPUT_3_SOURCE:
582 case WM2200_OUT1LMIX_INPUT_3_VOLUME:
583 case WM2200_OUT1LMIX_INPUT_4_SOURCE:
584 case WM2200_OUT1LMIX_INPUT_4_VOLUME:
585 case WM2200_OUT1RMIX_INPUT_1_SOURCE:
586 case WM2200_OUT1RMIX_INPUT_1_VOLUME:
587 case WM2200_OUT1RMIX_INPUT_2_SOURCE:
588 case WM2200_OUT1RMIX_INPUT_2_VOLUME:
589 case WM2200_OUT1RMIX_INPUT_3_SOURCE:
590 case WM2200_OUT1RMIX_INPUT_3_VOLUME:
591 case WM2200_OUT1RMIX_INPUT_4_SOURCE:
592 case WM2200_OUT1RMIX_INPUT_4_VOLUME:
593 case WM2200_OUT2LMIX_INPUT_1_SOURCE:
594 case WM2200_OUT2LMIX_INPUT_1_VOLUME:
595 case WM2200_OUT2LMIX_INPUT_2_SOURCE:
596 case WM2200_OUT2LMIX_INPUT_2_VOLUME:
597 case WM2200_OUT2LMIX_INPUT_3_SOURCE:
598 case WM2200_OUT2LMIX_INPUT_3_VOLUME:
599 case WM2200_OUT2LMIX_INPUT_4_SOURCE:
600 case WM2200_OUT2LMIX_INPUT_4_VOLUME:
601 case WM2200_OUT2RMIX_INPUT_1_SOURCE:
602 case WM2200_OUT2RMIX_INPUT_1_VOLUME:
603 case WM2200_OUT2RMIX_INPUT_2_SOURCE:
604 case WM2200_OUT2RMIX_INPUT_2_VOLUME:
605 case WM2200_OUT2RMIX_INPUT_3_SOURCE:
606 case WM2200_OUT2RMIX_INPUT_3_VOLUME:
607 case WM2200_OUT2RMIX_INPUT_4_SOURCE:
608 case WM2200_OUT2RMIX_INPUT_4_VOLUME:
609 case WM2200_AIF1TX1MIX_INPUT_1_SOURCE:
610 case WM2200_AIF1TX1MIX_INPUT_1_VOLUME:
611 case WM2200_AIF1TX1MIX_INPUT_2_SOURCE:
612 case WM2200_AIF1TX1MIX_INPUT_2_VOLUME:
613 case WM2200_AIF1TX1MIX_INPUT_3_SOURCE:
614 case WM2200_AIF1TX1MIX_INPUT_3_VOLUME:
615 case WM2200_AIF1TX1MIX_INPUT_4_SOURCE:
616 case WM2200_AIF1TX1MIX_INPUT_4_VOLUME:
617 case WM2200_AIF1TX2MIX_INPUT_1_SOURCE:
618 case WM2200_AIF1TX2MIX_INPUT_1_VOLUME:
619 case WM2200_AIF1TX2MIX_INPUT_2_SOURCE:
620 case WM2200_AIF1TX2MIX_INPUT_2_VOLUME:
621 case WM2200_AIF1TX2MIX_INPUT_3_SOURCE:
622 case WM2200_AIF1TX2MIX_INPUT_3_VOLUME:
623 case WM2200_AIF1TX2MIX_INPUT_4_SOURCE:
624 case WM2200_AIF1TX2MIX_INPUT_4_VOLUME:
625 case WM2200_AIF1TX3MIX_INPUT_1_SOURCE:
626 case WM2200_AIF1TX3MIX_INPUT_1_VOLUME:
627 case WM2200_AIF1TX3MIX_INPUT_2_SOURCE:
628 case WM2200_AIF1TX3MIX_INPUT_2_VOLUME:
629 case WM2200_AIF1TX3MIX_INPUT_3_SOURCE:
630 case WM2200_AIF1TX3MIX_INPUT_3_VOLUME:
631 case WM2200_AIF1TX3MIX_INPUT_4_SOURCE:
632 case WM2200_AIF1TX3MIX_INPUT_4_VOLUME:
633 case WM2200_AIF1TX4MIX_INPUT_1_SOURCE:
634 case WM2200_AIF1TX4MIX_INPUT_1_VOLUME:
635 case WM2200_AIF1TX4MIX_INPUT_2_SOURCE:
636 case WM2200_AIF1TX4MIX_INPUT_2_VOLUME:
637 case WM2200_AIF1TX4MIX_INPUT_3_SOURCE:
638 case WM2200_AIF1TX4MIX_INPUT_3_VOLUME:
639 case WM2200_AIF1TX4MIX_INPUT_4_SOURCE:
640 case WM2200_AIF1TX4MIX_INPUT_4_VOLUME:
641 case WM2200_AIF1TX5MIX_INPUT_1_SOURCE:
642 case WM2200_AIF1TX5MIX_INPUT_1_VOLUME:
643 case WM2200_AIF1TX5MIX_INPUT_2_SOURCE:
644 case WM2200_AIF1TX5MIX_INPUT_2_VOLUME:
645 case WM2200_AIF1TX5MIX_INPUT_3_SOURCE:
646 case WM2200_AIF1TX5MIX_INPUT_3_VOLUME:
647 case WM2200_AIF1TX5MIX_INPUT_4_SOURCE:
648 case WM2200_AIF1TX5MIX_INPUT_4_VOLUME:
649 case WM2200_AIF1TX6MIX_INPUT_1_SOURCE:
650 case WM2200_AIF1TX6MIX_INPUT_1_VOLUME:
651 case WM2200_AIF1TX6MIX_INPUT_2_SOURCE:
652 case WM2200_AIF1TX6MIX_INPUT_2_VOLUME:
653 case WM2200_AIF1TX6MIX_INPUT_3_SOURCE:
654 case WM2200_AIF1TX6MIX_INPUT_3_VOLUME:
655 case WM2200_AIF1TX6MIX_INPUT_4_SOURCE:
656 case WM2200_AIF1TX6MIX_INPUT_4_VOLUME:
657 case WM2200_EQLMIX_INPUT_1_SOURCE:
658 case WM2200_EQLMIX_INPUT_1_VOLUME:
659 case WM2200_EQLMIX_INPUT_2_SOURCE:
660 case WM2200_EQLMIX_INPUT_2_VOLUME:
661 case WM2200_EQLMIX_INPUT_3_SOURCE:
662 case WM2200_EQLMIX_INPUT_3_VOLUME:
663 case WM2200_EQLMIX_INPUT_4_SOURCE:
664 case WM2200_EQLMIX_INPUT_4_VOLUME:
665 case WM2200_EQRMIX_INPUT_1_SOURCE:
666 case WM2200_EQRMIX_INPUT_1_VOLUME:
667 case WM2200_EQRMIX_INPUT_2_SOURCE:
668 case WM2200_EQRMIX_INPUT_2_VOLUME:
669 case WM2200_EQRMIX_INPUT_3_SOURCE:
670 case WM2200_EQRMIX_INPUT_3_VOLUME:
671 case WM2200_EQRMIX_INPUT_4_SOURCE:
672 case WM2200_EQRMIX_INPUT_4_VOLUME:
673 case WM2200_LHPF1MIX_INPUT_1_SOURCE:
674 case WM2200_LHPF1MIX_INPUT_1_VOLUME:
675 case WM2200_LHPF1MIX_INPUT_2_SOURCE:
676 case WM2200_LHPF1MIX_INPUT_2_VOLUME:
677 case WM2200_LHPF1MIX_INPUT_3_SOURCE:
678 case WM2200_LHPF1MIX_INPUT_3_VOLUME:
679 case WM2200_LHPF1MIX_INPUT_4_SOURCE:
680 case WM2200_LHPF1MIX_INPUT_4_VOLUME:
681 case WM2200_LHPF2MIX_INPUT_1_SOURCE:
682 case WM2200_LHPF2MIX_INPUT_1_VOLUME:
683 case WM2200_LHPF2MIX_INPUT_2_SOURCE:
684 case WM2200_LHPF2MIX_INPUT_2_VOLUME:
685 case WM2200_LHPF2MIX_INPUT_3_SOURCE:
686 case WM2200_LHPF2MIX_INPUT_3_VOLUME:
687 case WM2200_LHPF2MIX_INPUT_4_SOURCE:
688 case WM2200_LHPF2MIX_INPUT_4_VOLUME:
689 case WM2200_DSP1LMIX_INPUT_1_SOURCE:
690 case WM2200_DSP1LMIX_INPUT_1_VOLUME:
691 case WM2200_DSP1LMIX_INPUT_2_SOURCE:
692 case WM2200_DSP1LMIX_INPUT_2_VOLUME:
693 case WM2200_DSP1LMIX_INPUT_3_SOURCE:
694 case WM2200_DSP1LMIX_INPUT_3_VOLUME:
695 case WM2200_DSP1LMIX_INPUT_4_SOURCE:
696 case WM2200_DSP1LMIX_INPUT_4_VOLUME:
697 case WM2200_DSP1RMIX_INPUT_1_SOURCE:
698 case WM2200_DSP1RMIX_INPUT_1_VOLUME:
699 case WM2200_DSP1RMIX_INPUT_2_SOURCE:
700 case WM2200_DSP1RMIX_INPUT_2_VOLUME:
701 case WM2200_DSP1RMIX_INPUT_3_SOURCE:
702 case WM2200_DSP1RMIX_INPUT_3_VOLUME:
703 case WM2200_DSP1RMIX_INPUT_4_SOURCE:
704 case WM2200_DSP1RMIX_INPUT_4_VOLUME:
705 case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE:
706 case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE:
707 case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE:
708 case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE:
709 case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE:
710 case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE:
711 case WM2200_DSP2LMIX_INPUT_1_SOURCE:
712 case WM2200_DSP2LMIX_INPUT_1_VOLUME:
713 case WM2200_DSP2LMIX_INPUT_2_SOURCE:
714 case WM2200_DSP2LMIX_INPUT_2_VOLUME:
715 case WM2200_DSP2LMIX_INPUT_3_SOURCE:
716 case WM2200_DSP2LMIX_INPUT_3_VOLUME:
717 case WM2200_DSP2LMIX_INPUT_4_SOURCE:
718 case WM2200_DSP2LMIX_INPUT_4_VOLUME:
719 case WM2200_DSP2RMIX_INPUT_1_SOURCE:
720 case WM2200_DSP2RMIX_INPUT_1_VOLUME:
721 case WM2200_DSP2RMIX_INPUT_2_SOURCE:
722 case WM2200_DSP2RMIX_INPUT_2_VOLUME:
723 case WM2200_DSP2RMIX_INPUT_3_SOURCE:
724 case WM2200_DSP2RMIX_INPUT_3_VOLUME:
725 case WM2200_DSP2RMIX_INPUT_4_SOURCE:
726 case WM2200_DSP2RMIX_INPUT_4_VOLUME:
727 case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE:
728 case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE:
729 case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE:
730 case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE:
731 case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE:
732 case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE:
733 case WM2200_GPIO_CTRL_1:
734 case WM2200_GPIO_CTRL_2:
735 case WM2200_GPIO_CTRL_3:
736 case WM2200_GPIO_CTRL_4:
737 case WM2200_ADPS1_IRQ0:
738 case WM2200_ADPS1_IRQ1:
739 case WM2200_MISC_PAD_CTRL_1:
740 case WM2200_INTERRUPT_STATUS_1:
741 case WM2200_INTERRUPT_STATUS_1_MASK:
742 case WM2200_INTERRUPT_STATUS_2:
743 case WM2200_INTERRUPT_RAW_STATUS_2:
744 case WM2200_INTERRUPT_STATUS_2_MASK:
745 case WM2200_INTERRUPT_CONTROL:
746 case WM2200_EQL_1:
747 case WM2200_EQL_2:
748 case WM2200_EQL_3:
749 case WM2200_EQL_4:
750 case WM2200_EQL_5:
751 case WM2200_EQL_6:
752 case WM2200_EQL_7:
753 case WM2200_EQL_8:
754 case WM2200_EQL_9:
755 case WM2200_EQL_10:
756 case WM2200_EQL_11:
757 case WM2200_EQL_12:
758 case WM2200_EQL_13:
759 case WM2200_EQL_14:
760 case WM2200_EQL_15:
761 case WM2200_EQL_16:
762 case WM2200_EQL_17:
763 case WM2200_EQL_18:
764 case WM2200_EQL_19:
765 case WM2200_EQL_20:
766 case WM2200_EQR_1:
767 case WM2200_EQR_2:
768 case WM2200_EQR_3:
769 case WM2200_EQR_4:
770 case WM2200_EQR_5:
771 case WM2200_EQR_6:
772 case WM2200_EQR_7:
773 case WM2200_EQR_8:
774 case WM2200_EQR_9:
775 case WM2200_EQR_10:
776 case WM2200_EQR_11:
777 case WM2200_EQR_12:
778 case WM2200_EQR_13:
779 case WM2200_EQR_14:
780 case WM2200_EQR_15:
781 case WM2200_EQR_16:
782 case WM2200_EQR_17:
783 case WM2200_EQR_18:
784 case WM2200_EQR_19:
785 case WM2200_EQR_20:
786 case WM2200_HPLPF1_1:
787 case WM2200_HPLPF1_2:
788 case WM2200_HPLPF2_1:
789 case WM2200_HPLPF2_2:
790 case WM2200_DSP1_CONTROL_1:
791 case WM2200_DSP1_CONTROL_2:
792 case WM2200_DSP1_CONTROL_3:
793 case WM2200_DSP1_CONTROL_4:
794 case WM2200_DSP1_CONTROL_5:
795 case WM2200_DSP1_CONTROL_6:
796 case WM2200_DSP1_CONTROL_7:
797 case WM2200_DSP1_CONTROL_8:
798 case WM2200_DSP1_CONTROL_9:
799 case WM2200_DSP1_CONTROL_10:
800 case WM2200_DSP1_CONTROL_11:
801 case WM2200_DSP1_CONTROL_12:
802 case WM2200_DSP1_CONTROL_13:
803 case WM2200_DSP1_CONTROL_14:
804 case WM2200_DSP1_CONTROL_15:
805 case WM2200_DSP1_CONTROL_16:
806 case WM2200_DSP1_CONTROL_17:
807 case WM2200_DSP1_CONTROL_18:
808 case WM2200_DSP1_CONTROL_19:
809 case WM2200_DSP1_CONTROL_20:
810 case WM2200_DSP1_CONTROL_21:
811 case WM2200_DSP1_CONTROL_22:
812 case WM2200_DSP1_CONTROL_23:
813 case WM2200_DSP1_CONTROL_24:
814 case WM2200_DSP1_CONTROL_25:
815 case WM2200_DSP1_CONTROL_26:
816 case WM2200_DSP1_CONTROL_27:
817 case WM2200_DSP1_CONTROL_28:
818 case WM2200_DSP1_CONTROL_29:
819 case WM2200_DSP1_CONTROL_30:
820 case WM2200_DSP1_CONTROL_31:
821 case WM2200_DSP2_CONTROL_1:
822 case WM2200_DSP2_CONTROL_2:
823 case WM2200_DSP2_CONTROL_3:
824 case WM2200_DSP2_CONTROL_4:
825 case WM2200_DSP2_CONTROL_5:
826 case WM2200_DSP2_CONTROL_6:
827 case WM2200_DSP2_CONTROL_7:
828 case WM2200_DSP2_CONTROL_8:
829 case WM2200_DSP2_CONTROL_9:
830 case WM2200_DSP2_CONTROL_10:
831 case WM2200_DSP2_CONTROL_11:
832 case WM2200_DSP2_CONTROL_12:
833 case WM2200_DSP2_CONTROL_13:
834 case WM2200_DSP2_CONTROL_14:
835 case WM2200_DSP2_CONTROL_15:
836 case WM2200_DSP2_CONTROL_16:
837 case WM2200_DSP2_CONTROL_17:
838 case WM2200_DSP2_CONTROL_18:
839 case WM2200_DSP2_CONTROL_19:
840 case WM2200_DSP2_CONTROL_20:
841 case WM2200_DSP2_CONTROL_21:
842 case WM2200_DSP2_CONTROL_22:
843 case WM2200_DSP2_CONTROL_23:
844 case WM2200_DSP2_CONTROL_24:
845 case WM2200_DSP2_CONTROL_25:
846 case WM2200_DSP2_CONTROL_26:
847 case WM2200_DSP2_CONTROL_27:
848 case WM2200_DSP2_CONTROL_28:
849 case WM2200_DSP2_CONTROL_29:
850 case WM2200_DSP2_CONTROL_30:
851 case WM2200_DSP2_CONTROL_31:
852 return true;
853 default:
854 return false;
855 }
856}
857
858static const struct reg_default wm2200_reva_patch[] = {
859 { 0x07, 0x0003 },
860 { 0x102, 0x0200 },
861 { 0x203, 0x0084 },
862 { 0x201, 0x83FF },
863 { 0x20C, 0x0062 },
864 { 0x20D, 0x0062 },
865 { 0x207, 0x2002 },
866 { 0x208, 0x20C0 },
867 { 0x21D, 0x01C0 },
868 { 0x50A, 0x0001 },
869 { 0x50B, 0x0002 },
870 { 0x50C, 0x0003 },
871 { 0x50D, 0x0004 },
872 { 0x50E, 0x0005 },
873 { 0x510, 0x0001 },
874 { 0x511, 0x0002 },
875 { 0x512, 0x0003 },
876 { 0x513, 0x0004 },
877 { 0x514, 0x0005 },
878 { 0x515, 0x0000 },
879 { 0x201, 0x8084 },
880 { 0x202, 0xBBDE },
881 { 0x203, 0x00EC },
882 { 0x500, 0x8000 },
883 { 0x507, 0x1820 },
884 { 0x508, 0x1820 },
885 { 0x505, 0x0300 },
886 { 0x506, 0x0300 },
887 { 0x302, 0x2280 },
888 { 0x303, 0x0080 },
889 { 0x304, 0x2280 },
890 { 0x305, 0x0080 },
891 { 0x306, 0x2280 },
892 { 0x307, 0x0080 },
893 { 0x401, 0x0080 },
894 { 0x402, 0x0080 },
895 { 0x417, 0x3069 },
896 { 0x900, 0x6318 },
897 { 0x901, 0x6300 },
898 { 0x902, 0x0FC8 },
899 { 0x903, 0x03FE },
900 { 0x904, 0x00E0 },
901 { 0x905, 0x1EC4 },
902 { 0x906, 0xF136 },
903 { 0x907, 0x0409 },
904 { 0x908, 0x04CC },
905 { 0x909, 0x1C9B },
906 { 0x90A, 0xF337 },
907 { 0x90B, 0x040B },
908 { 0x90C, 0x0CBB },
909 { 0x90D, 0x16F8 },
910 { 0x90E, 0xF7D9 },
911 { 0x90F, 0x040A },
912 { 0x910, 0x1F14 },
913 { 0x911, 0x058C },
914 { 0x912, 0x0563 },
915 { 0x913, 0x4000 },
916 { 0x916, 0x6318 },
917 { 0x917, 0x6300 },
918 { 0x918, 0x0FC8 },
919 { 0x919, 0x03FE },
920 { 0x91A, 0x00E0 },
921 { 0x91B, 0x1EC4 },
922 { 0x91C, 0xF136 },
923 { 0x91D, 0x0409 },
924 { 0x91E, 0x04CC },
925 { 0x91F, 0x1C9B },
926 { 0x920, 0xF337 },
927 { 0x921, 0x040B },
928 { 0x922, 0x0CBB },
929 { 0x923, 0x16F8 },
930 { 0x924, 0xF7D9 },
931 { 0x925, 0x040A },
932 { 0x926, 0x1F14 },
933 { 0x927, 0x058C },
934 { 0x928, 0x0563 },
935 { 0x929, 0x4000 },
936 { 0x709, 0x2000 },
937 { 0x207, 0x200E },
938 { 0x208, 0x20D4 },
939 { 0x20A, 0x0080 },
940 { 0x07, 0x0000 },
941};
942
943static int wm2200_reset(struct wm2200_priv *wm2200)
944{
945 if (wm2200->pdata.reset) {
946 gpio_set_value_cansleep(wm2200->pdata.reset, 0);
947 gpio_set_value_cansleep(wm2200->pdata.reset, 1);
948
949 return 0;
950 } else {
951 return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET,
952 0x2200);
953 }
954}
955
956static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
957static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
958static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
959
960static const char *wm2200_mixer_texts[] = {
961 "None",
962 "Tone Generator",
Mark Brown999e0682012-10-02 19:30:17 +0100963 "AEC Loopback",
Mark Brownd5315a22012-01-25 19:29:41 +0000964 "IN1L",
965 "IN1R",
966 "IN2L",
967 "IN2R",
968 "IN3L",
969 "IN3R",
970 "AIF1RX1",
971 "AIF1RX2",
972 "AIF1RX3",
973 "AIF1RX4",
974 "AIF1RX5",
975 "AIF1RX6",
976 "EQL",
977 "EQR",
978 "LHPF1",
979 "LHPF2",
980 "LHPF3",
981 "LHPF4",
982 "DSP1.1",
983 "DSP1.2",
984 "DSP1.3",
985 "DSP1.4",
986 "DSP1.5",
987 "DSP1.6",
988 "DSP2.1",
989 "DSP2.2",
990 "DSP2.3",
991 "DSP2.4",
992 "DSP2.5",
993 "DSP2.6",
994};
995
996static int wm2200_mixer_values[] = {
997 0x00,
998 0x04, /* Tone */
999 0x08, /* AEC */
1000 0x10, /* Input */
1001 0x11,
1002 0x12,
1003 0x13,
1004 0x14,
1005 0x15,
1006 0x20, /* AIF */
1007 0x21,
1008 0x22,
1009 0x23,
1010 0x24,
1011 0x25,
1012 0x50, /* EQ */
1013 0x51,
1014 0x52,
1015 0x60, /* LHPF1 */
1016 0x61, /* LHPF2 */
1017 0x68, /* DSP1 */
1018 0x69,
1019 0x6a,
1020 0x6b,
1021 0x6c,
1022 0x6d,
1023 0x70, /* DSP2 */
1024 0x71,
1025 0x72,
1026 0x73,
1027 0x74,
1028 0x75,
1029};
1030
1031#define WM2200_MIXER_CONTROLS(name, base) \
1032 SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
1033 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
1034 SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
1035 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
1036 SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
1037 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
1038 SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
1039 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
1040
1041#define WM2200_MUX_ENUM_DECL(name, reg) \
1042 SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
1043 wm2200_mixer_texts, wm2200_mixer_values)
1044
1045#define WM2200_MUX_CTL_DECL(name) \
1046 const struct snd_kcontrol_new name##_mux = \
1047 SOC_DAPM_VALUE_ENUM("Route", name##_enum)
1048
1049#define WM2200_MIXER_ENUMS(name, base_reg) \
1050 static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
1051 static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
1052 static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
1053 static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
1054 static WM2200_MUX_CTL_DECL(name##_in1); \
1055 static WM2200_MUX_CTL_DECL(name##_in2); \
1056 static WM2200_MUX_CTL_DECL(name##_in3); \
Mark Brownffa8d9d2012-01-29 21:45:31 +00001057 static WM2200_MUX_CTL_DECL(name##_in4)
Mark Brownd5315a22012-01-25 19:29:41 +00001058
1059static const struct snd_kcontrol_new wm2200_snd_controls[] = {
1060SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
1061 WM2200_IN1_OSR_SHIFT, 1, 0),
1062SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
1063 WM2200_IN2_OSR_SHIFT, 1, 0),
1064SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
1065 WM2200_IN3_OSR_SHIFT, 1, 0),
1066
1067SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
1068 WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
1069SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
1070 WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
1071SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
1072 WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
1073
1074SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
1075 WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
1076SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
1077 WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
1078SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
1079 WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
1080
1081SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
1082 WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
1083 0xbf, 0, digital_tlv),
1084SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
1085 WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
1086 0xbf, 0, digital_tlv),
1087SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
1088 WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
1089 0xbf, 0, digital_tlv),
1090
1091SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
1092 WM2200_OUT1_OSR_SHIFT, 1, 0),
1093SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
1094 WM2200_OUT2_OSR_SHIFT, 1, 0),
1095
1096SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
1097 WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
1098SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
1099 WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
1100 digital_tlv),
1101SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
1102 WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
1103 0x46, 0, out_tlv),
1104
1105SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
1106 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
1107SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
1108 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
1109 digital_tlv),
1110SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
Mark Browna1b98e12012-10-02 19:10:43 +01001111 WM2200_SPK1R_MUTE_SHIFT, 1, 1),
Mark Brownd5315a22012-01-25 19:29:41 +00001112};
1113
1114WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
1115WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
1116WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
1117WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
1118
1119WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
1120WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
1121WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
1122WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
1123WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
1124WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
1125
1126WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
1127WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
1128
1129WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
1130WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
1131WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
1132WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
1133
1134WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
1135WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
1136
1137#define WM2200_MUX(name, ctrl) \
1138 SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
1139
1140#define WM2200_MIXER_WIDGETS(name, name_str) \
1141 WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
1142 WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
1143 WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
1144 WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
1145 SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
1146
1147#define WM2200_MIXER_INPUT_ROUTES(name) \
1148 { name, "Tone Generator", "Tone Generator" }, \
Mark Brown999e0682012-10-02 19:30:17 +01001149 { name, "AEC Loopback", "AEC Loopback" }, \
Mark Brownd5315a22012-01-25 19:29:41 +00001150 { name, "IN1L", "IN1L PGA" }, \
1151 { name, "IN1R", "IN1R PGA" }, \
1152 { name, "IN2L", "IN2L PGA" }, \
1153 { name, "IN2R", "IN2R PGA" }, \
1154 { name, "IN3L", "IN3L PGA" }, \
1155 { name, "IN3R", "IN3R PGA" }, \
1156 { name, "DSP1.1", "DSP1" }, \
1157 { name, "DSP1.2", "DSP1" }, \
1158 { name, "DSP1.3", "DSP1" }, \
1159 { name, "DSP1.4", "DSP1" }, \
1160 { name, "DSP1.5", "DSP1" }, \
1161 { name, "DSP1.6", "DSP1" }, \
1162 { name, "DSP2.1", "DSP2" }, \
1163 { name, "DSP2.2", "DSP2" }, \
1164 { name, "DSP2.3", "DSP2" }, \
1165 { name, "DSP2.4", "DSP2" }, \
1166 { name, "DSP2.5", "DSP2" }, \
1167 { name, "DSP2.6", "DSP2" }, \
1168 { name, "AIF1RX1", "AIF1RX1" }, \
1169 { name, "AIF1RX2", "AIF1RX2" }, \
1170 { name, "AIF1RX3", "AIF1RX3" }, \
1171 { name, "AIF1RX4", "AIF1RX4" }, \
1172 { name, "AIF1RX5", "AIF1RX5" }, \
1173 { name, "AIF1RX6", "AIF1RX6" }, \
1174 { name, "EQL", "EQL" }, \
1175 { name, "EQR", "EQR" }, \
1176 { name, "LHPF1", "LHPF1" }, \
1177 { name, "LHPF2", "LHPF2" }
1178
1179#define WM2200_MIXER_ROUTES(widget, name) \
1180 { widget, NULL, name " Mixer" }, \
1181 { name " Mixer", NULL, name " Input 1" }, \
1182 { name " Mixer", NULL, name " Input 2" }, \
1183 { name " Mixer", NULL, name " Input 3" }, \
1184 { name " Mixer", NULL, name " Input 4" }, \
1185 WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
1186 WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
1187 WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
1188 WM2200_MIXER_INPUT_ROUTES(name " Input 4")
1189
Mark Brown999e0682012-10-02 19:30:17 +01001190
1191static const char *wm2200_aec_loopback_texts[] = {
1192 "OUT1L", "OUT1R", "OUT2L", "OUT2R",
1193};
1194
1195static const struct soc_enum wm2200_aec_loopback =
1196 SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
1197 WM2200_AEC_LOOPBACK_SRC_SHIFT,
1198 ARRAY_SIZE(wm2200_aec_loopback_texts),
1199 wm2200_aec_loopback_texts);
1200
1201static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
1202 SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
1203
Mark Brownd5315a22012-01-25 19:29:41 +00001204static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
1205SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
1206 NULL, 0),
1207SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
1208 NULL, 0),
1209SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
1210 NULL, 0),
1211SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
1212 0, NULL, 0),
1213SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
1214 0, NULL, 0),
Mark Brown822b4b82012-09-07 10:54:32 +08001215SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0),
1216SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20, 0),
Mark Brownd5315a22012-01-25 19:29:41 +00001217
1218SND_SOC_DAPM_INPUT("IN1L"),
1219SND_SOC_DAPM_INPUT("IN1R"),
1220SND_SOC_DAPM_INPUT("IN2L"),
1221SND_SOC_DAPM_INPUT("IN2R"),
1222SND_SOC_DAPM_INPUT("IN3L"),
1223SND_SOC_DAPM_INPUT("IN3R"),
1224
1225SND_SOC_DAPM_SIGGEN("TONE"),
1226SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
1227 WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
1228
1229SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
1230 NULL, 0),
1231SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
1232 NULL, 0),
1233SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
1234 NULL, 0),
1235SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
1236 NULL, 0),
1237SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
1238 NULL, 0),
1239SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
1240 NULL, 0),
1241
1242SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
1243 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
1244SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
1245 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
1246SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
1247 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
1248SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
1249 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
1250SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
1251 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
1252SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
1253 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
1254
1255SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
1256SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
1257
1258SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
1259 NULL, 0),
1260SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
1261 NULL, 0),
1262
1263SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
1264SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
1265
1266SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
1267 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
1268SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
1269 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
1270SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
1271 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
1272SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
1273 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
1274SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
1275 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
1276SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
1277 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
1278
Mark Brown999e0682012-10-02 19:30:17 +01001279SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
1280 WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
1281
Mark Brownd5315a22012-01-25 19:29:41 +00001282SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
1283 WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
1284SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
1285 WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
1286
1287SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1288 WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
1289SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1290 WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
1291SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1292 WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
1293
1294SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1295 WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
1296SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1297 WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
1298SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1299 WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
1300
1301SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1302 WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
1303SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1304 WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
1305SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1306 WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
1307
1308SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1309 WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
1310SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1311 WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
1312SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1313 WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
1314
1315SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
1316 0, NULL, 0),
1317SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
1318 0, NULL, 0),
1319
1320SND_SOC_DAPM_OUTPUT("EPOUTLN"),
1321SND_SOC_DAPM_OUTPUT("EPOUTLP"),
1322SND_SOC_DAPM_OUTPUT("EPOUTRN"),
1323SND_SOC_DAPM_OUTPUT("EPOUTRP"),
1324SND_SOC_DAPM_OUTPUT("SPK"),
1325
1326WM2200_MIXER_WIDGETS(EQL, "EQL"),
1327WM2200_MIXER_WIDGETS(EQR, "EQR"),
1328
1329WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
1330WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
1331
1332WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
1333WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
1334WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
1335WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
1336
1337WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
1338WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
1339WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
1340WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
1341WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
1342WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
1343
1344WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
1345WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
1346WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
1347WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
1348};
1349
1350static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
1351 /* Everything needs SYSCLK but only hook up things on the edge
1352 * of the chip */
1353 { "IN1L", NULL, "SYSCLK" },
1354 { "IN1R", NULL, "SYSCLK" },
1355 { "IN2L", NULL, "SYSCLK" },
1356 { "IN2R", NULL, "SYSCLK" },
1357 { "IN3L", NULL, "SYSCLK" },
1358 { "IN3R", NULL, "SYSCLK" },
1359 { "OUT1L", NULL, "SYSCLK" },
1360 { "OUT1R", NULL, "SYSCLK" },
1361 { "OUT2L", NULL, "SYSCLK" },
1362 { "OUT2R", NULL, "SYSCLK" },
1363 { "AIF1RX1", NULL, "SYSCLK" },
1364 { "AIF1RX2", NULL, "SYSCLK" },
1365 { "AIF1RX3", NULL, "SYSCLK" },
1366 { "AIF1RX4", NULL, "SYSCLK" },
1367 { "AIF1RX5", NULL, "SYSCLK" },
1368 { "AIF1RX6", NULL, "SYSCLK" },
1369 { "AIF1TX1", NULL, "SYSCLK" },
1370 { "AIF1TX2", NULL, "SYSCLK" },
1371 { "AIF1TX3", NULL, "SYSCLK" },
1372 { "AIF1TX4", NULL, "SYSCLK" },
1373 { "AIF1TX5", NULL, "SYSCLK" },
1374 { "AIF1TX6", NULL, "SYSCLK" },
1375
1376 { "IN1L", NULL, "AVDD" },
1377 { "IN1R", NULL, "AVDD" },
1378 { "IN2L", NULL, "AVDD" },
1379 { "IN2R", NULL, "AVDD" },
1380 { "IN3L", NULL, "AVDD" },
1381 { "IN3R", NULL, "AVDD" },
1382 { "OUT1L", NULL, "AVDD" },
1383 { "OUT1R", NULL, "AVDD" },
1384
1385 { "IN1L PGA", NULL, "IN1L" },
1386 { "IN1R PGA", NULL, "IN1R" },
1387 { "IN2L PGA", NULL, "IN2L" },
1388 { "IN2R PGA", NULL, "IN2R" },
1389 { "IN3L PGA", NULL, "IN3L" },
1390 { "IN3R PGA", NULL, "IN3R" },
1391
1392 { "Tone Generator", NULL, "TONE" },
1393
1394 { "CP2", NULL, "CPVDD" },
1395 { "MICBIAS1", NULL, "CP2" },
1396 { "MICBIAS2", NULL, "CP2" },
1397
1398 { "CP1", NULL, "CPVDD" },
1399 { "EPD_LN", NULL, "CP1" },
1400 { "EPD_LP", NULL, "CP1" },
1401 { "EPD_RN", NULL, "CP1" },
1402 { "EPD_RP", NULL, "CP1" },
1403
1404 { "EPD_LP", NULL, "OUT1L" },
1405 { "EPD_OUTP_LP", NULL, "EPD_LP" },
1406 { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
1407 { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
1408
1409 { "EPD_LN", NULL, "OUT1L" },
1410 { "EPD_OUTP_LN", NULL, "EPD_LN" },
1411 { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
1412 { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
1413
1414 { "EPD_RP", NULL, "OUT1R" },
1415 { "EPD_OUTP_RP", NULL, "EPD_RP" },
1416 { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
1417 { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
1418
1419 { "EPD_RN", NULL, "OUT1R" },
1420 { "EPD_OUTP_RN", NULL, "EPD_RN" },
1421 { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
1422 { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
1423
1424 { "SPK", NULL, "OUT2L" },
1425 { "SPK", NULL, "OUT2R" },
1426
Mark Brown999e0682012-10-02 19:30:17 +01001427 { "AEC Loopback", "OUT1L", "OUT1L" },
1428 { "AEC Loopback", "OUT1R", "OUT1R" },
1429 { "AEC Loopback", "OUT2L", "OUT2L" },
1430 { "AEC Loopback", "OUT2R", "OUT2R" },
1431
Mark Brownd5315a22012-01-25 19:29:41 +00001432 WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
1433 WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
1434 WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
1435 WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
1436
1437 WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
1438 WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
1439 WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
1440 WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
1441
1442 WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
1443 WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
1444 WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
1445 WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
1446 WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
1447 WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
1448
1449 WM2200_MIXER_ROUTES("EQL", "EQL"),
1450 WM2200_MIXER_ROUTES("EQR", "EQR"),
1451
1452 WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
1453 WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
1454};
1455
1456static int wm2200_probe(struct snd_soc_codec *codec)
1457{
1458 struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
1459 int ret;
1460
1461 wm2200->codec = codec;
1462 codec->control_data = wm2200->regmap;
1463 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
1464
1465 ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
1466 if (ret != 0) {
1467 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1468 return ret;
1469 }
1470
1471 return ret;
1472}
1473
1474static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1475{
1476 struct snd_soc_codec *codec = dai->codec;
1477 int lrclk, bclk, fmt_val;
1478
1479 lrclk = 0;
1480 bclk = 0;
1481
1482 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1483 case SND_SOC_DAIFMT_DSP_A:
1484 fmt_val = 0;
1485 break;
1486 case SND_SOC_DAIFMT_DSP_B:
1487 fmt_val = 1;
1488 break;
1489 case SND_SOC_DAIFMT_I2S:
1490 fmt_val = 2;
1491 break;
1492 case SND_SOC_DAIFMT_LEFT_J:
1493 fmt_val = 3;
1494 break;
1495 default:
1496 dev_err(codec->dev, "Unsupported DAI format %d\n",
1497 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1498 return -EINVAL;
1499 }
1500
1501 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1502 case SND_SOC_DAIFMT_CBS_CFS:
1503 break;
1504 case SND_SOC_DAIFMT_CBS_CFM:
1505 lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
1506 break;
1507 case SND_SOC_DAIFMT_CBM_CFS:
1508 bclk |= WM2200_AIF1_BCLK_MSTR;
1509 break;
1510 case SND_SOC_DAIFMT_CBM_CFM:
1511 lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
1512 bclk |= WM2200_AIF1_BCLK_MSTR;
1513 break;
1514 default:
1515 dev_err(codec->dev, "Unsupported master mode %d\n",
1516 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1517 return -EINVAL;
1518 }
1519
1520 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1521 case SND_SOC_DAIFMT_NB_NF:
1522 break;
1523 case SND_SOC_DAIFMT_IB_IF:
1524 bclk |= WM2200_AIF1_BCLK_INV;
1525 lrclk |= WM2200_AIF1TX_LRCLK_INV;
1526 break;
1527 case SND_SOC_DAIFMT_IB_NF:
1528 bclk |= WM2200_AIF1_BCLK_INV;
1529 break;
1530 case SND_SOC_DAIFMT_NB_IF:
1531 lrclk |= WM2200_AIF1TX_LRCLK_INV;
1532 break;
1533 default:
1534 return -EINVAL;
1535 }
1536
1537 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
1538 WM2200_AIF1_BCLK_INV, bclk);
1539 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
1540 WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
1541 lrclk);
1542 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
1543 WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
1544 lrclk);
1545 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
1546 WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
1547
1548 return 0;
1549}
1550
1551static int wm2200_sr_code[] = {
1552 0,
1553 12000,
1554 24000,
1555 48000,
1556 96000,
1557 192000,
1558 384000,
1559 768000,
1560 0,
1561 11025,
1562 22050,
1563 44100,
1564 88200,
1565 176400,
1566 352800,
1567 705600,
1568 4000,
1569 8000,
1570 16000,
1571 32000,
1572 64000,
1573 128000,
1574 256000,
1575 512000,
1576};
1577
1578#define WM2200_NUM_BCLK_RATES 12
1579
1580static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
1581 6144000,
1582 3072000,
1583 2048000,
1584 1536000,
1585 768000,
1586 512000,
1587 384000,
1588 256000,
1589 192000,
1590 128000,
1591 96000,
1592 64000,
1593};
1594
1595static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
1596 5644800,
Mark Brownb0dfa452012-06-20 14:16:57 +01001597 3763200,
Mark Brownd5315a22012-01-25 19:29:41 +00001598 2882400,
1599 1881600,
1600 1411200,
1601 705600,
1602 470400,
1603 352800,
1604 176400,
1605 117600,
1606 88200,
1607 58800,
1608};
1609
1610static int wm2200_hw_params(struct snd_pcm_substream *substream,
1611 struct snd_pcm_hw_params *params,
1612 struct snd_soc_dai *dai)
1613{
1614 struct snd_soc_codec *codec = dai->codec;
1615 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1616 int i, bclk, lrclk, wl, fl, sr_code;
1617 int *bclk_rates;
1618
1619 /* Data sizes if not using TDM */
1620 wl = snd_pcm_format_width(params_format(params));
1621 if (wl < 0)
1622 return wl;
1623 fl = snd_soc_params_to_frame_size(params);
1624 if (fl < 0)
1625 return fl;
1626
1627 dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
1628 wl, fl);
1629
1630 /* Target BCLK rate */
1631 bclk = snd_soc_params_to_bclk(params);
1632 if (bclk < 0)
1633 return bclk;
1634
1635 if (!wm2200->sysclk) {
1636 dev_err(codec->dev, "SYSCLK has no rate set\n");
1637 return -EINVAL;
1638 }
1639
1640 for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
1641 if (wm2200_sr_code[i] == params_rate(params))
1642 break;
1643 if (i == ARRAY_SIZE(wm2200_sr_code)) {
1644 dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
1645 params_rate(params));
1646 return -EINVAL;
1647 }
1648 sr_code = i;
1649
1650 dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
1651 bclk, wm2200->sysclk);
1652
1653 if (wm2200->sysclk % 4000)
1654 bclk_rates = wm2200_bclk_rates_cd;
1655 else
1656 bclk_rates = wm2200_bclk_rates_dat;
1657
1658 for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
1659 if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
1660 break;
1661 if (i == WM2200_NUM_BCLK_RATES) {
1662 dev_err(codec->dev,
1663 "No valid BCLK for %dHz found from %dHz SYSCLK\n",
1664 bclk, wm2200->sysclk);
1665 return -EINVAL;
1666 }
1667
1668 bclk = i;
1669 dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
1670 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
1671 WM2200_AIF1_BCLK_DIV_MASK, bclk);
1672
1673 lrclk = bclk_rates[bclk] / params_rate(params);
1674 dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
1675 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
1676 dai->symmetric_rates)
1677 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
1678 WM2200_AIF1RX_BCPF_MASK, lrclk);
1679 else
1680 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
1681 WM2200_AIF1TX_BCPF_MASK, lrclk);
1682
1683 i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
1684 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1685 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
1686 WM2200_AIF1RX_WL_MASK |
1687 WM2200_AIF1RX_SLOT_LEN_MASK, i);
1688 else
1689 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
1690 WM2200_AIF1TX_WL_MASK |
1691 WM2200_AIF1TX_SLOT_LEN_MASK, i);
1692
1693 snd_soc_update_bits(codec, WM2200_CLOCKING_4,
1694 WM2200_SAMPLE_RATE_1_MASK, sr_code);
1695
1696 return 0;
1697}
1698
1699static const struct snd_soc_dai_ops wm2200_dai_ops = {
1700 .set_fmt = wm2200_set_fmt,
1701 .hw_params = wm2200_hw_params,
1702};
1703
1704static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1705 int source, unsigned int freq, int dir)
1706{
1707 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1708 int fval;
1709
1710 switch (clk_id) {
1711 case WM2200_CLK_SYSCLK:
1712 break;
1713
1714 default:
1715 dev_err(codec->dev, "Unknown clock %d\n", clk_id);
1716 return -EINVAL;
1717 }
1718
1719 switch (source) {
1720 case WM2200_CLKSRC_MCLK1:
1721 case WM2200_CLKSRC_MCLK2:
1722 case WM2200_CLKSRC_FLL:
1723 case WM2200_CLKSRC_BCLK1:
1724 break;
1725 default:
1726 dev_err(codec->dev, "Invalid source %d\n", source);
1727 return -EINVAL;
1728 }
1729
1730 switch (freq) {
1731 case 22579200:
1732 case 24576000:
1733 fval = 2;
1734 break;
1735 default:
1736 dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
1737 return -EINVAL;
1738 }
1739
1740 /* TODO: Check if MCLKs are in use and enable/disable pulls to
1741 * match.
1742 */
1743
1744 snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
1745 WM2200_SYSCLK_SRC_MASK,
1746 fval << WM2200_SYSCLK_FREQ_SHIFT | source);
1747
1748 wm2200->sysclk = freq;
1749
1750 return 0;
1751}
1752
1753struct _fll_div {
1754 u16 fll_fratio;
1755 u16 fll_outdiv;
1756 u16 fll_refclk_div;
1757 u16 n;
1758 u16 theta;
1759 u16 lambda;
1760};
1761
1762static struct {
1763 unsigned int min;
1764 unsigned int max;
1765 u16 fll_fratio;
1766 int ratio;
1767} fll_fratios[] = {
1768 { 0, 64000, 4, 16 },
1769 { 64000, 128000, 3, 8 },
1770 { 128000, 256000, 2, 4 },
1771 { 256000, 1000000, 1, 2 },
1772 { 1000000, 13500000, 0, 1 },
1773};
1774
1775static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
1776 unsigned int Fout)
1777{
1778 unsigned int target;
1779 unsigned int div;
1780 unsigned int fratio, gcd_fll;
1781 int i;
1782
1783 /* Fref must be <=13.5MHz */
1784 div = 1;
1785 fll_div->fll_refclk_div = 0;
1786 while ((Fref / div) > 13500000) {
1787 div *= 2;
1788 fll_div->fll_refclk_div++;
1789
1790 if (div > 8) {
1791 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
1792 Fref);
1793 return -EINVAL;
1794 }
1795 }
1796
1797 pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
1798
1799 /* Apply the division for our remaining calculations */
1800 Fref /= div;
1801
1802 /* Fvco should be 90-100MHz; don't check the upper bound */
1803 div = 2;
1804 while (Fout * div < 90000000) {
1805 div++;
1806 if (div > 64) {
1807 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
1808 Fout);
1809 return -EINVAL;
1810 }
1811 }
1812 target = Fout * div;
1813 fll_div->fll_outdiv = div - 1;
1814
1815 pr_debug("FLL Fvco=%dHz\n", target);
1816
1817 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1818 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1819 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1820 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
1821 fratio = fll_fratios[i].ratio;
1822 break;
1823 }
1824 }
1825 if (i == ARRAY_SIZE(fll_fratios)) {
1826 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
1827 return -EINVAL;
1828 }
1829
1830 fll_div->n = target / (fratio * Fref);
1831
1832 if (target % Fref == 0) {
1833 fll_div->theta = 0;
1834 fll_div->lambda = 0;
1835 } else {
1836 gcd_fll = gcd(target, fratio * Fref);
1837
1838 fll_div->theta = (target - (fll_div->n * fratio * Fref))
1839 / gcd_fll;
1840 fll_div->lambda = (fratio * Fref) / gcd_fll;
1841 }
1842
1843 pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
1844 fll_div->n, fll_div->theta, fll_div->lambda);
1845 pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
1846 fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
1847 fll_div->fll_refclk_div);
1848
1849 return 0;
1850}
1851
1852static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
1853 unsigned int Fref, unsigned int Fout)
1854{
1855 struct i2c_client *i2c = to_i2c_client(codec->dev);
1856 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1857 struct _fll_div factors;
1858 int ret, i, timeout;
1859
1860 if (!Fout) {
1861 dev_dbg(codec->dev, "FLL disabled");
1862
1863 if (wm2200->fll_fout)
1864 pm_runtime_put(codec->dev);
1865
1866 wm2200->fll_fout = 0;
1867 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
1868 WM2200_FLL_ENA, 0);
1869 return 0;
1870 }
1871
1872 switch (source) {
1873 case WM2200_FLL_SRC_MCLK1:
1874 case WM2200_FLL_SRC_MCLK2:
1875 case WM2200_FLL_SRC_BCLK:
1876 break;
1877 default:
1878 dev_err(codec->dev, "Invalid FLL source %d\n", source);
1879 return -EINVAL;
1880 }
1881
1882 ret = fll_factors(&factors, Fref, Fout);
1883 if (ret < 0)
1884 return ret;
1885
1886 /* Disable the FLL while we reconfigure */
1887 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
1888
1889 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
1890 WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
1891 (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
1892 factors.fll_fratio);
1893 if (factors.theta) {
1894 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
1895 WM2200_FLL_FRACN_ENA,
1896 WM2200_FLL_FRACN_ENA);
1897 snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
1898 WM2200_FLL_EFS_ENA,
1899 WM2200_FLL_EFS_ENA);
1900 } else {
1901 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
1902 WM2200_FLL_FRACN_ENA, 0);
1903 snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
1904 WM2200_FLL_EFS_ENA, 0);
1905 }
1906
1907 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
1908 factors.theta);
1909 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
1910 factors.n);
1911 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
1912 WM2200_FLL_CLK_REF_DIV_MASK |
1913 WM2200_FLL_CLK_REF_SRC_MASK,
1914 (factors.fll_refclk_div
1915 << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
1916 snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
1917 WM2200_FLL_LAMBDA_MASK, factors.lambda);
1918
1919 /* Clear any pending completions */
1920 try_wait_for_completion(&wm2200->fll_lock);
1921
1922 pm_runtime_get_sync(codec->dev);
1923
1924 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
1925 WM2200_FLL_ENA, WM2200_FLL_ENA);
1926
1927 if (i2c->irq)
1928 timeout = 2;
1929 else
1930 timeout = 50;
1931
1932 snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
1933 WM2200_SYSCLK_ENA);
1934
1935 /* Poll for the lock; will use the interrupt to exit quickly */
1936 for (i = 0; i < timeout; i++) {
1937 if (i2c->irq) {
1938 ret = wait_for_completion_timeout(&wm2200->fll_lock,
1939 msecs_to_jiffies(25));
1940 if (ret > 0)
1941 break;
1942 } else {
1943 msleep(1);
1944 }
1945
1946 ret = snd_soc_read(codec,
1947 WM2200_INTERRUPT_RAW_STATUS_2);
1948 if (ret < 0) {
1949 dev_err(codec->dev,
1950 "Failed to read FLL status: %d\n",
1951 ret);
1952 continue;
1953 }
1954 if (ret & WM2200_FLL_LOCK_STS)
1955 break;
1956 }
1957 if (i == timeout) {
1958 dev_err(codec->dev, "FLL lock timed out\n");
1959 pm_runtime_put(codec->dev);
1960 return -ETIMEDOUT;
1961 }
1962
1963 wm2200->fll_src = source;
1964 wm2200->fll_fref = Fref;
1965 wm2200->fll_fout = Fout;
1966
1967 dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
1968
1969 return 0;
1970}
1971
1972static int wm2200_dai_probe(struct snd_soc_dai *dai)
1973{
1974 struct snd_soc_codec *codec = dai->codec;
1975 unsigned int val = 0;
1976 int ret;
1977
1978 ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
1979 if (ret >= 0) {
1980 if ((ret & WM2200_GP1_FN_MASK) != 0) {
1981 dai->symmetric_rates = true;
1982 val = WM2200_AIF1TX_LRCLK_SRC;
1983 }
1984 } else {
1985 dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
1986 }
1987
1988 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
1989 WM2200_AIF1TX_LRCLK_SRC, val);
1990
1991 return 0;
1992}
1993
1994#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
1995
1996#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1997 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1998
1999static struct snd_soc_dai_driver wm2200_dai = {
2000 .name = "wm2200",
2001 .probe = wm2200_dai_probe,
2002 .playback = {
2003 .stream_name = "Playback",
2004 .channels_min = 2,
2005 .channels_max = 2,
2006 .rates = WM2200_RATES,
2007 .formats = WM2200_FORMATS,
2008 },
2009 .capture = {
2010 .stream_name = "Capture",
2011 .channels_min = 2,
2012 .channels_max = 2,
2013 .rates = WM2200_RATES,
2014 .formats = WM2200_FORMATS,
2015 },
2016 .ops = &wm2200_dai_ops,
2017};
2018
2019static struct snd_soc_codec_driver soc_codec_wm2200 = {
2020 .probe = wm2200_probe,
2021
2022 .idle_bias_off = true,
Mark Brown17c0cee2012-02-08 18:35:43 +00002023 .ignore_pmdown_time = true,
Mark Brownd5315a22012-01-25 19:29:41 +00002024 .set_sysclk = wm2200_set_sysclk,
2025 .set_pll = wm2200_set_fll,
2026
2027 .controls = wm2200_snd_controls,
2028 .num_controls = ARRAY_SIZE(wm2200_snd_controls),
2029 .dapm_widgets = wm2200_dapm_widgets,
2030 .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
2031 .dapm_routes = wm2200_dapm_routes,
2032 .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
2033};
2034
2035static irqreturn_t wm2200_irq(int irq, void *data)
2036{
2037 struct wm2200_priv *wm2200 = data;
2038 unsigned int val, mask;
2039 int ret;
2040
2041 ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
2042 if (ret != 0) {
2043 dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
2044 return IRQ_NONE;
2045 }
2046
2047 ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
2048 &mask);
2049 if (ret != 0) {
2050 dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
2051 mask = 0;
2052 }
2053
2054 val &= ~mask;
2055
2056 if (val & WM2200_FLL_LOCK_EINT) {
2057 dev_dbg(wm2200->dev, "FLL locked\n");
2058 complete(&wm2200->fll_lock);
2059 }
2060
2061 if (val) {
2062 regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
2063
2064 return IRQ_HANDLED;
2065 } else {
2066 return IRQ_NONE;
2067 }
2068}
2069
2070static const struct regmap_config wm2200_regmap = {
2071 .reg_bits = 16,
2072 .val_bits = 16,
2073
Mark Browneae23282012-10-02 20:14:49 +01002074 .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
2075 WM2200_DSP_SPACING),
Mark Brownd5315a22012-01-25 19:29:41 +00002076 .reg_defaults = wm2200_reg_defaults,
2077 .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
2078 .volatile_reg = wm2200_volatile_register,
2079 .readable_reg = wm2200_readable_register,
2080 .cache_type = REGCACHE_RBTREE,
Mark Browneae23282012-10-02 20:14:49 +01002081 .ranges = wm2200_ranges,
2082 .num_ranges = ARRAY_SIZE(wm2200_ranges),
Mark Brownd5315a22012-01-25 19:29:41 +00002083};
2084
2085static const unsigned int wm2200_dig_vu[] = {
2086 WM2200_DAC_DIGITAL_VOLUME_1L,
2087 WM2200_DAC_DIGITAL_VOLUME_1R,
2088 WM2200_DAC_DIGITAL_VOLUME_2L,
2089 WM2200_DAC_DIGITAL_VOLUME_2R,
2090 WM2200_ADC_DIGITAL_VOLUME_1L,
2091 WM2200_ADC_DIGITAL_VOLUME_1R,
2092 WM2200_ADC_DIGITAL_VOLUME_2L,
2093 WM2200_ADC_DIGITAL_VOLUME_2R,
2094 WM2200_ADC_DIGITAL_VOLUME_3L,
2095 WM2200_ADC_DIGITAL_VOLUME_3R,
2096};
2097
2098static const unsigned int wm2200_mic_ctrl_reg[] = {
2099 WM2200_IN1L_CONTROL,
2100 WM2200_IN2L_CONTROL,
2101 WM2200_IN3L_CONTROL,
2102};
2103
2104static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
2105 const struct i2c_device_id *id)
2106{
2107 struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
2108 struct wm2200_priv *wm2200;
2109 unsigned int reg;
2110 int ret, i;
2111
2112 wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
2113 GFP_KERNEL);
2114 if (wm2200 == NULL)
2115 return -ENOMEM;
2116
2117 wm2200->dev = &i2c->dev;
2118 init_completion(&wm2200->fll_lock);
2119
Mark Brown98ad0892012-10-01 19:27:45 +01002120 wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
Mark Brownd5315a22012-01-25 19:29:41 +00002121 if (IS_ERR(wm2200->regmap)) {
2122 ret = PTR_ERR(wm2200->regmap);
2123 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
2124 ret);
2125 goto err;
2126 }
2127
2128 if (pdata)
2129 wm2200->pdata = *pdata;
2130
2131 i2c_set_clientdata(i2c, wm2200);
2132
2133 for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
2134 wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
2135
Mark Brown98ad0892012-10-01 19:27:45 +01002136 ret = devm_regulator_bulk_get(&i2c->dev,
2137 ARRAY_SIZE(wm2200->core_supplies),
2138 wm2200->core_supplies);
Mark Brownd5315a22012-01-25 19:29:41 +00002139 if (ret != 0) {
2140 dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
2141 ret);
2142 goto err_regmap;
2143 }
2144
2145 ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
2146 wm2200->core_supplies);
2147 if (ret != 0) {
2148 dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
2149 ret);
2150 goto err_core;
2151 }
2152
2153 if (wm2200->pdata.ldo_ena) {
Mark Brown98ad0892012-10-01 19:27:45 +01002154 ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
2155 GPIOF_OUT_INIT_HIGH,
2156 "WM2200 LDOENA");
Mark Brownd5315a22012-01-25 19:29:41 +00002157 if (ret < 0) {
2158 dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
2159 wm2200->pdata.ldo_ena, ret);
2160 goto err_enable;
2161 }
2162 msleep(2);
2163 }
2164
2165 if (wm2200->pdata.reset) {
Mark Brown98ad0892012-10-01 19:27:45 +01002166 ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
2167 GPIOF_OUT_INIT_HIGH,
2168 "WM2200 /RESET");
Mark Brownd5315a22012-01-25 19:29:41 +00002169 if (ret < 0) {
2170 dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
2171 wm2200->pdata.reset, ret);
2172 goto err_ldo;
2173 }
2174 }
2175
2176 ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
2177 if (ret < 0) {
2178 dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
2179 goto err_reset;
2180 }
2181 switch (reg) {
2182 case 0x2200:
2183 break;
2184
2185 default:
2186 dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
2187 ret = -EINVAL;
2188 goto err_reset;
2189 }
2190
2191 ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
2192 if (ret < 0) {
2193 dev_err(&i2c->dev, "Failed to read revision register\n");
2194 goto err_reset;
2195 }
2196
Axel Lin916be222012-02-16 10:05:59 +08002197 wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
Mark Brownd5315a22012-01-25 19:29:41 +00002198
2199 dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
2200
2201 switch (wm2200->rev) {
2202 case 0:
Mark Brown5ae9eb42012-10-02 12:02:48 +01002203 case 1:
Mark Brownd5315a22012-01-25 19:29:41 +00002204 ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
2205 ARRAY_SIZE(wm2200_reva_patch));
2206 if (ret != 0) {
2207 dev_err(&i2c->dev, "Failed to register patch: %d\n",
2208 ret);
2209 }
2210 break;
2211 default:
2212 break;
2213 }
2214
2215 ret = wm2200_reset(wm2200);
2216 if (ret < 0) {
2217 dev_err(&i2c->dev, "Failed to issue reset\n");
2218 goto err_reset;
2219 }
2220
2221 for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
2222 if (!wm2200->pdata.gpio_defaults[i])
2223 continue;
2224
2225 regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
2226 wm2200->pdata.gpio_defaults[i]);
2227 }
2228
2229 for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
2230 regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
2231 WM2200_OUT_VU, WM2200_OUT_VU);
2232
2233 /* Assign slots 1-6 to channels 1-6 for both TX and RX */
2234 for (i = 0; i < 6; i++) {
2235 regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
2236 regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
2237 }
2238
2239 for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
2240 regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
2241 WM2200_IN1_MODE_MASK |
2242 WM2200_IN1_DMIC_SUP_MASK,
2243 (wm2200->pdata.in_mode[i] <<
2244 WM2200_IN1_MODE_SHIFT) |
2245 (wm2200->pdata.dmic_sup[i] <<
2246 WM2200_IN1_DMIC_SUP_SHIFT));
2247 }
2248
2249 if (i2c->irq) {
2250 ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
2251 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
2252 "wm2200", wm2200);
2253 if (ret == 0)
2254 regmap_update_bits(wm2200->regmap,
2255 WM2200_INTERRUPT_STATUS_2_MASK,
2256 WM2200_FLL_LOCK_EINT, 0);
2257 else
2258 dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
2259 i2c->irq, ret);
2260 }
2261
2262 pm_runtime_set_active(&i2c->dev);
2263 pm_runtime_enable(&i2c->dev);
2264 pm_request_idle(&i2c->dev);
2265
2266 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
2267 &wm2200_dai, 1);
2268 if (ret != 0) {
2269 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
2270 goto err_pm_runtime;
2271 }
2272
2273 return 0;
2274
2275err_pm_runtime:
2276 pm_runtime_disable(&i2c->dev);
2277err_reset:
Mark Brown98ad0892012-10-01 19:27:45 +01002278 if (wm2200->pdata.reset)
Mark Brownd5315a22012-01-25 19:29:41 +00002279 gpio_set_value_cansleep(wm2200->pdata.reset, 0);
Mark Brownd5315a22012-01-25 19:29:41 +00002280err_ldo:
Mark Brown98ad0892012-10-01 19:27:45 +01002281 if (wm2200->pdata.ldo_ena)
Mark Brownd5315a22012-01-25 19:29:41 +00002282 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
Mark Brownd5315a22012-01-25 19:29:41 +00002283err_enable:
2284 regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
2285 wm2200->core_supplies);
2286err_core:
Mark Brownd5315a22012-01-25 19:29:41 +00002287err_regmap:
Mark Brownd5315a22012-01-25 19:29:41 +00002288err:
2289 return ret;
2290}
2291
2292static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
2293{
2294 struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
2295
2296 snd_soc_unregister_codec(&i2c->dev);
2297 if (i2c->irq)
2298 free_irq(i2c->irq, wm2200);
Mark Brown98ad0892012-10-01 19:27:45 +01002299 if (wm2200->pdata.reset)
Mark Brownd5315a22012-01-25 19:29:41 +00002300 gpio_set_value_cansleep(wm2200->pdata.reset, 0);
Mark Brown98ad0892012-10-01 19:27:45 +01002301 if (wm2200->pdata.ldo_ena)
Mark Brownd5315a22012-01-25 19:29:41 +00002302 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
Mark Brownd5315a22012-01-25 19:29:41 +00002303
2304 return 0;
2305}
2306
2307#ifdef CONFIG_PM_RUNTIME
2308static int wm2200_runtime_suspend(struct device *dev)
2309{
2310 struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
2311
2312 regcache_cache_only(wm2200->regmap, true);
2313 regcache_mark_dirty(wm2200->regmap);
2314 if (wm2200->pdata.ldo_ena)
2315 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
2316 regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
2317 wm2200->core_supplies);
2318
2319 return 0;
2320}
2321
2322static int wm2200_runtime_resume(struct device *dev)
2323{
2324 struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
2325 int ret;
2326
2327 ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
2328 wm2200->core_supplies);
2329 if (ret != 0) {
2330 dev_err(dev, "Failed to enable supplies: %d\n",
2331 ret);
2332 return ret;
2333 }
2334
2335 if (wm2200->pdata.ldo_ena) {
2336 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
2337 msleep(2);
2338 }
2339
2340 regcache_cache_only(wm2200->regmap, false);
2341 regcache_sync(wm2200->regmap);
2342
2343 return 0;
2344}
2345#endif
2346
2347static struct dev_pm_ops wm2200_pm = {
2348 SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
2349 NULL)
2350};
2351
2352static const struct i2c_device_id wm2200_i2c_id[] = {
2353 { "wm2200", 0 },
2354 { }
2355};
2356MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
2357
2358static struct i2c_driver wm2200_i2c_driver = {
2359 .driver = {
2360 .name = "wm2200",
2361 .owner = THIS_MODULE,
2362 .pm = &wm2200_pm,
2363 },
2364 .probe = wm2200_i2c_probe,
2365 .remove = __devexit_p(wm2200_i2c_remove),
2366 .id_table = wm2200_i2c_id,
2367};
2368
Sachin Kamata9418dd2012-08-06 17:25:53 +05302369module_i2c_driver(wm2200_i2c_driver);
Mark Brownd5315a22012-01-25 19:29:41 +00002370
2371MODULE_DESCRIPTION("ASoC WM2200 driver");
2372MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2373MODULE_LICENSE("GPL");