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