xref: /openbmc/linux/sound/soc/codecs/cs42l52.c (revision 36bccb11)
1 /*
2  * cs42l52.c -- CS42L52 ALSA SoC audio driver
3  *
4  * Copyright 2012 CirrusLogic, Inc.
5  *
6  * Author: Georgi Vlaev <joe@nucleusys.com>
7  * Author: Brian Austin <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/input.h>
24 #include <linux/regmap.h>
25 #include <linux/slab.h>
26 #include <linux/workqueue.h>
27 #include <linux/platform_device.h>
28 #include <sound/core.h>
29 #include <sound/pcm.h>
30 #include <sound/pcm_params.h>
31 #include <sound/soc.h>
32 #include <sound/soc-dapm.h>
33 #include <sound/initval.h>
34 #include <sound/tlv.h>
35 #include <sound/cs42l52.h>
36 #include "cs42l52.h"
37 
38 struct sp_config {
39 	u8 spc, format, spfs;
40 	u32 srate;
41 };
42 
43 struct  cs42l52_private {
44 	struct regmap *regmap;
45 	struct snd_soc_codec *codec;
46 	struct device *dev;
47 	struct sp_config config;
48 	struct cs42l52_platform_data pdata;
49 	u32 sysclk;
50 	u8 mclksel;
51 	u32 mclk;
52 	u8 flags;
53 #if IS_ENABLED(CONFIG_INPUT)
54 	struct input_dev *beep;
55 	struct work_struct beep_work;
56 	int beep_rate;
57 #endif
58 };
59 
60 static const struct reg_default cs42l52_reg_defaults[] = {
61 	{ CS42L52_PWRCTL1, 0x9F },	/* r02 PWRCTL 1 */
62 	{ CS42L52_PWRCTL2, 0x07 },	/* r03 PWRCTL 2 */
63 	{ CS42L52_PWRCTL3, 0xFF },	/* r04 PWRCTL 3 */
64 	{ CS42L52_CLK_CTL, 0xA0 },	/* r05 Clocking Ctl */
65 	{ CS42L52_IFACE_CTL1, 0x00 },	/* r06 Interface Ctl 1 */
66 	{ CS42L52_ADC_PGA_A, 0x80 },	/* r08 Input A Select */
67 	{ CS42L52_ADC_PGA_B, 0x80 },	/* r09 Input B Select */
68 	{ CS42L52_ANALOG_HPF_CTL, 0xA5 },	/* r0A Analog HPF Ctl */
69 	{ CS42L52_ADC_HPF_FREQ, 0x00 },	/* r0B ADC HPF Corner Freq */
70 	{ CS42L52_ADC_MISC_CTL, 0x00 },	/* r0C Misc. ADC Ctl */
71 	{ CS42L52_PB_CTL1, 0x60 },	/* r0D Playback Ctl 1 */
72 	{ CS42L52_MISC_CTL, 0x02 },	/* r0E Misc. Ctl */
73 	{ CS42L52_PB_CTL2, 0x00 },	/* r0F Playback Ctl 2 */
74 	{ CS42L52_MICA_CTL, 0x00 },	/* r10 MICA Amp Ctl */
75 	{ CS42L52_MICB_CTL, 0x00 },	/* r11 MICB Amp Ctl */
76 	{ CS42L52_PGAA_CTL, 0x00 },	/* r12 PGAA Vol, Misc. */
77 	{ CS42L52_PGAB_CTL, 0x00 },	/* r13 PGAB Vol, Misc. */
78 	{ CS42L52_PASSTHRUA_VOL, 0x00 },	/* r14 Bypass A Vol */
79 	{ CS42L52_PASSTHRUB_VOL, 0x00 },	/* r15 Bypass B Vol */
80 	{ CS42L52_ADCA_VOL, 0x00 },	/* r16 ADCA Volume */
81 	{ CS42L52_ADCB_VOL, 0x00 },	/* r17 ADCB Volume */
82 	{ CS42L52_ADCA_MIXER_VOL, 0x80 },	/* r18 ADCA Mixer Volume */
83 	{ CS42L52_ADCB_MIXER_VOL, 0x80 },	/* r19 ADCB Mixer Volume */
84 	{ CS42L52_PCMA_MIXER_VOL, 0x00 },	/* r1A PCMA Mixer Volume */
85 	{ CS42L52_PCMB_MIXER_VOL, 0x00 },	/* r1B PCMB Mixer Volume */
86 	{ CS42L52_BEEP_FREQ, 0x00 },	/* r1C Beep Freq on Time */
87 	{ CS42L52_BEEP_VOL, 0x00 },	/* r1D Beep Volume off Time */
88 	{ CS42L52_BEEP_TONE_CTL, 0x00 },	/* r1E Beep Tone Cfg. */
89 	{ CS42L52_TONE_CTL, 0x00 },	/* r1F Tone Ctl */
90 	{ CS42L52_MASTERA_VOL, 0x00 },	/* r20 Master A Volume */
91 	{ CS42L52_MASTERB_VOL, 0x00 },	/* r21 Master B Volume */
92 	{ CS42L52_HPA_VOL, 0x00 },	/* r22 Headphone A Volume */
93 	{ CS42L52_HPB_VOL, 0x00 },	/* r23 Headphone B Volume */
94 	{ CS42L52_SPKA_VOL, 0x00 },	/* r24 Speaker A Volume */
95 	{ CS42L52_SPKB_VOL, 0x00 },	/* r25 Speaker B Volume */
96 	{ CS42L52_ADC_PCM_MIXER, 0x00 },	/* r26 Channel Mixer and Swap */
97 	{ CS42L52_LIMITER_CTL1, 0x00 },	/* r27 Limit Ctl 1 Thresholds */
98 	{ CS42L52_LIMITER_CTL2, 0x7F },	/* r28 Limit Ctl 2 Release Rate */
99 	{ CS42L52_LIMITER_AT_RATE, 0xC0 },	/* r29 Limiter Attack Rate */
100 	{ CS42L52_ALC_CTL, 0x00 },	/* r2A ALC Ctl 1 Attack Rate */
101 	{ CS42L52_ALC_RATE, 0x3F },	/* r2B ALC Release Rate */
102 	{ CS42L52_ALC_THRESHOLD, 0x3f },	/* r2C ALC Thresholds */
103 	{ CS42L52_NOISE_GATE_CTL, 0x00 },	/* r2D Noise Gate Ctl */
104 	{ CS42L52_CLK_STATUS, 0x00 },	/* r2E Overflow and Clock Status */
105 	{ CS42L52_BATT_COMPEN, 0x00 },	/* r2F battery Compensation */
106 	{ CS42L52_BATT_LEVEL, 0x00 },	/* r30 VP Battery Level */
107 	{ CS42L52_SPK_STATUS, 0x00 },	/* r31 Speaker Status */
108 	{ CS42L52_TEM_CTL, 0x3B },	/* r32 Temp Ctl */
109 	{ CS42L52_THE_FOLDBACK, 0x00 },	/* r33 Foldback */
110 };
111 
112 static bool cs42l52_readable_register(struct device *dev, unsigned int reg)
113 {
114 	switch (reg) {
115 	case CS42L52_CHIP:
116 	case CS42L52_PWRCTL1:
117 	case CS42L52_PWRCTL2:
118 	case CS42L52_PWRCTL3:
119 	case CS42L52_CLK_CTL:
120 	case CS42L52_IFACE_CTL1:
121 	case CS42L52_IFACE_CTL2:
122 	case CS42L52_ADC_PGA_A:
123 	case CS42L52_ADC_PGA_B:
124 	case CS42L52_ANALOG_HPF_CTL:
125 	case CS42L52_ADC_HPF_FREQ:
126 	case CS42L52_ADC_MISC_CTL:
127 	case CS42L52_PB_CTL1:
128 	case CS42L52_MISC_CTL:
129 	case CS42L52_PB_CTL2:
130 	case CS42L52_MICA_CTL:
131 	case CS42L52_MICB_CTL:
132 	case CS42L52_PGAA_CTL:
133 	case CS42L52_PGAB_CTL:
134 	case CS42L52_PASSTHRUA_VOL:
135 	case CS42L52_PASSTHRUB_VOL:
136 	case CS42L52_ADCA_VOL:
137 	case CS42L52_ADCB_VOL:
138 	case CS42L52_ADCA_MIXER_VOL:
139 	case CS42L52_ADCB_MIXER_VOL:
140 	case CS42L52_PCMA_MIXER_VOL:
141 	case CS42L52_PCMB_MIXER_VOL:
142 	case CS42L52_BEEP_FREQ:
143 	case CS42L52_BEEP_VOL:
144 	case CS42L52_BEEP_TONE_CTL:
145 	case CS42L52_TONE_CTL:
146 	case CS42L52_MASTERA_VOL:
147 	case CS42L52_MASTERB_VOL:
148 	case CS42L52_HPA_VOL:
149 	case CS42L52_HPB_VOL:
150 	case CS42L52_SPKA_VOL:
151 	case CS42L52_SPKB_VOL:
152 	case CS42L52_ADC_PCM_MIXER:
153 	case CS42L52_LIMITER_CTL1:
154 	case CS42L52_LIMITER_CTL2:
155 	case CS42L52_LIMITER_AT_RATE:
156 	case CS42L52_ALC_CTL:
157 	case CS42L52_ALC_RATE:
158 	case CS42L52_ALC_THRESHOLD:
159 	case CS42L52_NOISE_GATE_CTL:
160 	case CS42L52_CLK_STATUS:
161 	case CS42L52_BATT_COMPEN:
162 	case CS42L52_BATT_LEVEL:
163 	case CS42L52_SPK_STATUS:
164 	case CS42L52_TEM_CTL:
165 	case CS42L52_THE_FOLDBACK:
166 	case CS42L52_CHARGE_PUMP:
167 		return true;
168 	default:
169 		return false;
170 	}
171 }
172 
173 static bool cs42l52_volatile_register(struct device *dev, unsigned int reg)
174 {
175 	switch (reg) {
176 	case CS42L52_IFACE_CTL2:
177 	case CS42L52_CLK_STATUS:
178 	case CS42L52_BATT_LEVEL:
179 	case CS42L52_SPK_STATUS:
180 	case CS42L52_CHARGE_PUMP:
181 		return 1;
182 	default:
183 		return 0;
184 	}
185 }
186 
187 static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
188 
189 static DECLARE_TLV_DB_SCALE(hpd_tlv, -9600, 50, 1);
190 
191 static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
192 
193 static DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0);
194 
195 static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
196 
197 static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0);
198 
199 static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0);
200 
201 static const unsigned int limiter_tlv[] = {
202 	TLV_DB_RANGE_HEAD(2),
203 	0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
204 	3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
205 };
206 
207 static const char * const cs42l52_adca_text[] = {
208 	"Input1A", "Input2A", "Input3A", "Input4A", "PGA Input Left"};
209 
210 static const char * const cs42l52_adcb_text[] = {
211 	"Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"};
212 
213 static SOC_ENUM_SINGLE_DECL(adca_enum,
214 			    CS42L52_ADC_PGA_A, 5, cs42l52_adca_text);
215 
216 static SOC_ENUM_SINGLE_DECL(adcb_enum,
217 			    CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text);
218 
219 static const struct snd_kcontrol_new adca_mux =
220 	SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum);
221 
222 static const struct snd_kcontrol_new adcb_mux =
223 	SOC_DAPM_ENUM("Right ADC Input Capture Mux", adcb_enum);
224 
225 static const char * const mic_bias_level_text[] = {
226 	"0.5 +VA", "0.6 +VA", "0.7 +VA",
227 	"0.8 +VA", "0.83 +VA", "0.91 +VA"
228 };
229 
230 static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum,
231 			    CS42L52_IFACE_CTL2, 0, mic_bias_level_text);
232 
233 static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" };
234 
235 static SOC_ENUM_SINGLE_DECL(mica_enum,
236 			    CS42L52_MICA_CTL, 5, cs42l52_mic_text);
237 
238 static SOC_ENUM_SINGLE_DECL(micb_enum,
239 			    CS42L52_MICB_CTL, 5, cs42l52_mic_text);
240 
241 static const char * const digital_output_mux_text[] = {"ADC", "DSP"};
242 
243 static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum,
244 			    CS42L52_ADC_MISC_CTL, 6,
245 			    digital_output_mux_text);
246 
247 static const struct snd_kcontrol_new digital_output_mux =
248 	SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum);
249 
250 static const char * const hp_gain_num_text[] = {
251 	"0.3959", "0.4571", "0.5111", "0.6047",
252 	"0.7099", "0.8399", "1.000", "1.1430"
253 };
254 
255 static SOC_ENUM_SINGLE_DECL(hp_gain_enum,
256 			    CS42L52_PB_CTL1, 5,
257 			    hp_gain_num_text);
258 
259 static const char * const beep_pitch_text[] = {
260 	"C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5",
261 	"C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"
262 };
263 
264 static SOC_ENUM_SINGLE_DECL(beep_pitch_enum,
265 			    CS42L52_BEEP_FREQ, 4,
266 			    beep_pitch_text);
267 
268 static const char * const beep_ontime_text[] = {
269 	"86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s",
270 	"1.80 s", "2.20 s", "2.50 s", "2.80 s", "3.20 s",
271 	"3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s"
272 };
273 
274 static SOC_ENUM_SINGLE_DECL(beep_ontime_enum,
275 			    CS42L52_BEEP_FREQ, 0,
276 			    beep_ontime_text);
277 
278 static const char * const beep_offtime_text[] = {
279 	"1.23 s", "2.58 s", "3.90 s", "5.20 s",
280 	"6.60 s", "8.05 s", "9.35 s", "10.80 s"
281 };
282 
283 static SOC_ENUM_SINGLE_DECL(beep_offtime_enum,
284 			    CS42L52_BEEP_VOL, 5,
285 			    beep_offtime_text);
286 
287 static const char * const beep_config_text[] = {
288 	"Off", "Single", "Multiple", "Continuous"
289 };
290 
291 static SOC_ENUM_SINGLE_DECL(beep_config_enum,
292 			    CS42L52_BEEP_TONE_CTL, 6,
293 			    beep_config_text);
294 
295 static const char * const beep_bass_text[] = {
296 	"50 Hz", "100 Hz", "200 Hz", "250 Hz"
297 };
298 
299 static SOC_ENUM_SINGLE_DECL(beep_bass_enum,
300 			    CS42L52_BEEP_TONE_CTL, 1,
301 			    beep_bass_text);
302 
303 static const char * const beep_treble_text[] = {
304 	"5 kHz", "7 kHz", "10 kHz", " 15 kHz"
305 };
306 
307 static SOC_ENUM_SINGLE_DECL(beep_treble_enum,
308 			    CS42L52_BEEP_TONE_CTL, 3,
309 			    beep_treble_text);
310 
311 static const char * const ng_threshold_text[] = {
312 	"-34dB", "-37dB", "-40dB", "-43dB",
313 	"-46dB", "-52dB", "-58dB", "-64dB"
314 };
315 
316 static SOC_ENUM_SINGLE_DECL(ng_threshold_enum,
317 			    CS42L52_NOISE_GATE_CTL, 2,
318 			    ng_threshold_text);
319 
320 static const char * const cs42l52_ng_delay_text[] = {
321 	"50ms", "100ms", "150ms", "200ms"};
322 
323 static SOC_ENUM_SINGLE_DECL(ng_delay_enum,
324 			    CS42L52_NOISE_GATE_CTL, 0,
325 			    cs42l52_ng_delay_text);
326 
327 static const char * const cs42l52_ng_type_text[] = {
328 	"Apply Specific", "Apply All"
329 };
330 
331 static SOC_ENUM_SINGLE_DECL(ng_type_enum,
332 			    CS42L52_NOISE_GATE_CTL, 6,
333 			    cs42l52_ng_type_text);
334 
335 static const char * const left_swap_text[] = {
336 	"Left", "LR 2", "Right"};
337 
338 static const char * const right_swap_text[] = {
339 	"Right", "LR 2", "Left"};
340 
341 static const unsigned int swap_values[] = { 0, 1, 3 };
342 
343 static const struct soc_enum adca_swap_enum =
344 	SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3,
345 			      ARRAY_SIZE(left_swap_text),
346 			      left_swap_text,
347 			      swap_values);
348 
349 static const struct snd_kcontrol_new adca_mixer =
350 	SOC_DAPM_ENUM("Route", adca_swap_enum);
351 
352 static const struct soc_enum pcma_swap_enum =
353 	SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3,
354 			      ARRAY_SIZE(left_swap_text),
355 			      left_swap_text,
356 			      swap_values);
357 
358 static const struct snd_kcontrol_new pcma_mixer =
359 	SOC_DAPM_ENUM("Route", pcma_swap_enum);
360 
361 static const struct soc_enum adcb_swap_enum =
362 	SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3,
363 			      ARRAY_SIZE(right_swap_text),
364 			      right_swap_text,
365 			      swap_values);
366 
367 static const struct snd_kcontrol_new adcb_mixer =
368 	SOC_DAPM_ENUM("Route", adcb_swap_enum);
369 
370 static const struct soc_enum pcmb_swap_enum =
371 	SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3,
372 			      ARRAY_SIZE(right_swap_text),
373 			      right_swap_text,
374 			      swap_values);
375 
376 static const struct snd_kcontrol_new pcmb_mixer =
377 	SOC_DAPM_ENUM("Route", pcmb_swap_enum);
378 
379 
380 static const struct snd_kcontrol_new passthrul_ctl =
381 	SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 6, 1, 0);
382 
383 static const struct snd_kcontrol_new passthrur_ctl =
384 	SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 7, 1, 0);
385 
386 static const struct snd_kcontrol_new spkl_ctl =
387 	SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 0, 1, 1);
388 
389 static const struct snd_kcontrol_new spkr_ctl =
390 	SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 2, 1, 1);
391 
392 static const struct snd_kcontrol_new hpl_ctl =
393 	SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 4, 1, 1);
394 
395 static const struct snd_kcontrol_new hpr_ctl =
396 	SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 6, 1, 1);
397 
398 static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
399 
400 	SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L52_MASTERA_VOL,
401 			      CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv),
402 
403 	SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL,
404 			      CS42L52_HPB_VOL, 0, 0x34, 0xCC, hpd_tlv),
405 
406 	SOC_ENUM("Headphone Analog Gain", hp_gain_enum),
407 
408 	SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL,
409 			      CS42L52_SPKB_VOL, 0, 0x1, 0xff, hl_tlv),
410 
411 	SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
412 			      CS42L52_PASSTHRUB_VOL, 6, 0x18, 0x90, pga_tlv),
413 
414 	SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0),
415 
416 	SOC_DOUBLE_R_TLV("MIC Gain Volume", CS42L52_MICA_CTL,
417 			      CS42L52_MICB_CTL, 0, 0x10, 0, mic_tlv),
418 
419 	SOC_ENUM("MIC Bias Level", mic_bias_level_enum),
420 
421 	SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL,
422 			      CS42L52_ADCB_VOL, 7, 0x80, 0xA0, ipd_tlv),
423 	SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
424 			     CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL,
425 				6, 0x7f, 0x19, ipd_tlv),
426 
427 	SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0),
428 
429 	SOC_DOUBLE_R("ADC Mixer Switch", CS42L52_ADCA_MIXER_VOL,
430 		     CS42L52_ADCB_MIXER_VOL, 7, 1, 1),
431 
432 	SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL,
433 			    CS42L52_PGAB_CTL, 0, 0x28, 0x30, pga_tlv),
434 
435 	SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume",
436 			    CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL,
437 				0, 0x7f, 0x19, mix_tlv),
438 	SOC_DOUBLE_R("PCM Mixer Switch",
439 		     CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
440 
441 	SOC_ENUM("Beep Config", beep_config_enum),
442 	SOC_ENUM("Beep Pitch", beep_pitch_enum),
443 	SOC_ENUM("Beep on Time", beep_ontime_enum),
444 	SOC_ENUM("Beep off Time", beep_offtime_enum),
445 	SOC_SINGLE_SX_TLV("Beep Volume", CS42L52_BEEP_VOL,
446 			0, 0x07, 0x1f, beep_tlv),
447 	SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1),
448 	SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
449 	SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
450 
451 	SOC_SINGLE("Tone Control Switch", CS42L52_BEEP_TONE_CTL, 0, 1, 1),
452 	SOC_SINGLE_TLV("Treble Gain Volume",
453 			    CS42L52_TONE_CTL, 4, 15, 1, hl_tlv),
454 	SOC_SINGLE_TLV("Bass Gain Volume",
455 			    CS42L52_TONE_CTL, 0, 15, 1, hl_tlv),
456 
457 	/* Limiter */
458 	SOC_SINGLE_TLV("Limiter Max Threshold Volume",
459 		       CS42L52_LIMITER_CTL1, 5, 7, 0, limiter_tlv),
460 	SOC_SINGLE_TLV("Limiter Cushion Threshold Volume",
461 		       CS42L52_LIMITER_CTL1, 2, 7, 0, limiter_tlv),
462 	SOC_SINGLE_TLV("Limiter Release Rate Volume",
463 		       CS42L52_LIMITER_CTL2, 0, 63, 0, limiter_tlv),
464 	SOC_SINGLE_TLV("Limiter Attack Rate Volume",
465 		       CS42L52_LIMITER_AT_RATE, 0, 63, 0, limiter_tlv),
466 
467 	SOC_SINGLE("Limiter SR Switch", CS42L52_LIMITER_CTL1, 1, 1, 0),
468 	SOC_SINGLE("Limiter ZC Switch", CS42L52_LIMITER_CTL1, 0, 1, 0),
469 	SOC_SINGLE("Limiter Switch", CS42L52_LIMITER_CTL2, 7, 1, 0),
470 
471 	/* ALC */
472 	SOC_SINGLE_TLV("ALC Attack Rate Volume", CS42L52_ALC_CTL,
473 		       0, 63, 0, limiter_tlv),
474 	SOC_SINGLE_TLV("ALC Release Rate Volume", CS42L52_ALC_RATE,
475 		       0, 63, 0, limiter_tlv),
476 	SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L52_ALC_THRESHOLD,
477 		       5, 7, 0, limiter_tlv),
478 	SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L52_ALC_THRESHOLD,
479 		       2, 7, 0, limiter_tlv),
480 
481 	SOC_DOUBLE_R("ALC SR Capture Switch", CS42L52_PGAA_CTL,
482 		     CS42L52_PGAB_CTL, 7, 1, 1),
483 	SOC_DOUBLE_R("ALC ZC Capture Switch", CS42L52_PGAA_CTL,
484 		     CS42L52_PGAB_CTL, 6, 1, 1),
485 	SOC_DOUBLE("ALC Capture Switch", CS42L52_ALC_CTL, 6, 7, 1, 0),
486 
487 	/* Noise gate */
488 	SOC_ENUM("NG Type Switch", ng_type_enum),
489 	SOC_SINGLE("NG Enable Switch", CS42L52_NOISE_GATE_CTL, 6, 1, 0),
490 	SOC_SINGLE("NG Boost Switch", CS42L52_NOISE_GATE_CTL, 5, 1, 1),
491 	SOC_ENUM("NG Threshold", ng_threshold_enum),
492 	SOC_ENUM("NG Delay", ng_delay_enum),
493 
494 	SOC_DOUBLE("HPF Switch", CS42L52_ANALOG_HPF_CTL, 5, 7, 1, 0),
495 
496 	SOC_DOUBLE("Analog SR Switch", CS42L52_ANALOG_HPF_CTL, 1, 3, 1, 1),
497 	SOC_DOUBLE("Analog ZC Switch", CS42L52_ANALOG_HPF_CTL, 0, 2, 1, 1),
498 	SOC_SINGLE("Digital SR Switch", CS42L52_MISC_CTL, 1, 1, 0),
499 	SOC_SINGLE("Digital ZC Switch", CS42L52_MISC_CTL, 0, 1, 0),
500 	SOC_SINGLE("Deemphasis Switch", CS42L52_MISC_CTL, 2, 1, 0),
501 
502 	SOC_SINGLE("Batt Compensation Switch", CS42L52_BATT_COMPEN, 7, 1, 0),
503 	SOC_SINGLE("Batt VP Monitor Switch", CS42L52_BATT_COMPEN, 6, 1, 0),
504 	SOC_SINGLE("Batt VP ref", CS42L52_BATT_COMPEN, 0, 0x0f, 0),
505 
506 	SOC_SINGLE("PGA AIN1L Switch", CS42L52_ADC_PGA_A, 0, 1, 0),
507 	SOC_SINGLE("PGA AIN1R Switch", CS42L52_ADC_PGA_B, 0, 1, 0),
508 	SOC_SINGLE("PGA AIN2L Switch", CS42L52_ADC_PGA_A, 1, 1, 0),
509 	SOC_SINGLE("PGA AIN2R Switch", CS42L52_ADC_PGA_B, 1, 1, 0),
510 
511 	SOC_SINGLE("PGA AIN3L Switch", CS42L52_ADC_PGA_A, 2, 1, 0),
512 	SOC_SINGLE("PGA AIN3R Switch", CS42L52_ADC_PGA_B, 2, 1, 0),
513 
514 	SOC_SINGLE("PGA AIN4L Switch", CS42L52_ADC_PGA_A, 3, 1, 0),
515 	SOC_SINGLE("PGA AIN4R Switch", CS42L52_ADC_PGA_B, 3, 1, 0),
516 
517 	SOC_SINGLE("PGA MICA Switch", CS42L52_ADC_PGA_A, 4, 1, 0),
518 	SOC_SINGLE("PGA MICB Switch", CS42L52_ADC_PGA_B, 4, 1, 0),
519 
520 };
521 
522 static const struct snd_kcontrol_new cs42l52_mica_controls[] = {
523 	SOC_ENUM("MICA Select", mica_enum),
524 };
525 
526 static const struct snd_kcontrol_new cs42l52_micb_controls[] = {
527 	SOC_ENUM("MICB Select", micb_enum),
528 };
529 
530 static int cs42l52_add_mic_controls(struct snd_soc_codec *codec)
531 {
532 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
533 	struct cs42l52_platform_data *pdata = &cs42l52->pdata;
534 
535 	if (!pdata->mica_diff_cfg)
536 		snd_soc_add_codec_controls(codec, cs42l52_mica_controls,
537 				     ARRAY_SIZE(cs42l52_mica_controls));
538 
539 	if (!pdata->micb_diff_cfg)
540 		snd_soc_add_codec_controls(codec, cs42l52_micb_controls,
541 				     ARRAY_SIZE(cs42l52_micb_controls));
542 
543 	return 0;
544 }
545 
546 static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
547 
548 	SND_SOC_DAPM_INPUT("AIN1L"),
549 	SND_SOC_DAPM_INPUT("AIN1R"),
550 	SND_SOC_DAPM_INPUT("AIN2L"),
551 	SND_SOC_DAPM_INPUT("AIN2R"),
552 	SND_SOC_DAPM_INPUT("AIN3L"),
553 	SND_SOC_DAPM_INPUT("AIN3R"),
554 	SND_SOC_DAPM_INPUT("AIN4L"),
555 	SND_SOC_DAPM_INPUT("AIN4R"),
556 	SND_SOC_DAPM_INPUT("MICA"),
557 	SND_SOC_DAPM_INPUT("MICB"),
558 	SND_SOC_DAPM_SIGGEN("Beep"),
559 
560 	SND_SOC_DAPM_AIF_OUT("AIFOUTL", NULL,  0,
561 			SND_SOC_NOPM, 0, 0),
562 	SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL,  0,
563 			SND_SOC_NOPM, 0, 0),
564 
565 	SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1),
566 	SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1),
567 	SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0),
568 	SND_SOC_DAPM_PGA("PGA Right", CS42L52_PWRCTL1, 4, 1, NULL, 0),
569 
570 	SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adca_mux),
571 	SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcb_mux),
572 
573 	SND_SOC_DAPM_MUX("ADC Left Swap", SND_SOC_NOPM,
574 			 0, 0, &adca_mixer),
575 	SND_SOC_DAPM_MUX("ADC Right Swap", SND_SOC_NOPM,
576 			 0, 0, &adcb_mixer),
577 
578 	SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM,
579 			 0, 0, &digital_output_mux),
580 
581 	SND_SOC_DAPM_PGA("PGA MICA", CS42L52_PWRCTL2, 1, 1, NULL, 0),
582 	SND_SOC_DAPM_PGA("PGA MICB", CS42L52_PWRCTL2, 2, 1, NULL, 0),
583 
584 	SND_SOC_DAPM_SUPPLY("Mic Bias", CS42L52_PWRCTL2, 0, 1, NULL, 0),
585 	SND_SOC_DAPM_SUPPLY("Charge Pump", CS42L52_PWRCTL1, 7, 1, NULL, 0),
586 
587 	SND_SOC_DAPM_AIF_IN("AIFINL", NULL,  0,
588 			SND_SOC_NOPM, 0, 0),
589 	SND_SOC_DAPM_AIF_IN("AIFINR", NULL,  0,
590 			SND_SOC_NOPM, 0, 0),
591 
592 	SND_SOC_DAPM_DAC("DAC Left", NULL, SND_SOC_NOPM, 0, 0),
593 	SND_SOC_DAPM_DAC("DAC Right", NULL, SND_SOC_NOPM, 0, 0),
594 
595 	SND_SOC_DAPM_SWITCH("Bypass Left", CS42L52_MISC_CTL,
596 			    6, 0, &passthrul_ctl),
597 	SND_SOC_DAPM_SWITCH("Bypass Right", CS42L52_MISC_CTL,
598 			    7, 0, &passthrur_ctl),
599 
600 	SND_SOC_DAPM_MUX("PCM Left Swap", SND_SOC_NOPM,
601 			 0, 0, &pcma_mixer),
602 	SND_SOC_DAPM_MUX("PCM Right Swap", SND_SOC_NOPM,
603 			 0, 0, &pcmb_mixer),
604 
605 	SND_SOC_DAPM_SWITCH("HP Left Amp", SND_SOC_NOPM, 0, 0, &hpl_ctl),
606 	SND_SOC_DAPM_SWITCH("HP Right Amp", SND_SOC_NOPM, 0, 0, &hpr_ctl),
607 
608 	SND_SOC_DAPM_SWITCH("SPK Left Amp", SND_SOC_NOPM, 0, 0, &spkl_ctl),
609 	SND_SOC_DAPM_SWITCH("SPK Right Amp", SND_SOC_NOPM, 0, 0, &spkr_ctl),
610 
611 	SND_SOC_DAPM_OUTPUT("HPOUTA"),
612 	SND_SOC_DAPM_OUTPUT("HPOUTB"),
613 	SND_SOC_DAPM_OUTPUT("SPKOUTA"),
614 	SND_SOC_DAPM_OUTPUT("SPKOUTB"),
615 
616 };
617 
618 static const struct snd_soc_dapm_route cs42l52_audio_map[] = {
619 
620 	{"Capture", NULL, "AIFOUTL"},
621 	{"Capture", NULL, "AIFOUTL"},
622 
623 	{"AIFOUTL", NULL, "Output Mux"},
624 	{"AIFOUTR", NULL, "Output Mux"},
625 
626 	{"Output Mux", "ADC", "ADC Left"},
627 	{"Output Mux", "ADC", "ADC Right"},
628 
629 	{"ADC Left", NULL, "Charge Pump"},
630 	{"ADC Right", NULL, "Charge Pump"},
631 
632 	{"Charge Pump", NULL, "ADC Left Mux"},
633 	{"Charge Pump", NULL, "ADC Right Mux"},
634 
635 	{"ADC Left Mux", "Input1A", "AIN1L"},
636 	{"ADC Right Mux", "Input1B", "AIN1R"},
637 	{"ADC Left Mux", "Input2A", "AIN2L"},
638 	{"ADC Right Mux", "Input2B", "AIN2R"},
639 	{"ADC Left Mux", "Input3A", "AIN3L"},
640 	{"ADC Right Mux", "Input3B", "AIN3R"},
641 	{"ADC Left Mux", "Input4A", "AIN4L"},
642 	{"ADC Right Mux", "Input4B", "AIN4R"},
643 	{"ADC Left Mux", "PGA Input Left", "PGA Left"},
644 	{"ADC Right Mux", "PGA Input Right" , "PGA Right"},
645 
646 	{"PGA Left", "Switch", "AIN1L"},
647 	{"PGA Right", "Switch", "AIN1R"},
648 	{"PGA Left", "Switch", "AIN2L"},
649 	{"PGA Right", "Switch", "AIN2R"},
650 	{"PGA Left", "Switch", "AIN3L"},
651 	{"PGA Right", "Switch", "AIN3R"},
652 	{"PGA Left", "Switch", "AIN4L"},
653 	{"PGA Right", "Switch", "AIN4R"},
654 
655 	{"PGA Left", "Switch", "PGA MICA"},
656 	{"PGA MICA", NULL, "MICA"},
657 
658 	{"PGA Right", "Switch", "PGA MICB"},
659 	{"PGA MICB", NULL, "MICB"},
660 
661 	{"HPOUTA", NULL, "HP Left Amp"},
662 	{"HPOUTB", NULL, "HP Right Amp"},
663 	{"HP Left Amp", NULL, "Bypass Left"},
664 	{"HP Right Amp", NULL, "Bypass Right"},
665 	{"Bypass Left", "Switch", "PGA Left"},
666 	{"Bypass Right", "Switch", "PGA Right"},
667 	{"HP Left Amp", "Switch", "DAC Left"},
668 	{"HP Right Amp", "Switch", "DAC Right"},
669 
670 	{"SPKOUTA", NULL, "SPK Left Amp"},
671 	{"SPKOUTB", NULL, "SPK Right Amp"},
672 
673 	{"SPK Left Amp", NULL, "Beep"},
674 	{"SPK Right Amp", NULL, "Beep"},
675 	{"SPK Left Amp", "Switch", "Playback"},
676 	{"SPK Right Amp", "Switch", "Playback"},
677 
678 	{"DAC Left", NULL, "Beep"},
679 	{"DAC Right", NULL, "Beep"},
680 	{"DAC Left", NULL, "Playback"},
681 	{"DAC Right", NULL, "Playback"},
682 
683 	{"Output Mux", "DSP", "Playback"},
684 	{"Output Mux", "DSP", "Playback"},
685 
686 	{"AIFINL", NULL, "Playback"},
687 	{"AIFINR", NULL, "Playback"},
688 
689 };
690 
691 struct cs42l52_clk_para {
692 	u32 mclk;
693 	u32 rate;
694 	u8 speed;
695 	u8 group;
696 	u8 videoclk;
697 	u8 ratio;
698 	u8 mclkdiv2;
699 };
700 
701 static const struct cs42l52_clk_para clk_map_table[] = {
702 	/*8k*/
703 	{12288000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
704 	{18432000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
705 	{12000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
706 	{24000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
707 	{27000000, 8000, CLK_QS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0},
708 
709 	/*11.025k*/
710 	{11289600, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
711 	{16934400, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
712 
713 	/*16k*/
714 	{12288000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
715 	{18432000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
716 	{12000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
717 	{24000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
718 	{27000000, 16000, CLK_HS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 1},
719 
720 	/*22.05k*/
721 	{11289600, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
722 	{16934400, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
723 
724 	/* 32k */
725 	{12288000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
726 	{18432000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
727 	{12000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
728 	{24000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
729 	{27000000, 32000, CLK_SS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0},
730 
731 	/* 44.1k */
732 	{11289600, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
733 	{16934400, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
734 
735 	/* 48k */
736 	{12288000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
737 	{18432000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
738 	{12000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0},
739 	{24000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1},
740 	{27000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_27M_MCLK, CLK_R_125, 1},
741 
742 	/* 88.2k */
743 	{11289600, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
744 	{16934400, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
745 
746 	/* 96k */
747 	{12288000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
748 	{18432000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
749 	{12000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0},
750 	{24000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1},
751 };
752 
753 static int cs42l52_get_clk(int mclk, int rate)
754 {
755 	int i, ret = -EINVAL;
756 	u_int mclk1, mclk2 = 0;
757 
758 	for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
759 		if (clk_map_table[i].rate == rate) {
760 			mclk1 = clk_map_table[i].mclk;
761 			if (abs(mclk - mclk1) < abs(mclk - mclk2)) {
762 				mclk2 = mclk1;
763 				ret = i;
764 			}
765 		}
766 	}
767 	return ret;
768 }
769 
770 static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
771 			int clk_id, unsigned int freq, int dir)
772 {
773 	struct snd_soc_codec *codec = codec_dai->codec;
774 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
775 
776 	if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) {
777 		cs42l52->sysclk = freq;
778 	} else {
779 		dev_err(codec->dev, "Invalid freq parameter\n");
780 		return -EINVAL;
781 	}
782 	return 0;
783 }
784 
785 static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
786 {
787 	struct snd_soc_codec *codec = codec_dai->codec;
788 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
789 	u8 iface = 0;
790 
791 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
792 	case SND_SOC_DAIFMT_CBM_CFM:
793 		iface = CS42L52_IFACE_CTL1_MASTER;
794 		break;
795 	case SND_SOC_DAIFMT_CBS_CFS:
796 		iface = CS42L52_IFACE_CTL1_SLAVE;
797 		break;
798 	default:
799 		return -EINVAL;
800 	}
801 
802 	 /* interface format */
803 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
804 	case SND_SOC_DAIFMT_I2S:
805 		iface |= CS42L52_IFACE_CTL1_ADC_FMT_I2S |
806 				CS42L52_IFACE_CTL1_DAC_FMT_I2S;
807 		break;
808 	case SND_SOC_DAIFMT_RIGHT_J:
809 		iface |= CS42L52_IFACE_CTL1_DAC_FMT_RIGHT_J;
810 		break;
811 	case SND_SOC_DAIFMT_LEFT_J:
812 		iface |= CS42L52_IFACE_CTL1_ADC_FMT_LEFT_J |
813 				CS42L52_IFACE_CTL1_DAC_FMT_LEFT_J;
814 		break;
815 	case SND_SOC_DAIFMT_DSP_A:
816 		iface |= CS42L52_IFACE_CTL1_DSP_MODE_EN;
817 		break;
818 	case SND_SOC_DAIFMT_DSP_B:
819 		break;
820 	default:
821 		return -EINVAL;
822 	}
823 
824 	/* clock inversion */
825 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
826 	case SND_SOC_DAIFMT_NB_NF:
827 		break;
828 	case SND_SOC_DAIFMT_IB_IF:
829 		iface |= CS42L52_IFACE_CTL1_INV_SCLK;
830 		break;
831 	case SND_SOC_DAIFMT_IB_NF:
832 		iface |= CS42L52_IFACE_CTL1_INV_SCLK;
833 		break;
834 	case SND_SOC_DAIFMT_NB_IF:
835 		break;
836 	default:
837 		return -EINVAL;
838 	}
839 	cs42l52->config.format = iface;
840 	snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
841 
842 	return 0;
843 }
844 
845 static int cs42l52_digital_mute(struct snd_soc_dai *dai, int mute)
846 {
847 	struct snd_soc_codec *codec = dai->codec;
848 
849 	if (mute)
850 		snd_soc_update_bits(codec, CS42L52_PB_CTL1,
851 				    CS42L52_PB_CTL1_MUTE_MASK,
852 				CS42L52_PB_CTL1_MUTE);
853 	else
854 		snd_soc_update_bits(codec, CS42L52_PB_CTL1,
855 				    CS42L52_PB_CTL1_MUTE_MASK,
856 				CS42L52_PB_CTL1_UNMUTE);
857 
858 	return 0;
859 }
860 
861 static int cs42l52_pcm_hw_params(struct snd_pcm_substream *substream,
862 				     struct snd_pcm_hw_params *params,
863 				     struct snd_soc_dai *dai)
864 {
865 	struct snd_soc_codec *codec = dai->codec;
866 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
867 	u32 clk = 0;
868 	int index;
869 
870 	index = cs42l52_get_clk(cs42l52->sysclk, params_rate(params));
871 	if (index >= 0) {
872 		cs42l52->sysclk = clk_map_table[index].mclk;
873 
874 		clk |= (clk_map_table[index].speed << CLK_SPEED_SHIFT) |
875 		(clk_map_table[index].group << CLK_32K_SR_SHIFT) |
876 		(clk_map_table[index].videoclk << CLK_27M_MCLK_SHIFT) |
877 		(clk_map_table[index].ratio << CLK_RATIO_SHIFT) |
878 		clk_map_table[index].mclkdiv2;
879 
880 		snd_soc_write(codec, CS42L52_CLK_CTL, clk);
881 	} else {
882 		dev_err(codec->dev, "can't get correct mclk\n");
883 		return -EINVAL;
884 	}
885 
886 	return 0;
887 }
888 
889 static int cs42l52_set_bias_level(struct snd_soc_codec *codec,
890 					enum snd_soc_bias_level level)
891 {
892 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
893 
894 	switch (level) {
895 	case SND_SOC_BIAS_ON:
896 		break;
897 	case SND_SOC_BIAS_PREPARE:
898 		snd_soc_update_bits(codec, CS42L52_PWRCTL1,
899 				    CS42L52_PWRCTL1_PDN_CODEC, 0);
900 		break;
901 	case SND_SOC_BIAS_STANDBY:
902 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
903 			regcache_cache_only(cs42l52->regmap, false);
904 			regcache_sync(cs42l52->regmap);
905 		}
906 		snd_soc_write(codec, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL);
907 		break;
908 	case SND_SOC_BIAS_OFF:
909 		snd_soc_write(codec, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL);
910 		regcache_cache_only(cs42l52->regmap, true);
911 		break;
912 	}
913 	codec->dapm.bias_level = level;
914 
915 	return 0;
916 }
917 
918 #define CS42L52_RATES (SNDRV_PCM_RATE_8000_96000)
919 
920 #define CS42L52_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
921 			SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \
922 			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
923 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
924 
925 static struct snd_soc_dai_ops cs42l52_ops = {
926 	.hw_params	= cs42l52_pcm_hw_params,
927 	.digital_mute	= cs42l52_digital_mute,
928 	.set_fmt	= cs42l52_set_fmt,
929 	.set_sysclk	= cs42l52_set_sysclk,
930 };
931 
932 static struct snd_soc_dai_driver cs42l52_dai = {
933 		.name = "cs42l52",
934 		.playback = {
935 			.stream_name = "Playback",
936 			.channels_min = 1,
937 			.channels_max = 2,
938 			.rates = CS42L52_RATES,
939 			.formats = CS42L52_FORMATS,
940 		},
941 		.capture = {
942 			.stream_name = "Capture",
943 			.channels_min = 1,
944 			.channels_max = 2,
945 			.rates = CS42L52_RATES,
946 			.formats = CS42L52_FORMATS,
947 		},
948 		.ops = &cs42l52_ops,
949 };
950 
951 static int cs42l52_suspend(struct snd_soc_codec *codec)
952 {
953 	cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF);
954 
955 	return 0;
956 }
957 
958 static int cs42l52_resume(struct snd_soc_codec *codec)
959 {
960 	cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
961 
962 	return 0;
963 }
964 
965 #if IS_ENABLED(CONFIG_INPUT)
966 static int beep_rates[] = {
967 	261, 522, 585, 667, 706, 774, 889, 1000,
968 	1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
969 };
970 
971 static void cs42l52_beep_work(struct work_struct *work)
972 {
973 	struct cs42l52_private *cs42l52 =
974 		container_of(work, struct cs42l52_private, beep_work);
975 	struct snd_soc_codec *codec = cs42l52->codec;
976 	struct snd_soc_dapm_context *dapm = &codec->dapm;
977 	int i;
978 	int val = 0;
979 	int best = 0;
980 
981 	if (cs42l52->beep_rate) {
982 		for (i = 0; i < ARRAY_SIZE(beep_rates); i++) {
983 			if (abs(cs42l52->beep_rate - beep_rates[i]) <
984 			    abs(cs42l52->beep_rate - beep_rates[best]))
985 				best = i;
986 		}
987 
988 		dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
989 			beep_rates[best], cs42l52->beep_rate);
990 
991 		val = (best << CS42L52_BEEP_RATE_SHIFT);
992 
993 		snd_soc_dapm_enable_pin(dapm, "Beep");
994 	} else {
995 		dev_dbg(codec->dev, "Disabling beep\n");
996 		snd_soc_dapm_disable_pin(dapm, "Beep");
997 	}
998 
999 	snd_soc_update_bits(codec, CS42L52_BEEP_FREQ,
1000 			    CS42L52_BEEP_RATE_MASK, val);
1001 
1002 	snd_soc_dapm_sync(dapm);
1003 }
1004 
1005 /* For usability define a way of injecting beep events for the device -
1006  * many systems will not have a keyboard.
1007  */
1008 static int cs42l52_beep_event(struct input_dev *dev, unsigned int type,
1009 			     unsigned int code, int hz)
1010 {
1011 	struct snd_soc_codec *codec = input_get_drvdata(dev);
1012 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
1013 
1014 	dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
1015 
1016 	switch (code) {
1017 	case SND_BELL:
1018 		if (hz)
1019 			hz = 261;
1020 	case SND_TONE:
1021 		break;
1022 	default:
1023 		return -1;
1024 	}
1025 
1026 	/* Kick the beep from a workqueue */
1027 	cs42l52->beep_rate = hz;
1028 	schedule_work(&cs42l52->beep_work);
1029 	return 0;
1030 }
1031 
1032 static ssize_t cs42l52_beep_set(struct device *dev,
1033 			       struct device_attribute *attr,
1034 			       const char *buf, size_t count)
1035 {
1036 	struct cs42l52_private *cs42l52 = dev_get_drvdata(dev);
1037 	long int time;
1038 	int ret;
1039 
1040 	ret = kstrtol(buf, 10, &time);
1041 	if (ret != 0)
1042 		return ret;
1043 
1044 	input_event(cs42l52->beep, EV_SND, SND_TONE, time);
1045 
1046 	return count;
1047 }
1048 
1049 static DEVICE_ATTR(beep, 0200, NULL, cs42l52_beep_set);
1050 
1051 static void cs42l52_init_beep(struct snd_soc_codec *codec)
1052 {
1053 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
1054 	int ret;
1055 
1056 	cs42l52->beep = devm_input_allocate_device(codec->dev);
1057 	if (!cs42l52->beep) {
1058 		dev_err(codec->dev, "Failed to allocate beep device\n");
1059 		return;
1060 	}
1061 
1062 	INIT_WORK(&cs42l52->beep_work, cs42l52_beep_work);
1063 	cs42l52->beep_rate = 0;
1064 
1065 	cs42l52->beep->name = "CS42L52 Beep Generator";
1066 	cs42l52->beep->phys = dev_name(codec->dev);
1067 	cs42l52->beep->id.bustype = BUS_I2C;
1068 
1069 	cs42l52->beep->evbit[0] = BIT_MASK(EV_SND);
1070 	cs42l52->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
1071 	cs42l52->beep->event = cs42l52_beep_event;
1072 	cs42l52->beep->dev.parent = codec->dev;
1073 	input_set_drvdata(cs42l52->beep, codec);
1074 
1075 	ret = input_register_device(cs42l52->beep);
1076 	if (ret != 0) {
1077 		cs42l52->beep = NULL;
1078 		dev_err(codec->dev, "Failed to register beep device\n");
1079 	}
1080 
1081 	ret = device_create_file(codec->dev, &dev_attr_beep);
1082 	if (ret != 0) {
1083 		dev_err(codec->dev, "Failed to create keyclick file: %d\n",
1084 			ret);
1085 	}
1086 }
1087 
1088 static void cs42l52_free_beep(struct snd_soc_codec *codec)
1089 {
1090 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
1091 
1092 	device_remove_file(codec->dev, &dev_attr_beep);
1093 	cancel_work_sync(&cs42l52->beep_work);
1094 	cs42l52->beep = NULL;
1095 
1096 	snd_soc_update_bits(codec, CS42L52_BEEP_TONE_CTL,
1097 			    CS42L52_BEEP_EN_MASK, 0);
1098 }
1099 #else
1100 static void cs42l52_init_beep(struct snd_soc_codec *codec)
1101 {
1102 }
1103 
1104 static void cs42l52_free_beep(struct snd_soc_codec *codec)
1105 {
1106 }
1107 #endif
1108 
1109 static int cs42l52_probe(struct snd_soc_codec *codec)
1110 {
1111 	struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
1112 
1113 	regcache_cache_only(cs42l52->regmap, true);
1114 
1115 	cs42l52_add_mic_controls(codec);
1116 
1117 	cs42l52_init_beep(codec);
1118 
1119 	cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1120 
1121 	cs42l52->sysclk = CS42L52_DEFAULT_CLK;
1122 	cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
1123 
1124 	return 0;
1125 }
1126 
1127 static int cs42l52_remove(struct snd_soc_codec *codec)
1128 {
1129 	cs42l52_free_beep(codec);
1130 	cs42l52_set_bias_level(codec, SND_SOC_BIAS_OFF);
1131 
1132 	return 0;
1133 }
1134 
1135 static struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
1136 	.probe = cs42l52_probe,
1137 	.remove = cs42l52_remove,
1138 	.suspend = cs42l52_suspend,
1139 	.resume = cs42l52_resume,
1140 	.set_bias_level = cs42l52_set_bias_level,
1141 
1142 	.dapm_widgets = cs42l52_dapm_widgets,
1143 	.num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets),
1144 	.dapm_routes = cs42l52_audio_map,
1145 	.num_dapm_routes = ARRAY_SIZE(cs42l52_audio_map),
1146 
1147 	.controls = cs42l52_snd_controls,
1148 	.num_controls = ARRAY_SIZE(cs42l52_snd_controls),
1149 };
1150 
1151 /* Current and threshold powerup sequence Pg37 */
1152 static const struct reg_default cs42l52_threshold_patch[] = {
1153 
1154 	{ 0x00, 0x99 },
1155 	{ 0x3E, 0xBA },
1156 	{ 0x47, 0x80 },
1157 	{ 0x32, 0xBB },
1158 	{ 0x32, 0x3B },
1159 	{ 0x00, 0x00 },
1160 
1161 };
1162 
1163 static struct regmap_config cs42l52_regmap = {
1164 	.reg_bits = 8,
1165 	.val_bits = 8,
1166 
1167 	.max_register = CS42L52_MAX_REGISTER,
1168 	.reg_defaults = cs42l52_reg_defaults,
1169 	.num_reg_defaults = ARRAY_SIZE(cs42l52_reg_defaults),
1170 	.readable_reg = cs42l52_readable_register,
1171 	.volatile_reg = cs42l52_volatile_register,
1172 	.cache_type = REGCACHE_RBTREE,
1173 };
1174 
1175 static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
1176 			     const struct i2c_device_id *id)
1177 {
1178 	struct cs42l52_private *cs42l52;
1179 	struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
1180 	int ret;
1181 	unsigned int devid = 0;
1182 	unsigned int reg;
1183 	u32 val32;
1184 
1185 	cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private),
1186 			       GFP_KERNEL);
1187 	if (cs42l52 == NULL)
1188 		return -ENOMEM;
1189 	cs42l52->dev = &i2c_client->dev;
1190 
1191 	cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap);
1192 	if (IS_ERR(cs42l52->regmap)) {
1193 		ret = PTR_ERR(cs42l52->regmap);
1194 		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1195 		return ret;
1196 	}
1197 	if (pdata) {
1198 		cs42l52->pdata = *pdata;
1199 	} else {
1200 		pdata = devm_kzalloc(&i2c_client->dev,
1201 				     sizeof(struct cs42l52_platform_data),
1202 				GFP_KERNEL);
1203 		if (!pdata) {
1204 			dev_err(&i2c_client->dev, "could not allocate pdata\n");
1205 			return -ENOMEM;
1206 		}
1207 		if (i2c_client->dev.of_node) {
1208 			if (of_property_read_bool(i2c_client->dev.of_node,
1209 				"cirrus,mica-differential-cfg"))
1210 				pdata->mica_diff_cfg = true;
1211 
1212 			if (of_property_read_bool(i2c_client->dev.of_node,
1213 				"cirrus,micb-differential-cfg"))
1214 				pdata->micb_diff_cfg = true;
1215 
1216 			if (of_property_read_u32(i2c_client->dev.of_node,
1217 				"cirrus,micbias-lvl", &val32) >= 0)
1218 				pdata->micbias_lvl = val32;
1219 
1220 			if (of_property_read_u32(i2c_client->dev.of_node,
1221 				"cirrus,chgfreq-divisor", &val32) >= 0)
1222 				pdata->chgfreq = val32;
1223 
1224 			pdata->reset_gpio =
1225 				of_get_named_gpio(i2c_client->dev.of_node,
1226 						"cirrus,reset-gpio", 0);
1227 		}
1228 		cs42l52->pdata = *pdata;
1229 	}
1230 
1231 	if (cs42l52->pdata.reset_gpio) {
1232 		ret = devm_gpio_request_one(&i2c_client->dev,
1233 					    cs42l52->pdata.reset_gpio,
1234 					    GPIOF_OUT_INIT_HIGH,
1235 					    "CS42L52 /RST");
1236 		if (ret < 0) {
1237 			dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
1238 				cs42l52->pdata.reset_gpio, ret);
1239 			return ret;
1240 		}
1241 		gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 0);
1242 		gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 1);
1243 	}
1244 
1245 	i2c_set_clientdata(i2c_client, cs42l52);
1246 
1247 	ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch,
1248 				    ARRAY_SIZE(cs42l52_threshold_patch));
1249 	if (ret != 0)
1250 		dev_warn(cs42l52->dev, "Failed to apply regmap patch: %d\n",
1251 			 ret);
1252 
1253 	ret = regmap_read(cs42l52->regmap, CS42L52_CHIP, &reg);
1254 	devid = reg & CS42L52_CHIP_ID_MASK;
1255 	if (devid != CS42L52_CHIP_ID) {
1256 		ret = -ENODEV;
1257 		dev_err(&i2c_client->dev,
1258 			"CS42L52 Device ID (%X). Expected %X\n",
1259 			devid, CS42L52_CHIP_ID);
1260 		return ret;
1261 	}
1262 
1263 	dev_info(&i2c_client->dev, "Cirrus Logic CS42L52, Revision: %02X\n",
1264 		 reg & CS42L52_CHIP_REV_MASK);
1265 
1266 	/* Set Platform Data */
1267 	if (cs42l52->pdata.mica_diff_cfg)
1268 		regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
1269 				   CS42L52_MIC_CTL_TYPE_MASK,
1270 				cs42l52->pdata.mica_diff_cfg <<
1271 				CS42L52_MIC_CTL_TYPE_SHIFT);
1272 
1273 	if (cs42l52->pdata.micb_diff_cfg)
1274 		regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
1275 				   CS42L52_MIC_CTL_TYPE_MASK,
1276 				cs42l52->pdata.micb_diff_cfg <<
1277 				CS42L52_MIC_CTL_TYPE_SHIFT);
1278 
1279 	if (cs42l52->pdata.chgfreq)
1280 		regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP,
1281 				   CS42L52_CHARGE_PUMP_MASK,
1282 				cs42l52->pdata.chgfreq <<
1283 				CS42L52_CHARGE_PUMP_SHIFT);
1284 
1285 	if (cs42l52->pdata.micbias_lvl)
1286 		regmap_update_bits(cs42l52->regmap, CS42L52_IFACE_CTL2,
1287 				   CS42L52_IFACE_CTL2_BIAS_LVL,
1288 				cs42l52->pdata.micbias_lvl);
1289 
1290 	ret =  snd_soc_register_codec(&i2c_client->dev,
1291 			&soc_codec_dev_cs42l52, &cs42l52_dai, 1);
1292 	if (ret < 0)
1293 		return ret;
1294 	return 0;
1295 }
1296 
1297 static int cs42l52_i2c_remove(struct i2c_client *client)
1298 {
1299 	snd_soc_unregister_codec(&client->dev);
1300 	return 0;
1301 }
1302 
1303 static const struct of_device_id cs42l52_of_match[] = {
1304 	{ .compatible = "cirrus,cs42l52", },
1305 	{},
1306 };
1307 MODULE_DEVICE_TABLE(of, cs42l52_of_match);
1308 
1309 
1310 static const struct i2c_device_id cs42l52_id[] = {
1311 	{ "cs42l52", 0 },
1312 	{ }
1313 };
1314 MODULE_DEVICE_TABLE(i2c, cs42l52_id);
1315 
1316 static struct i2c_driver cs42l52_i2c_driver = {
1317 	.driver = {
1318 		.name = "cs42l52",
1319 		.owner = THIS_MODULE,
1320 		.of_match_table = cs42l52_of_match,
1321 	},
1322 	.id_table = cs42l52_id,
1323 	.probe =    cs42l52_i2c_probe,
1324 	.remove =   cs42l52_i2c_remove,
1325 };
1326 
1327 module_i2c_driver(cs42l52_i2c_driver);
1328 
1329 MODULE_DESCRIPTION("ASoC CS42L52 driver");
1330 MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
1331 MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
1332 MODULE_LICENSE("GPL");
1333