blob: f24ef0aeeb322041defbaa31cebf0c71371a4c83 [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
Mark Brown09d5d582012-10-03 15:57:03 +01001059#define WM2200_DSP_ENUMS(name, base_reg) \
1060 static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg); \
1061 static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \
1062 static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \
1063 static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \
1064 static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \
1065 static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \
1066 static WM2200_MUX_CTL_DECL(name##_aux1); \
1067 static WM2200_MUX_CTL_DECL(name##_aux2); \
1068 static WM2200_MUX_CTL_DECL(name##_aux3); \
1069 static WM2200_MUX_CTL_DECL(name##_aux4); \
1070 static WM2200_MUX_CTL_DECL(name##_aux5); \
1071 static WM2200_MUX_CTL_DECL(name##_aux6);
1072
Mark Brownd5315a22012-01-25 19:29:41 +00001073static const struct snd_kcontrol_new wm2200_snd_controls[] = {
1074SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
1075 WM2200_IN1_OSR_SHIFT, 1, 0),
1076SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
1077 WM2200_IN2_OSR_SHIFT, 1, 0),
1078SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
1079 WM2200_IN3_OSR_SHIFT, 1, 0),
1080
1081SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
1082 WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
1083SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
1084 WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
1085SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
1086 WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
1087
1088SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
1089 WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
1090SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
1091 WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
1092SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
1093 WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
1094
1095SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
1096 WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
1097 0xbf, 0, digital_tlv),
1098SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
1099 WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
1100 0xbf, 0, digital_tlv),
1101SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
1102 WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
1103 0xbf, 0, digital_tlv),
1104
1105SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
1106 WM2200_OUT1_OSR_SHIFT, 1, 0),
1107SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
1108 WM2200_OUT2_OSR_SHIFT, 1, 0),
1109
1110SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
1111 WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
1112SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
1113 WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
1114 digital_tlv),
1115SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
1116 WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
1117 0x46, 0, out_tlv),
1118
1119SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
1120 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
1121SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
1122 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
1123 digital_tlv),
1124SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
Mark Browna1b98e12012-10-02 19:10:43 +01001125 WM2200_SPK1R_MUTE_SHIFT, 1, 1),
Mark Brownd5315a22012-01-25 19:29:41 +00001126};
1127
1128WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
1129WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
1130WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
1131WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
1132
1133WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
1134WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
1135WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
1136WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
1137WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
1138WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
1139
1140WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
1141WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
1142
1143WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
1144WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
1145WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
1146WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
1147
Mark Brown09d5d582012-10-03 15:57:03 +01001148WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE);
1149WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE);
1150
Mark Brownd5315a22012-01-25 19:29:41 +00001151WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
1152WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
1153
1154#define WM2200_MUX(name, ctrl) \
1155 SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
1156
1157#define WM2200_MIXER_WIDGETS(name, name_str) \
1158 WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
1159 WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
1160 WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
1161 WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
1162 SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
1163
Mark Brown09d5d582012-10-03 15:57:03 +01001164#define WM2200_DSP_WIDGETS(name, name_str) \
1165 WM2200_MIXER_WIDGETS(name##L, name_str "L"), \
1166 WM2200_MIXER_WIDGETS(name##R, name_str "R"), \
1167 WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \
1168 WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \
1169 WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \
1170 WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \
1171 WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \
1172 WM2200_MUX(name_str " Aux 6", &name##_aux6_mux)
1173
Mark Brownd5315a22012-01-25 19:29:41 +00001174#define WM2200_MIXER_INPUT_ROUTES(name) \
1175 { name, "Tone Generator", "Tone Generator" }, \
Mark Brown999e0682012-10-02 19:30:17 +01001176 { name, "AEC Loopback", "AEC Loopback" }, \
Mark Brownd5315a22012-01-25 19:29:41 +00001177 { name, "IN1L", "IN1L PGA" }, \
1178 { name, "IN1R", "IN1R PGA" }, \
1179 { name, "IN2L", "IN2L PGA" }, \
1180 { name, "IN2R", "IN2R PGA" }, \
1181 { name, "IN3L", "IN3L PGA" }, \
1182 { name, "IN3R", "IN3R PGA" }, \
1183 { name, "DSP1.1", "DSP1" }, \
1184 { name, "DSP1.2", "DSP1" }, \
1185 { name, "DSP1.3", "DSP1" }, \
1186 { name, "DSP1.4", "DSP1" }, \
1187 { name, "DSP1.5", "DSP1" }, \
1188 { name, "DSP1.6", "DSP1" }, \
1189 { name, "DSP2.1", "DSP2" }, \
1190 { name, "DSP2.2", "DSP2" }, \
1191 { name, "DSP2.3", "DSP2" }, \
1192 { name, "DSP2.4", "DSP2" }, \
1193 { name, "DSP2.5", "DSP2" }, \
1194 { name, "DSP2.6", "DSP2" }, \
1195 { name, "AIF1RX1", "AIF1RX1" }, \
1196 { name, "AIF1RX2", "AIF1RX2" }, \
1197 { name, "AIF1RX3", "AIF1RX3" }, \
1198 { name, "AIF1RX4", "AIF1RX4" }, \
1199 { name, "AIF1RX5", "AIF1RX5" }, \
1200 { name, "AIF1RX6", "AIF1RX6" }, \
1201 { name, "EQL", "EQL" }, \
1202 { name, "EQR", "EQR" }, \
1203 { name, "LHPF1", "LHPF1" }, \
1204 { name, "LHPF2", "LHPF2" }
1205
1206#define WM2200_MIXER_ROUTES(widget, name) \
1207 { widget, NULL, name " Mixer" }, \
1208 { name " Mixer", NULL, name " Input 1" }, \
1209 { name " Mixer", NULL, name " Input 2" }, \
1210 { name " Mixer", NULL, name " Input 3" }, \
1211 { name " Mixer", NULL, name " Input 4" }, \
1212 WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
1213 WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
1214 WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
1215 WM2200_MIXER_INPUT_ROUTES(name " Input 4")
1216
Mark Brown09d5d582012-10-03 15:57:03 +01001217#define WM2200_DSP_AUX_ROUTES(name) \
1218 { name, NULL, name " Aux 1" }, \
1219 { name, NULL, name " Aux 2" }, \
1220 { name, NULL, name " Aux 3" }, \
1221 { name, NULL, name " Aux 4" }, \
1222 { name, NULL, name " Aux 5" }, \
1223 { name, NULL, name " Aux 6" }, \
1224 WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \
1225 WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \
1226 WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \
1227 WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \
1228 WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \
1229 WM2200_MIXER_INPUT_ROUTES(name " Aux 6")
Mark Brown999e0682012-10-02 19:30:17 +01001230
1231static const char *wm2200_aec_loopback_texts[] = {
1232 "OUT1L", "OUT1R", "OUT2L", "OUT2R",
1233};
1234
1235static const struct soc_enum wm2200_aec_loopback =
1236 SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
1237 WM2200_AEC_LOOPBACK_SRC_SHIFT,
1238 ARRAY_SIZE(wm2200_aec_loopback_texts),
1239 wm2200_aec_loopback_texts);
1240
1241static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
1242 SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
1243
Mark Brownd5315a22012-01-25 19:29:41 +00001244static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
1245SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
1246 NULL, 0),
1247SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
1248 NULL, 0),
1249SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
1250 NULL, 0),
1251SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
1252 0, NULL, 0),
1253SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
1254 0, NULL, 0),
Mark Brown822b4b82012-09-07 10:54:32 +08001255SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0),
1256SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20, 0),
Mark Brownd5315a22012-01-25 19:29:41 +00001257
1258SND_SOC_DAPM_INPUT("IN1L"),
1259SND_SOC_DAPM_INPUT("IN1R"),
1260SND_SOC_DAPM_INPUT("IN2L"),
1261SND_SOC_DAPM_INPUT("IN2R"),
1262SND_SOC_DAPM_INPUT("IN3L"),
1263SND_SOC_DAPM_INPUT("IN3R"),
1264
1265SND_SOC_DAPM_SIGGEN("TONE"),
1266SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
1267 WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
1268
1269SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
1270 NULL, 0),
1271SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
1272 NULL, 0),
1273SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
1274 NULL, 0),
1275SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
1276 NULL, 0),
1277SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
1278 NULL, 0),
1279SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
1280 NULL, 0),
1281
1282SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
1283 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
1284SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
1285 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
1286SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
1287 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
1288SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
1289 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
1290SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
1291 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
1292SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
1293 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
1294
1295SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
1296SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
1297
1298SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
1299 NULL, 0),
1300SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
1301 NULL, 0),
1302
Mark Brown09d5d582012-10-03 15:57:03 +01001303SND_SOC_DAPM_PGA_E("DSP1", WM2200_DSP1_CONTROL_30, WM2200_DSP1_SYS_ENA_SHIFT,
1304 0, NULL, 0, NULL, 0),
1305SND_SOC_DAPM_PGA_E("DSP2", WM2200_DSP2_CONTROL_30, WM2200_DSP2_SYS_ENA_SHIFT,
1306 0, NULL, 0, NULL, 0),
Mark Brownd5315a22012-01-25 19:29:41 +00001307
1308SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
1309 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
1310SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
1311 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
1312SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
1313 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
1314SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
1315 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
1316SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
1317 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
1318SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
1319 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
1320
Mark Brown999e0682012-10-02 19:30:17 +01001321SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
1322 WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
1323
Mark Brownd5315a22012-01-25 19:29:41 +00001324SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
1325 WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
1326SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
1327 WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
1328
1329SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1330 WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
1331SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1332 WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
1333SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1334 WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
1335
1336SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1337 WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
1338SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1339 WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
1340SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1341 WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
1342
1343SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1344 WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
1345SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1346 WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
1347SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1348 WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
1349
1350SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1351 WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
1352SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1353 WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
1354SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1355 WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
1356
1357SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
1358 0, NULL, 0),
1359SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
1360 0, NULL, 0),
1361
1362SND_SOC_DAPM_OUTPUT("EPOUTLN"),
1363SND_SOC_DAPM_OUTPUT("EPOUTLP"),
1364SND_SOC_DAPM_OUTPUT("EPOUTRN"),
1365SND_SOC_DAPM_OUTPUT("EPOUTRP"),
1366SND_SOC_DAPM_OUTPUT("SPK"),
1367
1368WM2200_MIXER_WIDGETS(EQL, "EQL"),
1369WM2200_MIXER_WIDGETS(EQR, "EQR"),
1370
1371WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
1372WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
1373
Mark Brown09d5d582012-10-03 15:57:03 +01001374WM2200_DSP_WIDGETS(DSP1, "DSP1"),
1375WM2200_DSP_WIDGETS(DSP2, "DSP2"),
Mark Brownd5315a22012-01-25 19:29:41 +00001376
1377WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
1378WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
1379WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
1380WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
1381WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
1382WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
1383
1384WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
1385WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
1386WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
1387WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
1388};
1389
1390static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
1391 /* Everything needs SYSCLK but only hook up things on the edge
1392 * of the chip */
1393 { "IN1L", NULL, "SYSCLK" },
1394 { "IN1R", NULL, "SYSCLK" },
1395 { "IN2L", NULL, "SYSCLK" },
1396 { "IN2R", NULL, "SYSCLK" },
1397 { "IN3L", NULL, "SYSCLK" },
1398 { "IN3R", NULL, "SYSCLK" },
1399 { "OUT1L", NULL, "SYSCLK" },
1400 { "OUT1R", NULL, "SYSCLK" },
1401 { "OUT2L", NULL, "SYSCLK" },
1402 { "OUT2R", NULL, "SYSCLK" },
1403 { "AIF1RX1", NULL, "SYSCLK" },
1404 { "AIF1RX2", NULL, "SYSCLK" },
1405 { "AIF1RX3", NULL, "SYSCLK" },
1406 { "AIF1RX4", NULL, "SYSCLK" },
1407 { "AIF1RX5", NULL, "SYSCLK" },
1408 { "AIF1RX6", NULL, "SYSCLK" },
1409 { "AIF1TX1", NULL, "SYSCLK" },
1410 { "AIF1TX2", NULL, "SYSCLK" },
1411 { "AIF1TX3", NULL, "SYSCLK" },
1412 { "AIF1TX4", NULL, "SYSCLK" },
1413 { "AIF1TX5", NULL, "SYSCLK" },
1414 { "AIF1TX6", NULL, "SYSCLK" },
1415
1416 { "IN1L", NULL, "AVDD" },
1417 { "IN1R", NULL, "AVDD" },
1418 { "IN2L", NULL, "AVDD" },
1419 { "IN2R", NULL, "AVDD" },
1420 { "IN3L", NULL, "AVDD" },
1421 { "IN3R", NULL, "AVDD" },
1422 { "OUT1L", NULL, "AVDD" },
1423 { "OUT1R", NULL, "AVDD" },
1424
1425 { "IN1L PGA", NULL, "IN1L" },
1426 { "IN1R PGA", NULL, "IN1R" },
1427 { "IN2L PGA", NULL, "IN2L" },
1428 { "IN2R PGA", NULL, "IN2R" },
1429 { "IN3L PGA", NULL, "IN3L" },
1430 { "IN3R PGA", NULL, "IN3R" },
1431
1432 { "Tone Generator", NULL, "TONE" },
1433
1434 { "CP2", NULL, "CPVDD" },
1435 { "MICBIAS1", NULL, "CP2" },
1436 { "MICBIAS2", NULL, "CP2" },
1437
1438 { "CP1", NULL, "CPVDD" },
1439 { "EPD_LN", NULL, "CP1" },
1440 { "EPD_LP", NULL, "CP1" },
1441 { "EPD_RN", NULL, "CP1" },
1442 { "EPD_RP", NULL, "CP1" },
1443
1444 { "EPD_LP", NULL, "OUT1L" },
1445 { "EPD_OUTP_LP", NULL, "EPD_LP" },
1446 { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
1447 { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
1448
1449 { "EPD_LN", NULL, "OUT1L" },
1450 { "EPD_OUTP_LN", NULL, "EPD_LN" },
1451 { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
1452 { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
1453
1454 { "EPD_RP", NULL, "OUT1R" },
1455 { "EPD_OUTP_RP", NULL, "EPD_RP" },
1456 { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
1457 { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
1458
1459 { "EPD_RN", NULL, "OUT1R" },
1460 { "EPD_OUTP_RN", NULL, "EPD_RN" },
1461 { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
1462 { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
1463
1464 { "SPK", NULL, "OUT2L" },
1465 { "SPK", NULL, "OUT2R" },
1466
Mark Brown999e0682012-10-02 19:30:17 +01001467 { "AEC Loopback", "OUT1L", "OUT1L" },
1468 { "AEC Loopback", "OUT1R", "OUT1R" },
1469 { "AEC Loopback", "OUT2L", "OUT2L" },
1470 { "AEC Loopback", "OUT2R", "OUT2R" },
1471
Mark Brownd5315a22012-01-25 19:29:41 +00001472 WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
1473 WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
1474 WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
1475 WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
1476
Mark Brown09d5d582012-10-03 15:57:03 +01001477 WM2200_DSP_AUX_ROUTES("DSP1"),
1478 WM2200_DSP_AUX_ROUTES("DSP2"),
1479
Mark Brownd5315a22012-01-25 19:29:41 +00001480 WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
1481 WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
1482 WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
1483 WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
1484
1485 WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
1486 WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
1487 WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
1488 WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
1489 WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
1490 WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
1491
1492 WM2200_MIXER_ROUTES("EQL", "EQL"),
1493 WM2200_MIXER_ROUTES("EQR", "EQR"),
1494
1495 WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
1496 WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
1497};
1498
1499static int wm2200_probe(struct snd_soc_codec *codec)
1500{
1501 struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
1502 int ret;
1503
1504 wm2200->codec = codec;
1505 codec->control_data = wm2200->regmap;
1506 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
1507
1508 ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
1509 if (ret != 0) {
1510 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1511 return ret;
1512 }
1513
1514 return ret;
1515}
1516
1517static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1518{
1519 struct snd_soc_codec *codec = dai->codec;
1520 int lrclk, bclk, fmt_val;
1521
1522 lrclk = 0;
1523 bclk = 0;
1524
1525 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1526 case SND_SOC_DAIFMT_DSP_A:
1527 fmt_val = 0;
1528 break;
1529 case SND_SOC_DAIFMT_DSP_B:
1530 fmt_val = 1;
1531 break;
1532 case SND_SOC_DAIFMT_I2S:
1533 fmt_val = 2;
1534 break;
1535 case SND_SOC_DAIFMT_LEFT_J:
1536 fmt_val = 3;
1537 break;
1538 default:
1539 dev_err(codec->dev, "Unsupported DAI format %d\n",
1540 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1541 return -EINVAL;
1542 }
1543
1544 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1545 case SND_SOC_DAIFMT_CBS_CFS:
1546 break;
1547 case SND_SOC_DAIFMT_CBS_CFM:
1548 lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
1549 break;
1550 case SND_SOC_DAIFMT_CBM_CFS:
1551 bclk |= WM2200_AIF1_BCLK_MSTR;
1552 break;
1553 case SND_SOC_DAIFMT_CBM_CFM:
1554 lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
1555 bclk |= WM2200_AIF1_BCLK_MSTR;
1556 break;
1557 default:
1558 dev_err(codec->dev, "Unsupported master mode %d\n",
1559 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1560 return -EINVAL;
1561 }
1562
1563 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1564 case SND_SOC_DAIFMT_NB_NF:
1565 break;
1566 case SND_SOC_DAIFMT_IB_IF:
1567 bclk |= WM2200_AIF1_BCLK_INV;
1568 lrclk |= WM2200_AIF1TX_LRCLK_INV;
1569 break;
1570 case SND_SOC_DAIFMT_IB_NF:
1571 bclk |= WM2200_AIF1_BCLK_INV;
1572 break;
1573 case SND_SOC_DAIFMT_NB_IF:
1574 lrclk |= WM2200_AIF1TX_LRCLK_INV;
1575 break;
1576 default:
1577 return -EINVAL;
1578 }
1579
1580 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
1581 WM2200_AIF1_BCLK_INV, bclk);
1582 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
1583 WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
1584 lrclk);
1585 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
1586 WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
1587 lrclk);
1588 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
1589 WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
1590
1591 return 0;
1592}
1593
1594static int wm2200_sr_code[] = {
1595 0,
1596 12000,
1597 24000,
1598 48000,
1599 96000,
1600 192000,
1601 384000,
1602 768000,
1603 0,
1604 11025,
1605 22050,
1606 44100,
1607 88200,
1608 176400,
1609 352800,
1610 705600,
1611 4000,
1612 8000,
1613 16000,
1614 32000,
1615 64000,
1616 128000,
1617 256000,
1618 512000,
1619};
1620
1621#define WM2200_NUM_BCLK_RATES 12
1622
1623static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
1624 6144000,
1625 3072000,
1626 2048000,
1627 1536000,
1628 768000,
1629 512000,
1630 384000,
1631 256000,
1632 192000,
1633 128000,
1634 96000,
1635 64000,
1636};
1637
1638static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
1639 5644800,
Mark Brownb0dfa452012-06-20 14:16:57 +01001640 3763200,
Mark Brownd5315a22012-01-25 19:29:41 +00001641 2882400,
1642 1881600,
1643 1411200,
1644 705600,
1645 470400,
1646 352800,
1647 176400,
1648 117600,
1649 88200,
1650 58800,
1651};
1652
1653static int wm2200_hw_params(struct snd_pcm_substream *substream,
1654 struct snd_pcm_hw_params *params,
1655 struct snd_soc_dai *dai)
1656{
1657 struct snd_soc_codec *codec = dai->codec;
1658 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1659 int i, bclk, lrclk, wl, fl, sr_code;
1660 int *bclk_rates;
1661
1662 /* Data sizes if not using TDM */
1663 wl = snd_pcm_format_width(params_format(params));
1664 if (wl < 0)
1665 return wl;
1666 fl = snd_soc_params_to_frame_size(params);
1667 if (fl < 0)
1668 return fl;
1669
1670 dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
1671 wl, fl);
1672
1673 /* Target BCLK rate */
1674 bclk = snd_soc_params_to_bclk(params);
1675 if (bclk < 0)
1676 return bclk;
1677
1678 if (!wm2200->sysclk) {
1679 dev_err(codec->dev, "SYSCLK has no rate set\n");
1680 return -EINVAL;
1681 }
1682
1683 for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
1684 if (wm2200_sr_code[i] == params_rate(params))
1685 break;
1686 if (i == ARRAY_SIZE(wm2200_sr_code)) {
1687 dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
1688 params_rate(params));
1689 return -EINVAL;
1690 }
1691 sr_code = i;
1692
1693 dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
1694 bclk, wm2200->sysclk);
1695
1696 if (wm2200->sysclk % 4000)
1697 bclk_rates = wm2200_bclk_rates_cd;
1698 else
1699 bclk_rates = wm2200_bclk_rates_dat;
1700
1701 for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
1702 if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
1703 break;
1704 if (i == WM2200_NUM_BCLK_RATES) {
1705 dev_err(codec->dev,
1706 "No valid BCLK for %dHz found from %dHz SYSCLK\n",
1707 bclk, wm2200->sysclk);
1708 return -EINVAL;
1709 }
1710
1711 bclk = i;
1712 dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
1713 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
1714 WM2200_AIF1_BCLK_DIV_MASK, bclk);
1715
1716 lrclk = bclk_rates[bclk] / params_rate(params);
1717 dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
1718 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
1719 dai->symmetric_rates)
1720 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
1721 WM2200_AIF1RX_BCPF_MASK, lrclk);
1722 else
1723 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
1724 WM2200_AIF1TX_BCPF_MASK, lrclk);
1725
1726 i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
1727 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1728 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
1729 WM2200_AIF1RX_WL_MASK |
1730 WM2200_AIF1RX_SLOT_LEN_MASK, i);
1731 else
1732 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
1733 WM2200_AIF1TX_WL_MASK |
1734 WM2200_AIF1TX_SLOT_LEN_MASK, i);
1735
1736 snd_soc_update_bits(codec, WM2200_CLOCKING_4,
1737 WM2200_SAMPLE_RATE_1_MASK, sr_code);
1738
1739 return 0;
1740}
1741
1742static const struct snd_soc_dai_ops wm2200_dai_ops = {
1743 .set_fmt = wm2200_set_fmt,
1744 .hw_params = wm2200_hw_params,
1745};
1746
1747static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1748 int source, unsigned int freq, int dir)
1749{
1750 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1751 int fval;
1752
1753 switch (clk_id) {
1754 case WM2200_CLK_SYSCLK:
1755 break;
1756
1757 default:
1758 dev_err(codec->dev, "Unknown clock %d\n", clk_id);
1759 return -EINVAL;
1760 }
1761
1762 switch (source) {
1763 case WM2200_CLKSRC_MCLK1:
1764 case WM2200_CLKSRC_MCLK2:
1765 case WM2200_CLKSRC_FLL:
1766 case WM2200_CLKSRC_BCLK1:
1767 break;
1768 default:
1769 dev_err(codec->dev, "Invalid source %d\n", source);
1770 return -EINVAL;
1771 }
1772
1773 switch (freq) {
1774 case 22579200:
1775 case 24576000:
1776 fval = 2;
1777 break;
1778 default:
1779 dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
1780 return -EINVAL;
1781 }
1782
1783 /* TODO: Check if MCLKs are in use and enable/disable pulls to
1784 * match.
1785 */
1786
1787 snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
1788 WM2200_SYSCLK_SRC_MASK,
1789 fval << WM2200_SYSCLK_FREQ_SHIFT | source);
1790
1791 wm2200->sysclk = freq;
1792
1793 return 0;
1794}
1795
1796struct _fll_div {
1797 u16 fll_fratio;
1798 u16 fll_outdiv;
1799 u16 fll_refclk_div;
1800 u16 n;
1801 u16 theta;
1802 u16 lambda;
1803};
1804
1805static struct {
1806 unsigned int min;
1807 unsigned int max;
1808 u16 fll_fratio;
1809 int ratio;
1810} fll_fratios[] = {
1811 { 0, 64000, 4, 16 },
1812 { 64000, 128000, 3, 8 },
1813 { 128000, 256000, 2, 4 },
1814 { 256000, 1000000, 1, 2 },
1815 { 1000000, 13500000, 0, 1 },
1816};
1817
1818static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
1819 unsigned int Fout)
1820{
1821 unsigned int target;
1822 unsigned int div;
1823 unsigned int fratio, gcd_fll;
1824 int i;
1825
1826 /* Fref must be <=13.5MHz */
1827 div = 1;
1828 fll_div->fll_refclk_div = 0;
1829 while ((Fref / div) > 13500000) {
1830 div *= 2;
1831 fll_div->fll_refclk_div++;
1832
1833 if (div > 8) {
1834 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
1835 Fref);
1836 return -EINVAL;
1837 }
1838 }
1839
1840 pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
1841
1842 /* Apply the division for our remaining calculations */
1843 Fref /= div;
1844
1845 /* Fvco should be 90-100MHz; don't check the upper bound */
1846 div = 2;
1847 while (Fout * div < 90000000) {
1848 div++;
1849 if (div > 64) {
1850 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
1851 Fout);
1852 return -EINVAL;
1853 }
1854 }
1855 target = Fout * div;
1856 fll_div->fll_outdiv = div - 1;
1857
1858 pr_debug("FLL Fvco=%dHz\n", target);
1859
1860 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1861 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1862 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1863 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
1864 fratio = fll_fratios[i].ratio;
1865 break;
1866 }
1867 }
1868 if (i == ARRAY_SIZE(fll_fratios)) {
1869 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
1870 return -EINVAL;
1871 }
1872
1873 fll_div->n = target / (fratio * Fref);
1874
1875 if (target % Fref == 0) {
1876 fll_div->theta = 0;
1877 fll_div->lambda = 0;
1878 } else {
1879 gcd_fll = gcd(target, fratio * Fref);
1880
1881 fll_div->theta = (target - (fll_div->n * fratio * Fref))
1882 / gcd_fll;
1883 fll_div->lambda = (fratio * Fref) / gcd_fll;
1884 }
1885
1886 pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
1887 fll_div->n, fll_div->theta, fll_div->lambda);
1888 pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
1889 fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
1890 fll_div->fll_refclk_div);
1891
1892 return 0;
1893}
1894
1895static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
1896 unsigned int Fref, unsigned int Fout)
1897{
1898 struct i2c_client *i2c = to_i2c_client(codec->dev);
1899 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1900 struct _fll_div factors;
1901 int ret, i, timeout;
1902
1903 if (!Fout) {
1904 dev_dbg(codec->dev, "FLL disabled");
1905
1906 if (wm2200->fll_fout)
1907 pm_runtime_put(codec->dev);
1908
1909 wm2200->fll_fout = 0;
1910 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
1911 WM2200_FLL_ENA, 0);
1912 return 0;
1913 }
1914
1915 switch (source) {
1916 case WM2200_FLL_SRC_MCLK1:
1917 case WM2200_FLL_SRC_MCLK2:
1918 case WM2200_FLL_SRC_BCLK:
1919 break;
1920 default:
1921 dev_err(codec->dev, "Invalid FLL source %d\n", source);
1922 return -EINVAL;
1923 }
1924
1925 ret = fll_factors(&factors, Fref, Fout);
1926 if (ret < 0)
1927 return ret;
1928
1929 /* Disable the FLL while we reconfigure */
1930 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
1931
1932 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
1933 WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
1934 (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
1935 factors.fll_fratio);
1936 if (factors.theta) {
1937 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
1938 WM2200_FLL_FRACN_ENA,
1939 WM2200_FLL_FRACN_ENA);
1940 snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
1941 WM2200_FLL_EFS_ENA,
1942 WM2200_FLL_EFS_ENA);
1943 } else {
1944 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
1945 WM2200_FLL_FRACN_ENA, 0);
1946 snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
1947 WM2200_FLL_EFS_ENA, 0);
1948 }
1949
1950 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
1951 factors.theta);
1952 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
1953 factors.n);
1954 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
1955 WM2200_FLL_CLK_REF_DIV_MASK |
1956 WM2200_FLL_CLK_REF_SRC_MASK,
1957 (factors.fll_refclk_div
1958 << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
1959 snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
1960 WM2200_FLL_LAMBDA_MASK, factors.lambda);
1961
1962 /* Clear any pending completions */
1963 try_wait_for_completion(&wm2200->fll_lock);
1964
1965 pm_runtime_get_sync(codec->dev);
1966
1967 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
1968 WM2200_FLL_ENA, WM2200_FLL_ENA);
1969
1970 if (i2c->irq)
1971 timeout = 2;
1972 else
1973 timeout = 50;
1974
1975 snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
1976 WM2200_SYSCLK_ENA);
1977
1978 /* Poll for the lock; will use the interrupt to exit quickly */
1979 for (i = 0; i < timeout; i++) {
1980 if (i2c->irq) {
1981 ret = wait_for_completion_timeout(&wm2200->fll_lock,
1982 msecs_to_jiffies(25));
1983 if (ret > 0)
1984 break;
1985 } else {
1986 msleep(1);
1987 }
1988
1989 ret = snd_soc_read(codec,
1990 WM2200_INTERRUPT_RAW_STATUS_2);
1991 if (ret < 0) {
1992 dev_err(codec->dev,
1993 "Failed to read FLL status: %d\n",
1994 ret);
1995 continue;
1996 }
1997 if (ret & WM2200_FLL_LOCK_STS)
1998 break;
1999 }
2000 if (i == timeout) {
2001 dev_err(codec->dev, "FLL lock timed out\n");
2002 pm_runtime_put(codec->dev);
2003 return -ETIMEDOUT;
2004 }
2005
2006 wm2200->fll_src = source;
2007 wm2200->fll_fref = Fref;
2008 wm2200->fll_fout = Fout;
2009
2010 dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
2011
2012 return 0;
2013}
2014
2015static int wm2200_dai_probe(struct snd_soc_dai *dai)
2016{
2017 struct snd_soc_codec *codec = dai->codec;
2018 unsigned int val = 0;
2019 int ret;
2020
2021 ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
2022 if (ret >= 0) {
2023 if ((ret & WM2200_GP1_FN_MASK) != 0) {
2024 dai->symmetric_rates = true;
2025 val = WM2200_AIF1TX_LRCLK_SRC;
2026 }
2027 } else {
2028 dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
2029 }
2030
2031 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
2032 WM2200_AIF1TX_LRCLK_SRC, val);
2033
2034 return 0;
2035}
2036
2037#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
2038
2039#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
2040 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
2041
2042static struct snd_soc_dai_driver wm2200_dai = {
2043 .name = "wm2200",
2044 .probe = wm2200_dai_probe,
2045 .playback = {
2046 .stream_name = "Playback",
2047 .channels_min = 2,
2048 .channels_max = 2,
2049 .rates = WM2200_RATES,
2050 .formats = WM2200_FORMATS,
2051 },
2052 .capture = {
2053 .stream_name = "Capture",
2054 .channels_min = 2,
2055 .channels_max = 2,
2056 .rates = WM2200_RATES,
2057 .formats = WM2200_FORMATS,
2058 },
2059 .ops = &wm2200_dai_ops,
2060};
2061
2062static struct snd_soc_codec_driver soc_codec_wm2200 = {
2063 .probe = wm2200_probe,
2064
2065 .idle_bias_off = true,
Mark Brown17c0cee2012-02-08 18:35:43 +00002066 .ignore_pmdown_time = true,
Mark Brownd5315a22012-01-25 19:29:41 +00002067 .set_sysclk = wm2200_set_sysclk,
2068 .set_pll = wm2200_set_fll,
2069
2070 .controls = wm2200_snd_controls,
2071 .num_controls = ARRAY_SIZE(wm2200_snd_controls),
2072 .dapm_widgets = wm2200_dapm_widgets,
2073 .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
2074 .dapm_routes = wm2200_dapm_routes,
2075 .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
2076};
2077
2078static irqreturn_t wm2200_irq(int irq, void *data)
2079{
2080 struct wm2200_priv *wm2200 = data;
2081 unsigned int val, mask;
2082 int ret;
2083
2084 ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
2085 if (ret != 0) {
2086 dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
2087 return IRQ_NONE;
2088 }
2089
2090 ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
2091 &mask);
2092 if (ret != 0) {
2093 dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
2094 mask = 0;
2095 }
2096
2097 val &= ~mask;
2098
2099 if (val & WM2200_FLL_LOCK_EINT) {
2100 dev_dbg(wm2200->dev, "FLL locked\n");
2101 complete(&wm2200->fll_lock);
2102 }
2103
2104 if (val) {
2105 regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
2106
2107 return IRQ_HANDLED;
2108 } else {
2109 return IRQ_NONE;
2110 }
2111}
2112
2113static const struct regmap_config wm2200_regmap = {
2114 .reg_bits = 16,
2115 .val_bits = 16,
2116
Mark Browneae23282012-10-02 20:14:49 +01002117 .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
2118 WM2200_DSP_SPACING),
Mark Brownd5315a22012-01-25 19:29:41 +00002119 .reg_defaults = wm2200_reg_defaults,
2120 .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
2121 .volatile_reg = wm2200_volatile_register,
2122 .readable_reg = wm2200_readable_register,
2123 .cache_type = REGCACHE_RBTREE,
Mark Browneae23282012-10-02 20:14:49 +01002124 .ranges = wm2200_ranges,
2125 .num_ranges = ARRAY_SIZE(wm2200_ranges),
Mark Brownd5315a22012-01-25 19:29:41 +00002126};
2127
2128static const unsigned int wm2200_dig_vu[] = {
2129 WM2200_DAC_DIGITAL_VOLUME_1L,
2130 WM2200_DAC_DIGITAL_VOLUME_1R,
2131 WM2200_DAC_DIGITAL_VOLUME_2L,
2132 WM2200_DAC_DIGITAL_VOLUME_2R,
2133 WM2200_ADC_DIGITAL_VOLUME_1L,
2134 WM2200_ADC_DIGITAL_VOLUME_1R,
2135 WM2200_ADC_DIGITAL_VOLUME_2L,
2136 WM2200_ADC_DIGITAL_VOLUME_2R,
2137 WM2200_ADC_DIGITAL_VOLUME_3L,
2138 WM2200_ADC_DIGITAL_VOLUME_3R,
2139};
2140
2141static const unsigned int wm2200_mic_ctrl_reg[] = {
2142 WM2200_IN1L_CONTROL,
2143 WM2200_IN2L_CONTROL,
2144 WM2200_IN3L_CONTROL,
2145};
2146
2147static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
2148 const struct i2c_device_id *id)
2149{
2150 struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
2151 struct wm2200_priv *wm2200;
2152 unsigned int reg;
2153 int ret, i;
2154
2155 wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
2156 GFP_KERNEL);
2157 if (wm2200 == NULL)
2158 return -ENOMEM;
2159
2160 wm2200->dev = &i2c->dev;
2161 init_completion(&wm2200->fll_lock);
2162
Mark Brown98ad0892012-10-01 19:27:45 +01002163 wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
Mark Brownd5315a22012-01-25 19:29:41 +00002164 if (IS_ERR(wm2200->regmap)) {
2165 ret = PTR_ERR(wm2200->regmap);
2166 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
2167 ret);
2168 goto err;
2169 }
2170
2171 if (pdata)
2172 wm2200->pdata = *pdata;
2173
2174 i2c_set_clientdata(i2c, wm2200);
2175
2176 for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
2177 wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
2178
Mark Brown98ad0892012-10-01 19:27:45 +01002179 ret = devm_regulator_bulk_get(&i2c->dev,
2180 ARRAY_SIZE(wm2200->core_supplies),
2181 wm2200->core_supplies);
Mark Brownd5315a22012-01-25 19:29:41 +00002182 if (ret != 0) {
2183 dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
2184 ret);
2185 goto err_regmap;
2186 }
2187
2188 ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
2189 wm2200->core_supplies);
2190 if (ret != 0) {
2191 dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
2192 ret);
2193 goto err_core;
2194 }
2195
2196 if (wm2200->pdata.ldo_ena) {
Mark Brown98ad0892012-10-01 19:27:45 +01002197 ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
2198 GPIOF_OUT_INIT_HIGH,
2199 "WM2200 LDOENA");
Mark Brownd5315a22012-01-25 19:29:41 +00002200 if (ret < 0) {
2201 dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
2202 wm2200->pdata.ldo_ena, ret);
2203 goto err_enable;
2204 }
2205 msleep(2);
2206 }
2207
2208 if (wm2200->pdata.reset) {
Mark Brown98ad0892012-10-01 19:27:45 +01002209 ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
2210 GPIOF_OUT_INIT_HIGH,
2211 "WM2200 /RESET");
Mark Brownd5315a22012-01-25 19:29:41 +00002212 if (ret < 0) {
2213 dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
2214 wm2200->pdata.reset, ret);
2215 goto err_ldo;
2216 }
2217 }
2218
2219 ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
2220 if (ret < 0) {
2221 dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
2222 goto err_reset;
2223 }
2224 switch (reg) {
2225 case 0x2200:
2226 break;
2227
2228 default:
2229 dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
2230 ret = -EINVAL;
2231 goto err_reset;
2232 }
2233
2234 ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
2235 if (ret < 0) {
2236 dev_err(&i2c->dev, "Failed to read revision register\n");
2237 goto err_reset;
2238 }
2239
Axel Lin916be222012-02-16 10:05:59 +08002240 wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
Mark Brownd5315a22012-01-25 19:29:41 +00002241
2242 dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
2243
2244 switch (wm2200->rev) {
2245 case 0:
Mark Brown5ae9eb42012-10-02 12:02:48 +01002246 case 1:
Mark Brownd5315a22012-01-25 19:29:41 +00002247 ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
2248 ARRAY_SIZE(wm2200_reva_patch));
2249 if (ret != 0) {
2250 dev_err(&i2c->dev, "Failed to register patch: %d\n",
2251 ret);
2252 }
2253 break;
2254 default:
2255 break;
2256 }
2257
2258 ret = wm2200_reset(wm2200);
2259 if (ret < 0) {
2260 dev_err(&i2c->dev, "Failed to issue reset\n");
2261 goto err_reset;
2262 }
2263
2264 for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
2265 if (!wm2200->pdata.gpio_defaults[i])
2266 continue;
2267
2268 regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
2269 wm2200->pdata.gpio_defaults[i]);
2270 }
2271
2272 for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
2273 regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
2274 WM2200_OUT_VU, WM2200_OUT_VU);
2275
2276 /* Assign slots 1-6 to channels 1-6 for both TX and RX */
2277 for (i = 0; i < 6; i++) {
2278 regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
2279 regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
2280 }
2281
2282 for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
2283 regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
2284 WM2200_IN1_MODE_MASK |
2285 WM2200_IN1_DMIC_SUP_MASK,
2286 (wm2200->pdata.in_mode[i] <<
2287 WM2200_IN1_MODE_SHIFT) |
2288 (wm2200->pdata.dmic_sup[i] <<
2289 WM2200_IN1_DMIC_SUP_SHIFT));
2290 }
2291
2292 if (i2c->irq) {
2293 ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
2294 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
2295 "wm2200", wm2200);
2296 if (ret == 0)
2297 regmap_update_bits(wm2200->regmap,
2298 WM2200_INTERRUPT_STATUS_2_MASK,
2299 WM2200_FLL_LOCK_EINT, 0);
2300 else
2301 dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
2302 i2c->irq, ret);
2303 }
2304
2305 pm_runtime_set_active(&i2c->dev);
2306 pm_runtime_enable(&i2c->dev);
2307 pm_request_idle(&i2c->dev);
2308
2309 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
2310 &wm2200_dai, 1);
2311 if (ret != 0) {
2312 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
2313 goto err_pm_runtime;
2314 }
2315
2316 return 0;
2317
2318err_pm_runtime:
2319 pm_runtime_disable(&i2c->dev);
2320err_reset:
Mark Brown98ad0892012-10-01 19:27:45 +01002321 if (wm2200->pdata.reset)
Mark Brownd5315a22012-01-25 19:29:41 +00002322 gpio_set_value_cansleep(wm2200->pdata.reset, 0);
Mark Brownd5315a22012-01-25 19:29:41 +00002323err_ldo:
Mark Brown98ad0892012-10-01 19:27:45 +01002324 if (wm2200->pdata.ldo_ena)
Mark Brownd5315a22012-01-25 19:29:41 +00002325 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
Mark Brownd5315a22012-01-25 19:29:41 +00002326err_enable:
2327 regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
2328 wm2200->core_supplies);
2329err_core:
Mark Brownd5315a22012-01-25 19:29:41 +00002330err_regmap:
Mark Brownd5315a22012-01-25 19:29:41 +00002331err:
2332 return ret;
2333}
2334
2335static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
2336{
2337 struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
2338
2339 snd_soc_unregister_codec(&i2c->dev);
2340 if (i2c->irq)
2341 free_irq(i2c->irq, wm2200);
Mark Brown98ad0892012-10-01 19:27:45 +01002342 if (wm2200->pdata.reset)
Mark Brownd5315a22012-01-25 19:29:41 +00002343 gpio_set_value_cansleep(wm2200->pdata.reset, 0);
Mark Brown98ad0892012-10-01 19:27:45 +01002344 if (wm2200->pdata.ldo_ena)
Mark Brownd5315a22012-01-25 19:29:41 +00002345 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
Mark Brownd5315a22012-01-25 19:29:41 +00002346
2347 return 0;
2348}
2349
2350#ifdef CONFIG_PM_RUNTIME
2351static int wm2200_runtime_suspend(struct device *dev)
2352{
2353 struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
2354
2355 regcache_cache_only(wm2200->regmap, true);
2356 regcache_mark_dirty(wm2200->regmap);
2357 if (wm2200->pdata.ldo_ena)
2358 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
2359 regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
2360 wm2200->core_supplies);
2361
2362 return 0;
2363}
2364
2365static int wm2200_runtime_resume(struct device *dev)
2366{
2367 struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
2368 int ret;
2369
2370 ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
2371 wm2200->core_supplies);
2372 if (ret != 0) {
2373 dev_err(dev, "Failed to enable supplies: %d\n",
2374 ret);
2375 return ret;
2376 }
2377
2378 if (wm2200->pdata.ldo_ena) {
2379 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
2380 msleep(2);
2381 }
2382
2383 regcache_cache_only(wm2200->regmap, false);
2384 regcache_sync(wm2200->regmap);
2385
2386 return 0;
2387}
2388#endif
2389
2390static struct dev_pm_ops wm2200_pm = {
2391 SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
2392 NULL)
2393};
2394
2395static const struct i2c_device_id wm2200_i2c_id[] = {
2396 { "wm2200", 0 },
2397 { }
2398};
2399MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
2400
2401static struct i2c_driver wm2200_i2c_driver = {
2402 .driver = {
2403 .name = "wm2200",
2404 .owner = THIS_MODULE,
2405 .pm = &wm2200_pm,
2406 },
2407 .probe = wm2200_i2c_probe,
2408 .remove = __devexit_p(wm2200_i2c_remove),
2409 .id_table = wm2200_i2c_id,
2410};
2411
Sachin Kamata9418dd2012-08-06 17:25:53 +05302412module_i2c_driver(wm2200_i2c_driver);
Mark Brownd5315a22012-01-25 19:29:41 +00002413
2414MODULE_DESCRIPTION("ASoC WM2200 driver");
2415MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2416MODULE_LICENSE("GPL");