1 // SPDX-License-Identifier: GPL-2.0-only
3 // tegra210_admaif.c - Tegra ADMAIF driver
5 // Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
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"
20 #define CH_REG(offset, reg, id) \
21 ((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id)))
23 #define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id)
25 #define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
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 }
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)
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)
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)
80 static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
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);
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))
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))
106 } else if ((reg >= global_base) && (reg < reg_max)) {
107 if (reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE))
114 static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg)
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);
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))
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))
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)))
158 static bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg)
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);
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))
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))
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)))
196 static const struct regmap_config tegra210_admaif_regmap_config = {
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,
209 static const struct regmap_config tegra186_admaif_regmap_config = {
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,
222 static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev)
224 struct tegra_admaif *admaif = dev_get_drvdata(dev);
226 regcache_cache_only(admaif->regmap, true);
227 regcache_mark_dirty(admaif->regmap);
232 static int __maybe_unused tegra_admaif_runtime_resume(struct device *dev)
234 struct tegra_admaif *admaif = dev_get_drvdata(dev);
236 regcache_cache_only(admaif->regmap, false);
237 regcache_sync(admaif->regmap);
242 static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
247 regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN);
248 regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
251 regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN);
252 regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
255 regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
256 regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
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)
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;
275 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
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;
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;
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;
294 dev_err(dev, "unsupported format!\n");
298 channels = params_channels(params);
299 cif_conf.client_ch = channels;
300 cif_conf.audio_ch = channels;
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);
306 path = ADMAIF_RX_PATH;
307 reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id);
310 cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id];
311 cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id];
313 tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
315 tegra_set_cif(admaif->regmap, reg, &cif_conf);
320 static int tegra_admaif_start(struct snd_soc_dai *dai, int direction)
322 struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
323 unsigned int reg, mask, val;
326 case SNDRV_PCM_STREAM_PLAYBACK:
327 mask = TX_ENABLE_MASK;
329 reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
331 case SNDRV_PCM_STREAM_CAPTURE:
332 mask = RX_ENABLE_MASK;
334 reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
340 regmap_update_bits(admaif->regmap, reg, mask, val);
345 static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
347 struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
348 unsigned int enable_reg, status_reg, reset_reg, mask, val;
353 case SNDRV_PCM_STREAM_PLAYBACK:
354 mask = TX_ENABLE_MASK;
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);
361 case SNDRV_PCM_STREAM_CAPTURE:
362 mask = RX_ENABLE_MASK;
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);
373 /* Disable TX/RX channel */
374 regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable);
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);
380 dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n",
381 dai->id + 1, dir_name);
384 regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET);
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),
391 dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n",
392 dai->id + 1, dir_name);
399 static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
400 struct snd_soc_dai *dai)
404 err = snd_dmaengine_pcm_trigger(substream, 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);
422 static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
423 .hw_params = tegra_admaif_hw_params,
424 .trigger = tegra_admaif_trigger,
427 static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol,
428 struct snd_ctl_elem_value *ucontrol)
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];
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];
447 static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol,
448 struct snd_ctl_elem_value *ucontrol)
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];
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;
467 static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
469 struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
471 dai->capture_dma_data = &admaif->capture_dma_data[dai->id];
472 dai->playback_dma_data = &admaif->playback_dma_data[dai->id];
477 #define DAI(dai_name) \
480 .probe = tegra_admaif_dai_probe, \
482 .stream_name = dai_name " Playback", \
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, \
491 .stream_name = dai_name " Capture", \
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, \
499 .ops = &tegra_admaif_dai_ops, \
502 static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
515 static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
538 static const char * const tegra_admaif_stereo_conv_text[] = {
542 static const char * const tegra_admaif_mono_conv_text[] = {
547 * Below macro is added to avoid looping over all ADMAIFx controls related
548 * to mono/stereo conversions in get()/put() callbacks.
550 #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \
552 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
553 .info = snd_soc_info_enum_double, \
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) \
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)
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),
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),
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,
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,
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,
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,
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 },
662 MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
664 static int tegra_admaif_probe(struct platform_device *pdev)
666 struct tegra_admaif *admaif;
668 struct resource *res;
671 admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
675 admaif->soc_data = of_device_get_match_data(&pdev->dev);
677 dev_set_drvdata(&pdev->dev, admaif);
679 admaif->capture_dma_data =
680 devm_kcalloc(&pdev->dev,
681 admaif->soc_data->num_ch,
682 sizeof(struct snd_dmaengine_dai_dma_data),
684 if (!admaif->capture_dma_data)
687 admaif->playback_dma_data =
688 devm_kcalloc(&pdev->dev,
689 admaif->soc_data->num_ch,
690 sizeof(struct snd_dmaengine_dai_dma_data),
692 if (!admaif->playback_dma_data)
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])
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])
709 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
711 regs = devm_ioremap_resource(&pdev->dev, res);
713 return PTR_ERR(regs);
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);
722 regcache_cache_only(admaif->regmap, true);
724 regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
725 TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
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);
731 admaif->capture_dma_data[i].addr = res->start +
732 CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
734 admaif->playback_dma_data[i].addr_width = 32;
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) {
740 "missing property nvidia,dma-names\n");
745 admaif->capture_dma_data[i].addr_width = 32;
747 if (of_property_read_string_index(pdev->dev.of_node,
750 &admaif->capture_dma_data[i].chan_name) < 0) {
752 "missing property nvidia,dma-names\n");
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);
764 "can't register ADMAIF component, err: %d\n", err);
768 pm_runtime_enable(&pdev->dev);
773 static int tegra_admaif_remove(struct platform_device *pdev)
775 pm_runtime_disable(&pdev->dev);
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)
787 static struct platform_driver tegra_admaif_driver = {
788 .probe = tegra_admaif_probe,
789 .remove = tegra_admaif_remove,
791 .name = "tegra210-admaif",
792 .of_match_table = tegra_admaif_of_match,
793 .pm = &tegra_admaif_pm_ops,
796 module_platform_driver(tegra_admaif_driver);
798 MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
799 MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
800 MODULE_LICENSE("GPL v2");