xref: /openbmc/linux/sound/soc/codecs/cs53l30.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2de9b1214SNicolin Chen /*
3de9b1214SNicolin Chen  * cs53l30.c  --  CS53l30 ALSA Soc Audio driver
4de9b1214SNicolin Chen  *
5de9b1214SNicolin Chen  * Copyright 2015 Cirrus Logic, Inc.
6de9b1214SNicolin Chen  *
7de9b1214SNicolin Chen  * Authors: Paul Handrigan <Paul.Handrigan@cirrus.com>,
8de9b1214SNicolin Chen  *          Tim Howe <Tim.Howe@cirrus.com>
9de9b1214SNicolin Chen  */
10de9b1214SNicolin Chen 
11de9b1214SNicolin Chen #include <linux/clk.h>
12de9b1214SNicolin Chen #include <linux/delay.h>
13de9b1214SNicolin Chen #include <linux/i2c.h>
14de9b1214SNicolin Chen #include <linux/module.h>
15de9b1214SNicolin Chen #include <linux/of_gpio.h>
1653d4b031SArnd Bergmann #include <linux/gpio/consumer.h>
17de9b1214SNicolin Chen #include <linux/regulator/consumer.h>
18de9b1214SNicolin Chen #include <sound/pcm_params.h>
19de9b1214SNicolin Chen #include <sound/soc.h>
20de9b1214SNicolin Chen #include <sound/tlv.h>
21de9b1214SNicolin Chen 
22de9b1214SNicolin Chen #include "cs53l30.h"
234fc81bc8SCharles Keepax #include "cirrus_legacy.h"
24de9b1214SNicolin Chen 
25de9b1214SNicolin Chen #define CS53L30_NUM_SUPPLIES 2
26de9b1214SNicolin Chen static const char *const cs53l30_supply_names[CS53L30_NUM_SUPPLIES] = {
27de9b1214SNicolin Chen 	"VA",
28de9b1214SNicolin Chen 	"VP",
29de9b1214SNicolin Chen };
30de9b1214SNicolin Chen 
31de9b1214SNicolin Chen struct cs53l30_private {
32de9b1214SNicolin Chen 	struct regulator_bulk_data	supplies[CS53L30_NUM_SUPPLIES];
33de9b1214SNicolin Chen 	struct regmap			*regmap;
34de9b1214SNicolin Chen 	struct gpio_desc		*reset_gpio;
3505f33bc5SNicolin Chen 	struct gpio_desc		*mute_gpio;
36de9b1214SNicolin Chen 	struct clk			*mclk;
37de9b1214SNicolin Chen 	bool				use_sdout2;
38de9b1214SNicolin Chen 	u32				mclk_rate;
39de9b1214SNicolin Chen };
40de9b1214SNicolin Chen 
41de9b1214SNicolin Chen static const struct reg_default cs53l30_reg_defaults[] = {
42de9b1214SNicolin Chen 	{ CS53L30_PWRCTL,		CS53L30_PWRCTL_DEFAULT },
43de9b1214SNicolin Chen 	{ CS53L30_MCLKCTL,		CS53L30_MCLKCTL_DEFAULT },
44de9b1214SNicolin Chen 	{ CS53L30_INT_SR_CTL,		CS53L30_INT_SR_CTL_DEFAULT },
45de9b1214SNicolin Chen 	{ CS53L30_MICBIAS_CTL,		CS53L30_MICBIAS_CTL_DEFAULT },
46de9b1214SNicolin Chen 	{ CS53L30_ASPCFG_CTL,		CS53L30_ASPCFG_CTL_DEFAULT },
47de9b1214SNicolin Chen 	{ CS53L30_ASP_CTL1,		CS53L30_ASP_CTL1_DEFAULT },
48de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_CTL1,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },
49de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_CTL2,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },
50de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_CTL3,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },
51de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_CTL4,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },
52de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_EN1,	CS53L30_ASP_TDMTX_ENx_DEFAULT },
53de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_EN2,	CS53L30_ASP_TDMTX_ENx_DEFAULT },
54de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_EN3,	CS53L30_ASP_TDMTX_ENx_DEFAULT },
55de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_EN4,	CS53L30_ASP_TDMTX_ENx_DEFAULT },
56de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_EN5,	CS53L30_ASP_TDMTX_ENx_DEFAULT },
57de9b1214SNicolin Chen 	{ CS53L30_ASP_TDMTX_EN6,	CS53L30_ASP_TDMTX_ENx_DEFAULT },
58de9b1214SNicolin Chen 	{ CS53L30_ASP_CTL2,		CS53L30_ASP_CTL2_DEFAULT },
59de9b1214SNicolin Chen 	{ CS53L30_SFT_RAMP,		CS53L30_SFT_RMP_DEFAULT },
60de9b1214SNicolin Chen 	{ CS53L30_LRCK_CTL1,		CS53L30_LRCK_CTLx_DEFAULT },
61de9b1214SNicolin Chen 	{ CS53L30_LRCK_CTL2,		CS53L30_LRCK_CTLx_DEFAULT },
62de9b1214SNicolin Chen 	{ CS53L30_MUTEP_CTL1,		CS53L30_MUTEP_CTL1_DEFAULT },
63de9b1214SNicolin Chen 	{ CS53L30_MUTEP_CTL2,		CS53L30_MUTEP_CTL2_DEFAULT },
64de9b1214SNicolin Chen 	{ CS53L30_INBIAS_CTL1,		CS53L30_INBIAS_CTL1_DEFAULT },
65de9b1214SNicolin Chen 	{ CS53L30_INBIAS_CTL2,		CS53L30_INBIAS_CTL2_DEFAULT },
66de9b1214SNicolin Chen 	{ CS53L30_DMIC1_STR_CTL,	CS53L30_DMIC1_STR_CTL_DEFAULT },
67de9b1214SNicolin Chen 	{ CS53L30_DMIC2_STR_CTL,	CS53L30_DMIC2_STR_CTL_DEFAULT },
68de9b1214SNicolin Chen 	{ CS53L30_ADCDMIC1_CTL1,	CS53L30_ADCDMICx_CTL1_DEFAULT },
69de9b1214SNicolin Chen 	{ CS53L30_ADCDMIC1_CTL2,	CS53L30_ADCDMIC1_CTL2_DEFAULT },
70de9b1214SNicolin Chen 	{ CS53L30_ADC1_CTL3,		CS53L30_ADCx_CTL3_DEFAULT },
71de9b1214SNicolin Chen 	{ CS53L30_ADC1_NG_CTL,		CS53L30_ADCx_NG_CTL_DEFAULT },
72de9b1214SNicolin Chen 	{ CS53L30_ADC1A_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },
73de9b1214SNicolin Chen 	{ CS53L30_ADC1B_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },
74de9b1214SNicolin Chen 	{ CS53L30_ADC1A_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },
75de9b1214SNicolin Chen 	{ CS53L30_ADC1B_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },
76de9b1214SNicolin Chen 	{ CS53L30_ADCDMIC2_CTL1,	CS53L30_ADCDMICx_CTL1_DEFAULT },
77de9b1214SNicolin Chen 	{ CS53L30_ADCDMIC2_CTL2,	CS53L30_ADCDMIC1_CTL2_DEFAULT },
78de9b1214SNicolin Chen 	{ CS53L30_ADC2_CTL3,		CS53L30_ADCx_CTL3_DEFAULT },
79de9b1214SNicolin Chen 	{ CS53L30_ADC2_NG_CTL,		CS53L30_ADCx_NG_CTL_DEFAULT },
80de9b1214SNicolin Chen 	{ CS53L30_ADC2A_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },
81de9b1214SNicolin Chen 	{ CS53L30_ADC2B_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },
82de9b1214SNicolin Chen 	{ CS53L30_ADC2A_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },
83de9b1214SNicolin Chen 	{ CS53L30_ADC2B_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },
84de9b1214SNicolin Chen 	{ CS53L30_INT_MASK,		CS53L30_DEVICE_INT_MASK },
85de9b1214SNicolin Chen };
86de9b1214SNicolin Chen 
cs53l30_volatile_register(struct device * dev,unsigned int reg)87de9b1214SNicolin Chen static bool cs53l30_volatile_register(struct device *dev, unsigned int reg)
88de9b1214SNicolin Chen {
89de9b1214SNicolin Chen 	if (reg == CS53L30_IS)
90de9b1214SNicolin Chen 		return true;
91de9b1214SNicolin Chen 	else
92de9b1214SNicolin Chen 		return false;
93de9b1214SNicolin Chen }
94de9b1214SNicolin Chen 
cs53l30_writeable_register(struct device * dev,unsigned int reg)95de9b1214SNicolin Chen static bool cs53l30_writeable_register(struct device *dev, unsigned int reg)
96de9b1214SNicolin Chen {
97de9b1214SNicolin Chen 	switch (reg) {
98de9b1214SNicolin Chen 	case CS53L30_DEVID_AB:
99de9b1214SNicolin Chen 	case CS53L30_DEVID_CD:
100de9b1214SNicolin Chen 	case CS53L30_DEVID_E:
101de9b1214SNicolin Chen 	case CS53L30_REVID:
102de9b1214SNicolin Chen 	case CS53L30_IS:
103de9b1214SNicolin Chen 		return false;
104de9b1214SNicolin Chen 	default:
105de9b1214SNicolin Chen 		return true;
106de9b1214SNicolin Chen 	}
107de9b1214SNicolin Chen }
108de9b1214SNicolin Chen 
cs53l30_readable_register(struct device * dev,unsigned int reg)109de9b1214SNicolin Chen static bool cs53l30_readable_register(struct device *dev, unsigned int reg)
110de9b1214SNicolin Chen {
111de9b1214SNicolin Chen 	switch (reg) {
112de9b1214SNicolin Chen 	case CS53L30_DEVID_AB:
113de9b1214SNicolin Chen 	case CS53L30_DEVID_CD:
114de9b1214SNicolin Chen 	case CS53L30_DEVID_E:
115de9b1214SNicolin Chen 	case CS53L30_REVID:
116de9b1214SNicolin Chen 	case CS53L30_PWRCTL:
117de9b1214SNicolin Chen 	case CS53L30_MCLKCTL:
118de9b1214SNicolin Chen 	case CS53L30_INT_SR_CTL:
119de9b1214SNicolin Chen 	case CS53L30_MICBIAS_CTL:
120de9b1214SNicolin Chen 	case CS53L30_ASPCFG_CTL:
121de9b1214SNicolin Chen 	case CS53L30_ASP_CTL1:
122de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_CTL1:
123de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_CTL2:
124de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_CTL3:
125de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_CTL4:
126de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_EN1:
127de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_EN2:
128de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_EN3:
129de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_EN4:
130de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_EN5:
131de9b1214SNicolin Chen 	case CS53L30_ASP_TDMTX_EN6:
132de9b1214SNicolin Chen 	case CS53L30_ASP_CTL2:
133de9b1214SNicolin Chen 	case CS53L30_SFT_RAMP:
134de9b1214SNicolin Chen 	case CS53L30_LRCK_CTL1:
135de9b1214SNicolin Chen 	case CS53L30_LRCK_CTL2:
136de9b1214SNicolin Chen 	case CS53L30_MUTEP_CTL1:
137de9b1214SNicolin Chen 	case CS53L30_MUTEP_CTL2:
138de9b1214SNicolin Chen 	case CS53L30_INBIAS_CTL1:
139de9b1214SNicolin Chen 	case CS53L30_INBIAS_CTL2:
140de9b1214SNicolin Chen 	case CS53L30_DMIC1_STR_CTL:
141de9b1214SNicolin Chen 	case CS53L30_DMIC2_STR_CTL:
142de9b1214SNicolin Chen 	case CS53L30_ADCDMIC1_CTL1:
143de9b1214SNicolin Chen 	case CS53L30_ADCDMIC1_CTL2:
144de9b1214SNicolin Chen 	case CS53L30_ADC1_CTL3:
145de9b1214SNicolin Chen 	case CS53L30_ADC1_NG_CTL:
146de9b1214SNicolin Chen 	case CS53L30_ADC1A_AFE_CTL:
147de9b1214SNicolin Chen 	case CS53L30_ADC1B_AFE_CTL:
148de9b1214SNicolin Chen 	case CS53L30_ADC1A_DIG_VOL:
149de9b1214SNicolin Chen 	case CS53L30_ADC1B_DIG_VOL:
150de9b1214SNicolin Chen 	case CS53L30_ADCDMIC2_CTL1:
151de9b1214SNicolin Chen 	case CS53L30_ADCDMIC2_CTL2:
152de9b1214SNicolin Chen 	case CS53L30_ADC2_CTL3:
153de9b1214SNicolin Chen 	case CS53L30_ADC2_NG_CTL:
154de9b1214SNicolin Chen 	case CS53L30_ADC2A_AFE_CTL:
155de9b1214SNicolin Chen 	case CS53L30_ADC2B_AFE_CTL:
156de9b1214SNicolin Chen 	case CS53L30_ADC2A_DIG_VOL:
157de9b1214SNicolin Chen 	case CS53L30_ADC2B_DIG_VOL:
158de9b1214SNicolin Chen 	case CS53L30_INT_MASK:
159de9b1214SNicolin Chen 		return true;
160de9b1214SNicolin Chen 	default:
161de9b1214SNicolin Chen 		return false;
162de9b1214SNicolin Chen 	}
163de9b1214SNicolin Chen }
164de9b1214SNicolin Chen 
165de9b1214SNicolin Chen static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2000, 0);
166de9b1214SNicolin Chen static DECLARE_TLV_DB_SCALE(adc_ng_boost_tlv, 0, 3000, 0);
167de9b1214SNicolin Chen static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
168de9b1214SNicolin Chen static DECLARE_TLV_DB_SCALE(dig_tlv, -9600, 100, 1);
169de9b1214SNicolin Chen static DECLARE_TLV_DB_SCALE(pga_preamp_tlv, 0, 10000, 0);
170de9b1214SNicolin Chen 
171de9b1214SNicolin Chen static const char * const input1_sel_text[] = {
172de9b1214SNicolin Chen 	"DMIC1 On AB In",
173de9b1214SNicolin Chen 	"DMIC1 On A In",
174de9b1214SNicolin Chen 	"DMIC1 On B In",
175de9b1214SNicolin Chen 	"ADC1 On AB In",
176de9b1214SNicolin Chen 	"ADC1 On A In",
177de9b1214SNicolin Chen 	"ADC1 On B In",
178de9b1214SNicolin Chen 	"DMIC1 Off ADC1 Off",
179de9b1214SNicolin Chen };
180de9b1214SNicolin Chen 
181ee85be8cSWei Yongjun static unsigned int const input1_sel_values[] = {
182de9b1214SNicolin Chen 	CS53L30_CH_TYPE,
183de9b1214SNicolin Chen 	CS53L30_ADCxB_PDN | CS53L30_CH_TYPE,
184de9b1214SNicolin Chen 	CS53L30_ADCxA_PDN | CS53L30_CH_TYPE,
185de9b1214SNicolin Chen 	CS53L30_DMICx_PDN,
186de9b1214SNicolin Chen 	CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,
187de9b1214SNicolin Chen 	CS53L30_ADCxA_PDN | CS53L30_DMICx_PDN,
188de9b1214SNicolin Chen 	CS53L30_ADCxA_PDN | CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,
189de9b1214SNicolin Chen };
190de9b1214SNicolin Chen 
191de9b1214SNicolin Chen static const char * const input2_sel_text[] = {
192de9b1214SNicolin Chen 	"DMIC2 On AB In",
193de9b1214SNicolin Chen 	"DMIC2 On A In",
194de9b1214SNicolin Chen 	"DMIC2 On B In",
195de9b1214SNicolin Chen 	"ADC2 On AB In",
196de9b1214SNicolin Chen 	"ADC2 On A In",
197de9b1214SNicolin Chen 	"ADC2 On B In",
198de9b1214SNicolin Chen 	"DMIC2 Off ADC2 Off",
199de9b1214SNicolin Chen };
200de9b1214SNicolin Chen 
201ee85be8cSWei Yongjun static unsigned int const input2_sel_values[] = {
202de9b1214SNicolin Chen 	0x0,
203de9b1214SNicolin Chen 	CS53L30_ADCxB_PDN,
204de9b1214SNicolin Chen 	CS53L30_ADCxA_PDN,
205de9b1214SNicolin Chen 	CS53L30_DMICx_PDN,
206de9b1214SNicolin Chen 	CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,
207de9b1214SNicolin Chen 	CS53L30_ADCxA_PDN | CS53L30_DMICx_PDN,
208de9b1214SNicolin Chen 	CS53L30_ADCxA_PDN | CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,
209de9b1214SNicolin Chen };
210de9b1214SNicolin Chen 
211de9b1214SNicolin Chen static const char * const input1_route_sel_text[] = {
212de9b1214SNicolin Chen 	"ADC1_SEL", "DMIC1_SEL",
213de9b1214SNicolin Chen };
214de9b1214SNicolin Chen 
215de9b1214SNicolin Chen static const struct soc_enum input1_route_sel_enum =
216de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADCDMIC1_CTL1, CS53L30_CH_TYPE_SHIFT,
217de9b1214SNicolin Chen 			ARRAY_SIZE(input1_route_sel_text),
218de9b1214SNicolin Chen 			input1_route_sel_text);
219de9b1214SNicolin Chen 
220de9b1214SNicolin Chen static SOC_VALUE_ENUM_SINGLE_DECL(input1_sel_enum, CS53L30_ADCDMIC1_CTL1, 0,
221de9b1214SNicolin Chen 				  CS53L30_ADCDMICx_PDN_MASK, input1_sel_text,
222de9b1214SNicolin Chen 				  input1_sel_values);
223de9b1214SNicolin Chen 
224de9b1214SNicolin Chen static const struct snd_kcontrol_new input1_route_sel_mux =
225de9b1214SNicolin Chen 	SOC_DAPM_ENUM("Input 1 Route", input1_route_sel_enum);
226de9b1214SNicolin Chen 
227de9b1214SNicolin Chen static const char * const input2_route_sel_text[] = {
228de9b1214SNicolin Chen 	"ADC2_SEL", "DMIC2_SEL",
229de9b1214SNicolin Chen };
230de9b1214SNicolin Chen 
231de9b1214SNicolin Chen /* Note: CS53L30_ADCDMIC1_CTL1 CH_TYPE controls inputs 1 and 2 */
232de9b1214SNicolin Chen static const struct soc_enum input2_route_sel_enum =
233de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADCDMIC1_CTL1, 0,
234de9b1214SNicolin Chen 			ARRAY_SIZE(input2_route_sel_text),
235de9b1214SNicolin Chen 			input2_route_sel_text);
236de9b1214SNicolin Chen 
237de9b1214SNicolin Chen static SOC_VALUE_ENUM_SINGLE_DECL(input2_sel_enum, CS53L30_ADCDMIC2_CTL1, 0,
238de9b1214SNicolin Chen 				  CS53L30_ADCDMICx_PDN_MASK, input2_sel_text,
239de9b1214SNicolin Chen 				  input2_sel_values);
240de9b1214SNicolin Chen 
241de9b1214SNicolin Chen static const struct snd_kcontrol_new input2_route_sel_mux =
242de9b1214SNicolin Chen 	SOC_DAPM_ENUM("Input 2 Route", input2_route_sel_enum);
243de9b1214SNicolin Chen 
244de9b1214SNicolin Chen /*
245de9b1214SNicolin Chen  * TB = 6144*(MCLK(int) scaling factor)/MCLK(internal)
246de9b1214SNicolin Chen  * TB - Time base
247de9b1214SNicolin Chen  * NOTE: If MCLK_INT_SCALE = 0, then TB=1
248de9b1214SNicolin Chen  */
249de9b1214SNicolin Chen static const char * const cs53l30_ng_delay_text[] = {
250de9b1214SNicolin Chen 	"TB*50ms", "TB*100ms", "TB*150ms", "TB*200ms",
251de9b1214SNicolin Chen };
252de9b1214SNicolin Chen 
253de9b1214SNicolin Chen static const struct soc_enum adc1_ng_delay_enum =
254de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADC1_NG_CTL, CS53L30_ADCx_NG_DELAY_SHIFT,
255de9b1214SNicolin Chen 			ARRAY_SIZE(cs53l30_ng_delay_text),
256de9b1214SNicolin Chen 			cs53l30_ng_delay_text);
257de9b1214SNicolin Chen 
258de9b1214SNicolin Chen static const struct soc_enum adc2_ng_delay_enum =
259de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADC2_NG_CTL, CS53L30_ADCx_NG_DELAY_SHIFT,
260de9b1214SNicolin Chen 			ARRAY_SIZE(cs53l30_ng_delay_text),
261de9b1214SNicolin Chen 			cs53l30_ng_delay_text);
262de9b1214SNicolin Chen 
263de9b1214SNicolin Chen /* The noise gate threshold selected will depend on NG Boost */
264de9b1214SNicolin Chen static const char * const cs53l30_ng_thres_text[] = {
265de9b1214SNicolin Chen 	"-64dB/-34dB", "-66dB/-36dB", "-70dB/-40dB", "-73dB/-43dB",
266de9b1214SNicolin Chen 	"-76dB/-46dB", "-82dB/-52dB", "-58dB", "-64dB",
267de9b1214SNicolin Chen };
268de9b1214SNicolin Chen 
269de9b1214SNicolin Chen static const struct soc_enum adc1_ng_thres_enum =
270de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADC1_NG_CTL, CS53L30_ADCx_NG_THRESH_SHIFT,
271de9b1214SNicolin Chen 			ARRAY_SIZE(cs53l30_ng_thres_text),
272de9b1214SNicolin Chen 			cs53l30_ng_thres_text);
273de9b1214SNicolin Chen 
274de9b1214SNicolin Chen static const struct soc_enum adc2_ng_thres_enum =
275de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADC2_NG_CTL, CS53L30_ADCx_NG_THRESH_SHIFT,
276de9b1214SNicolin Chen 			ARRAY_SIZE(cs53l30_ng_thres_text),
277de9b1214SNicolin Chen 			cs53l30_ng_thres_text);
278de9b1214SNicolin Chen 
279de9b1214SNicolin Chen /* Corner frequencies are with an Fs of 48kHz. */
280de9b1214SNicolin Chen static const char * const hpf_corner_freq_text[] = {
281de9b1214SNicolin Chen 	"1.86Hz", "120Hz", "235Hz", "466Hz",
282de9b1214SNicolin Chen };
283de9b1214SNicolin Chen 
284de9b1214SNicolin Chen static const struct soc_enum adc1_hpf_enum =
285de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADC1_CTL3, CS53L30_ADCx_HPF_CF_SHIFT,
286de9b1214SNicolin Chen 			ARRAY_SIZE(hpf_corner_freq_text), hpf_corner_freq_text);
287de9b1214SNicolin Chen 
288de9b1214SNicolin Chen static const struct soc_enum adc2_hpf_enum =
289de9b1214SNicolin Chen 	SOC_ENUM_SINGLE(CS53L30_ADC2_CTL3, CS53L30_ADCx_HPF_CF_SHIFT,
290de9b1214SNicolin Chen 			ARRAY_SIZE(hpf_corner_freq_text), hpf_corner_freq_text);
291de9b1214SNicolin Chen 
292de9b1214SNicolin Chen static const struct snd_kcontrol_new cs53l30_snd_controls[] = {
293de9b1214SNicolin Chen 	SOC_SINGLE("Digital Soft-Ramp Switch", CS53L30_SFT_RAMP,
294de9b1214SNicolin Chen 		   CS53L30_DIGSFT_SHIFT, 1, 0),
295de9b1214SNicolin Chen 	SOC_SINGLE("ADC1 Noise Gate Ganging Switch", CS53L30_ADC1_CTL3,
296de9b1214SNicolin Chen 		   CS53L30_ADCx_NG_ALL_SHIFT, 1, 0),
297de9b1214SNicolin Chen 	SOC_SINGLE("ADC2 Noise Gate Ganging Switch", CS53L30_ADC2_CTL3,
298de9b1214SNicolin Chen 		   CS53L30_ADCx_NG_ALL_SHIFT, 1, 0),
299de9b1214SNicolin Chen 	SOC_SINGLE("ADC1A Noise Gate Enable Switch", CS53L30_ADC1_NG_CTL,
300de9b1214SNicolin Chen 		   CS53L30_ADCxA_NG_SHIFT, 1, 0),
301de9b1214SNicolin Chen 	SOC_SINGLE("ADC1B Noise Gate Enable Switch", CS53L30_ADC1_NG_CTL,
302de9b1214SNicolin Chen 		   CS53L30_ADCxB_NG_SHIFT, 1, 0),
303de9b1214SNicolin Chen 	SOC_SINGLE("ADC2A Noise Gate Enable Switch", CS53L30_ADC2_NG_CTL,
304de9b1214SNicolin Chen 		   CS53L30_ADCxA_NG_SHIFT, 1, 0),
305de9b1214SNicolin Chen 	SOC_SINGLE("ADC2B Noise Gate Enable Switch", CS53L30_ADC2_NG_CTL,
306de9b1214SNicolin Chen 		   CS53L30_ADCxB_NG_SHIFT, 1, 0),
307de9b1214SNicolin Chen 	SOC_SINGLE("ADC1 Notch Filter Switch", CS53L30_ADCDMIC1_CTL2,
308de9b1214SNicolin Chen 		   CS53L30_ADCx_NOTCH_DIS_SHIFT, 1, 1),
309de9b1214SNicolin Chen 	SOC_SINGLE("ADC2 Notch Filter Switch", CS53L30_ADCDMIC2_CTL2,
310de9b1214SNicolin Chen 		   CS53L30_ADCx_NOTCH_DIS_SHIFT, 1, 1),
311de9b1214SNicolin Chen 	SOC_SINGLE("ADC1A Invert Switch", CS53L30_ADCDMIC1_CTL2,
312de9b1214SNicolin Chen 		   CS53L30_ADCxA_INV_SHIFT, 1, 0),
313de9b1214SNicolin Chen 	SOC_SINGLE("ADC1B Invert Switch", CS53L30_ADCDMIC1_CTL2,
314de9b1214SNicolin Chen 		   CS53L30_ADCxB_INV_SHIFT, 1, 0),
315de9b1214SNicolin Chen 	SOC_SINGLE("ADC2A Invert Switch", CS53L30_ADCDMIC2_CTL2,
316de9b1214SNicolin Chen 		   CS53L30_ADCxA_INV_SHIFT, 1, 0),
317de9b1214SNicolin Chen 	SOC_SINGLE("ADC2B Invert Switch", CS53L30_ADCDMIC2_CTL2,
318de9b1214SNicolin Chen 		   CS53L30_ADCxB_INV_SHIFT, 1, 0),
319de9b1214SNicolin Chen 
320de9b1214SNicolin Chen 	SOC_SINGLE_TLV("ADC1A Digital Boost Volume", CS53L30_ADCDMIC1_CTL2,
321de9b1214SNicolin Chen 		       CS53L30_ADCxA_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),
322de9b1214SNicolin Chen 	SOC_SINGLE_TLV("ADC1B Digital Boost Volume", CS53L30_ADCDMIC1_CTL2,
323de9b1214SNicolin Chen 		       CS53L30_ADCxB_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),
324de9b1214SNicolin Chen 	SOC_SINGLE_TLV("ADC2A Digital Boost Volume", CS53L30_ADCDMIC2_CTL2,
325de9b1214SNicolin Chen 		       CS53L30_ADCxA_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),
326de9b1214SNicolin Chen 	SOC_SINGLE_TLV("ADC2B Digital Boost Volume", CS53L30_ADCDMIC2_CTL2,
327de9b1214SNicolin Chen 		       CS53L30_ADCxB_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),
328de9b1214SNicolin Chen 	SOC_SINGLE_TLV("ADC1 NG Boost Volume", CS53L30_ADC1_NG_CTL,
329de9b1214SNicolin Chen 		       CS53L30_ADCx_NG_BOOST_SHIFT, 1, 0, adc_ng_boost_tlv),
330de9b1214SNicolin Chen 	SOC_SINGLE_TLV("ADC2 NG Boost Volume", CS53L30_ADC2_NG_CTL,
331de9b1214SNicolin Chen 		       CS53L30_ADCx_NG_BOOST_SHIFT, 1, 0, adc_ng_boost_tlv),
332de9b1214SNicolin Chen 
333b97c4446SNicolin Chen 	SOC_DOUBLE_R_TLV("ADC1 Preamplifier Volume", CS53L30_ADC1A_AFE_CTL,
334de9b1214SNicolin Chen 			 CS53L30_ADC1B_AFE_CTL, CS53L30_ADCxy_PREAMP_SHIFT,
335de9b1214SNicolin Chen 			 2, 0, pga_preamp_tlv),
336b97c4446SNicolin Chen 	SOC_DOUBLE_R_TLV("ADC2 Preamplifier Volume", CS53L30_ADC2A_AFE_CTL,
337de9b1214SNicolin Chen 			 CS53L30_ADC2B_AFE_CTL, CS53L30_ADCxy_PREAMP_SHIFT,
338de9b1214SNicolin Chen 			 2, 0, pga_preamp_tlv),
339de9b1214SNicolin Chen 
340de9b1214SNicolin Chen 	SOC_ENUM("Input 1 Channel Select", input1_sel_enum),
341de9b1214SNicolin Chen 	SOC_ENUM("Input 2 Channel Select", input2_sel_enum),
342de9b1214SNicolin Chen 
343de9b1214SNicolin Chen 	SOC_ENUM("ADC1 HPF Select", adc1_hpf_enum),
344de9b1214SNicolin Chen 	SOC_ENUM("ADC2 HPF Select", adc2_hpf_enum),
345de9b1214SNicolin Chen 	SOC_ENUM("ADC1 NG Threshold", adc1_ng_thres_enum),
346de9b1214SNicolin Chen 	SOC_ENUM("ADC2 NG Threshold", adc2_ng_thres_enum),
347de9b1214SNicolin Chen 	SOC_ENUM("ADC1 NG Delay", adc1_ng_delay_enum),
348de9b1214SNicolin Chen 	SOC_ENUM("ADC2 NG Delay", adc2_ng_delay_enum),
349de9b1214SNicolin Chen 
350de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC1A PGA Volume",
3517fbd6dd6SCharles Keepax 		    CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
352de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC1B PGA Volume",
3537fbd6dd6SCharles Keepax 		    CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
354de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC2A PGA Volume",
3557fbd6dd6SCharles Keepax 		    CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
356de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC2B PGA Volume",
3577fbd6dd6SCharles Keepax 		    CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),
358de9b1214SNicolin Chen 
359de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC1A Digital Volume",
3607fbd6dd6SCharles Keepax 		    CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
361de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC1B Digital Volume",
3627fbd6dd6SCharles Keepax 		    CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
363de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC2A Digital Volume",
3647fbd6dd6SCharles Keepax 		    CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
365de9b1214SNicolin Chen 	SOC_SINGLE_SX_TLV("ADC2B Digital Volume",
3667fbd6dd6SCharles Keepax 		    CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),
367de9b1214SNicolin Chen };
368de9b1214SNicolin Chen 
369de9b1214SNicolin Chen static const struct snd_soc_dapm_widget cs53l30_dapm_widgets[] = {
370de9b1214SNicolin Chen 	SND_SOC_DAPM_INPUT("IN1_DMIC1"),
371de9b1214SNicolin Chen 	SND_SOC_DAPM_INPUT("IN2"),
372de9b1214SNicolin Chen 	SND_SOC_DAPM_INPUT("IN3_DMIC2"),
373de9b1214SNicolin Chen 	SND_SOC_DAPM_INPUT("IN4"),
374de9b1214SNicolin Chen 	SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS53L30_MICBIAS_CTL,
375de9b1214SNicolin Chen 			    CS53L30_MIC1_BIAS_PDN_SHIFT, 1, NULL, 0),
376de9b1214SNicolin Chen 	SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS53L30_MICBIAS_CTL,
377de9b1214SNicolin Chen 			    CS53L30_MIC2_BIAS_PDN_SHIFT, 1, NULL, 0),
378de9b1214SNicolin Chen 	SND_SOC_DAPM_SUPPLY("MIC3 Bias", CS53L30_MICBIAS_CTL,
379de9b1214SNicolin Chen 			    CS53L30_MIC3_BIAS_PDN_SHIFT, 1, NULL, 0),
380de9b1214SNicolin Chen 	SND_SOC_DAPM_SUPPLY("MIC4 Bias", CS53L30_MICBIAS_CTL,
381de9b1214SNicolin Chen 			    CS53L30_MIC4_BIAS_PDN_SHIFT, 1, NULL, 0),
382de9b1214SNicolin Chen 
383de9b1214SNicolin Chen 	SND_SOC_DAPM_AIF_OUT("ASP_SDOUT1", NULL, 0, CS53L30_ASP_CTL1,
384de9b1214SNicolin Chen 			     CS53L30_ASP_SDOUTx_PDN_SHIFT, 1),
385de9b1214SNicolin Chen 	SND_SOC_DAPM_AIF_OUT("ASP_SDOUT2", NULL, 0, CS53L30_ASP_CTL2,
386de9b1214SNicolin Chen 			     CS53L30_ASP_SDOUTx_PDN_SHIFT, 1),
387de9b1214SNicolin Chen 
388de9b1214SNicolin Chen 	SND_SOC_DAPM_MUX("Input Mux 1", SND_SOC_NOPM, 0, 0,
389de9b1214SNicolin Chen 			 &input1_route_sel_mux),
390de9b1214SNicolin Chen 	SND_SOC_DAPM_MUX("Input Mux 2", SND_SOC_NOPM, 0, 0,
391de9b1214SNicolin Chen 			 &input2_route_sel_mux),
392de9b1214SNicolin Chen 
393de9b1214SNicolin Chen 	SND_SOC_DAPM_ADC("ADC1A", NULL, CS53L30_ADCDMIC1_CTL1,
394de9b1214SNicolin Chen 			 CS53L30_ADCxA_PDN_SHIFT, 1),
395de9b1214SNicolin Chen 	SND_SOC_DAPM_ADC("ADC1B", NULL, CS53L30_ADCDMIC1_CTL1,
396de9b1214SNicolin Chen 			 CS53L30_ADCxB_PDN_SHIFT, 1),
397de9b1214SNicolin Chen 	SND_SOC_DAPM_ADC("ADC2A", NULL, CS53L30_ADCDMIC2_CTL1,
398de9b1214SNicolin Chen 			 CS53L30_ADCxA_PDN_SHIFT, 1),
399de9b1214SNicolin Chen 	SND_SOC_DAPM_ADC("ADC2B", NULL, CS53L30_ADCDMIC2_CTL1,
400de9b1214SNicolin Chen 			 CS53L30_ADCxB_PDN_SHIFT, 1),
401de9b1214SNicolin Chen 	SND_SOC_DAPM_ADC("DMIC1", NULL, CS53L30_ADCDMIC1_CTL1,
402de9b1214SNicolin Chen 			 CS53L30_DMICx_PDN_SHIFT, 1),
403de9b1214SNicolin Chen 	SND_SOC_DAPM_ADC("DMIC2", NULL, CS53L30_ADCDMIC2_CTL1,
404de9b1214SNicolin Chen 			 CS53L30_DMICx_PDN_SHIFT, 1),
405de9b1214SNicolin Chen };
406de9b1214SNicolin Chen 
407de9b1214SNicolin Chen static const struct snd_soc_dapm_route cs53l30_dapm_routes[] = {
408de9b1214SNicolin Chen 	/* ADC Input Paths */
409de9b1214SNicolin Chen 	{"ADC1A", NULL, "IN1_DMIC1"},
410de9b1214SNicolin Chen 	{"Input Mux 1", "ADC1_SEL", "ADC1A"},
411de9b1214SNicolin Chen 	{"ADC1B", NULL, "IN2"},
412de9b1214SNicolin Chen 
413de9b1214SNicolin Chen 	{"ADC2A", NULL, "IN3_DMIC2"},
414de9b1214SNicolin Chen 	{"Input Mux 2", "ADC2_SEL", "ADC2A"},
415de9b1214SNicolin Chen 	{"ADC2B", NULL, "IN4"},
416de9b1214SNicolin Chen 
417de9b1214SNicolin Chen 	/* MIC Bias Paths */
418de9b1214SNicolin Chen 	{"ADC1A", NULL, "MIC1 Bias"},
419de9b1214SNicolin Chen 	{"ADC1B", NULL, "MIC2 Bias"},
420de9b1214SNicolin Chen 	{"ADC2A", NULL, "MIC3 Bias"},
421de9b1214SNicolin Chen 	{"ADC2B", NULL, "MIC4 Bias"},
422de9b1214SNicolin Chen 
423de9b1214SNicolin Chen 	/* DMIC Paths */
424de9b1214SNicolin Chen 	{"DMIC1", NULL, "IN1_DMIC1"},
425de9b1214SNicolin Chen 	{"Input Mux 1", "DMIC1_SEL", "DMIC1"},
426de9b1214SNicolin Chen 
427de9b1214SNicolin Chen 	{"DMIC2", NULL, "IN3_DMIC2"},
428de9b1214SNicolin Chen 	{"Input Mux 2", "DMIC2_SEL", "DMIC2"},
429de9b1214SNicolin Chen };
430de9b1214SNicolin Chen 
431de9b1214SNicolin Chen static const struct snd_soc_dapm_route cs53l30_dapm_routes_sdout1[] = {
432de9b1214SNicolin Chen 	/* Output Paths when using SDOUT1 only */
433de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "ADC1A" },
434de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "Input Mux 1"},
435de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "ADC1B"},
436de9b1214SNicolin Chen 
437de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "ADC2A"},
438de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "Input Mux 2"},
439de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "ADC2B"},
440de9b1214SNicolin Chen 
441de9b1214SNicolin Chen 	{"Capture", NULL, "ASP_SDOUT1"},
442de9b1214SNicolin Chen };
443de9b1214SNicolin Chen 
444de9b1214SNicolin Chen static const struct snd_soc_dapm_route cs53l30_dapm_routes_sdout2[] = {
445de9b1214SNicolin Chen 	/* Output Paths when using both SDOUT1 and SDOUT2 */
446de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "ADC1A" },
447de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "Input Mux 1"},
448de9b1214SNicolin Chen 	{"ASP_SDOUT1", NULL, "ADC1B"},
449de9b1214SNicolin Chen 
450de9b1214SNicolin Chen 	{"ASP_SDOUT2", NULL, "ADC2A"},
451de9b1214SNicolin Chen 	{"ASP_SDOUT2", NULL, "Input Mux 2"},
452de9b1214SNicolin Chen 	{"ASP_SDOUT2", NULL, "ADC2B"},
453de9b1214SNicolin Chen 
454de9b1214SNicolin Chen 	{"Capture", NULL, "ASP_SDOUT1"},
455de9b1214SNicolin Chen 	{"Capture", NULL, "ASP_SDOUT2"},
456de9b1214SNicolin Chen };
457de9b1214SNicolin Chen 
458de9b1214SNicolin Chen struct cs53l30_mclk_div {
459de9b1214SNicolin Chen 	u32 mclk_rate;
460de9b1214SNicolin Chen 	u32 srate;
461de9b1214SNicolin Chen 	u8 asp_rate;
462de9b1214SNicolin Chen 	u8 internal_fs_ratio;
463de9b1214SNicolin Chen 	u8 mclk_int_scale;
464de9b1214SNicolin Chen };
465de9b1214SNicolin Chen 
4663597fcedSAxel Lin static const struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = {
467de9b1214SNicolin Chen 	/* NOTE: Enable MCLK_INT_SCALE to save power. */
468de9b1214SNicolin Chen 
469de9b1214SNicolin Chen 	/* MCLK, Sample Rate, asp_rate, internal_fs_ratio, mclk_int_scale */
470de9b1214SNicolin Chen 	{5644800, 11025, 0x4, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
471de9b1214SNicolin Chen 	{5644800, 22050, 0x8, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
472de9b1214SNicolin Chen 	{5644800, 44100, 0xC, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
473de9b1214SNicolin Chen 
474de9b1214SNicolin Chen 	{6000000,  8000, 0x1, 0, CS53L30_MCLK_INT_SCALE},
475de9b1214SNicolin Chen 	{6000000, 11025, 0x2, 0, CS53L30_MCLK_INT_SCALE},
476de9b1214SNicolin Chen 	{6000000, 12000, 0x4, 0, CS53L30_MCLK_INT_SCALE},
477de9b1214SNicolin Chen 	{6000000, 16000, 0x5, 0, CS53L30_MCLK_INT_SCALE},
478de9b1214SNicolin Chen 	{6000000, 22050, 0x6, 0, CS53L30_MCLK_INT_SCALE},
479de9b1214SNicolin Chen 	{6000000, 24000, 0x8, 0, CS53L30_MCLK_INT_SCALE},
480de9b1214SNicolin Chen 	{6000000, 32000, 0x9, 0, CS53L30_MCLK_INT_SCALE},
481de9b1214SNicolin Chen 	{6000000, 44100, 0xA, 0, CS53L30_MCLK_INT_SCALE},
482de9b1214SNicolin Chen 	{6000000, 48000, 0xC, 0, CS53L30_MCLK_INT_SCALE},
483de9b1214SNicolin Chen 
484de9b1214SNicolin Chen 	{6144000,  8000, 0x1, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
485de9b1214SNicolin Chen 	{6144000, 11025, 0x2, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
486de9b1214SNicolin Chen 	{6144000, 12000, 0x4, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
487de9b1214SNicolin Chen 	{6144000, 16000, 0x5, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
488de9b1214SNicolin Chen 	{6144000, 22050, 0x6, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
489de9b1214SNicolin Chen 	{6144000, 24000, 0x8, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
490de9b1214SNicolin Chen 	{6144000, 32000, 0x9, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
491de9b1214SNicolin Chen 	{6144000, 44100, 0xA, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
492de9b1214SNicolin Chen 	{6144000, 48000, 0xC, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
493de9b1214SNicolin Chen 
494de9b1214SNicolin Chen 	{6400000,  8000, 0x1, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
495de9b1214SNicolin Chen 	{6400000, 11025, 0x2, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
496de9b1214SNicolin Chen 	{6400000, 12000, 0x4, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
497de9b1214SNicolin Chen 	{6400000, 16000, 0x5, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
498de9b1214SNicolin Chen 	{6400000, 22050, 0x6, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
499de9b1214SNicolin Chen 	{6400000, 24000, 0x8, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
500de9b1214SNicolin Chen 	{6400000, 32000, 0x9, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
501de9b1214SNicolin Chen 	{6400000, 44100, 0xA, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
502de9b1214SNicolin Chen 	{6400000, 48000, 0xC, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},
503de9b1214SNicolin Chen };
504de9b1214SNicolin Chen 
505de9b1214SNicolin Chen struct cs53l30_mclkx_div {
506de9b1214SNicolin Chen 	u32 mclkx;
507de9b1214SNicolin Chen 	u8 ratio;
508de9b1214SNicolin Chen 	u8 mclkdiv;
509de9b1214SNicolin Chen };
510de9b1214SNicolin Chen 
5113597fcedSAxel Lin static const struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = {
512de9b1214SNicolin Chen 	{5644800,  1, CS53L30_MCLK_DIV_BY_1},
513de9b1214SNicolin Chen 	{6000000,  1, CS53L30_MCLK_DIV_BY_1},
514de9b1214SNicolin Chen 	{6144000,  1, CS53L30_MCLK_DIV_BY_1},
515de9b1214SNicolin Chen 	{11289600, 2, CS53L30_MCLK_DIV_BY_2},
516de9b1214SNicolin Chen 	{12288000, 2, CS53L30_MCLK_DIV_BY_2},
517de9b1214SNicolin Chen 	{12000000, 2, CS53L30_MCLK_DIV_BY_2},
518de9b1214SNicolin Chen 	{19200000, 3, CS53L30_MCLK_DIV_BY_3},
519de9b1214SNicolin Chen };
520de9b1214SNicolin Chen 
cs53l30_get_mclkx_coeff(int mclkx)521de9b1214SNicolin Chen static int cs53l30_get_mclkx_coeff(int mclkx)
522de9b1214SNicolin Chen {
523de9b1214SNicolin Chen 	int i;
524de9b1214SNicolin Chen 
525de9b1214SNicolin Chen 	for (i = 0; i < ARRAY_SIZE(cs53l30_mclkx_coeffs); i++) {
526de9b1214SNicolin Chen 		if (cs53l30_mclkx_coeffs[i].mclkx == mclkx)
527de9b1214SNicolin Chen 			return i;
528de9b1214SNicolin Chen 	}
529de9b1214SNicolin Chen 
530de9b1214SNicolin Chen 	return -EINVAL;
531de9b1214SNicolin Chen }
532de9b1214SNicolin Chen 
cs53l30_get_mclk_coeff(int mclk_rate,int srate)533de9b1214SNicolin Chen static int cs53l30_get_mclk_coeff(int mclk_rate, int srate)
534de9b1214SNicolin Chen {
535de9b1214SNicolin Chen 	int i;
536de9b1214SNicolin Chen 
537de9b1214SNicolin Chen 	for (i = 0; i < ARRAY_SIZE(cs53l30_mclk_coeffs); i++) {
538de9b1214SNicolin Chen 		if (cs53l30_mclk_coeffs[i].mclk_rate == mclk_rate &&
539de9b1214SNicolin Chen 		    cs53l30_mclk_coeffs[i].srate == srate)
540de9b1214SNicolin Chen 			return i;
541de9b1214SNicolin Chen 	}
542de9b1214SNicolin Chen 
543de9b1214SNicolin Chen 	return -EINVAL;
544de9b1214SNicolin Chen }
545de9b1214SNicolin Chen 
cs53l30_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)546de9b1214SNicolin Chen static int cs53l30_set_sysclk(struct snd_soc_dai *dai,
547de9b1214SNicolin Chen 			      int clk_id, unsigned int freq, int dir)
548de9b1214SNicolin Chen {
549534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);
550de9b1214SNicolin Chen 	int mclkx_coeff;
551de9b1214SNicolin Chen 	u32 mclk_rate;
552de9b1214SNicolin Chen 
553de9b1214SNicolin Chen 	/* MCLKX -> MCLK */
554de9b1214SNicolin Chen 	mclkx_coeff = cs53l30_get_mclkx_coeff(freq);
555de9b1214SNicolin Chen 	if (mclkx_coeff < 0)
556de9b1214SNicolin Chen 		return mclkx_coeff;
557de9b1214SNicolin Chen 
558de9b1214SNicolin Chen 	mclk_rate = cs53l30_mclkx_coeffs[mclkx_coeff].mclkx /
559de9b1214SNicolin Chen 		    cs53l30_mclkx_coeffs[mclkx_coeff].ratio;
560de9b1214SNicolin Chen 
561de9b1214SNicolin Chen 	regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,
562de9b1214SNicolin Chen 			   CS53L30_MCLK_DIV_MASK,
563de9b1214SNicolin Chen 			   cs53l30_mclkx_coeffs[mclkx_coeff].mclkdiv);
564de9b1214SNicolin Chen 
565de9b1214SNicolin Chen 	priv->mclk_rate = mclk_rate;
566de9b1214SNicolin Chen 
567de9b1214SNicolin Chen 	return 0;
568de9b1214SNicolin Chen }
569de9b1214SNicolin Chen 
cs53l30_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)570de9b1214SNicolin Chen static int cs53l30_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
571de9b1214SNicolin Chen {
572534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);
573de9b1214SNicolin Chen 	u8 aspcfg = 0, aspctl1 = 0;
574de9b1214SNicolin Chen 
575de9b1214SNicolin Chen 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
576de9b1214SNicolin Chen 	case SND_SOC_DAIFMT_CBM_CFM:
577de9b1214SNicolin Chen 		aspcfg |= CS53L30_ASP_MS;
578de9b1214SNicolin Chen 		break;
579de9b1214SNicolin Chen 	case SND_SOC_DAIFMT_CBS_CFS:
580de9b1214SNicolin Chen 		break;
581de9b1214SNicolin Chen 	default:
582de9b1214SNicolin Chen 		return -EINVAL;
583de9b1214SNicolin Chen 	}
584de9b1214SNicolin Chen 
585de9b1214SNicolin Chen 	/* DAI mode */
586de9b1214SNicolin Chen 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
587de9b1214SNicolin Chen 	case SND_SOC_DAIFMT_I2S:
588de9b1214SNicolin Chen 		/* Set TDM_PDN to turn off TDM mode -- Reset default */
589de9b1214SNicolin Chen 		aspctl1 |= CS53L30_ASP_TDM_PDN;
590de9b1214SNicolin Chen 		break;
591de9b1214SNicolin Chen 	case SND_SOC_DAIFMT_DSP_A:
5921708796fSNicolin Chen 		/*
5931708796fSNicolin Chen 		 * Clear TDM_PDN to turn on TDM mode; Use ASP_SCLK_INV = 0
5941708796fSNicolin Chen 		 * with SHIFT_LEFT = 1 combination as Figure 4-13 shows in
5951708796fSNicolin Chen 		 * the CS53L30 datasheet
5961708796fSNicolin Chen 		 */
5971708796fSNicolin Chen 		aspctl1 |= CS53L30_SHIFT_LEFT;
598de9b1214SNicolin Chen 		break;
599de9b1214SNicolin Chen 	default:
600de9b1214SNicolin Chen 		return -EINVAL;
601de9b1214SNicolin Chen 	}
602de9b1214SNicolin Chen 
603de9b1214SNicolin Chen 	/* Check to see if the SCLK is inverted */
60488b1c01fSNicolin Chen 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
60588b1c01fSNicolin Chen 	case SND_SOC_DAIFMT_IB_NF:
60688b1c01fSNicolin Chen 	case SND_SOC_DAIFMT_IB_IF:
607de9b1214SNicolin Chen 		aspcfg ^= CS53L30_ASP_SCLK_INV;
60888b1c01fSNicolin Chen 		break;
60988b1c01fSNicolin Chen 	default:
61088b1c01fSNicolin Chen 		break;
61188b1c01fSNicolin Chen 	}
612de9b1214SNicolin Chen 
613de9b1214SNicolin Chen 	regmap_update_bits(priv->regmap, CS53L30_ASPCFG_CTL,
614de9b1214SNicolin Chen 			   CS53L30_ASP_MS | CS53L30_ASP_SCLK_INV, aspcfg);
615de9b1214SNicolin Chen 
616de9b1214SNicolin Chen 	regmap_update_bits(priv->regmap, CS53L30_ASP_CTL1,
617de9b1214SNicolin Chen 			   CS53L30_ASP_TDM_PDN | CS53L30_SHIFT_LEFT, aspctl1);
618de9b1214SNicolin Chen 
619de9b1214SNicolin Chen 	return 0;
620de9b1214SNicolin Chen }
621de9b1214SNicolin Chen 
cs53l30_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)622de9b1214SNicolin Chen static int cs53l30_pcm_hw_params(struct snd_pcm_substream *substream,
623de9b1214SNicolin Chen 				 struct snd_pcm_hw_params *params,
624de9b1214SNicolin Chen 				 struct snd_soc_dai *dai)
625de9b1214SNicolin Chen {
626534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);
627de9b1214SNicolin Chen 	int srate = params_rate(params);
628de9b1214SNicolin Chen 	int mclk_coeff;
629de9b1214SNicolin Chen 
630de9b1214SNicolin Chen 	/* MCLK -> srate */
631de9b1214SNicolin Chen 	mclk_coeff = cs53l30_get_mclk_coeff(priv->mclk_rate, srate);
632de9b1214SNicolin Chen 	if (mclk_coeff < 0)
633de9b1214SNicolin Chen 		return -EINVAL;
634de9b1214SNicolin Chen 
635de9b1214SNicolin Chen 	regmap_update_bits(priv->regmap, CS53L30_INT_SR_CTL,
636de9b1214SNicolin Chen 			   CS53L30_INTRNL_FS_RATIO_MASK,
637de9b1214SNicolin Chen 			   cs53l30_mclk_coeffs[mclk_coeff].internal_fs_ratio);
638de9b1214SNicolin Chen 
639de9b1214SNicolin Chen 	regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,
640de9b1214SNicolin Chen 			   CS53L30_MCLK_INT_SCALE_MASK,
641de9b1214SNicolin Chen 			   cs53l30_mclk_coeffs[mclk_coeff].mclk_int_scale);
642de9b1214SNicolin Chen 
643de9b1214SNicolin Chen 	regmap_update_bits(priv->regmap, CS53L30_ASPCFG_CTL,
644de9b1214SNicolin Chen 			   CS53L30_ASP_RATE_MASK,
645de9b1214SNicolin Chen 			   cs53l30_mclk_coeffs[mclk_coeff].asp_rate);
646de9b1214SNicolin Chen 
647de9b1214SNicolin Chen 	return 0;
648de9b1214SNicolin Chen }
649de9b1214SNicolin Chen 
cs53l30_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)650534cf41cSKuninori Morimoto static int cs53l30_set_bias_level(struct snd_soc_component *component,
651de9b1214SNicolin Chen 				  enum snd_soc_bias_level level)
652de9b1214SNicolin Chen {
653534cf41cSKuninori Morimoto 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
654534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(component);
655de9b1214SNicolin Chen 	unsigned int reg;
656de9b1214SNicolin Chen 	int i, inter_max_check, ret;
657de9b1214SNicolin Chen 
658de9b1214SNicolin Chen 	switch (level) {
659de9b1214SNicolin Chen 	case SND_SOC_BIAS_ON:
660de9b1214SNicolin Chen 		break;
661de9b1214SNicolin Chen 	case SND_SOC_BIAS_PREPARE:
662de9b1214SNicolin Chen 		if (dapm->bias_level == SND_SOC_BIAS_STANDBY)
663de9b1214SNicolin Chen 			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
664de9b1214SNicolin Chen 					   CS53L30_PDN_LP_MASK, 0);
665de9b1214SNicolin Chen 		break;
666de9b1214SNicolin Chen 	case SND_SOC_BIAS_STANDBY:
667de9b1214SNicolin Chen 		if (dapm->bias_level == SND_SOC_BIAS_OFF) {
668de9b1214SNicolin Chen 			ret = clk_prepare_enable(priv->mclk);
669de9b1214SNicolin Chen 			if (ret) {
670534cf41cSKuninori Morimoto 				dev_err(component->dev,
671de9b1214SNicolin Chen 					"failed to enable MCLK: %d\n", ret);
672de9b1214SNicolin Chen 				return ret;
673de9b1214SNicolin Chen 			}
674de9b1214SNicolin Chen 			regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,
675de9b1214SNicolin Chen 					   CS53L30_MCLK_DIS_MASK, 0);
676de9b1214SNicolin Chen 			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
677de9b1214SNicolin Chen 					   CS53L30_PDN_ULP_MASK, 0);
678de9b1214SNicolin Chen 			msleep(50);
679de9b1214SNicolin Chen 		} else {
680de9b1214SNicolin Chen 			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
681de9b1214SNicolin Chen 					   CS53L30_PDN_ULP_MASK,
682de9b1214SNicolin Chen 					   CS53L30_PDN_ULP);
683de9b1214SNicolin Chen 		}
684de9b1214SNicolin Chen 		break;
685de9b1214SNicolin Chen 	case SND_SOC_BIAS_OFF:
686de9b1214SNicolin Chen 		regmap_update_bits(priv->regmap, CS53L30_INT_MASK,
687de9b1214SNicolin Chen 				   CS53L30_PDN_DONE, 0);
688de9b1214SNicolin Chen 		/*
689de9b1214SNicolin Chen 		 * If digital softramp is set, the amount of time required
690de9b1214SNicolin Chen 		 * for power down increases and depends on the digital
691de9b1214SNicolin Chen 		 * volume setting.
692de9b1214SNicolin Chen 		 */
693de9b1214SNicolin Chen 
694de9b1214SNicolin Chen 		/* Set the max possible time if digsft is set */
695de9b1214SNicolin Chen 		regmap_read(priv->regmap, CS53L30_SFT_RAMP, &reg);
696de9b1214SNicolin Chen 		if (reg & CS53L30_DIGSFT_MASK)
697de9b1214SNicolin Chen 			inter_max_check = CS53L30_PDN_POLL_MAX;
698de9b1214SNicolin Chen 		else
699de9b1214SNicolin Chen 			inter_max_check = 10;
700de9b1214SNicolin Chen 
701de9b1214SNicolin Chen 		regmap_update_bits(priv->regmap, CS53L30_PWRCTL,
702de9b1214SNicolin Chen 				   CS53L30_PDN_ULP_MASK,
703de9b1214SNicolin Chen 				   CS53L30_PDN_ULP);
704de9b1214SNicolin Chen 		/* PDN_DONE will take a min of 20ms to be set.*/
705de9b1214SNicolin Chen 		msleep(20);
706de9b1214SNicolin Chen 		/* Clr status */
707de9b1214SNicolin Chen 		regmap_read(priv->regmap, CS53L30_IS, &reg);
708de9b1214SNicolin Chen 		for (i = 0; i < inter_max_check; i++) {
709de9b1214SNicolin Chen 			if (inter_max_check < 10) {
710de9b1214SNicolin Chen 				usleep_range(1000, 1100);
711de9b1214SNicolin Chen 				regmap_read(priv->regmap, CS53L30_IS, &reg);
712de9b1214SNicolin Chen 				if (reg & CS53L30_PDN_DONE)
713de9b1214SNicolin Chen 					break;
714de9b1214SNicolin Chen 			} else {
715de9b1214SNicolin Chen 				usleep_range(10000, 10100);
716de9b1214SNicolin Chen 				regmap_read(priv->regmap, CS53L30_IS, &reg);
717de9b1214SNicolin Chen 				if (reg & CS53L30_PDN_DONE)
718de9b1214SNicolin Chen 					break;
719de9b1214SNicolin Chen 			}
720de9b1214SNicolin Chen 		}
721de9b1214SNicolin Chen 		/* PDN_DONE is set. We now can disable the MCLK */
722de9b1214SNicolin Chen 		regmap_update_bits(priv->regmap, CS53L30_INT_MASK,
723de9b1214SNicolin Chen 				   CS53L30_PDN_DONE, CS53L30_PDN_DONE);
724de9b1214SNicolin Chen 		regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,
725de9b1214SNicolin Chen 				   CS53L30_MCLK_DIS_MASK,
726de9b1214SNicolin Chen 				   CS53L30_MCLK_DIS);
727de9b1214SNicolin Chen 		clk_disable_unprepare(priv->mclk);
728de9b1214SNicolin Chen 		break;
729de9b1214SNicolin Chen 	}
730de9b1214SNicolin Chen 
731de9b1214SNicolin Chen 	return 0;
732de9b1214SNicolin Chen }
733de9b1214SNicolin Chen 
cs53l30_set_tristate(struct snd_soc_dai * dai,int tristate)734de9b1214SNicolin Chen static int cs53l30_set_tristate(struct snd_soc_dai *dai, int tristate)
735de9b1214SNicolin Chen {
736534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);
737de9b1214SNicolin Chen 	u8 val = tristate ? CS53L30_ASP_3ST : 0;
738de9b1214SNicolin Chen 
739de9b1214SNicolin Chen 	return regmap_update_bits(priv->regmap, CS53L30_ASP_CTL1,
740de9b1214SNicolin Chen 				  CS53L30_ASP_3ST_MASK, val);
741de9b1214SNicolin Chen }
742de9b1214SNicolin Chen 
743ee85be8cSWei Yongjun static unsigned int const cs53l30_src_rates[] = {
744de9b1214SNicolin Chen 	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
745de9b1214SNicolin Chen };
746de9b1214SNicolin Chen 
74792f468d2STakashi Iwai static const struct snd_pcm_hw_constraint_list src_constraints = {
748de9b1214SNicolin Chen 	.count = ARRAY_SIZE(cs53l30_src_rates),
749de9b1214SNicolin Chen 	.list = cs53l30_src_rates,
750de9b1214SNicolin Chen };
751de9b1214SNicolin Chen 
cs53l30_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)752de9b1214SNicolin Chen static int cs53l30_pcm_startup(struct snd_pcm_substream *substream,
753de9b1214SNicolin Chen 			       struct snd_soc_dai *dai)
754de9b1214SNicolin Chen {
755de9b1214SNicolin Chen 	snd_pcm_hw_constraint_list(substream->runtime, 0,
756de9b1214SNicolin Chen 				   SNDRV_PCM_HW_PARAM_RATE, &src_constraints);
757de9b1214SNicolin Chen 
758de9b1214SNicolin Chen 	return 0;
759de9b1214SNicolin Chen }
760de9b1214SNicolin Chen 
761de9b1214SNicolin Chen /*
762de9b1214SNicolin Chen  * Note: CS53L30 counts the slot number per byte while ASoC counts the slot
763de9b1214SNicolin Chen  * number per slot_width. So there is a difference between the slots of ASoC
764de9b1214SNicolin Chen  * and the slots of CS53L30.
765de9b1214SNicolin Chen  */
cs53l30_set_dai_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)766de9b1214SNicolin Chen static int cs53l30_set_dai_tdm_slot(struct snd_soc_dai *dai,
767de9b1214SNicolin Chen 				    unsigned int tx_mask, unsigned int rx_mask,
768de9b1214SNicolin Chen 				    int slots, int slot_width)
769de9b1214SNicolin Chen {
770534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);
771de9b1214SNicolin Chen 	unsigned int loc[CS53L30_TDM_SLOT_MAX] = {48, 48, 48, 48};
772de9b1214SNicolin Chen 	unsigned int slot_next, slot_step;
773de9b1214SNicolin Chen 	u64 tx_enable = 0;
774de9b1214SNicolin Chen 	int i;
775de9b1214SNicolin Chen 
776de9b1214SNicolin Chen 	if (!rx_mask) {
777de9b1214SNicolin Chen 		dev_err(dai->dev, "rx masks must not be 0\n");
778de9b1214SNicolin Chen 		return -EINVAL;
779de9b1214SNicolin Chen 	}
780de9b1214SNicolin Chen 
781de9b1214SNicolin Chen 	/* Assuming slot_width is not supposed to be greater than 64 */
782de9b1214SNicolin Chen 	if (slots <= 0 || slot_width <= 0 || slot_width > 64) {
783de9b1214SNicolin Chen 		dev_err(dai->dev, "invalid slot number or slot width\n");
784de9b1214SNicolin Chen 		return -EINVAL;
785de9b1214SNicolin Chen 	}
786de9b1214SNicolin Chen 
787de9b1214SNicolin Chen 	if (slot_width & 0x7) {
788de9b1214SNicolin Chen 		dev_err(dai->dev, "slot width must count in byte\n");
789de9b1214SNicolin Chen 		return -EINVAL;
790de9b1214SNicolin Chen 	}
791de9b1214SNicolin Chen 
792de9b1214SNicolin Chen 	/* How many bytes in each ASoC slot */
793de9b1214SNicolin Chen 	slot_step = slot_width >> 3;
794de9b1214SNicolin Chen 
795de9b1214SNicolin Chen 	for (i = 0; rx_mask && i < CS53L30_TDM_SLOT_MAX; i++) {
796de9b1214SNicolin Chen 		/* Find the first slot from LSB */
797de9b1214SNicolin Chen 		slot_next = __ffs(rx_mask);
798de9b1214SNicolin Chen 		/* Save the slot location by converting to CS53L30 slot */
799de9b1214SNicolin Chen 		loc[i] = slot_next * slot_step;
800de9b1214SNicolin Chen 		/* Create the mask of CS53L30 slot */
801de9b1214SNicolin Chen 		tx_enable |= (u64)((u64)(1 << slot_step) - 1) << (u64)loc[i];
802de9b1214SNicolin Chen 		/* Clear this slot from rx_mask */
803de9b1214SNicolin Chen 		rx_mask &= ~(1 << slot_next);
804de9b1214SNicolin Chen 	}
805de9b1214SNicolin Chen 
806de9b1214SNicolin Chen 	/* Error out to avoid slot shift */
807de9b1214SNicolin Chen 	if (rx_mask && i == CS53L30_TDM_SLOT_MAX) {
808de9b1214SNicolin Chen 		dev_err(dai->dev, "rx_mask exceeds max slot number: %d\n",
809de9b1214SNicolin Chen 			CS53L30_TDM_SLOT_MAX);
810de9b1214SNicolin Chen 		return -EINVAL;
811de9b1214SNicolin Chen 	}
812de9b1214SNicolin Chen 
81362201937SNicolin Chen 	/* Validate the last active CS53L30 slot */
81462201937SNicolin Chen 	slot_next = loc[i - 1] + slot_step - 1;
815de9b1214SNicolin Chen 	if (slot_next > 47) {
816de9b1214SNicolin Chen 		dev_err(dai->dev, "slot selection out of bounds: %u\n",
817de9b1214SNicolin Chen 			slot_next);
818de9b1214SNicolin Chen 		return -EINVAL;
819de9b1214SNicolin Chen 	}
820de9b1214SNicolin Chen 
821de9b1214SNicolin Chen 	for (i = 0; i < CS53L30_TDM_SLOT_MAX && loc[i] != 48; i++) {
822de9b1214SNicolin Chen 		regmap_update_bits(priv->regmap, CS53L30_ASP_TDMTX_CTL(i),
823de9b1214SNicolin Chen 				   CS53L30_ASP_CHx_TX_LOC_MASK, loc[i]);
824de9b1214SNicolin Chen 		dev_dbg(dai->dev, "loc[%d]=%x\n", i, loc[i]);
825de9b1214SNicolin Chen 	}
826de9b1214SNicolin Chen 
827de9b1214SNicolin Chen 	for (i = 0; i < CS53L30_ASP_TDMTX_ENx_MAX && tx_enable; i++) {
828de9b1214SNicolin Chen 		regmap_write(priv->regmap, CS53L30_ASP_TDMTX_ENx(i),
829de9b1214SNicolin Chen 			     tx_enable & 0xff);
830de9b1214SNicolin Chen 		tx_enable >>= 8;
831de9b1214SNicolin Chen 		dev_dbg(dai->dev, "en_reg=%x, tx_enable=%llx\n",
832de9b1214SNicolin Chen 			CS53L30_ASP_TDMTX_ENx(i), tx_enable & 0xff);
833de9b1214SNicolin Chen 	}
834de9b1214SNicolin Chen 
835de9b1214SNicolin Chen 	return 0;
836de9b1214SNicolin Chen }
837de9b1214SNicolin Chen 
cs53l30_mute_stream(struct snd_soc_dai * dai,int mute,int stream)83805f33bc5SNicolin Chen static int cs53l30_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
83905f33bc5SNicolin Chen {
840534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);
84105f33bc5SNicolin Chen 
84205f33bc5SNicolin Chen 	gpiod_set_value_cansleep(priv->mute_gpio, mute);
84305f33bc5SNicolin Chen 
84405f33bc5SNicolin Chen 	return 0;
84505f33bc5SNicolin Chen }
84605f33bc5SNicolin Chen 
847de9b1214SNicolin Chen /* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */
848de9b1214SNicolin Chen #define CS53L30_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT)
849de9b1214SNicolin Chen 
850de9b1214SNicolin Chen #define CS53L30_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
851de9b1214SNicolin Chen 			SNDRV_PCM_FMTBIT_S24_LE)
852de9b1214SNicolin Chen 
853de9b1214SNicolin Chen static const struct snd_soc_dai_ops cs53l30_ops = {
854de9b1214SNicolin Chen 	.startup = cs53l30_pcm_startup,
855de9b1214SNicolin Chen 	.hw_params = cs53l30_pcm_hw_params,
856de9b1214SNicolin Chen 	.set_fmt = cs53l30_set_dai_fmt,
857de9b1214SNicolin Chen 	.set_sysclk = cs53l30_set_sysclk,
858de9b1214SNicolin Chen 	.set_tristate = cs53l30_set_tristate,
859de9b1214SNicolin Chen 	.set_tdm_slot = cs53l30_set_dai_tdm_slot,
86005f33bc5SNicolin Chen 	.mute_stream = cs53l30_mute_stream,
861de9b1214SNicolin Chen };
862de9b1214SNicolin Chen 
863de9b1214SNicolin Chen static struct snd_soc_dai_driver cs53l30_dai = {
864de9b1214SNicolin Chen 	.name = "cs53l30",
865de9b1214SNicolin Chen 	.capture = {
866de9b1214SNicolin Chen 		.stream_name = "Capture",
867de9b1214SNicolin Chen 		.channels_min = 1,
868de9b1214SNicolin Chen 		.channels_max = 4,
869de9b1214SNicolin Chen 		.rates = CS53L30_RATES,
870de9b1214SNicolin Chen 		.formats = CS53L30_FORMATS,
871de9b1214SNicolin Chen 	},
872de9b1214SNicolin Chen 	.ops = &cs53l30_ops,
873260b668cSKuninori Morimoto 	.symmetric_rate = 1,
874de9b1214SNicolin Chen };
875de9b1214SNicolin Chen 
cs53l30_component_probe(struct snd_soc_component * component)876534cf41cSKuninori Morimoto static int cs53l30_component_probe(struct snd_soc_component *component)
877de9b1214SNicolin Chen {
878534cf41cSKuninori Morimoto 	struct cs53l30_private *priv = snd_soc_component_get_drvdata(component);
879534cf41cSKuninori Morimoto 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
880de9b1214SNicolin Chen 
881de9b1214SNicolin Chen 	if (priv->use_sdout2)
882de9b1214SNicolin Chen 		snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout2,
883de9b1214SNicolin Chen 					ARRAY_SIZE(cs53l30_dapm_routes_sdout2));
884de9b1214SNicolin Chen 	else
885de9b1214SNicolin Chen 		snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout1,
886de9b1214SNicolin Chen 					ARRAY_SIZE(cs53l30_dapm_routes_sdout1));
887de9b1214SNicolin Chen 
888de9b1214SNicolin Chen 	return 0;
889de9b1214SNicolin Chen }
890de9b1214SNicolin Chen 
891534cf41cSKuninori Morimoto static const struct snd_soc_component_driver cs53l30_driver = {
892534cf41cSKuninori Morimoto 	.probe			= cs53l30_component_probe,
893de9b1214SNicolin Chen 	.set_bias_level		= cs53l30_set_bias_level,
894cbe5cdbfSKuninori Morimoto 	.controls		= cs53l30_snd_controls,
895cbe5cdbfSKuninori Morimoto 	.num_controls		= ARRAY_SIZE(cs53l30_snd_controls),
896de9b1214SNicolin Chen 	.dapm_widgets		= cs53l30_dapm_widgets,
897de9b1214SNicolin Chen 	.num_dapm_widgets	= ARRAY_SIZE(cs53l30_dapm_widgets),
898de9b1214SNicolin Chen 	.dapm_routes		= cs53l30_dapm_routes,
899de9b1214SNicolin Chen 	.num_dapm_routes	= ARRAY_SIZE(cs53l30_dapm_routes),
900534cf41cSKuninori Morimoto 	.use_pmdown_time	= 1,
901534cf41cSKuninori Morimoto 	.endianness		= 1,
902de9b1214SNicolin Chen };
903de9b1214SNicolin Chen 
904de9b1214SNicolin Chen static struct regmap_config cs53l30_regmap = {
905de9b1214SNicolin Chen 	.reg_bits = 8,
906de9b1214SNicolin Chen 	.val_bits = 8,
907de9b1214SNicolin Chen 
908de9b1214SNicolin Chen 	.max_register = CS53L30_MAX_REGISTER,
909de9b1214SNicolin Chen 	.reg_defaults = cs53l30_reg_defaults,
910de9b1214SNicolin Chen 	.num_reg_defaults = ARRAY_SIZE(cs53l30_reg_defaults),
911de9b1214SNicolin Chen 	.volatile_reg = cs53l30_volatile_register,
912de9b1214SNicolin Chen 	.writeable_reg = cs53l30_writeable_register,
913de9b1214SNicolin Chen 	.readable_reg = cs53l30_readable_register,
914*0eff26b1SMark Brown 	.cache_type = REGCACHE_MAPLE,
91596f68597SCharles Keepax 
91696f68597SCharles Keepax 	.use_single_read = true,
91796f68597SCharles Keepax 	.use_single_write = true,
918de9b1214SNicolin Chen };
919de9b1214SNicolin Chen 
cs53l30_i2c_probe(struct i2c_client * client)9204a404345SStephen Kitt static int cs53l30_i2c_probe(struct i2c_client *client)
921de9b1214SNicolin Chen {
922de9b1214SNicolin Chen 	const struct device_node *np = client->dev.of_node;
923de9b1214SNicolin Chen 	struct device *dev = &client->dev;
924de9b1214SNicolin Chen 	struct cs53l30_private *cs53l30;
925de9b1214SNicolin Chen 	unsigned int reg;
9264fc81bc8SCharles Keepax 	int ret = 0, i, devid;
927de9b1214SNicolin Chen 	u8 val;
928de9b1214SNicolin Chen 
929de9b1214SNicolin Chen 	cs53l30 = devm_kzalloc(dev, sizeof(*cs53l30), GFP_KERNEL);
930de9b1214SNicolin Chen 	if (!cs53l30)
931de9b1214SNicolin Chen 		return -ENOMEM;
932de9b1214SNicolin Chen 
933de9b1214SNicolin Chen 	for (i = 0; i < ARRAY_SIZE(cs53l30->supplies); i++)
934de9b1214SNicolin Chen 		cs53l30->supplies[i].supply = cs53l30_supply_names[i];
935de9b1214SNicolin Chen 
936de9b1214SNicolin Chen 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs53l30->supplies),
937de9b1214SNicolin Chen 				      cs53l30->supplies);
938de9b1214SNicolin Chen 	if (ret) {
939de9b1214SNicolin Chen 		dev_err(dev, "failed to get supplies: %d\n", ret);
940de9b1214SNicolin Chen 		return ret;
941de9b1214SNicolin Chen 	}
942de9b1214SNicolin Chen 
943de9b1214SNicolin Chen 	ret = regulator_bulk_enable(ARRAY_SIZE(cs53l30->supplies),
944de9b1214SNicolin Chen 				    cs53l30->supplies);
945de9b1214SNicolin Chen 	if (ret) {
946de9b1214SNicolin Chen 		dev_err(dev, "failed to enable supplies: %d\n", ret);
947de9b1214SNicolin Chen 		return ret;
948de9b1214SNicolin Chen 	}
949de9b1214SNicolin Chen 
950de9b1214SNicolin Chen 	/* Reset the Device */
951de9b1214SNicolin Chen 	cs53l30->reset_gpio = devm_gpiod_get_optional(dev, "reset",
952de9b1214SNicolin Chen 						      GPIOD_OUT_LOW);
953de9b1214SNicolin Chen 	if (IS_ERR(cs53l30->reset_gpio)) {
954de9b1214SNicolin Chen 		ret = PTR_ERR(cs53l30->reset_gpio);
9554fc81bc8SCharles Keepax 		goto error_supplies;
956de9b1214SNicolin Chen 	}
957de9b1214SNicolin Chen 
958de9b1214SNicolin Chen 	gpiod_set_value_cansleep(cs53l30->reset_gpio, 1);
959de9b1214SNicolin Chen 
960de9b1214SNicolin Chen 	i2c_set_clientdata(client, cs53l30);
961de9b1214SNicolin Chen 
962de9b1214SNicolin Chen 	cs53l30->mclk_rate = 0;
963de9b1214SNicolin Chen 
964de9b1214SNicolin Chen 	cs53l30->regmap = devm_regmap_init_i2c(client, &cs53l30_regmap);
965de9b1214SNicolin Chen 	if (IS_ERR(cs53l30->regmap)) {
966de9b1214SNicolin Chen 		ret = PTR_ERR(cs53l30->regmap);
967de9b1214SNicolin Chen 		dev_err(dev, "regmap_init() failed: %d\n", ret);
968de9b1214SNicolin Chen 		goto error;
969de9b1214SNicolin Chen 	}
970de9b1214SNicolin Chen 
971de9b1214SNicolin Chen 	/* Initialize codec */
9724fc81bc8SCharles Keepax 	devid = cirrus_read_device_id(cs53l30->regmap, CS53L30_DEVID_AB);
9734fc81bc8SCharles Keepax 	if (devid < 0) {
9744fc81bc8SCharles Keepax 		ret = devid;
9754fc81bc8SCharles Keepax 		dev_err(dev, "Failed to read device ID: %d\n", ret);
9764fc81bc8SCharles Keepax 		goto error;
9774fc81bc8SCharles Keepax 	}
978de9b1214SNicolin Chen 
979de9b1214SNicolin Chen 	if (devid != CS53L30_DEVID) {
980de9b1214SNicolin Chen 		ret = -ENODEV;
981de9b1214SNicolin Chen 		dev_err(dev, "Device ID (%X). Expected %X\n",
982de9b1214SNicolin Chen 			devid, CS53L30_DEVID);
983de9b1214SNicolin Chen 		goto error;
984de9b1214SNicolin Chen 	}
985de9b1214SNicolin Chen 
986de9b1214SNicolin Chen 	ret = regmap_read(cs53l30->regmap, CS53L30_REVID, &reg);
987de9b1214SNicolin Chen 	if (ret < 0) {
988de9b1214SNicolin Chen 		dev_err(dev, "failed to get Revision ID: %d\n", ret);
989de9b1214SNicolin Chen 		goto error;
990de9b1214SNicolin Chen 	}
991de9b1214SNicolin Chen 
992de9b1214SNicolin Chen 	/* Check if MCLK provided */
9930b855cbbSChristophe JAILLET 	cs53l30->mclk = devm_clk_get_optional(dev, "mclk");
994de9b1214SNicolin Chen 	if (IS_ERR(cs53l30->mclk)) {
9954d48298aSNicolin Chen 		ret = PTR_ERR(cs53l30->mclk);
996de9b1214SNicolin Chen 		goto error;
997de9b1214SNicolin Chen 	}
998de9b1214SNicolin Chen 
99905f33bc5SNicolin Chen 	/* Fetch the MUTE control */
100005f33bc5SNicolin Chen 	cs53l30->mute_gpio = devm_gpiod_get_optional(dev, "mute",
100105f33bc5SNicolin Chen 						     GPIOD_OUT_HIGH);
100205f33bc5SNicolin Chen 	if (IS_ERR(cs53l30->mute_gpio)) {
100305f33bc5SNicolin Chen 		ret = PTR_ERR(cs53l30->mute_gpio);
100405f33bc5SNicolin Chen 		goto error;
100505f33bc5SNicolin Chen 	}
100605f33bc5SNicolin Chen 
100705f33bc5SNicolin Chen 	if (cs53l30->mute_gpio) {
100805f33bc5SNicolin Chen 		/* Enable MUTE controls via MUTE pin */
100905f33bc5SNicolin Chen 		regmap_write(cs53l30->regmap, CS53L30_MUTEP_CTL1,
101005f33bc5SNicolin Chen 			     CS53L30_MUTEP_CTL1_MUTEALL);
101105f33bc5SNicolin Chen 		/* Flip the polarity of MUTE pin */
101205f33bc5SNicolin Chen 		if (gpiod_is_active_low(cs53l30->mute_gpio))
101305f33bc5SNicolin Chen 			regmap_update_bits(cs53l30->regmap, CS53L30_MUTEP_CTL2,
101405f33bc5SNicolin Chen 					   CS53L30_MUTE_PIN_POLARITY, 0);
101505f33bc5SNicolin Chen 	}
101605f33bc5SNicolin Chen 
1017de9b1214SNicolin Chen 	if (!of_property_read_u8(np, "cirrus,micbias-lvl", &val))
1018de9b1214SNicolin Chen 		regmap_update_bits(cs53l30->regmap, CS53L30_MICBIAS_CTL,
1019de9b1214SNicolin Chen 				   CS53L30_MIC_BIAS_CTRL_MASK, val);
1020de9b1214SNicolin Chen 
1021de9b1214SNicolin Chen 	if (of_property_read_bool(np, "cirrus,use-sdout2"))
1022de9b1214SNicolin Chen 		cs53l30->use_sdout2 = true;
1023de9b1214SNicolin Chen 
1024de9b1214SNicolin Chen 	dev_info(dev, "Cirrus Logic CS53L30, Revision: %02X\n", reg & 0xFF);
1025de9b1214SNicolin Chen 
1026534cf41cSKuninori Morimoto 	ret = devm_snd_soc_register_component(dev, &cs53l30_driver, &cs53l30_dai, 1);
1027de9b1214SNicolin Chen 	if (ret) {
1028534cf41cSKuninori Morimoto 		dev_err(dev, "failed to register component: %d\n", ret);
1029de9b1214SNicolin Chen 		goto error;
1030de9b1214SNicolin Chen 	}
1031de9b1214SNicolin Chen 
1032de9b1214SNicolin Chen 	return 0;
1033de9b1214SNicolin Chen 
1034de9b1214SNicolin Chen error:
10354fc81bc8SCharles Keepax 	gpiod_set_value_cansleep(cs53l30->reset_gpio, 0);
10364fc81bc8SCharles Keepax error_supplies:
1037de9b1214SNicolin Chen 	regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies),
1038de9b1214SNicolin Chen 			       cs53l30->supplies);
1039de9b1214SNicolin Chen 	return ret;
1040de9b1214SNicolin Chen }
1041de9b1214SNicolin Chen 
cs53l30_i2c_remove(struct i2c_client * client)1042ed5c2f5fSUwe Kleine-König static void cs53l30_i2c_remove(struct i2c_client *client)
1043de9b1214SNicolin Chen {
1044de9b1214SNicolin Chen 	struct cs53l30_private *cs53l30 = i2c_get_clientdata(client);
1045de9b1214SNicolin Chen 
1046de9b1214SNicolin Chen 	/* Hold down reset */
1047de9b1214SNicolin Chen 	gpiod_set_value_cansleep(cs53l30->reset_gpio, 0);
1048de9b1214SNicolin Chen 
1049de9b1214SNicolin Chen 	regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies),
1050de9b1214SNicolin Chen 			       cs53l30->supplies);
1051de9b1214SNicolin Chen }
1052de9b1214SNicolin Chen 
1053de9b1214SNicolin Chen #ifdef CONFIG_PM
cs53l30_runtime_suspend(struct device * dev)1054de9b1214SNicolin Chen static int cs53l30_runtime_suspend(struct device *dev)
1055de9b1214SNicolin Chen {
1056de9b1214SNicolin Chen 	struct cs53l30_private *cs53l30 = dev_get_drvdata(dev);
1057de9b1214SNicolin Chen 
1058de9b1214SNicolin Chen 	regcache_cache_only(cs53l30->regmap, true);
1059de9b1214SNicolin Chen 
1060de9b1214SNicolin Chen 	/* Hold down reset */
1061de9b1214SNicolin Chen 	gpiod_set_value_cansleep(cs53l30->reset_gpio, 0);
1062de9b1214SNicolin Chen 
1063de9b1214SNicolin Chen 	regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies),
1064de9b1214SNicolin Chen 			       cs53l30->supplies);
1065de9b1214SNicolin Chen 
1066de9b1214SNicolin Chen 	return 0;
1067de9b1214SNicolin Chen }
1068de9b1214SNicolin Chen 
cs53l30_runtime_resume(struct device * dev)1069de9b1214SNicolin Chen static int cs53l30_runtime_resume(struct device *dev)
1070de9b1214SNicolin Chen {
1071de9b1214SNicolin Chen 	struct cs53l30_private *cs53l30 = dev_get_drvdata(dev);
1072de9b1214SNicolin Chen 	int ret;
1073de9b1214SNicolin Chen 
1074de9b1214SNicolin Chen 	ret = regulator_bulk_enable(ARRAY_SIZE(cs53l30->supplies),
1075de9b1214SNicolin Chen 				    cs53l30->supplies);
1076de9b1214SNicolin Chen 	if (ret) {
1077de9b1214SNicolin Chen 		dev_err(dev, "failed to enable supplies: %d\n", ret);
1078de9b1214SNicolin Chen 		return ret;
1079de9b1214SNicolin Chen 	}
1080de9b1214SNicolin Chen 
1081de9b1214SNicolin Chen 	gpiod_set_value_cansleep(cs53l30->reset_gpio, 1);
1082de9b1214SNicolin Chen 
1083de9b1214SNicolin Chen 	regcache_cache_only(cs53l30->regmap, false);
108487a4bb11SNicolin Chen 	ret = regcache_sync(cs53l30->regmap);
108587a4bb11SNicolin Chen 	if (ret) {
108687a4bb11SNicolin Chen 		dev_err(dev, "failed to synchronize regcache: %d\n", ret);
108787a4bb11SNicolin Chen 		return ret;
108887a4bb11SNicolin Chen 	}
1089de9b1214SNicolin Chen 
1090de9b1214SNicolin Chen 	return 0;
1091de9b1214SNicolin Chen }
1092de9b1214SNicolin Chen #endif
1093de9b1214SNicolin Chen 
1094de9b1214SNicolin Chen static const struct dev_pm_ops cs53l30_runtime_pm = {
1095de9b1214SNicolin Chen 	SET_RUNTIME_PM_OPS(cs53l30_runtime_suspend, cs53l30_runtime_resume,
1096de9b1214SNicolin Chen 			   NULL)
1097de9b1214SNicolin Chen };
1098de9b1214SNicolin Chen 
1099de9b1214SNicolin Chen static const struct of_device_id cs53l30_of_match[] = {
1100de9b1214SNicolin Chen 	{ .compatible = "cirrus,cs53l30", },
1101de9b1214SNicolin Chen 	{},
1102de9b1214SNicolin Chen };
1103de9b1214SNicolin Chen 
1104de9b1214SNicolin Chen MODULE_DEVICE_TABLE(of, cs53l30_of_match);
1105de9b1214SNicolin Chen 
1106de9b1214SNicolin Chen static const struct i2c_device_id cs53l30_id[] = {
1107de9b1214SNicolin Chen 	{ "cs53l30", 0 },
1108de9b1214SNicolin Chen 	{}
1109de9b1214SNicolin Chen };
1110de9b1214SNicolin Chen 
1111de9b1214SNicolin Chen MODULE_DEVICE_TABLE(i2c, cs53l30_id);
1112de9b1214SNicolin Chen 
1113de9b1214SNicolin Chen static struct i2c_driver cs53l30_i2c_driver = {
1114de9b1214SNicolin Chen 	.driver = {
1115de9b1214SNicolin Chen 		.name = "cs53l30",
111613023ff3SJavier Martinez Canillas 		.of_match_table = cs53l30_of_match,
1117de9b1214SNicolin Chen 		.pm = &cs53l30_runtime_pm,
1118de9b1214SNicolin Chen 	},
1119de9b1214SNicolin Chen 	.id_table = cs53l30_id,
11209abcd240SUwe Kleine-König 	.probe = cs53l30_i2c_probe,
1121de9b1214SNicolin Chen 	.remove = cs53l30_i2c_remove,
1122de9b1214SNicolin Chen };
1123de9b1214SNicolin Chen 
1124de9b1214SNicolin Chen module_i2c_driver(cs53l30_i2c_driver);
1125de9b1214SNicolin Chen 
1126de9b1214SNicolin Chen MODULE_DESCRIPTION("ASoC CS53L30 driver");
1127de9b1214SNicolin Chen MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <Paul.Handrigan@cirrus.com>");
1128de9b1214SNicolin Chen MODULE_LICENSE("GPL");
1129