xref: /openbmc/linux/sound/soc/codecs/adau7118.c (revision bbb774d9)
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 
35 struct 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 */
47 static 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 
54 static 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 
88 static 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 
105 static 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 
109 static 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 
116 static 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 
123 static 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 
145 static 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 
208 static 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 
226 static 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 
264 static 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 
326 static 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 
385 static 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 
414 static 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 
422 static 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 
438 static 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 
447 static void adau7118_regulator_disable(void *data)
448 {
449 	struct adau7118_data *st = data;
450 	int ret;
451 	/*
452 	 * If we fail to disable DVDD, don't bother in trying IOVDD. We
453 	 * actually don't want to be left in the situation where DVDD
454 	 * is enabled and IOVDD is disabled.
455 	 */
456 	ret = regulator_disable(st->dvdd);
457 	if (ret)
458 		return;
459 
460 	regulator_disable(st->iovdd);
461 }
462 
463 static int adau7118_regulator_setup(struct adau7118_data *st)
464 {
465 	st->iovdd = devm_regulator_get(st->dev, "iovdd");
466 	if (IS_ERR(st->iovdd)) {
467 		dev_err(st->dev, "Could not get iovdd: %ld\n",
468 			PTR_ERR(st->iovdd));
469 		return PTR_ERR(st->iovdd);
470 	}
471 
472 	st->dvdd = devm_regulator_get(st->dev, "dvdd");
473 	if (IS_ERR(st->dvdd)) {
474 		dev_err(st->dev, "Could not get dvdd: %ld\n",
475 			PTR_ERR(st->dvdd));
476 		return PTR_ERR(st->dvdd);
477 	}
478 	/* just assume the device is in reset */
479 	if (!st->hw_mode) {
480 		regcache_mark_dirty(st->map);
481 		regcache_cache_only(st->map, true);
482 	}
483 
484 	return devm_add_action_or_reset(st->dev, adau7118_regulator_disable,
485 					st);
486 }
487 
488 static int adau7118_parset_dt(const struct adau7118_data *st)
489 {
490 	int ret;
491 	u32 dec_ratio = 0;
492 	/* 4 inputs */
493 	u32 clk_map[4], regval;
494 
495 	if (st->hw_mode)
496 		return 0;
497 
498 	ret = device_property_read_u32(st->dev, "adi,decimation-ratio",
499 				       &dec_ratio);
500 	if (!ret) {
501 		switch (dec_ratio) {
502 		case 64:
503 			regval = ADAU7118_DEC_RATIO(0);
504 			break;
505 		case 32:
506 			regval = ADAU7118_DEC_RATIO(1);
507 			break;
508 		case 16:
509 			regval = ADAU7118_DEC_RATIO(2);
510 			break;
511 		default:
512 			dev_err(st->dev, "Invalid dec ratio: %u", dec_ratio);
513 			return -EINVAL;
514 		}
515 
516 		ret = regmap_update_bits(st->map,
517 					 ADAU7118_REG_DEC_RATIO_CLK_MAP,
518 					 ADAU7118_DEC_RATIO_MASK, regval);
519 		if (ret)
520 			return ret;
521 	}
522 
523 	ret = device_property_read_u32_array(st->dev, "adi,pdm-clk-map",
524 					     clk_map, ARRAY_SIZE(clk_map));
525 	if (!ret) {
526 		int pdm;
527 		u32 _clk_map = 0;
528 
529 		for (pdm = 0; pdm < ARRAY_SIZE(clk_map); pdm++)
530 			_clk_map |= (clk_map[pdm] << (pdm + 4));
531 
532 		ret = regmap_update_bits(st->map,
533 					 ADAU7118_REG_DEC_RATIO_CLK_MAP,
534 					 ADAU7118_CLK_MAP_MASK, _clk_map);
535 		if (ret)
536 			return ret;
537 	}
538 
539 	return 0;
540 }
541 
542 int adau7118_probe(struct device *dev, struct regmap *map, bool hw_mode)
543 {
544 	struct adau7118_data *st;
545 	int ret;
546 
547 	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
548 	if (!st)
549 		return -ENOMEM;
550 
551 	st->dev = dev;
552 	st->hw_mode = hw_mode;
553 	dev_set_drvdata(dev, st);
554 
555 	if (!hw_mode) {
556 		st->map = map;
557 		adau7118_dai.ops = &adau7118_ops;
558 		/*
559 		 * Perform a full soft reset. This will set all register's
560 		 * with their reset values.
561 		 */
562 		ret = regmap_update_bits(map, ADAU7118_REG_RESET,
563 					 ADAU7118_FULL_SOFT_R_MASK,
564 					 ADAU7118_FULL_SOFT_R(1));
565 		if (ret)
566 			return ret;
567 	}
568 
569 	ret = adau7118_parset_dt(st);
570 	if (ret)
571 		return ret;
572 
573 	ret = adau7118_regulator_setup(st);
574 	if (ret)
575 		return ret;
576 
577 	return devm_snd_soc_register_component(dev,
578 					       &adau7118_component_driver,
579 					       &adau7118_dai, 1);
580 }
581 EXPORT_SYMBOL_GPL(adau7118_probe);
582 
583 MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
584 MODULE_DESCRIPTION("ADAU7118 8 channel PDM-to-I2S/TDM Converter driver");
585 MODULE_LICENSE("GPL");
586