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