1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // CS530x CODEC driver
4 //
5 // Copyright (C) 2024-2025 Cirrus Logic, Inc. and
6 // Cirrus Logic International Semiconductor Ltd.
7
8 #include <linux/delay.h>
9 #include <linux/i2c.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/pm.h>
13 #include <linux/property.h>
14 #include <linux/slab.h>
15 #include <linux/spi/spi.h>
16 #include <sound/core.h>
17 #include <sound/initval.h>
18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21 #include <sound/tlv.h>
22
23 #include "cs530x.h"
24
25 static const char *cs530x_supply_names[CS530X_NUM_SUPPLIES] = {
26 "vdd-a",
27 "vdd-io",
28 };
29
30 static const struct reg_default cs530x_reg_defaults[] = {
31 { CS530X_CLK_CFG_0, 0x30 },
32 { CS530X_CLK_CFG_1, 0x0001 },
33 { CS530X_CHIP_ENABLE, 0 },
34 { CS530X_ASP_CFG, 0 },
35 { CS530X_SIGNAL_PATH_CFG, 0 },
36 { CS530X_IN_ENABLES, 0 },
37 { CS530X_IN_RAMP_SUM, 0x0022 },
38 { CS530X_IN_FILTER, 0 },
39 { CS530X_IN_HIZ, 0 },
40 { CS530X_IN_INV, 0 },
41 { CS530X_IN_VOL_CTRL1_0, 0x8000 },
42 { CS530X_IN_VOL_CTRL1_1, 0x8000 },
43 { CS530X_IN_VOL_CTRL2_0, 0x8000 },
44 { CS530X_IN_VOL_CTRL2_1, 0x8000 },
45 { CS530X_IN_VOL_CTRL3_0, 0x8000 },
46 { CS530X_IN_VOL_CTRL3_1, 0x8000 },
47 { CS530X_IN_VOL_CTRL4_0, 0x8000 },
48 { CS530X_IN_VOL_CTRL4_1, 0x8000 },
49 { CS530X_OUT_ENABLES, 0 },
50 { CS530X_OUT_RAMP_SUM, 0x0022 },
51 { CS530X_OUT_FILTER, 0 },
52 { CS530X_OUT_INV, 0 },
53 { CS530X_OUT_VOL_CTRL1_0, 0x8000 },
54 { CS530X_OUT_VOL_CTRL1_1, 0x8000 },
55 { CS530X_OUT_VOL_CTRL2_0, 0x8000 },
56 { CS530X_OUT_VOL_CTRL2_1, 0x8000 },
57 { CS530X_OUT_VOL_CTRL3_0, 0x8000 },
58 { CS530X_OUT_VOL_CTRL3_1, 0x8000 },
59 { CS530X_OUT_VOL_CTRL4_0, 0x8000 },
60 { CS530X_OUT_VOL_CTRL4_1, 0x8000 },
61 { CS530X_PAD_FN, 0 },
62 { CS530X_PAD_LVL, 0 },
63 };
64
cs530x_read_and_write_regs(unsigned int reg)65 static bool cs530x_read_and_write_regs(unsigned int reg)
66 {
67 switch (reg) {
68 case CS530X_CLK_CFG_0:
69 case CS530X_CLK_CFG_1:
70 case CS530X_CHIP_ENABLE:
71 case CS530X_ASP_CFG:
72 case CS530X_SIGNAL_PATH_CFG:
73 case CS530X_IN_ENABLES:
74 case CS530X_IN_RAMP_SUM:
75 case CS530X_IN_FILTER:
76 case CS530X_IN_HIZ:
77 case CS530X_IN_INV:
78 case CS530X_IN_VOL_CTRL1_0:
79 case CS530X_IN_VOL_CTRL1_1:
80 case CS530X_IN_VOL_CTRL2_0:
81 case CS530X_IN_VOL_CTRL2_1:
82 case CS530X_IN_VOL_CTRL3_0:
83 case CS530X_IN_VOL_CTRL3_1:
84 case CS530X_IN_VOL_CTRL4_0:
85 case CS530X_IN_VOL_CTRL4_1:
86 case CS530X_OUT_ENABLES:
87 case CS530X_OUT_RAMP_SUM:
88 case CS530X_OUT_DEEMPH:
89 case CS530X_OUT_FILTER:
90 case CS530X_OUT_INV:
91 case CS530X_OUT_VOL_CTRL1_0:
92 case CS530X_OUT_VOL_CTRL1_1:
93 case CS530X_OUT_VOL_CTRL2_0:
94 case CS530X_OUT_VOL_CTRL2_1:
95 case CS530X_OUT_VOL_CTRL3_0:
96 case CS530X_OUT_VOL_CTRL3_1:
97 case CS530X_OUT_VOL_CTRL4_0:
98 case CS530X_OUT_VOL_CTRL4_1:
99 case CS530X_PAD_FN:
100 case CS530X_PAD_LVL:
101 return true;
102 default:
103 return false;
104 }
105 }
106
cs530x_readable_register(struct device * dev,unsigned int reg)107 static bool cs530x_readable_register(struct device *dev, unsigned int reg)
108 {
109 switch (reg) {
110 case CS530X_DEVID:
111 case CS530X_REVID:
112 return true;
113 default:
114 return cs530x_read_and_write_regs(reg);
115 }
116 }
117
cs530x_writeable_register(struct device * dev,unsigned int reg)118 static bool cs530x_writeable_register(struct device *dev, unsigned int reg)
119 {
120 switch (reg) {
121 case CS530X_SW_RESET:
122 case CS530X_IN_VOL_CTRL5:
123 case CS530X_OUT_VOL_CTRL5:
124 return true;
125 default:
126 return cs530x_read_and_write_regs(reg);
127 }
128 }
129
cs530x_put_volsw_vu(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)130 static int cs530x_put_volsw_vu(struct snd_kcontrol *kcontrol,
131 struct snd_ctl_elem_value *ucontrol)
132 {
133 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
134 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
135 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
136 struct regmap *regmap = cs530x->regmap;
137 int ret;
138
139 snd_soc_dapm_mutex_lock(dapm);
140
141 ret = snd_soc_put_volsw(kcontrol, ucontrol);
142 if (ret)
143 goto volsw_err;
144
145 /* Write INOUT_VU bit for the volume change to take effect */
146 regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_INOUT_VU);
147
148 volsw_err:
149 snd_soc_dapm_mutex_unlock(dapm);
150
151 return ret;
152 }
153
154 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0);
155
156 static const char * const cs530x_inout_filter_text[] = {
157 "Min Phase Slow Roll-off",
158 "Min Phase Fast Roll-off",
159 "Linear Phase Slow Roll-off",
160 "Linear Phase Fast Roll-off",
161 };
162
163 static SOC_ENUM_SINGLE_DECL(cs530x_in_filter_enum, CS530X_IN_FILTER,
164 CS530X_INOUT_FILTER_SHIFT,
165 cs530x_inout_filter_text);
166
167 static SOC_ENUM_SINGLE_DECL(cs530x_out_filter_enum, CS530X_OUT_FILTER,
168 CS530X_INOUT_FILTER_SHIFT,
169 cs530x_inout_filter_text);
170
171 static const char * const cs530x_4ch_sum_text[] = {
172 "None",
173 "Groups of 2",
174 "Groups of 4",
175 };
176
177 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM,
178 CS530X_INOUT_SUM_MODE_SHIFT,
179 cs530x_4ch_sum_text);
180
181 static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] = {
182 SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum),
183 };
184
185 static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch4_enum, CS530X_OUT_RAMP_SUM,
186 CS530X_INOUT_SUM_MODE_SHIFT,
187 cs530x_4ch_sum_text);
188
189 static const struct snd_kcontrol_new cs530x_out_sum_4ch_controls[] = {
190 SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch4_enum),
191 };
192
193 static const char * const cs530x_8ch_sum_text[] = {
194 "None",
195 "Groups of 2",
196 "Groups of 4",
197 "Groups of 8",
198 };
199
200 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM,
201 CS530X_INOUT_SUM_MODE_SHIFT,
202 cs530x_8ch_sum_text);
203
204 static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] = {
205 SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum),
206 };
207
208 static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch8_enum, CS530X_OUT_RAMP_SUM,
209 CS530X_INOUT_SUM_MODE_SHIFT,
210 cs530x_8ch_sum_text);
211
212 static const struct snd_kcontrol_new cs530x_out_sum_8ch_controls[] = {
213 SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch8_enum),
214 };
215
216 static const char * const cs530x_vol_ramp_text[] = {
217 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
218 "15ms/6dB", "30ms/6dB",
219 };
220
221 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_inc_enum, CS530X_IN_RAMP_SUM,
222 CS530X_RAMP_RATE_INC_SHIFT,
223 cs530x_vol_ramp_text);
224
225 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_dec_enum, CS530X_IN_RAMP_SUM,
226 CS530X_RAMP_RATE_DEC_SHIFT,
227 cs530x_vol_ramp_text);
228
229 static const struct snd_kcontrol_new cs530x_in_1_to_2_controls[] = {
230 SOC_SINGLE_EXT_TLV("IN1 Volume", CS530X_IN_VOL_CTRL1_0, 0, 255, 1,
231 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
232 SOC_SINGLE_EXT_TLV("IN2 Volume", CS530X_IN_VOL_CTRL1_1, 0, 255, 1,
233 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
234
235 SOC_ENUM("IN DEC Filter Select", cs530x_in_filter_enum),
236 SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum),
237 SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum),
238
239 SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_INOUT1_INV_SHIFT, 1, 0),
240 SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_INOUT2_INV_SHIFT, 1, 0),
241 };
242
243 static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] = {
244 SOC_SINGLE_EXT_TLV("IN3 Volume", CS530X_IN_VOL_CTRL2_0, 0, 255, 1,
245 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
246 SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1,
247 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
248
249 SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_INOUT3_INV_SHIFT, 1, 0),
250 SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_INOUT4_INV_SHIFT, 1, 0),
251 };
252
253 static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] = {
254 SOC_SINGLE_EXT_TLV("IN5 Volume", CS530X_IN_VOL_CTRL3_0, 0, 255, 1,
255 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
256 SOC_SINGLE_EXT_TLV("IN6 Volume", CS530X_IN_VOL_CTRL3_1, 0, 255, 1,
257 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
258 SOC_SINGLE_EXT_TLV("IN7 Volume", CS530X_IN_VOL_CTRL4_0, 0, 255, 1,
259 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
260 SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1,
261 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
262
263 SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_INOUT5_INV_SHIFT, 1, 0),
264 SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_INOUT6_INV_SHIFT, 1, 0),
265 SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_INOUT7_INV_SHIFT, 1, 0),
266 SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_INOUT8_INV_SHIFT, 1, 0),
267 };
268
cs530x_adc_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)269 static int cs530x_adc_event(struct snd_soc_dapm_widget *w,
270 struct snd_kcontrol *kcontrol, int event)
271 {
272 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
273 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
274 struct regmap *regmap = cs530x->regmap;
275
276 switch (event) {
277 case SND_SOC_DAPM_PRE_PMU:
278 cs530x->adc_pairs_count++;
279 break;
280 case SND_SOC_DAPM_POST_PMU:
281 regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
282 (w->shift * 2), CS530X_INOUT_MUTE);
283 regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
284 ((w->shift + 1) * 2), CS530X_INOUT_MUTE);
285
286 cs530x->adc_pairs_count--;
287 if (!cs530x->adc_pairs_count) {
288 usleep_range(1000, 1100);
289 return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
290 CS530X_INOUT_VU);
291 }
292 break;
293 case SND_SOC_DAPM_PRE_PMD:
294 regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
295 (w->shift * 2), CS530X_INOUT_MUTE);
296 regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
297 ((w->shift + 1) * 2), CS530X_INOUT_MUTE);
298 return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
299 CS530X_INOUT_VU);
300 default:
301 return -EINVAL;
302 }
303
304 return 0;
305 }
306
307 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_inc_enum, CS530X_OUT_RAMP_SUM,
308 CS530X_RAMP_RATE_INC_SHIFT,
309 cs530x_vol_ramp_text);
310
311 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_dec_enum, CS530X_OUT_RAMP_SUM,
312 CS530X_RAMP_RATE_DEC_SHIFT,
313 cs530x_vol_ramp_text);
314
315 static const struct snd_kcontrol_new cs530x_out_1_to_2_controls[] = {
316 SOC_SINGLE_EXT_TLV("OUT1 Volume", CS530X_OUT_VOL_CTRL1_0, 0, 255, 1,
317 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
318 SOC_SINGLE_EXT_TLV("OUT2 Volume", CS530X_OUT_VOL_CTRL1_1, 0, 255, 1,
319 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
320
321 SOC_ENUM("OUT DEC Filter Select", cs530x_out_filter_enum),
322 SOC_ENUM("Output Ramp Up", cs530x_ramp_out_inc_enum),
323 SOC_ENUM("Output Ramp Down", cs530x_ramp_out_dec_enum),
324
325 SOC_SINGLE("DAC1 Invert Switch", CS530X_OUT_INV, CS530X_INOUT1_INV_SHIFT, 1, 0),
326 SOC_SINGLE("DAC2 Invert Switch", CS530X_OUT_INV, CS530X_INOUT2_INV_SHIFT, 1, 0),
327 };
328
329 static const struct snd_kcontrol_new cs530x_out_3_to_4_controls[] = {
330 SOC_SINGLE_EXT_TLV("OUT3 Volume", CS530X_OUT_VOL_CTRL2_0, 0, 255, 1,
331 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
332 SOC_SINGLE_EXT_TLV("OUT4 Volume", CS530X_OUT_VOL_CTRL2_1, 0, 255, 1,
333 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
334
335 SOC_SINGLE("DAC3 Invert Switch", CS530X_OUT_INV, CS530X_INOUT3_INV_SHIFT, 1, 0),
336 SOC_SINGLE("DAC4 Invert Switch", CS530X_OUT_INV, CS530X_INOUT4_INV_SHIFT, 1, 0),
337 };
338
339 static const struct snd_kcontrol_new cs530x_out_5_to_8_controls[] = {
340 SOC_SINGLE_EXT_TLV("OUT5 Volume", CS530X_OUT_VOL_CTRL3_0, 0, 255, 1,
341 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
342 SOC_SINGLE_EXT_TLV("OUT6 Volume", CS530X_OUT_VOL_CTRL3_1, 0, 255, 1,
343 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
344 SOC_SINGLE_EXT_TLV("OUT7 Volume", CS530X_OUT_VOL_CTRL4_0, 0, 255, 1,
345 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
346 SOC_SINGLE_EXT_TLV("OUT8 Volume", CS530X_OUT_VOL_CTRL4_1, 0, 255, 1,
347 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
348
349 SOC_SINGLE("DAC5 Invert Switch", CS530X_OUT_INV, CS530X_INOUT5_INV_SHIFT, 1, 0),
350 SOC_SINGLE("DAC6 Invert Switch", CS530X_OUT_INV, CS530X_INOUT6_INV_SHIFT, 1, 0),
351 SOC_SINGLE("DAC7 Invert Switch", CS530X_OUT_INV, CS530X_INOUT7_INV_SHIFT, 1, 0),
352 SOC_SINGLE("DAC8 Invert Switch", CS530X_OUT_INV, CS530X_INOUT8_INV_SHIFT, 1, 0),
353 };
354
cs530x_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)355 static int cs530x_dac_event(struct snd_soc_dapm_widget *w,
356 struct snd_kcontrol *kcontrol, int event)
357 {
358 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
359 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
360 struct regmap *regmap = cs530x->regmap;
361
362 switch (event) {
363 case SND_SOC_DAPM_PRE_PMU:
364 cs530x->dac_pairs_count++;
365 break;
366 case SND_SOC_DAPM_POST_PMU:
367 regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 +
368 (w->shift * 2), CS530X_INOUT_MUTE);
369 regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 +
370 ((w->shift + 1) * 2), CS530X_INOUT_MUTE);
371
372 cs530x->dac_pairs_count--;
373 if (!cs530x->dac_pairs_count) {
374 usleep_range(1000, 1100);
375 return regmap_write(regmap, CS530X_OUT_VOL_CTRL5,
376 CS530X_INOUT_VU);
377 }
378 break;
379 case SND_SOC_DAPM_PRE_PMD:
380 regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 +
381 (w->shift * 2), CS530X_INOUT_MUTE);
382 regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 +
383 ((w->shift + 1) * 2), CS530X_INOUT_MUTE);
384 return regmap_write(regmap, CS530X_OUT_VOL_CTRL5,
385 CS530X_INOUT_VU);
386 default:
387 return -EINVAL;
388 }
389
390 return 0;
391 }
392
393 static const struct snd_kcontrol_new adc12_ctrl =
394 SOC_DAPM_SINGLE_VIRT("Switch", 1);
395 static const struct snd_kcontrol_new adc34_ctrl =
396 SOC_DAPM_SINGLE_VIRT("Switch", 1);
397 static const struct snd_kcontrol_new adc56_ctrl =
398 SOC_DAPM_SINGLE_VIRT("Switch", 1);
399 static const struct snd_kcontrol_new adc78_ctrl =
400 SOC_DAPM_SINGLE_VIRT("Switch", 1);
401 static const struct snd_kcontrol_new dac12_ctrl =
402 SOC_DAPM_SINGLE_VIRT("Switch", 1);
403 static const struct snd_kcontrol_new dac34_ctrl =
404 SOC_DAPM_SINGLE_VIRT("Switch", 1);
405 static const struct snd_kcontrol_new dac56_ctrl =
406 SOC_DAPM_SINGLE_VIRT("Switch", 1);
407 static const struct snd_kcontrol_new dac78_ctrl =
408 SOC_DAPM_SINGLE_VIRT("Switch", 1);
409 static const struct snd_kcontrol_new in_hpf_ctrl =
410 SOC_DAPM_SINGLE_VIRT("Switch", 1);
411 static const struct snd_kcontrol_new out_hpf_ctrl =
412 SOC_DAPM_SINGLE_VIRT("Switch", 1);
413
414 /* General DAPM widgets for all devices */
415 static const struct snd_soc_dapm_widget cs530x_gen_dapm_widgets[] = {
416 SND_SOC_DAPM_SUPPLY("Global Enable", CS530X_CHIP_ENABLE, 0, 0, NULL, 0),
417 };
418
419 /* ADC's Channels 1 and 2 plus generic ADC DAPM events */
420 static const struct snd_soc_dapm_widget cs530x_adc_ch12_dapm_widgets[] = {
421 SND_SOC_DAPM_INPUT("IN1"),
422 SND_SOC_DAPM_INPUT("IN2"),
423 SND_SOC_DAPM_ADC_E("ADC1", NULL, CS530X_IN_ENABLES, 0, 0,
424 cs530x_adc_event,
425 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
426 SND_SOC_DAPM_PRE_PMU),
427 SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0),
428 SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl),
429 SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_INOUT_HPF_EN_SHIFT,
430 0, &in_hpf_ctrl),
431 };
432
433 /* ADC's Channels 3 and 4 */
434 static const struct snd_soc_dapm_widget cs530x_adc_ch34_dapm_widgets[] = {
435 SND_SOC_DAPM_INPUT("IN3"),
436 SND_SOC_DAPM_INPUT("IN4"),
437 SND_SOC_DAPM_ADC_E("ADC3", NULL, CS530X_IN_ENABLES, 2, 0,
438 cs530x_adc_event,
439 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
440 SND_SOC_DAPM_PRE_PMU),
441 SND_SOC_DAPM_ADC("ADC4", NULL, CS530X_IN_ENABLES, 3, 0),
442 SND_SOC_DAPM_SWITCH("ADC34 Enable", SND_SOC_NOPM, 0, 0, &adc34_ctrl),
443 };
444
445 /* ADC's Channels 5 to 8 */
446 static const struct snd_soc_dapm_widget cs530x_adc_ch58_dapm_widgets[] = {
447 SND_SOC_DAPM_INPUT("IN5"),
448 SND_SOC_DAPM_INPUT("IN6"),
449 SND_SOC_DAPM_INPUT("IN7"),
450 SND_SOC_DAPM_INPUT("IN8"),
451 SND_SOC_DAPM_ADC_E("ADC5", NULL, CS530X_IN_ENABLES, 4, 0,
452 cs530x_adc_event,
453 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
454 SND_SOC_DAPM_PRE_PMU),
455 SND_SOC_DAPM_ADC("ADC6", NULL, CS530X_IN_ENABLES, 5, 0),
456 SND_SOC_DAPM_SWITCH("ADC56 Enable", SND_SOC_NOPM, 0, 0, &adc56_ctrl),
457 SND_SOC_DAPM_ADC_E("ADC7", NULL, CS530X_IN_ENABLES, 6, 0,
458 cs530x_adc_event,
459 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
460 SND_SOC_DAPM_PRE_PMU),
461 SND_SOC_DAPM_ADC("ADC8", NULL, CS530X_IN_ENABLES, 7, 0),
462 SND_SOC_DAPM_SWITCH("ADC78 Enable", SND_SOC_NOPM, 0, 0, &adc78_ctrl),
463 };
464
465 static const struct snd_soc_dapm_route adc_ch1_2_routes[] = {
466 { "ADC1", NULL, "Global Enable" },
467 { "ADC2", NULL, "Global Enable" },
468
469 { "ADC12 Enable", "Switch", "IN1" },
470 { "ADC12 Enable", "Switch", "IN2" },
471 { "ADC1", NULL, "ADC12 Enable" },
472 { "ADC2", NULL, "ADC12 Enable" },
473 { "IN HPF", "Switch", "ADC1" },
474 { "IN HPF", "Switch", "ADC2" },
475
476 { "AIF Capture", NULL, "IN HPF" },
477 { "AIF Capture", NULL, "ADC1" },
478 { "AIF Capture", NULL, "ADC2" },
479 };
480
481 static const struct snd_soc_dapm_route adc_ch3_4_routes[] = {
482 { "ADC3", NULL, "Global Enable" },
483 { "ADC4", NULL, "Global Enable" },
484
485 { "ADC34 Enable", "Switch", "IN3" },
486 { "ADC34 Enable", "Switch", "IN4" },
487 { "ADC3", NULL, "ADC34 Enable" },
488 { "ADC4", NULL, "ADC34 Enable" },
489 { "IN HPF", "Switch", "ADC3" },
490 { "IN HPF", "Switch", "ADC4" },
491
492 { "AIF Capture", NULL, "ADC3" },
493 { "AIF Capture", NULL, "ADC4" },
494 };
495
496 static const struct snd_soc_dapm_route adc_ch5_8_routes[] = {
497 { "ADC5", NULL, "Global Enable" },
498 { "ADC6", NULL, "Global Enable" },
499 { "ADC7", NULL, "Global Enable" },
500 { "ADC8", NULL, "Global Enable" },
501
502 { "ADC56 Enable", "Switch", "IN5" },
503 { "ADC56 Enable", "Switch", "IN6" },
504 { "ADC5", NULL, "ADC56 Enable" },
505 { "ADC6", NULL, "ADC56 Enable" },
506 { "IN HPF", "Switch", "ADC5" },
507 { "IN HPF", "Switch", "ADC6" },
508
509 { "AIF Capture", NULL, "ADC5" },
510 { "AIF Capture", NULL, "ADC6" },
511
512 { "ADC78 Enable", "Switch", "IN7" },
513 { "ADC78 Enable", "Switch", "IN8" },
514 { "ADC7", NULL, "ADC78 Enable" },
515 { "ADC8", NULL, "ADC78 Enable" },
516 { "IN HPF", "Switch", "ADC7" },
517 { "IN HPF", "Switch", "ADC8" },
518
519 { "AIF Capture", NULL, "ADC7" },
520 { "AIF Capture", NULL, "ADC8" },
521 };
522
cs530x_add_12_adc_widgets(struct snd_soc_component * component)523 static void cs530x_add_12_adc_widgets(struct snd_soc_component *component)
524 {
525 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
526
527 snd_soc_add_component_controls(component,
528 cs530x_in_1_to_2_controls,
529 ARRAY_SIZE(cs530x_in_1_to_2_controls));
530
531 snd_soc_dapm_new_controls(dapm, cs530x_adc_ch12_dapm_widgets,
532 ARRAY_SIZE(cs530x_adc_ch12_dapm_widgets));
533
534 snd_soc_dapm_add_routes(dapm, adc_ch1_2_routes,
535 ARRAY_SIZE(adc_ch1_2_routes));
536 }
537
cs530x_add_34_adc_widgets(struct snd_soc_component * component)538 static void cs530x_add_34_adc_widgets(struct snd_soc_component *component)
539 {
540 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
541
542 snd_soc_add_component_controls(component,
543 cs530x_in_3_to_4_controls,
544 ARRAY_SIZE(cs530x_in_3_to_4_controls));
545
546 snd_soc_dapm_new_controls(dapm, cs530x_adc_ch34_dapm_widgets,
547 ARRAY_SIZE(cs530x_adc_ch34_dapm_widgets));
548
549 snd_soc_dapm_add_routes(dapm, adc_ch3_4_routes,
550 ARRAY_SIZE(adc_ch3_4_routes));
551 }
552
553 /* DAC's Channels 1 and 2 plus generic DAC DAPM events */
554 static const struct snd_soc_dapm_widget cs530x_dac_ch12_dapm_widgets[] = {
555 SND_SOC_DAPM_OUTPUT("OUT1"),
556 SND_SOC_DAPM_OUTPUT("OUT2"),
557 SND_SOC_DAPM_DAC_E("DAC1", NULL, CS530X_OUT_ENABLES, 0, 0,
558 cs530x_dac_event,
559 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
560 SND_SOC_DAPM_PRE_PMU),
561 SND_SOC_DAPM_DAC("DAC2", NULL, CS530X_OUT_ENABLES, 1, 0),
562 SND_SOC_DAPM_SWITCH("DAC12 Enable", SND_SOC_NOPM, 0, 0, &dac12_ctrl),
563 SND_SOC_DAPM_SWITCH("OUT HPF", CS530X_OUT_FILTER, CS530X_INOUT_HPF_EN_SHIFT,
564 0, &out_hpf_ctrl),
565 };
566
567 /* DAC's Channels 3 and 4 */
568 static const struct snd_soc_dapm_widget cs530x_dac_ch34_dapm_widgets[] = {
569 SND_SOC_DAPM_OUTPUT("OUT3"),
570 SND_SOC_DAPM_OUTPUT("OUT4"),
571 SND_SOC_DAPM_DAC_E("DAC3", NULL, CS530X_OUT_ENABLES, 2, 0,
572 cs530x_dac_event,
573 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
574 SND_SOC_DAPM_PRE_PMU),
575 SND_SOC_DAPM_DAC("DAC4", NULL, CS530X_OUT_ENABLES, 3, 0),
576 SND_SOC_DAPM_SWITCH("DAC34 Enable", SND_SOC_NOPM, 0, 0, &dac34_ctrl),
577 };
578
579 /* DAC's Channels 5 to 8 */
580 static const struct snd_soc_dapm_widget cs530x_dac_ch58_dapm_widgets[] = {
581 SND_SOC_DAPM_OUTPUT("OUT5"),
582 SND_SOC_DAPM_OUTPUT("OUT6"),
583 SND_SOC_DAPM_OUTPUT("OUT7"),
584 SND_SOC_DAPM_OUTPUT("OUT8"),
585 SND_SOC_DAPM_DAC_E("DAC5", NULL, CS530X_OUT_ENABLES, 4, 0,
586 cs530x_dac_event,
587 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
588 SND_SOC_DAPM_PRE_PMU),
589 SND_SOC_DAPM_DAC("DAC6", NULL, CS530X_OUT_ENABLES, 5, 0),
590 SND_SOC_DAPM_SWITCH("DAC56 Enable", SND_SOC_NOPM, 0, 0, &dac56_ctrl),
591 SND_SOC_DAPM_DAC_E("DAC7", NULL, CS530X_OUT_ENABLES, 6, 0,
592 cs530x_dac_event,
593 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
594 SND_SOC_DAPM_PRE_PMU),
595 SND_SOC_DAPM_DAC("DAC8", NULL, CS530X_OUT_ENABLES, 7, 0),
596 SND_SOC_DAPM_SWITCH("DAC78 Enable", SND_SOC_NOPM, 0, 0, &dac78_ctrl),
597 };
598
599 static const struct snd_soc_dapm_route dac_ch1_2_routes[] = {
600 { "DAC1", NULL, "Global Enable" },
601 { "DAC2", NULL, "Global Enable" },
602
603 { "DAC12 Enable", "Switch", "OUT1" },
604 { "DAC12 Enable", "Switch", "OUT2" },
605 { "DAC1", NULL, "DAC12 Enable" },
606 { "DAC2", NULL, "DAC12 Enable" },
607 { "OUT HPF", "Switch", "DAC1" },
608 { "OUT HPF", "Switch", "DAC2" },
609
610 { "OUT HPF", NULL, "AIF Playback" },
611 { "DAC1", NULL, "AIF Playback" },
612 { "DAC2", NULL, "AIF Playback" },
613
614 { "OUT1", NULL, "DAC1" },
615 { "OUT2", NULL, "DAC2" },
616 };
617
618 static const struct snd_soc_dapm_route dac_ch3_4_routes[] = {
619 { "DAC3", NULL, "Global Enable" },
620 { "DAC4", NULL, "Global Enable" },
621
622 { "DAC34 Enable", "Switch", "OUT3" },
623 { "DAC34 Enable", "Switch", "OUT4" },
624 { "DAC3", NULL, "DAC34 Enable" },
625 { "DAC4", NULL, "DAC34 Enable" },
626 { "OUT HPF", "Switch", "DAC3" },
627 { "OUT HPF", "Switch", "DAC4" },
628
629 { "DAC3", NULL, "AIF Playback" },
630 { "DAC4", NULL, "AIF Playback" },
631
632 { "OUT3", NULL, "DAC3" },
633 { "OUT4", NULL, "DAC4" },
634 };
635
636 static const struct snd_soc_dapm_route dac_ch5_8_routes[] = {
637 { "DAC5", NULL, "Global Enable" },
638 { "DAC6", NULL, "Global Enable" },
639
640 { "DAC56 Enable", "Switch", "OUT5" },
641 { "DAC56 Enable", "Switch", "OUT6" },
642 { "DAC5", NULL, "DAC56 Enable" },
643 { "DAC6", NULL, "DAC56 Enable" },
644 { "OUT HPF", "Switch", "DAC5" },
645 { "OUT HPF", "Switch", "DAC6" },
646
647 { "DAC5", NULL, "AIF Playback" },
648 { "DAC6", NULL, "AIF Playback" },
649
650 { "OUT5", NULL, "DAC5" },
651 { "OUT6", NULL, "DAC6" },
652
653 { "DAC7", NULL, "Global Enable" },
654 { "DAC8", NULL, "Global Enable" },
655
656 { "DAC78 Enable", "Switch", "OUT7" },
657 { "DAC78 Enable", "Switch", "OUT8" },
658 { "DAC7", NULL, "DAC78 Enable" },
659 { "DAC8", NULL, "DAC78 Enable" },
660 { "OUT HPF", "Switch", "DAC7" },
661 { "OUT HPF", "Switch", "DAC8" },
662
663 { "DAC7", NULL, "AIF Playback" },
664 { "DAC8", NULL, "AIF Playback" },
665
666 { "OUT7", NULL, "DAC7" },
667 { "OUT8", NULL, "DAC8" },
668 };
669
cs530x_add_12_dac_widgets(struct snd_soc_component * component)670 static void cs530x_add_12_dac_widgets(struct snd_soc_component *component)
671 {
672 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
673
674 snd_soc_add_component_controls(component,
675 cs530x_out_1_to_2_controls,
676 ARRAY_SIZE(cs530x_out_1_to_2_controls));
677
678 snd_soc_dapm_new_controls(dapm, cs530x_dac_ch12_dapm_widgets,
679 ARRAY_SIZE(cs530x_dac_ch12_dapm_widgets));
680
681 snd_soc_dapm_add_routes(dapm, dac_ch1_2_routes,
682 ARRAY_SIZE(dac_ch1_2_routes));
683 }
684
cs530x_add_34_dac_widgets(struct snd_soc_component * component)685 static void cs530x_add_34_dac_widgets(struct snd_soc_component *component)
686 {
687 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
688
689 snd_soc_add_component_controls(component,
690 cs530x_out_3_to_4_controls,
691 ARRAY_SIZE(cs530x_out_3_to_4_controls));
692
693 snd_soc_dapm_new_controls(dapm, cs530x_dac_ch34_dapm_widgets,
694 ARRAY_SIZE(cs530x_dac_ch34_dapm_widgets));
695
696 snd_soc_dapm_add_routes(dapm, dac_ch3_4_routes,
697 ARRAY_SIZE(dac_ch3_4_routes));
698 }
699
cs530x_set_bclk(struct snd_soc_component * component,const int freq)700 static int cs530x_set_bclk(struct snd_soc_component *component, const int freq)
701 {
702 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
703 struct regmap *regmap = cs530x->regmap;
704 unsigned int bclk_val;
705
706 switch (freq) {
707 case 2822400:
708 case 3072000:
709 bclk_val = CS530X_BCLK_2P822_3P072;
710 break;
711 case 5644800:
712 case 6144000:
713 bclk_val = CS530X_BCLK_5P6448_6P144;
714 break;
715 case 11289600:
716 case 12288000:
717 bclk_val = CS530X_BCLK_11P2896_12P288;
718 break;
719 case 22579200:
720 case 24576000:
721 bclk_val = CS530X_BCLK_24P5792_24P576;
722 break;
723 default:
724 dev_err(component->dev, "Invalid BCLK frequency %d\n", freq);
725 return -EINVAL;
726 }
727
728 dev_dbg(component->dev, "BCLK frequency is %d\n", freq);
729
730 return regmap_update_bits(regmap, CS530X_ASP_CFG,
731 CS530X_ASP_BCLK_FREQ_MASK, bclk_val);
732 }
733
cs530x_set_pll_refclk(struct snd_soc_component * component,const unsigned int freq)734 static int cs530x_set_pll_refclk(struct snd_soc_component *component,
735 const unsigned int freq)
736 {
737 struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
738 struct regmap *regmap = priv->regmap;
739 unsigned int refclk;
740
741 switch (freq) {
742 case 2822400:
743 case 3072000:
744 refclk = CS530X_REFCLK_2P822_3P072;
745 break;
746 case 5644800:
747 case 6144000:
748 refclk = CS530X_REFCLK_5P6448_6P144;
749 break;
750 case 11289600:
751 case 12288000:
752 refclk = CS530X_REFCLK_11P2896_12P288;
753 break;
754 case 22579200:
755 case 24576000:
756 refclk = CS530X_REFCLK_24P5792_24P576;
757 break;
758 default:
759 dev_err(component->dev, "Invalid PLL refclk %d\n", freq);
760 return -EINVAL;
761 }
762
763 return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
764 CS530X_PLL_REFCLK_FREQ_MASK, refclk);
765 }
766
cs530x_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)767 static int cs530x_hw_params(struct snd_pcm_substream *substream,
768 struct snd_pcm_hw_params *params,
769 struct snd_soc_dai *dai)
770 {
771 struct snd_soc_component *component = dai->component;
772 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
773 struct regmap *regmap = cs530x->regmap;
774 int ret = 0, fs = params_rate(params), bclk;
775 unsigned int fs_val;
776
777 switch (fs) {
778 case 32000:
779 fs_val = CS530X_FS_32K;
780 break;
781 case 44100:
782 case 48000:
783 fs_val = CS530X_FS_44P1K_48K;
784 break;
785 case 88200:
786 case 96000:
787 fs_val = CS530X_FS_88P2K_96K;
788 break;
789 case 176400:
790 case 192000:
791 fs_val = CS530X_FS_176P4K_192K;
792 break;
793 case 356800:
794 case 384000:
795 fs_val = CS530X_FS_356P8K_384K;
796 break;
797 case 705600:
798 case 768000:
799 fs_val = CS530X_FS_705P6K_768K;
800 break;
801 default:
802 dev_err(component->dev, "Invalid sample rate %d\n", fs);
803 return -EINVAL;
804 }
805
806 regmap_update_bits(regmap, CS530X_CLK_CFG_1,
807 CS530X_SAMPLE_RATE_MASK, fs_val);
808
809
810 if (regmap_test_bits(regmap, CS530X_SIGNAL_PATH_CFG,
811 CS530X_TDM_EN_MASK)) {
812 dev_dbg(component->dev, "Configuring for %d %d bit TDM slots\n",
813 cs530x->tdm_slots, cs530x->tdm_width);
814 bclk = snd_soc_tdm_params_to_bclk(params,
815 cs530x->tdm_width,
816 cs530x->tdm_slots,
817 1);
818 } else {
819 bclk = snd_soc_params_to_bclk(params);
820 }
821
822 if (!regmap_test_bits(regmap, CS530X_CLK_CFG_0,
823 CS530X_PLL_REFCLK_SRC_MASK)) {
824 ret = cs530x_set_pll_refclk(component, bclk);
825 if (ret)
826 return ret;
827 }
828
829 return cs530x_set_bclk(component, bclk);
830 }
831
cs530x_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)832 static int cs530x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
833 {
834 struct snd_soc_component *component = dai->component;
835 struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
836 struct regmap *regmap = priv->regmap;
837 unsigned int asp_fmt, asp_cfg = 0;
838
839 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
840 case SND_SOC_DAIFMT_CBC_CFC:
841 break;
842 case SND_SOC_DAIFMT_CBP_CFP:
843 asp_cfg = CS530X_ASP_PRIMARY;
844 break;
845 default:
846 return -EINVAL;
847 }
848
849 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
850 case SND_SOC_DAIFMT_DSP_A:
851 asp_fmt = CS530X_ASP_FMT_DSP_A;
852 break;
853 case SND_SOC_DAIFMT_I2S:
854 asp_fmt = CS530X_ASP_FMT_I2S;
855 break;
856 case SND_SOC_DAIFMT_LEFT_J:
857 asp_fmt = CS530X_ASP_FMT_LJ;
858 break;
859 default:
860 return -EINVAL;
861 }
862
863 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
864 case SND_SOC_DAIFMT_NB_NF:
865 break;
866 case SND_SOC_DAIFMT_IB_IF:
867 asp_cfg |= CS530X_ASP_BCLK_INV;
868 break;
869 default:
870 return -EINVAL;
871 }
872
873 regmap_update_bits(regmap, CS530X_ASP_CFG,
874 CS530X_ASP_PRIMARY | CS530X_ASP_BCLK_INV,
875 asp_cfg);
876
877 return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
878 CS530X_ASP_FMT_MASK, asp_fmt);
879 }
880
cs530x_check_mclk_freq(struct snd_soc_component * component,const unsigned int freq)881 static bool cs530x_check_mclk_freq(struct snd_soc_component *component,
882 const unsigned int freq)
883 {
884 switch (freq) {
885 case 24576000:
886 case 22579200:
887 case 12288000:
888 case 11289600:
889 return true;
890 default:
891 dev_err(component->dev, "Invalid MCLK %d\n", freq);
892 return false;
893 }
894 }
895
cs530x_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)896 static int cs530x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
897 unsigned int rx_mask, int slots, int slot_width)
898 {
899 struct snd_soc_component *component = dai->component;
900 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
901 struct regmap *regmap = cs530x->regmap;
902 unsigned int val;
903
904 switch (tx_mask) {
905 case CS530X_0_1_TDM_SLOT_MASK:
906 case CS530X_0_3_TDM_SLOT_MASK:
907 case CS530X_0_7_TDM_SLOT_MASK:
908 val = CS530X_0_7_TDM_SLOT_VAL;
909 break;
910 case CS530X_2_3_TDM_SLOT_MASK:
911 val = CS530X_2_3_TDM_SLOT_VAL;
912 break;
913 case CS530X_4_5_TDM_SLOT_MASK:
914 case CS530X_4_7_TDM_SLOT_MASK:
915 val = CS530X_4_7_TDM_SLOT_VAL;
916 break;
917 case CS530X_6_7_TDM_SLOT_MASK:
918 val = CS530X_6_7_TDM_SLOT_VAL;
919 break;
920 case CS530X_8_9_TDM_SLOT_MASK:
921 case CS530X_8_11_TDM_SLOT_MASK:
922 case CS530X_8_15_TDM_SLOT_MASK:
923 val = CS530X_8_15_TDM_SLOT_VAL;
924 break;
925 case CS530X_10_11_TDM_SLOT_MASK:
926 val = CS530X_10_11_TDM_SLOT_VAL;
927 break;
928 case CS530X_12_13_TDM_SLOT_MASK:
929 case CS530X_12_15_TDM_SLOT_MASK:
930 val = CS530X_12_15_TDM_SLOT_VAL;
931 break;
932 case CS530X_14_15_TDM_SLOT_MASK:
933 val = CS530X_14_15_TDM_SLOT_VAL;
934 break;
935 default:
936 dev_err(component->dev, "Invalid TX slot(s) 0x%x\n", tx_mask);
937 return -EINVAL;
938 }
939
940 cs530x->tdm_width = slot_width;
941 cs530x->tdm_slots = slots;
942
943 return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
944 CS530X_ASP_TDM_SLOT_MASK,
945 val << CS530X_ASP_TDM_SLOT_SHIFT);
946 }
947
948 static const struct snd_soc_dai_ops cs530x_dai_ops = {
949 .set_fmt = cs530x_set_fmt,
950 .hw_params = cs530x_hw_params,
951 .set_tdm_slot = cs530x_set_tdm_slot,
952 };
953
954 static const struct snd_soc_dai_driver cs530x_dai = {
955 .name = "cs530x-dai",
956 .capture = {
957 .stream_name = "AIF Capture",
958 .rates = SNDRV_PCM_RATE_KNOT,
959 .formats = SNDRV_PCM_FMTBIT_S32_LE,
960 },
961 .playback = {
962 .stream_name = "AIF Playback",
963 .rates = SNDRV_PCM_RATE_KNOT,
964 .formats = SNDRV_PCM_FMTBIT_S32_LE,
965 },
966 .ops = &cs530x_dai_ops,
967 .symmetric_rate = 1,
968 .symmetric_sample_bits = 1,
969 };
970
cs530x_set_pll(struct snd_soc_component * component,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)971 static int cs530x_set_pll(struct snd_soc_component *component, int pll_id,
972 int source, unsigned int freq_in,
973 unsigned int freq_out)
974 {
975 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
976 struct regmap *regmap = cs530x->regmap;
977 unsigned int sysclk_src;
978 int ret;
979
980 regmap_read(regmap, CS530X_CLK_CFG_0, &sysclk_src);
981
982 /* Check if the source is the PLL */
983 if ((sysclk_src & CS530X_SYSCLK_SRC_MASK) == 0)
984 return 0;
985
986 switch (source) {
987 case CS530X_PLL_SRC_MCLK:
988 if (!cs530x_check_mclk_freq(component, freq_in))
989 return -EINVAL;
990
991 ret = cs530x_set_pll_refclk(component, freq_in);
992 if (ret)
993 return ret;
994
995 break;
996 case CS530X_PLL_SRC_BCLK:
997 break;
998 default:
999 dev_err(component->dev, "Invalid PLL source %d\n", source);
1000 return -EINVAL;
1001 }
1002
1003 return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
1004 CS530X_PLL_REFCLK_SRC_MASK, source);
1005 }
1006
cs530x_component_probe(struct snd_soc_component * component)1007 static int cs530x_component_probe(struct snd_soc_component *component)
1008 {
1009 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
1010 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
1011 int num_widgets;
1012
1013 snd_soc_dapm_new_controls(dapm, cs530x_gen_dapm_widgets,
1014 ARRAY_SIZE(cs530x_gen_dapm_widgets));
1015
1016 switch (cs530x->devtype) {
1017 case CS4282:
1018 cs530x_add_12_adc_widgets(component);
1019 cs530x_add_12_dac_widgets(component);
1020 break;
1021 case CS4302:
1022 cs530x_add_12_dac_widgets(component);
1023 break;
1024 case CS4304:
1025 cs530x_add_12_dac_widgets(component);
1026 cs530x_add_34_dac_widgets(component);
1027
1028 num_widgets = ARRAY_SIZE(cs530x_out_sum_4ch_controls);
1029 snd_soc_add_component_controls(component,
1030 cs530x_out_sum_4ch_controls,
1031 num_widgets);
1032 break;
1033 case CS4308:
1034 cs530x_add_12_dac_widgets(component);
1035 cs530x_add_34_dac_widgets(component);
1036
1037 num_widgets = ARRAY_SIZE(cs530x_out_5_to_8_controls);
1038 snd_soc_add_component_controls(component,
1039 cs530x_out_5_to_8_controls,
1040 num_widgets);
1041
1042 num_widgets = ARRAY_SIZE(cs530x_out_sum_8ch_controls);
1043 snd_soc_add_component_controls(component,
1044 cs530x_out_sum_8ch_controls,
1045 num_widgets);
1046
1047 num_widgets = ARRAY_SIZE(cs530x_dac_ch58_dapm_widgets);
1048 snd_soc_dapm_new_controls(dapm, cs530x_dac_ch58_dapm_widgets,
1049 num_widgets);
1050
1051 snd_soc_dapm_add_routes(dapm, dac_ch5_8_routes,
1052 ARRAY_SIZE(dac_ch5_8_routes));
1053 break;
1054 case CS5302:
1055 cs530x_add_12_adc_widgets(component);
1056 break;
1057 case CS5304:
1058 cs530x_add_12_adc_widgets(component);
1059 cs530x_add_34_adc_widgets(component);
1060
1061 num_widgets = ARRAY_SIZE(cs530x_in_sum_4ch_controls);
1062 snd_soc_add_component_controls(component,
1063 cs530x_in_sum_4ch_controls,
1064 num_widgets);
1065 break;
1066 case CS5308:
1067 cs530x_add_12_adc_widgets(component);
1068 cs530x_add_34_adc_widgets(component);
1069
1070 num_widgets = ARRAY_SIZE(cs530x_in_5_to_8_controls);
1071 snd_soc_add_component_controls(component,
1072 cs530x_in_5_to_8_controls,
1073 num_widgets);
1074
1075 num_widgets = ARRAY_SIZE(cs530x_in_sum_8ch_controls);
1076 snd_soc_add_component_controls(component,
1077 cs530x_in_sum_8ch_controls,
1078 num_widgets);
1079
1080 num_widgets = ARRAY_SIZE(cs530x_adc_ch58_dapm_widgets);
1081 snd_soc_dapm_new_controls(dapm, cs530x_adc_ch58_dapm_widgets,
1082 num_widgets);
1083
1084 snd_soc_dapm_add_routes(dapm, adc_ch5_8_routes,
1085 ARRAY_SIZE(adc_ch5_8_routes));
1086 break;
1087 default:
1088 dev_err(component->dev, "Invalid device type %d\n",
1089 cs530x->devtype);
1090 return -EINVAL;
1091 }
1092
1093 return 0;
1094 }
1095
cs530x_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)1096 static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id,
1097 int source, unsigned int freq, int dir)
1098 {
1099 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
1100 struct regmap *regmap = cs530x->regmap;
1101
1102 switch (source) {
1103 case CS530X_SYSCLK_SRC_MCLK:
1104 switch (freq) {
1105 case CS530X_SYSCLK_REF_45_1MHZ:
1106 case CS530X_SYSCLK_REF_49_1MHZ:
1107 break;
1108 default:
1109 dev_err(component->dev, "Invalid MCLK source rate %d\n", freq);
1110 return -EINVAL;
1111 }
1112 break;
1113 case CS530X_SYSCLK_SRC_PLL:
1114 break;
1115 default:
1116 dev_err(component->dev, "Invalid sysclk source: %d\n", source);
1117 return -EINVAL;
1118 }
1119
1120 return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
1121 CS530X_SYSCLK_SRC_MASK,
1122 source << CS530X_SYSCLK_SRC_SHIFT);
1123 }
1124
1125 static const struct snd_soc_component_driver soc_component_dev_cs530x = {
1126 .probe = cs530x_component_probe,
1127 .set_sysclk = cs530x_set_sysclk,
1128 .set_pll = cs530x_set_pll,
1129 .endianness = 1,
1130 };
1131
1132 const struct regmap_config cs530x_regmap_i2c = {
1133 .reg_bits = 16,
1134 .val_bits = 16,
1135
1136 .max_register = CS530X_MAX_REGISTER,
1137 .readable_reg = cs530x_readable_register,
1138 .writeable_reg = cs530x_writeable_register,
1139
1140 .cache_type = REGCACHE_MAPLE,
1141 .reg_defaults = cs530x_reg_defaults,
1142 .num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults),
1143 };
1144 EXPORT_SYMBOL_NS_GPL(cs530x_regmap_i2c, "SND_SOC_CS530X");
1145
1146 const struct regmap_config cs530x_regmap_spi = {
1147 .reg_bits = 16,
1148 .pad_bits = 16,
1149 .val_bits = 16,
1150
1151 .reg_stride = 2,
1152
1153 .reg_format_endian = REGMAP_ENDIAN_BIG,
1154 .val_format_endian = REGMAP_ENDIAN_BIG,
1155
1156 .max_register = CS530X_MAX_REGISTER,
1157 .writeable_reg = cs530x_writeable_register,
1158 .readable_reg = cs530x_readable_register,
1159
1160 .cache_type = REGCACHE_MAPLE,
1161 .reg_defaults = cs530x_reg_defaults,
1162 .num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults),
1163 };
1164 EXPORT_SYMBOL_NS_GPL(cs530x_regmap_spi, "SND_SOC_CS530X");
1165
cs530x_check_device_id(struct cs530x_priv * cs530x)1166 static int cs530x_check_device_id(struct cs530x_priv *cs530x)
1167 {
1168 struct device *dev = cs530x->dev;
1169 unsigned int dev_id, rev;
1170 int ret;
1171
1172 ret = regmap_read(cs530x->regmap, CS530X_DEVID, &dev_id);
1173 if (ret)
1174 return dev_err_probe(dev, ret, "Can't read device ID\n");
1175
1176 ret = regmap_read(cs530x->regmap, CS530X_REVID, &rev);
1177 if (ret)
1178 return dev_err_probe(dev, ret, "Can't read REV ID\n");
1179
1180 switch (dev_id) {
1181 case CS530X_2CH_CODEC_DEV_ID:
1182 cs530x->num_dacs = 2;
1183 cs530x->num_adcs = 2;
1184 break;
1185 case CS530X_2CH_DAC_DEV_ID:
1186 cs530x->num_dacs = 2;
1187 break;
1188 case CS530X_4CH_DAC_DEV_ID:
1189 cs530x->num_dacs = 4;
1190 break;
1191 case CS530X_8CH_DAC_DEV_ID:
1192 cs530x->num_dacs = 8;
1193 break;
1194 case CS530X_2CH_ADC_DEV_ID:
1195 cs530x->num_adcs = 2;
1196 break;
1197 case CS530X_4CH_ADC_DEV_ID:
1198 cs530x->num_adcs = 4;
1199 break;
1200 case CS530X_8CH_ADC_DEV_ID:
1201 cs530x->num_adcs = 8;
1202 break;
1203 default:
1204 return dev_err_probe(dev, -EINVAL, "Invalid device ID 0x%x\n",
1205 dev_id);
1206 }
1207
1208 if (cs530x->devtype != dev_id) {
1209 dev_err(dev, "Read device ID 0x%x is not the expected devtype 0x%x\n",
1210 dev_id, cs530x->devtype);
1211 return -EINVAL;
1212 }
1213
1214 dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x (%d in %d out)\n", dev_id, rev,
1215 cs530x->num_adcs, cs530x->num_dacs);
1216
1217 return 0;
1218 }
1219
cs530x_parse_device_properties(struct cs530x_priv * cs530x)1220 static int cs530x_parse_device_properties(struct cs530x_priv *cs530x)
1221 {
1222 struct regmap *regmap = cs530x->regmap;
1223 struct device *dev = cs530x->dev;
1224 unsigned int val = 0;
1225
1226 switch (cs530x->num_adcs) {
1227 case 8:
1228 if (device_property_read_bool(dev, "cirrus,in-hiz-pin78"))
1229 val = CS530X_IN78_HIZ;
1230
1231 if (device_property_read_bool(dev, "cirrus,in-hiz-pin56"))
1232 val |= CS530X_IN56_HIZ;
1233
1234 fallthrough;
1235 case 4:
1236 if (device_property_read_bool(dev, "cirrus,in-hiz-pin34"))
1237 val |= CS530X_IN34_HIZ;
1238
1239 fallthrough;
1240 case 2:
1241 if (device_property_read_bool(dev, "cirrus,in-hiz-pin12"))
1242 val |= CS530X_IN12_HIZ;
1243
1244 return regmap_set_bits(regmap, CS530X_IN_HIZ, val);
1245 case 0:
1246 /* No ADCs */
1247 return 0;
1248 default:
1249 return dev_err_probe(dev, -EINVAL,
1250 "Invalid number of adcs %d\n",
1251 cs530x->num_adcs);
1252 }
1253 }
1254
cs530x_probe(struct cs530x_priv * cs530x)1255 int cs530x_probe(struct cs530x_priv *cs530x)
1256 {
1257 struct device *dev = cs530x->dev;
1258 int ret, i;
1259
1260 cs530x->dev_dai = devm_kmemdup(dev, &cs530x_dai,
1261 sizeof(*(cs530x->dev_dai)),
1262 GFP_KERNEL);
1263 if (!cs530x->dev_dai)
1264 return -ENOMEM;
1265
1266 for (i = 0; i < ARRAY_SIZE(cs530x->supplies); i++)
1267 cs530x->supplies[i].supply = cs530x_supply_names[i];
1268
1269 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs530x->supplies),
1270 cs530x->supplies);
1271 if (ret != 0)
1272 return dev_err_probe(dev, ret, "Failed to request supplies");
1273
1274 ret = regulator_bulk_enable(ARRAY_SIZE(cs530x->supplies),
1275 cs530x->supplies);
1276 if (ret != 0)
1277 return dev_err_probe(dev, ret, "Failed to enable supplies");
1278
1279 cs530x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
1280 GPIOD_OUT_HIGH);
1281 if (IS_ERR(cs530x->reset_gpio)) {
1282 ret = dev_err_probe(dev, PTR_ERR(cs530x->reset_gpio),
1283 "Reset gpio not available\n");
1284 goto err_regulator;
1285 }
1286
1287 if (cs530x->reset_gpio) {
1288 usleep_range(2000, 2100);
1289 gpiod_set_value_cansleep(cs530x->reset_gpio, 0);
1290 }
1291
1292 usleep_range(5000, 5100);
1293 ret = cs530x_check_device_id(cs530x);
1294 if (ret)
1295 goto err_reset;
1296
1297 if (!cs530x->reset_gpio) {
1298 ret = regmap_write(cs530x->regmap, CS530X_SW_RESET,
1299 CS530X_SW_RST_VAL);
1300 if (ret) {
1301 dev_err_probe(dev, ret, "Soft Reset Failed\n");
1302 goto err_reset;
1303 }
1304 }
1305
1306 ret = cs530x_parse_device_properties(cs530x);
1307 if (ret)
1308 goto err_reset;
1309
1310 if (cs530x->num_adcs) {
1311 cs530x->dev_dai->capture.channels_min = 2;
1312 cs530x->dev_dai->capture.channels_max = cs530x->num_adcs;
1313 }
1314
1315 if (cs530x->num_dacs) {
1316 cs530x->dev_dai->playback.channels_min = 2;
1317 cs530x->dev_dai->playback.channels_max = cs530x->num_dacs;
1318 }
1319
1320 ret = devm_snd_soc_register_component(dev,
1321 &soc_component_dev_cs530x,
1322 cs530x->dev_dai, 1);
1323 if (ret) {
1324 dev_err_probe(dev, ret, "Can't register cs530x component\n");
1325 goto err_reset;
1326 }
1327
1328 return 0;
1329
1330 err_reset:
1331 gpiod_set_value_cansleep(cs530x->reset_gpio, 1);
1332
1333 err_regulator:
1334 regulator_bulk_disable(ARRAY_SIZE(cs530x->supplies),
1335 cs530x->supplies);
1336
1337 return ret;
1338 }
1339 EXPORT_SYMBOL_NS_GPL(cs530x_probe, "SND_SOC_CS530X");
1340
1341 MODULE_DESCRIPTION("CS530X CODEC Driver");
1342 MODULE_AUTHOR("Paul Handrigan <paulha@opensource.cirrus.com>");
1343 MODULE_LICENSE("GPL");
1344