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