1// SPDX-License-Identifier: GPL-2.0
2//
3// Analog Devices ADAU7118 8 channel PDM-to-I2S/TDM Converter driver
4//
5// Copyright 2019 Analog Devices Inc.
6
7#include <linux/bitfield.h>
8#include <linux/module.h>
9#include <linux/regmap.h>
10#include <linux/regulator/consumer.h>
11#include <sound/pcm_params.h>
12#include <sound/soc.h>
13
14#include "adau7118.h"
15
16#define ADAU7118_DEC_RATIO_MASK		GENMASK(1, 0)
17#define ADAU7118_DEC_RATIO(x)		FIELD_PREP(ADAU7118_DEC_RATIO_MASK, x)
18#define ADAU7118_CLK_MAP_MASK		GENMASK(7, 4)
19#define ADAU7118_SLOT_WIDTH_MASK	GENMASK(5, 4)
20#define ADAU7118_SLOT_WIDTH(x)		FIELD_PREP(ADAU7118_SLOT_WIDTH_MASK, x)
21#define ADAU7118_TRISTATE_MASK		BIT(6)
22#define ADAU7118_TRISTATE(x)		FIELD_PREP(ADAU7118_TRISTATE_MASK, x)
23#define ADAU7118_DATA_FMT_MASK		GENMASK(3, 1)
24#define ADAU7118_DATA_FMT(x)		FIELD_PREP(ADAU7118_DATA_FMT_MASK, x)
25#define ADAU7118_SAI_MODE_MASK		BIT(0)
26#define ADAU7118_SAI_MODE(x)		FIELD_PREP(ADAU7118_SAI_MODE_MASK, x)
27#define ADAU7118_LRCLK_BCLK_POL_MASK	GENMASK(1, 0)
28#define ADAU7118_LRCLK_BCLK_POL(x) \
29				FIELD_PREP(ADAU7118_LRCLK_BCLK_POL_MASK, x)
30#define ADAU7118_SPT_SLOT_MASK		GENMASK(7, 4)
31#define ADAU7118_SPT_SLOT(x)		FIELD_PREP(ADAU7118_SPT_SLOT_MASK, x)
32#define ADAU7118_FULL_SOFT_R_MASK	BIT(1)
33#define ADAU7118_FULL_SOFT_R(x)		FIELD_PREP(ADAU7118_FULL_SOFT_R_MASK, x)
34
35struct adau7118_data {
36	struct regmap *map;
37	struct device *dev;
38	struct regulator *iovdd;
39	struct regulator *dvdd;
40	u32 slot_width;
41	u32 slots;
42	bool hw_mode;
43	bool right_j;
44};
45
46/* Input Enable */
47static const struct snd_kcontrol_new adau7118_dapm_pdm_control[4] = {
48	SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 0, 1, 0),
49	SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 1, 1, 0),
50	SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 2, 1, 0),
51	SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 3, 1, 0),
52};
53
54static const struct snd_soc_dapm_widget adau7118_widgets_sw[] = {
55	/* Input Enable Switches */
56	SND_SOC_DAPM_SWITCH("PDM0", SND_SOC_NOPM, 0, 0,
57			    &adau7118_dapm_pdm_control[0]),
58	SND_SOC_DAPM_SWITCH("PDM1", SND_SOC_NOPM, 0, 0,
59			    &adau7118_dapm_pdm_control[1]),
60	SND_SOC_DAPM_SWITCH("PDM2", SND_SOC_NOPM, 0, 0,
61			    &adau7118_dapm_pdm_control[2]),
62	SND_SOC_DAPM_SWITCH("PDM3", SND_SOC_NOPM, 0, 0,
63			    &adau7118_dapm_pdm_control[3]),
64
65	/* PDM Clocks */
66	SND_SOC_DAPM_SUPPLY("PDM_CLK0", ADAU7118_REG_ENABLES, 4, 0, NULL, 0),
67	SND_SOC_DAPM_SUPPLY("PDM_CLK1", ADAU7118_REG_ENABLES, 5, 0, NULL, 0),
68
69	/* Output channels */
70	SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, ADAU7118_REG_SPT_CX(0),
71			     0, 0),
72	SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 0, ADAU7118_REG_SPT_CX(1),
73			     0, 0),
74	SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 0, ADAU7118_REG_SPT_CX(2),
75			     0, 0),
76	SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 0, ADAU7118_REG_SPT_CX(3),
77			     0, 0),
78	SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 0, ADAU7118_REG_SPT_CX(4),
79			     0, 0),
80	SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 0, ADAU7118_REG_SPT_CX(5),
81			     0, 0),
82	SND_SOC_DAPM_AIF_OUT("AIF1TX7", "Capture", 0, ADAU7118_REG_SPT_CX(6),
83			     0, 0),
84	SND_SOC_DAPM_AIF_OUT("AIF1TX8", "Capture", 0, ADAU7118_REG_SPT_CX(7),
85			     0, 0),
86};
87
88static const struct snd_soc_dapm_route adau7118_routes_sw[] = {
89	{ "PDM0", "Capture Switch", "PDM_DAT0" },
90	{ "PDM1", "Capture Switch", "PDM_DAT1" },
91	{ "PDM2", "Capture Switch", "PDM_DAT2" },
92	{ "PDM3", "Capture Switch", "PDM_DAT3" },
93	{ "AIF1TX1", NULL, "PDM0" },
94	{ "AIF1TX2", NULL, "PDM0" },
95	{ "AIF1TX3", NULL, "PDM1" },
96	{ "AIF1TX4", NULL, "PDM1" },
97	{ "AIF1TX5", NULL, "PDM2" },
98	{ "AIF1TX6", NULL, "PDM2" },
99	{ "AIF1TX7", NULL, "PDM3" },
100	{ "AIF1TX8", NULL, "PDM3" },
101	{ "Capture", NULL, "PDM_CLK0" },
102	{ "Capture", NULL, "PDM_CLK1" },
103};
104
105static const struct snd_soc_dapm_widget adau7118_widgets_hw[] = {
106	SND_SOC_DAPM_AIF_OUT("AIF1TX", "Capture", 0, SND_SOC_NOPM, 0, 0),
107};
108
109static const struct snd_soc_dapm_route adau7118_routes_hw[] = {
110	{ "AIF1TX", NULL, "PDM_DAT0" },
111	{ "AIF1TX", NULL, "PDM_DAT1" },
112	{ "AIF1TX", NULL, "PDM_DAT2" },
113	{ "AIF1TX", NULL, "PDM_DAT3" },
114};
115
116static const struct snd_soc_dapm_widget adau7118_widgets[] = {
117	SND_SOC_DAPM_INPUT("PDM_DAT0"),
118	SND_SOC_DAPM_INPUT("PDM_DAT1"),
119	SND_SOC_DAPM_INPUT("PDM_DAT2"),
120	SND_SOC_DAPM_INPUT("PDM_DAT3"),
121};
122
123static int adau7118_set_channel_map(struct snd_soc_dai *dai,
124				    unsigned int tx_num, unsigned int *tx_slot,
125				    unsigned int rx_num, unsigned int *rx_slot)
126{
127	struct adau7118_data *st =
128		snd_soc_component_get_drvdata(dai->component);
129	int chan, ret;
130
131	dev_dbg(st->dev, "Set channel map, %d", tx_num);
132
133	for (chan = 0; chan < tx_num; chan++) {
134		ret = snd_soc_component_update_bits(dai->component,
135					ADAU7118_REG_SPT_CX(chan),
136					ADAU7118_SPT_SLOT_MASK,
137					ADAU7118_SPT_SLOT(tx_slot[chan]));
138		if (ret < 0)
139			return ret;
140	}
141
142	return 0;
143}
144
145static int adau7118_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
146{
147	struct adau7118_data *st =
148		snd_soc_component_get_drvdata(dai->component);
149	int ret = 0;
150	u32 regval;
151
152	dev_dbg(st->dev, "Set format, fmt:%d\n", fmt);
153
154	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
155	case SND_SOC_DAIFMT_I2S:
156		ret = snd_soc_component_update_bits(dai->component,
157						    ADAU7118_REG_SPT_CTRL1,
158						    ADAU7118_DATA_FMT_MASK,
159						    ADAU7118_DATA_FMT(0));
160		break;
161	case SND_SOC_DAIFMT_LEFT_J:
162		ret = snd_soc_component_update_bits(dai->component,
163						    ADAU7118_REG_SPT_CTRL1,
164						    ADAU7118_DATA_FMT_MASK,
165						    ADAU7118_DATA_FMT(1));
166		break;
167	case SND_SOC_DAIFMT_RIGHT_J:
168		st->right_j = true;
169		break;
170	default:
171		dev_err(st->dev, "Invalid format %d",
172			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
173		return -EINVAL;
174	}
175
176	if (ret < 0)
177		return ret;
178
179	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
180	case SND_SOC_DAIFMT_NB_NF:
181		regval = ADAU7118_LRCLK_BCLK_POL(0);
182		break;
183	case SND_SOC_DAIFMT_NB_IF:
184		regval = ADAU7118_LRCLK_BCLK_POL(2);
185		break;
186	case SND_SOC_DAIFMT_IB_NF:
187		regval = ADAU7118_LRCLK_BCLK_POL(1);
188		break;
189	case SND_SOC_DAIFMT_IB_IF:
190		regval = ADAU7118_LRCLK_BCLK_POL(3);
191		break;
192	default:
193		dev_err(st->dev, "Invalid Inv mask %d",
194			fmt & SND_SOC_DAIFMT_INV_MASK);
195		return -EINVAL;
196	}
197
198	ret = snd_soc_component_update_bits(dai->component,
199					    ADAU7118_REG_SPT_CTRL2,
200					    ADAU7118_LRCLK_BCLK_POL_MASK,
201					    regval);
202	if (ret < 0)
203		return ret;
204
205	return 0;
206}
207
208static int adau7118_set_tristate(struct snd_soc_dai *dai, int tristate)
209{
210	struct adau7118_data *st =
211		snd_soc_component_get_drvdata(dai->component);
212	int ret;
213
214	dev_dbg(st->dev, "Set tristate, %d\n", tristate);
215
216	ret = snd_soc_component_update_bits(dai->component,
217					    ADAU7118_REG_SPT_CTRL1,
218					    ADAU7118_TRISTATE_MASK,
219					    ADAU7118_TRISTATE(tristate));
220	if (ret < 0)
221		return ret;
222
223	return 0;
224}
225
226static int adau7118_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
227				 unsigned int rx_mask, int slots,
228				 int slot_width)
229{
230	struct adau7118_data *st =
231		snd_soc_component_get_drvdata(dai->component);
232	int ret = 0;
233	u32 regval;
234
235	dev_dbg(st->dev, "Set tdm, slots:%d width:%d\n", slots, slot_width);
236
237	switch (slot_width) {
238	case 32:
239		regval = ADAU7118_SLOT_WIDTH(0);
240		break;
241	case 24:
242		regval = ADAU7118_SLOT_WIDTH(2);
243		break;
244	case 16:
245		regval = ADAU7118_SLOT_WIDTH(1);
246		break;
247	default:
248		dev_err(st->dev, "Invalid slot width:%d\n", slot_width);
249		return -EINVAL;
250	}
251
252	ret = snd_soc_component_update_bits(dai->component,
253					    ADAU7118_REG_SPT_CTRL1,
254					    ADAU7118_SLOT_WIDTH_MASK, regval);
255	if (ret < 0)
256		return ret;
257
258	st->slot_width = slot_width;
259	st->slots = slots;
260
261	return 0;
262}
263
264static int adau7118_hw_params(struct snd_pcm_substream *substream,
265			      struct snd_pcm_hw_params *params,
266			      struct snd_soc_dai *dai)
267{
268	struct adau7118_data *st =
269		snd_soc_component_get_drvdata(dai->component);
270	u32 data_width = params_width(params), slots_width;
271	int ret;
272	u32 regval;
273
274	if (!st->slots) {
275		/* set stereo mode */
276		ret = snd_soc_component_update_bits(dai->component,
277						    ADAU7118_REG_SPT_CTRL1,
278						    ADAU7118_SAI_MODE_MASK,
279						    ADAU7118_SAI_MODE(0));
280		if (ret < 0)
281			return ret;
282
283		slots_width = 32;
284	} else {
285		slots_width = st->slot_width;
286	}
287
288	if (data_width > slots_width) {
289		dev_err(st->dev, "Invalid data_width:%d, slots_width:%d",
290			data_width, slots_width);
291		return -EINVAL;
292	}
293
294	if (st->right_j) {
295		switch (slots_width - data_width) {
296		case 8:
297			/* delay bclck by 8 */
298			regval = ADAU7118_DATA_FMT(2);
299			break;
300		case 12:
301			/* delay bclck by 12 */
302			regval = ADAU7118_DATA_FMT(3);
303			break;
304		case 16:
305			/* delay bclck by 16 */
306			regval = ADAU7118_DATA_FMT(4);
307			break;
308		default:
309			dev_err(st->dev,
310				"Cannot set right_j setting, slot_w:%d, data_w:%d\n",
311					slots_width, data_width);
312			return -EINVAL;
313		}
314
315		ret = snd_soc_component_update_bits(dai->component,
316						    ADAU7118_REG_SPT_CTRL1,
317						    ADAU7118_DATA_FMT_MASK,
318						    regval);
319		if (ret < 0)
320			return ret;
321	}
322
323	return 0;
324}
325
326static int adau7118_set_bias_level(struct snd_soc_component *component,
327				   enum snd_soc_bias_level level)
328{
329	struct adau7118_data *st = snd_soc_component_get_drvdata(component);
330	int ret = 0;
331
332	dev_dbg(st->dev, "Set bias level %d\n", level);
333
334	switch (level) {
335	case SND_SOC_BIAS_ON:
336	case SND_SOC_BIAS_PREPARE:
337		break;
338
339	case SND_SOC_BIAS_STANDBY:
340		if (snd_soc_component_get_bias_level(component) ==
341							SND_SOC_BIAS_OFF) {
342			/* power on */
343			ret = regulator_enable(st->iovdd);
344			if (ret)
345				return ret;
346
347			/* there's no timing constraints before enabling dvdd */
348			ret = regulator_enable(st->dvdd);
349			if (ret) {
350				regulator_disable(st->iovdd);
351				return ret;
352			}
353
354			if (st->hw_mode)
355				return 0;
356
357			regcache_cache_only(st->map, false);
358			/* sync cache */
359			ret = snd_soc_component_cache_sync(component);
360		}
361		break;
362	case SND_SOC_BIAS_OFF:
363		/* power off */
364		ret = regulator_disable(st->dvdd);
365		if (ret)
366			return ret;
367
368		ret = regulator_disable(st->iovdd);
369		if (ret)
370			return ret;
371
372		if (st->hw_mode)
373			return 0;
374
375		/* cache only */
376		regcache_mark_dirty(st->map);
377		regcache_cache_only(st->map, true);
378
379		break;
380	}
381
382	return ret;
383}
384
385static int adau7118_component_probe(struct snd_soc_component *component)
386{
387	struct adau7118_data *st = snd_soc_component_get_drvdata(component);
388	struct snd_soc_dapm_context *dapm =
389					snd_soc_component_get_dapm(component);
390	int ret = 0;
391
392	if (st->hw_mode) {
393		ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_hw,
394					ARRAY_SIZE(adau7118_widgets_hw));
395		if (ret)
396			return ret;
397
398		ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_hw,
399					      ARRAY_SIZE(adau7118_routes_hw));
400	} else {
401		snd_soc_component_init_regmap(component, st->map);
402		ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_sw,
403					ARRAY_SIZE(adau7118_widgets_sw));
404		if (ret)
405			return ret;
406
407		ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_sw,
408					      ARRAY_SIZE(adau7118_routes_sw));
409	}
410
411	return ret;
412}
413
414static const struct snd_soc_dai_ops adau7118_ops = {
415	.hw_params = adau7118_hw_params,
416	.set_channel_map = adau7118_set_channel_map,
417	.set_fmt = adau7118_set_fmt,
418	.set_tdm_slot = adau7118_set_tdm_slot,
419	.set_tristate = adau7118_set_tristate,
420};
421
422static struct snd_soc_dai_driver adau7118_dai = {
423	.name = "adau7118-hifi-capture",
424	.capture = {
425		.stream_name = "Capture",
426		.channels_min = 1,
427		.channels_max = 8,
428		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |
429			SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S24_LE |
430			SNDRV_PCM_FMTBIT_S24_3LE,
431		.rates = SNDRV_PCM_RATE_CONTINUOUS,
432		.rate_min = 4000,
433		.rate_max = 192000,
434		.sig_bits = 24,
435	},
436};
437
438static const struct snd_soc_component_driver adau7118_component_driver = {
439	.probe			= adau7118_component_probe,
440	.set_bias_level		= adau7118_set_bias_level,
441	.dapm_widgets		= adau7118_widgets,
442	.num_dapm_widgets	= ARRAY_SIZE(adau7118_widgets),
443	.use_pmdown_time	= 1,
444	.endianness		= 1,
445};
446
447static int adau7118_regulator_setup(struct adau7118_data *st)
448{
449	st->iovdd = devm_regulator_get(st->dev, "iovdd");
450	if (IS_ERR(st->iovdd)) {
451		dev_err(st->dev, "Could not get iovdd: %ld\n",
452			PTR_ERR(st->iovdd));
453		return PTR_ERR(st->iovdd);
454	}
455
456	st->dvdd = devm_regulator_get(st->dev, "dvdd");
457	if (IS_ERR(st->dvdd)) {
458		dev_err(st->dev, "Could not get dvdd: %ld\n",
459			PTR_ERR(st->dvdd));
460		return PTR_ERR(st->dvdd);
461	}
462	/* just assume the device is in reset */
463	if (!st->hw_mode) {
464		regcache_mark_dirty(st->map);
465		regcache_cache_only(st->map, true);
466	}
467
468	return 0;
469}
470
471static int adau7118_parset_dt(const struct adau7118_data *st)
472{
473	int ret;
474	u32 dec_ratio = 0;
475	/* 4 inputs */
476	u32 clk_map[4], regval;
477
478	if (st->hw_mode)
479		return 0;
480
481	ret = device_property_read_u32(st->dev, "adi,decimation-ratio",
482				       &dec_ratio);
483	if (!ret) {
484		switch (dec_ratio) {
485		case 64:
486			regval = ADAU7118_DEC_RATIO(0);
487			break;
488		case 32:
489			regval = ADAU7118_DEC_RATIO(1);
490			break;
491		case 16:
492			regval = ADAU7118_DEC_RATIO(2);
493			break;
494		default:
495			dev_err(st->dev, "Invalid dec ratio: %u", dec_ratio);
496			return -EINVAL;
497		}
498
499		ret = regmap_update_bits(st->map,
500					 ADAU7118_REG_DEC_RATIO_CLK_MAP,
501					 ADAU7118_DEC_RATIO_MASK, regval);
502		if (ret)
503			return ret;
504	}
505
506	ret = device_property_read_u32_array(st->dev, "adi,pdm-clk-map",
507					     clk_map, ARRAY_SIZE(clk_map));
508	if (!ret) {
509		int pdm;
510		u32 _clk_map = 0;
511
512		for (pdm = 0; pdm < ARRAY_SIZE(clk_map); pdm++)
513			_clk_map |= (clk_map[pdm] << (pdm + 4));
514
515		ret = regmap_update_bits(st->map,
516					 ADAU7118_REG_DEC_RATIO_CLK_MAP,
517					 ADAU7118_CLK_MAP_MASK, _clk_map);
518		if (ret)
519			return ret;
520	}
521
522	return 0;
523}
524
525int adau7118_probe(struct device *dev, struct regmap *map, bool hw_mode)
526{
527	struct adau7118_data *st;
528	int ret;
529
530	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
531	if (!st)
532		return -ENOMEM;
533
534	st->dev = dev;
535	st->hw_mode = hw_mode;
536	dev_set_drvdata(dev, st);
537
538	if (!hw_mode) {
539		st->map = map;
540		adau7118_dai.ops = &adau7118_ops;
541		/*
542		 * Perform a full soft reset. This will set all register's
543		 * with their reset values.
544		 */
545		ret = regmap_update_bits(map, ADAU7118_REG_RESET,
546					 ADAU7118_FULL_SOFT_R_MASK,
547					 ADAU7118_FULL_SOFT_R(1));
548		if (ret)
549			return ret;
550	}
551
552	ret = adau7118_parset_dt(st);
553	if (ret)
554		return ret;
555
556	ret = adau7118_regulator_setup(st);
557	if (ret)
558		return ret;
559
560	return devm_snd_soc_register_component(dev,
561					       &adau7118_component_driver,
562					       &adau7118_dai, 1);
563}
564EXPORT_SYMBOL_GPL(adau7118_probe);
565
566MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
567MODULE_DESCRIPTION("ADAU7118 8 channel PDM-to-I2S/TDM Converter driver");
568MODULE_LICENSE("GPL");
569