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