1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES.
3 // All rights reserved.
5 // tegra210_admaif.c - Tegra ADMAIF driver
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_S24_LE
:
289 cif_conf
.audio_bits
= TEGRA_ACIF_BITS_32
;
290 cif_conf
.client_bits
= TEGRA_ACIF_BITS_24
;
291 valid_bit
= DATA_32BIT
;
293 case SNDRV_PCM_FORMAT_S32_LE
:
294 cif_conf
.audio_bits
= TEGRA_ACIF_BITS_32
;
295 cif_conf
.client_bits
= TEGRA_ACIF_BITS_32
;
296 valid_bit
= DATA_32BIT
;
299 dev_err(dev
, "unsupported format!\n");
303 channels
= params_channels(params
);
304 cif_conf
.client_ch
= channels
;
305 cif_conf
.audio_ch
= channels
;
307 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
308 path
= ADMAIF_TX_PATH
;
309 reg
= CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL
, dai
->id
);
311 path
= ADMAIF_RX_PATH
;
312 reg
= CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL
, dai
->id
);
315 cif_conf
.mono_conv
= admaif
->mono_to_stereo
[path
][dai
->id
];
316 cif_conf
.stereo_conv
= admaif
->stereo_to_mono
[path
][dai
->id
];
318 tegra_admaif_set_pack_mode(admaif
->regmap
, reg
, valid_bit
);
320 tegra_set_cif(admaif
->regmap
, reg
, &cif_conf
);
325 static int tegra_admaif_start(struct snd_soc_dai
*dai
, int direction
)
327 struct tegra_admaif
*admaif
= snd_soc_dai_get_drvdata(dai
);
328 unsigned int reg
, mask
, val
;
331 case SNDRV_PCM_STREAM_PLAYBACK
:
332 mask
= TX_ENABLE_MASK
;
334 reg
= CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE
, dai
->id
);
336 case SNDRV_PCM_STREAM_CAPTURE
:
337 mask
= RX_ENABLE_MASK
;
339 reg
= CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE
, dai
->id
);
345 regmap_update_bits(admaif
->regmap
, reg
, mask
, val
);
350 static int tegra_admaif_stop(struct snd_soc_dai
*dai
, int direction
)
352 struct tegra_admaif
*admaif
= snd_soc_dai_get_drvdata(dai
);
353 unsigned int enable_reg
, status_reg
, reset_reg
, mask
, val
;
358 case SNDRV_PCM_STREAM_PLAYBACK
:
359 mask
= TX_ENABLE_MASK
;
362 enable_reg
= CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE
, dai
->id
);
363 status_reg
= CH_TX_REG(TEGRA_ADMAIF_TX_STATUS
, dai
->id
);
364 reset_reg
= CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET
, dai
->id
);
366 case SNDRV_PCM_STREAM_CAPTURE
:
367 mask
= RX_ENABLE_MASK
;
370 enable_reg
= CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE
, dai
->id
);
371 status_reg
= CH_RX_REG(TEGRA_ADMAIF_RX_STATUS
, dai
->id
);
372 reset_reg
= CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET
, dai
->id
);
378 /* Disable TX/RX channel */
379 regmap_update_bits(admaif
->regmap
, enable_reg
, mask
, ~enable
);
381 /* Wait until ADMAIF TX/RX status is disabled */
382 err
= regmap_read_poll_timeout_atomic(admaif
->regmap
, status_reg
, val
,
383 !(val
& enable
), 10, 10000);
385 dev_warn(dai
->dev
, "timeout: failed to disable ADMAIF%d_%s\n",
386 dai
->id
+ 1, dir_name
);
389 regmap_update_bits(admaif
->regmap
, reset_reg
, SW_RESET_MASK
, SW_RESET
);
391 /* Wait till SW reset is complete */
392 err
= regmap_read_poll_timeout_atomic(admaif
->regmap
, reset_reg
, val
,
393 !(val
& SW_RESET_MASK
& SW_RESET
),
396 dev_err(dai
->dev
, "timeout: SW reset failed for ADMAIF%d_%s\n",
397 dai
->id
+ 1, dir_name
);
404 static int tegra_admaif_trigger(struct snd_pcm_substream
*substream
, int cmd
,
405 struct snd_soc_dai
*dai
)
409 err
= snd_dmaengine_pcm_trigger(substream
, cmd
);
414 case SNDRV_PCM_TRIGGER_START
:
415 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
416 case SNDRV_PCM_TRIGGER_RESUME
:
417 return tegra_admaif_start(dai
, substream
->stream
);
418 case SNDRV_PCM_TRIGGER_STOP
:
419 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
420 case SNDRV_PCM_TRIGGER_SUSPEND
:
421 return tegra_admaif_stop(dai
, substream
->stream
);
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 snd_soc_dai_init_dma_data(dai
, &admaif
->playback_dma_data
[dai
->id
],
548 &admaif
->capture_dma_data
[dai
->id
]);
553 static const struct snd_soc_dai_ops tegra_admaif_dai_ops
= {
554 .probe
= tegra_admaif_dai_probe
,
555 .hw_params
= tegra_admaif_hw_params
,
556 .trigger
= tegra_admaif_trigger
,
559 #define DAI(dai_name) \
563 .stream_name = dai_name " Playback", \
565 .channels_max = 16, \
566 .rates = SNDRV_PCM_RATE_8000_192000, \
567 .formats = SNDRV_PCM_FMTBIT_S8 | \
568 SNDRV_PCM_FMTBIT_S16_LE | \
569 SNDRV_PCM_FMTBIT_S24_LE | \
570 SNDRV_PCM_FMTBIT_S32_LE, \
573 .stream_name = dai_name " Capture", \
575 .channels_max = 16, \
576 .rates = SNDRV_PCM_RATE_8000_192000, \
577 .formats = SNDRV_PCM_FMTBIT_S8 | \
578 SNDRV_PCM_FMTBIT_S16_LE | \
579 SNDRV_PCM_FMTBIT_S24_LE | \
580 SNDRV_PCM_FMTBIT_S32_LE, \
582 .ops = &tegra_admaif_dai_ops, \
585 static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais
[] = {
598 static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais
[] = {
621 static const char * const tegra_admaif_stereo_conv_text
[] = {
625 static const char * const tegra_admaif_mono_conv_text
[] = {
630 * Below macro is added to avoid looping over all ADMAIFx controls related
631 * to mono/stereo conversions in get()/put() callbacks.
633 #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \
635 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
636 .info = snd_soc_info_enum_double, \
638 .get = xhandler_get, \
639 .put = xhandler_put, \
640 .private_value = (unsigned long)&(struct soc_enum) \
641 SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text) \
644 #define TEGRA_ADMAIF_CIF_CTRL(reg) \
645 NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \
646 tegra210_admaif_pget_mono_to_stereo, \
647 tegra210_admaif_pput_mono_to_stereo, \
648 tegra_admaif_mono_conv_text), \
649 NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \
650 tegra210_admaif_pget_stereo_to_mono, \
651 tegra210_admaif_pput_stereo_to_mono, \
652 tegra_admaif_stereo_conv_text), \
653 NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
654 tegra210_admaif_cget_mono_to_stereo, \
655 tegra210_admaif_cput_mono_to_stereo, \
656 tegra_admaif_mono_conv_text), \
657 NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
658 tegra210_admaif_cget_stereo_to_mono, \
659 tegra210_admaif_cput_stereo_to_mono, \
660 tegra_admaif_stereo_conv_text)
662 static struct snd_kcontrol_new tegra210_admaif_controls
[] = {
663 TEGRA_ADMAIF_CIF_CTRL(1),
664 TEGRA_ADMAIF_CIF_CTRL(2),
665 TEGRA_ADMAIF_CIF_CTRL(3),
666 TEGRA_ADMAIF_CIF_CTRL(4),
667 TEGRA_ADMAIF_CIF_CTRL(5),
668 TEGRA_ADMAIF_CIF_CTRL(6),
669 TEGRA_ADMAIF_CIF_CTRL(7),
670 TEGRA_ADMAIF_CIF_CTRL(8),
671 TEGRA_ADMAIF_CIF_CTRL(9),
672 TEGRA_ADMAIF_CIF_CTRL(10),
675 static struct snd_kcontrol_new tegra186_admaif_controls
[] = {
676 TEGRA_ADMAIF_CIF_CTRL(1),
677 TEGRA_ADMAIF_CIF_CTRL(2),
678 TEGRA_ADMAIF_CIF_CTRL(3),
679 TEGRA_ADMAIF_CIF_CTRL(4),
680 TEGRA_ADMAIF_CIF_CTRL(5),
681 TEGRA_ADMAIF_CIF_CTRL(6),
682 TEGRA_ADMAIF_CIF_CTRL(7),
683 TEGRA_ADMAIF_CIF_CTRL(8),
684 TEGRA_ADMAIF_CIF_CTRL(9),
685 TEGRA_ADMAIF_CIF_CTRL(10),
686 TEGRA_ADMAIF_CIF_CTRL(11),
687 TEGRA_ADMAIF_CIF_CTRL(12),
688 TEGRA_ADMAIF_CIF_CTRL(13),
689 TEGRA_ADMAIF_CIF_CTRL(14),
690 TEGRA_ADMAIF_CIF_CTRL(15),
691 TEGRA_ADMAIF_CIF_CTRL(16),
692 TEGRA_ADMAIF_CIF_CTRL(17),
693 TEGRA_ADMAIF_CIF_CTRL(18),
694 TEGRA_ADMAIF_CIF_CTRL(19),
695 TEGRA_ADMAIF_CIF_CTRL(20),
698 static const struct snd_soc_component_driver tegra210_admaif_cmpnt
= {
699 .controls
= tegra210_admaif_controls
,
700 .num_controls
= ARRAY_SIZE(tegra210_admaif_controls
),
701 .pcm_construct
= tegra_pcm_construct
,
702 .open
= tegra_pcm_open
,
703 .close
= tegra_pcm_close
,
704 .hw_params
= tegra_pcm_hw_params
,
705 .pointer
= tegra_pcm_pointer
,
708 static const struct snd_soc_component_driver tegra186_admaif_cmpnt
= {
709 .controls
= tegra186_admaif_controls
,
710 .num_controls
= ARRAY_SIZE(tegra186_admaif_controls
),
711 .pcm_construct
= tegra_pcm_construct
,
712 .open
= tegra_pcm_open
,
713 .close
= tegra_pcm_close
,
714 .hw_params
= tegra_pcm_hw_params
,
715 .pointer
= tegra_pcm_pointer
,
718 static const struct tegra_admaif_soc_data soc_data_tegra210
= {
719 .num_ch
= TEGRA210_ADMAIF_CHANNEL_COUNT
,
720 .cmpnt
= &tegra210_admaif_cmpnt
,
721 .dais
= tegra210_admaif_cmpnt_dais
,
722 .regmap_conf
= &tegra210_admaif_regmap_config
,
723 .global_base
= TEGRA210_ADMAIF_GLOBAL_BASE
,
724 .tx_base
= TEGRA210_ADMAIF_TX_BASE
,
725 .rx_base
= TEGRA210_ADMAIF_RX_BASE
,
728 static const struct tegra_admaif_soc_data soc_data_tegra186
= {
729 .num_ch
= TEGRA186_ADMAIF_CHANNEL_COUNT
,
730 .cmpnt
= &tegra186_admaif_cmpnt
,
731 .dais
= tegra186_admaif_cmpnt_dais
,
732 .regmap_conf
= &tegra186_admaif_regmap_config
,
733 .global_base
= TEGRA186_ADMAIF_GLOBAL_BASE
,
734 .tx_base
= TEGRA186_ADMAIF_TX_BASE
,
735 .rx_base
= TEGRA186_ADMAIF_RX_BASE
,
738 static const struct of_device_id tegra_admaif_of_match
[] = {
739 { .compatible
= "nvidia,tegra210-admaif", .data
= &soc_data_tegra210
},
740 { .compatible
= "nvidia,tegra186-admaif", .data
= &soc_data_tegra186
},
743 MODULE_DEVICE_TABLE(of
, tegra_admaif_of_match
);
745 static int tegra_admaif_probe(struct platform_device
*pdev
)
747 struct tegra_admaif
*admaif
;
749 struct resource
*res
;
752 admaif
= devm_kzalloc(&pdev
->dev
, sizeof(*admaif
), GFP_KERNEL
);
756 admaif
->soc_data
= of_device_get_match_data(&pdev
->dev
);
758 dev_set_drvdata(&pdev
->dev
, admaif
);
760 admaif
->capture_dma_data
=
761 devm_kcalloc(&pdev
->dev
,
762 admaif
->soc_data
->num_ch
,
763 sizeof(struct snd_dmaengine_dai_dma_data
),
765 if (!admaif
->capture_dma_data
)
768 admaif
->playback_dma_data
=
769 devm_kcalloc(&pdev
->dev
,
770 admaif
->soc_data
->num_ch
,
771 sizeof(struct snd_dmaengine_dai_dma_data
),
773 if (!admaif
->playback_dma_data
)
776 for (i
= 0; i
< ADMAIF_PATHS
; i
++) {
777 admaif
->mono_to_stereo
[i
] =
778 devm_kcalloc(&pdev
->dev
, admaif
->soc_data
->num_ch
,
779 sizeof(unsigned int), GFP_KERNEL
);
780 if (!admaif
->mono_to_stereo
[i
])
783 admaif
->stereo_to_mono
[i
] =
784 devm_kcalloc(&pdev
->dev
, admaif
->soc_data
->num_ch
,
785 sizeof(unsigned int), GFP_KERNEL
);
786 if (!admaif
->stereo_to_mono
[i
])
790 regs
= devm_platform_get_and_ioremap_resource(pdev
, 0, &res
);
792 return PTR_ERR(regs
);
794 admaif
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, regs
,
795 admaif
->soc_data
->regmap_conf
);
796 if (IS_ERR(admaif
->regmap
)) {
797 dev_err(&pdev
->dev
, "regmap init failed\n");
798 return PTR_ERR(admaif
->regmap
);
801 regcache_cache_only(admaif
->regmap
, true);
803 regmap_update_bits(admaif
->regmap
, admaif
->soc_data
->global_base
+
804 TEGRA_ADMAIF_GLOBAL_ENABLE
, 1, 1);
806 for (i
= 0; i
< admaif
->soc_data
->num_ch
; i
++) {
807 admaif
->playback_dma_data
[i
].addr
= res
->start
+
808 CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE
, i
);
810 admaif
->capture_dma_data
[i
].addr
= res
->start
+
811 CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ
, i
);
813 admaif
->playback_dma_data
[i
].addr_width
= 32;
815 if (of_property_read_string_index(pdev
->dev
.of_node
,
816 "dma-names", (i
* 2) + 1,
817 &admaif
->playback_dma_data
[i
].chan_name
) < 0) {
819 "missing property nvidia,dma-names\n");
824 admaif
->capture_dma_data
[i
].addr_width
= 32;
826 if (of_property_read_string_index(pdev
->dev
.of_node
,
829 &admaif
->capture_dma_data
[i
].chan_name
) < 0) {
831 "missing property nvidia,dma-names\n");
837 err
= devm_snd_soc_register_component(&pdev
->dev
,
838 admaif
->soc_data
->cmpnt
,
839 admaif
->soc_data
->dais
,
840 admaif
->soc_data
->num_ch
);
843 "can't register ADMAIF component, err: %d\n", err
);
847 pm_runtime_enable(&pdev
->dev
);
852 static void tegra_admaif_remove(struct platform_device
*pdev
)
854 pm_runtime_disable(&pdev
->dev
);
857 static const struct dev_pm_ops tegra_admaif_pm_ops
= {
858 SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend
,
859 tegra_admaif_runtime_resume
, NULL
)
860 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
861 pm_runtime_force_resume
)
864 static struct platform_driver tegra_admaif_driver
= {
865 .probe
= tegra_admaif_probe
,
866 .remove
= tegra_admaif_remove
,
868 .name
= "tegra210-admaif",
869 .of_match_table
= tegra_admaif_of_match
,
870 .pm
= &tegra_admaif_pm_ops
,
873 module_platform_driver(tegra_admaif_driver
);
875 MODULE_AUTHOR("Songhee Baek <sbaek@nvidia.com>");
876 MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
877 MODULE_LICENSE("GPL v2");