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 tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
428 struct snd_ctl_elem_value *ucontrol)
430 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
431 struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
432 struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
434 ucontrol->value.enumerated.item[0] =
435 admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
440 static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
441 struct snd_ctl_elem_value *ucontrol)
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 unsigned int value = ucontrol->value.enumerated.item[0];
448 if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg])
451 admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
456 static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
457 struct snd_ctl_elem_value *ucontrol)
459 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
460 struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
461 struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
463 ucontrol->value.enumerated.item[0] =
464 admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
469 static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
470 struct snd_ctl_elem_value *ucontrol)
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 unsigned int value = ucontrol->value.enumerated.item[0];
477 if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg])
480 admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
485 static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
486 struct snd_ctl_elem_value *ucontrol)
488 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
489 struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
490 struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
492 ucontrol->value.enumerated.item[0] =
493 admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
498 static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
499 struct snd_ctl_elem_value *ucontrol)
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 unsigned int value = ucontrol->value.enumerated.item[0];
506 if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg])
509 admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
514 static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
515 struct snd_ctl_elem_value *ucontrol)
517 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
518 struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
519 struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
521 ucontrol->value.enumerated.item[0] =
522 admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
527 static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
528 struct snd_ctl_elem_value *ucontrol)
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 unsigned int value = ucontrol->value.enumerated.item[0];
535 if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg])
538 admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
543 static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
545 struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
547 dai->capture_dma_data = &admaif->capture_dma_data[dai->id];
548 dai->playback_dma_data = &admaif->playback_dma_data[dai->id];
553 #define DAI(dai_name) \
556 .probe = tegra_admaif_dai_probe, \
558 .stream_name = dai_name " Playback", \
560 .channels_max = 16, \
561 .rates = SNDRV_PCM_RATE_8000_192000, \
562 .formats = SNDRV_PCM_FMTBIT_S8 | \
563 SNDRV_PCM_FMTBIT_S16_LE | \
564 SNDRV_PCM_FMTBIT_S32_LE, \
567 .stream_name = dai_name " Capture", \
569 .channels_max = 16, \
570 .rates = SNDRV_PCM_RATE_8000_192000, \
571 .formats = SNDRV_PCM_FMTBIT_S8 | \
572 SNDRV_PCM_FMTBIT_S16_LE | \
573 SNDRV_PCM_FMTBIT_S32_LE, \
575 .ops = &tegra_admaif_dai_ops, \
578 static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
591 static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
614 static const char * const tegra_admaif_stereo_conv_text[] = {
618 static const char * const tegra_admaif_mono_conv_text[] = {
623 * Below macro is added to avoid looping over all ADMAIFx controls related
624 * to mono/stereo conversions in get()/put() callbacks.
626 #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \
628 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
629 .info = snd_soc_info_enum_double, \
631 .get = xhandler_get, \
632 .put = xhandler_put, \
633 .private_value = (unsigned long)&(struct soc_enum) \
634 SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text) \
637 #define TEGRA_ADMAIF_CIF_CTRL(reg) \
638 NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \
639 tegra210_admaif_pget_mono_to_stereo, \
640 tegra210_admaif_pput_mono_to_stereo, \
641 tegra_admaif_mono_conv_text), \
642 NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \
643 tegra210_admaif_pget_stereo_to_mono, \
644 tegra210_admaif_pput_stereo_to_mono, \
645 tegra_admaif_stereo_conv_text), \
646 NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
647 tegra210_admaif_cget_mono_to_stereo, \
648 tegra210_admaif_cput_mono_to_stereo, \
649 tegra_admaif_mono_conv_text), \
650 NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
651 tegra210_admaif_cget_stereo_to_mono, \
652 tegra210_admaif_cput_stereo_to_mono, \
653 tegra_admaif_stereo_conv_text)
655 static struct snd_kcontrol_new tegra210_admaif_controls[] = {
656 TEGRA_ADMAIF_CIF_CTRL(1),
657 TEGRA_ADMAIF_CIF_CTRL(2),
658 TEGRA_ADMAIF_CIF_CTRL(3),
659 TEGRA_ADMAIF_CIF_CTRL(4),
660 TEGRA_ADMAIF_CIF_CTRL(5),
661 TEGRA_ADMAIF_CIF_CTRL(6),
662 TEGRA_ADMAIF_CIF_CTRL(7),
663 TEGRA_ADMAIF_CIF_CTRL(8),
664 TEGRA_ADMAIF_CIF_CTRL(9),
665 TEGRA_ADMAIF_CIF_CTRL(10),
668 static struct snd_kcontrol_new tegra186_admaif_controls[] = {
669 TEGRA_ADMAIF_CIF_CTRL(1),
670 TEGRA_ADMAIF_CIF_CTRL(2),
671 TEGRA_ADMAIF_CIF_CTRL(3),
672 TEGRA_ADMAIF_CIF_CTRL(4),
673 TEGRA_ADMAIF_CIF_CTRL(5),
674 TEGRA_ADMAIF_CIF_CTRL(6),
675 TEGRA_ADMAIF_CIF_CTRL(7),
676 TEGRA_ADMAIF_CIF_CTRL(8),
677 TEGRA_ADMAIF_CIF_CTRL(9),
678 TEGRA_ADMAIF_CIF_CTRL(10),
679 TEGRA_ADMAIF_CIF_CTRL(11),
680 TEGRA_ADMAIF_CIF_CTRL(12),
681 TEGRA_ADMAIF_CIF_CTRL(13),
682 TEGRA_ADMAIF_CIF_CTRL(14),
683 TEGRA_ADMAIF_CIF_CTRL(15),
684 TEGRA_ADMAIF_CIF_CTRL(16),
685 TEGRA_ADMAIF_CIF_CTRL(17),
686 TEGRA_ADMAIF_CIF_CTRL(18),
687 TEGRA_ADMAIF_CIF_CTRL(19),
688 TEGRA_ADMAIF_CIF_CTRL(20),
691 static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
692 .controls = tegra210_admaif_controls,
693 .num_controls = ARRAY_SIZE(tegra210_admaif_controls),
694 .pcm_construct = tegra_pcm_construct,
695 .open = tegra_pcm_open,
696 .close = tegra_pcm_close,
697 .hw_params = tegra_pcm_hw_params,
698 .pointer = tegra_pcm_pointer,
701 static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
702 .controls = tegra186_admaif_controls,
703 .num_controls = ARRAY_SIZE(tegra186_admaif_controls),
704 .pcm_construct = tegra_pcm_construct,
705 .open = tegra_pcm_open,
706 .close = tegra_pcm_close,
707 .hw_params = tegra_pcm_hw_params,
708 .pointer = tegra_pcm_pointer,
711 static const struct tegra_admaif_soc_data soc_data_tegra210 = {
712 .num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT,
713 .cmpnt = &tegra210_admaif_cmpnt,
714 .dais = tegra210_admaif_cmpnt_dais,
715 .regmap_conf = &tegra210_admaif_regmap_config,
716 .global_base = TEGRA210_ADMAIF_GLOBAL_BASE,
717 .tx_base = TEGRA210_ADMAIF_TX_BASE,
718 .rx_base = TEGRA210_ADMAIF_RX_BASE,
721 static const struct tegra_admaif_soc_data soc_data_tegra186 = {
722 .num_ch = TEGRA186_ADMAIF_CHANNEL_COUNT,
723 .cmpnt = &tegra186_admaif_cmpnt,
724 .dais = tegra186_admaif_cmpnt_dais,
725 .regmap_conf = &tegra186_admaif_regmap_config,
726 .global_base = TEGRA186_ADMAIF_GLOBAL_BASE,
727 .tx_base = TEGRA186_ADMAIF_TX_BASE,
728 .rx_base = TEGRA186_ADMAIF_RX_BASE,
731 static const struct of_device_id tegra_admaif_of_match[] = {
732 { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
733 { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
736 MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
738 static int tegra_admaif_probe(struct platform_device *pdev)
740 struct tegra_admaif *admaif;
742 struct resource *res;
745 admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
749 admaif->soc_data = of_device_get_match_data(&pdev->dev);
751 dev_set_drvdata(&pdev->dev, admaif);
753 admaif->capture_dma_data =
754 devm_kcalloc(&pdev->dev,
755 admaif->soc_data->num_ch,
756 sizeof(struct snd_dmaengine_dai_dma_data),
758 if (!admaif->capture_dma_data)
761 admaif->playback_dma_data =
762 devm_kcalloc(&pdev->dev,
763 admaif->soc_data->num_ch,
764 sizeof(struct snd_dmaengine_dai_dma_data),
766 if (!admaif->playback_dma_data)
769 for (i = 0; i < ADMAIF_PATHS; i++) {
770 admaif->mono_to_stereo[i] =
771 devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
772 sizeof(unsigned int), GFP_KERNEL);
773 if (!admaif->mono_to_stereo[i])
776 admaif->stereo_to_mono[i] =
777 devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
778 sizeof(unsigned int), GFP_KERNEL);
779 if (!admaif->stereo_to_mono[i])
783 regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
785 return PTR_ERR(regs);
787 admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
788 admaif->soc_data->regmap_conf);
789 if (IS_ERR(admaif->regmap)) {
790 dev_err(&pdev->dev, "regmap init failed\n");
791 return PTR_ERR(admaif->regmap);
794 regcache_cache_only(admaif->regmap, true);
796 regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
797 TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
799 for (i = 0; i < admaif->soc_data->num_ch; i++) {
800 admaif->playback_dma_data[i].addr = res->start +
801 CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
803 admaif->capture_dma_data[i].addr = res->start +
804 CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
806 admaif->playback_dma_data[i].addr_width = 32;
808 if (of_property_read_string_index(pdev->dev.of_node,
809 "dma-names", (i * 2) + 1,
810 &admaif->playback_dma_data[i].chan_name) < 0) {
812 "missing property nvidia,dma-names\n");
817 admaif->capture_dma_data[i].addr_width = 32;
819 if (of_property_read_string_index(pdev->dev.of_node,
822 &admaif->capture_dma_data[i].chan_name) < 0) {
824 "missing property nvidia,dma-names\n");
830 err = devm_snd_soc_register_component(&pdev->dev,
831 admaif->soc_data->cmpnt,
832 admaif->soc_data->dais,
833 admaif->soc_data->num_ch);
836 "can't register ADMAIF component, err: %d\n", err);
840 pm_runtime_enable(&pdev->dev);
845 static int tegra_admaif_remove(struct platform_device *pdev)
847 pm_runtime_disable(&pdev->dev);
852 static const struct dev_pm_ops tegra_admaif_pm_ops = {
853 SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
854 tegra_admaif_runtime_resume, NULL)
855 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
856 pm_runtime_force_resume)
859 static struct platform_driver tegra_admaif_driver = {
860 .probe = tegra_admaif_probe,
861 .remove = tegra_admaif_remove,
863 .name = "tegra210-admaif",
864 .of_match_table = tegra_admaif_of_match,
865 .pm = &tegra_admaif_pm_ops,
868 module_platform_driver(tegra_admaif_driver);
870 MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
871 MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
872 MODULE_LICENSE("GPL v2");