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