2 * tegra210_admaif_alt.c - Tegra ADMAIF driver
4 * Copyright (c) 2014-2017 NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/delay.h>
20 #include <linux/clk.h>
21 #include <linux/device.h>
23 #include <linux/module.h>
24 #include <linux/of_platform.h>
25 #include <linux/platform_device.h>
26 #include <linux/pm_runtime.h>
27 #include <linux/regmap.h>
28 #include <linux/slab.h>
29 #include <linux/clk/tegra.h>
30 #include <sound/soc.h>
31 #include <sound/pcm_params.h>
33 #include "tegra_pcm_alt.h"
34 #include "tegra210_xbar_alt.h"
35 #include "tegra_isomgr_bw_alt.h"
36 #if defined(CONFIG_ARCH_TEGRA_18x_SOC)
37 #include <sound/tegra_audio.h>
39 #include "tegra210_admaif_alt.h"
41 #define DRV_NAME "tegra210-ape-admaif"
43 #define ADMAIF_CH_REG(reg, id) (reg + (TEGRA210_ADMAIF_CHANNEL_REG_STRIDE * id))
44 #define ADMAIF_REG_DEFAULTS(id, rx_fifo_ctrl, tx_fifo_ctrl) \
45 { ADMAIF_CH_REG(TEGRA210_ADMAIF_XBAR_RX_INT_MASK, id), 0x00000001}, \
46 { ADMAIF_CH_REG(TEGRA210_ADMAIF_CHAN_ACIF_RX_CTRL, id), 0x00007700}, \
47 { ADMAIF_CH_REG(TEGRA210_ADMAIF_XBAR_RX_FIFO_CTRL, id), rx_fifo_ctrl}, \
48 { ADMAIF_CH_REG(TEGRA210_ADMAIF_XBAR_TX_INT_MASK, id), 0x00000001}, \
49 { ADMAIF_CH_REG(TEGRA210_ADMAIF_CHAN_ACIF_TX_CTRL, id), 0x00007700}, \
50 { ADMAIF_CH_REG(TEGRA210_ADMAIF_XBAR_TX_FIFO_CTRL, id), tx_fifo_ctrl}
52 static const struct reg_default tegra210_admaif_reg_defaults[] = {
53 { TEGRA210_ADMAIF_GLOBAL_CG_0, 0x00000003},
54 ADMAIF_REG_DEFAULTS(0, ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT,
55 ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT),
56 ADMAIF_REG_DEFAULTS(1, ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT,
57 ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT),
58 ADMAIF_REG_DEFAULTS(2, ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT,
59 ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT),
60 ADMAIF_REG_DEFAULTS(3, ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT,
61 ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT),
62 ADMAIF_REG_DEFAULTS(4, ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT,
63 ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT),
64 ADMAIF_REG_DEFAULTS(5, ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT,
65 ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT),
66 ADMAIF_REG_DEFAULTS(6, ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT,
67 ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT),
68 ADMAIF_REG_DEFAULTS(7, ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT,
69 ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT),
70 ADMAIF_REG_DEFAULTS(8, ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT,
71 ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT),
72 ADMAIF_REG_DEFAULTS(9, ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT,
73 ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT),
74 ADMAIF_REG_DEFAULTS(10, ADMAIF_RX11_FIFO_CTRL_REG_DEFAULT,
75 ADMAIF_TX11_FIFO_CTRL_REG_DEFAULT),
76 ADMAIF_REG_DEFAULTS(11, ADMAIF_RX12_FIFO_CTRL_REG_DEFAULT,
77 ADMAIF_TX12_FIFO_CTRL_REG_DEFAULT),
78 ADMAIF_REG_DEFAULTS(12, ADMAIF_RX13_FIFO_CTRL_REG_DEFAULT,
79 ADMAIF_TX13_FIFO_CTRL_REG_DEFAULT),
80 ADMAIF_REG_DEFAULTS(13, ADMAIF_RX14_FIFO_CTRL_REG_DEFAULT,
81 ADMAIF_TX14_FIFO_CTRL_REG_DEFAULT),
82 ADMAIF_REG_DEFAULTS(14, ADMAIF_RX15_FIFO_CTRL_REG_DEFAULT,
83 ADMAIF_TX15_FIFO_CTRL_REG_DEFAULT),
84 ADMAIF_REG_DEFAULTS(15, ADMAIF_RX16_FIFO_CTRL_REG_DEFAULT,
85 ADMAIF_TX16_FIFO_CTRL_REG_DEFAULT),
86 ADMAIF_REG_DEFAULTS(16, ADMAIF_RX17_FIFO_CTRL_REG_DEFAULT,
87 ADMAIF_TX17_FIFO_CTRL_REG_DEFAULT),
88 ADMAIF_REG_DEFAULTS(17, ADMAIF_RX18_FIFO_CTRL_REG_DEFAULT,
89 ADMAIF_TX18_FIFO_CTRL_REG_DEFAULT),
90 ADMAIF_REG_DEFAULTS(18, ADMAIF_RX19_FIFO_CTRL_REG_DEFAULT,
91 ADMAIF_TX19_FIFO_CTRL_REG_DEFAULT),
92 ADMAIF_REG_DEFAULTS(19, ADMAIF_RX20_FIFO_CTRL_REG_DEFAULT,
93 ADMAIF_TX20_FIFO_CTRL_REG_DEFAULT),
96 static bool tegra210_admaif_wr_reg(struct device *dev, unsigned int reg)
98 reg = reg % TEGRA210_ADMAIF_CHANNEL_REG_STRIDE;
101 case TEGRA210_ADMAIF_XBAR_TX_ENABLE:
102 case TEGRA210_ADMAIF_XBAR_TX_STATUS:
103 case TEGRA210_ADMAIF_XBAR_TX_FIFO_CTRL:
104 case TEGRA210_ADMAIF_XBAR_TX_SOFT_RESET:
105 case TEGRA210_ADMAIF_CHAN_ACIF_TX_CTRL:
106 case TEGRA210_ADMAIF_XBAR_RX_ENABLE:
107 case TEGRA210_ADMAIF_XBAR_RX_FIFO_CTRL:
108 case TEGRA210_ADMAIF_XBAR_RX_SOFT_RESET:
109 case TEGRA210_ADMAIF_CHAN_ACIF_RX_CTRL:
110 case TEGRA210_ADMAIF_GLOBAL_ENABLE:
119 static bool tegra210_admaif_rd_reg(struct device *dev, unsigned int reg)
121 reg = reg % TEGRA210_ADMAIF_CHANNEL_REG_STRIDE;
124 case TEGRA210_ADMAIF_XBAR_RX_STATUS:
125 case TEGRA210_ADMAIF_XBAR_RX_INT_STATUS:
126 case TEGRA210_ADMAIF_XBAR_RX_ENABLE:
127 case TEGRA210_ADMAIF_XBAR_RX_SOFT_RESET:
128 case TEGRA210_ADMAIF_XBAR_RX_FIFO_CTRL:
129 case TEGRA210_ADMAIF_CHAN_ACIF_RX_CTRL:
130 case TEGRA210_ADMAIF_XBAR_TX_STATUS:
131 case TEGRA210_ADMAIF_XBAR_TX_INT_STATUS:
132 case TEGRA210_ADMAIF_XBAR_TX_ENABLE:
133 case TEGRA210_ADMAIF_XBAR_TX_SOFT_RESET:
134 case TEGRA210_ADMAIF_XBAR_TX_FIFO_CTRL:
135 case TEGRA210_ADMAIF_CHAN_ACIF_TX_CTRL:
136 case TEGRA210_ADMAIF_GLOBAL_ENABLE:
143 static bool tegra210_admaif_volatile_reg(struct device *dev, unsigned int reg)
145 if (reg > 0 && (reg < TEGRA210_ADMAIF_CHANNEL_COUNT *
146 TEGRA210_ADMAIF_CHANNEL_REG_STRIDE * 2))
147 reg = reg % TEGRA210_ADMAIF_CHANNEL_REG_STRIDE;
150 case TEGRA210_ADMAIF_XBAR_RX_STATUS:
151 case TEGRA210_ADMAIF_XBAR_TX_STATUS:
152 case TEGRA210_ADMAIF_XBAR_RX_INT_STATUS:
153 case TEGRA210_ADMAIF_XBAR_TX_INT_STATUS:
154 case TEGRA210_ADMAIF_XBAR_RX_SOFT_RESET:
155 case TEGRA210_ADMAIF_XBAR_TX_SOFT_RESET:
156 case TEGRA210_ADMAIF_XBAR_TX_ENABLE:
157 case TEGRA210_ADMAIF_XBAR_RX_ENABLE:
166 static const struct regmap_config tegra210_admaif_regmap_config = {
170 .max_register = TEGRA210_ADMAIF_LAST_REG,
171 .writeable_reg = tegra210_admaif_wr_reg,
172 .readable_reg = tegra210_admaif_rd_reg,
173 .volatile_reg = tegra210_admaif_volatile_reg,
174 .reg_defaults = tegra210_admaif_reg_defaults,
175 .num_reg_defaults = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1,
176 .cache_type = REGCACHE_FLAT,
179 static int tegra210_admaif_sw_reset(struct snd_soc_dai *dai,
180 int direction, int timeout)
182 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
183 unsigned int sw_reset_reg, val;
186 if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
187 sw_reset_reg = TEGRA210_ADMAIF_XBAR_TX_SOFT_RESET +
188 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
190 sw_reset_reg = TEGRA210_ADMAIF_XBAR_RX_SOFT_RESET +
191 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
194 regmap_update_bits(admaif->regmap, sw_reset_reg, 1, 1);
197 regmap_read(admaif->regmap, sw_reset_reg, &val);
201 } while (val & 0x00000001);
206 static int tegra210_admaif_get_status(struct snd_soc_dai *dai,
209 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
210 unsigned int status_reg, val;
212 if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
213 status_reg = TEGRA210_ADMAIF_XBAR_TX_STATUS +
214 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
216 status_reg = TEGRA210_ADMAIF_XBAR_RX_STATUS +
217 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
219 regmap_read(admaif->regmap, status_reg, &val);
220 val = (val & 0x00000001);
225 static int tegra210_admaif_runtime_suspend(struct device *dev)
227 struct tegra210_admaif *admaif = dev_get_drvdata(dev);
229 regcache_cache_only(admaif->regmap, true);
230 regcache_mark_dirty(admaif->regmap);
231 pm_runtime_put_sync(dev->parent);
236 static int tegra210_admaif_runtime_resume(struct device *dev)
238 struct tegra210_admaif *admaif = dev_get_drvdata(dev);
241 ret = pm_runtime_get_sync(dev->parent);
243 dev_err(dev, "parent get_sync failed: %d\n", ret);
247 regcache_cache_only(admaif->regmap, false);
248 if (!admaif->is_shutdown)
249 regcache_sync(admaif->regmap);
254 #ifdef CONFIG_PM_SLEEP
255 static int tegra210_admaif_suspend(struct device *dev)
261 static int tegra210_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
266 regmap_update_bits(map, reg,
267 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK8_EN_MASK,
268 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK8_EN);
269 regmap_update_bits(map, reg,
270 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK16_EN_MASK,
274 regmap_update_bits(map, reg,
275 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK16_EN_MASK,
276 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK16_EN);
277 regmap_update_bits(map, reg,
278 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK8_EN_MASK,
282 regmap_update_bits(map, reg,
283 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK16_EN_MASK,
285 regmap_update_bits(map, reg,
286 TEGRA210_ADMAIF_CHAN_ACIF_CTRL_PACK8_EN_MASK,
296 static int tegra210_admaif_prepare(struct snd_pcm_substream *substream,
297 struct snd_soc_dai *dai)
299 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
301 if (admaif->soc_data->is_isomgr_client)
302 tegra_isomgr_adma_setbw(substream, true);
307 static int tegra210_admaif_startup(struct snd_pcm_substream *substream,
308 struct snd_soc_dai *dai)
310 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
312 if (admaif->is_shutdown)
318 static void tegra210_admaif_shutdown(struct snd_pcm_substream *substream,
319 struct snd_soc_dai *dai)
321 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
323 if (admaif->soc_data->is_isomgr_client)
324 tegra_isomgr_adma_setbw(substream, false);
327 static int tegra210_admaif_hw_params(struct snd_pcm_substream *substream,
328 struct snd_pcm_hw_params *params,
329 struct snd_soc_dai *dai)
331 struct device *dev = dai->dev;
332 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
333 struct tegra210_xbar_cif_conf cif_conf;
335 int valid_bit, channels;
337 memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
339 channels = params_channels(params);
340 if (admaif->override_channels[dai->id] > 0)
341 channels = admaif->override_channels[dai->id];
343 cif_conf.audio_channels = channels;
344 cif_conf.client_channels = channels;
346 switch (params_format(params)) {
347 case SNDRV_PCM_FORMAT_S8:
348 cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_8;
349 cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_8;
350 valid_bit = DATA_8BIT;
352 case SNDRV_PCM_FORMAT_S16_LE:
353 cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_16;
354 cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_16;
355 valid_bit = DATA_16BIT;
357 case SNDRV_PCM_FORMAT_S24_LE:
358 cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_24;
359 cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_24;
360 valid_bit = DATA_32BIT;
362 case SNDRV_PCM_FORMAT_S32_LE:
363 cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_32;
364 cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_32;
365 valid_bit = DATA_32BIT;
368 dev_err(dev, "Wrong format!\n");
372 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
373 reg = TEGRA210_ADMAIF_CHAN_ACIF_TX_CTRL +
374 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
375 /* For playback path, the mono input from client channel
376 * can be converted to stereo using cif controls.
378 if (admaif->tx_mono_to_stereo[dai->id] > 0) {
380 admaif->tx_mono_to_stereo[dai->id] - 1;
381 cif_conf.audio_channels = 2;
382 cif_conf.client_channels = 1;
385 reg = TEGRA210_ADMAIF_CHAN_ACIF_RX_CTRL +
386 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
387 /* For capture path, the stereo audio channel can be
388 * converted to mono using cif controls.
390 if (admaif->rx_stereo_to_mono[dai->id] > 0) {
391 cif_conf.stereo_conv =
392 admaif->rx_stereo_to_mono[dai->id] - 1;
393 cif_conf.audio_channels = 2;
394 cif_conf.client_channels = 1;
398 tegra210_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
399 admaif->soc_data->set_audio_cif(admaif->regmap, reg, &cif_conf);
404 static void tegra210_admaif_start_playback(struct snd_soc_dai *dai)
406 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
409 reg = TEGRA210_ADMAIF_XBAR_TX_ENABLE +
410 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
411 regmap_update_bits(admaif->regmap, reg,
412 TEGRA210_ADMAIF_XBAR_TX_ENABLE_MASK,
413 TEGRA210_ADMAIF_XBAR_TX_EN);
416 static void tegra210_admaif_stop_playback(struct snd_soc_dai *dai)
418 struct device *dev = dai->dev;
419 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
423 reg = TEGRA210_ADMAIF_XBAR_TX_ENABLE +
424 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
425 regmap_update_bits(admaif->regmap, reg,
426 TEGRA210_ADMAIF_XBAR_TX_ENABLE_MASK,
429 /* wait until ADMAIF TX status is disabled */
430 while (tegra210_admaif_get_status(dai, SNDRV_PCM_STREAM_PLAYBACK) &&
434 /* HW needs sw reset to make sure previous transaction be clean */
435 ret = tegra210_admaif_sw_reset(dai, SNDRV_PCM_STREAM_PLAYBACK, 0xffff);
437 dev_err(dev, "Failed at ADMAIF%d_TX sw reset\n", dev->id);
440 static void tegra210_admaif_start_capture(struct snd_soc_dai *dai)
442 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
445 reg = TEGRA210_ADMAIF_XBAR_RX_ENABLE +
446 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
447 regmap_update_bits(admaif->regmap, reg,
448 TEGRA210_ADMAIF_XBAR_RX_ENABLE_MASK,
449 TEGRA210_ADMAIF_XBAR_RX_EN);
452 static void tegra210_admaif_stop_capture(struct snd_soc_dai *dai)
454 struct device *dev = dai->dev;
455 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
459 reg = TEGRA210_ADMAIF_XBAR_RX_ENABLE +
460 (dai->id * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
461 regmap_update_bits(admaif->regmap, reg,
462 TEGRA210_ADMAIF_XBAR_RX_ENABLE_MASK,
465 /* wait until ADMAIF RX status is disabled */
466 while (tegra210_admaif_get_status(dai, SNDRV_PCM_STREAM_CAPTURE) &&
470 /* HW needs sw reset to make sure previous transaction be clean */
471 ret = tegra210_admaif_sw_reset(dai, SNDRV_PCM_STREAM_CAPTURE, 0xffff);
473 dev_err(dev, "Failed at ADMAIF%d_RX sw reset\n", dev->id);
476 static int tegra210_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
477 struct snd_soc_dai *dai)
480 case SNDRV_PCM_TRIGGER_START:
481 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
482 case SNDRV_PCM_TRIGGER_RESUME:
483 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
484 tegra210_admaif_start_playback(dai);
486 tegra210_admaif_start_capture(dai);
488 case SNDRV_PCM_TRIGGER_STOP:
489 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
490 case SNDRV_PCM_TRIGGER_SUSPEND:
491 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
492 tegra210_admaif_stop_playback(dai);
494 tegra210_admaif_stop_capture(dai);
503 static struct snd_soc_dai_ops tegra210_admaif_dai_ops = {
504 .hw_params = tegra210_admaif_hw_params,
505 .trigger = tegra210_admaif_trigger,
506 .startup = tegra210_admaif_startup,
507 .shutdown = tegra210_admaif_shutdown,
508 .prepare = tegra210_admaif_prepare,
511 static int tegra210_admaif_get_format(struct snd_kcontrol *kcontrol,
512 struct snd_ctl_elem_value *ucontrol)
514 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
515 struct soc_mixer_control *mc =
516 (struct soc_mixer_control *)kcontrol->private_value;
517 struct tegra210_admaif *admaif = snd_soc_codec_get_drvdata(codec);
521 if (strstr(kcontrol->id.name, "Channels"))
522 ucontrol->value.integer.value[0] =
523 admaif->override_channels[mc->reg];
525 for (i = 0 ; i < TEGRA210_ADMAIF_CHANNEL_COUNT; i++) {
526 snprintf(buf, 50, "ADMAIF%d RX stereo to mono", i+1);
527 if (strstr(kcontrol->id.name, buf)) {
528 ucontrol->value.integer.value[0] =
529 admaif->rx_stereo_to_mono[i];
532 snprintf(buf, 50, "ADMAIF%d TX mono to stereo", i+1);
533 if (strstr(kcontrol->id.name, buf)) {
534 ucontrol->value.integer.value[0] =
535 admaif->tx_mono_to_stereo[i];
544 static int tegra210_admaif_put_format(struct snd_kcontrol *kcontrol,
545 struct snd_ctl_elem_value *ucontrol)
547 struct soc_mixer_control *mc =
548 (struct soc_mixer_control *)kcontrol->private_value;
549 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
550 struct tegra210_admaif *admaif = snd_soc_codec_get_drvdata(codec);
551 int value = ucontrol->value.integer.value[0];
555 if (strstr(kcontrol->id.name, "Channels")) {
556 if (value > 0 && value <= 16)
557 admaif->override_channels[mc->reg] = value;
561 for (i = 0 ; i < TEGRA210_ADMAIF_CHANNEL_COUNT; i++) {
562 snprintf(buf, 50, "ADMAIF%d RX stereo to mono", i+1);
563 if (strstr(kcontrol->id.name, buf)) {
564 admaif->rx_stereo_to_mono[i] = value;
567 snprintf(buf, 50, "ADMAIF%d TX mono to stereo", i+1);
568 if (strstr(kcontrol->id.name, buf)) {
569 admaif->tx_mono_to_stereo[i] = value;
578 static int tegra210_admaif_dai_probe(struct snd_soc_dai *dai)
580 struct tegra210_admaif *admaif = snd_soc_dai_get_drvdata(dai);
582 dai->capture_dma_data = &admaif->capture_dma_data[dai->id];
583 dai->playback_dma_data = &admaif->playback_dma_data[dai->id];
588 #define ADMAIF_DAI(id) \
590 .name = "ADMAIF" #id, \
591 .probe = tegra210_admaif_dai_probe, \
593 .stream_name = "Playback " #id, \
595 .channels_max = 16, \
596 .rates = SNDRV_PCM_RATE_8000_192000, \
597 .formats = SNDRV_PCM_FMTBIT_S8 | \
598 SNDRV_PCM_FMTBIT_S16_LE | \
599 SNDRV_PCM_FMTBIT_S24_LE | \
600 SNDRV_PCM_FMTBIT_S32_LE, \
603 .stream_name = "Capture " #id, \
605 .channels_max = 16, \
606 .rates = SNDRV_PCM_RATE_8000_192000, \
607 .formats = SNDRV_PCM_FMTBIT_S8 | \
608 SNDRV_PCM_FMTBIT_S16_LE | \
609 SNDRV_PCM_FMTBIT_S24_LE | \
610 SNDRV_PCM_FMTBIT_S32_LE, \
612 .ops = &tegra210_admaif_dai_ops, \
615 static struct snd_soc_dai_driver tegra210_admaif_dais[] = {
638 #define ADMAIF_CODEC_FIFO_DAI(id) \
640 .name = "ADMAIF" #id " FIFO", \
642 .stream_name = "ADMAIF" #id " FIFO Transmit", \
644 .channels_max = 16, \
645 .rates = SNDRV_PCM_RATE_8000_192000, \
646 .formats = SNDRV_PCM_FMTBIT_S8 | \
647 SNDRV_PCM_FMTBIT_S16_LE | \
648 SNDRV_PCM_FMTBIT_S24_LE | \
649 SNDRV_PCM_FMTBIT_S32_LE, \
652 .stream_name = "ADMAIF" #id " FIFO Receive", \
654 .channels_max = 16, \
655 .rates = SNDRV_PCM_RATE_8000_192000, \
656 .formats = SNDRV_PCM_FMTBIT_S8 | \
657 SNDRV_PCM_FMTBIT_S16_LE | \
658 SNDRV_PCM_FMTBIT_S24_LE | \
659 SNDRV_PCM_FMTBIT_S32_LE, \
661 .ops = &tegra210_admaif_dai_ops, \
664 #define ADMAIF_CODEC_CIF_DAI(id) \
666 .name = "ADMAIF" #id " CIF", \
668 .stream_name = "ADMAIF" #id " CIF Transmit", \
670 .channels_max = 16, \
671 .rates = SNDRV_PCM_RATE_8000_192000, \
672 .formats = SNDRV_PCM_FMTBIT_S8 | \
673 SNDRV_PCM_FMTBIT_S16_LE | \
674 SNDRV_PCM_FMTBIT_S24_LE | \
675 SNDRV_PCM_FMTBIT_S32_LE, \
678 .stream_name = "ADMAIF" #id " CIF Receive", \
680 .channels_max = 16, \
681 .rates = SNDRV_PCM_RATE_8000_192000, \
682 .formats = SNDRV_PCM_FMTBIT_S8 | \
683 SNDRV_PCM_FMTBIT_S16_LE | \
684 SNDRV_PCM_FMTBIT_S24_LE | \
685 SNDRV_PCM_FMTBIT_S32_LE, \
689 static struct snd_soc_dai_driver tegra210_admaif_codec_dais[] = {
690 ADMAIF_CODEC_FIFO_DAI(1),
691 ADMAIF_CODEC_FIFO_DAI(2),
692 ADMAIF_CODEC_FIFO_DAI(3),
693 ADMAIF_CODEC_FIFO_DAI(4),
694 ADMAIF_CODEC_FIFO_DAI(5),
695 ADMAIF_CODEC_FIFO_DAI(6),
696 ADMAIF_CODEC_FIFO_DAI(7),
697 ADMAIF_CODEC_FIFO_DAI(8),
698 ADMAIF_CODEC_FIFO_DAI(9),
699 ADMAIF_CODEC_FIFO_DAI(10),
700 #if defined(CONFIG_ARCH_TEGRA_18x_SOC)
701 ADMAIF_CODEC_FIFO_DAI(11),
702 ADMAIF_CODEC_FIFO_DAI(12),
703 ADMAIF_CODEC_FIFO_DAI(13),
704 ADMAIF_CODEC_FIFO_DAI(14),
705 ADMAIF_CODEC_FIFO_DAI(15),
706 ADMAIF_CODEC_FIFO_DAI(16),
707 ADMAIF_CODEC_FIFO_DAI(17),
708 ADMAIF_CODEC_FIFO_DAI(18),
709 ADMAIF_CODEC_FIFO_DAI(19),
710 ADMAIF_CODEC_FIFO_DAI(20),
712 ADMAIF_CODEC_CIF_DAI(1),
713 ADMAIF_CODEC_CIF_DAI(2),
714 ADMAIF_CODEC_CIF_DAI(3),
715 ADMAIF_CODEC_CIF_DAI(4),
716 ADMAIF_CODEC_CIF_DAI(5),
717 ADMAIF_CODEC_CIF_DAI(6),
718 ADMAIF_CODEC_CIF_DAI(7),
719 ADMAIF_CODEC_CIF_DAI(8),
720 ADMAIF_CODEC_CIF_DAI(9),
721 ADMAIF_CODEC_CIF_DAI(10),
722 #if defined(CONFIG_ARCH_TEGRA_18x_SOC)
723 ADMAIF_CODEC_CIF_DAI(11),
724 ADMAIF_CODEC_CIF_DAI(12),
725 ADMAIF_CODEC_CIF_DAI(13),
726 ADMAIF_CODEC_CIF_DAI(14),
727 ADMAIF_CODEC_CIF_DAI(15),
728 ADMAIF_CODEC_CIF_DAI(16),
729 ADMAIF_CODEC_CIF_DAI(17),
730 ADMAIF_CODEC_CIF_DAI(18),
731 ADMAIF_CODEC_CIF_DAI(19),
732 ADMAIF_CODEC_CIF_DAI(20),
736 #define ADMAIF_WIDGETS(id) \
737 SND_SOC_DAPM_AIF_IN("ADMAIF" #id " FIFO RX", NULL, 0, \
738 SND_SOC_NOPM, 0, 0), \
739 SND_SOC_DAPM_AIF_OUT("ADMAIF" #id " FIFO TX", NULL, 0, \
740 SND_SOC_NOPM, 0, 0), \
741 SND_SOC_DAPM_AIF_IN("ADMAIF" #id " CIF RX", NULL, 0, \
742 SND_SOC_NOPM, 0, 0), \
743 SND_SOC_DAPM_AIF_OUT("ADMAIF" #id " CIF TX", NULL, 0, \
746 static const struct snd_soc_dapm_widget tegra210_admaif_widgets[] = {
769 #define ADMAIF_ROUTES(id) \
770 { "ADMAIF" #id " FIFO RX", NULL, "ADMAIF" #id " FIFO Transmit" }, \
771 { "ADMAIF" #id " CIF TX", NULL, "ADMAIF" #id " FIFO RX" },\
772 { "ADMAIF" #id " CIF Receive", NULL, "ADMAIF" #id " CIF TX" }, \
773 { "ADMAIF" #id " CIF RX", NULL, "ADMAIF" #id " CIF Transmit" }, \
774 { "ADMAIF" #id " FIFO TX", NULL, "ADMAIF" #id " CIF RX" }, \
775 { "ADMAIF" #id " FIFO Receive", NULL, "ADMAIF" #id " FIFO TX" } \
777 static const struct snd_soc_dapm_route tegra210_admaif_routes[] = {
800 static const char * const tegra_admaif_stereo_conv_text[] = {
801 "None", "CH0", "CH1", "AVG",
804 static const char * const tegra_admaif_mono_conv_text[] = {
805 "None", "ZERO", "COPY",
808 static const struct soc_enum tegra_admaif_mono_conv_enum =
809 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
810 ARRAY_SIZE(tegra_admaif_mono_conv_text),
811 tegra_admaif_mono_conv_text);
813 static const struct soc_enum tegra_admaif_stereo_conv_enum =
814 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
815 ARRAY_SIZE(tegra_admaif_stereo_conv_text),
816 tegra_admaif_stereo_conv_text);
818 #define TEGRA210_ADMAIF_CHANNEL_CTRL(reg) \
819 SOC_SINGLE_EXT("ADMAIF" #reg " Channels", reg - 1, 0, 16, 0, \
820 tegra210_admaif_get_format, tegra210_admaif_put_format)
822 #define TEGRA210_ADMAIF_TX_CIF_CTRL(reg) \
823 SOC_ENUM_EXT("ADMAIF" #reg " TX mono to stereo conv", \
824 tegra_admaif_mono_conv_enum, tegra210_admaif_get_format, \
825 tegra210_admaif_put_format)
827 #define TEGRA210_ADMAIF_RX_CIF_CTRL(reg) \
828 SOC_ENUM_EXT("ADMAIF" #reg " RX stereo to mono conv", \
829 tegra_admaif_stereo_conv_enum, tegra210_admaif_get_format, \
830 tegra210_admaif_put_format)
832 static struct snd_kcontrol_new tegra210_admaif_controls[] = {
833 TEGRA210_ADMAIF_CHANNEL_CTRL(1),
834 TEGRA210_ADMAIF_CHANNEL_CTRL(2),
835 TEGRA210_ADMAIF_CHANNEL_CTRL(3),
836 TEGRA210_ADMAIF_CHANNEL_CTRL(4),
837 TEGRA210_ADMAIF_CHANNEL_CTRL(5),
838 TEGRA210_ADMAIF_CHANNEL_CTRL(6),
839 TEGRA210_ADMAIF_CHANNEL_CTRL(7),
840 TEGRA210_ADMAIF_CHANNEL_CTRL(8),
841 TEGRA210_ADMAIF_CHANNEL_CTRL(9),
842 TEGRA210_ADMAIF_CHANNEL_CTRL(10),
843 #if defined(CONFIG_ARCH_TEGRA_18x_SOC)
844 TEGRA210_ADMAIF_CHANNEL_CTRL(11),
845 TEGRA210_ADMAIF_CHANNEL_CTRL(12),
846 TEGRA210_ADMAIF_CHANNEL_CTRL(13),
847 TEGRA210_ADMAIF_CHANNEL_CTRL(14),
848 TEGRA210_ADMAIF_CHANNEL_CTRL(15),
849 TEGRA210_ADMAIF_CHANNEL_CTRL(16),
850 TEGRA210_ADMAIF_CHANNEL_CTRL(17),
851 TEGRA210_ADMAIF_CHANNEL_CTRL(18),
852 TEGRA210_ADMAIF_CHANNEL_CTRL(19),
853 TEGRA210_ADMAIF_CHANNEL_CTRL(20),
855 TEGRA210_ADMAIF_RX_CIF_CTRL(1),
856 TEGRA210_ADMAIF_RX_CIF_CTRL(2),
857 TEGRA210_ADMAIF_RX_CIF_CTRL(3),
858 TEGRA210_ADMAIF_RX_CIF_CTRL(4),
859 TEGRA210_ADMAIF_RX_CIF_CTRL(5),
860 TEGRA210_ADMAIF_RX_CIF_CTRL(6),
861 TEGRA210_ADMAIF_RX_CIF_CTRL(7),
862 TEGRA210_ADMAIF_RX_CIF_CTRL(8),
863 TEGRA210_ADMAIF_RX_CIF_CTRL(9),
864 TEGRA210_ADMAIF_RX_CIF_CTRL(10),
865 #if defined(CONFIG_ARCH_TEGRA_18x_SOC)
866 TEGRA210_ADMAIF_RX_CIF_CTRL(11),
867 TEGRA210_ADMAIF_RX_CIF_CTRL(12),
868 TEGRA210_ADMAIF_RX_CIF_CTRL(13),
869 TEGRA210_ADMAIF_RX_CIF_CTRL(14),
870 TEGRA210_ADMAIF_RX_CIF_CTRL(15),
871 TEGRA210_ADMAIF_RX_CIF_CTRL(16),
872 TEGRA210_ADMAIF_RX_CIF_CTRL(17),
873 TEGRA210_ADMAIF_RX_CIF_CTRL(18),
874 TEGRA210_ADMAIF_RX_CIF_CTRL(19),
875 TEGRA210_ADMAIF_RX_CIF_CTRL(20),
877 TEGRA210_ADMAIF_TX_CIF_CTRL(1),
878 TEGRA210_ADMAIF_TX_CIF_CTRL(2),
879 TEGRA210_ADMAIF_TX_CIF_CTRL(3),
880 TEGRA210_ADMAIF_TX_CIF_CTRL(4),
881 TEGRA210_ADMAIF_TX_CIF_CTRL(5),
882 TEGRA210_ADMAIF_TX_CIF_CTRL(6),
883 TEGRA210_ADMAIF_TX_CIF_CTRL(7),
884 TEGRA210_ADMAIF_TX_CIF_CTRL(8),
885 TEGRA210_ADMAIF_TX_CIF_CTRL(9),
886 TEGRA210_ADMAIF_TX_CIF_CTRL(10),
887 #if defined(CONFIG_ARCH_TEGRA_18x_SOC)
888 TEGRA210_ADMAIF_TX_CIF_CTRL(11),
889 TEGRA210_ADMAIF_TX_CIF_CTRL(12),
890 TEGRA210_ADMAIF_TX_CIF_CTRL(13),
891 TEGRA210_ADMAIF_TX_CIF_CTRL(14),
892 TEGRA210_ADMAIF_TX_CIF_CTRL(15),
893 TEGRA210_ADMAIF_TX_CIF_CTRL(16),
894 TEGRA210_ADMAIF_TX_CIF_CTRL(17),
895 TEGRA210_ADMAIF_TX_CIF_CTRL(18),
896 TEGRA210_ADMAIF_TX_CIF_CTRL(19),
897 TEGRA210_ADMAIF_TX_CIF_CTRL(20),
901 static int tegra210_admaif_codec_probe(struct snd_soc_codec *codec)
903 struct tegra210_admaif *admaif = snd_soc_codec_get_drvdata(codec);
905 codec->control_data = admaif->regmap;
910 static struct snd_soc_codec_driver tegra210_admaif_codec = {
911 .probe = tegra210_admaif_codec_probe,
912 .dapm_widgets = tegra210_admaif_widgets,
913 .num_dapm_widgets = TEGRA210_ADMAIF_CHANNEL_COUNT * 4,
914 .dapm_routes = tegra210_admaif_routes,
915 .num_dapm_routes = TEGRA210_ADMAIF_CHANNEL_COUNT * 6,
916 .controls = tegra210_admaif_controls,
917 .num_controls = ARRAY_SIZE(tegra210_admaif_controls),
921 static const struct snd_soc_component_driver tegra210_admaif_dai_driver = {
925 static struct tegra210_admaif_soc_data soc_data_tegra210 = {
926 .num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT,
927 .set_audio_cif = tegra210_xbar_set_cif,
930 static const struct of_device_id tegra210_admaif_of_match[] = {
931 { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
935 static int tegra210_admaif_probe(struct platform_device *pdev)
940 struct tegra210_admaif *admaif;
942 struct resource *res;
943 const struct of_device_id *match;
944 struct tegra210_admaif_soc_data *soc_data;
945 unsigned int buffer_size;
947 match = of_match_device(tegra210_admaif_of_match, &pdev->dev);
949 dev_err(&pdev->dev, "Error: No device match found\n");
952 soc_data = (struct tegra210_admaif_soc_data *)match->data;
954 admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
956 dev_err(&pdev->dev, "Can't allocate tegra210_admaif\n");
963 admaif->soc_data = soc_data;
964 admaif->is_shutdown = false;
966 admaif->capture_dma_data = devm_kzalloc(&pdev->dev,
967 sizeof(struct tegra_alt_pcm_dma_params) *
968 admaif->soc_data->num_ch,
970 if (!admaif->capture_dma_data) {
971 dev_err(&pdev->dev, "Can't allocate capture_dma_data\n");
976 admaif->playback_dma_data = devm_kzalloc(&pdev->dev,
977 sizeof(struct tegra_alt_pcm_dma_params) *
978 admaif->soc_data->num_ch,
980 if (!admaif->playback_dma_data) {
981 dev_err(&pdev->dev, "Can't allocate playback_dma_data\n");
986 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
988 dev_err(&pdev->dev, "No memory resource for admaif\n");
993 regs = devm_ioremap_resource(&pdev->dev, res);
995 dev_err(&pdev->dev, "request/iomap region failed\n");
1000 admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
1001 &tegra210_admaif_regmap_config);
1002 if (IS_ERR(admaif->regmap)) {
1003 dev_err(&pdev->dev, "regmap init failed\n");
1004 ret = PTR_ERR(admaif->regmap);
1007 regcache_cache_only(admaif->regmap, true);
1009 pm_runtime_enable(&pdev->dev);
1010 if (!pm_runtime_enabled(&pdev->dev)) {
1011 ret = tegra210_admaif_runtime_resume(&pdev->dev);
1013 goto err_pm_disable;
1016 if (admaif->soc_data->is_isomgr_client)
1017 tegra_isomgr_adma_register();
1019 for (i = 0; i < admaif->soc_data->num_ch; i++) {
1020 admaif->playback_dma_data[i].addr = res->start +
1021 TEGRA210_ADMAIF_XBAR_TX_FIFO_WRITE +
1022 (i * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
1024 admaif->capture_dma_data[i].addr = res->start +
1025 TEGRA210_ADMAIF_XBAR_RX_FIFO_READ +
1026 (i * TEGRA210_ADMAIF_CHANNEL_REG_STRIDE);
1028 admaif->playback_dma_data[i].wrap = 4;
1029 admaif->playback_dma_data[i].width = 32;
1030 admaif->playback_dma_data[i].req_sel = i + 1;
1031 if (of_property_read_string_index(pdev->dev.of_node,
1034 &admaif->playback_dma_data[i].chan_name) < 0) {
1036 "Missing property nvidia,dma-names\n");
1041 if (of_property_read_u32_index(pdev->dev.of_node,
1044 &buffer_size) < 0) {
1046 "Missing property nvidia,dma-buffer-size\n");
1048 admaif->playback_dma_data[i].buffer_size = buffer_size;
1050 admaif->capture_dma_data[i].wrap = 4;
1051 admaif->capture_dma_data[i].width = 32;
1052 admaif->capture_dma_data[i].req_sel = i + 1;
1053 if (of_property_read_string_index(pdev->dev.of_node,
1056 &admaif->capture_dma_data[i].chan_name) < 0) {
1058 "Missing property nvidia,dma-names\n");
1063 if (of_property_read_u32_index(pdev->dev.of_node,
1066 &buffer_size) < 0) {
1068 "Missing property nvidia,dma-buffer-size\n");
1070 admaif->capture_dma_data[i].buffer_size = buffer_size;
1073 ret = snd_soc_register_component(&pdev->dev,
1074 &tegra210_admaif_dai_driver,
1075 tegra210_admaif_dais,
1076 admaif->soc_data->num_ch);
1078 dev_err(&pdev->dev, "Could not register DAIs %d: %d\n",
1084 ret = snd_soc_register_codec(&pdev->dev, &tegra210_admaif_codec,
1085 tegra210_admaif_codec_dais,
1086 admaif->soc_data->num_ch * 2);
1088 dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
1089 goto err_unregister_dais;
1092 ret = tegra_alt_pcm_platform_register(&pdev->dev);
1094 dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
1095 goto err_unregister_codec;
1098 regmap_update_bits(admaif->regmap,
1099 TEGRA210_ADMAIF_GLOBAL_ENABLE, 1, 1);
1101 dev_set_drvdata(&pdev->dev, admaif);
1105 err_unregister_codec:
1106 snd_soc_unregister_codec(&pdev->dev);
1107 err_unregister_dais:
1108 snd_soc_unregister_component(&pdev->dev);
1110 if (!pm_runtime_status_suspended(&pdev->dev))
1111 tegra210_admaif_runtime_suspend(&pdev->dev);
1113 pm_runtime_disable(&pdev->dev);
1118 static void tegra210_admaif_platform_shutdown(struct platform_device *pdev)
1120 struct tegra210_admaif *admaif = dev_get_drvdata(&pdev->dev);
1122 admaif->is_shutdown = true;
1125 static int tegra210_admaif_remove(struct platform_device *pdev)
1127 struct tegra210_admaif *admaif = dev_get_drvdata(&pdev->dev);
1129 if (admaif->soc_data->is_isomgr_client)
1130 tegra_isomgr_adma_unregister();
1132 snd_soc_unregister_component(&pdev->dev);
1134 snd_soc_unregister_codec(&pdev->dev);
1136 tegra_alt_pcm_platform_unregister(&pdev->dev);
1138 pm_runtime_disable(&pdev->dev);
1139 if (!pm_runtime_status_suspended(&pdev->dev))
1140 tegra210_admaif_runtime_suspend(&pdev->dev);
1145 static const struct dev_pm_ops tegra210_admaif_pm_ops = {
1146 SET_RUNTIME_PM_OPS(tegra210_admaif_runtime_suspend,
1147 tegra210_admaif_runtime_resume, NULL)
1148 SET_SYSTEM_SLEEP_PM_OPS(tegra210_admaif_suspend, NULL)
1151 static struct platform_driver tegra210_admaif_driver = {
1152 .probe = tegra210_admaif_probe,
1153 .remove = tegra210_admaif_remove,
1154 .shutdown = tegra210_admaif_platform_shutdown,
1157 .owner = THIS_MODULE,
1158 .of_match_table = tegra210_admaif_of_match,
1159 .pm = &tegra210_admaif_pm_ops,
1162 module_platform_driver(tegra210_admaif_driver);
1164 MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
1165 MODULE_DESCRIPTION("Tegra210 ADMAIF driver");
1166 MODULE_LICENSE("GPL v2");
1167 MODULE_ALIAS("platform:" DRV_NAME);