xref: /openbmc/linux/sound/soc/codecs/cs42l73.c (revision d2999e1b)
1 /*
2  * cs42l73.c  --  CS42L73 ALSA Soc Audio driver
3  *
4  * Copyright 2011 Cirrus Logic, Inc.
5  *
6  * Authors: Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>
7  *	    Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  */
14 
15 #include <linux/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/delay.h>
20 #include <linux/of_gpio.h>
21 #include <linux/pm.h>
22 #include <linux/i2c.h>
23 #include <linux/regmap.h>
24 #include <linux/slab.h>
25 #include <sound/core.h>
26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h>
28 #include <sound/soc.h>
29 #include <sound/soc-dapm.h>
30 #include <sound/initval.h>
31 #include <sound/tlv.h>
32 #include <sound/cs42l73.h>
33 #include "cs42l73.h"
34 
35 struct sp_config {
36 	u8 spc, mmcc, spfs;
37 	u32 srate;
38 };
39 struct  cs42l73_private {
40 	struct cs42l73_platform_data pdata;
41 	struct sp_config config[3];
42 	struct regmap *regmap;
43 	u32 sysclk;
44 	u8 mclksel;
45 	u32 mclk;
46 	int shutdwn_delay;
47 };
48 
49 static const struct reg_default cs42l73_reg_defaults[] = {
50 	{ 6, 0xF1 },	/* r06	- Power Ctl 1 */
51 	{ 7, 0xDF },	/* r07	- Power Ctl 2 */
52 	{ 8, 0x3F },	/* r08	- Power Ctl 3 */
53 	{ 9, 0x50 },	/* r09	- Charge Pump Freq */
54 	{ 10, 0x53 },	/* r0A	- Output Load MicBias Short Detect */
55 	{ 11, 0x00 },	/* r0B	- DMIC Master Clock Ctl */
56 	{ 12, 0x00 },	/* r0C	- Aux PCM Ctl */
57 	{ 13, 0x15 },	/* r0D	- Aux PCM Master Clock Ctl */
58 	{ 14, 0x00 },	/* r0E	- Audio PCM Ctl */
59 	{ 15, 0x15 },	/* r0F	- Audio PCM Master Clock Ctl */
60 	{ 16, 0x00 },	/* r10	- Voice PCM Ctl */
61 	{ 17, 0x15 },	/* r11	- Voice PCM Master Clock Ctl */
62 	{ 18, 0x00 },	/* r12	- Voice/Aux Sample Rate */
63 	{ 19, 0x06 },	/* r13	- Misc I/O Path Ctl */
64 	{ 20, 0x00 },	/* r14	- ADC Input Path Ctl */
65 	{ 21, 0x00 },	/* r15	- MICA Preamp, PGA Volume */
66 	{ 22, 0x00 },	/* r16	- MICB Preamp, PGA Volume */
67 	{ 23, 0x00 },	/* r17	- Input Path A Digital Volume */
68 	{ 24, 0x00 },	/* r18	- Input Path B Digital Volume */
69 	{ 25, 0x00 },	/* r19	- Playback Digital Ctl */
70 	{ 26, 0x00 },	/* r1A	- HP/LO Left Digital Volume */
71 	{ 27, 0x00 },	/* r1B	- HP/LO Right Digital Volume */
72 	{ 28, 0x00 },	/* r1C	- Speakerphone Digital Volume */
73 	{ 29, 0x00 },	/* r1D	- Ear/SPKLO Digital Volume */
74 	{ 30, 0x00 },	/* r1E	- HP Left Analog Volume */
75 	{ 31, 0x00 },	/* r1F	- HP Right Analog Volume */
76 	{ 32, 0x00 },	/* r20	- LO Left Analog Volume */
77 	{ 33, 0x00 },	/* r21	- LO Right Analog Volume */
78 	{ 34, 0x00 },	/* r22	- Stereo Input Path Advisory Volume */
79 	{ 35, 0x00 },	/* r23	- Aux PCM Input Advisory Volume */
80 	{ 36, 0x00 },	/* r24	- Audio PCM Input Advisory Volume */
81 	{ 37, 0x00 },	/* r25	- Voice PCM Input Advisory Volume */
82 	{ 38, 0x00 },	/* r26	- Limiter Attack Rate HP/LO */
83 	{ 39, 0x7F },	/* r27	- Limter Ctl, Release Rate HP/LO */
84 	{ 40, 0x00 },	/* r28	- Limter Threshold HP/LO */
85 	{ 41, 0x00 },	/* r29	- Limiter Attack Rate Speakerphone */
86 	{ 42, 0x3F },	/* r2A	- Limter Ctl, Release Rate Speakerphone */
87 	{ 43, 0x00 },	/* r2B	- Limter Threshold Speakerphone */
88 	{ 44, 0x00 },	/* r2C	- Limiter Attack Rate Ear/SPKLO */
89 	{ 45, 0x3F },	/* r2D	- Limter Ctl, Release Rate Ear/SPKLO */
90 	{ 46, 0x00 },	/* r2E	- Limter Threshold Ear/SPKLO */
91 	{ 47, 0x00 },	/* r2F	- ALC Enable, Attack Rate Left/Right */
92 	{ 48, 0x3F },	/* r30	- ALC Release Rate Left/Right */
93 	{ 49, 0x00 },	/* r31	- ALC Threshold Left/Right */
94 	{ 50, 0x00 },	/* r32	- Noise Gate Ctl Left/Right */
95 	{ 51, 0x00 },	/* r33	- ALC/NG Misc Ctl */
96 	{ 52, 0x18 },	/* r34	- Mixer Ctl */
97 	{ 53, 0x3F },	/* r35	- HP/LO Left Mixer Input Path Volume */
98 	{ 54, 0x3F },	/* r36	- HP/LO Right Mixer Input Path Volume */
99 	{ 55, 0x3F },	/* r37	- HP/LO Left Mixer Aux PCM Volume */
100 	{ 56, 0x3F },	/* r38	- HP/LO Right Mixer Aux PCM Volume */
101 	{ 57, 0x3F },	/* r39	- HP/LO Left Mixer Audio PCM Volume */
102 	{ 58, 0x3F },	/* r3A	- HP/LO Right Mixer Audio PCM Volume */
103 	{ 59, 0x3F },	/* r3B	- HP/LO Left Mixer Voice PCM Mono Volume */
104 	{ 60, 0x3F },	/* r3C	- HP/LO Right Mixer Voice PCM Mono Volume */
105 	{ 61, 0x3F },	/* r3D	- Aux PCM Left Mixer Input Path Volume */
106 	{ 62, 0x3F },	/* r3E	- Aux PCM Right Mixer Input Path Volume */
107 	{ 63, 0x3F },	/* r3F	- Aux PCM Left Mixer Volume */
108 	{ 64, 0x3F },	/* r40	- Aux PCM Left Mixer Volume */
109 	{ 65, 0x3F },	/* r41	- Aux PCM Left Mixer Audio PCM L Volume */
110 	{ 66, 0x3F },	/* r42	- Aux PCM Right Mixer Audio PCM R Volume */
111 	{ 67, 0x3F },	/* r43	- Aux PCM Left Mixer Voice PCM Volume */
112 	{ 68, 0x3F },	/* r44	- Aux PCM Right Mixer Voice PCM Volume */
113 	{ 69, 0x3F },	/* r45	- Audio PCM Left Input Path Volume */
114 	{ 70, 0x3F },	/* r46	- Audio PCM Right Input Path Volume */
115 	{ 71, 0x3F },	/* r47	- Audio PCM Left Mixer Aux PCM L Volume */
116 	{ 72, 0x3F },	/* r48	- Audio PCM Right Mixer Aux PCM R Volume */
117 	{ 73, 0x3F },	/* r49	- Audio PCM Left Mixer Volume */
118 	{ 74, 0x3F },	/* r4A	- Audio PCM Right Mixer Volume */
119 	{ 75, 0x3F },	/* r4B	- Audio PCM Left Mixer Voice PCM Volume */
120 	{ 76, 0x3F },	/* r4C	- Audio PCM Right Mixer Voice PCM Volume */
121 	{ 77, 0x3F },	/* r4D	- Voice PCM Left Input Path Volume */
122 	{ 78, 0x3F },	/* r4E	- Voice PCM Right Input Path Volume */
123 	{ 79, 0x3F },	/* r4F	- Voice PCM Left Mixer Aux PCM L Volume */
124 	{ 80, 0x3F },	/* r50	- Voice PCM Right Mixer Aux PCM R Volume */
125 	{ 81, 0x3F },	/* r51	- Voice PCM Left Mixer Audio PCM L Volume */
126 	{ 82, 0x3F },	/* r52	- Voice PCM Right Mixer Audio PCM R Volume */
127 	{ 83, 0x3F },	/* r53	- Voice PCM Left Mixer Voice PCM Volume */
128 	{ 84, 0x3F },	/* r54	- Voice PCM Right Mixer Voice PCM Volume */
129 	{ 85, 0xAA },	/* r55	- Mono Mixer Ctl */
130 	{ 86, 0x3F },	/* r56	- SPK Mono Mixer Input Path Volume */
131 	{ 87, 0x3F },	/* r57	- SPK Mono Mixer Aux PCM Mono/L/R Volume */
132 	{ 88, 0x3F },	/* r58	- SPK Mono Mixer Audio PCM Mono/L/R Volume */
133 	{ 89, 0x3F },	/* r59	- SPK Mono Mixer Voice PCM Mono Volume */
134 	{ 90, 0x3F },	/* r5A	- SPKLO Mono Mixer Input Path Mono Volume */
135 	{ 91, 0x3F },	/* r5B	- SPKLO Mono Mixer Aux Mono/L/R Volume */
136 	{ 92, 0x3F },	/* r5C	- SPKLO Mono Mixer Audio Mono/L/R Volume */
137 	{ 93, 0x3F },	/* r5D	- SPKLO Mono Mixer Voice Mono Volume */
138 	{ 94, 0x00 },	/* r5E	- Interrupt Mask 1 */
139 	{ 95, 0x00 },	/* r5F	- Interrupt Mask 2 */
140 };
141 
142 static bool cs42l73_volatile_register(struct device *dev, unsigned int reg)
143 {
144 	switch (reg) {
145 	case CS42L73_IS1:
146 	case CS42L73_IS2:
147 		return true;
148 	default:
149 		return false;
150 	}
151 }
152 
153 static bool cs42l73_readable_register(struct device *dev, unsigned int reg)
154 {
155 	switch (reg) {
156 	case CS42L73_DEVID_AB:
157 	case CS42L73_DEVID_CD:
158 	case CS42L73_DEVID_E:
159 	case CS42L73_REVID:
160 	case CS42L73_PWRCTL1:
161 	case CS42L73_PWRCTL2:
162 	case CS42L73_PWRCTL3:
163 	case CS42L73_CPFCHC:
164 	case CS42L73_OLMBMSDC:
165 	case CS42L73_DMMCC:
166 	case CS42L73_XSPC:
167 	case CS42L73_XSPMMCC:
168 	case CS42L73_ASPC:
169 	case CS42L73_ASPMMCC:
170 	case CS42L73_VSPC:
171 	case CS42L73_VSPMMCC:
172 	case CS42L73_VXSPFS:
173 	case CS42L73_MIOPC:
174 	case CS42L73_ADCIPC:
175 	case CS42L73_MICAPREPGAAVOL:
176 	case CS42L73_MICBPREPGABVOL:
177 	case CS42L73_IPADVOL:
178 	case CS42L73_IPBDVOL:
179 	case CS42L73_PBDC:
180 	case CS42L73_HLADVOL:
181 	case CS42L73_HLBDVOL:
182 	case CS42L73_SPKDVOL:
183 	case CS42L73_ESLDVOL:
184 	case CS42L73_HPAAVOL:
185 	case CS42L73_HPBAVOL:
186 	case CS42L73_LOAAVOL:
187 	case CS42L73_LOBAVOL:
188 	case CS42L73_STRINV:
189 	case CS42L73_XSPINV:
190 	case CS42L73_ASPINV:
191 	case CS42L73_VSPINV:
192 	case CS42L73_LIMARATEHL:
193 	case CS42L73_LIMRRATEHL:
194 	case CS42L73_LMAXHL:
195 	case CS42L73_LIMARATESPK:
196 	case CS42L73_LIMRRATESPK:
197 	case CS42L73_LMAXSPK:
198 	case CS42L73_LIMARATEESL:
199 	case CS42L73_LIMRRATEESL:
200 	case CS42L73_LMAXESL:
201 	case CS42L73_ALCARATE:
202 	case CS42L73_ALCRRATE:
203 	case CS42L73_ALCMINMAX:
204 	case CS42L73_NGCAB:
205 	case CS42L73_ALCNGMC:
206 	case CS42L73_MIXERCTL:
207 	case CS42L73_HLAIPAA:
208 	case CS42L73_HLBIPBA:
209 	case CS42L73_HLAXSPAA:
210 	case CS42L73_HLBXSPBA:
211 	case CS42L73_HLAASPAA:
212 	case CS42L73_HLBASPBA:
213 	case CS42L73_HLAVSPMA:
214 	case CS42L73_HLBVSPMA:
215 	case CS42L73_XSPAIPAA:
216 	case CS42L73_XSPBIPBA:
217 	case CS42L73_XSPAXSPAA:
218 	case CS42L73_XSPBXSPBA:
219 	case CS42L73_XSPAASPAA:
220 	case CS42L73_XSPAASPBA:
221 	case CS42L73_XSPAVSPMA:
222 	case CS42L73_XSPBVSPMA:
223 	case CS42L73_ASPAIPAA:
224 	case CS42L73_ASPBIPBA:
225 	case CS42L73_ASPAXSPAA:
226 	case CS42L73_ASPBXSPBA:
227 	case CS42L73_ASPAASPAA:
228 	case CS42L73_ASPBASPBA:
229 	case CS42L73_ASPAVSPMA:
230 	case CS42L73_ASPBVSPMA:
231 	case CS42L73_VSPAIPAA:
232 	case CS42L73_VSPBIPBA:
233 	case CS42L73_VSPAXSPAA:
234 	case CS42L73_VSPBXSPBA:
235 	case CS42L73_VSPAASPAA:
236 	case CS42L73_VSPBASPBA:
237 	case CS42L73_VSPAVSPMA:
238 	case CS42L73_VSPBVSPMA:
239 	case CS42L73_MMIXCTL:
240 	case CS42L73_SPKMIPMA:
241 	case CS42L73_SPKMXSPA:
242 	case CS42L73_SPKMASPA:
243 	case CS42L73_SPKMVSPMA:
244 	case CS42L73_ESLMIPMA:
245 	case CS42L73_ESLMXSPA:
246 	case CS42L73_ESLMASPA:
247 	case CS42L73_ESLMVSPMA:
248 	case CS42L73_IM1:
249 	case CS42L73_IM2:
250 		return true;
251 	default:
252 		return false;
253 	}
254 }
255 
256 static const unsigned int hpaloa_tlv[] = {
257 	TLV_DB_RANGE_HEAD(2),
258 	0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0),
259 	14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0),
260 };
261 
262 static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0);
263 
264 static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
265 
266 static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
267 
268 static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0);
269 
270 static const unsigned int limiter_tlv[] = {
271 	TLV_DB_RANGE_HEAD(2),
272 	0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
273 	3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
274 };
275 
276 static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
277 
278 static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" };
279 static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" };
280 
281 static SOC_ENUM_SINGLE_DECL(pgaa_enum,
282 			    CS42L73_ADCIPC, 3,
283 			    cs42l73_pgaa_text);
284 
285 static SOC_ENUM_SINGLE_DECL(pgab_enum,
286 			    CS42L73_ADCIPC, 7,
287 			    cs42l73_pgab_text);
288 
289 static const struct snd_kcontrol_new pgaa_mux =
290 	SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum);
291 
292 static const struct snd_kcontrol_new pgab_mux =
293 	SOC_DAPM_ENUM("Right Analog Input Capture Mux", pgab_enum);
294 
295 static const struct snd_kcontrol_new input_left_mixer[] = {
296 	SOC_DAPM_SINGLE("ADC Left Input", CS42L73_PWRCTL1,
297 			5, 1, 1),
298 	SOC_DAPM_SINGLE("DMIC Left Input", CS42L73_PWRCTL1,
299 			4, 1, 1),
300 };
301 
302 static const struct snd_kcontrol_new input_right_mixer[] = {
303 	SOC_DAPM_SINGLE("ADC Right Input", CS42L73_PWRCTL1,
304 			7, 1, 1),
305 	SOC_DAPM_SINGLE("DMIC Right Input", CS42L73_PWRCTL1,
306 			6, 1, 1),
307 };
308 
309 static const char * const cs42l73_ng_delay_text[] = {
310 	"50ms", "100ms", "150ms", "200ms" };
311 
312 static SOC_ENUM_SINGLE_DECL(ng_delay_enum,
313 			    CS42L73_NGCAB, 0,
314 			    cs42l73_ng_delay_text);
315 
316 static const char * const cs42l73_mono_mix_texts[] = {
317 	"Left", "Right", "Mono Mix"};
318 
319 static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 };
320 
321 static const struct soc_enum spk_asp_enum =
322 	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 3,
323 			      ARRAY_SIZE(cs42l73_mono_mix_texts),
324 			      cs42l73_mono_mix_texts,
325 			      cs42l73_mono_mix_values);
326 
327 static const struct snd_kcontrol_new spk_asp_mixer =
328 	SOC_DAPM_ENUM("Route", spk_asp_enum);
329 
330 static const struct soc_enum spk_xsp_enum =
331 	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 4, 3,
332 			      ARRAY_SIZE(cs42l73_mono_mix_texts),
333 			      cs42l73_mono_mix_texts,
334 			      cs42l73_mono_mix_values);
335 
336 static const struct snd_kcontrol_new spk_xsp_mixer =
337 	SOC_DAPM_ENUM("Route", spk_xsp_enum);
338 
339 static const struct soc_enum esl_asp_enum =
340 	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 3,
341 			      ARRAY_SIZE(cs42l73_mono_mix_texts),
342 			      cs42l73_mono_mix_texts,
343 			      cs42l73_mono_mix_values);
344 
345 static const struct snd_kcontrol_new esl_asp_mixer =
346 	SOC_DAPM_ENUM("Route", esl_asp_enum);
347 
348 static const struct soc_enum esl_xsp_enum =
349 	SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 3,
350 			      ARRAY_SIZE(cs42l73_mono_mix_texts),
351 			      cs42l73_mono_mix_texts,
352 			      cs42l73_mono_mix_values);
353 
354 static const struct snd_kcontrol_new esl_xsp_mixer =
355 	SOC_DAPM_ENUM("Route", esl_xsp_enum);
356 
357 static const char * const cs42l73_ip_swap_text[] = {
358 	"Stereo", "Mono A", "Mono B", "Swap A-B"};
359 
360 static SOC_ENUM_SINGLE_DECL(ip_swap_enum,
361 			    CS42L73_MIOPC, 6,
362 			    cs42l73_ip_swap_text);
363 
364 static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"};
365 
366 static SOC_ENUM_SINGLE_DECL(vsp_output_mux_enum,
367 			    CS42L73_MIXERCTL, 5,
368 			    cs42l73_spo_mixer_text);
369 
370 static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum,
371 			    CS42L73_MIXERCTL, 4,
372 			    cs42l73_spo_mixer_text);
373 
374 static const struct snd_kcontrol_new vsp_output_mux =
375 	SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
376 
377 static const struct snd_kcontrol_new xsp_output_mux =
378 	SOC_DAPM_ENUM("Route", xsp_output_mux_enum);
379 
380 static const struct snd_kcontrol_new hp_amp_ctl =
381 	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1);
382 
383 static const struct snd_kcontrol_new lo_amp_ctl =
384 	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 1, 1, 1);
385 
386 static const struct snd_kcontrol_new spk_amp_ctl =
387 	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 2, 1, 1);
388 
389 static const struct snd_kcontrol_new spklo_amp_ctl =
390 	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 4, 1, 1);
391 
392 static const struct snd_kcontrol_new ear_amp_ctl =
393 	SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 3, 1, 1);
394 
395 static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
396 	SOC_DOUBLE_R_SX_TLV("Headphone Analog Playback Volume",
397 			CS42L73_HPAAVOL, CS42L73_HPBAVOL, 0,
398 			0x41, 0x4B, hpaloa_tlv),
399 
400 	SOC_DOUBLE_R_SX_TLV("LineOut Analog Playback Volume", CS42L73_LOAAVOL,
401 			CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv),
402 
403 	SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
404 			CS42L73_MICBPREPGABVOL, 5, 0x34,
405 			0x24, micpga_tlv),
406 
407 	SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
408 			CS42L73_MICBPREPGABVOL, 6, 1, 1),
409 
410 	SOC_DOUBLE_R_SX_TLV("Input Path Digital Volume", CS42L73_IPADVOL,
411 			CS42L73_IPBDVOL, 0, 0xA0, 0x6C, ipd_tlv),
412 
413 	SOC_DOUBLE_R_SX_TLV("HL Digital Playback Volume",
414 			CS42L73_HLADVOL, CS42L73_HLBDVOL,
415 			0, 0x34, 0xE4, hl_tlv),
416 
417 	SOC_SINGLE_TLV("ADC A Boost Volume",
418 			CS42L73_ADCIPC, 2, 0x01, 1, adc_boost_tlv),
419 
420 	SOC_SINGLE_TLV("ADC B Boost Volume",
421 		       CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv),
422 
423 	SOC_SINGLE_SX_TLV("Speakerphone Digital Volume",
424 			    CS42L73_SPKDVOL, 0, 0x34, 0xE4, hl_tlv),
425 
426 	SOC_SINGLE_SX_TLV("Ear Speaker Digital Volume",
427 			    CS42L73_ESLDVOL, 0, 0x34, 0xE4, hl_tlv),
428 
429 	SOC_DOUBLE_R("Headphone Analog Playback Switch", CS42L73_HPAAVOL,
430 			CS42L73_HPBAVOL, 7, 1, 1),
431 
432 	SOC_DOUBLE_R("LineOut Analog Playback Switch", CS42L73_LOAAVOL,
433 			CS42L73_LOBAVOL, 7, 1, 1),
434 	SOC_DOUBLE("Input Path Digital Switch", CS42L73_ADCIPC, 0, 4, 1, 1),
435 	SOC_DOUBLE("HL Digital Playback Switch", CS42L73_PBDC, 0,
436 			1, 1, 1),
437 	SOC_SINGLE("Speakerphone Digital Playback Switch", CS42L73_PBDC, 2, 1,
438 			1),
439 	SOC_SINGLE("Ear Speaker Digital Playback Switch", CS42L73_PBDC, 3, 1,
440 			1),
441 
442 	SOC_SINGLE("PGA Soft-Ramp Switch", CS42L73_MIOPC, 3, 1, 0),
443 	SOC_SINGLE("Analog Zero Cross Switch", CS42L73_MIOPC, 2, 1, 0),
444 	SOC_SINGLE("Digital Soft-Ramp Switch", CS42L73_MIOPC, 1, 1, 0),
445 	SOC_SINGLE("Analog Output Soft-Ramp Switch", CS42L73_MIOPC, 0, 1, 0),
446 
447 	SOC_DOUBLE("ADC Signal Polarity Switch", CS42L73_ADCIPC, 1, 5, 1,
448 			0),
449 
450 	SOC_SINGLE("HL Limiter Attack Rate", CS42L73_LIMARATEHL, 0, 0x3F,
451 			0),
452 	SOC_SINGLE("HL Limiter Release Rate", CS42L73_LIMRRATEHL, 0,
453 			0x3F, 0),
454 
455 
456 	SOC_SINGLE("HL Limiter Switch", CS42L73_LIMRRATEHL, 7, 1, 0),
457 	SOC_SINGLE("HL Limiter All Channels Switch", CS42L73_LIMRRATEHL, 6, 1,
458 			0),
459 
460 	SOC_SINGLE_TLV("HL Limiter Max Threshold Volume", CS42L73_LMAXHL, 5, 7,
461 			1, limiter_tlv),
462 
463 	SOC_SINGLE_TLV("HL Limiter Cushion Volume", CS42L73_LMAXHL, 2, 7, 1,
464 			limiter_tlv),
465 
466 	SOC_SINGLE("SPK Limiter Attack Rate Volume", CS42L73_LIMARATESPK, 0,
467 			0x3F, 0),
468 	SOC_SINGLE("SPK Limiter Release Rate Volume", CS42L73_LIMRRATESPK, 0,
469 			0x3F, 0),
470 	SOC_SINGLE("SPK Limiter Switch", CS42L73_LIMRRATESPK, 7, 1, 0),
471 	SOC_SINGLE("SPK Limiter All Channels Switch", CS42L73_LIMRRATESPK,
472 			6, 1, 0),
473 	SOC_SINGLE_TLV("SPK Limiter Max Threshold Volume", CS42L73_LMAXSPK, 5,
474 			7, 1, limiter_tlv),
475 
476 	SOC_SINGLE_TLV("SPK Limiter Cushion Volume", CS42L73_LMAXSPK, 2, 7, 1,
477 			limiter_tlv),
478 
479 	SOC_SINGLE("ESL Limiter Attack Rate Volume", CS42L73_LIMARATEESL, 0,
480 			0x3F, 0),
481 	SOC_SINGLE("ESL Limiter Release Rate Volume", CS42L73_LIMRRATEESL, 0,
482 			0x3F, 0),
483 	SOC_SINGLE("ESL Limiter Switch", CS42L73_LIMRRATEESL, 7, 1, 0),
484 	SOC_SINGLE_TLV("ESL Limiter Max Threshold Volume", CS42L73_LMAXESL, 5,
485 			7, 1, limiter_tlv),
486 
487 	SOC_SINGLE_TLV("ESL Limiter Cushion Volume", CS42L73_LMAXESL, 2, 7, 1,
488 			limiter_tlv),
489 
490 	SOC_SINGLE("ALC Attack Rate Volume", CS42L73_ALCARATE, 0, 0x3F, 0),
491 	SOC_SINGLE("ALC Release Rate Volume", CS42L73_ALCRRATE, 0, 0x3F, 0),
492 	SOC_DOUBLE("ALC Switch", CS42L73_ALCARATE, 6, 7, 1, 0),
493 	SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L73_ALCMINMAX, 5, 7, 0,
494 			limiter_tlv),
495 	SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L73_ALCMINMAX, 2, 7, 0,
496 			limiter_tlv),
497 
498 	SOC_DOUBLE("NG Enable Switch", CS42L73_NGCAB, 6, 7, 1, 0),
499 	SOC_SINGLE("NG Boost Switch", CS42L73_NGCAB, 5, 1, 0),
500 	/*
501 	    NG Threshold depends on NG_BOOTSAB, which selects
502 	    between two threshold scales in decibels.
503 	    Set linear values for now ..
504 	*/
505 	SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0),
506 	SOC_ENUM("NG Delay", ng_delay_enum),
507 
508 	SOC_DOUBLE_R_TLV("XSP-IP Volume",
509 			CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1,
510 			attn_tlv),
511 	SOC_DOUBLE_R_TLV("XSP-XSP Volume",
512 			CS42L73_XSPAXSPAA, CS42L73_XSPBXSPBA, 0, 0x3F, 1,
513 			attn_tlv),
514 	SOC_DOUBLE_R_TLV("XSP-ASP Volume",
515 			CS42L73_XSPAASPAA, CS42L73_XSPAASPBA, 0, 0x3F, 1,
516 			attn_tlv),
517 	SOC_DOUBLE_R_TLV("XSP-VSP Volume",
518 			CS42L73_XSPAVSPMA, CS42L73_XSPBVSPMA, 0, 0x3F, 1,
519 			attn_tlv),
520 
521 	SOC_DOUBLE_R_TLV("ASP-IP Volume",
522 			CS42L73_ASPAIPAA, CS42L73_ASPBIPBA, 0, 0x3F, 1,
523 			attn_tlv),
524 	SOC_DOUBLE_R_TLV("ASP-XSP Volume",
525 			CS42L73_ASPAXSPAA, CS42L73_ASPBXSPBA, 0, 0x3F, 1,
526 			attn_tlv),
527 	SOC_DOUBLE_R_TLV("ASP-ASP Volume",
528 			CS42L73_ASPAASPAA, CS42L73_ASPBASPBA, 0, 0x3F, 1,
529 			attn_tlv),
530 	SOC_DOUBLE_R_TLV("ASP-VSP Volume",
531 			CS42L73_ASPAVSPMA, CS42L73_ASPBVSPMA, 0, 0x3F, 1,
532 			attn_tlv),
533 
534 	SOC_DOUBLE_R_TLV("VSP-IP Volume",
535 			CS42L73_VSPAIPAA, CS42L73_VSPBIPBA, 0, 0x3F, 1,
536 			attn_tlv),
537 	SOC_DOUBLE_R_TLV("VSP-XSP Volume",
538 			CS42L73_VSPAXSPAA, CS42L73_VSPBXSPBA, 0, 0x3F, 1,
539 			attn_tlv),
540 	SOC_DOUBLE_R_TLV("VSP-ASP Volume",
541 			CS42L73_VSPAASPAA, CS42L73_VSPBASPBA, 0, 0x3F, 1,
542 			attn_tlv),
543 	SOC_DOUBLE_R_TLV("VSP-VSP Volume",
544 			CS42L73_VSPAVSPMA, CS42L73_VSPBVSPMA, 0, 0x3F, 1,
545 			attn_tlv),
546 
547 	SOC_DOUBLE_R_TLV("HL-IP Volume",
548 			CS42L73_HLAIPAA, CS42L73_HLBIPBA, 0, 0x3F, 1,
549 			attn_tlv),
550 	SOC_DOUBLE_R_TLV("HL-XSP Volume",
551 			CS42L73_HLAXSPAA, CS42L73_HLBXSPBA, 0, 0x3F, 1,
552 			attn_tlv),
553 	SOC_DOUBLE_R_TLV("HL-ASP Volume",
554 			CS42L73_HLAASPAA, CS42L73_HLBASPBA, 0, 0x3F, 1,
555 			attn_tlv),
556 	SOC_DOUBLE_R_TLV("HL-VSP Volume",
557 			CS42L73_HLAVSPMA, CS42L73_HLBVSPMA, 0, 0x3F, 1,
558 			attn_tlv),
559 
560 	SOC_SINGLE_TLV("SPK-IP Mono Volume",
561 			CS42L73_SPKMIPMA, 0, 0x3F, 1, attn_tlv),
562 	SOC_SINGLE_TLV("SPK-XSP Mono Volume",
563 			CS42L73_SPKMXSPA, 0, 0x3F, 1, attn_tlv),
564 	SOC_SINGLE_TLV("SPK-ASP Mono Volume",
565 			CS42L73_SPKMASPA, 0, 0x3F, 1, attn_tlv),
566 	SOC_SINGLE_TLV("SPK-VSP Mono Volume",
567 			CS42L73_SPKMVSPMA, 0, 0x3F, 1, attn_tlv),
568 
569 	SOC_SINGLE_TLV("ESL-IP Mono Volume",
570 			CS42L73_ESLMIPMA, 0, 0x3F, 1, attn_tlv),
571 	SOC_SINGLE_TLV("ESL-XSP Mono Volume",
572 			CS42L73_ESLMXSPA, 0, 0x3F, 1, attn_tlv),
573 	SOC_SINGLE_TLV("ESL-ASP Mono Volume",
574 			CS42L73_ESLMASPA, 0, 0x3F, 1, attn_tlv),
575 	SOC_SINGLE_TLV("ESL-VSP Mono Volume",
576 			CS42L73_ESLMVSPMA, 0, 0x3F, 1, attn_tlv),
577 
578 	SOC_ENUM("IP Digital Swap/Mono Select", ip_swap_enum),
579 
580 	SOC_ENUM("VSPOUT Mono/Stereo Select", vsp_output_mux_enum),
581 	SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum),
582 };
583 
584 static int cs42l73_spklo_spk_amp_event(struct snd_soc_dapm_widget *w,
585 	struct snd_kcontrol *kcontrol, int event)
586 {
587 	struct snd_soc_codec *codec = w->codec;
588 	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
589 	switch (event) {
590 	case SND_SOC_DAPM_POST_PMD:
591 		/* 150 ms delay between setting PDN and MCLKDIS */
592 		priv->shutdwn_delay = 150;
593 		break;
594 	default:
595 		pr_err("Invalid event = 0x%x\n", event);
596 	}
597 	return 0;
598 }
599 
600 static int cs42l73_ear_amp_event(struct snd_soc_dapm_widget *w,
601 	struct snd_kcontrol *kcontrol, int event)
602 {
603 	struct snd_soc_codec *codec = w->codec;
604 	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
605 	switch (event) {
606 	case SND_SOC_DAPM_POST_PMD:
607 		/* 50 ms delay between setting PDN and MCLKDIS */
608 		if (priv->shutdwn_delay < 50)
609 			priv->shutdwn_delay = 50;
610 		break;
611 	default:
612 		pr_err("Invalid event = 0x%x\n", event);
613 	}
614 	return 0;
615 }
616 
617 
618 static int cs42l73_hp_amp_event(struct snd_soc_dapm_widget *w,
619 	struct snd_kcontrol *kcontrol, int event)
620 {
621 	struct snd_soc_codec *codec = w->codec;
622 	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
623 	switch (event) {
624 	case SND_SOC_DAPM_POST_PMD:
625 		/* 30 ms delay between setting PDN and MCLKDIS */
626 		if (priv->shutdwn_delay < 30)
627 			priv->shutdwn_delay = 30;
628 		break;
629 	default:
630 		pr_err("Invalid event = 0x%x\n", event);
631 	}
632 	return 0;
633 }
634 
635 static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
636 	SND_SOC_DAPM_INPUT("DMICA"),
637 	SND_SOC_DAPM_INPUT("DMICB"),
638 	SND_SOC_DAPM_INPUT("LINEINA"),
639 	SND_SOC_DAPM_INPUT("LINEINB"),
640 	SND_SOC_DAPM_INPUT("MIC1"),
641 	SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS42L73_PWRCTL2, 6, 1, NULL, 0),
642 	SND_SOC_DAPM_INPUT("MIC2"),
643 	SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS42L73_PWRCTL2, 7, 1, NULL, 0),
644 
645 	SND_SOC_DAPM_AIF_OUT("XSPOUTL", NULL,  0,
646 			CS42L73_PWRCTL2, 1, 1),
647 	SND_SOC_DAPM_AIF_OUT("XSPOUTR", NULL,  0,
648 			CS42L73_PWRCTL2, 1, 1),
649 	SND_SOC_DAPM_AIF_OUT("ASPOUTL", NULL,  0,
650 			CS42L73_PWRCTL2, 3, 1),
651 	SND_SOC_DAPM_AIF_OUT("ASPOUTR", NULL,  0,
652 			CS42L73_PWRCTL2, 3, 1),
653 	SND_SOC_DAPM_AIF_OUT("VSPINOUT", NULL,  0,
654 			CS42L73_PWRCTL2, 4, 1),
655 
656 	SND_SOC_DAPM_PGA("PGA Left", SND_SOC_NOPM, 0, 0, NULL, 0),
657 	SND_SOC_DAPM_PGA("PGA Right", SND_SOC_NOPM, 0, 0, NULL, 0),
658 
659 	SND_SOC_DAPM_MUX("PGA Left Mux", SND_SOC_NOPM, 0, 0, &pgaa_mux),
660 	SND_SOC_DAPM_MUX("PGA Right Mux", SND_SOC_NOPM, 0, 0, &pgab_mux),
661 
662 	SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L73_PWRCTL1, 7, 1),
663 	SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L73_PWRCTL1, 5, 1),
664 	SND_SOC_DAPM_ADC("DMIC Left", NULL, CS42L73_PWRCTL1, 6, 1),
665 	SND_SOC_DAPM_ADC("DMIC Right", NULL, CS42L73_PWRCTL1, 4, 1),
666 
667 	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Left Capture", SND_SOC_NOPM,
668 			 0, 0, input_left_mixer,
669 			 ARRAY_SIZE(input_left_mixer)),
670 
671 	SND_SOC_DAPM_MIXER_NAMED_CTL("Input Right Capture", SND_SOC_NOPM,
672 			0, 0, input_right_mixer,
673 			ARRAY_SIZE(input_right_mixer)),
674 
675 	SND_SOC_DAPM_MIXER("ASPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
676 	SND_SOC_DAPM_MIXER("ASPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
677 	SND_SOC_DAPM_MIXER("XSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
678 	SND_SOC_DAPM_MIXER("XSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
679 	SND_SOC_DAPM_MIXER("VSP Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
680 
681 	SND_SOC_DAPM_AIF_IN("XSPINL", NULL, 0,
682 				CS42L73_PWRCTL2, 0, 1),
683 	SND_SOC_DAPM_AIF_IN("XSPINR", NULL, 0,
684 				CS42L73_PWRCTL2, 0, 1),
685 	SND_SOC_DAPM_AIF_IN("XSPINM", NULL, 0,
686 				CS42L73_PWRCTL2, 0, 1),
687 
688 	SND_SOC_DAPM_AIF_IN("ASPINL", NULL, 0,
689 				CS42L73_PWRCTL2, 2, 1),
690 	SND_SOC_DAPM_AIF_IN("ASPINR", NULL, 0,
691 				CS42L73_PWRCTL2, 2, 1),
692 	SND_SOC_DAPM_AIF_IN("ASPINM", NULL, 0,
693 				CS42L73_PWRCTL2, 2, 1),
694 
695 	SND_SOC_DAPM_AIF_IN("VSPINOUT", NULL, 0,
696 				CS42L73_PWRCTL2, 4, 1),
697 
698 	SND_SOC_DAPM_MIXER("HL Left Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
699 	SND_SOC_DAPM_MIXER("HL Right Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
700 	SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
701 	SND_SOC_DAPM_MIXER("ESL Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
702 
703 	SND_SOC_DAPM_MUX("ESL-XSP Mux", SND_SOC_NOPM,
704 			 0, 0, &esl_xsp_mixer),
705 
706 	SND_SOC_DAPM_MUX("ESL-ASP Mux", SND_SOC_NOPM,
707 			 0, 0, &esl_asp_mixer),
708 
709 	SND_SOC_DAPM_MUX("SPK-ASP Mux", SND_SOC_NOPM,
710 			 0, 0, &spk_asp_mixer),
711 
712 	SND_SOC_DAPM_MUX("SPK-XSP Mux", SND_SOC_NOPM,
713 			 0, 0, &spk_xsp_mixer),
714 
715 	SND_SOC_DAPM_PGA("HL Left DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
716 	SND_SOC_DAPM_PGA("HL Right DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
717 	SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
718 	SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
719 
720 	SND_SOC_DAPM_SWITCH_E("HP Amp",  CS42L73_PWRCTL3, 0, 1,
721 			    &hp_amp_ctl, cs42l73_hp_amp_event,
722 			SND_SOC_DAPM_POST_PMD),
723 	SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1,
724 			    &lo_amp_ctl),
725 	SND_SOC_DAPM_SWITCH_E("SPK Amp", CS42L73_PWRCTL3, 2, 1,
726 			&spk_amp_ctl, cs42l73_spklo_spk_amp_event,
727 			SND_SOC_DAPM_POST_PMD),
728 	SND_SOC_DAPM_SWITCH_E("EAR Amp", CS42L73_PWRCTL3, 3, 1,
729 			    &ear_amp_ctl, cs42l73_ear_amp_event,
730 			SND_SOC_DAPM_POST_PMD),
731 	SND_SOC_DAPM_SWITCH_E("SPKLO Amp", CS42L73_PWRCTL3, 4, 1,
732 			    &spklo_amp_ctl, cs42l73_spklo_spk_amp_event,
733 			SND_SOC_DAPM_POST_PMD),
734 
735 	SND_SOC_DAPM_OUTPUT("HPOUTA"),
736 	SND_SOC_DAPM_OUTPUT("HPOUTB"),
737 	SND_SOC_DAPM_OUTPUT("LINEOUTA"),
738 	SND_SOC_DAPM_OUTPUT("LINEOUTB"),
739 	SND_SOC_DAPM_OUTPUT("EAROUT"),
740 	SND_SOC_DAPM_OUTPUT("SPKOUT"),
741 	SND_SOC_DAPM_OUTPUT("SPKLINEOUT"),
742 };
743 
744 static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
745 
746 	/* SPKLO EARSPK Paths */
747 	{"EAROUT", NULL, "EAR Amp"},
748 	{"SPKLINEOUT", NULL, "SPKLO Amp"},
749 
750 	{"EAR Amp", "Switch", "ESL DAC"},
751 	{"SPKLO Amp", "Switch", "ESL DAC"},
752 
753 	{"ESL DAC", "ESL-ASP Mono Volume", "ESL Mixer"},
754 	{"ESL DAC", "ESL-XSP Mono Volume", "ESL Mixer"},
755 	{"ESL DAC", "ESL-VSP Mono Volume", "VSPINOUT"},
756 	/* Loopback */
757 	{"ESL DAC", "ESL-IP Mono Volume", "Input Left Capture"},
758 	{"ESL DAC", "ESL-IP Mono Volume", "Input Right Capture"},
759 
760 	{"ESL Mixer", NULL, "ESL-ASP Mux"},
761 	{"ESL Mixer", NULL, "ESL-XSP Mux"},
762 
763 	{"ESL-ASP Mux", "Left", "ASPINL"},
764 	{"ESL-ASP Mux", "Right", "ASPINR"},
765 	{"ESL-ASP Mux", "Mono Mix", "ASPINM"},
766 
767 	{"ESL-XSP Mux", "Left", "XSPINL"},
768 	{"ESL-XSP Mux", "Right", "XSPINR"},
769 	{"ESL-XSP Mux", "Mono Mix", "XSPINM"},
770 
771 	/* Speakerphone Paths */
772 	{"SPKOUT", NULL, "SPK Amp"},
773 	{"SPK Amp", "Switch", "SPK DAC"},
774 
775 	{"SPK DAC", "SPK-ASP Mono Volume", "SPK Mixer"},
776 	{"SPK DAC", "SPK-XSP Mono Volume", "SPK Mixer"},
777 	{"SPK DAC", "SPK-VSP Mono Volume", "VSPINOUT"},
778 	/* Loopback */
779 	{"SPK DAC", "SPK-IP Mono Volume", "Input Left Capture"},
780 	{"SPK DAC", "SPK-IP Mono Volume", "Input Right Capture"},
781 
782 	{"SPK Mixer", NULL, "SPK-ASP Mux"},
783 	{"SPK Mixer", NULL, "SPK-XSP Mux"},
784 
785 	{"SPK-ASP Mux", "Left", "ASPINL"},
786 	{"SPK-ASP Mux", "Mono Mix", "ASPINM"},
787 	{"SPK-ASP Mux", "Right", "ASPINR"},
788 
789 	{"SPK-XSP Mux", "Left", "XSPINL"},
790 	{"SPK-XSP Mux", "Mono Mix", "XSPINM"},
791 	{"SPK-XSP Mux", "Right", "XSPINR"},
792 
793 	/* HP LineOUT Paths */
794 	{"HPOUTA", NULL, "HP Amp"},
795 	{"HPOUTB", NULL, "HP Amp"},
796 	{"LINEOUTA", NULL, "LO Amp"},
797 	{"LINEOUTB", NULL, "LO Amp"},
798 
799 	{"HP Amp", "Switch", "HL Left DAC"},
800 	{"HP Amp", "Switch", "HL Right DAC"},
801 	{"LO Amp", "Switch", "HL Left DAC"},
802 	{"LO Amp", "Switch", "HL Right DAC"},
803 
804 	{"HL Left DAC", "HL-XSP Volume", "HL Left Mixer"},
805 	{"HL Right DAC", "HL-XSP Volume", "HL Right Mixer"},
806 	{"HL Left DAC", "HL-ASP Volume", "HL Left Mixer"},
807 	{"HL Right DAC", "HL-ASP Volume", "HL Right Mixer"},
808 	{"HL Left DAC", "HL-VSP Volume", "HL Left Mixer"},
809 	{"HL Right DAC", "HL-VSP Volume", "HL Right Mixer"},
810 	/* Loopback */
811 	{"HL Left DAC", "HL-IP Volume", "HL Left Mixer"},
812 	{"HL Right DAC", "HL-IP Volume", "HL Right Mixer"},
813 	{"HL Left Mixer", NULL, "Input Left Capture"},
814 	{"HL Right Mixer", NULL, "Input Right Capture"},
815 
816 	{"HL Left Mixer", NULL, "ASPINL"},
817 	{"HL Right Mixer", NULL, "ASPINR"},
818 	{"HL Left Mixer", NULL, "XSPINL"},
819 	{"HL Right Mixer", NULL, "XSPINR"},
820 	{"HL Left Mixer", NULL, "VSPINOUT"},
821 	{"HL Right Mixer", NULL, "VSPINOUT"},
822 
823 	{"ASPINL", NULL, "ASP Playback"},
824 	{"ASPINM", NULL, "ASP Playback"},
825 	{"ASPINR", NULL, "ASP Playback"},
826 	{"XSPINL", NULL, "XSP Playback"},
827 	{"XSPINM", NULL, "XSP Playback"},
828 	{"XSPINR", NULL, "XSP Playback"},
829 	{"VSPINOUT", NULL, "VSP Playback"},
830 
831 	/* Capture Paths */
832 	{"MIC1", NULL, "MIC1 Bias"},
833 	{"PGA Left Mux", "Mic 1", "MIC1"},
834 	{"MIC2", NULL, "MIC2 Bias"},
835 	{"PGA Right Mux", "Mic 2", "MIC2"},
836 
837 	{"PGA Left Mux", "Line A", "LINEINA"},
838 	{"PGA Right Mux", "Line B", "LINEINB"},
839 
840 	{"PGA Left", NULL, "PGA Left Mux"},
841 	{"PGA Right", NULL, "PGA Right Mux"},
842 
843 	{"ADC Left", NULL, "PGA Left"},
844 	{"ADC Right", NULL, "PGA Right"},
845 	{"DMIC Left", NULL, "DMICA"},
846 	{"DMIC Right", NULL, "DMICB"},
847 
848 	{"Input Left Capture", "ADC Left Input", "ADC Left"},
849 	{"Input Right Capture", "ADC Right Input", "ADC Right"},
850 	{"Input Left Capture", "DMIC Left Input", "DMIC Left"},
851 	{"Input Right Capture", "DMIC Right Input", "DMIC Right"},
852 
853 	/* Audio Capture */
854 	{"ASPL Output Mixer", NULL, "Input Left Capture"},
855 	{"ASPR Output Mixer", NULL, "Input Right Capture"},
856 
857 	{"ASPOUTL", "ASP-IP Volume", "ASPL Output Mixer"},
858 	{"ASPOUTR", "ASP-IP Volume", "ASPR Output Mixer"},
859 
860 	/* Auxillary Capture */
861 	{"XSPL Output Mixer", NULL, "Input Left Capture"},
862 	{"XSPR Output Mixer", NULL, "Input Right Capture"},
863 
864 	{"XSPOUTL", "XSP-IP Volume", "XSPL Output Mixer"},
865 	{"XSPOUTR", "XSP-IP Volume", "XSPR Output Mixer"},
866 
867 	{"XSPOUTL", NULL, "XSPL Output Mixer"},
868 	{"XSPOUTR", NULL, "XSPR Output Mixer"},
869 
870 	/* Voice Capture */
871 	{"VSP Output Mixer", NULL, "Input Left Capture"},
872 	{"VSP Output Mixer", NULL, "Input Right Capture"},
873 
874 	{"VSPINOUT", "VSP-IP Volume", "VSP Output Mixer"},
875 
876 	{"VSPINOUT", NULL, "VSP Output Mixer"},
877 
878 	{"ASP Capture", NULL, "ASPOUTL"},
879 	{"ASP Capture", NULL, "ASPOUTR"},
880 	{"XSP Capture", NULL, "XSPOUTL"},
881 	{"XSP Capture", NULL, "XSPOUTR"},
882 	{"VSP Capture", NULL, "VSPINOUT"},
883 };
884 
885 struct cs42l73_mclk_div {
886 	u32 mclk;
887 	u32 srate;
888 	u8 mmcc;
889 };
890 
891 static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = {
892 	/* MCLK, Sample Rate, xMMCC[5:0] */
893 	{5644800, 11025, 0x30},
894 	{5644800, 22050, 0x20},
895 	{5644800, 44100, 0x10},
896 
897 	{6000000,  8000, 0x39},
898 	{6000000, 11025, 0x33},
899 	{6000000, 12000, 0x31},
900 	{6000000, 16000, 0x29},
901 	{6000000, 22050, 0x23},
902 	{6000000, 24000, 0x21},
903 	{6000000, 32000, 0x19},
904 	{6000000, 44100, 0x13},
905 	{6000000, 48000, 0x11},
906 
907 	{6144000,  8000, 0x38},
908 	{6144000, 12000, 0x30},
909 	{6144000, 16000, 0x28},
910 	{6144000, 24000, 0x20},
911 	{6144000, 32000, 0x18},
912 	{6144000, 48000, 0x10},
913 
914 	{6500000,  8000, 0x3C},
915 	{6500000, 11025, 0x35},
916 	{6500000, 12000, 0x34},
917 	{6500000, 16000, 0x2C},
918 	{6500000, 22050, 0x25},
919 	{6500000, 24000, 0x24},
920 	{6500000, 32000, 0x1C},
921 	{6500000, 44100, 0x15},
922 	{6500000, 48000, 0x14},
923 
924 	{6400000,  8000, 0x3E},
925 	{6400000, 11025, 0x37},
926 	{6400000, 12000, 0x36},
927 	{6400000, 16000, 0x2E},
928 	{6400000, 22050, 0x27},
929 	{6400000, 24000, 0x26},
930 	{6400000, 32000, 0x1E},
931 	{6400000, 44100, 0x17},
932 	{6400000, 48000, 0x16},
933 };
934 
935 struct cs42l73_mclkx_div {
936 	u32 mclkx;
937 	u8 ratio;
938 	u8 mclkdiv;
939 };
940 
941 static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = {
942 	{5644800,  1, 0},	/* 5644800 */
943 	{6000000,  1, 0},	/* 6000000 */
944 	{6144000,  1, 0},	/* 6144000 */
945 	{11289600, 2, 2},	/* 5644800 */
946 	{12288000, 2, 2},	/* 6144000 */
947 	{12000000, 2, 2},	/* 6000000 */
948 	{13000000, 2, 2},	/* 6500000 */
949 	{19200000, 3, 3},	/* 6400000 */
950 	{24000000, 4, 4},	/* 6000000 */
951 	{26000000, 4, 4},	/* 6500000 */
952 	{38400000, 6, 5}	/* 6400000 */
953 };
954 
955 static int cs42l73_get_mclkx_coeff(int mclkx)
956 {
957 	int i;
958 
959 	for (i = 0; i < ARRAY_SIZE(cs42l73_mclkx_coeffs); i++) {
960 		if (cs42l73_mclkx_coeffs[i].mclkx == mclkx)
961 			return i;
962 	}
963 	return -EINVAL;
964 }
965 
966 static int cs42l73_get_mclk_coeff(int mclk, int srate)
967 {
968 	int i;
969 
970 	for (i = 0; i < ARRAY_SIZE(cs42l73_mclk_coeffs); i++) {
971 		if (cs42l73_mclk_coeffs[i].mclk == mclk &&
972 		    cs42l73_mclk_coeffs[i].srate == srate)
973 			return i;
974 	}
975 	return -EINVAL;
976 
977 }
978 
979 static int cs42l73_set_mclk(struct snd_soc_dai *dai, unsigned int freq)
980 {
981 	struct snd_soc_codec *codec = dai->codec;
982 	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
983 
984 	int mclkx_coeff;
985 	u32 mclk = 0;
986 	u8 dmmcc = 0;
987 
988 	/* MCLKX -> MCLK */
989 	mclkx_coeff = cs42l73_get_mclkx_coeff(freq);
990 	if (mclkx_coeff < 0)
991 		return mclkx_coeff;
992 
993 	mclk = cs42l73_mclkx_coeffs[mclkx_coeff].mclkx /
994 		cs42l73_mclkx_coeffs[mclkx_coeff].ratio;
995 
996 	dev_dbg(codec->dev, "MCLK%u %u  <-> internal MCLK %u\n",
997 		 priv->mclksel + 1, cs42l73_mclkx_coeffs[mclkx_coeff].mclkx,
998 		 mclk);
999 
1000 	dmmcc = (priv->mclksel << 4) |
1001 		(cs42l73_mclkx_coeffs[mclkx_coeff].mclkdiv << 1);
1002 
1003 	snd_soc_write(codec, CS42L73_DMMCC, dmmcc);
1004 
1005 	priv->sysclk = mclkx_coeff;
1006 	priv->mclk = mclk;
1007 
1008 	return 0;
1009 }
1010 
1011 static int cs42l73_set_sysclk(struct snd_soc_dai *dai,
1012 			      int clk_id, unsigned int freq, int dir)
1013 {
1014 	struct snd_soc_codec *codec = dai->codec;
1015 	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
1016 
1017 	switch (clk_id) {
1018 	case CS42L73_CLKID_MCLK1:
1019 		break;
1020 	case CS42L73_CLKID_MCLK2:
1021 		break;
1022 	default:
1023 		return -EINVAL;
1024 	}
1025 
1026 	if ((cs42l73_set_mclk(dai, freq)) < 0) {
1027 		dev_err(codec->dev, "Unable to set MCLK for dai %s\n",
1028 			dai->name);
1029 		return -EINVAL;
1030 	}
1031 
1032 	priv->mclksel = clk_id;
1033 
1034 	return 0;
1035 }
1036 
1037 static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
1038 {
1039 	struct snd_soc_codec *codec = codec_dai->codec;
1040 	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
1041 	u8 id = codec_dai->id;
1042 	unsigned int inv, format;
1043 	u8 spc, mmcc;
1044 
1045 	spc = snd_soc_read(codec, CS42L73_SPC(id));
1046 	mmcc = snd_soc_read(codec, CS42L73_MMCC(id));
1047 
1048 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1049 	case SND_SOC_DAIFMT_CBM_CFM:
1050 		mmcc |= CS42L73_MS_MASTER;
1051 		break;
1052 
1053 	case SND_SOC_DAIFMT_CBS_CFS:
1054 		mmcc &= ~CS42L73_MS_MASTER;
1055 		break;
1056 
1057 	default:
1058 		return -EINVAL;
1059 	}
1060 
1061 	format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1062 	inv = (fmt & SND_SOC_DAIFMT_INV_MASK);
1063 
1064 	switch (format) {
1065 	case SND_SOC_DAIFMT_I2S:
1066 		spc &= ~CS42L73_SPDIF_PCM;
1067 		break;
1068 	case SND_SOC_DAIFMT_DSP_A:
1069 	case SND_SOC_DAIFMT_DSP_B:
1070 		if (mmcc & CS42L73_MS_MASTER) {
1071 			dev_err(codec->dev,
1072 				"PCM format in slave mode only\n");
1073 			return -EINVAL;
1074 		}
1075 		if (id == CS42L73_ASP) {
1076 			dev_err(codec->dev,
1077 				"PCM format is not supported on ASP port\n");
1078 			return -EINVAL;
1079 		}
1080 		spc |= CS42L73_SPDIF_PCM;
1081 		break;
1082 	default:
1083 		return -EINVAL;
1084 	}
1085 
1086 	if (spc & CS42L73_SPDIF_PCM) {
1087 		/* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
1088 		spc &= ~(CS42L73_PCM_MODE_MASK | CS42L73_PCM_BIT_ORDER);
1089 		switch (format) {
1090 		case SND_SOC_DAIFMT_DSP_B:
1091 			if (inv == SND_SOC_DAIFMT_IB_IF)
1092 				spc |= CS42L73_PCM_MODE0;
1093 			if (inv == SND_SOC_DAIFMT_IB_NF)
1094 				spc |= CS42L73_PCM_MODE1;
1095 		break;
1096 		case SND_SOC_DAIFMT_DSP_A:
1097 			if (inv == SND_SOC_DAIFMT_IB_IF)
1098 				spc |= CS42L73_PCM_MODE1;
1099 			break;
1100 		default:
1101 			return -EINVAL;
1102 		}
1103 	}
1104 
1105 	priv->config[id].spc = spc;
1106 	priv->config[id].mmcc = mmcc;
1107 
1108 	return 0;
1109 }
1110 
1111 static const unsigned int cs42l73_asrc_rates[] = {
1112 	8000, 11025, 12000, 16000, 22050,
1113 	24000, 32000, 44100, 48000
1114 };
1115 
1116 static unsigned int cs42l73_get_xspfs_coeff(u32 rate)
1117 {
1118 	int i;
1119 	for (i = 0; i < ARRAY_SIZE(cs42l73_asrc_rates); i++) {
1120 		if (cs42l73_asrc_rates[i] == rate)
1121 			return i + 1;
1122 	}
1123 	return 0;		/* 0 = Don't know */
1124 }
1125 
1126 static void cs42l73_update_asrc(struct snd_soc_codec *codec, int id, int srate)
1127 {
1128 	u8 spfs = 0;
1129 
1130 	if (srate > 0)
1131 		spfs = cs42l73_get_xspfs_coeff(srate);
1132 
1133 	switch (id) {
1134 	case CS42L73_XSP:
1135 		snd_soc_update_bits(codec, CS42L73_VXSPFS, 0x0f, spfs);
1136 	break;
1137 	case CS42L73_ASP:
1138 		snd_soc_update_bits(codec, CS42L73_ASPC, 0x3c, spfs << 2);
1139 	break;
1140 	case CS42L73_VSP:
1141 		snd_soc_update_bits(codec, CS42L73_VXSPFS, 0xf0, spfs << 4);
1142 	break;
1143 	default:
1144 	break;
1145 	}
1146 }
1147 
1148 static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
1149 				 struct snd_pcm_hw_params *params,
1150 				 struct snd_soc_dai *dai)
1151 {
1152 	struct snd_soc_codec *codec = dai->codec;
1153 	struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
1154 	int id = dai->id;
1155 	int mclk_coeff;
1156 	int srate = params_rate(params);
1157 
1158 	if (priv->config[id].mmcc & CS42L73_MS_MASTER) {
1159 		/* CS42L73 Master */
1160 		/* MCLK -> srate */
1161 		mclk_coeff =
1162 		    cs42l73_get_mclk_coeff(priv->mclk, srate);
1163 
1164 		if (mclk_coeff < 0)
1165 			return -EINVAL;
1166 
1167 		dev_dbg(codec->dev,
1168 			 "DAI[%d]: MCLK %u, srate %u, MMCC[5:0] = %x\n",
1169 			 id, priv->mclk, srate,
1170 			 cs42l73_mclk_coeffs[mclk_coeff].mmcc);
1171 
1172 		priv->config[id].mmcc &= 0xC0;
1173 		priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
1174 		priv->config[id].spc &= 0xFC;
1175 		/* Use SCLK=64*Fs if internal MCLK >= 6.4MHz */
1176 		if (priv->mclk >= 6400000)
1177 			priv->config[id].spc |= CS42L73_MCK_SCLK_64FS;
1178 		else
1179 			priv->config[id].spc |= CS42L73_MCK_SCLK_MCLK;
1180 	} else {
1181 		/* CS42L73 Slave */
1182 		priv->config[id].spc &= 0xFC;
1183 		priv->config[id].spc |= CS42L73_MCK_SCLK_64FS;
1184 	}
1185 	/* Update ASRCs */
1186 	priv->config[id].srate = srate;
1187 
1188 	snd_soc_write(codec, CS42L73_SPC(id), priv->config[id].spc);
1189 	snd_soc_write(codec, CS42L73_MMCC(id), priv->config[id].mmcc);
1190 
1191 	cs42l73_update_asrc(codec, id, srate);
1192 
1193 	return 0;
1194 }
1195 
1196 static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
1197 				  enum snd_soc_bias_level level)
1198 {
1199 	struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
1200 
1201 	switch (level) {
1202 	case SND_SOC_BIAS_ON:
1203 		snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 0);
1204 		snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 0);
1205 		break;
1206 
1207 	case SND_SOC_BIAS_PREPARE:
1208 		break;
1209 
1210 	case SND_SOC_BIAS_STANDBY:
1211 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
1212 			regcache_cache_only(cs42l73->regmap, false);
1213 			regcache_sync(cs42l73->regmap);
1214 		}
1215 		snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1);
1216 		break;
1217 
1218 	case SND_SOC_BIAS_OFF:
1219 		snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1);
1220 		if (cs42l73->shutdwn_delay > 0) {
1221 			mdelay(cs42l73->shutdwn_delay);
1222 			cs42l73->shutdwn_delay = 0;
1223 		} else {
1224 			mdelay(15); /* Min amount of time requred to power
1225 				     * down.
1226 				     */
1227 		}
1228 		snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 1);
1229 		break;
1230 	}
1231 	codec->dapm.bias_level = level;
1232 	return 0;
1233 }
1234 
1235 static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
1236 {
1237 	struct snd_soc_codec *codec = dai->codec;
1238 	int id = dai->id;
1239 
1240 	return snd_soc_update_bits(codec, CS42L73_SPC(id),
1241 					0x7F, tristate << 7);
1242 }
1243 
1244 static const struct snd_pcm_hw_constraint_list constraints_12_24 = {
1245 	.count  = ARRAY_SIZE(cs42l73_asrc_rates),
1246 	.list   = cs42l73_asrc_rates,
1247 };
1248 
1249 static int cs42l73_pcm_startup(struct snd_pcm_substream *substream,
1250 			       struct snd_soc_dai *dai)
1251 {
1252 	snd_pcm_hw_constraint_list(substream->runtime, 0,
1253 					SNDRV_PCM_HW_PARAM_RATE,
1254 					&constraints_12_24);
1255 	return 0;
1256 }
1257 
1258 
1259 #define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1260 	SNDRV_PCM_FMTBIT_S24_LE)
1261 
1262 static const struct snd_soc_dai_ops cs42l73_ops = {
1263 	.startup = cs42l73_pcm_startup,
1264 	.hw_params = cs42l73_pcm_hw_params,
1265 	.set_fmt = cs42l73_set_dai_fmt,
1266 	.set_sysclk = cs42l73_set_sysclk,
1267 	.set_tristate = cs42l73_set_tristate,
1268 };
1269 
1270 static struct snd_soc_dai_driver cs42l73_dai[] = {
1271 	{
1272 		.name = "cs42l73-xsp",
1273 		.id = CS42L73_XSP,
1274 		.playback = {
1275 			.stream_name = "XSP Playback",
1276 			.channels_min = 1,
1277 			.channels_max = 2,
1278 			.rates = SNDRV_PCM_RATE_KNOT,
1279 			.formats = CS42L73_FORMATS,
1280 		},
1281 		.capture = {
1282 			.stream_name = "XSP Capture",
1283 			.channels_min = 1,
1284 			.channels_max = 2,
1285 			.rates = SNDRV_PCM_RATE_KNOT,
1286 			.formats = CS42L73_FORMATS,
1287 		},
1288 		.ops = &cs42l73_ops,
1289 		.symmetric_rates = 1,
1290 	 },
1291 	{
1292 		.name = "cs42l73-asp",
1293 		.id = CS42L73_ASP,
1294 		.playback = {
1295 			.stream_name = "ASP Playback",
1296 			.channels_min = 2,
1297 			.channels_max = 2,
1298 			.rates = SNDRV_PCM_RATE_KNOT,
1299 			.formats = CS42L73_FORMATS,
1300 		},
1301 		.capture = {
1302 			.stream_name = "ASP Capture",
1303 			.channels_min = 2,
1304 			.channels_max = 2,
1305 			.rates = SNDRV_PCM_RATE_KNOT,
1306 			.formats = CS42L73_FORMATS,
1307 		},
1308 		.ops = &cs42l73_ops,
1309 		.symmetric_rates = 1,
1310 	 },
1311 	{
1312 		.name = "cs42l73-vsp",
1313 		.id = CS42L73_VSP,
1314 		.playback = {
1315 			.stream_name = "VSP Playback",
1316 			.channels_min = 1,
1317 			.channels_max = 2,
1318 			.rates = SNDRV_PCM_RATE_KNOT,
1319 			.formats = CS42L73_FORMATS,
1320 		},
1321 		.capture = {
1322 			.stream_name = "VSP Capture",
1323 			.channels_min = 1,
1324 			.channels_max = 2,
1325 			.rates = SNDRV_PCM_RATE_KNOT,
1326 			.formats = CS42L73_FORMATS,
1327 		},
1328 		.ops = &cs42l73_ops,
1329 		.symmetric_rates = 1,
1330 	 }
1331 };
1332 
1333 static int cs42l73_suspend(struct snd_soc_codec *codec)
1334 {
1335 	cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
1336 
1337 	return 0;
1338 }
1339 
1340 static int cs42l73_resume(struct snd_soc_codec *codec)
1341 {
1342 	cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1343 	return 0;
1344 }
1345 
1346 static int cs42l73_probe(struct snd_soc_codec *codec)
1347 {
1348 	struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
1349 
1350 	cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1351 
1352 	/* Set Charge Pump Frequency */
1353 	if (cs42l73->pdata.chgfreq)
1354 		snd_soc_update_bits(codec, CS42L73_CPFCHC,
1355 				    CS42L73_CHARGEPUMP_MASK,
1356 					cs42l73->pdata.chgfreq << 4);
1357 
1358 	/* MCLK1 as master clk */
1359 	cs42l73->mclksel = CS42L73_CLKID_MCLK1;
1360 	cs42l73->mclk = 0;
1361 
1362 	return 0;
1363 }
1364 
1365 static int cs42l73_remove(struct snd_soc_codec *codec)
1366 {
1367 	cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
1368 	return 0;
1369 }
1370 
1371 static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
1372 	.probe = cs42l73_probe,
1373 	.remove = cs42l73_remove,
1374 	.suspend = cs42l73_suspend,
1375 	.resume = cs42l73_resume,
1376 	.set_bias_level = cs42l73_set_bias_level,
1377 
1378 	.dapm_widgets = cs42l73_dapm_widgets,
1379 	.num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets),
1380 	.dapm_routes = cs42l73_audio_map,
1381 	.num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map),
1382 
1383 	.controls = cs42l73_snd_controls,
1384 	.num_controls = ARRAY_SIZE(cs42l73_snd_controls),
1385 };
1386 
1387 static struct regmap_config cs42l73_regmap = {
1388 	.reg_bits = 8,
1389 	.val_bits = 8,
1390 
1391 	.max_register = CS42L73_MAX_REGISTER,
1392 	.reg_defaults = cs42l73_reg_defaults,
1393 	.num_reg_defaults = ARRAY_SIZE(cs42l73_reg_defaults),
1394 	.volatile_reg = cs42l73_volatile_register,
1395 	.readable_reg = cs42l73_readable_register,
1396 	.cache_type = REGCACHE_RBTREE,
1397 };
1398 
1399 static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
1400 			     const struct i2c_device_id *id)
1401 {
1402 	struct cs42l73_private *cs42l73;
1403 	struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
1404 	int ret;
1405 	unsigned int devid = 0;
1406 	unsigned int reg;
1407 	u32 val32;
1408 
1409 	cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
1410 			       GFP_KERNEL);
1411 	if (!cs42l73) {
1412 		dev_err(&i2c_client->dev, "could not allocate codec\n");
1413 		return -ENOMEM;
1414 	}
1415 
1416 	cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
1417 	if (IS_ERR(cs42l73->regmap)) {
1418 		ret = PTR_ERR(cs42l73->regmap);
1419 		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1420 		return ret;
1421 	}
1422 
1423 	if (pdata) {
1424 		cs42l73->pdata = *pdata;
1425 	} else {
1426 		pdata = devm_kzalloc(&i2c_client->dev,
1427 				     sizeof(struct cs42l73_platform_data),
1428 				GFP_KERNEL);
1429 		if (!pdata) {
1430 			dev_err(&i2c_client->dev, "could not allocate pdata\n");
1431 			return -ENOMEM;
1432 		}
1433 		if (i2c_client->dev.of_node) {
1434 			if (of_property_read_u32(i2c_client->dev.of_node,
1435 				"chgfreq", &val32) >= 0)
1436 				pdata->chgfreq = val32;
1437 		}
1438 		pdata->reset_gpio = of_get_named_gpio(i2c_client->dev.of_node,
1439 						"reset-gpio", 0);
1440 		cs42l73->pdata = *pdata;
1441 	}
1442 
1443 	i2c_set_clientdata(i2c_client, cs42l73);
1444 
1445 	if (cs42l73->pdata.reset_gpio) {
1446 		ret = devm_gpio_request_one(&i2c_client->dev,
1447 					    cs42l73->pdata.reset_gpio,
1448 					    GPIOF_OUT_INIT_HIGH,
1449 					    "CS42L73 /RST");
1450 		if (ret < 0) {
1451 			dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
1452 				cs42l73->pdata.reset_gpio, ret);
1453 			return ret;
1454 		}
1455 		gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
1456 		gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
1457 	}
1458 
1459 	regcache_cache_bypass(cs42l73->regmap, true);
1460 
1461 	/* initialize codec */
1462 	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
1463 	devid = (reg & 0xFF) << 12;
1464 
1465 	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, &reg);
1466 	devid |= (reg & 0xFF) << 4;
1467 
1468 	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
1469 	devid |= (reg & 0xF0) >> 4;
1470 
1471 	if (devid != CS42L73_DEVID) {
1472 		ret = -ENODEV;
1473 		dev_err(&i2c_client->dev,
1474 			"CS42L73 Device ID (%X). Expected %X\n",
1475 			devid, CS42L73_DEVID);
1476 		return ret;
1477 	}
1478 
1479 	ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
1480 	if (ret < 0) {
1481 		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
1482 		return ret;;
1483 	}
1484 
1485 	dev_info(&i2c_client->dev,
1486 		 "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
1487 
1488 	regcache_cache_bypass(cs42l73->regmap, false);
1489 
1490 	ret =  snd_soc_register_codec(&i2c_client->dev,
1491 			&soc_codec_dev_cs42l73, cs42l73_dai,
1492 			ARRAY_SIZE(cs42l73_dai));
1493 	if (ret < 0)
1494 		return ret;
1495 	return 0;
1496 }
1497 
1498 static int cs42l73_i2c_remove(struct i2c_client *client)
1499 {
1500 	snd_soc_unregister_codec(&client->dev);
1501 	return 0;
1502 }
1503 
1504 static const struct of_device_id cs42l73_of_match[] = {
1505 	{ .compatible = "cirrus,cs42l73", },
1506 	{},
1507 };
1508 MODULE_DEVICE_TABLE(of, cs42l73_of_match);
1509 
1510 static const struct i2c_device_id cs42l73_id[] = {
1511 	{"cs42l73", 0},
1512 	{}
1513 };
1514 
1515 MODULE_DEVICE_TABLE(i2c, cs42l73_id);
1516 
1517 static struct i2c_driver cs42l73_i2c_driver = {
1518 	.driver = {
1519 		   .name = "cs42l73",
1520 		   .owner = THIS_MODULE,
1521 		   .of_match_table = cs42l73_of_match,
1522 		   },
1523 	.id_table = cs42l73_id,
1524 	.probe = cs42l73_i2c_probe,
1525 	.remove = cs42l73_i2c_remove,
1526 
1527 };
1528 
1529 module_i2c_driver(cs42l73_i2c_driver);
1530 
1531 MODULE_DESCRIPTION("ASoC CS42L73 driver");
1532 MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
1533 MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
1534 MODULE_LICENSE("GPL");
1535