blob: 9932aacaa5b87a8b67fd4865b32c348700123e39 [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",
883 "AEC loopback",
884 "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",
Mark Brownd5315a22012-01-25 19:29:41 +0000900 "DSP1.1",
901 "DSP1.2",
902 "DSP1.3",
903 "DSP1.4",
904 "DSP1.5",
905 "DSP1.6",
906 "DSP2.1",
907 "DSP2.2",
908 "DSP2.3",
909 "DSP2.4",
910 "DSP2.5",
911 "DSP2.6",
912};
913
914static int wm2200_mixer_values[] = {
915 0x00,
916 0x04, /* Tone */
917 0x08, /* AEC */
918 0x10, /* Input */
919 0x11,
920 0x12,
921 0x13,
922 0x14,
923 0x15,
924 0x20, /* AIF */
925 0x21,
926 0x22,
927 0x23,
928 0x24,
929 0x25,
930 0x50, /* EQ */
931 0x51,
Mark Brownd5315a22012-01-25 19:29:41 +0000932 0x60, /* LHPF1 */
933 0x61, /* LHPF2 */
934 0x68, /* DSP1 */
935 0x69,
936 0x6a,
937 0x6b,
938 0x6c,
939 0x6d,
940 0x70, /* DSP2 */
941 0x71,
942 0x72,
943 0x73,
944 0x74,
945 0x75,
946};
947
948#define WM2200_MIXER_CONTROLS(name, base) \
949 SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
950 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
951 SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
952 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
953 SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
954 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
955 SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
956 WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
957
958#define WM2200_MUX_ENUM_DECL(name, reg) \
959 SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
960 wm2200_mixer_texts, wm2200_mixer_values)
961
962#define WM2200_MUX_CTL_DECL(name) \
963 const struct snd_kcontrol_new name##_mux = \
964 SOC_DAPM_VALUE_ENUM("Route", name##_enum)
965
966#define WM2200_MIXER_ENUMS(name, base_reg) \
967 static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
968 static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
969 static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
970 static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
971 static WM2200_MUX_CTL_DECL(name##_in1); \
972 static WM2200_MUX_CTL_DECL(name##_in2); \
973 static WM2200_MUX_CTL_DECL(name##_in3); \
Mark Brownffa8d9d2012-01-29 21:45:31 +0000974 static WM2200_MUX_CTL_DECL(name##_in4)
Mark Brownd5315a22012-01-25 19:29:41 +0000975
976static const struct snd_kcontrol_new wm2200_snd_controls[] = {
977SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
978 WM2200_IN1_OSR_SHIFT, 1, 0),
979SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
980 WM2200_IN2_OSR_SHIFT, 1, 0),
981SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
982 WM2200_IN3_OSR_SHIFT, 1, 0),
983
984SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
985 WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
986SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
987 WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
988SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
989 WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
990
991SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
992 WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
Chris Rattray03e578b2013-02-01 15:51:41 +0000993SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_2L,
Mark Brownd5315a22012-01-25 19:29:41 +0000994 WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
Chris Rattray03e578b2013-02-01 15:51:41 +0000995SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_3L,
Mark Brownd5315a22012-01-25 19:29:41 +0000996 WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
997
998SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
999 WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
1000 0xbf, 0, digital_tlv),
1001SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
1002 WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
1003 0xbf, 0, digital_tlv),
1004SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
1005 WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
1006 0xbf, 0, digital_tlv),
1007
1008SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
1009 WM2200_OUT1_OSR_SHIFT, 1, 0),
1010SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
1011 WM2200_OUT2_OSR_SHIFT, 1, 0),
1012
1013SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
1014 WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
1015SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
1016 WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
1017 digital_tlv),
1018SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
1019 WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
1020 0x46, 0, out_tlv),
1021
1022SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
1023 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
1024SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
1025 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
1026 digital_tlv),
1027SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
Mark Browneb695ee2012-10-02 19:10:43 +01001028 WM2200_SPK1R_MUTE_SHIFT, 1, 1),
Mark Brownd5315a22012-01-25 19:29:41 +00001029};
1030
1031WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
1032WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
1033WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
1034WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
1035
1036WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
1037WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
1038WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
1039WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
1040WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
1041WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
1042
1043WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
1044WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
1045
1046WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
1047WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
1048WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
1049WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
1050
1051WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
1052WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
1053
1054#define WM2200_MUX(name, ctrl) \
1055 SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
1056
1057#define WM2200_MIXER_WIDGETS(name, name_str) \
1058 WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
1059 WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
1060 WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
1061 WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
1062 SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
1063
1064#define WM2200_MIXER_INPUT_ROUTES(name) \
1065 { name, "Tone Generator", "Tone Generator" }, \
1066 { name, "IN1L", "IN1L PGA" }, \
1067 { name, "IN1R", "IN1R PGA" }, \
1068 { name, "IN2L", "IN2L PGA" }, \
1069 { name, "IN2R", "IN2R PGA" }, \
1070 { name, "IN3L", "IN3L PGA" }, \
1071 { name, "IN3R", "IN3R PGA" }, \
1072 { name, "DSP1.1", "DSP1" }, \
1073 { name, "DSP1.2", "DSP1" }, \
1074 { name, "DSP1.3", "DSP1" }, \
1075 { name, "DSP1.4", "DSP1" }, \
1076 { name, "DSP1.5", "DSP1" }, \
1077 { name, "DSP1.6", "DSP1" }, \
1078 { name, "DSP2.1", "DSP2" }, \
1079 { name, "DSP2.2", "DSP2" }, \
1080 { name, "DSP2.3", "DSP2" }, \
1081 { name, "DSP2.4", "DSP2" }, \
1082 { name, "DSP2.5", "DSP2" }, \
1083 { name, "DSP2.6", "DSP2" }, \
1084 { name, "AIF1RX1", "AIF1RX1" }, \
1085 { name, "AIF1RX2", "AIF1RX2" }, \
1086 { name, "AIF1RX3", "AIF1RX3" }, \
1087 { name, "AIF1RX4", "AIF1RX4" }, \
1088 { name, "AIF1RX5", "AIF1RX5" }, \
1089 { name, "AIF1RX6", "AIF1RX6" }, \
1090 { name, "EQL", "EQL" }, \
1091 { name, "EQR", "EQR" }, \
1092 { name, "LHPF1", "LHPF1" }, \
1093 { name, "LHPF2", "LHPF2" }
1094
1095#define WM2200_MIXER_ROUTES(widget, name) \
1096 { widget, NULL, name " Mixer" }, \
1097 { name " Mixer", NULL, name " Input 1" }, \
1098 { name " Mixer", NULL, name " Input 2" }, \
1099 { name " Mixer", NULL, name " Input 3" }, \
1100 { name " Mixer", NULL, name " Input 4" }, \
1101 WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
1102 WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
1103 WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
1104 WM2200_MIXER_INPUT_ROUTES(name " Input 4")
1105
1106static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
1107SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
1108 NULL, 0),
1109SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
1110 NULL, 0),
1111SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
1112 NULL, 0),
1113SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
1114 0, NULL, 0),
1115SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
1116 0, NULL, 0),
1117SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
1118SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20),
1119
1120SND_SOC_DAPM_INPUT("IN1L"),
1121SND_SOC_DAPM_INPUT("IN1R"),
1122SND_SOC_DAPM_INPUT("IN2L"),
1123SND_SOC_DAPM_INPUT("IN2R"),
1124SND_SOC_DAPM_INPUT("IN3L"),
1125SND_SOC_DAPM_INPUT("IN3R"),
1126
1127SND_SOC_DAPM_SIGGEN("TONE"),
1128SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
1129 WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
1130
1131SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
1132 NULL, 0),
1133SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
1134 NULL, 0),
1135SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
1136 NULL, 0),
1137SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
1138 NULL, 0),
1139SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
1140 NULL, 0),
1141SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
1142 NULL, 0),
1143
1144SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
1145 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
1146SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
1147 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
1148SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
1149 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
1150SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
1151 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
1152SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
1153 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
1154SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
1155 WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
1156
1157SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
1158SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
1159
1160SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
1161 NULL, 0),
1162SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
1163 NULL, 0),
1164
1165SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
1166SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
1167
1168SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
1169 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
1170SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
1171 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
1172SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
1173 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
1174SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
1175 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
1176SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
1177 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
1178SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
1179 WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
1180
1181SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
1182 WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
1183SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
1184 WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
1185
1186SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1187 WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
1188SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1189 WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
1190SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
1191 WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
1192
1193SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1194 WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
1195SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1196 WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
1197SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
1198 WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
1199
1200SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1201 WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
1202SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1203 WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
1204SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
1205 WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
1206
1207SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1208 WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
1209SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1210 WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
1211SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
1212 WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
1213
1214SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
1215 0, NULL, 0),
1216SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
1217 0, NULL, 0),
1218
1219SND_SOC_DAPM_OUTPUT("EPOUTLN"),
1220SND_SOC_DAPM_OUTPUT("EPOUTLP"),
1221SND_SOC_DAPM_OUTPUT("EPOUTRN"),
1222SND_SOC_DAPM_OUTPUT("EPOUTRP"),
1223SND_SOC_DAPM_OUTPUT("SPK"),
1224
1225WM2200_MIXER_WIDGETS(EQL, "EQL"),
1226WM2200_MIXER_WIDGETS(EQR, "EQR"),
1227
1228WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
1229WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
1230
1231WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
1232WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
1233WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
1234WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
1235
1236WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
1237WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
1238WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
1239WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
1240WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
1241WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
1242
1243WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
1244WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
1245WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
1246WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
1247};
1248
1249static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
1250 /* Everything needs SYSCLK but only hook up things on the edge
1251 * of the chip */
1252 { "IN1L", NULL, "SYSCLK" },
1253 { "IN1R", NULL, "SYSCLK" },
1254 { "IN2L", NULL, "SYSCLK" },
1255 { "IN2R", NULL, "SYSCLK" },
1256 { "IN3L", NULL, "SYSCLK" },
1257 { "IN3R", NULL, "SYSCLK" },
1258 { "OUT1L", NULL, "SYSCLK" },
1259 { "OUT1R", NULL, "SYSCLK" },
1260 { "OUT2L", NULL, "SYSCLK" },
1261 { "OUT2R", NULL, "SYSCLK" },
1262 { "AIF1RX1", NULL, "SYSCLK" },
1263 { "AIF1RX2", NULL, "SYSCLK" },
1264 { "AIF1RX3", NULL, "SYSCLK" },
1265 { "AIF1RX4", NULL, "SYSCLK" },
1266 { "AIF1RX5", NULL, "SYSCLK" },
1267 { "AIF1RX6", NULL, "SYSCLK" },
1268 { "AIF1TX1", NULL, "SYSCLK" },
1269 { "AIF1TX2", NULL, "SYSCLK" },
1270 { "AIF1TX3", NULL, "SYSCLK" },
1271 { "AIF1TX4", NULL, "SYSCLK" },
1272 { "AIF1TX5", NULL, "SYSCLK" },
1273 { "AIF1TX6", NULL, "SYSCLK" },
1274
1275 { "IN1L", NULL, "AVDD" },
1276 { "IN1R", NULL, "AVDD" },
1277 { "IN2L", NULL, "AVDD" },
1278 { "IN2R", NULL, "AVDD" },
1279 { "IN3L", NULL, "AVDD" },
1280 { "IN3R", NULL, "AVDD" },
1281 { "OUT1L", NULL, "AVDD" },
1282 { "OUT1R", NULL, "AVDD" },
1283
1284 { "IN1L PGA", NULL, "IN1L" },
1285 { "IN1R PGA", NULL, "IN1R" },
1286 { "IN2L PGA", NULL, "IN2L" },
1287 { "IN2R PGA", NULL, "IN2R" },
1288 { "IN3L PGA", NULL, "IN3L" },
1289 { "IN3R PGA", NULL, "IN3R" },
1290
1291 { "Tone Generator", NULL, "TONE" },
1292
1293 { "CP2", NULL, "CPVDD" },
1294 { "MICBIAS1", NULL, "CP2" },
1295 { "MICBIAS2", NULL, "CP2" },
1296
1297 { "CP1", NULL, "CPVDD" },
1298 { "EPD_LN", NULL, "CP1" },
1299 { "EPD_LP", NULL, "CP1" },
1300 { "EPD_RN", NULL, "CP1" },
1301 { "EPD_RP", NULL, "CP1" },
1302
1303 { "EPD_LP", NULL, "OUT1L" },
1304 { "EPD_OUTP_LP", NULL, "EPD_LP" },
1305 { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
1306 { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
1307
1308 { "EPD_LN", NULL, "OUT1L" },
1309 { "EPD_OUTP_LN", NULL, "EPD_LN" },
1310 { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
1311 { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
1312
1313 { "EPD_RP", NULL, "OUT1R" },
1314 { "EPD_OUTP_RP", NULL, "EPD_RP" },
1315 { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
1316 { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
1317
1318 { "EPD_RN", NULL, "OUT1R" },
1319 { "EPD_OUTP_RN", NULL, "EPD_RN" },
1320 { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
1321 { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
1322
1323 { "SPK", NULL, "OUT2L" },
1324 { "SPK", NULL, "OUT2R" },
1325
1326 WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
1327 WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
1328 WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
1329 WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
1330
1331 WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
1332 WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
1333 WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
1334 WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
1335
1336 WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
1337 WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
1338 WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
1339 WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
1340 WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
1341 WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
1342
1343 WM2200_MIXER_ROUTES("EQL", "EQL"),
1344 WM2200_MIXER_ROUTES("EQR", "EQR"),
1345
1346 WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
1347 WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
1348};
1349
1350static int wm2200_probe(struct snd_soc_codec *codec)
1351{
1352 struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
1353 int ret;
1354
1355 wm2200->codec = codec;
1356 codec->control_data = wm2200->regmap;
1357 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
1358
1359 ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
1360 if (ret != 0) {
1361 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1362 return ret;
1363 }
1364
1365 return ret;
1366}
1367
1368static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1369{
1370 struct snd_soc_codec *codec = dai->codec;
1371 int lrclk, bclk, fmt_val;
1372
1373 lrclk = 0;
1374 bclk = 0;
1375
1376 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1377 case SND_SOC_DAIFMT_DSP_A:
1378 fmt_val = 0;
1379 break;
Mark Brownd5315a22012-01-25 19:29:41 +00001380 case SND_SOC_DAIFMT_I2S:
1381 fmt_val = 2;
1382 break;
Mark Brownd5315a22012-01-25 19:29:41 +00001383 default:
1384 dev_err(codec->dev, "Unsupported DAI format %d\n",
1385 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1386 return -EINVAL;
1387 }
1388
1389 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1390 case SND_SOC_DAIFMT_CBS_CFS:
1391 break;
1392 case SND_SOC_DAIFMT_CBS_CFM:
1393 lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
1394 break;
1395 case SND_SOC_DAIFMT_CBM_CFS:
1396 bclk |= WM2200_AIF1_BCLK_MSTR;
1397 break;
1398 case SND_SOC_DAIFMT_CBM_CFM:
1399 lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
1400 bclk |= WM2200_AIF1_BCLK_MSTR;
1401 break;
1402 default:
1403 dev_err(codec->dev, "Unsupported master mode %d\n",
1404 fmt & SND_SOC_DAIFMT_MASTER_MASK);
1405 return -EINVAL;
1406 }
1407
1408 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1409 case SND_SOC_DAIFMT_NB_NF:
1410 break;
1411 case SND_SOC_DAIFMT_IB_IF:
1412 bclk |= WM2200_AIF1_BCLK_INV;
1413 lrclk |= WM2200_AIF1TX_LRCLK_INV;
1414 break;
1415 case SND_SOC_DAIFMT_IB_NF:
1416 bclk |= WM2200_AIF1_BCLK_INV;
1417 break;
1418 case SND_SOC_DAIFMT_NB_IF:
1419 lrclk |= WM2200_AIF1TX_LRCLK_INV;
1420 break;
1421 default:
1422 return -EINVAL;
1423 }
1424
1425 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
1426 WM2200_AIF1_BCLK_INV, bclk);
1427 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
1428 WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
1429 lrclk);
1430 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
1431 WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
1432 lrclk);
1433 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
Axel Linbc856432012-12-21 16:28:37 +08001434 WM2200_AIF1_FMT_MASK, fmt_val);
Mark Brownd5315a22012-01-25 19:29:41 +00001435
1436 return 0;
1437}
1438
1439static int wm2200_sr_code[] = {
1440 0,
1441 12000,
1442 24000,
1443 48000,
1444 96000,
1445 192000,
1446 384000,
1447 768000,
1448 0,
1449 11025,
1450 22050,
1451 44100,
1452 88200,
1453 176400,
1454 352800,
1455 705600,
1456 4000,
1457 8000,
1458 16000,
1459 32000,
1460 64000,
1461 128000,
1462 256000,
1463 512000,
1464};
1465
1466#define WM2200_NUM_BCLK_RATES 12
1467
1468static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
1469 6144000,
1470 3072000,
1471 2048000,
1472 1536000,
1473 768000,
1474 512000,
1475 384000,
1476 256000,
1477 192000,
1478 128000,
1479 96000,
1480 64000,
1481};
1482
1483static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
1484 5644800,
Mark Brown78713dd2012-06-20 14:16:57 +01001485 3763200,
Mark Brownd5315a22012-01-25 19:29:41 +00001486 2882400,
1487 1881600,
1488 1411200,
1489 705600,
1490 470400,
1491 352800,
1492 176400,
1493 117600,
1494 88200,
1495 58800,
1496};
1497
1498static int wm2200_hw_params(struct snd_pcm_substream *substream,
1499 struct snd_pcm_hw_params *params,
1500 struct snd_soc_dai *dai)
1501{
1502 struct snd_soc_codec *codec = dai->codec;
1503 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1504 int i, bclk, lrclk, wl, fl, sr_code;
1505 int *bclk_rates;
1506
1507 /* Data sizes if not using TDM */
1508 wl = snd_pcm_format_width(params_format(params));
1509 if (wl < 0)
1510 return wl;
1511 fl = snd_soc_params_to_frame_size(params);
1512 if (fl < 0)
1513 return fl;
1514
1515 dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
1516 wl, fl);
1517
1518 /* Target BCLK rate */
1519 bclk = snd_soc_params_to_bclk(params);
1520 if (bclk < 0)
1521 return bclk;
1522
1523 if (!wm2200->sysclk) {
1524 dev_err(codec->dev, "SYSCLK has no rate set\n");
1525 return -EINVAL;
1526 }
1527
1528 for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
1529 if (wm2200_sr_code[i] == params_rate(params))
1530 break;
1531 if (i == ARRAY_SIZE(wm2200_sr_code)) {
1532 dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
1533 params_rate(params));
1534 return -EINVAL;
1535 }
1536 sr_code = i;
1537
1538 dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
1539 bclk, wm2200->sysclk);
1540
1541 if (wm2200->sysclk % 4000)
1542 bclk_rates = wm2200_bclk_rates_cd;
1543 else
1544 bclk_rates = wm2200_bclk_rates_dat;
1545
1546 for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
1547 if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
1548 break;
1549 if (i == WM2200_NUM_BCLK_RATES) {
1550 dev_err(codec->dev,
1551 "No valid BCLK for %dHz found from %dHz SYSCLK\n",
1552 bclk, wm2200->sysclk);
1553 return -EINVAL;
1554 }
1555
1556 bclk = i;
1557 dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
1558 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
1559 WM2200_AIF1_BCLK_DIV_MASK, bclk);
1560
1561 lrclk = bclk_rates[bclk] / params_rate(params);
1562 dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
1563 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
1564 dai->symmetric_rates)
1565 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
1566 WM2200_AIF1RX_BCPF_MASK, lrclk);
1567 else
1568 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
1569 WM2200_AIF1TX_BCPF_MASK, lrclk);
1570
1571 i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
1572 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1573 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
1574 WM2200_AIF1RX_WL_MASK |
1575 WM2200_AIF1RX_SLOT_LEN_MASK, i);
1576 else
1577 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
1578 WM2200_AIF1TX_WL_MASK |
1579 WM2200_AIF1TX_SLOT_LEN_MASK, i);
1580
1581 snd_soc_update_bits(codec, WM2200_CLOCKING_4,
1582 WM2200_SAMPLE_RATE_1_MASK, sr_code);
1583
1584 return 0;
1585}
1586
1587static const struct snd_soc_dai_ops wm2200_dai_ops = {
1588 .set_fmt = wm2200_set_fmt,
1589 .hw_params = wm2200_hw_params,
1590};
1591
1592static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1593 int source, unsigned int freq, int dir)
1594{
1595 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1596 int fval;
1597
1598 switch (clk_id) {
1599 case WM2200_CLK_SYSCLK:
1600 break;
1601
1602 default:
1603 dev_err(codec->dev, "Unknown clock %d\n", clk_id);
1604 return -EINVAL;
1605 }
1606
1607 switch (source) {
1608 case WM2200_CLKSRC_MCLK1:
1609 case WM2200_CLKSRC_MCLK2:
1610 case WM2200_CLKSRC_FLL:
1611 case WM2200_CLKSRC_BCLK1:
1612 break;
1613 default:
1614 dev_err(codec->dev, "Invalid source %d\n", source);
1615 return -EINVAL;
1616 }
1617
1618 switch (freq) {
1619 case 22579200:
1620 case 24576000:
1621 fval = 2;
1622 break;
1623 default:
1624 dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
1625 return -EINVAL;
1626 }
1627
1628 /* TODO: Check if MCLKs are in use and enable/disable pulls to
1629 * match.
1630 */
1631
1632 snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
1633 WM2200_SYSCLK_SRC_MASK,
1634 fval << WM2200_SYSCLK_FREQ_SHIFT | source);
1635
1636 wm2200->sysclk = freq;
1637
1638 return 0;
1639}
1640
1641struct _fll_div {
1642 u16 fll_fratio;
1643 u16 fll_outdiv;
1644 u16 fll_refclk_div;
1645 u16 n;
1646 u16 theta;
1647 u16 lambda;
1648};
1649
1650static struct {
1651 unsigned int min;
1652 unsigned int max;
1653 u16 fll_fratio;
1654 int ratio;
1655} fll_fratios[] = {
1656 { 0, 64000, 4, 16 },
1657 { 64000, 128000, 3, 8 },
1658 { 128000, 256000, 2, 4 },
1659 { 256000, 1000000, 1, 2 },
1660 { 1000000, 13500000, 0, 1 },
1661};
1662
1663static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
1664 unsigned int Fout)
1665{
1666 unsigned int target;
1667 unsigned int div;
1668 unsigned int fratio, gcd_fll;
1669 int i;
1670
1671 /* Fref must be <=13.5MHz */
1672 div = 1;
1673 fll_div->fll_refclk_div = 0;
1674 while ((Fref / div) > 13500000) {
1675 div *= 2;
1676 fll_div->fll_refclk_div++;
1677
1678 if (div > 8) {
1679 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
1680 Fref);
1681 return -EINVAL;
1682 }
1683 }
1684
1685 pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
1686
1687 /* Apply the division for our remaining calculations */
1688 Fref /= div;
1689
1690 /* Fvco should be 90-100MHz; don't check the upper bound */
1691 div = 2;
1692 while (Fout * div < 90000000) {
1693 div++;
1694 if (div > 64) {
1695 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
1696 Fout);
1697 return -EINVAL;
1698 }
1699 }
1700 target = Fout * div;
1701 fll_div->fll_outdiv = div - 1;
1702
1703 pr_debug("FLL Fvco=%dHz\n", target);
1704
1705 /* Find an appropraite FLL_FRATIO and factor it out of the target */
1706 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1707 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1708 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
1709 fratio = fll_fratios[i].ratio;
1710 break;
1711 }
1712 }
1713 if (i == ARRAY_SIZE(fll_fratios)) {
1714 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
1715 return -EINVAL;
1716 }
1717
1718 fll_div->n = target / (fratio * Fref);
1719
1720 if (target % Fref == 0) {
1721 fll_div->theta = 0;
1722 fll_div->lambda = 0;
1723 } else {
1724 gcd_fll = gcd(target, fratio * Fref);
1725
1726 fll_div->theta = (target - (fll_div->n * fratio * Fref))
1727 / gcd_fll;
1728 fll_div->lambda = (fratio * Fref) / gcd_fll;
1729 }
1730
1731 pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
1732 fll_div->n, fll_div->theta, fll_div->lambda);
1733 pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
1734 fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
1735 fll_div->fll_refclk_div);
1736
1737 return 0;
1738}
1739
1740static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
1741 unsigned int Fref, unsigned int Fout)
1742{
1743 struct i2c_client *i2c = to_i2c_client(codec->dev);
1744 struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
1745 struct _fll_div factors;
1746 int ret, i, timeout;
1747
1748 if (!Fout) {
1749 dev_dbg(codec->dev, "FLL disabled");
1750
1751 if (wm2200->fll_fout)
1752 pm_runtime_put(codec->dev);
1753
1754 wm2200->fll_fout = 0;
1755 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
1756 WM2200_FLL_ENA, 0);
1757 return 0;
1758 }
1759
1760 switch (source) {
1761 case WM2200_FLL_SRC_MCLK1:
1762 case WM2200_FLL_SRC_MCLK2:
1763 case WM2200_FLL_SRC_BCLK:
1764 break;
1765 default:
1766 dev_err(codec->dev, "Invalid FLL source %d\n", source);
1767 return -EINVAL;
1768 }
1769
1770 ret = fll_factors(&factors, Fref, Fout);
1771 if (ret < 0)
1772 return ret;
1773
1774 /* Disable the FLL while we reconfigure */
1775 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
1776
1777 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
1778 WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
1779 (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
1780 factors.fll_fratio);
1781 if (factors.theta) {
1782 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
1783 WM2200_FLL_FRACN_ENA,
1784 WM2200_FLL_FRACN_ENA);
1785 snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
1786 WM2200_FLL_EFS_ENA,
1787 WM2200_FLL_EFS_ENA);
1788 } else {
1789 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
1790 WM2200_FLL_FRACN_ENA, 0);
1791 snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
1792 WM2200_FLL_EFS_ENA, 0);
1793 }
1794
1795 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
1796 factors.theta);
1797 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
1798 factors.n);
1799 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
1800 WM2200_FLL_CLK_REF_DIV_MASK |
1801 WM2200_FLL_CLK_REF_SRC_MASK,
1802 (factors.fll_refclk_div
1803 << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
1804 snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
1805 WM2200_FLL_LAMBDA_MASK, factors.lambda);
1806
1807 /* Clear any pending completions */
1808 try_wait_for_completion(&wm2200->fll_lock);
1809
1810 pm_runtime_get_sync(codec->dev);
1811
1812 snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
1813 WM2200_FLL_ENA, WM2200_FLL_ENA);
1814
1815 if (i2c->irq)
1816 timeout = 2;
1817 else
1818 timeout = 50;
1819
1820 snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
1821 WM2200_SYSCLK_ENA);
1822
1823 /* Poll for the lock; will use the interrupt to exit quickly */
1824 for (i = 0; i < timeout; i++) {
1825 if (i2c->irq) {
1826 ret = wait_for_completion_timeout(&wm2200->fll_lock,
1827 msecs_to_jiffies(25));
1828 if (ret > 0)
1829 break;
1830 } else {
1831 msleep(1);
1832 }
1833
1834 ret = snd_soc_read(codec,
1835 WM2200_INTERRUPT_RAW_STATUS_2);
1836 if (ret < 0) {
1837 dev_err(codec->dev,
1838 "Failed to read FLL status: %d\n",
1839 ret);
1840 continue;
1841 }
1842 if (ret & WM2200_FLL_LOCK_STS)
1843 break;
1844 }
1845 if (i == timeout) {
1846 dev_err(codec->dev, "FLL lock timed out\n");
1847 pm_runtime_put(codec->dev);
1848 return -ETIMEDOUT;
1849 }
1850
1851 wm2200->fll_src = source;
1852 wm2200->fll_fref = Fref;
1853 wm2200->fll_fout = Fout;
1854
1855 dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
1856
1857 return 0;
1858}
1859
1860static int wm2200_dai_probe(struct snd_soc_dai *dai)
1861{
1862 struct snd_soc_codec *codec = dai->codec;
1863 unsigned int val = 0;
1864 int ret;
1865
1866 ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
1867 if (ret >= 0) {
1868 if ((ret & WM2200_GP1_FN_MASK) != 0) {
1869 dai->symmetric_rates = true;
1870 val = WM2200_AIF1TX_LRCLK_SRC;
1871 }
1872 } else {
1873 dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
1874 }
1875
1876 snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
1877 WM2200_AIF1TX_LRCLK_SRC, val);
1878
1879 return 0;
1880}
1881
1882#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
1883
1884#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1885 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1886
1887static struct snd_soc_dai_driver wm2200_dai = {
1888 .name = "wm2200",
1889 .probe = wm2200_dai_probe,
1890 .playback = {
1891 .stream_name = "Playback",
1892 .channels_min = 2,
1893 .channels_max = 2,
1894 .rates = WM2200_RATES,
1895 .formats = WM2200_FORMATS,
1896 },
1897 .capture = {
1898 .stream_name = "Capture",
1899 .channels_min = 2,
1900 .channels_max = 2,
1901 .rates = WM2200_RATES,
1902 .formats = WM2200_FORMATS,
1903 },
1904 .ops = &wm2200_dai_ops,
1905};
1906
1907static struct snd_soc_codec_driver soc_codec_wm2200 = {
1908 .probe = wm2200_probe,
1909
1910 .idle_bias_off = true,
Mark Brown17c0cee2012-02-08 18:35:43 +00001911 .ignore_pmdown_time = true,
Mark Brownd5315a22012-01-25 19:29:41 +00001912 .set_sysclk = wm2200_set_sysclk,
1913 .set_pll = wm2200_set_fll,
1914
1915 .controls = wm2200_snd_controls,
1916 .num_controls = ARRAY_SIZE(wm2200_snd_controls),
1917 .dapm_widgets = wm2200_dapm_widgets,
1918 .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
1919 .dapm_routes = wm2200_dapm_routes,
1920 .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
1921};
1922
1923static irqreturn_t wm2200_irq(int irq, void *data)
1924{
1925 struct wm2200_priv *wm2200 = data;
1926 unsigned int val, mask;
1927 int ret;
1928
1929 ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
1930 if (ret != 0) {
1931 dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
1932 return IRQ_NONE;
1933 }
1934
1935 ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
1936 &mask);
1937 if (ret != 0) {
1938 dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
1939 mask = 0;
1940 }
1941
1942 val &= ~mask;
1943
1944 if (val & WM2200_FLL_LOCK_EINT) {
1945 dev_dbg(wm2200->dev, "FLL locked\n");
1946 complete(&wm2200->fll_lock);
1947 }
1948
1949 if (val) {
1950 regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
1951
1952 return IRQ_HANDLED;
1953 } else {
1954 return IRQ_NONE;
1955 }
1956}
1957
1958static const struct regmap_config wm2200_regmap = {
1959 .reg_bits = 16,
1960 .val_bits = 16,
1961
1962 .max_register = WM2200_MAX_REGISTER,
1963 .reg_defaults = wm2200_reg_defaults,
1964 .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
1965 .volatile_reg = wm2200_volatile_register,
1966 .readable_reg = wm2200_readable_register,
1967 .cache_type = REGCACHE_RBTREE,
1968};
1969
1970static const unsigned int wm2200_dig_vu[] = {
1971 WM2200_DAC_DIGITAL_VOLUME_1L,
1972 WM2200_DAC_DIGITAL_VOLUME_1R,
1973 WM2200_DAC_DIGITAL_VOLUME_2L,
1974 WM2200_DAC_DIGITAL_VOLUME_2R,
1975 WM2200_ADC_DIGITAL_VOLUME_1L,
1976 WM2200_ADC_DIGITAL_VOLUME_1R,
1977 WM2200_ADC_DIGITAL_VOLUME_2L,
1978 WM2200_ADC_DIGITAL_VOLUME_2R,
1979 WM2200_ADC_DIGITAL_VOLUME_3L,
1980 WM2200_ADC_DIGITAL_VOLUME_3R,
1981};
1982
1983static const unsigned int wm2200_mic_ctrl_reg[] = {
1984 WM2200_IN1L_CONTROL,
1985 WM2200_IN2L_CONTROL,
1986 WM2200_IN3L_CONTROL,
1987};
1988
1989static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
1990 const struct i2c_device_id *id)
1991{
1992 struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
1993 struct wm2200_priv *wm2200;
1994 unsigned int reg;
1995 int ret, i;
1996
1997 wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
1998 GFP_KERNEL);
1999 if (wm2200 == NULL)
2000 return -ENOMEM;
2001
2002 wm2200->dev = &i2c->dev;
2003 init_completion(&wm2200->fll_lock);
2004
2005 wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
2006 if (IS_ERR(wm2200->regmap)) {
2007 ret = PTR_ERR(wm2200->regmap);
2008 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
2009 ret);
2010 goto err;
2011 }
2012
2013 if (pdata)
2014 wm2200->pdata = *pdata;
2015
2016 i2c_set_clientdata(i2c, wm2200);
2017
2018 for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
2019 wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
2020
2021 ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
2022 wm2200->core_supplies);
2023 if (ret != 0) {
2024 dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
2025 ret);
2026 goto err_regmap;
2027 }
2028
2029 ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
2030 wm2200->core_supplies);
2031 if (ret != 0) {
2032 dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
2033 ret);
2034 goto err_core;
2035 }
2036
2037 if (wm2200->pdata.ldo_ena) {
2038 ret = gpio_request_one(wm2200->pdata.ldo_ena,
2039 GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
2040 if (ret < 0) {
2041 dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
2042 wm2200->pdata.ldo_ena, ret);
2043 goto err_enable;
2044 }
2045 msleep(2);
2046 }
2047
2048 if (wm2200->pdata.reset) {
2049 ret = gpio_request_one(wm2200->pdata.reset,
2050 GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
2051 if (ret < 0) {
2052 dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
2053 wm2200->pdata.reset, ret);
2054 goto err_ldo;
2055 }
2056 }
2057
2058 ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
2059 if (ret < 0) {
2060 dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
2061 goto err_reset;
2062 }
2063 switch (reg) {
2064 case 0x2200:
2065 break;
2066
2067 default:
2068 dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
2069 ret = -EINVAL;
2070 goto err_reset;
2071 }
2072
2073 ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
2074 if (ret < 0) {
2075 dev_err(&i2c->dev, "Failed to read revision register\n");
2076 goto err_reset;
2077 }
2078
Axel Lin916be222012-02-16 10:05:59 +08002079 wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
Mark Brownd5315a22012-01-25 19:29:41 +00002080
2081 dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
2082
2083 switch (wm2200->rev) {
2084 case 0:
Mark Brownefd9aa32012-10-02 12:02:48 +01002085 case 1:
Mark Brownd5315a22012-01-25 19:29:41 +00002086 ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
2087 ARRAY_SIZE(wm2200_reva_patch));
2088 if (ret != 0) {
2089 dev_err(&i2c->dev, "Failed to register patch: %d\n",
2090 ret);
2091 }
2092 break;
2093 default:
2094 break;
2095 }
2096
2097 ret = wm2200_reset(wm2200);
2098 if (ret < 0) {
2099 dev_err(&i2c->dev, "Failed to issue reset\n");
2100 goto err_reset;
2101 }
2102
2103 for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
2104 if (!wm2200->pdata.gpio_defaults[i])
2105 continue;
2106
2107 regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
2108 wm2200->pdata.gpio_defaults[i]);
2109 }
2110
2111 for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
2112 regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
2113 WM2200_OUT_VU, WM2200_OUT_VU);
2114
2115 /* Assign slots 1-6 to channels 1-6 for both TX and RX */
2116 for (i = 0; i < 6; i++) {
2117 regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
2118 regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
2119 }
2120
2121 for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
2122 regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
2123 WM2200_IN1_MODE_MASK |
2124 WM2200_IN1_DMIC_SUP_MASK,
2125 (wm2200->pdata.in_mode[i] <<
2126 WM2200_IN1_MODE_SHIFT) |
2127 (wm2200->pdata.dmic_sup[i] <<
2128 WM2200_IN1_DMIC_SUP_SHIFT));
2129 }
2130
2131 if (i2c->irq) {
2132 ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
2133 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
2134 "wm2200", wm2200);
2135 if (ret == 0)
2136 regmap_update_bits(wm2200->regmap,
2137 WM2200_INTERRUPT_STATUS_2_MASK,
2138 WM2200_FLL_LOCK_EINT, 0);
2139 else
2140 dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
2141 i2c->irq, ret);
2142 }
2143
2144 pm_runtime_set_active(&i2c->dev);
2145 pm_runtime_enable(&i2c->dev);
2146 pm_request_idle(&i2c->dev);
2147
2148 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
2149 &wm2200_dai, 1);
2150 if (ret != 0) {
2151 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
2152 goto err_pm_runtime;
2153 }
2154
2155 return 0;
2156
2157err_pm_runtime:
2158 pm_runtime_disable(&i2c->dev);
2159err_reset:
2160 if (wm2200->pdata.reset) {
2161 gpio_set_value_cansleep(wm2200->pdata.reset, 0);
2162 gpio_free(wm2200->pdata.reset);
2163 }
2164err_ldo:
2165 if (wm2200->pdata.ldo_ena) {
2166 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
2167 gpio_free(wm2200->pdata.ldo_ena);
2168 }
2169err_enable:
2170 regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
2171 wm2200->core_supplies);
2172err_core:
2173 regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
2174 wm2200->core_supplies);
2175err_regmap:
2176 regmap_exit(wm2200->regmap);
2177err:
2178 return ret;
2179}
2180
2181static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
2182{
2183 struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
2184
2185 snd_soc_unregister_codec(&i2c->dev);
2186 if (i2c->irq)
2187 free_irq(i2c->irq, wm2200);
2188 if (wm2200->pdata.reset) {
2189 gpio_set_value_cansleep(wm2200->pdata.reset, 0);
2190 gpio_free(wm2200->pdata.reset);
2191 }
2192 if (wm2200->pdata.ldo_ena) {
2193 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
2194 gpio_free(wm2200->pdata.ldo_ena);
2195 }
2196 regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
2197 wm2200->core_supplies);
2198 regmap_exit(wm2200->regmap);
2199
2200 return 0;
2201}
2202
2203#ifdef CONFIG_PM_RUNTIME
2204static int wm2200_runtime_suspend(struct device *dev)
2205{
2206 struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
2207
2208 regcache_cache_only(wm2200->regmap, true);
2209 regcache_mark_dirty(wm2200->regmap);
2210 if (wm2200->pdata.ldo_ena)
2211 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
2212 regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
2213 wm2200->core_supplies);
2214
2215 return 0;
2216}
2217
2218static int wm2200_runtime_resume(struct device *dev)
2219{
2220 struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
2221 int ret;
2222
2223 ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
2224 wm2200->core_supplies);
2225 if (ret != 0) {
2226 dev_err(dev, "Failed to enable supplies: %d\n",
2227 ret);
2228 return ret;
2229 }
2230
2231 if (wm2200->pdata.ldo_ena) {
2232 gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
2233 msleep(2);
2234 }
2235
2236 regcache_cache_only(wm2200->regmap, false);
2237 regcache_sync(wm2200->regmap);
2238
2239 return 0;
2240}
2241#endif
2242
2243static struct dev_pm_ops wm2200_pm = {
2244 SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
2245 NULL)
2246};
2247
2248static const struct i2c_device_id wm2200_i2c_id[] = {
2249 { "wm2200", 0 },
2250 { }
2251};
2252MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
2253
2254static struct i2c_driver wm2200_i2c_driver = {
2255 .driver = {
2256 .name = "wm2200",
2257 .owner = THIS_MODULE,
2258 .pm = &wm2200_pm,
2259 },
2260 .probe = wm2200_i2c_probe,
2261 .remove = __devexit_p(wm2200_i2c_remove),
2262 .id_table = wm2200_i2c_id,
2263};
2264
2265static int __init wm2200_modinit(void)
2266{
2267 return i2c_add_driver(&wm2200_i2c_driver);
2268}
2269module_init(wm2200_modinit);
2270
2271static void __exit wm2200_exit(void)
2272{
2273 i2c_del_driver(&wm2200_i2c_driver);
2274}
2275module_exit(wm2200_exit);
2276
2277MODULE_DESCRIPTION("ASoC WM2200 driver");
2278MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2279MODULE_LICENSE("GPL");