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