xref: /linux/sound/soc/tegra/tegra210_admaif.c (revision 26fbb4c8c7c3ee9a4c3b4de555a8587b5a19154e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // tegra210_admaif.c - Tegra ADMAIF driver
4 //
5 // Copyright (c) 2020 NVIDIA CORPORATION.  All rights reserved.
6 
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/module.h>
10 #include <linux/of_platform.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14 #include <sound/pcm_params.h>
15 #include <sound/soc.h>
16 #include "tegra210_admaif.h"
17 #include "tegra_cif.h"
18 #include "tegra_pcm.h"
19 
20 #define CH_REG(offset, reg, id)						       \
21 	((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id)))
22 
23 #define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id)
24 
25 #define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
26 
27 #define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base)		       \
28 	{ CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 },	       \
29 	{ CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), 0x00007700 },     \
30 	{ CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl },	       \
31 	{ CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 },	       \
32 	{ CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), 0x00007700 },     \
33 	{ CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl }
34 
35 #define ADMAIF_REG_DEFAULTS(id, chip)					       \
36 	REG_DEFAULTS((id) - 1,						       \
37 		chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT,	       \
38 		chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT,	       \
39 		chip ## _ADMAIF_TX_BASE,				       \
40 		chip ## _ADMAIF_RX_BASE)
41 
42 static const struct reg_default tegra186_admaif_reg_defaults[] = {
43 	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003},
44 	ADMAIF_REG_DEFAULTS(1, TEGRA186),
45 	ADMAIF_REG_DEFAULTS(2, TEGRA186),
46 	ADMAIF_REG_DEFAULTS(3, TEGRA186),
47 	ADMAIF_REG_DEFAULTS(4, TEGRA186),
48 	ADMAIF_REG_DEFAULTS(5, TEGRA186),
49 	ADMAIF_REG_DEFAULTS(6, TEGRA186),
50 	ADMAIF_REG_DEFAULTS(7, TEGRA186),
51 	ADMAIF_REG_DEFAULTS(8, TEGRA186),
52 	ADMAIF_REG_DEFAULTS(9, TEGRA186),
53 	ADMAIF_REG_DEFAULTS(10, TEGRA186),
54 	ADMAIF_REG_DEFAULTS(11, TEGRA186),
55 	ADMAIF_REG_DEFAULTS(12, TEGRA186),
56 	ADMAIF_REG_DEFAULTS(13, TEGRA186),
57 	ADMAIF_REG_DEFAULTS(14, TEGRA186),
58 	ADMAIF_REG_DEFAULTS(15, TEGRA186),
59 	ADMAIF_REG_DEFAULTS(16, TEGRA186),
60 	ADMAIF_REG_DEFAULTS(17, TEGRA186),
61 	ADMAIF_REG_DEFAULTS(18, TEGRA186),
62 	ADMAIF_REG_DEFAULTS(19, TEGRA186),
63 	ADMAIF_REG_DEFAULTS(20, TEGRA186)
64 };
65 
66 static const struct reg_default tegra210_admaif_reg_defaults[] = {
67 	{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003},
68 	ADMAIF_REG_DEFAULTS(1, TEGRA210),
69 	ADMAIF_REG_DEFAULTS(2, TEGRA210),
70 	ADMAIF_REG_DEFAULTS(3, TEGRA210),
71 	ADMAIF_REG_DEFAULTS(4, TEGRA210),
72 	ADMAIF_REG_DEFAULTS(5, TEGRA210),
73 	ADMAIF_REG_DEFAULTS(6, TEGRA210),
74 	ADMAIF_REG_DEFAULTS(7, TEGRA210),
75 	ADMAIF_REG_DEFAULTS(8, TEGRA210),
76 	ADMAIF_REG_DEFAULTS(9, TEGRA210),
77 	ADMAIF_REG_DEFAULTS(10, TEGRA210)
78 };
79 
80 static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
81 {
82 	struct tegra_admaif *admaif = dev_get_drvdata(dev);
83 	unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
84 	unsigned int num_ch = admaif->soc_data->num_ch;
85 	unsigned int rx_base = admaif->soc_data->rx_base;
86 	unsigned int tx_base = admaif->soc_data->tx_base;
87 	unsigned int global_base = admaif->soc_data->global_base;
88 	unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
89 	unsigned int rx_max = rx_base + (num_ch * ch_stride);
90 	unsigned int tx_max = tx_base + (num_ch * ch_stride);
91 
92 	if ((reg >= rx_base) && (reg < rx_max)) {
93 		reg = (reg - rx_base) % ch_stride;
94 		if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
95 		    (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
96 		    (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
97 		    (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
98 			return true;
99 	} else if ((reg >= tx_base) && (reg < tx_max)) {
100 		reg = (reg - tx_base) % ch_stride;
101 		if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
102 		    (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
103 		    (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
104 		    (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
105 			return true;
106 	} else if ((reg >= global_base) && (reg < reg_max)) {
107 		if (reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE))
108 			return true;
109 	}
110 
111 	return false;
112 }
113 
114 static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg)
115 {
116 	struct tegra_admaif *admaif = dev_get_drvdata(dev);
117 	unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
118 	unsigned int num_ch = admaif->soc_data->num_ch;
119 	unsigned int rx_base = admaif->soc_data->rx_base;
120 	unsigned int tx_base = admaif->soc_data->tx_base;
121 	unsigned int global_base = admaif->soc_data->global_base;
122 	unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
123 	unsigned int rx_max = rx_base + (num_ch * ch_stride);
124 	unsigned int tx_max = tx_base + (num_ch * ch_stride);
125 
126 	if ((reg >= rx_base) && (reg < rx_max)) {
127 		reg = (reg - rx_base) % ch_stride;
128 		if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
129 		    (reg == TEGRA_ADMAIF_RX_STATUS) ||
130 		    (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
131 		    (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
132 		    (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
133 		    (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
134 			return true;
135 	} else if ((reg >= tx_base) && (reg < tx_max)) {
136 		reg = (reg - tx_base) % ch_stride;
137 		if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
138 		    (reg == TEGRA_ADMAIF_TX_STATUS) ||
139 		    (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
140 		    (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
141 		    (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
142 		    (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
143 			return true;
144 	} else if ((reg >= global_base) && (reg < reg_max)) {
145 		if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) ||
146 		    (reg == (global_base + TEGRA_ADMAIF_GLOBAL_CG_0)) ||
147 		    (reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
148 		    (reg == (global_base +
149 				TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
150 		    (reg == (global_base +
151 				TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
152 			return true;
153 	}
154 
155 	return false;
156 }
157 
158 static bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg)
159 {
160 	struct tegra_admaif *admaif = dev_get_drvdata(dev);
161 	unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
162 	unsigned int num_ch = admaif->soc_data->num_ch;
163 	unsigned int rx_base = admaif->soc_data->rx_base;
164 	unsigned int tx_base = admaif->soc_data->tx_base;
165 	unsigned int global_base = admaif->soc_data->global_base;
166 	unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
167 	unsigned int rx_max = rx_base + (num_ch * ch_stride);
168 	unsigned int tx_max = tx_base + (num_ch * ch_stride);
169 
170 	if ((reg >= rx_base) && (reg < rx_max)) {
171 		reg = (reg - rx_base) % ch_stride;
172 		if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
173 		    (reg == TEGRA_ADMAIF_RX_STATUS) ||
174 		    (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
175 		    (reg == TEGRA_ADMAIF_RX_SOFT_RESET))
176 			return true;
177 	} else if ((reg >= tx_base) && (reg < tx_max)) {
178 		reg = (reg - tx_base) % ch_stride;
179 		if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
180 		    (reg == TEGRA_ADMAIF_TX_STATUS) ||
181 		    (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
182 		    (reg == TEGRA_ADMAIF_TX_SOFT_RESET))
183 			return true;
184 	} else if ((reg >= global_base) && (reg < reg_max)) {
185 		if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
186 		    (reg == (global_base +
187 				TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
188 		    (reg == (global_base +
189 				TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
190 			return true;
191 	}
192 
193 	return false;
194 }
195 
196 static const struct regmap_config tegra210_admaif_regmap_config = {
197 	.reg_bits		= 32,
198 	.reg_stride		= 4,
199 	.val_bits		= 32,
200 	.max_register		= TEGRA210_ADMAIF_LAST_REG,
201 	.writeable_reg		= tegra_admaif_wr_reg,
202 	.readable_reg		= tegra_admaif_rd_reg,
203 	.volatile_reg		= tegra_admaif_volatile_reg,
204 	.reg_defaults		= tegra210_admaif_reg_defaults,
205 	.num_reg_defaults	= TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1,
206 	.cache_type		= REGCACHE_FLAT,
207 };
208 
209 static const struct regmap_config tegra186_admaif_regmap_config = {
210 	.reg_bits		= 32,
211 	.reg_stride		= 4,
212 	.val_bits		= 32,
213 	.max_register		= TEGRA186_ADMAIF_LAST_REG,
214 	.writeable_reg		= tegra_admaif_wr_reg,
215 	.readable_reg		= tegra_admaif_rd_reg,
216 	.volatile_reg		= tegra_admaif_volatile_reg,
217 	.reg_defaults		= tegra186_admaif_reg_defaults,
218 	.num_reg_defaults	= TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1,
219 	.cache_type		= REGCACHE_FLAT,
220 };
221 
222 static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev)
223 {
224 	struct tegra_admaif *admaif = dev_get_drvdata(dev);
225 
226 	regcache_cache_only(admaif->regmap, true);
227 	regcache_mark_dirty(admaif->regmap);
228 
229 	return 0;
230 }
231 
232 static int __maybe_unused tegra_admaif_runtime_resume(struct device *dev)
233 {
234 	struct tegra_admaif *admaif = dev_get_drvdata(dev);
235 
236 	regcache_cache_only(admaif->regmap, false);
237 	regcache_sync(admaif->regmap);
238 
239 	return 0;
240 }
241 
242 static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
243 				      int valid_bit)
244 {
245 	switch (valid_bit) {
246 	case DATA_8BIT:
247 		regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN);
248 		regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
249 		break;
250 	case DATA_16BIT:
251 		regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN);
252 		regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
253 		break;
254 	case DATA_32BIT:
255 		regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
256 		regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
257 		break;
258 	default:
259 		return -EINVAL;
260 	}
261 
262 	return 0;
263 }
264 
265 static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
266 				  struct snd_pcm_hw_params *params,
267 				  struct snd_soc_dai *dai)
268 {
269 	struct device *dev = dai->dev;
270 	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
271 	struct tegra_cif_conf cif_conf;
272 	unsigned int reg, path;
273 	int valid_bit, channels;
274 
275 	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
276 
277 	switch (params_format(params)) {
278 	case SNDRV_PCM_FORMAT_S8:
279 		cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
280 		cif_conf.client_bits = TEGRA_ACIF_BITS_8;
281 		valid_bit = DATA_8BIT;
282 		break;
283 	case SNDRV_PCM_FORMAT_S16_LE:
284 		cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
285 		cif_conf.client_bits = TEGRA_ACIF_BITS_16;
286 		valid_bit = DATA_16BIT;
287 		break;
288 	case SNDRV_PCM_FORMAT_S32_LE:
289 		cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
290 		cif_conf.client_bits = TEGRA_ACIF_BITS_32;
291 		valid_bit  = DATA_32BIT;
292 		break;
293 	default:
294 		dev_err(dev, "unsupported format!\n");
295 		return -EOPNOTSUPP;
296 	}
297 
298 	channels = params_channels(params);
299 	cif_conf.client_ch = channels;
300 	cif_conf.audio_ch = channels;
301 
302 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
303 		path = ADMAIF_TX_PATH;
304 		reg = CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL, dai->id);
305 	} else {
306 		path = ADMAIF_RX_PATH;
307 		reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id);
308 	}
309 
310 	cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id];
311 	cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id];
312 
313 	tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
314 
315 	tegra_set_cif(admaif->regmap, reg, &cif_conf);
316 
317 	return 0;
318 }
319 
320 static int tegra_admaif_start(struct snd_soc_dai *dai, int direction)
321 {
322 	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
323 	unsigned int reg, mask, val;
324 
325 	switch (direction) {
326 	case SNDRV_PCM_STREAM_PLAYBACK:
327 		mask = TX_ENABLE_MASK;
328 		val = TX_ENABLE;
329 		reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
330 		break;
331 	case SNDRV_PCM_STREAM_CAPTURE:
332 		mask = RX_ENABLE_MASK;
333 		val = RX_ENABLE;
334 		reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
335 		break;
336 	default:
337 		return -EINVAL;
338 	}
339 
340 	regmap_update_bits(admaif->regmap, reg, mask, val);
341 
342 	return 0;
343 }
344 
345 static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
346 {
347 	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
348 	unsigned int enable_reg, status_reg, reset_reg, mask, val;
349 	char *dir_name;
350 	int err, enable;
351 
352 	switch (direction) {
353 	case SNDRV_PCM_STREAM_PLAYBACK:
354 		mask = TX_ENABLE_MASK;
355 		enable = TX_ENABLE;
356 		dir_name = "TX";
357 		enable_reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
358 		status_reg = CH_TX_REG(TEGRA_ADMAIF_TX_STATUS, dai->id);
359 		reset_reg = CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET, dai->id);
360 		break;
361 	case SNDRV_PCM_STREAM_CAPTURE:
362 		mask = RX_ENABLE_MASK;
363 		enable = RX_ENABLE;
364 		dir_name = "RX";
365 		enable_reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
366 		status_reg = CH_RX_REG(TEGRA_ADMAIF_RX_STATUS, dai->id);
367 		reset_reg = CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET, dai->id);
368 		break;
369 	default:
370 		return -EINVAL;
371 	}
372 
373 	/* Disable TX/RX channel */
374 	regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable);
375 
376 	/* Wait until ADMAIF TX/RX status is disabled */
377 	err = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val,
378 					      !(val & enable), 10, 10000);
379 	if (err < 0)
380 		dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n",
381 			 dai->id + 1, dir_name);
382 
383 	/* SW reset */
384 	regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET);
385 
386 	/* Wait till SW reset is complete */
387 	err = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val,
388 					      !(val & SW_RESET_MASK & SW_RESET),
389 					      10, 10000);
390 	if (err) {
391 		dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n",
392 			dai->id + 1, dir_name);
393 		return err;
394 	}
395 
396 	return 0;
397 }
398 
399 static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
400 				struct snd_soc_dai *dai)
401 {
402 	int err;
403 
404 	err = snd_dmaengine_pcm_trigger(substream, cmd);
405 	if (err)
406 		return err;
407 
408 	switch (cmd) {
409 	case SNDRV_PCM_TRIGGER_START:
410 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
411 	case SNDRV_PCM_TRIGGER_RESUME:
412 		return tegra_admaif_start(dai, substream->stream);
413 	case SNDRV_PCM_TRIGGER_STOP:
414 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
415 	case SNDRV_PCM_TRIGGER_SUSPEND:
416 		return tegra_admaif_stop(dai, substream->stream);
417 	default:
418 		return -EINVAL;
419 	}
420 }
421 
422 static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
423 	.hw_params	= tegra_admaif_hw_params,
424 	.trigger	= tegra_admaif_trigger,
425 };
426 
427 static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol,
428 				    struct snd_ctl_elem_value *ucontrol)
429 {
430 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
431 	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
432 	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
433 	long *uctl_val = &ucontrol->value.integer.value[0];
434 
435 	if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
436 		*uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
437 	else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
438 		*uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
439 	else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
440 		*uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
441 	else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
442 		*uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
443 
444 	return 0;
445 }
446 
447 static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol,
448 				    struct snd_ctl_elem_value *ucontrol)
449 {
450 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
451 	struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
452 	struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
453 	int value = ucontrol->value.integer.value[0];
454 
455 	if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
456 		admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
457 	else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
458 		admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
459 	else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
460 		admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
461 	else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
462 		admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
463 
464 	return 0;
465 }
466 
467 static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
468 {
469 	struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
470 
471 	dai->capture_dma_data = &admaif->capture_dma_data[dai->id];
472 	dai->playback_dma_data = &admaif->playback_dma_data[dai->id];
473 
474 	return 0;
475 }
476 
477 #define DAI(dai_name)					\
478 	{							\
479 		.name = dai_name,				\
480 		.probe = tegra_admaif_dai_probe,		\
481 		.playback = {					\
482 			.stream_name = dai_name " Playback",	\
483 			.channels_min = 1,			\
484 			.channels_max = 16,			\
485 			.rates = SNDRV_PCM_RATE_8000_192000,	\
486 			.formats = SNDRV_PCM_FMTBIT_S8 |	\
487 				SNDRV_PCM_FMTBIT_S16_LE |	\
488 				SNDRV_PCM_FMTBIT_S32_LE,	\
489 		},						\
490 		.capture = {					\
491 			.stream_name = dai_name " Capture",	\
492 			.channels_min = 1,			\
493 			.channels_max = 16,			\
494 			.rates = SNDRV_PCM_RATE_8000_192000,	\
495 			.formats = SNDRV_PCM_FMTBIT_S8 |	\
496 				SNDRV_PCM_FMTBIT_S16_LE |	\
497 				SNDRV_PCM_FMTBIT_S32_LE,	\
498 		},						\
499 		.ops = &tegra_admaif_dai_ops,			\
500 	}
501 
502 static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
503 	DAI("ADMAIF1"),
504 	DAI("ADMAIF2"),
505 	DAI("ADMAIF3"),
506 	DAI("ADMAIF4"),
507 	DAI("ADMAIF5"),
508 	DAI("ADMAIF6"),
509 	DAI("ADMAIF7"),
510 	DAI("ADMAIF8"),
511 	DAI("ADMAIF9"),
512 	DAI("ADMAIF10"),
513 };
514 
515 static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
516 	DAI("ADMAIF1"),
517 	DAI("ADMAIF2"),
518 	DAI("ADMAIF3"),
519 	DAI("ADMAIF4"),
520 	DAI("ADMAIF5"),
521 	DAI("ADMAIF6"),
522 	DAI("ADMAIF7"),
523 	DAI("ADMAIF8"),
524 	DAI("ADMAIF9"),
525 	DAI("ADMAIF10"),
526 	DAI("ADMAIF11"),
527 	DAI("ADMAIF12"),
528 	DAI("ADMAIF13"),
529 	DAI("ADMAIF14"),
530 	DAI("ADMAIF15"),
531 	DAI("ADMAIF16"),
532 	DAI("ADMAIF17"),
533 	DAI("ADMAIF18"),
534 	DAI("ADMAIF19"),
535 	DAI("ADMAIF20"),
536 };
537 
538 static const char * const tegra_admaif_stereo_conv_text[] = {
539 	"CH0", "CH1", "AVG",
540 };
541 
542 static const char * const tegra_admaif_mono_conv_text[] = {
543 	"Zero", "Copy",
544 };
545 
546 /*
547  * Below macro is added to avoid looping over all ADMAIFx controls related
548  * to mono/stereo conversions in get()/put() callbacks.
549  */
550 #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text)   \
551 {									       \
552 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,				       \
553 	.info = snd_soc_info_enum_double,				       \
554 	.name = xname,							       \
555 	.get = xhandler_get,						       \
556 	.put = xhandler_put,						       \
557 	.private_value = (unsigned long)&(struct soc_enum)		       \
558 		SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text)   \
559 }
560 
561 #define TEGRA_ADMAIF_CIF_CTRL(reg)					       \
562 	NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\
563 			tegra_admaif_get_control, tegra_admaif_put_control,    \
564 			tegra_admaif_mono_conv_text),			       \
565 	NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\
566 			tegra_admaif_get_control, tegra_admaif_put_control,    \
567 			tegra_admaif_stereo_conv_text),			       \
568 	NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
569 			tegra_admaif_get_control, tegra_admaif_put_control,    \
570 			tegra_admaif_mono_conv_text),			       \
571 	NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
572 			tegra_admaif_get_control, tegra_admaif_put_control,    \
573 			tegra_admaif_stereo_conv_text)
574 
575 static struct snd_kcontrol_new tegra210_admaif_controls[] = {
576 	TEGRA_ADMAIF_CIF_CTRL(1),
577 	TEGRA_ADMAIF_CIF_CTRL(2),
578 	TEGRA_ADMAIF_CIF_CTRL(3),
579 	TEGRA_ADMAIF_CIF_CTRL(4),
580 	TEGRA_ADMAIF_CIF_CTRL(5),
581 	TEGRA_ADMAIF_CIF_CTRL(6),
582 	TEGRA_ADMAIF_CIF_CTRL(7),
583 	TEGRA_ADMAIF_CIF_CTRL(8),
584 	TEGRA_ADMAIF_CIF_CTRL(9),
585 	TEGRA_ADMAIF_CIF_CTRL(10),
586 };
587 
588 static struct snd_kcontrol_new tegra186_admaif_controls[] = {
589 	TEGRA_ADMAIF_CIF_CTRL(1),
590 	TEGRA_ADMAIF_CIF_CTRL(2),
591 	TEGRA_ADMAIF_CIF_CTRL(3),
592 	TEGRA_ADMAIF_CIF_CTRL(4),
593 	TEGRA_ADMAIF_CIF_CTRL(5),
594 	TEGRA_ADMAIF_CIF_CTRL(6),
595 	TEGRA_ADMAIF_CIF_CTRL(7),
596 	TEGRA_ADMAIF_CIF_CTRL(8),
597 	TEGRA_ADMAIF_CIF_CTRL(9),
598 	TEGRA_ADMAIF_CIF_CTRL(10),
599 	TEGRA_ADMAIF_CIF_CTRL(11),
600 	TEGRA_ADMAIF_CIF_CTRL(12),
601 	TEGRA_ADMAIF_CIF_CTRL(13),
602 	TEGRA_ADMAIF_CIF_CTRL(14),
603 	TEGRA_ADMAIF_CIF_CTRL(15),
604 	TEGRA_ADMAIF_CIF_CTRL(16),
605 	TEGRA_ADMAIF_CIF_CTRL(17),
606 	TEGRA_ADMAIF_CIF_CTRL(18),
607 	TEGRA_ADMAIF_CIF_CTRL(19),
608 	TEGRA_ADMAIF_CIF_CTRL(20),
609 };
610 
611 static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
612 	.controls		= tegra210_admaif_controls,
613 	.num_controls		= ARRAY_SIZE(tegra210_admaif_controls),
614 	.pcm_construct		= tegra_pcm_construct,
615 	.pcm_destruct		= tegra_pcm_destruct,
616 	.open			= tegra_pcm_open,
617 	.close			= tegra_pcm_close,
618 	.hw_params		= tegra_pcm_hw_params,
619 	.hw_free		= tegra_pcm_hw_free,
620 	.mmap			= tegra_pcm_mmap,
621 	.pointer		= tegra_pcm_pointer,
622 };
623 
624 static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
625 	.controls		= tegra186_admaif_controls,
626 	.num_controls		= ARRAY_SIZE(tegra186_admaif_controls),
627 	.pcm_construct		= tegra_pcm_construct,
628 	.pcm_destruct		= tegra_pcm_destruct,
629 	.open			= tegra_pcm_open,
630 	.close			= tegra_pcm_close,
631 	.hw_params		= tegra_pcm_hw_params,
632 	.hw_free		= tegra_pcm_hw_free,
633 	.mmap			= tegra_pcm_mmap,
634 	.pointer		= tegra_pcm_pointer,
635 };
636 
637 static const struct tegra_admaif_soc_data soc_data_tegra210 = {
638 	.num_ch		= TEGRA210_ADMAIF_CHANNEL_COUNT,
639 	.cmpnt		= &tegra210_admaif_cmpnt,
640 	.dais		= tegra210_admaif_cmpnt_dais,
641 	.regmap_conf	= &tegra210_admaif_regmap_config,
642 	.global_base	= TEGRA210_ADMAIF_GLOBAL_BASE,
643 	.tx_base	= TEGRA210_ADMAIF_TX_BASE,
644 	.rx_base	= TEGRA210_ADMAIF_RX_BASE,
645 };
646 
647 static const struct tegra_admaif_soc_data soc_data_tegra186 = {
648 	.num_ch		= TEGRA186_ADMAIF_CHANNEL_COUNT,
649 	.cmpnt		= &tegra186_admaif_cmpnt,
650 	.dais		= tegra186_admaif_cmpnt_dais,
651 	.regmap_conf	= &tegra186_admaif_regmap_config,
652 	.global_base	= TEGRA186_ADMAIF_GLOBAL_BASE,
653 	.tx_base	= TEGRA186_ADMAIF_TX_BASE,
654 	.rx_base	= TEGRA186_ADMAIF_RX_BASE,
655 };
656 
657 static const struct of_device_id tegra_admaif_of_match[] = {
658 	{ .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
659 	{ .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
660 	{},
661 };
662 MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
663 
664 static int tegra_admaif_probe(struct platform_device *pdev)
665 {
666 	struct tegra_admaif *admaif;
667 	void __iomem *regs;
668 	struct resource *res;
669 	int err, i;
670 
671 	admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
672 	if (!admaif)
673 		return -ENOMEM;
674 
675 	admaif->soc_data = of_device_get_match_data(&pdev->dev);
676 
677 	dev_set_drvdata(&pdev->dev, admaif);
678 
679 	admaif->capture_dma_data =
680 		devm_kcalloc(&pdev->dev,
681 			     admaif->soc_data->num_ch,
682 			     sizeof(struct snd_dmaengine_dai_dma_data),
683 			     GFP_KERNEL);
684 	if (!admaif->capture_dma_data)
685 		return -ENOMEM;
686 
687 	admaif->playback_dma_data =
688 		devm_kcalloc(&pdev->dev,
689 			     admaif->soc_data->num_ch,
690 			     sizeof(struct snd_dmaengine_dai_dma_data),
691 			     GFP_KERNEL);
692 	if (!admaif->playback_dma_data)
693 		return -ENOMEM;
694 
695 	for (i = 0; i < ADMAIF_PATHS; i++) {
696 		admaif->mono_to_stereo[i] =
697 			devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
698 				     sizeof(unsigned int), GFP_KERNEL);
699 		if (!admaif->mono_to_stereo[i])
700 			return -ENOMEM;
701 
702 		admaif->stereo_to_mono[i] =
703 			devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
704 				     sizeof(unsigned int), GFP_KERNEL);
705 		if (!admaif->stereo_to_mono[i])
706 			return -ENOMEM;
707 	}
708 
709 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
710 
711 	regs = devm_ioremap_resource(&pdev->dev, res);
712 	if (IS_ERR(regs))
713 		return PTR_ERR(regs);
714 
715 	admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
716 					       admaif->soc_data->regmap_conf);
717 	if (IS_ERR(admaif->regmap)) {
718 		dev_err(&pdev->dev, "regmap init failed\n");
719 		return PTR_ERR(admaif->regmap);
720 	}
721 
722 	regcache_cache_only(admaif->regmap, true);
723 
724 	regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
725 			   TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
726 
727 	for (i = 0; i < admaif->soc_data->num_ch; i++) {
728 		admaif->playback_dma_data[i].addr = res->start +
729 			CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
730 
731 		admaif->capture_dma_data[i].addr = res->start +
732 			CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
733 
734 		admaif->playback_dma_data[i].addr_width = 32;
735 
736 		if (of_property_read_string_index(pdev->dev.of_node,
737 				"dma-names", (i * 2) + 1,
738 				&admaif->playback_dma_data[i].chan_name) < 0) {
739 			dev_err(&pdev->dev,
740 				"missing property nvidia,dma-names\n");
741 
742 			return -ENODEV;
743 		}
744 
745 		admaif->capture_dma_data[i].addr_width = 32;
746 
747 		if (of_property_read_string_index(pdev->dev.of_node,
748 				"dma-names",
749 				(i * 2),
750 				&admaif->capture_dma_data[i].chan_name) < 0) {
751 			dev_err(&pdev->dev,
752 				"missing property nvidia,dma-names\n");
753 
754 			return -ENODEV;
755 		}
756 	}
757 
758 	err = devm_snd_soc_register_component(&pdev->dev,
759 					      admaif->soc_data->cmpnt,
760 					      admaif->soc_data->dais,
761 					      admaif->soc_data->num_ch);
762 	if (err) {
763 		dev_err(&pdev->dev,
764 			"can't register ADMAIF component, err: %d\n", err);
765 		return err;
766 	}
767 
768 	pm_runtime_enable(&pdev->dev);
769 
770 	return 0;
771 }
772 
773 static int tegra_admaif_remove(struct platform_device *pdev)
774 {
775 	pm_runtime_disable(&pdev->dev);
776 
777 	return 0;
778 }
779 
780 static const struct dev_pm_ops tegra_admaif_pm_ops = {
781 	SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
782 			   tegra_admaif_runtime_resume, NULL)
783 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
784 				pm_runtime_force_resume)
785 };
786 
787 static struct platform_driver tegra_admaif_driver = {
788 	.probe = tegra_admaif_probe,
789 	.remove = tegra_admaif_remove,
790 	.driver = {
791 		.name = "tegra210-admaif",
792 		.of_match_table = tegra_admaif_of_match,
793 		.pm = &tegra_admaif_pm_ops,
794 	},
795 };
796 module_platform_driver(tegra_admaif_driver);
797 
798 MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
799 MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
800 MODULE_LICENSE("GPL v2");
801