blob: eec1ff853b98bdc1ca7c2390a9cd50ec44edbf2c [file] [log] [blame]
Brian Austin272b5ed2014-05-05 15:09:08 -05001/*
2 * cs42l56.c -- CS42L56 ALSA SoC audio driver
3 *
4 * Copyright 2014 CirrusLogic, Inc.
5 *
6 * Author: Brian Austin <brian.austin@cirrus.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/input.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
24#include <linux/workqueue.h>
25#include <linux/platform_device.h>
26#include <linux/regulator/consumer.h>
27#include <linux/of_device.h>
28#include <linux/of_gpio.h>
29#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/pcm_params.h>
32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34#include <sound/initval.h>
35#include <sound/tlv.h>
36#include <sound/cs42l56.h>
37#include "cs42l56.h"
38
39#define CS42L56_NUM_SUPPLIES 3
40static const char *const cs42l56_supply_names[CS42L56_NUM_SUPPLIES] = {
41 "VA",
42 "VCP",
43 "VLDO",
44};
45
46struct cs42l56_private {
47 struct regmap *regmap;
48 struct snd_soc_codec *codec;
49 struct device *dev;
50 struct cs42l56_platform_data pdata;
51 struct regulator_bulk_data supplies[CS42L56_NUM_SUPPLIES];
52 u32 mclk;
53 u8 mclk_prediv;
54 u8 mclk_div2;
55 u8 mclk_ratio;
56 u8 iface;
57 u8 iface_fmt;
58 u8 iface_inv;
Javier Martinez Canillasde06f222016-04-25 19:30:39 -040059#if IS_ENABLED(CONFIG_INPUT)
Brian Austin272b5ed2014-05-05 15:09:08 -050060 struct input_dev *beep;
61 struct work_struct beep_work;
62 int beep_rate;
63#endif
64};
65
66static const struct reg_default cs42l56_reg_defaults[] = {
67 { 1, 0x56 }, /* r01 - ID 1 */
68 { 2, 0x04 }, /* r02 - ID 2 */
69 { 3, 0x7f }, /* r03 - Power Ctl 1 */
70 { 4, 0xff }, /* r04 - Power Ctl 2 */
71 { 5, 0x00 }, /* ro5 - Clocking Ctl 1 */
72 { 6, 0x0b }, /* r06 - Clocking Ctl 2 */
73 { 7, 0x00 }, /* r07 - Serial Format */
74 { 8, 0x05 }, /* r08 - Class H Ctl */
75 { 9, 0x0c }, /* r09 - Misc Ctl */
76 { 10, 0x80 }, /* r0a - INT Status */
77 { 11, 0x00 }, /* r0b - Playback Ctl */
78 { 12, 0x0c }, /* r0c - DSP Mute Ctl */
79 { 13, 0x00 }, /* r0d - ADCA Mixer Volume */
80 { 14, 0x00 }, /* r0e - ADCB Mixer Volume */
81 { 15, 0x00 }, /* r0f - PCMA Mixer Volume */
82 { 16, 0x00 }, /* r10 - PCMB Mixer Volume */
83 { 17, 0x00 }, /* r11 - Analog Input Advisory Volume */
84 { 18, 0x00 }, /* r12 - Digital Input Advisory Volume */
85 { 19, 0x00 }, /* r13 - Master A Volume */
86 { 20, 0x00 }, /* r14 - Master B Volume */
87 { 21, 0x00 }, /* r15 - Beep Freq / On Time */
88 { 22, 0x00 }, /* r16 - Beep Volume / Off Time */
89 { 23, 0x00 }, /* r17 - Beep Tone Ctl */
90 { 24, 0x88 }, /* r18 - Tone Ctl */
91 { 25, 0x00 }, /* r19 - Channel Mixer & Swap */
92 { 26, 0x00 }, /* r1a - AIN Ref Config / ADC Mux */
93 { 27, 0xa0 }, /* r1b - High-Pass Filter Ctl */
94 { 28, 0x00 }, /* r1c - Misc ADC Ctl */
95 { 29, 0x00 }, /* r1d - Gain & Bias Ctl */
96 { 30, 0x00 }, /* r1e - PGAA Mux & Volume */
97 { 31, 0x00 }, /* r1f - PGAB Mux & Volume */
98 { 32, 0x00 }, /* r20 - ADCA Attenuator */
99 { 33, 0x00 }, /* r21 - ADCB Attenuator */
100 { 34, 0x00 }, /* r22 - ALC Enable & Attack Rate */
101 { 35, 0xbf }, /* r23 - ALC Release Rate */
102 { 36, 0x00 }, /* r24 - ALC Threshold */
103 { 37, 0x00 }, /* r25 - Noise Gate Ctl */
104 { 38, 0x00 }, /* r26 - ALC, Limiter, SFT, ZeroCross */
105 { 39, 0x00 }, /* r27 - Analog Mute, LO & HP Mux */
106 { 40, 0x00 }, /* r28 - HP A Volume */
107 { 41, 0x00 }, /* r29 - HP B Volume */
108 { 42, 0x00 }, /* r2a - LINEOUT A Volume */
109 { 43, 0x00 }, /* r2b - LINEOUT B Volume */
110 { 44, 0x00 }, /* r2c - Limit Threshold Ctl */
111 { 45, 0x7f }, /* r2d - Limiter Ctl & Release Rate */
112 { 46, 0x00 }, /* r2e - Limiter Attack Rate */
113};
114
115static bool cs42l56_readable_register(struct device *dev, unsigned int reg)
116{
117 switch (reg) {
Axel Lin7f325bf2015-08-12 11:09:39 +0800118 case CS42L56_CHIP_ID_1 ... CS42L56_LIM_ATTACK_RATE:
Brian Austin272b5ed2014-05-05 15:09:08 -0500119 return true;
120 default:
121 return false;
122 }
123}
124
125static bool cs42l56_volatile_register(struct device *dev, unsigned int reg)
126{
127 switch (reg) {
128 case CS42L56_INT_STATUS:
Brian Austinc2b49ae2014-08-28 10:02:42 -0500129 return true;
Brian Austin272b5ed2014-05-05 15:09:08 -0500130 default:
Brian Austinc2b49ae2014-08-28 10:02:42 -0500131 return false;
Brian Austin272b5ed2014-05-05 15:09:08 -0500132 }
133}
134
135static DECLARE_TLV_DB_SCALE(beep_tlv, -5000, 200, 0);
136static DECLARE_TLV_DB_SCALE(hl_tlv, -6000, 50, 0);
137static DECLARE_TLV_DB_SCALE(adv_tlv, -10200, 50, 0);
138static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, 0);
139static DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
140static DECLARE_TLV_DB_SCALE(preamp_tlv, 0, 1000, 0);
141static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
142
Lars-Peter Clausen37879ba2015-08-02 17:19:35 +0200143static const DECLARE_TLV_DB_RANGE(ngnb_tlv,
Brian Austin272b5ed2014-05-05 15:09:08 -0500144 0, 1, TLV_DB_SCALE_ITEM(-8200, 600, 0),
Lars-Peter Clausen37879ba2015-08-02 17:19:35 +0200145 2, 5, TLV_DB_SCALE_ITEM(-7600, 300, 0)
146);
147static const DECLARE_TLV_DB_RANGE(ngb_tlv,
Brian Austin272b5ed2014-05-05 15:09:08 -0500148 0, 2, TLV_DB_SCALE_ITEM(-6400, 600, 0),
Lars-Peter Clausen37879ba2015-08-02 17:19:35 +0200149 3, 7, TLV_DB_SCALE_ITEM(-4600, 300, 0)
150);
151static const DECLARE_TLV_DB_RANGE(alc_tlv,
Brian Austin272b5ed2014-05-05 15:09:08 -0500152 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
Lars-Peter Clausen37879ba2015-08-02 17:19:35 +0200153 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0)
154);
Brian Austin272b5ed2014-05-05 15:09:08 -0500155
156static const char * const beep_config_text[] = {
157 "Off", "Single", "Multiple", "Continuous"
158};
159
160static const struct soc_enum beep_config_enum =
161 SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 6,
162 ARRAY_SIZE(beep_config_text), beep_config_text);
163
164static const char * const beep_pitch_text[] = {
165 "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5",
166 "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"
167};
168
169static const struct soc_enum beep_pitch_enum =
170 SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_ONTIME, 4,
171 ARRAY_SIZE(beep_pitch_text), beep_pitch_text);
172
173static const char * const beep_ontime_text[] = {
174 "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s",
175 "1.80 s", "2.20 s", "2.50 s", "2.80 s", "3.20 s",
176 "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s"
177};
178
179static const struct soc_enum beep_ontime_enum =
180 SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_ONTIME, 0,
181 ARRAY_SIZE(beep_ontime_text), beep_ontime_text);
182
183static const char * const beep_offtime_text[] = {
184 "1.23 s", "2.58 s", "3.90 s", "5.20 s",
185 "6.60 s", "8.05 s", "9.35 s", "10.80 s"
186};
187
188static const struct soc_enum beep_offtime_enum =
189 SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_OFFTIME, 5,
190 ARRAY_SIZE(beep_offtime_text), beep_offtime_text);
191
192static const char * const beep_treble_text[] = {
193 "5kHz", "7kHz", "10kHz", "15kHz"
194};
195
196static const struct soc_enum beep_treble_enum =
197 SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 3,
198 ARRAY_SIZE(beep_treble_text), beep_treble_text);
199
200static const char * const beep_bass_text[] = {
201 "50Hz", "100Hz", "200Hz", "250Hz"
202};
203
204static const struct soc_enum beep_bass_enum =
205 SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1,
206 ARRAY_SIZE(beep_bass_text), beep_bass_text);
207
208static const char * const adc_swap_text[] = {
209 "None", "A+B/2", "A-B/2", "Swap"
210};
211
212static const struct soc_enum adc_swap_enum =
213 SOC_ENUM_SINGLE(CS42L56_MISC_ADC_CTL, 3,
214 ARRAY_SIZE(adc_swap_text), adc_swap_text);
215
216static const char * const pgaa_mux_text[] = {
217 "AIN1A", "AIN2A", "AIN3A"};
218
219static const struct soc_enum pgaa_mux_enum =
220 SOC_ENUM_SINGLE(CS42L56_PGAA_MUX_VOLUME, 0,
221 ARRAY_SIZE(pgaa_mux_text),
222 pgaa_mux_text);
223
224static const struct snd_kcontrol_new pgaa_mux =
225 SOC_DAPM_ENUM("Route", pgaa_mux_enum);
226
227static const char * const pgab_mux_text[] = {
228 "AIN1B", "AIN2B", "AIN3B"};
229
230static const struct soc_enum pgab_mux_enum =
231 SOC_ENUM_SINGLE(CS42L56_PGAB_MUX_VOLUME, 0,
232 ARRAY_SIZE(pgab_mux_text),
233 pgab_mux_text);
234
235static const struct snd_kcontrol_new pgab_mux =
236 SOC_DAPM_ENUM("Route", pgab_mux_enum);
237
238static const char * const adca_mux_text[] = {
239 "PGAA", "AIN1A", "AIN2A", "AIN3A"};
240
241static const struct soc_enum adca_mux_enum =
242 SOC_ENUM_SINGLE(CS42L56_AIN_REFCFG_ADC_MUX, 0,
243 ARRAY_SIZE(adca_mux_text),
244 adca_mux_text);
245
246static const struct snd_kcontrol_new adca_mux =
247 SOC_DAPM_ENUM("Route", adca_mux_enum);
248
249static const char * const adcb_mux_text[] = {
250 "PGAB", "AIN1B", "AIN2B", "AIN3B"};
251
252static const struct soc_enum adcb_mux_enum =
253 SOC_ENUM_SINGLE(CS42L56_AIN_REFCFG_ADC_MUX, 2,
254 ARRAY_SIZE(adcb_mux_text),
255 adcb_mux_text);
256
257static const struct snd_kcontrol_new adcb_mux =
258 SOC_DAPM_ENUM("Route", adcb_mux_enum);
259
260static const char * const left_swap_text[] = {
261 "Left", "LR 2", "Right"};
262
263static const char * const right_swap_text[] = {
264 "Right", "LR 2", "Left"};
265
266static const unsigned int swap_values[] = { 0, 1, 3 };
267
268static const struct soc_enum adca_swap_enum =
269 SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 0, 3,
270 ARRAY_SIZE(left_swap_text),
271 left_swap_text,
272 swap_values);
Brian Austinc4324bf2014-07-08 09:56:35 -0500273static const struct snd_kcontrol_new adca_swap_mux =
274 SOC_DAPM_ENUM("Route", adca_swap_enum);
Brian Austin272b5ed2014-05-05 15:09:08 -0500275
276static const struct soc_enum pcma_swap_enum =
277 SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3,
278 ARRAY_SIZE(left_swap_text),
279 left_swap_text,
280 swap_values);
Brian Austinc4324bf2014-07-08 09:56:35 -0500281static const struct snd_kcontrol_new pcma_swap_mux =
282 SOC_DAPM_ENUM("Route", pcma_swap_enum);
Brian Austin272b5ed2014-05-05 15:09:08 -0500283
284static const struct soc_enum adcb_swap_enum =
285 SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3,
286 ARRAY_SIZE(right_swap_text),
287 right_swap_text,
288 swap_values);
Brian Austinc4324bf2014-07-08 09:56:35 -0500289static const struct snd_kcontrol_new adcb_swap_mux =
290 SOC_DAPM_ENUM("Route", adcb_swap_enum);
Brian Austin272b5ed2014-05-05 15:09:08 -0500291
292static const struct soc_enum pcmb_swap_enum =
293 SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3,
294 ARRAY_SIZE(right_swap_text),
295 right_swap_text,
296 swap_values);
Brian Austinc4324bf2014-07-08 09:56:35 -0500297static const struct snd_kcontrol_new pcmb_swap_mux =
298 SOC_DAPM_ENUM("Route", pcmb_swap_enum);
Brian Austin272b5ed2014-05-05 15:09:08 -0500299
300static const struct snd_kcontrol_new hpa_switch =
301 SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1);
302
303static const struct snd_kcontrol_new hpb_switch =
304 SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 4, 1, 1);
305
306static const struct snd_kcontrol_new loa_switch =
307 SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 2, 1, 1);
308
309static const struct snd_kcontrol_new lob_switch =
310 SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 0, 1, 1);
311
312static const char * const hploa_input_text[] = {
313 "DACA", "PGAA"};
314
315static const struct soc_enum lineouta_input_enum =
316 SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 2,
317 ARRAY_SIZE(hploa_input_text),
318 hploa_input_text);
319
320static const struct snd_kcontrol_new lineouta_input =
321 SOC_DAPM_ENUM("Route", lineouta_input_enum);
322
323static const struct soc_enum hpa_input_enum =
324 SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 0,
325 ARRAY_SIZE(hploa_input_text),
326 hploa_input_text);
327
328static const struct snd_kcontrol_new hpa_input =
329 SOC_DAPM_ENUM("Route", hpa_input_enum);
330
331static const char * const hplob_input_text[] = {
332 "DACB", "PGAB"};
333
334static const struct soc_enum lineoutb_input_enum =
335 SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 3,
336 ARRAY_SIZE(hplob_input_text),
337 hplob_input_text);
338
339static const struct snd_kcontrol_new lineoutb_input =
340 SOC_DAPM_ENUM("Route", lineoutb_input_enum);
341
342static const struct soc_enum hpb_input_enum =
343 SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 1,
344 ARRAY_SIZE(hplob_input_text),
345 hplob_input_text);
346
347static const struct snd_kcontrol_new hpb_input =
348 SOC_DAPM_ENUM("Route", hpb_input_enum);
349
350static const char * const dig_mux_text[] = {
351 "ADC", "DSP"};
352
353static const struct soc_enum dig_mux_enum =
354 SOC_ENUM_SINGLE(CS42L56_MISC_CTL, 7,
355 ARRAY_SIZE(dig_mux_text),
356 dig_mux_text);
357
358static const struct snd_kcontrol_new dig_mux =
359 SOC_DAPM_ENUM("Route", dig_mux_enum);
360
361static const char * const hpf_freq_text[] = {
362 "1.8Hz", "119Hz", "236Hz", "464Hz"
363};
364
365static const struct soc_enum hpfa_freq_enum =
366 SOC_ENUM_SINGLE(CS42L56_HPF_CTL, 0,
367 ARRAY_SIZE(hpf_freq_text), hpf_freq_text);
368
369static const struct soc_enum hpfb_freq_enum =
370 SOC_ENUM_SINGLE(CS42L56_HPF_CTL, 2,
371 ARRAY_SIZE(hpf_freq_text), hpf_freq_text);
372
373static const char * const ng_delay_text[] = {
374 "50ms", "100ms", "150ms", "200ms"
375};
376
377static const struct soc_enum ng_delay_enum =
378 SOC_ENUM_SINGLE(CS42L56_NOISE_GATE_CTL, 0,
379 ARRAY_SIZE(ng_delay_text), ng_delay_text);
380
381static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
382
383 SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME,
Brian Austina0465582014-07-17 13:16:55 -0500384 CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xE4, adv_tlv),
Brian Austin272b5ed2014-05-05 15:09:08 -0500385 SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1),
386
387 SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME,
Brian Austina0465582014-07-17 13:16:55 -0500388 CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv),
Brian Austin272b5ed2014-05-05 15:09:08 -0500389 SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1),
390
391 SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME,
Brian Austina0465582014-07-17 13:16:55 -0500392 CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv),
Brian Austin272b5ed2014-05-05 15:09:08 -0500393 SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1),
394
395 SOC_SINGLE_TLV("Analog Advisory Volume",
396 CS42L56_ANAINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv),
397 SOC_SINGLE_TLV("Digital Advisory Volume",
398 CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv),
399
400 SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME,
Brian Austina0465582014-07-17 13:16:55 -0500401 CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0x24, pga_tlv),
Brian Austin272b5ed2014-05-05 15:09:08 -0500402 SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR,
403 CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv),
404 SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1),
405 SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1),
406
407 SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME,
Brian Austina0465582014-07-17 13:16:55 -0500408 CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv),
Brian Austin272b5ed2014-05-05 15:09:08 -0500409 SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME,
Brian Austina0465582014-07-17 13:16:55 -0500410 CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv),
Brian Austin272b5ed2014-05-05 15:09:08 -0500411
412 SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL,
413 0, 0x00, 1, tone_tlv),
414 SOC_SINGLE_TLV("Treble Shelving Volume", CS42L56_TONE_CTL,
415 4, 0x00, 1, tone_tlv),
416
417 SOC_DOUBLE_TLV("PGA Preamp Volume", CS42L56_GAIN_BIAS_CTL,
418 4, 6, 0x02, 1, preamp_tlv),
419
420 SOC_SINGLE("DSP Switch", CS42L56_PLAYBACK_CTL, 7, 1, 1),
421 SOC_SINGLE("Gang Playback Switch", CS42L56_PLAYBACK_CTL, 4, 1, 1),
422 SOC_SINGLE("Gang ADC Switch", CS42L56_MISC_ADC_CTL, 7, 1, 1),
423 SOC_SINGLE("Gang PGA Switch", CS42L56_MISC_ADC_CTL, 6, 1, 1),
424
425 SOC_SINGLE("PCMA Invert", CS42L56_PLAYBACK_CTL, 2, 1, 1),
426 SOC_SINGLE("PCMB Invert", CS42L56_PLAYBACK_CTL, 3, 1, 1),
427 SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1),
428 SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1),
429
Brian Austin272b5ed2014-05-05 15:09:08 -0500430 SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1),
431 SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1),
432 SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum),
433 SOC_ENUM("HPFB Corner Freq", hpfb_freq_enum),
434
435 SOC_SINGLE("Analog Soft Ramp", CS42L56_MISC_CTL, 4, 1, 1),
436 SOC_DOUBLE("Analog Soft Ramp Disable", CS42L56_ALC_LIM_SFT_ZC,
437 7, 5, 1, 1),
438 SOC_SINGLE("Analog Zero Cross", CS42L56_MISC_CTL, 3, 1, 1),
439 SOC_DOUBLE("Analog Zero Cross Disable", CS42L56_ALC_LIM_SFT_ZC,
440 6, 4, 1, 1),
441 SOC_SINGLE("Digital Soft Ramp", CS42L56_MISC_CTL, 2, 1, 1),
442 SOC_SINGLE("Digital Soft Ramp Disable", CS42L56_ALC_LIM_SFT_ZC,
443 3, 1, 1),
444
445 SOC_SINGLE("HL Deemphasis", CS42L56_PLAYBACK_CTL, 6, 1, 1),
446
447 SOC_SINGLE("ALC Switch", CS42L56_ALC_EN_ATTACK_RATE, 6, 1, 1),
448 SOC_SINGLE("ALC Limit All Switch", CS42L56_ALC_RELEASE_RATE, 7, 1, 1),
449 SOC_SINGLE_RANGE("ALC Attack", CS42L56_ALC_EN_ATTACK_RATE,
450 0, 0, 0x3f, 0),
451 SOC_SINGLE_RANGE("ALC Release", CS42L56_ALC_RELEASE_RATE,
452 0, 0x3f, 0, 0),
453 SOC_SINGLE_TLV("ALC MAX", CS42L56_ALC_THRESHOLD,
454 5, 0x07, 1, alc_tlv),
455 SOC_SINGLE_TLV("ALC MIN", CS42L56_ALC_THRESHOLD,
456 2, 0x07, 1, alc_tlv),
457
458 SOC_SINGLE("Limiter Switch", CS42L56_LIM_CTL_RELEASE_RATE, 7, 1, 1),
459 SOC_SINGLE("Limit All Switch", CS42L56_LIM_CTL_RELEASE_RATE, 6, 1, 1),
460 SOC_SINGLE_RANGE("Limiter Attack", CS42L56_LIM_ATTACK_RATE,
461 0, 0, 0x3f, 0),
462 SOC_SINGLE_RANGE("Limiter Release", CS42L56_LIM_CTL_RELEASE_RATE,
463 0, 0x3f, 0, 0),
464 SOC_SINGLE_TLV("Limiter MAX", CS42L56_LIM_THRESHOLD_CTL,
465 5, 0x07, 1, alc_tlv),
466 SOC_SINGLE_TLV("Limiter Cushion", CS42L56_ALC_THRESHOLD,
467 2, 0x07, 1, alc_tlv),
468
469 SOC_SINGLE("NG Switch", CS42L56_NOISE_GATE_CTL, 6, 1, 1),
470 SOC_SINGLE("NG All Switch", CS42L56_NOISE_GATE_CTL, 7, 1, 1),
471 SOC_SINGLE("NG Boost Switch", CS42L56_NOISE_GATE_CTL, 5, 1, 1),
472 SOC_SINGLE_TLV("NG Unboost Threshold", CS42L56_NOISE_GATE_CTL,
473 2, 0x07, 1, ngnb_tlv),
474 SOC_SINGLE_TLV("NG Boost Threshold", CS42L56_NOISE_GATE_CTL,
475 2, 0x07, 1, ngb_tlv),
476 SOC_ENUM("NG Delay", ng_delay_enum),
477
478 SOC_ENUM("Beep Config", beep_config_enum),
479 SOC_ENUM("Beep Pitch", beep_pitch_enum),
480 SOC_ENUM("Beep on Time", beep_ontime_enum),
481 SOC_ENUM("Beep off Time", beep_offtime_enum),
482 SOC_SINGLE_SX_TLV("Beep Volume", CS42L56_BEEP_FREQ_OFFTIME,
483 0, 0x07, 0x23, beep_tlv),
484 SOC_SINGLE("Beep Tone Ctl Switch", CS42L56_BEEP_TONE_CFG, 0, 1, 1),
485 SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
486 SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
487
488};
489
490static const struct snd_soc_dapm_widget cs42l56_dapm_widgets[] = {
491
492 SND_SOC_DAPM_SIGGEN("Beep"),
493 SND_SOC_DAPM_SUPPLY("VBUF", CS42L56_PWRCTL_1, 5, 1, NULL, 0),
494 SND_SOC_DAPM_MICBIAS("MIC1 Bias", CS42L56_PWRCTL_1, 4, 1),
495 SND_SOC_DAPM_SUPPLY("Charge Pump", CS42L56_PWRCTL_1, 3, 1, NULL, 0),
496
497 SND_SOC_DAPM_INPUT("AIN1A"),
498 SND_SOC_DAPM_INPUT("AIN2A"),
499 SND_SOC_DAPM_INPUT("AIN1B"),
500 SND_SOC_DAPM_INPUT("AIN2B"),
501 SND_SOC_DAPM_INPUT("AIN3A"),
502 SND_SOC_DAPM_INPUT("AIN3B"),
503
504 SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0,
505 SND_SOC_NOPM, 0, 0),
506
507 SND_SOC_DAPM_AIF_IN("SDIN", NULL, 0,
508 SND_SOC_NOPM, 0, 0),
509
510 SND_SOC_DAPM_MUX("Digital Output Mux", SND_SOC_NOPM,
511 0, 0, &dig_mux),
512
513 SND_SOC_DAPM_PGA("PGAA", SND_SOC_NOPM, 0, 0, NULL, 0),
514 SND_SOC_DAPM_PGA("PGAB", SND_SOC_NOPM, 0, 0, NULL, 0),
515 SND_SOC_DAPM_MUX("PGAA Input Mux",
516 SND_SOC_NOPM, 0, 0, &pgaa_mux),
517 SND_SOC_DAPM_MUX("PGAB Input Mux",
518 SND_SOC_NOPM, 0, 0, &pgab_mux),
519
520 SND_SOC_DAPM_MUX("ADCA Mux", SND_SOC_NOPM,
521 0, 0, &adca_mux),
522 SND_SOC_DAPM_MUX("ADCB Mux", SND_SOC_NOPM,
523 0, 0, &adcb_mux),
524
525 SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1),
526 SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1),
527
Brian Austinc4324bf2014-07-08 09:56:35 -0500528 SND_SOC_DAPM_MUX("ADCA Swap Mux", SND_SOC_NOPM, 0, 0,
529 &adca_swap_mux),
530 SND_SOC_DAPM_MUX("ADCB Swap Mux", SND_SOC_NOPM, 0, 0,
531 &adcb_swap_mux),
532
533 SND_SOC_DAPM_MUX("PCMA Swap Mux", SND_SOC_NOPM, 0, 0,
534 &pcma_swap_mux),
535 SND_SOC_DAPM_MUX("PCMB Swap Mux", SND_SOC_NOPM, 0, 0,
536 &pcmb_swap_mux),
537
Brian Austin272b5ed2014-05-05 15:09:08 -0500538 SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0),
539 SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0),
540
541 SND_SOC_DAPM_OUTPUT("HPA"),
542 SND_SOC_DAPM_OUTPUT("LOA"),
543 SND_SOC_DAPM_OUTPUT("HPB"),
544 SND_SOC_DAPM_OUTPUT("LOB"),
545
546 SND_SOC_DAPM_SWITCH("Headphone Right",
547 CS42L56_PWRCTL_2, 4, 1, &hpb_switch),
548 SND_SOC_DAPM_SWITCH("Headphone Left",
549 CS42L56_PWRCTL_2, 6, 1, &hpa_switch),
550
551 SND_SOC_DAPM_SWITCH("Lineout Right",
552 CS42L56_PWRCTL_2, 0, 1, &lob_switch),
553 SND_SOC_DAPM_SWITCH("Lineout Left",
554 CS42L56_PWRCTL_2, 2, 1, &loa_switch),
555
556 SND_SOC_DAPM_MUX("LINEOUTA Input Mux", SND_SOC_NOPM,
557 0, 0, &lineouta_input),
558 SND_SOC_DAPM_MUX("LINEOUTB Input Mux", SND_SOC_NOPM,
559 0, 0, &lineoutb_input),
560 SND_SOC_DAPM_MUX("HPA Input Mux", SND_SOC_NOPM,
561 0, 0, &hpa_input),
562 SND_SOC_DAPM_MUX("HPB Input Mux", SND_SOC_NOPM,
563 0, 0, &hpb_input),
564
565};
566
567static const struct snd_soc_dapm_route cs42l56_audio_map[] = {
568
569 {"HiFi Capture", "DSP", "Digital Output Mux"},
570 {"HiFi Capture", "ADC", "Digital Output Mux"},
571
572 {"Digital Output Mux", NULL, "ADCA"},
573 {"Digital Output Mux", NULL, "ADCB"},
574
Brian Austinc4324bf2014-07-08 09:56:35 -0500575 {"ADCB", NULL, "ADCB Swap Mux"},
576 {"ADCA", NULL, "ADCA Swap Mux"},
577
578 {"ADCA Swap Mux", NULL, "ADCA"},
579 {"ADCB Swap Mux", NULL, "ADCB"},
580
581 {"DACA", "Left", "ADCA Swap Mux"},
582 {"DACA", "LR 2", "ADCA Swap Mux"},
583 {"DACA", "Right", "ADCA Swap Mux"},
584
585 {"DACB", "Left", "ADCB Swap Mux"},
586 {"DACB", "LR 2", "ADCB Swap Mux"},
587 {"DACB", "Right", "ADCB Swap Mux"},
Brian Austin272b5ed2014-05-05 15:09:08 -0500588
589 {"ADCA Mux", NULL, "AIN3A"},
590 {"ADCA Mux", NULL, "AIN2A"},
591 {"ADCA Mux", NULL, "AIN1A"},
592 {"ADCA Mux", NULL, "PGAA"},
593 {"ADCB Mux", NULL, "AIN3B"},
594 {"ADCB Mux", NULL, "AIN2B"},
595 {"ADCB Mux", NULL, "AIN1B"},
596 {"ADCB Mux", NULL, "PGAB"},
597
598 {"PGAA", "AIN1A", "PGAA Input Mux"},
599 {"PGAA", "AIN2A", "PGAA Input Mux"},
600 {"PGAA", "AIN3A", "PGAA Input Mux"},
601 {"PGAB", "AIN1B", "PGAB Input Mux"},
602 {"PGAB", "AIN2B", "PGAB Input Mux"},
603 {"PGAB", "AIN3B", "PGAB Input Mux"},
604
605 {"PGAA Input Mux", NULL, "AIN1A"},
606 {"PGAA Input Mux", NULL, "AIN2A"},
607 {"PGAA Input Mux", NULL, "AIN3A"},
608 {"PGAB Input Mux", NULL, "AIN1B"},
609 {"PGAB Input Mux", NULL, "AIN2B"},
610 {"PGAB Input Mux", NULL, "AIN3B"},
611
Brian Austinc4324bf2014-07-08 09:56:35 -0500612 {"LOB", "Switch", "LINEOUTB Input Mux"},
613 {"LOA", "Switch", "LINEOUTA Input Mux"},
Brian Austin272b5ed2014-05-05 15:09:08 -0500614
615 {"LINEOUTA Input Mux", "PGAA", "PGAA"},
616 {"LINEOUTB Input Mux", "PGAB", "PGAB"},
617 {"LINEOUTA Input Mux", "DACA", "DACA"},
618 {"LINEOUTB Input Mux", "DACB", "DACB"},
619
Brian Austinc4324bf2014-07-08 09:56:35 -0500620 {"HPA", "Switch", "HPB Input Mux"},
621 {"HPB", "Switch", "HPA Input Mux"},
Brian Austin272b5ed2014-05-05 15:09:08 -0500622
623 {"HPA Input Mux", "PGAA", "PGAA"},
624 {"HPB Input Mux", "PGAB", "PGAB"},
625 {"HPA Input Mux", "DACA", "DACA"},
626 {"HPB Input Mux", "DACB", "DACB"},
627
Brian Austinc4324bf2014-07-08 09:56:35 -0500628 {"DACA", NULL, "PCMA Swap Mux"},
629 {"DACB", NULL, "PCMB Swap Mux"},
630
631 {"PCMB Swap Mux", "Left", "HiFi Playback"},
632 {"PCMB Swap Mux", "LR 2", "HiFi Playback"},
633 {"PCMB Swap Mux", "Right", "HiFi Playback"},
634
635 {"PCMA Swap Mux", "Left", "HiFi Playback"},
636 {"PCMA Swap Mux", "LR 2", "HiFi Playback"},
637 {"PCMA Swap Mux", "Right", "HiFi Playback"},
Brian Austin272b5ed2014-05-05 15:09:08 -0500638
639};
640
641struct cs42l56_clk_para {
642 u32 mclk;
643 u32 srate;
644 u8 ratio;
645};
646
647static const struct cs42l56_clk_para clk_ratio_table[] = {
648 /* 8k */
649 { 6000000, 8000, CS42L56_MCLK_LRCLK_768 },
650 { 6144000, 8000, CS42L56_MCLK_LRCLK_750 },
651 { 12000000, 8000, CS42L56_MCLK_LRCLK_768 },
652 { 12288000, 8000, CS42L56_MCLK_LRCLK_750 },
653 { 24000000, 8000, CS42L56_MCLK_LRCLK_768 },
654 { 24576000, 8000, CS42L56_MCLK_LRCLK_750 },
655 /* 11.025k */
656 { 5644800, 11025, CS42L56_MCLK_LRCLK_512},
657 { 11289600, 11025, CS42L56_MCLK_LRCLK_512},
658 { 22579200, 11025, CS42L56_MCLK_LRCLK_512 },
659 /* 11.0294k */
660 { 6000000, 110294, CS42L56_MCLK_LRCLK_544 },
661 { 12000000, 110294, CS42L56_MCLK_LRCLK_544 },
662 { 24000000, 110294, CS42L56_MCLK_LRCLK_544 },
663 /* 12k */
664 { 6000000, 12000, CS42L56_MCLK_LRCLK_500 },
665 { 6144000, 12000, CS42L56_MCLK_LRCLK_512 },
666 { 12000000, 12000, CS42L56_MCLK_LRCLK_500 },
667 { 12288000, 12000, CS42L56_MCLK_LRCLK_512 },
668 { 24000000, 12000, CS42L56_MCLK_LRCLK_500 },
669 { 24576000, 12000, CS42L56_MCLK_LRCLK_512 },
670 /* 16k */
671 { 6000000, 16000, CS42L56_MCLK_LRCLK_375 },
672 { 6144000, 16000, CS42L56_MCLK_LRCLK_384 },
673 { 12000000, 16000, CS42L56_MCLK_LRCLK_375 },
674 { 12288000, 16000, CS42L56_MCLK_LRCLK_384 },
675 { 24000000, 16000, CS42L56_MCLK_LRCLK_375 },
676 { 24576000, 16000, CS42L56_MCLK_LRCLK_384 },
677 /* 22.050k */
678 { 5644800, 22050, CS42L56_MCLK_LRCLK_256 },
679 { 11289600, 22050, CS42L56_MCLK_LRCLK_256 },
680 { 22579200, 22050, CS42L56_MCLK_LRCLK_256 },
681 /* 22.0588k */
682 { 6000000, 220588, CS42L56_MCLK_LRCLK_272 },
683 { 12000000, 220588, CS42L56_MCLK_LRCLK_272 },
684 { 24000000, 220588, CS42L56_MCLK_LRCLK_272 },
685 /* 24k */
686 { 6000000, 24000, CS42L56_MCLK_LRCLK_250 },
687 { 6144000, 24000, CS42L56_MCLK_LRCLK_256 },
688 { 12000000, 24000, CS42L56_MCLK_LRCLK_250 },
689 { 12288000, 24000, CS42L56_MCLK_LRCLK_256 },
690 { 24000000, 24000, CS42L56_MCLK_LRCLK_250 },
691 { 24576000, 24000, CS42L56_MCLK_LRCLK_256 },
692 /* 32k */
693 { 6000000, 32000, CS42L56_MCLK_LRCLK_187P5 },
694 { 6144000, 32000, CS42L56_MCLK_LRCLK_192 },
695 { 12000000, 32000, CS42L56_MCLK_LRCLK_187P5 },
696 { 12288000, 32000, CS42L56_MCLK_LRCLK_192 },
697 { 24000000, 32000, CS42L56_MCLK_LRCLK_187P5 },
698 { 24576000, 32000, CS42L56_MCLK_LRCLK_192 },
699 /* 44.118k */
700 { 6000000, 44118, CS42L56_MCLK_LRCLK_136 },
701 { 12000000, 44118, CS42L56_MCLK_LRCLK_136 },
702 { 24000000, 44118, CS42L56_MCLK_LRCLK_136 },
703 /* 44.1k */
704 { 5644800, 44100, CS42L56_MCLK_LRCLK_128 },
705 { 11289600, 44100, CS42L56_MCLK_LRCLK_128 },
706 { 22579200, 44100, CS42L56_MCLK_LRCLK_128 },
707 /* 48k */
708 { 6000000, 48000, CS42L56_MCLK_LRCLK_125 },
709 { 6144000, 48000, CS42L56_MCLK_LRCLK_128 },
710 { 12000000, 48000, CS42L56_MCLK_LRCLK_125 },
711 { 12288000, 48000, CS42L56_MCLK_LRCLK_128 },
712 { 24000000, 48000, CS42L56_MCLK_LRCLK_125 },
713 { 24576000, 48000, CS42L56_MCLK_LRCLK_128 },
714};
715
716static int cs42l56_get_mclk_ratio(int mclk, int rate)
717{
718 int i;
719
720 for (i = 0; i < ARRAY_SIZE(clk_ratio_table); i++) {
721 if (clk_ratio_table[i].mclk == mclk &&
722 clk_ratio_table[i].srate == rate)
723 return clk_ratio_table[i].ratio;
724 }
725 return -EINVAL;
726}
727
728static int cs42l56_set_sysclk(struct snd_soc_dai *codec_dai,
729 int clk_id, unsigned int freq, int dir)
730{
731 struct snd_soc_codec *codec = codec_dai->codec;
732 struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
733
734 switch (freq) {
735 case CS42L56_MCLK_5P6448MHZ:
736 case CS42L56_MCLK_6MHZ:
737 case CS42L56_MCLK_6P144MHZ:
738 cs42l56->mclk_div2 = 0;
739 cs42l56->mclk_prediv = 0;
740 break;
741 case CS42L56_MCLK_11P2896MHZ:
742 case CS42L56_MCLK_12MHZ:
743 case CS42L56_MCLK_12P288MHZ:
Axel Lin4641c772014-05-23 13:05:31 +0800744 cs42l56->mclk_div2 = CS42L56_MCLK_DIV2;
Brian Austin272b5ed2014-05-05 15:09:08 -0500745 cs42l56->mclk_prediv = 0;
746 break;
747 case CS42L56_MCLK_22P5792MHZ:
748 case CS42L56_MCLK_24MHZ:
749 case CS42L56_MCLK_24P576MHZ:
Axel Lin4641c772014-05-23 13:05:31 +0800750 cs42l56->mclk_div2 = CS42L56_MCLK_DIV2;
751 cs42l56->mclk_prediv = CS42L56_MCLK_PREDIV;
Brian Austin272b5ed2014-05-05 15:09:08 -0500752 break;
753 default:
754 return -EINVAL;
755 }
756 cs42l56->mclk = freq;
757
758 snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
759 CS42L56_MCLK_PREDIV_MASK,
760 cs42l56->mclk_prediv);
761 snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
762 CS42L56_MCLK_DIV2_MASK,
763 cs42l56->mclk_div2);
764
765 return 0;
766}
767
768static int cs42l56_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
769{
770 struct snd_soc_codec *codec = codec_dai->codec;
771 struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
772
773 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
774 case SND_SOC_DAIFMT_CBM_CFM:
775 cs42l56->iface = CS42L56_MASTER_MODE;
776 break;
777 case SND_SOC_DAIFMT_CBS_CFS:
778 cs42l56->iface = CS42L56_SLAVE_MODE;
779 break;
780 default:
781 return -EINVAL;
782 }
783
784 /* interface format */
785 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
786 case SND_SOC_DAIFMT_I2S:
787 cs42l56->iface_fmt = CS42L56_DIG_FMT_I2S;
788 break;
789 case SND_SOC_DAIFMT_LEFT_J:
790 cs42l56->iface_fmt = CS42L56_DIG_FMT_LEFT_J;
791 break;
792 default:
793 return -EINVAL;
794 }
795
796 /* sclk inversion */
797 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
798 case SND_SOC_DAIFMT_NB_NF:
799 cs42l56->iface_inv = 0;
800 break;
801 case SND_SOC_DAIFMT_IB_NF:
802 cs42l56->iface_inv = CS42L56_SCLK_INV;
803 break;
804 default:
805 return -EINVAL;
806 }
807
808 snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
809 CS42L56_MS_MODE_MASK, cs42l56->iface);
810 snd_soc_update_bits(codec, CS42L56_SERIAL_FMT,
811 CS42L56_DIG_FMT_MASK, cs42l56->iface_fmt);
812 snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
813 CS42L56_SCLK_INV_MASK, cs42l56->iface_inv);
814 return 0;
815}
816
817static int cs42l56_digital_mute(struct snd_soc_dai *dai, int mute)
818{
819 struct snd_soc_codec *codec = dai->codec;
820
821 if (mute) {
822 /* Hit the DSP Mixer first */
823 snd_soc_update_bits(codec, CS42L56_DSP_MUTE_CTL,
824 CS42L56_ADCAMIX_MUTE_MASK |
Axel Lin4641c772014-05-23 13:05:31 +0800825 CS42L56_ADCBMIX_MUTE_MASK |
826 CS42L56_PCMAMIX_MUTE_MASK |
827 CS42L56_PCMBMIX_MUTE_MASK |
828 CS42L56_MSTB_MUTE_MASK |
829 CS42L56_MSTA_MUTE_MASK,
830 CS42L56_MUTE_ALL);
Brian Austin272b5ed2014-05-05 15:09:08 -0500831 /* Mute ADC's */
832 snd_soc_update_bits(codec, CS42L56_MISC_ADC_CTL,
Axel Lin4641c772014-05-23 13:05:31 +0800833 CS42L56_ADCA_MUTE_MASK |
834 CS42L56_ADCB_MUTE_MASK,
835 CS42L56_MUTE_ALL);
Brian Austin272b5ed2014-05-05 15:09:08 -0500836 /* HP And LO */
837 snd_soc_update_bits(codec, CS42L56_HPA_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800838 CS42L56_HP_MUTE_MASK, CS42L56_MUTE_ALL);
Brian Austin272b5ed2014-05-05 15:09:08 -0500839 snd_soc_update_bits(codec, CS42L56_HPB_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800840 CS42L56_HP_MUTE_MASK, CS42L56_MUTE_ALL);
Brian Austin272b5ed2014-05-05 15:09:08 -0500841 snd_soc_update_bits(codec, CS42L56_LOA_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800842 CS42L56_LO_MUTE_MASK, CS42L56_MUTE_ALL);
Brian Austin272b5ed2014-05-05 15:09:08 -0500843 snd_soc_update_bits(codec, CS42L56_LOB_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800844 CS42L56_LO_MUTE_MASK, CS42L56_MUTE_ALL);
Brian Austin272b5ed2014-05-05 15:09:08 -0500845 } else {
846 snd_soc_update_bits(codec, CS42L56_DSP_MUTE_CTL,
847 CS42L56_ADCAMIX_MUTE_MASK |
Axel Lin4641c772014-05-23 13:05:31 +0800848 CS42L56_ADCBMIX_MUTE_MASK |
849 CS42L56_PCMAMIX_MUTE_MASK |
850 CS42L56_PCMBMIX_MUTE_MASK |
851 CS42L56_MSTB_MUTE_MASK |
852 CS42L56_MSTA_MUTE_MASK,
853 CS42L56_UNMUTE);
854
Brian Austin272b5ed2014-05-05 15:09:08 -0500855 snd_soc_update_bits(codec, CS42L56_MISC_ADC_CTL,
Axel Lin4641c772014-05-23 13:05:31 +0800856 CS42L56_ADCA_MUTE_MASK |
857 CS42L56_ADCB_MUTE_MASK,
858 CS42L56_UNMUTE);
859
Brian Austin272b5ed2014-05-05 15:09:08 -0500860 snd_soc_update_bits(codec, CS42L56_HPA_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800861 CS42L56_HP_MUTE_MASK, CS42L56_UNMUTE);
Brian Austin272b5ed2014-05-05 15:09:08 -0500862 snd_soc_update_bits(codec, CS42L56_HPB_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800863 CS42L56_HP_MUTE_MASK, CS42L56_UNMUTE);
Brian Austin272b5ed2014-05-05 15:09:08 -0500864 snd_soc_update_bits(codec, CS42L56_LOA_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800865 CS42L56_LO_MUTE_MASK, CS42L56_UNMUTE);
Brian Austin272b5ed2014-05-05 15:09:08 -0500866 snd_soc_update_bits(codec, CS42L56_LOB_VOLUME,
Axel Lin4641c772014-05-23 13:05:31 +0800867 CS42L56_LO_MUTE_MASK, CS42L56_UNMUTE);
Brian Austin272b5ed2014-05-05 15:09:08 -0500868 }
869 return 0;
870}
871
872static int cs42l56_pcm_hw_params(struct snd_pcm_substream *substream,
873 struct snd_pcm_hw_params *params,
874 struct snd_soc_dai *dai)
875{
876 struct snd_soc_codec *codec = dai->codec;
877 struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
878 int ratio;
879
880 ratio = cs42l56_get_mclk_ratio(cs42l56->mclk, params_rate(params));
881 if (ratio >= 0) {
882 snd_soc_update_bits(codec, CS42L56_CLKCTL_2,
883 CS42L56_CLK_RATIO_MASK, ratio);
884 } else {
885 dev_err(codec->dev, "unsupported mclk/sclk/lrclk ratio\n");
886 return -EINVAL;
887 }
888
889 return 0;
890}
891
892static int cs42l56_set_bias_level(struct snd_soc_codec *codec,
893 enum snd_soc_bias_level level)
894{
895 struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
896 int ret;
897
898 switch (level) {
899 case SND_SOC_BIAS_ON:
900 break;
901 case SND_SOC_BIAS_PREPARE:
902 snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
903 CS42L56_MCLK_DIS_MASK, 0);
904 snd_soc_update_bits(codec, CS42L56_PWRCTL_1,
905 CS42L56_PDN_ALL_MASK, 0);
906 break;
907 case SND_SOC_BIAS_STANDBY:
Lars-Peter Clausen46a35b02015-06-01 10:10:21 +0200908 if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
Brian Austin272b5ed2014-05-05 15:09:08 -0500909 regcache_cache_only(cs42l56->regmap, false);
910 regcache_sync(cs42l56->regmap);
911 ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies),
912 cs42l56->supplies);
913 if (ret != 0) {
914 dev_err(cs42l56->dev,
915 "Failed to enable regulators: %d\n",
916 ret);
917 return ret;
918 }
919 }
920 snd_soc_update_bits(codec, CS42L56_PWRCTL_1,
921 CS42L56_PDN_ALL_MASK, 1);
922 break;
923 case SND_SOC_BIAS_OFF:
924 snd_soc_update_bits(codec, CS42L56_PWRCTL_1,
925 CS42L56_PDN_ALL_MASK, 1);
926 snd_soc_update_bits(codec, CS42L56_CLKCTL_1,
927 CS42L56_MCLK_DIS_MASK, 1);
928 regcache_cache_only(cs42l56->regmap, true);
929 regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies),
930 cs42l56->supplies);
931 break;
932 }
Brian Austin272b5ed2014-05-05 15:09:08 -0500933
934 return 0;
935}
936
937#define CS42L56_RATES (SNDRV_PCM_RATE_8000_48000)
938
939#define CS42L56_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
940 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
941 SNDRV_PCM_FMTBIT_S32_LE)
942
943
Axel Lin64793042015-07-15 15:38:14 +0800944static const struct snd_soc_dai_ops cs42l56_ops = {
Brian Austin272b5ed2014-05-05 15:09:08 -0500945 .hw_params = cs42l56_pcm_hw_params,
946 .digital_mute = cs42l56_digital_mute,
947 .set_fmt = cs42l56_set_dai_fmt,
948 .set_sysclk = cs42l56_set_sysclk,
949};
950
951static struct snd_soc_dai_driver cs42l56_dai = {
952 .name = "cs42l56",
953 .playback = {
954 .stream_name = "HiFi Playback",
955 .channels_min = 1,
956 .channels_max = 2,
957 .rates = CS42L56_RATES,
958 .formats = CS42L56_FORMATS,
959 },
960 .capture = {
961 .stream_name = "HiFi Capture",
962 .channels_min = 1,
963 .channels_max = 2,
964 .rates = CS42L56_RATES,
965 .formats = CS42L56_FORMATS,
966 },
967 .ops = &cs42l56_ops,
968};
969
Brian Austin272b5ed2014-05-05 15:09:08 -0500970static int beep_freq[] = {
971 261, 522, 585, 667, 706, 774, 889, 1000,
972 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
973};
974
975static void cs42l56_beep_work(struct work_struct *work)
976{
977 struct cs42l56_private *cs42l56 =
978 container_of(work, struct cs42l56_private, beep_work);
979 struct snd_soc_codec *codec = cs42l56->codec;
Lars-Peter Clausen46a35b02015-06-01 10:10:21 +0200980 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
Brian Austin272b5ed2014-05-05 15:09:08 -0500981 int i;
982 int val = 0;
983 int best = 0;
984
985 if (cs42l56->beep_rate) {
986 for (i = 0; i < ARRAY_SIZE(beep_freq); i++) {
987 if (abs(cs42l56->beep_rate - beep_freq[i]) <
988 abs(cs42l56->beep_rate - beep_freq[best]))
989 best = i;
990 }
991
992 dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
993 beep_freq[best], cs42l56->beep_rate);
994
995 val = (best << CS42L56_BEEP_RATE_SHIFT);
996
997 snd_soc_dapm_enable_pin(dapm, "Beep");
998 } else {
999 dev_dbg(codec->dev, "Disabling beep\n");
1000 snd_soc_dapm_disable_pin(dapm, "Beep");
1001 }
1002
1003 snd_soc_update_bits(codec, CS42L56_BEEP_FREQ_ONTIME,
1004 CS42L56_BEEP_FREQ_MASK, val);
1005
1006 snd_soc_dapm_sync(dapm);
1007}
1008
1009/* For usability define a way of injecting beep events for the device -
1010 * many systems will not have a keyboard.
1011 */
1012static int cs42l56_beep_event(struct input_dev *dev, unsigned int type,
1013 unsigned int code, int hz)
1014{
1015 struct snd_soc_codec *codec = input_get_drvdata(dev);
1016 struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
1017
1018 dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
1019
1020 switch (code) {
1021 case SND_BELL:
1022 if (hz)
1023 hz = 261;
1024 case SND_TONE:
1025 break;
1026 default:
1027 return -1;
1028 }
1029
1030 /* Kick the beep from a workqueue */
1031 cs42l56->beep_rate = hz;
1032 schedule_work(&cs42l56->beep_work);
1033 return 0;
1034}
1035
1036static ssize_t cs42l56_beep_set(struct device *dev,
1037 struct device_attribute *attr,
1038 const char *buf, size_t count)
1039{
1040 struct cs42l56_private *cs42l56 = dev_get_drvdata(dev);
1041 long int time;
1042 int ret;
1043
1044 ret = kstrtol(buf, 10, &time);
1045 if (ret != 0)
1046 return ret;
1047
1048 input_event(cs42l56->beep, EV_SND, SND_TONE, time);
1049
1050 return count;
1051}
1052
1053static DEVICE_ATTR(beep, 0200, NULL, cs42l56_beep_set);
1054
1055static void cs42l56_init_beep(struct snd_soc_codec *codec)
1056{
1057 struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
1058 int ret;
1059
1060 cs42l56->beep = devm_input_allocate_device(codec->dev);
1061 if (!cs42l56->beep) {
1062 dev_err(codec->dev, "Failed to allocate beep device\n");
1063 return;
1064 }
1065
1066 INIT_WORK(&cs42l56->beep_work, cs42l56_beep_work);
1067 cs42l56->beep_rate = 0;
1068
1069 cs42l56->beep->name = "CS42L56 Beep Generator";
1070 cs42l56->beep->phys = dev_name(codec->dev);
1071 cs42l56->beep->id.bustype = BUS_I2C;
1072
1073 cs42l56->beep->evbit[0] = BIT_MASK(EV_SND);
1074 cs42l56->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
1075 cs42l56->beep->event = cs42l56_beep_event;
1076 cs42l56->beep->dev.parent = codec->dev;
1077 input_set_drvdata(cs42l56->beep, codec);
1078
1079 ret = input_register_device(cs42l56->beep);
1080 if (ret != 0) {
1081 cs42l56->beep = NULL;
1082 dev_err(codec->dev, "Failed to register beep device\n");
1083 }
1084
1085 ret = device_create_file(codec->dev, &dev_attr_beep);
1086 if (ret != 0) {
1087 dev_err(codec->dev, "Failed to create keyclick file: %d\n",
1088 ret);
1089 }
1090}
1091
1092static void cs42l56_free_beep(struct snd_soc_codec *codec)
1093{
1094 struct cs42l56_private *cs42l56 = snd_soc_codec_get_drvdata(codec);
1095
1096 device_remove_file(codec->dev, &dev_attr_beep);
1097 cancel_work_sync(&cs42l56->beep_work);
1098 cs42l56->beep = NULL;
1099
1100 snd_soc_update_bits(codec, CS42L56_BEEP_TONE_CFG,
1101 CS42L56_BEEP_EN_MASK, 0);
1102}
1103
1104static int cs42l56_probe(struct snd_soc_codec *codec)
1105{
1106 cs42l56_init_beep(codec);
1107
Brian Austin272b5ed2014-05-05 15:09:08 -05001108 return 0;
1109}
1110
1111static int cs42l56_remove(struct snd_soc_codec *codec)
1112{
Brian Austin272b5ed2014-05-05 15:09:08 -05001113 cs42l56_free_beep(codec);
Brian Austin272b5ed2014-05-05 15:09:08 -05001114
1115 return 0;
1116}
1117
Krzysztof Kozlowskicf0efa12015-01-05 10:18:24 +01001118static const struct snd_soc_codec_driver soc_codec_dev_cs42l56 = {
Brian Austin272b5ed2014-05-05 15:09:08 -05001119 .probe = cs42l56_probe,
1120 .remove = cs42l56_remove,
Brian Austin272b5ed2014-05-05 15:09:08 -05001121 .set_bias_level = cs42l56_set_bias_level,
Lars-Peter Clausen2a4bc752014-09-09 20:42:41 +02001122 .suspend_bias_off = true,
Brian Austin272b5ed2014-05-05 15:09:08 -05001123
1124 .dapm_widgets = cs42l56_dapm_widgets,
1125 .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets),
1126 .dapm_routes = cs42l56_audio_map,
1127 .num_dapm_routes = ARRAY_SIZE(cs42l56_audio_map),
1128
1129 .controls = cs42l56_snd_controls,
1130 .num_controls = ARRAY_SIZE(cs42l56_snd_controls),
1131};
1132
Krzysztof Kozlowskicf0efa12015-01-05 10:18:24 +01001133static const struct regmap_config cs42l56_regmap = {
Brian Austin272b5ed2014-05-05 15:09:08 -05001134 .reg_bits = 8,
1135 .val_bits = 8,
1136
1137 .max_register = CS42L56_MAX_REGISTER,
1138 .reg_defaults = cs42l56_reg_defaults,
1139 .num_reg_defaults = ARRAY_SIZE(cs42l56_reg_defaults),
1140 .readable_reg = cs42l56_readable_register,
1141 .volatile_reg = cs42l56_volatile_register,
1142 .cache_type = REGCACHE_RBTREE,
1143};
1144
1145static int cs42l56_handle_of_data(struct i2c_client *i2c_client,
1146 struct cs42l56_platform_data *pdata)
1147{
1148 struct device_node *np = i2c_client->dev.of_node;
1149 u32 val32;
1150
1151 if (of_property_read_bool(np, "cirrus,ain1a-reference-cfg"))
1152 pdata->ain1a_ref_cfg = true;
1153
1154 if (of_property_read_bool(np, "cirrus,ain2a-reference-cfg"))
1155 pdata->ain2a_ref_cfg = true;
1156
1157 if (of_property_read_bool(np, "cirrus,ain1b-reference-cfg"))
1158 pdata->ain1b_ref_cfg = true;
1159
1160 if (of_property_read_bool(np, "cirrus,ain2b-reference-cfg"))
1161 pdata->ain2b_ref_cfg = true;
1162
1163 if (of_property_read_u32(np, "cirrus,micbias-lvl", &val32) >= 0)
1164 pdata->micbias_lvl = val32;
1165
1166 if (of_property_read_u32(np, "cirrus,chgfreq-divisor", &val32) >= 0)
1167 pdata->chgfreq = val32;
1168
1169 if (of_property_read_u32(np, "cirrus,adaptive-pwr-cfg", &val32) >= 0)
1170 pdata->adaptive_pwr = val32;
1171
1172 if (of_property_read_u32(np, "cirrus,hpf-left-freq", &val32) >= 0)
1173 pdata->hpfa_freq = val32;
1174
1175 if (of_property_read_u32(np, "cirrus,hpf-left-freq", &val32) >= 0)
1176 pdata->hpfb_freq = val32;
1177
1178 pdata->gpio_nreset = of_get_named_gpio(np, "cirrus,gpio-nreset", 0);
1179
1180 return 0;
1181}
1182
1183static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
1184 const struct i2c_device_id *id)
1185{
1186 struct cs42l56_private *cs42l56;
1187 struct cs42l56_platform_data *pdata =
1188 dev_get_platdata(&i2c_client->dev);
1189 int ret, i;
1190 unsigned int devid = 0;
1191 unsigned int alpha_rev, metal_rev;
1192 unsigned int reg;
1193
1194 cs42l56 = devm_kzalloc(&i2c_client->dev,
1195 sizeof(struct cs42l56_private),
1196 GFP_KERNEL);
1197 if (cs42l56 == NULL)
1198 return -ENOMEM;
1199 cs42l56->dev = &i2c_client->dev;
1200
1201 cs42l56->regmap = devm_regmap_init_i2c(i2c_client, &cs42l56_regmap);
1202 if (IS_ERR(cs42l56->regmap)) {
1203 ret = PTR_ERR(cs42l56->regmap);
1204 dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1205 return ret;
1206 }
1207
1208 if (pdata) {
1209 cs42l56->pdata = *pdata;
1210 } else {
1211 pdata = devm_kzalloc(&i2c_client->dev,
1212 sizeof(struct cs42l56_platform_data),
1213 GFP_KERNEL);
1214 if (!pdata) {
1215 dev_err(&i2c_client->dev,
1216 "could not allocate pdata\n");
1217 return -ENOMEM;
1218 }
1219 if (i2c_client->dev.of_node) {
1220 ret = cs42l56_handle_of_data(i2c_client,
1221 &cs42l56->pdata);
1222 if (ret != 0)
1223 return ret;
1224 }
1225 cs42l56->pdata = *pdata;
1226 }
1227
1228 if (cs42l56->pdata.gpio_nreset) {
1229 ret = gpio_request_one(cs42l56->pdata.gpio_nreset,
1230 GPIOF_OUT_INIT_HIGH, "CS42L56 /RST");
1231 if (ret < 0) {
1232 dev_err(&i2c_client->dev,
1233 "Failed to request /RST %d: %d\n",
1234 cs42l56->pdata.gpio_nreset, ret);
1235 return ret;
1236 }
1237 gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 0);
1238 gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 1);
1239 }
1240
1241
1242 i2c_set_clientdata(i2c_client, cs42l56);
1243
1244 for (i = 0; i < ARRAY_SIZE(cs42l56->supplies); i++)
1245 cs42l56->supplies[i].supply = cs42l56_supply_names[i];
1246
1247 ret = devm_regulator_bulk_get(&i2c_client->dev,
1248 ARRAY_SIZE(cs42l56->supplies),
1249 cs42l56->supplies);
1250 if (ret != 0) {
1251 dev_err(&i2c_client->dev,
1252 "Failed to request supplies: %d\n", ret);
1253 return ret;
1254 }
1255
1256 ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies),
1257 cs42l56->supplies);
1258 if (ret != 0) {
1259 dev_err(&i2c_client->dev,
1260 "Failed to enable supplies: %d\n", ret);
1261 return ret;
1262 }
1263
1264 regcache_cache_bypass(cs42l56->regmap, true);
1265
1266 ret = regmap_read(cs42l56->regmap, CS42L56_CHIP_ID_1, &reg);
1267 devid = reg & CS42L56_CHIP_ID_MASK;
1268 if (devid != CS42L56_DEVID) {
1269 dev_err(&i2c_client->dev,
1270 "CS42L56 Device ID (%X). Expected %X\n",
1271 devid, CS42L56_DEVID);
1272 goto err_enable;
1273 }
1274 alpha_rev = reg & CS42L56_AREV_MASK;
1275 metal_rev = reg & CS42L56_MTLREV_MASK;
1276
1277 dev_info(&i2c_client->dev, "Cirrus Logic CS42L56 ");
1278 dev_info(&i2c_client->dev, "Alpha Rev %X Metal Rev %X\n",
1279 alpha_rev, metal_rev);
1280
1281 regcache_cache_bypass(cs42l56->regmap, false);
1282
1283 if (cs42l56->pdata.ain1a_ref_cfg)
1284 regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
1285 CS42L56_AIN1A_REF_MASK, 1);
1286
1287 if (cs42l56->pdata.ain1b_ref_cfg)
1288 regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
1289 CS42L56_AIN1B_REF_MASK, 1);
1290
1291 if (cs42l56->pdata.ain2a_ref_cfg)
1292 regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
1293 CS42L56_AIN2A_REF_MASK, 1);
1294
1295 if (cs42l56->pdata.ain2b_ref_cfg)
1296 regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
1297 CS42L56_AIN2B_REF_MASK, 1);
1298
1299 if (cs42l56->pdata.micbias_lvl)
1300 regmap_update_bits(cs42l56->regmap, CS42L56_GAIN_BIAS_CTL,
1301 CS42L56_MIC_BIAS_MASK,
1302 cs42l56->pdata.micbias_lvl);
1303
1304 if (cs42l56->pdata.chgfreq)
1305 regmap_update_bits(cs42l56->regmap, CS42L56_CLASSH_CTL,
1306 CS42L56_CHRG_FREQ_MASK,
1307 cs42l56->pdata.chgfreq);
1308
1309 if (cs42l56->pdata.hpfb_freq)
1310 regmap_update_bits(cs42l56->regmap, CS42L56_HPF_CTL,
1311 CS42L56_HPFB_FREQ_MASK,
1312 cs42l56->pdata.hpfb_freq);
1313
1314 if (cs42l56->pdata.hpfa_freq)
1315 regmap_update_bits(cs42l56->regmap, CS42L56_HPF_CTL,
1316 CS42L56_HPFA_FREQ_MASK,
1317 cs42l56->pdata.hpfa_freq);
1318
1319 if (cs42l56->pdata.adaptive_pwr)
1320 regmap_update_bits(cs42l56->regmap, CS42L56_CLASSH_CTL,
1321 CS42L56_ADAPT_PWR_MASK,
1322 cs42l56->pdata.adaptive_pwr);
1323
1324 ret = snd_soc_register_codec(&i2c_client->dev,
1325 &soc_codec_dev_cs42l56, &cs42l56_dai, 1);
1326 if (ret < 0)
1327 return ret;
1328
1329 return 0;
1330
1331err_enable:
1332 regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies),
1333 cs42l56->supplies);
1334 return ret;
1335}
1336
1337static int cs42l56_i2c_remove(struct i2c_client *client)
1338{
1339 struct cs42l56_private *cs42l56 = i2c_get_clientdata(client);
1340
1341 snd_soc_unregister_codec(&client->dev);
1342 regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies),
1343 cs42l56->supplies);
1344 return 0;
1345}
1346
1347static const struct of_device_id cs42l56_of_match[] = {
1348 { .compatible = "cirrus,cs42l56", },
1349 { }
1350};
1351MODULE_DEVICE_TABLE(of, cs42l56_of_match);
1352
1353
1354static const struct i2c_device_id cs42l56_id[] = {
1355 { "cs42l56", 0 },
1356 { }
1357};
1358MODULE_DEVICE_TABLE(i2c, cs42l56_id);
1359
1360static struct i2c_driver cs42l56_i2c_driver = {
1361 .driver = {
1362 .name = "cs42l56",
Brian Austin272b5ed2014-05-05 15:09:08 -05001363 .of_match_table = cs42l56_of_match,
1364 },
1365 .id_table = cs42l56_id,
1366 .probe = cs42l56_i2c_probe,
1367 .remove = cs42l56_i2c_remove,
1368};
1369
1370module_i2c_driver(cs42l56_i2c_driver);
1371
1372MODULE_DESCRIPTION("ASoC CS42L56 driver");
1373MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
1374MODULE_LICENSE("GPL");