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");