Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// CS530x CODEC driver
  4//
  5// Copyright (C) 2024 Cirrus Logic, Inc. and
  6//                    Cirrus Logic International Semiconductor Ltd.
  7
  8#include <sound/core.h>
  9#include <linux/delay.h>
 10#include <linux/i2c.h>
 11#include <linux/init.h>
 12#include <sound/initval.h>
 13#include <linux/module.h>
 14#include <sound/pcm.h>
 15#include <sound/pcm_params.h>
 16#include <linux/pm.h>
 17#include <linux/property.h>
 18#include <linux/slab.h>
 19#include <sound/soc.h>
 20#include <sound/tlv.h>
 21
 22#include "cs530x.h"
 23
 24#define CS530X_MAX_ADC_CH	8
 25#define CS530X_MIN_ADC_CH	2
 26
 27static const char *cs530x_supply_names[CS530X_NUM_SUPPLIES] = {
 28	"vdd-a",
 29	"vdd-io",
 30};
 31
 32static const struct reg_default cs530x_reg_defaults[] = {
 33	{ CS530X_CLK_CFG_0, 0x30 },
 34	{ CS530X_CLK_CFG_1, 0x0001 },
 35	{ CS530X_CHIP_ENABLE, 0 },
 36	{ CS530X_ASP_CFG, 0 },
 37	{ CS530X_SIGNAL_PATH_CFG, 0 },
 38	{ CS530X_IN_ENABLES, 0 },
 39	{ CS530X_IN_RAMP_SUM, 0x0022 },
 40	{ CS530X_IN_FILTER, 0 },
 41	{ CS530X_IN_HIZ, 0 },
 42	{ CS530X_IN_INV, 0 },
 43	{ CS530X_IN_VOL_CTRL1_0, 0x8000 },
 44	{ CS530X_IN_VOL_CTRL1_1, 0x8000 },
 45	{ CS530X_IN_VOL_CTRL2_0, 0x8000 },
 46	{ CS530X_IN_VOL_CTRL2_1, 0x8000 },
 47	{ CS530X_IN_VOL_CTRL3_0, 0x8000 },
 48	{ CS530X_IN_VOL_CTRL3_1, 0x8000 },
 49	{ CS530X_IN_VOL_CTRL4_0, 0x8000 },
 50	{ CS530X_IN_VOL_CTRL4_1, 0x8000 },
 51	{ CS530X_PAD_FN, 0 },
 52	{ CS530X_PAD_LVL, 0 },
 53};
 54
 55static bool cs530x_read_and_write_regs(unsigned int reg)
 56{
 57	switch (reg) {
 58	case CS530X_CLK_CFG_0:
 59	case CS530X_CLK_CFG_1:
 60	case CS530X_CHIP_ENABLE:
 61	case CS530X_ASP_CFG:
 62	case CS530X_SIGNAL_PATH_CFG:
 63	case CS530X_IN_ENABLES:
 64	case CS530X_IN_RAMP_SUM:
 65	case CS530X_IN_FILTER:
 66	case CS530X_IN_HIZ:
 67	case CS530X_IN_INV:
 68	case CS530X_IN_VOL_CTRL1_0:
 69	case CS530X_IN_VOL_CTRL1_1:
 70	case CS530X_IN_VOL_CTRL2_0:
 71	case CS530X_IN_VOL_CTRL2_1:
 72	case CS530X_IN_VOL_CTRL3_0:
 73	case CS530X_IN_VOL_CTRL3_1:
 74	case CS530X_IN_VOL_CTRL4_0:
 75	case CS530X_IN_VOL_CTRL4_1:
 76	case CS530X_PAD_FN:
 77	case CS530X_PAD_LVL:
 78		return true;
 79	default:
 80		return false;
 81	}
 82}
 83
 84static bool cs530x_readable_register(struct device *dev, unsigned int reg)
 85{
 86	switch (reg) {
 87	case CS530X_DEVID:
 88	case CS530X_REVID:
 89		return true;
 90	default:
 91		return cs530x_read_and_write_regs(reg);
 92	}
 93}
 94
 95static bool cs530x_writeable_register(struct device *dev, unsigned int reg)
 96{
 97	switch (reg) {
 98	case CS530X_SW_RESET:
 99	case CS530X_IN_VOL_CTRL5:
100		return true;
101	default:
102		return cs530x_read_and_write_regs(reg);
103	}
104}
105
106static int cs530x_put_volsw_vu(struct snd_kcontrol *kcontrol,
107				struct snd_ctl_elem_value *ucontrol)
108{
109	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
110	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
111	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
112	struct regmap *regmap = cs530x->regmap;
113	int ret;
114
115	snd_soc_dapm_mutex_lock(dapm);
116
117	ret = snd_soc_put_volsw(kcontrol, ucontrol);
118	if (ret)
119		goto volsw_err;
120
121	/* Write IN_VU bit for the volume change to take effect */
122	regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_IN_VU);
123
124volsw_err:
125	snd_soc_dapm_mutex_unlock(dapm);
126
127	return ret;
128}
129
130static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0);
131
132static const char * const cs530x_in_filter_text[] = {
133	"Min Phase Slow Roll-off",
134	"Min Phase Fast Roll-off",
135	"Linear Phase Slow Roll-off",
136	"Linear Phase Fast Roll-off",
137};
138
139static SOC_ENUM_SINGLE_DECL(cs530x_in_filter_enum, CS530X_IN_FILTER,
140			    CS530X_IN_FILTER_SHIFT,
141			    cs530x_in_filter_text);
142
143static const char * const cs530x_in_4ch_sum_text[] = {
144	"None",
145	"Groups of 2",
146	"Groups of 4",
147};
148
149static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM,
150			    CS530X_IN_SUM_MODE_SHIFT,
151			    cs530x_in_4ch_sum_text);
152
153static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] = {
154SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum),
155};
156
157static const char * const cs530x_in_8ch_sum_text[] = {
158	"None",
159	"Groups of 2",
160	"Groups of 4",
161	"Groups of 8",
162};
163
164static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM,
165			    CS530X_IN_SUM_MODE_SHIFT,
166			    cs530x_in_8ch_sum_text);
167
168static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] = {
169SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum),
170};
171
172
173static const char * const cs530x_vol_ramp_text[] = {
174	"0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
175	"15ms/6dB", "30ms/6dB",
176};
177
178static SOC_ENUM_SINGLE_DECL(cs530x_ramp_inc_enum, CS530X_IN_RAMP_SUM,
179			    CS530X_RAMP_RATE_INC_SHIFT,
180			    cs530x_vol_ramp_text);
181
182static SOC_ENUM_SINGLE_DECL(cs530x_ramp_dec_enum, CS530X_IN_RAMP_SUM,
183			    CS530X_RAMP_RATE_DEC_SHIFT,
184			    cs530x_vol_ramp_text);
185
186static const struct snd_kcontrol_new cs530x_in_1_to_2_controls[] = {
187SOC_SINGLE_EXT_TLV("IN1 Volume", CS530X_IN_VOL_CTRL1_0, 0, 255, 1,
188		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
189SOC_SINGLE_EXT_TLV("IN2 Volume", CS530X_IN_VOL_CTRL1_1, 0, 255, 1,
190		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
191
192SOC_ENUM("IN DEC Filter Select", cs530x_in_filter_enum),
193SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum),
194SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum),
195
196SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_IN1_INV_SHIFT, 1, 0),
197SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_IN2_INV_SHIFT, 1, 0),
198};
199
200static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] = {
201SOC_SINGLE_EXT_TLV("IN3 Volume", CS530X_IN_VOL_CTRL2_0, 0, 255, 1,
202		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
203SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1,
204		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
205
206SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_IN3_INV_SHIFT, 1, 0),
207SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_IN4_INV_SHIFT, 1, 0),
208};
209
210static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] = {
211SOC_SINGLE_EXT_TLV("IN5 Volume", CS530X_IN_VOL_CTRL3_0, 0, 255, 1,
212		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
213SOC_SINGLE_EXT_TLV("IN6 Volume", CS530X_IN_VOL_CTRL3_1, 0, 255, 1,
214		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
215SOC_SINGLE_EXT_TLV("IN7 Volume", CS530X_IN_VOL_CTRL4_0, 0, 255, 1,
216		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
217SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1,
218		    snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv),
219
220SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_IN5_INV_SHIFT, 1, 0),
221SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_IN6_INV_SHIFT, 1, 0),
222SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_IN7_INV_SHIFT, 1, 0),
223SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_IN8_INV_SHIFT, 1, 0),
224};
225
226static int cs530x_adc_event(struct snd_soc_dapm_widget *w,
227			     struct snd_kcontrol *kcontrol, int event)
228{
229	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
230	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
231	struct regmap *regmap = cs530x->regmap;
232
233	switch (event) {
234	case SND_SOC_DAPM_PRE_PMU:
235		cs530x->adc_pairs_count++;
236		break;
237	case SND_SOC_DAPM_POST_PMU:
238		regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
239				 (w->shift * 2), CS530X_IN_MUTE);
240		regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
241				 ((w->shift+1) * 2), CS530X_IN_MUTE);
242
243		cs530x->adc_pairs_count--;
244		if (!cs530x->adc_pairs_count) {
245			usleep_range(1000, 1100);
246			return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
247					    CS530X_IN_VU);
248		}
249		break;
250	case SND_SOC_DAPM_PRE_PMD:
251		regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
252			       (w->shift * 2), CS530X_IN_MUTE);
253		regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 +
254			       ((w->shift+1) * 2), CS530X_IN_MUTE);
255		return regmap_write(regmap, CS530X_IN_VOL_CTRL5,
256				    CS530X_IN_VU);
257	default:
258		return -EINVAL;
259	}
260
261	return 0;
262}
263
264static const struct snd_kcontrol_new adc12_ctrl =
265	SOC_DAPM_SINGLE_VIRT("Switch", 1);
266
267static const struct snd_kcontrol_new adc34_ctrl =
268	SOC_DAPM_SINGLE_VIRT("Switch", 1);
269
270static const struct snd_kcontrol_new adc56_ctrl =
271	SOC_DAPM_SINGLE_VIRT("Switch", 1);
272
273static const struct snd_kcontrol_new adc78_ctrl =
274	SOC_DAPM_SINGLE_VIRT("Switch", 1);
275
276static const struct snd_kcontrol_new in_hpf_ctrl =
277	SOC_DAPM_SINGLE_VIRT("Switch", 1);
278
279/* General DAPM widgets for all devices */
280static const struct snd_soc_dapm_widget cs530x_gen_dapm_widgets[] = {
281SND_SOC_DAPM_SUPPLY("Global Enable", CS530X_CHIP_ENABLE, 0, 0, NULL, 0),
282};
283
284/* ADC's Channels 1 and 2 plus generic ADC DAPM events */
285static const struct snd_soc_dapm_widget cs530x_adc_ch12_dapm_widgets[] = {
286SND_SOC_DAPM_INPUT("IN1"),
287SND_SOC_DAPM_INPUT("IN2"),
288SND_SOC_DAPM_ADC_E("ADC1", NULL, CS530X_IN_ENABLES, 0, 0,
289		   cs530x_adc_event,
290		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
291		   SND_SOC_DAPM_PRE_PMU),
292SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0),
293SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl),
294SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_IN_HPF_EN_SHIFT,
295		    0, &in_hpf_ctrl),
296};
297
298/* ADC's Channels 3 and 4 */
299static const struct snd_soc_dapm_widget cs530x_adc_ch34_dapm_widgets[] = {
300SND_SOC_DAPM_INPUT("IN3"),
301SND_SOC_DAPM_INPUT("IN4"),
302SND_SOC_DAPM_ADC_E("ADC3", NULL, CS530X_IN_ENABLES, 2, 0,
303		   cs530x_adc_event,
304		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
305		   SND_SOC_DAPM_PRE_PMU),
306SND_SOC_DAPM_ADC("ADC4", NULL, CS530X_IN_ENABLES, 3, 0),
307SND_SOC_DAPM_SWITCH("ADC34 Enable", SND_SOC_NOPM, 0, 0, &adc34_ctrl),
308};
309
310/* ADC's Channels 5 to 8 */
311static const struct snd_soc_dapm_widget cs530x_adc_ch58_dapm_widgets[] = {
312SND_SOC_DAPM_INPUT("IN5"),
313SND_SOC_DAPM_INPUT("IN6"),
314SND_SOC_DAPM_INPUT("IN7"),
315SND_SOC_DAPM_INPUT("IN8"),
316SND_SOC_DAPM_ADC_E("ADC5", NULL, CS530X_IN_ENABLES, 4, 0,
317		   cs530x_adc_event,
318		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
319		   SND_SOC_DAPM_PRE_PMU),
320SND_SOC_DAPM_ADC("ADC6", NULL, CS530X_IN_ENABLES, 5, 0),
321SND_SOC_DAPM_SWITCH("ADC56 Enable", SND_SOC_NOPM, 0, 0, &adc56_ctrl),
322SND_SOC_DAPM_ADC_E("ADC7", NULL, CS530X_IN_ENABLES, 6, 0,
323		   cs530x_adc_event,
324		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU |
325		   SND_SOC_DAPM_PRE_PMU),
326SND_SOC_DAPM_ADC("ADC8", NULL, CS530X_IN_ENABLES, 7, 0),
327SND_SOC_DAPM_SWITCH("ADC78 Enable", SND_SOC_NOPM, 0, 0, &adc78_ctrl),
328};
329
330static const struct snd_soc_dapm_route adc_ch1_2_routes[] = {
331	{ "ADC1", NULL, "Global Enable" },
332	{ "ADC2", NULL, "Global Enable" },
333
334	{ "ADC12 Enable", "Switch", "IN1" },
335	{ "ADC12 Enable", "Switch", "IN2" },
336	{ "ADC1", NULL, "ADC12 Enable" },
337	{ "ADC2", NULL, "ADC12 Enable" },
338	{ "IN HPF", "Switch", "ADC1" },
339	{ "IN HPF", "Switch", "ADC2" },
340
341	{ "AIF Capture", NULL, "IN HPF" },
342	{ "AIF Capture", NULL, "ADC1" },
343	{ "AIF Capture", NULL, "ADC2" },
344};
345
346static const struct snd_soc_dapm_route adc_ch3_4_routes[] = {
347	{ "ADC3", NULL, "Global Enable" },
348	{ "ADC4", NULL, "Global Enable" },
349
350	{ "ADC34 Enable", "Switch", "IN3" },
351	{ "ADC34 Enable", "Switch", "IN4" },
352	{ "ADC3", NULL, "ADC34 Enable" },
353	{ "ADC4", NULL, "ADC34 Enable" },
354	{ "IN HPF", "Switch", "ADC3" },
355	{ "IN HPF", "Switch", "ADC4" },
356
357	{ "AIF Capture", NULL, "ADC3" },
358	{ "AIF Capture", NULL, "ADC4" },
359};
360
361static const struct snd_soc_dapm_route adc_ch5_8_routes[] = {
362	{ "ADC5", NULL, "Global Enable" },
363	{ "ADC6", NULL, "Global Enable" },
364	{ "ADC7", NULL, "Global Enable" },
365	{ "ADC8", NULL, "Global Enable" },
366
367	{ "ADC56 Enable", "Switch", "IN5" },
368	{ "ADC56 Enable", "Switch", "IN6" },
369	{ "ADC5", NULL, "ADC56 Enable" },
370	{ "ADC6", NULL, "ADC56 Enable" },
371	{ "IN HPF", "Switch", "ADC5" },
372	{ "IN HPF", "Switch", "ADC6" },
373
374	{ "AIF Capture", NULL, "ADC5" },
375	{ "AIF Capture", NULL, "ADC6" },
376
377	{ "ADC78 Enable", "Switch", "IN7" },
378	{ "ADC78 Enable", "Switch", "IN8" },
379	{ "ADC7", NULL, "ADC78 Enable" },
380	{ "ADC8", NULL, "ADC78 Enable" },
381	{ "IN HPF", "Switch", "ADC7" },
382	{ "IN HPF", "Switch", "ADC8" },
383
384	{ "AIF Capture", NULL, "ADC7" },
385	{ "AIF Capture", NULL, "ADC8" },
386};
387
388static void cs530x_add_12_adc_widgets(struct snd_soc_component *component)
389{
390	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
391
392	snd_soc_add_component_controls(component,
393				       cs530x_in_1_to_2_controls,
394				       ARRAY_SIZE(cs530x_in_1_to_2_controls));
395
396	snd_soc_dapm_new_controls(dapm, cs530x_adc_ch12_dapm_widgets,
397				  ARRAY_SIZE(cs530x_adc_ch12_dapm_widgets));
398
399	snd_soc_dapm_add_routes(dapm, adc_ch1_2_routes,
400				ARRAY_SIZE(adc_ch1_2_routes));
401}
402
403static void cs530x_add_34_adc_widgets(struct snd_soc_component *component)
404{
405	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
406
407	snd_soc_add_component_controls(component,
408				       cs530x_in_3_to_4_controls,
409				       ARRAY_SIZE(cs530x_in_3_to_4_controls));
410
411	snd_soc_dapm_new_controls(dapm, cs530x_adc_ch34_dapm_widgets,
412				  ARRAY_SIZE(cs530x_adc_ch34_dapm_widgets));
413
414	snd_soc_dapm_add_routes(dapm, adc_ch3_4_routes,
415				ARRAY_SIZE(adc_ch3_4_routes));
416}
417
418static int cs530x_set_bclk(struct snd_soc_component *component, const int freq)
419{
420	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
421	struct regmap *regmap = cs530x->regmap;
422	unsigned int bclk_val;
423
424	switch (freq) {
425	case 2822400:
426	case 3072000:
427		bclk_val = CS530X_BCLK_2P822_3P072;
428		break;
429	case 5644800:
430	case 6144000:
431		bclk_val = CS530X_BCLK_5P6448_6P144;
432		break;
433	case 11289600:
434	case 12288000:
435		bclk_val = CS530X_BCLK_11P2896_12P288;
436		break;
437	case 22579200:
438	case 24576000:
439		bclk_val = CS530X_BCLK_24P5792_24P576;
440		break;
441	default:
442		dev_err(component->dev, "Invalid BCLK frequency %d\n", freq);
443		return -EINVAL;
444	}
445
446	dev_dbg(component->dev, "BCLK frequency is %d\n", freq);
447
448	return regmap_update_bits(regmap, CS530X_ASP_CFG,
449				  CS530X_ASP_BCLK_FREQ_MASK, bclk_val);
450}
451
452static int cs530x_set_pll_refclk(struct snd_soc_component *component,
453				  const unsigned int freq)
454{
455	struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
456	struct regmap *regmap = priv->regmap;
457	unsigned int refclk;
458
459	switch (freq) {
460	case 2822400:
461	case 3072000:
462		refclk = CS530X_REFCLK_2P822_3P072;
463		break;
464	case 5644800:
465	case 6144000:
466		refclk = CS530X_REFCLK_5P6448_6P144;
467		break;
468	case 11289600:
469	case 12288000:
470		refclk = CS530X_REFCLK_11P2896_12P288;
471		break;
472	case 22579200:
473	case 24576000:
474		refclk = CS530X_REFCLK_24P5792_24P576;
475		break;
476	default:
477		dev_err(component->dev, "Invalid PLL refclk %d\n", freq);
478		return -EINVAL;
479	}
480
481	return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
482				  CS530X_PLL_REFCLK_FREQ_MASK, refclk);
483}
484
485static int cs530x_hw_params(struct snd_pcm_substream *substream,
486			    struct snd_pcm_hw_params *params,
487			    struct snd_soc_dai *dai)
488{
489	struct snd_soc_component *component = dai->component;
490	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
491	struct regmap *regmap = cs530x->regmap;
492	int ret = 0, fs = params_rate(params), bclk;
493	unsigned int fs_val;
494
495
496	switch (fs) {
497	case 32000:
498		fs_val = CS530X_FS_32K;
499		break;
500	case 44100:
501	case 48000:
502		fs_val = CS530X_FS_48K_44P1K;
503		break;
504	case 88200:
505	case 96000:
506		fs_val = CS530X_FS_96K_88P2K;
507		break;
508	case 176400:
509	case 192000:
510		fs_val = CS530X_FS_192K_176P4K;
511		break;
512	case 356800:
513	case 384000:
514		fs_val = CS530X_FS_384K_356P8K;
515		break;
516	case 705600:
517	case 768000:
518		fs_val = CS530X_FS_768K_705P6K;
519		break;
520	default:
521		dev_err(component->dev, "Invalid sample rate %d\n", fs);
522		return -EINVAL;
523	}
524
525	cs530x->fs = fs;
526	regmap_update_bits(regmap, CS530X_CLK_CFG_1,
527			   CS530X_SAMPLE_RATE_MASK, fs_val);
528
529
530	if (regmap_test_bits(regmap, CS530X_SIGNAL_PATH_CFG,
531			     CS530X_TDM_EN_MASK)) {
532		dev_dbg(component->dev, "Configuring for %d %d bit TDM slots\n",
533			cs530x->tdm_slots, cs530x->tdm_width);
534		bclk = snd_soc_tdm_params_to_bclk(params,
535						  cs530x->tdm_width,
536						  cs530x->tdm_slots,
537						  1);
538	} else {
539		bclk = snd_soc_params_to_bclk(params);
540	}
541
542	if (!regmap_test_bits(regmap, CS530X_CLK_CFG_0,
543			     CS530X_PLL_REFCLK_SRC_MASK)) {
544		ret = cs530x_set_pll_refclk(component, bclk);
545		if (ret)
546			return ret;
547	}
548
549	return cs530x_set_bclk(component, bclk);
550}
551
552static int cs530x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
553{
554	struct snd_soc_component *component = dai->component;
555	struct cs530x_priv *priv = snd_soc_component_get_drvdata(component);
556	struct regmap *regmap = priv->regmap;
557	unsigned int asp_fmt, asp_cfg = 0;
558
559	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
560	case SND_SOC_DAIFMT_CBS_CFS:
561		break;
562	case SND_SOC_DAIFMT_CBM_CFM:
563		asp_cfg = CS530X_ASP_PRIMARY;
564		break;
565	default:
566		return -EINVAL;
567	}
568
569	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
570	case SND_SOC_DAIFMT_DSP_A:
571		asp_fmt = CS530X_ASP_FMT_DSP_A;
572		break;
573	case SND_SOC_DAIFMT_I2S:
574		asp_fmt = CS530X_ASP_FMT_I2S;
575		break;
576	case SND_SOC_DAIFMT_LEFT_J:
577		asp_fmt = CS530X_ASP_FMT_LJ;
578		break;
579	default:
580		return -EINVAL;
581	}
582
583	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
584	case SND_SOC_DAIFMT_NB_NF:
585		break;
586	case SND_SOC_DAIFMT_IB_IF:
587		asp_cfg |= CS530X_ASP_BCLK_INV;
588		break;
589	default:
590		return -EINVAL;
591	}
592
593	regmap_update_bits(regmap, CS530X_ASP_CFG,
594			   CS530X_ASP_PRIMARY | CS530X_ASP_BCLK_INV,
595			   asp_cfg);
596
597	return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
598				  CS530X_ASP_FMT_MASK, asp_fmt);
599}
600
601static bool cs530x_check_mclk_freq(struct snd_soc_component *component,
602				   const unsigned int freq)
603{
604	switch (freq) {
605	case 24576000:
606	case 22579200:
607	case 12288000:
608	case 11289600:
609		return true;
610	default:
611		dev_err(component->dev, "Invalid MCLK %d\n", freq);
612		return false;
613	}
614}
615
616static int cs530x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
617				 unsigned int rx_mask, int slots, int slot_width)
618{
619	struct snd_soc_component *component = dai->component;
620	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
621	struct regmap *regmap = cs530x->regmap;
622	unsigned int val;
623
624	switch (tx_mask) {
625	case CS530X_0_1_TDM_SLOT_MASK:
626	case CS530X_0_3_TDM_SLOT_MASK:
627	case CS530X_0_7_TDM_SLOT_MASK:
628		val = CS530X_0_7_TDM_SLOT_VAL;
629		break;
630	case CS530X_2_3_TDM_SLOT_MASK:
631		val = CS530X_2_3_TDM_SLOT_VAL;
632		break;
633	case CS530X_4_5_TDM_SLOT_MASK:
634	case CS530X_4_7_TDM_SLOT_MASK:
635		val = CS530X_4_7_TDM_SLOT_VAL;
636		break;
637	case CS530X_6_7_TDM_SLOT_MASK:
638		val = CS530X_6_7_TDM_SLOT_VAL;
639		break;
640	case CS530X_8_9_TDM_SLOT_MASK:
641	case CS530X_8_11_TDM_SLOT_MASK:
642	case CS530X_8_15_TDM_SLOT_MASK:
643		val = CS530X_8_15_TDM_SLOT_VAL;
644		break;
645	case CS530X_10_11_TDM_SLOT_MASK:
646		val = CS530X_10_11_TDM_SLOT_VAL;
647		break;
648	case CS530X_12_13_TDM_SLOT_MASK:
649	case CS530X_12_15_TDM_SLOT_MASK:
650		val = CS530X_12_15_TDM_SLOT_VAL;
651		break;
652	case CS530X_14_15_TDM_SLOT_MASK:
653		val = CS530X_14_15_TDM_SLOT_VAL;
654		break;
655	default:
656		dev_err(component->dev, "Invalid TX slot(s) 0x%x\n", tx_mask);
657		return -EINVAL;
658	}
659
660	cs530x->tdm_width = slot_width;
661	cs530x->tdm_slots = slots;
662
663	return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG,
664				  CS530X_ASP_TDM_SLOT_MASK,
665				  val << CS530X_ASP_TDM_SLOT_SHIFT);
666}
667
668static const struct snd_soc_dai_ops cs530x_dai_ops = {
669	.set_fmt = cs530x_set_fmt,
670	.hw_params = cs530x_hw_params,
671	.set_tdm_slot = cs530x_set_tdm_slot,
672};
673
674static const struct snd_soc_dai_driver cs530x_dai = {
675	.name = "cs530x-dai",
676	.capture = {
677		.stream_name = "AIF Capture",
678		.channels_min = 2,
679		.channels_max = 8,
680		.rates = SNDRV_PCM_RATE_KNOT,
681		.formats = SNDRV_PCM_FMTBIT_S32_LE,
682	},
683	.ops = &cs530x_dai_ops,
684	.symmetric_rate = 1,
685	.symmetric_sample_bits = 1,
686};
687
688static int cs530x_set_pll(struct snd_soc_component *component, int pll_id,
689			   int source, unsigned int freq_in,
690			   unsigned int freq_out)
691{
692	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
693	struct regmap *regmap = cs530x->regmap;
694	unsigned int sysclk_src;
695	int ret;
696
697	regmap_read(regmap, CS530X_CLK_CFG_0, &sysclk_src);
698
699	/* Check if the source is the PLL  */
700	if ((sysclk_src & CS530X_SYSCLK_SRC_MASK) == 0)
701		return 0;
702
703	switch (source) {
704	case CS530X_PLL_SRC_MCLK:
705		if (!cs530x_check_mclk_freq(component, freq_in))
706			return -EINVAL;
707
708		ret = cs530x_set_pll_refclk(component, freq_in);
709		if (ret)
710			return ret;
711
712		break;
713	case CS530X_PLL_SRC_BCLK:
714		break;
715	default:
716		dev_err(component->dev, "Invalid PLL source %d\n", source);
717		return -EINVAL;
718	}
719
720	return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
721				  CS530X_PLL_REFCLK_SRC_MASK, source);
722}
723
724static int cs530x_component_probe(struct snd_soc_component *component)
725{
726	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
727	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
728	int num_widgets;
729
730	snd_soc_dapm_new_controls(dapm, cs530x_gen_dapm_widgets,
731				  ARRAY_SIZE(cs530x_gen_dapm_widgets));
732
733	switch (cs530x->devtype) {
734	case CS5302:
735		cs530x_add_12_adc_widgets(component);
736		break;
737	case CS5304:
738		cs530x_add_12_adc_widgets(component);
739		cs530x_add_34_adc_widgets(component);
740
741		num_widgets = ARRAY_SIZE(cs530x_in_sum_4ch_controls);
742		snd_soc_add_component_controls(component,
743					       cs530x_in_sum_4ch_controls,
744					       num_widgets);
745		break;
746
747	case CS5308:
748		cs530x_add_12_adc_widgets(component);
749		cs530x_add_34_adc_widgets(component);
750
751		num_widgets = ARRAY_SIZE(cs530x_in_5_to_8_controls);
752		snd_soc_add_component_controls(component,
753					       cs530x_in_5_to_8_controls,
754					       num_widgets);
755
756		num_widgets = ARRAY_SIZE(cs530x_in_sum_8ch_controls);
757		snd_soc_add_component_controls(component,
758					       cs530x_in_sum_8ch_controls,
759					       num_widgets);
760
761		num_widgets = ARRAY_SIZE(cs530x_adc_ch58_dapm_widgets);
762		snd_soc_dapm_new_controls(dapm, cs530x_adc_ch58_dapm_widgets,
763					  num_widgets);
764
765		snd_soc_dapm_add_routes(dapm, adc_ch5_8_routes,
766					ARRAY_SIZE(adc_ch5_8_routes));
767		break;
768	default:
769		dev_err(component->dev, "Invalid device type %d\n",
770			cs530x->devtype);
771		return -EINVAL;
772	}
773
774	return 0;
775}
776
777static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id,
778				int source, unsigned int freq, int dir)
779{
780	struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component);
781	struct regmap *regmap = cs530x->regmap;
782
783	switch (source) {
784	case CS530X_SYSCLK_SRC_MCLK:
785		if (freq != 24560000 && freq != 22572000) {
786			dev_err(component->dev, "Invalid MCLK source rate %d\n",
787				freq);
788			return -EINVAL;
789		}
790
791		cs530x->mclk_rate = freq;
792		break;
793	case CS530X_SYSCLK_SRC_PLL:
794		break;
795	default:
796		dev_err(component->dev, "Invalid clock id %d\n", clk_id);
797		return -EINVAL;
798	}
799
800	return regmap_update_bits(regmap, CS530X_CLK_CFG_0,
801				  CS530X_SYSCLK_SRC_MASK,
802				  source << CS530X_SYSCLK_SRC_SHIFT);
803}
804
805static const struct snd_soc_component_driver soc_component_dev_cs530x = {
806	.probe			= cs530x_component_probe,
807	.set_sysclk		= cs530x_set_sysclk,
808	.set_pll		= cs530x_set_pll,
809	.endianness		= 1,
810};
811
812const struct regmap_config cs530x_regmap = {
813	.reg_bits = 16,
814	.val_bits = 16,
815
816	.max_register = CS530X_MAX_REGISTER,
817	.readable_reg = cs530x_readable_register,
818	.writeable_reg = cs530x_writeable_register,
819
820	.cache_type = REGCACHE_MAPLE,
821	.reg_defaults = cs530x_reg_defaults,
822	.num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults),
823};
824EXPORT_SYMBOL_NS_GPL(cs530x_regmap, "SND_SOC_CS530X");
825
826static int cs530x_check_device_id(struct cs530x_priv *cs530x)
827{
828	struct device *dev = cs530x->dev;
829	unsigned int dev_id, rev;
830	int ret;
831
832	ret = regmap_read(cs530x->regmap, CS530X_DEVID, &dev_id);
833	if (ret)
834		return dev_err_probe(dev, ret, "Can't read device ID\n");
835
836	ret = regmap_read(cs530x->regmap, CS530X_REVID, &rev);
837	if (ret)
838		return dev_err_probe(dev, ret, "Can't read REV ID\n");
839
840	dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x\n", dev_id, rev);
841
842	switch (dev_id) {
843	case CS530X_2CH_ADC_DEV_ID:
844		cs530x->num_adcs = 2;
845		break;
846	case CS530X_4CH_ADC_DEV_ID:
847		cs530x->num_adcs = 4;
848		break;
849	case CS530X_8CH_ADC_DEV_ID:
850		cs530x->num_adcs = 8;
851		break;
852	default:
853		return dev_err_probe(dev, -EINVAL, "Invalid device ID 0x%x\n",
854				     dev_id);
855	}
856
857	return 0;
858}
859
860static int cs530x_parse_device_properties(struct cs530x_priv *cs530x)
861{
862	struct regmap *regmap = cs530x->regmap;
863	struct device *dev = cs530x->dev;
864	unsigned int val = 0;
865
866	switch (cs530x->num_adcs) {
867	case 8:
868		if (device_property_read_bool(dev, "cirrus,in-hiz-pin78"))
869			val = CS530X_IN78_HIZ;
870
871		if (device_property_read_bool(dev, "cirrus,in-hiz-pin56"))
872			val |= CS530X_IN56_HIZ;
873
874		fallthrough;
875	case 4:
876		if (device_property_read_bool(dev, "cirrus,in-hiz-pin34"))
877			val |= CS530X_IN34_HIZ;
878
879		fallthrough;
880	case 2:
881		if (device_property_read_bool(dev, "cirrus,in-hiz-pin12"))
882			val |= CS530X_IN12_HIZ;
883
884		return regmap_set_bits(regmap, CS530X_IN_HIZ, val);
885	default:
886		return dev_err_probe(dev, -EINVAL,
887				     "Invalid number of adcs %d\n",
888				     cs530x->num_adcs);
889	}
890}
891
892int cs530x_probe(struct cs530x_priv *cs530x)
893{
894	struct device *dev = cs530x->dev;
895	int ret, i;
896
897	cs530x->dev_dai = devm_kmemdup(dev, &cs530x_dai,
898					sizeof(*(cs530x->dev_dai)),
899					GFP_KERNEL);
900	if (!cs530x->dev_dai)
901		return -ENOMEM;
902
903	for (i = 0; i < ARRAY_SIZE(cs530x->supplies); i++)
904		cs530x->supplies[i].supply = cs530x_supply_names[i];
905
906	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs530x->supplies),
907				      cs530x->supplies);
908	if (ret != 0)
909		return dev_err_probe(dev, ret, "Failed to request supplies");
910
911	ret = regulator_bulk_enable(ARRAY_SIZE(cs530x->supplies),
912				    cs530x->supplies);
913	if (ret != 0)
914		return dev_err_probe(dev, ret, "Failed to enable supplies");
915
916	cs530x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
917						      GPIOD_OUT_HIGH);
918	if (IS_ERR(cs530x->reset_gpio)) {
919		ret = dev_err_probe(dev, PTR_ERR(cs530x->reset_gpio),
920			      "Reset gpio not available\n");
921		goto err_regulator;
922	}
923
924	if (cs530x->reset_gpio) {
925		usleep_range(2000, 2100);
926		gpiod_set_value_cansleep(cs530x->reset_gpio, 0);
927	}
928
929	usleep_range(5000, 5100);
930	ret = cs530x_check_device_id(cs530x);
931	if (ret)
932		goto err_reset;
933
934	if (!cs530x->reset_gpio) {
935		ret = regmap_write(cs530x->regmap, CS530X_SW_RESET,
936				   CS530X_SW_RST_VAL);
937		if (ret) {
938			dev_err_probe(dev, ret, "Soft Reset Failed\n");
939			goto err_reset;
940		}
941	}
942
943	ret = cs530x_parse_device_properties(cs530x);
944	if (ret)
945		goto err_reset;
946
947	cs530x->dev_dai->capture.channels_max = cs530x->num_adcs;
948
949	ret = devm_snd_soc_register_component(dev,
950			&soc_component_dev_cs530x, cs530x->dev_dai, 1);
951	if (ret) {
952		dev_err_probe(dev, ret, "Can't register cs530x component\n");
953		goto err_reset;
954	}
955
956	return 0;
957
958err_reset:
959	gpiod_set_value_cansleep(cs530x->reset_gpio, 1);
960
961err_regulator:
962	regulator_bulk_disable(ARRAY_SIZE(cs530x->supplies),
963			       cs530x->supplies);
964
965	return ret;
966}
967EXPORT_SYMBOL_NS_GPL(cs530x_probe, "SND_SOC_CS530X");
968
969MODULE_DESCRIPTION("CS530X CODEC Driver");
970MODULE_AUTHOR("Paul Handrigan <paulha@opensource.cirrus.com>");
971MODULE_LICENSE("GPL");