xref: /linux/sound/soc/tegra/tegra210_adx.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES.
3 // All rights reserved.
4 //
5 // tegra210_adx.c - Tegra210 ADX driver
6 
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/io.h>
10 #include <linux/mod_devicetable.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/regmap.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 
21 #include "tegra210_adx.h"
22 #include "tegra_cif.h"
23 
24 static const struct reg_default tegra210_adx_reg_defaults[] = {
25 	{ TEGRA210_ADX_RX_INT_MASK, 0x00000001},
26 	{ TEGRA210_ADX_RX_CIF_CTRL, 0x00007000},
27 	{ TEGRA210_ADX_TX_INT_MASK, 0x0000000f },
28 	{ TEGRA210_ADX_TX1_CIF_CTRL, 0x00007000},
29 	{ TEGRA210_ADX_TX2_CIF_CTRL, 0x00007000},
30 	{ TEGRA210_ADX_TX3_CIF_CTRL, 0x00007000},
31 	{ TEGRA210_ADX_TX4_CIF_CTRL, 0x00007000},
32 	{ TEGRA210_ADX_CG, 0x1},
33 	{ TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000},
34 };
35 
36 static const struct reg_default tegra264_adx_reg_defaults[] = {
37 	{ TEGRA210_ADX_RX_INT_MASK, 0x00000001},
38 	{ TEGRA210_ADX_RX_CIF_CTRL, 0x00003800},
39 	{ TEGRA210_ADX_TX_INT_MASK, 0x0000000f },
40 	{ TEGRA210_ADX_TX1_CIF_CTRL, 0x00003800},
41 	{ TEGRA210_ADX_TX2_CIF_CTRL, 0x00003800},
42 	{ TEGRA210_ADX_TX3_CIF_CTRL, 0x00003800},
43 	{ TEGRA210_ADX_TX4_CIF_CTRL, 0x00003800},
44 	{ TEGRA210_ADX_CG, 0x1},
45 	{ TEGRA264_ADX_CFG_RAM_CTRL, 0x00004000},
46 };
47 
48 static void tegra210_adx_write_map_ram(struct tegra210_adx *adx)
49 {
50 	int i;
51 
52 	regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL +
53 			adx->soc_data->cya_offset,
54 		     TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
55 		     TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN |
56 		     TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE);
57 
58 	for (i = 0; i < adx->soc_data->ram_depth; i++)
59 		regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA +
60 				adx->soc_data->cya_offset,
61 			     adx->map[i]);
62 
63 	for (i = 0; i < adx->soc_data->byte_mask_size; i++)
64 		regmap_write(adx->regmap,
65 			     TEGRA210_ADX_IN_BYTE_EN0 + (i * TEGRA210_ADX_AUDIOCIF_CH_STRIDE),
66 			     adx->byte_mask[i]);
67 }
68 
69 static int tegra210_adx_startup(struct snd_pcm_substream *substream,
70 				struct snd_soc_dai *dai)
71 {
72 	struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
73 	unsigned int val;
74 	int err;
75 
76 	/* Ensure if ADX status is disabled */
77 	err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_STATUS,
78 				       val, !(val & 0x1), 10, 10000);
79 	if (err < 0) {
80 		dev_err(dai->dev, "failed to stop ADX, err = %d\n", err);
81 		return err;
82 	}
83 
84 	/*
85 	 * Soft Reset: Below performs module soft reset which clears
86 	 * all FSM logic, flushes flow control of FIFO and resets the
87 	 * state register. It also brings module back to disabled
88 	 * state (without flushing the data in the pipe).
89 	 */
90 	regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET,
91 			   TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK,
92 			   TEGRA210_ADX_SOFT_RESET_SOFT_EN);
93 
94 	err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET,
95 				       val, !(val & 0x1), 10, 10000);
96 	if (err < 0) {
97 		dev_err(dai->dev, "failed to reset ADX, err = %d\n", err);
98 		return err;
99 	}
100 
101 	return 0;
102 }
103 
104 static int tegra210_adx_runtime_suspend(struct device *dev)
105 {
106 	struct tegra210_adx *adx = dev_get_drvdata(dev);
107 
108 	regcache_cache_only(adx->regmap, true);
109 	regcache_mark_dirty(adx->regmap);
110 
111 	return 0;
112 }
113 
114 static int tegra210_adx_runtime_resume(struct device *dev)
115 {
116 	struct tegra210_adx *adx = dev_get_drvdata(dev);
117 
118 	regcache_cache_only(adx->regmap, false);
119 	regcache_sync(adx->regmap);
120 
121 	tegra210_adx_write_map_ram(adx);
122 
123 	return 0;
124 }
125 
126 static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
127 				      unsigned int channels,
128 				      snd_pcm_format_t format,
129 				      unsigned int reg)
130 {
131 	struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
132 	struct tegra_cif_conf cif_conf;
133 	int audio_bits;
134 
135 	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
136 
137 	if (channels < 1 || channels > adx->soc_data->max_ch) {
138 		dev_err(dai->dev, "invalid channels: %u (max %u)\n",
139 			channels, adx->soc_data->max_ch);
140 		return -EINVAL;
141 	}
142 
143 	switch (format) {
144 	case SNDRV_PCM_FORMAT_S8:
145 		audio_bits = TEGRA_ACIF_BITS_8;
146 		break;
147 	case SNDRV_PCM_FORMAT_S16_LE:
148 		audio_bits = TEGRA_ACIF_BITS_16;
149 		break;
150 	case SNDRV_PCM_FORMAT_S24_LE:
151 	case SNDRV_PCM_FORMAT_S32_LE:
152 		audio_bits = TEGRA_ACIF_BITS_32;
153 		break;
154 	default:
155 		dev_err(dai->dev, "unsupported format: %d\n", format);
156 		return -EINVAL;
157 	}
158 
159 	cif_conf.audio_ch = channels;
160 	cif_conf.client_ch = channels;
161 	cif_conf.audio_bits = audio_bits;
162 	cif_conf.client_bits = audio_bits;
163 
164 	if (adx->soc_data->max_ch == 32)
165 		tegra264_set_cif(adx->regmap, reg, &cif_conf);
166 	else
167 		tegra_set_cif(adx->regmap, reg, &cif_conf);
168 
169 	return 0;
170 }
171 
172 static int tegra210_adx_out_hw_params(struct snd_pcm_substream *substream,
173 				      struct snd_pcm_hw_params *params,
174 				      struct snd_soc_dai *dai)
175 {
176 	return tegra210_adx_set_audio_cif(dai, params_channels(params),
177 			params_format(params),
178 			TEGRA210_ADX_TX1_CIF_CTRL + ((dai->id - 1) * TEGRA210_ADX_AUDIOCIF_CH_STRIDE));
179 }
180 
181 static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream,
182 				     struct snd_pcm_hw_params *params,
183 				     struct snd_soc_dai *dai)
184 {
185 	return tegra210_adx_set_audio_cif(dai, params_channels(params),
186 					  params_format(params),
187 					  TEGRA210_ADX_RX_CIF_CTRL);
188 }
189 
190 static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
191 				     struct snd_ctl_elem_value *ucontrol)
192 {
193 	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
194 	struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
195 	struct soc_mixer_control *mc;
196 	unsigned char *bytes_map = (unsigned char *)adx->map;
197 	int enabled;
198 
199 	mc = (struct soc_mixer_control *)kcontrol->private_value;
200 	enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
201 
202 	/*
203 	 * TODO: Simplify this logic to just return from bytes_map[]
204 	 *
205 	 * Presently below is required since bytes_map[] is
206 	 * tightly packed and cannot store the control value of 256.
207 	 * Byte mask state is used to know if 256 needs to be returned.
208 	 * Note that for control value of 256, the put() call stores 0
209 	 * in the bytes_map[] and disables the corresponding bit in
210 	 * byte_mask[].
211 	 */
212 	if (enabled)
213 		ucontrol->value.integer.value[0] = bytes_map[mc->reg];
214 	else
215 		ucontrol->value.integer.value[0] = 256;
216 
217 	return 0;
218 }
219 
220 static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
221 				     struct snd_ctl_elem_value *ucontrol)
222 {
223 	struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
224 	struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
225 	unsigned char *bytes_map = (unsigned char *)adx->map;
226 	int value = ucontrol->value.integer.value[0];
227 	struct soc_mixer_control *mc =
228 		(struct soc_mixer_control *)kcontrol->private_value;
229 	unsigned int mask_val = adx->byte_mask[mc->reg / 32];
230 
231 	if (value >= 0 && value <= 255)
232 		mask_val |= (1 << (mc->reg % 32));
233 	else
234 		mask_val &= ~(1 << (mc->reg % 32));
235 
236 	if (mask_val == adx->byte_mask[mc->reg / 32])
237 		return 0;
238 
239 	/* Update byte map and slot */
240 	bytes_map[mc->reg] = value % 256;
241 	adx->byte_mask[mc->reg / 32] = mask_val;
242 
243 	return 1;
244 }
245 
246 static const struct snd_soc_dai_ops tegra210_adx_in_dai_ops = {
247 	.hw_params	= tegra210_adx_in_hw_params,
248 	.startup	= tegra210_adx_startup,
249 };
250 
251 static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
252 	.hw_params	= tegra210_adx_out_hw_params,
253 };
254 
255 #define IN_DAI							\
256 	{							\
257 		.name = "ADX-RX-CIF",				\
258 		.playback = {					\
259 			.stream_name = "RX-CIF-Playback",	\
260 			.channels_min = 1,			\
261 			.channels_max = 16,			\
262 			.rates = SNDRV_PCM_RATE_8000_192000,	\
263 			.formats = SNDRV_PCM_FMTBIT_S8 |	\
264 				   SNDRV_PCM_FMTBIT_S16_LE |	\
265 				   SNDRV_PCM_FMTBIT_S24_LE |	\
266 				   SNDRV_PCM_FMTBIT_S32_LE,	\
267 		},						\
268 		.capture = {					\
269 			.stream_name = "RX-CIF-Capture",	\
270 			.channels_min = 1,			\
271 			.channels_max = 16,			\
272 			.rates = SNDRV_PCM_RATE_8000_192000,	\
273 			.formats = SNDRV_PCM_FMTBIT_S8 |	\
274 				   SNDRV_PCM_FMTBIT_S16_LE |	\
275 				   SNDRV_PCM_FMTBIT_S24_LE |	\
276 				   SNDRV_PCM_FMTBIT_S32_LE,	\
277 		},						\
278 		.ops = &tegra210_adx_in_dai_ops,		\
279 	}
280 
281 #define OUT_DAI(id)						\
282 	{							\
283 		.name = "ADX-TX" #id "-CIF",			\
284 		.playback = {					\
285 			.stream_name = "TX" #id "-CIF-Playback",\
286 			.channels_min = 1,			\
287 			.channels_max = 16,			\
288 			.rates = SNDRV_PCM_RATE_8000_192000,	\
289 			.formats = SNDRV_PCM_FMTBIT_S8 |	\
290 				   SNDRV_PCM_FMTBIT_S16_LE |	\
291 				   SNDRV_PCM_FMTBIT_S24_LE |	\
292 				   SNDRV_PCM_FMTBIT_S32_LE,	\
293 		},						\
294 		.capture = {					\
295 			.stream_name = "TX" #id "-CIF-Capture",	\
296 			.channels_min = 1,			\
297 			.channels_max = 16,			\
298 			.rates = SNDRV_PCM_RATE_8000_192000,	\
299 			.formats = SNDRV_PCM_FMTBIT_S8 |	\
300 				   SNDRV_PCM_FMTBIT_S16_LE |	\
301 				   SNDRV_PCM_FMTBIT_S24_LE |	\
302 				   SNDRV_PCM_FMTBIT_S32_LE,	\
303 		},						\
304 		.ops = &tegra210_adx_out_dai_ops,		\
305 	}
306 
307 static struct snd_soc_dai_driver tegra210_adx_dais[] = {
308 	IN_DAI,
309 	OUT_DAI(1),
310 	OUT_DAI(2),
311 	OUT_DAI(3),
312 	OUT_DAI(4),
313 };
314 
315 static const struct snd_soc_dapm_widget tegra210_adx_widgets[] = {
316 	SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA210_ADX_ENABLE,
317 			    TEGRA210_ADX_ENABLE_SHIFT, 0),
318 	SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_ADX_CTRL, 0, 0),
319 	SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_ADX_CTRL, 1, 0),
320 	SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_ADX_CTRL, 2, 0),
321 	SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_ADX_CTRL, 3, 0),
322 };
323 
324 #define STREAM_ROUTES(id, sname)					  \
325 	{ "XBAR-" sname,		NULL,	"XBAR-TX" },		  \
326 	{ "RX-CIF-" sname,		NULL,	"XBAR-" sname },	  \
327 	{ "RX",				NULL,	"RX-CIF-" sname },	  \
328 	{ "TX" #id,			NULL,	"RX" },			  \
329 	{ "TX" #id "-CIF-" sname,	NULL,	"TX" #id },		  \
330 	{ "TX" #id " XBAR-" sname,	NULL,	"TX" #id "-CIF-" sname }, \
331 	{ "TX" #id " XBAR-RX",		NULL,	"TX" #id " XBAR-" sname }
332 
333 #define ADX_ROUTES(id)			\
334 	STREAM_ROUTES(id, "Playback"),	\
335 	STREAM_ROUTES(id, "Capture")
336 
337 #define STREAM_ROUTES(id, sname)					  \
338 	{ "XBAR-" sname,		NULL,	"XBAR-TX" },		  \
339 	{ "RX-CIF-" sname,		NULL,	"XBAR-" sname },	  \
340 	{ "RX",				NULL,	"RX-CIF-" sname },	  \
341 	{ "TX" #id,			NULL,	"RX" },			  \
342 	{ "TX" #id "-CIF-" sname,	NULL,	"TX" #id },		  \
343 	{ "TX" #id " XBAR-" sname,	NULL,	"TX" #id "-CIF-" sname }, \
344 	{ "TX" #id " XBAR-RX",		NULL,	"TX" #id " XBAR-" sname }
345 
346 #define ADX_ROUTES(id)			\
347 	STREAM_ROUTES(id, "Playback"),	\
348 	STREAM_ROUTES(id, "Capture")
349 
350 static const struct snd_soc_dapm_route tegra210_adx_routes[] = {
351 	ADX_ROUTES(1),
352 	ADX_ROUTES(2),
353 	ADX_ROUTES(3),
354 	ADX_ROUTES(4),
355 };
356 
357 #define TEGRA210_ADX_BYTE_MAP_CTRL(reg)			 \
358 	SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0, \
359 		       tegra210_adx_get_byte_map,	 \
360 		       tegra210_adx_put_byte_map)
361 
362 static struct snd_kcontrol_new tegra210_adx_controls[] = {
363 	TEGRA210_ADX_BYTE_MAP_CTRL(0),
364 	TEGRA210_ADX_BYTE_MAP_CTRL(1),
365 	TEGRA210_ADX_BYTE_MAP_CTRL(2),
366 	TEGRA210_ADX_BYTE_MAP_CTRL(3),
367 	TEGRA210_ADX_BYTE_MAP_CTRL(4),
368 	TEGRA210_ADX_BYTE_MAP_CTRL(5),
369 	TEGRA210_ADX_BYTE_MAP_CTRL(6),
370 	TEGRA210_ADX_BYTE_MAP_CTRL(7),
371 	TEGRA210_ADX_BYTE_MAP_CTRL(8),
372 	TEGRA210_ADX_BYTE_MAP_CTRL(9),
373 	TEGRA210_ADX_BYTE_MAP_CTRL(10),
374 	TEGRA210_ADX_BYTE_MAP_CTRL(11),
375 	TEGRA210_ADX_BYTE_MAP_CTRL(12),
376 	TEGRA210_ADX_BYTE_MAP_CTRL(13),
377 	TEGRA210_ADX_BYTE_MAP_CTRL(14),
378 	TEGRA210_ADX_BYTE_MAP_CTRL(15),
379 	TEGRA210_ADX_BYTE_MAP_CTRL(16),
380 	TEGRA210_ADX_BYTE_MAP_CTRL(17),
381 	TEGRA210_ADX_BYTE_MAP_CTRL(18),
382 	TEGRA210_ADX_BYTE_MAP_CTRL(19),
383 	TEGRA210_ADX_BYTE_MAP_CTRL(20),
384 	TEGRA210_ADX_BYTE_MAP_CTRL(21),
385 	TEGRA210_ADX_BYTE_MAP_CTRL(22),
386 	TEGRA210_ADX_BYTE_MAP_CTRL(23),
387 	TEGRA210_ADX_BYTE_MAP_CTRL(24),
388 	TEGRA210_ADX_BYTE_MAP_CTRL(25),
389 	TEGRA210_ADX_BYTE_MAP_CTRL(26),
390 	TEGRA210_ADX_BYTE_MAP_CTRL(27),
391 	TEGRA210_ADX_BYTE_MAP_CTRL(28),
392 	TEGRA210_ADX_BYTE_MAP_CTRL(29),
393 	TEGRA210_ADX_BYTE_MAP_CTRL(30),
394 	TEGRA210_ADX_BYTE_MAP_CTRL(31),
395 	TEGRA210_ADX_BYTE_MAP_CTRL(32),
396 	TEGRA210_ADX_BYTE_MAP_CTRL(33),
397 	TEGRA210_ADX_BYTE_MAP_CTRL(34),
398 	TEGRA210_ADX_BYTE_MAP_CTRL(35),
399 	TEGRA210_ADX_BYTE_MAP_CTRL(36),
400 	TEGRA210_ADX_BYTE_MAP_CTRL(37),
401 	TEGRA210_ADX_BYTE_MAP_CTRL(38),
402 	TEGRA210_ADX_BYTE_MAP_CTRL(39),
403 	TEGRA210_ADX_BYTE_MAP_CTRL(40),
404 	TEGRA210_ADX_BYTE_MAP_CTRL(41),
405 	TEGRA210_ADX_BYTE_MAP_CTRL(42),
406 	TEGRA210_ADX_BYTE_MAP_CTRL(43),
407 	TEGRA210_ADX_BYTE_MAP_CTRL(44),
408 	TEGRA210_ADX_BYTE_MAP_CTRL(45),
409 	TEGRA210_ADX_BYTE_MAP_CTRL(46),
410 	TEGRA210_ADX_BYTE_MAP_CTRL(47),
411 	TEGRA210_ADX_BYTE_MAP_CTRL(48),
412 	TEGRA210_ADX_BYTE_MAP_CTRL(49),
413 	TEGRA210_ADX_BYTE_MAP_CTRL(50),
414 	TEGRA210_ADX_BYTE_MAP_CTRL(51),
415 	TEGRA210_ADX_BYTE_MAP_CTRL(52),
416 	TEGRA210_ADX_BYTE_MAP_CTRL(53),
417 	TEGRA210_ADX_BYTE_MAP_CTRL(54),
418 	TEGRA210_ADX_BYTE_MAP_CTRL(55),
419 	TEGRA210_ADX_BYTE_MAP_CTRL(56),
420 	TEGRA210_ADX_BYTE_MAP_CTRL(57),
421 	TEGRA210_ADX_BYTE_MAP_CTRL(58),
422 	TEGRA210_ADX_BYTE_MAP_CTRL(59),
423 	TEGRA210_ADX_BYTE_MAP_CTRL(60),
424 	TEGRA210_ADX_BYTE_MAP_CTRL(61),
425 	TEGRA210_ADX_BYTE_MAP_CTRL(62),
426 	TEGRA210_ADX_BYTE_MAP_CTRL(63),
427 };
428 
429 static struct snd_kcontrol_new tegra264_adx_controls[] = {
430 	TEGRA210_ADX_BYTE_MAP_CTRL(64),
431 	TEGRA210_ADX_BYTE_MAP_CTRL(65),
432 	TEGRA210_ADX_BYTE_MAP_CTRL(66),
433 	TEGRA210_ADX_BYTE_MAP_CTRL(67),
434 	TEGRA210_ADX_BYTE_MAP_CTRL(68),
435 	TEGRA210_ADX_BYTE_MAP_CTRL(69),
436 	TEGRA210_ADX_BYTE_MAP_CTRL(70),
437 	TEGRA210_ADX_BYTE_MAP_CTRL(71),
438 	TEGRA210_ADX_BYTE_MAP_CTRL(72),
439 	TEGRA210_ADX_BYTE_MAP_CTRL(73),
440 	TEGRA210_ADX_BYTE_MAP_CTRL(74),
441 	TEGRA210_ADX_BYTE_MAP_CTRL(75),
442 	TEGRA210_ADX_BYTE_MAP_CTRL(76),
443 	TEGRA210_ADX_BYTE_MAP_CTRL(77),
444 	TEGRA210_ADX_BYTE_MAP_CTRL(78),
445 	TEGRA210_ADX_BYTE_MAP_CTRL(79),
446 	TEGRA210_ADX_BYTE_MAP_CTRL(80),
447 	TEGRA210_ADX_BYTE_MAP_CTRL(81),
448 	TEGRA210_ADX_BYTE_MAP_CTRL(82),
449 	TEGRA210_ADX_BYTE_MAP_CTRL(83),
450 	TEGRA210_ADX_BYTE_MAP_CTRL(84),
451 	TEGRA210_ADX_BYTE_MAP_CTRL(85),
452 	TEGRA210_ADX_BYTE_MAP_CTRL(86),
453 	TEGRA210_ADX_BYTE_MAP_CTRL(87),
454 	TEGRA210_ADX_BYTE_MAP_CTRL(88),
455 	TEGRA210_ADX_BYTE_MAP_CTRL(89),
456 	TEGRA210_ADX_BYTE_MAP_CTRL(90),
457 	TEGRA210_ADX_BYTE_MAP_CTRL(91),
458 	TEGRA210_ADX_BYTE_MAP_CTRL(92),
459 	TEGRA210_ADX_BYTE_MAP_CTRL(93),
460 	TEGRA210_ADX_BYTE_MAP_CTRL(94),
461 	TEGRA210_ADX_BYTE_MAP_CTRL(95),
462 	TEGRA210_ADX_BYTE_MAP_CTRL(96),
463 	TEGRA210_ADX_BYTE_MAP_CTRL(97),
464 	TEGRA210_ADX_BYTE_MAP_CTRL(98),
465 	TEGRA210_ADX_BYTE_MAP_CTRL(99),
466 	TEGRA210_ADX_BYTE_MAP_CTRL(100),
467 	TEGRA210_ADX_BYTE_MAP_CTRL(101),
468 	TEGRA210_ADX_BYTE_MAP_CTRL(102),
469 	TEGRA210_ADX_BYTE_MAP_CTRL(103),
470 	TEGRA210_ADX_BYTE_MAP_CTRL(104),
471 	TEGRA210_ADX_BYTE_MAP_CTRL(105),
472 	TEGRA210_ADX_BYTE_MAP_CTRL(106),
473 	TEGRA210_ADX_BYTE_MAP_CTRL(107),
474 	TEGRA210_ADX_BYTE_MAP_CTRL(108),
475 	TEGRA210_ADX_BYTE_MAP_CTRL(109),
476 	TEGRA210_ADX_BYTE_MAP_CTRL(110),
477 	TEGRA210_ADX_BYTE_MAP_CTRL(111),
478 	TEGRA210_ADX_BYTE_MAP_CTRL(112),
479 	TEGRA210_ADX_BYTE_MAP_CTRL(113),
480 	TEGRA210_ADX_BYTE_MAP_CTRL(114),
481 	TEGRA210_ADX_BYTE_MAP_CTRL(115),
482 	TEGRA210_ADX_BYTE_MAP_CTRL(116),
483 	TEGRA210_ADX_BYTE_MAP_CTRL(117),
484 	TEGRA210_ADX_BYTE_MAP_CTRL(118),
485 	TEGRA210_ADX_BYTE_MAP_CTRL(119),
486 	TEGRA210_ADX_BYTE_MAP_CTRL(120),
487 	TEGRA210_ADX_BYTE_MAP_CTRL(121),
488 	TEGRA210_ADX_BYTE_MAP_CTRL(122),
489 	TEGRA210_ADX_BYTE_MAP_CTRL(123),
490 	TEGRA210_ADX_BYTE_MAP_CTRL(124),
491 	TEGRA210_ADX_BYTE_MAP_CTRL(125),
492 	TEGRA210_ADX_BYTE_MAP_CTRL(126),
493 	TEGRA210_ADX_BYTE_MAP_CTRL(127),
494 };
495 
496 static int tegra210_adx_component_probe(struct snd_soc_component *component)
497 {
498 	struct tegra210_adx *adx = snd_soc_component_get_drvdata(component);
499 	int err = 0;
500 
501 	if (adx->soc_data->num_controls) {
502 		err = snd_soc_add_component_controls(component, adx->soc_data->controls,
503 						     adx->soc_data->num_controls);
504 		if (err)
505 			dev_err(component->dev, "can't add ADX controls, err: %d\n", err);
506 	}
507 
508 	return err;
509 }
510 
511 static const struct snd_soc_component_driver tegra210_adx_cmpnt = {
512 	.probe			= tegra210_adx_component_probe,
513 	.dapm_widgets		= tegra210_adx_widgets,
514 	.num_dapm_widgets	= ARRAY_SIZE(tegra210_adx_widgets),
515 	.dapm_routes		= tegra210_adx_routes,
516 	.num_dapm_routes	= ARRAY_SIZE(tegra210_adx_routes),
517 	.controls		= tegra210_adx_controls,
518 	.num_controls		= ARRAY_SIZE(tegra210_adx_controls),
519 };
520 
521 static bool tegra210_adx_wr_reg(struct device *dev,
522 				unsigned int reg)
523 {
524 	switch (reg) {
525 	case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL:
526 	case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL:
527 	case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG:
528 	case TEGRA210_ADX_CTRL ... TEGRA210_ADX_IN_BYTE_EN1:
529 	case TEGRA210_ADX_CFG_RAM_CTRL ... TEGRA210_ADX_CFG_RAM_DATA:
530 		return true;
531 	default:
532 		return false;
533 	}
534 }
535 
536 static bool tegra210_adx_rd_reg(struct device *dev,
537 				unsigned int reg)
538 {
539 	switch (reg) {
540 	case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_CFG_RAM_DATA:
541 		return true;
542 	default:
543 		return false;
544 	}
545 }
546 
547 static bool tegra210_adx_volatile_reg(struct device *dev,
548 				unsigned int reg)
549 {
550 	switch (reg) {
551 	case TEGRA210_ADX_RX_STATUS:
552 	case TEGRA210_ADX_RX_INT_STATUS:
553 	case TEGRA210_ADX_RX_INT_SET:
554 	case TEGRA210_ADX_TX_STATUS:
555 	case TEGRA210_ADX_TX_INT_STATUS:
556 	case TEGRA210_ADX_TX_INT_SET:
557 	case TEGRA210_ADX_SOFT_RESET:
558 	case TEGRA210_ADX_STATUS:
559 	case TEGRA210_ADX_INT_STATUS:
560 	case TEGRA210_ADX_CFG_RAM_CTRL:
561 	case TEGRA210_ADX_CFG_RAM_DATA:
562 		return true;
563 	default:
564 		break;
565 	}
566 
567 	return false;
568 }
569 
570 static bool tegra264_adx_wr_reg(struct device *dev,
571 				unsigned int reg)
572 {
573 	switch (reg) {
574 	case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL:
575 	case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL:
576 	case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG:
577 	case TEGRA210_ADX_CTRL ... TEGRA264_ADX_CYA:
578 	case TEGRA264_ADX_CFG_RAM_CTRL ... TEGRA264_ADX_CFG_RAM_DATA:
579 		return true;
580 	default:
581 		return false;
582 	}
583 }
584 
585 static bool tegra264_adx_rd_reg(struct device *dev,
586 				unsigned int reg)
587 {
588 	switch (reg) {
589 	case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_RX_CIF_CTRL:
590 	case TEGRA210_ADX_TX_STATUS ... TEGRA210_ADX_TX4_CIF_CTRL:
591 	case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_INT_STATUS:
592 	case TEGRA210_ADX_CTRL ... TEGRA264_ADX_CFG_RAM_DATA:
593 		return true;
594 	default:
595 		return false;
596 	}
597 }
598 
599 static bool tegra264_adx_volatile_reg(struct device *dev,
600 				      unsigned int reg)
601 {
602 	switch (reg) {
603 	case TEGRA210_ADX_RX_STATUS:
604 	case TEGRA210_ADX_RX_INT_STATUS:
605 	case TEGRA210_ADX_RX_INT_SET:
606 	case TEGRA210_ADX_TX_STATUS:
607 	case TEGRA210_ADX_TX_INT_STATUS:
608 	case TEGRA210_ADX_TX_INT_SET:
609 	case TEGRA210_ADX_SOFT_RESET:
610 	case TEGRA210_ADX_STATUS:
611 	case TEGRA210_ADX_INT_STATUS:
612 	case TEGRA264_ADX_CFG_RAM_CTRL:
613 	case TEGRA264_ADX_CFG_RAM_DATA:
614 		return true;
615 	default:
616 		break;
617 	}
618 
619 	return false;
620 }
621 
622 static const struct regmap_config tegra210_adx_regmap_config = {
623 	.reg_bits		= 32,
624 	.reg_stride		= 4,
625 	.val_bits		= 32,
626 	.max_register		= TEGRA210_ADX_CFG_RAM_DATA,
627 	.writeable_reg		= tegra210_adx_wr_reg,
628 	.readable_reg		= tegra210_adx_rd_reg,
629 	.volatile_reg		= tegra210_adx_volatile_reg,
630 	.reg_defaults		= tegra210_adx_reg_defaults,
631 	.num_reg_defaults	= ARRAY_SIZE(tegra210_adx_reg_defaults),
632 	.reg_default_cb		= regmap_default_zero_cb,
633 	.cache_type		= REGCACHE_FLAT,
634 };
635 
636 static const struct regmap_config tegra264_adx_regmap_config = {
637 	.reg_bits		= 32,
638 	.reg_stride		= 4,
639 	.val_bits		= 32,
640 	.max_register		= TEGRA264_ADX_CFG_RAM_DATA,
641 	.writeable_reg		= tegra264_adx_wr_reg,
642 	.readable_reg		= tegra264_adx_rd_reg,
643 	.volatile_reg		= tegra264_adx_volatile_reg,
644 	.reg_defaults		= tegra264_adx_reg_defaults,
645 	.num_reg_defaults	= ARRAY_SIZE(tegra264_adx_reg_defaults),
646 	.reg_default_cb		= regmap_default_zero_cb,
647 	.cache_type		= REGCACHE_FLAT,
648 };
649 
650 static const struct tegra210_adx_soc_data soc_data_tegra210 = {
651 	.regmap_conf		= &tegra210_adx_regmap_config,
652 	.max_ch			= TEGRA210_ADX_MAX_CHANNEL,
653 	.ram_depth		= TEGRA210_ADX_RAM_DEPTH,
654 	.byte_mask_size		= TEGRA210_ADX_BYTE_MASK_COUNT,
655 	.cya_offset		= TEGRA210_ADX_CYA_OFFSET,
656 };
657 
658 static const struct tegra210_adx_soc_data soc_data_tegra264 = {
659 	.regmap_conf		= &tegra264_adx_regmap_config,
660 	.max_ch			= TEGRA264_ADX_MAX_CHANNEL,
661 	.ram_depth		= TEGRA264_ADX_RAM_DEPTH,
662 	.byte_mask_size		= TEGRA264_ADX_BYTE_MASK_COUNT,
663 	.cya_offset		= TEGRA264_ADX_CYA_OFFSET,
664 	.controls		= tegra264_adx_controls,
665 	.num_controls		= ARRAY_SIZE(tegra264_adx_controls),
666 };
667 
668 static const struct of_device_id tegra210_adx_of_match[] = {
669 	{ .compatible = "nvidia,tegra210-adx", .data = &soc_data_tegra210 },
670 	{ .compatible = "nvidia,tegra264-adx", .data = &soc_data_tegra264 },
671 	{},
672 };
673 MODULE_DEVICE_TABLE(of, tegra210_adx_of_match);
674 
675 static int tegra210_adx_platform_probe(struct platform_device *pdev)
676 {
677 	struct device *dev = &pdev->dev;
678 	struct tegra210_adx *adx;
679 	const struct of_device_id *match;
680 	struct tegra210_adx_soc_data *soc_data;
681 	void __iomem *regs;
682 	int err;
683 
684 	adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL);
685 	if (!adx)
686 		return -ENOMEM;
687 
688 	match = of_match_device(tegra210_adx_of_match, dev);
689 	soc_data = (struct tegra210_adx_soc_data *)match->data;
690 	adx->soc_data = soc_data;
691 
692 	dev_set_drvdata(dev, adx);
693 
694 	regs = devm_platform_ioremap_resource(pdev, 0);
695 	if (IS_ERR(regs))
696 		return PTR_ERR(regs);
697 
698 	adx->regmap = devm_regmap_init_mmio(dev, regs,
699 					    soc_data->regmap_conf);
700 	if (IS_ERR(adx->regmap))
701 		return dev_err_probe(dev, PTR_ERR(adx->regmap),
702 				     "regmap init failed\n");
703 
704 	regcache_cache_only(adx->regmap, true);
705 
706 	adx->map = devm_kzalloc(dev, soc_data->ram_depth * sizeof(*adx->map),
707 				GFP_KERNEL);
708 	if (!adx->map)
709 		return -ENOMEM;
710 
711 	adx->byte_mask = devm_kzalloc(dev,
712 				      soc_data->byte_mask_size * sizeof(*adx->byte_mask),
713 				      GFP_KERNEL);
714 	if (!adx->byte_mask)
715 		return -ENOMEM;
716 
717 	tegra210_adx_dais[TEGRA_ADX_IN_DAI_ID].playback.channels_max =
718 			adx->soc_data->max_ch;
719 
720 	err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt,
721 					      tegra210_adx_dais,
722 					      ARRAY_SIZE(tegra210_adx_dais));
723 	if (err)
724 		return dev_err_probe(dev, err,
725 				     "can't register ADX component\n");
726 
727 	pm_runtime_enable(dev);
728 
729 	return 0;
730 }
731 
732 static void tegra210_adx_platform_remove(struct platform_device *pdev)
733 {
734 	pm_runtime_disable(&pdev->dev);
735 }
736 
737 static const struct dev_pm_ops tegra210_adx_pm_ops = {
738 	RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
739 		       tegra210_adx_runtime_resume, NULL)
740 	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
741 };
742 
743 static struct platform_driver tegra210_adx_driver = {
744 	.driver = {
745 		.name = "tegra210-adx",
746 		.of_match_table = tegra210_adx_of_match,
747 		.pm = pm_ptr(&tegra210_adx_pm_ops),
748 	},
749 	.probe = tegra210_adx_platform_probe,
750 	.remove = tegra210_adx_platform_remove,
751 };
752 module_platform_driver(tegra210_adx_driver);
753 
754 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
755 MODULE_DESCRIPTION("Tegra210 ADX ASoC driver");
756 MODULE_LICENSE("GPL v2");
757