1 // SPDX-License-Identifier: GPL-2.0-only
3 // tegra186_asrc.c - Tegra186 ASRC driver
5 // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
8 #include <linux/delay.h>
9 #include <linux/device.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/regmap.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
21 #include "tegra186_asrc.h"
22 #include "tegra_cif.h"
24 #define ASRC_STREAM_SOURCE_SELECT(id) \
25 (TEGRA186_ASRC_CFG + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
27 #define ASRC_STREAM_REG(reg, id) ((reg) + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
29 #define ASRC_STREAM_REG_DEFAULTS(id) \
30 { ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id), \
31 (((id) + 1) << 4) }, \
32 { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id), \
34 { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id), \
36 { ASRC_STREAM_REG(TEGRA186_ASRC_MUTE_UNMUTE_DURATION, id), \
38 { ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, id), \
40 { ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id), \
43 static const struct reg_default tegra186_asrc_reg_defaults
[] = {
44 ASRC_STREAM_REG_DEFAULTS(0),
45 ASRC_STREAM_REG_DEFAULTS(1),
46 ASRC_STREAM_REG_DEFAULTS(2),
47 ASRC_STREAM_REG_DEFAULTS(3),
48 ASRC_STREAM_REG_DEFAULTS(4),
49 ASRC_STREAM_REG_DEFAULTS(5),
51 { TEGRA186_ASRC_GLOBAL_ENB
, 0},
52 { TEGRA186_ASRC_GLOBAL_SOFT_RESET
, 0},
53 { TEGRA186_ASRC_GLOBAL_CG
, 0x1 },
54 { TEGRA186_ASRC_GLOBAL_CFG
, 0x0 },
55 { TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR
, 0},
56 { TEGRA186_ASRC_GLOBAL_SCRATCH_CFG
, 0x0c207980 },
57 { TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL
, 0x00115500 },
58 { TEGRA186_ASRC_GLOBAL_INT_MASK
, 0x0},
59 { TEGRA186_ASRC_GLOBAL_INT_SET
, 0x0},
60 { TEGRA186_ASRC_GLOBAL_INT_CLEAR
, 0x0},
61 { TEGRA186_ASRC_GLOBAL_APR_CTRL
, 0x0},
62 { TEGRA186_ASRC_GLOBAL_APR_CTRL_ACCESS_CTRL
, 0x0},
63 { TEGRA186_ASRC_GLOBAL_DISARM_APR
, 0x0},
64 { TEGRA186_ASRC_GLOBAL_DISARM_APR_ACCESS_CTRL
, 0x0},
65 { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS
, 0x0},
66 { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS_CTRL
, 0x0},
67 { TEGRA186_ASRC_CYA
, 0x0},
70 static void tegra186_asrc_lock_stream(struct tegra186_asrc
*asrc
,
73 regmap_write(asrc
->regmap
,
74 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_LOCK_STATUS
,
79 static int __maybe_unused
tegra186_asrc_runtime_suspend(struct device
*dev
)
81 struct tegra186_asrc
*asrc
= dev_get_drvdata(dev
);
83 regcache_cache_only(asrc
->regmap
, true);
84 regcache_mark_dirty(asrc
->regmap
);
89 static int __maybe_unused
tegra186_asrc_runtime_resume(struct device
*dev
)
91 struct tegra186_asrc
*asrc
= dev_get_drvdata(dev
);
94 regcache_cache_only(asrc
->regmap
, false);
97 * Below sequence is recommended after a runtime PM cycle.
98 * This otherwise leads to transfer failures. The cache
99 * sync is done after this to restore other settings.
101 regmap_write(asrc
->regmap
, TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR
,
102 TEGRA186_ASRC_ARAM_START_ADDR
);
103 regmap_write(asrc
->regmap
, TEGRA186_ASRC_GLOBAL_ENB
,
104 TEGRA186_ASRC_GLOBAL_EN
);
106 regcache_sync(asrc
->regmap
);
108 for (id
= 0; id
< TEGRA186_ASRC_STREAM_MAX
; id
++) {
109 if (asrc
->lane
[id
].ratio_source
!=
110 TEGRA186_ASRC_RATIO_SOURCE_SW
)
113 regmap_write(asrc
->regmap
,
114 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
,
116 asrc
->lane
[id
].int_part
);
118 regmap_write(asrc
->regmap
,
119 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
,
121 asrc
->lane
[id
].frac_part
);
123 tegra186_asrc_lock_stream(asrc
, id
);
129 static int tegra186_asrc_set_audio_cif(struct tegra186_asrc
*asrc
,
130 struct snd_pcm_hw_params
*params
,
133 int channels
, audio_bits
;
134 struct tegra_cif_conf cif_conf
;
136 memset(&cif_conf
, 0, sizeof(struct tegra_cif_conf
));
138 channels
= params_channels(params
);
140 switch (params_format(params
)) {
141 case SNDRV_PCM_FORMAT_S16_LE
:
142 audio_bits
= TEGRA_ACIF_BITS_16
;
144 case SNDRV_PCM_FORMAT_S24_LE
:
145 case SNDRV_PCM_FORMAT_S32_LE
:
146 audio_bits
= TEGRA_ACIF_BITS_32
;
152 cif_conf
.audio_ch
= channels
;
153 cif_conf
.client_ch
= channels
;
154 cif_conf
.audio_bits
= audio_bits
;
155 cif_conf
.client_bits
= TEGRA_ACIF_BITS_24
;
157 tegra_set_cif(asrc
->regmap
, reg
, &cif_conf
);
162 static int tegra186_asrc_in_hw_params(struct snd_pcm_substream
*substream
,
163 struct snd_pcm_hw_params
*params
,
164 struct snd_soc_dai
*dai
)
166 struct device
*dev
= dai
->dev
;
167 struct tegra186_asrc
*asrc
= snd_soc_dai_get_drvdata(dai
);
168 int ret
, id
= dai
->id
;
170 /* Set input threshold */
171 regmap_write(asrc
->regmap
,
172 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD
, dai
->id
),
173 asrc
->lane
[id
].input_thresh
);
175 ret
= tegra186_asrc_set_audio_cif(asrc
, params
,
176 ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL
, dai
->id
));
178 dev_err(dev
, "Can't set ASRC RX%d CIF: %d\n", dai
->id
, ret
);
185 static int tegra186_asrc_out_hw_params(struct snd_pcm_substream
*substream
,
186 struct snd_pcm_hw_params
*params
,
187 struct snd_soc_dai
*dai
)
189 struct device
*dev
= dai
->dev
;
190 struct tegra186_asrc
*asrc
= snd_soc_dai_get_drvdata(dai
);
191 int ret
, id
= dai
->id
- 7;
193 /* Set output threshold */
194 regmap_write(asrc
->regmap
,
195 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD
, id
),
196 asrc
->lane
[id
].output_thresh
);
198 ret
= tegra186_asrc_set_audio_cif(asrc
, params
,
199 ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL
, id
));
201 dev_err(dev
, "Can't set ASRC TX%d CIF: %d\n", id
, ret
);
205 /* Set ENABLE_HW_RATIO_COMP */
206 if (asrc
->lane
[id
].hwcomp_disable
) {
207 regmap_update_bits(asrc
->regmap
,
208 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, id
),
209 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK
,
210 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_DISABLE
);
212 regmap_update_bits(asrc
->regmap
,
213 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, id
),
214 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK
,
215 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_ENABLE
);
217 regmap_write(asrc
->regmap
,
218 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_COMP
, id
),
219 TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE
);
223 regmap_update_bits(asrc
->regmap
,
224 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, id
),
225 1, asrc
->lane
[id
].ratio_source
);
227 if (asrc
->lane
[id
].ratio_source
== TEGRA186_ASRC_RATIO_SOURCE_SW
) {
228 regmap_write(asrc
->regmap
,
229 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, id
),
230 asrc
->lane
[id
].int_part
);
231 regmap_write(asrc
->regmap
,
232 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, id
),
233 asrc
->lane
[id
].frac_part
);
234 tegra186_asrc_lock_stream(asrc
, id
);
240 static int tegra186_asrc_get_ratio_source(struct snd_kcontrol
*kcontrol
,
241 struct snd_ctl_elem_value
*ucontrol
)
243 struct soc_enum
*asrc_private
=
244 (struct soc_enum
*)kcontrol
->private_value
;
245 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
246 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
247 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
249 ucontrol
->value
.enumerated
.item
[0] = asrc
->lane
[id
].ratio_source
;
254 static int tegra186_asrc_put_ratio_source(struct snd_kcontrol
*kcontrol
,
255 struct snd_ctl_elem_value
*ucontrol
)
257 struct soc_enum
*asrc_private
=
258 (struct soc_enum
*)kcontrol
->private_value
;
259 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
260 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
261 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
264 asrc
->lane
[id
].ratio_source
= ucontrol
->value
.enumerated
.item
[0];
266 regmap_update_bits_check(asrc
->regmap
, asrc_private
->reg
,
267 TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK
,
268 asrc
->lane
[id
].ratio_source
,
271 return change
? 1 : 0;
274 static int tegra186_asrc_get_ratio_int(struct snd_kcontrol
*kcontrol
,
275 struct snd_ctl_elem_value
*ucontrol
)
277 struct soc_mixer_control
*asrc_private
=
278 (struct soc_mixer_control
*)kcontrol
->private_value
;
279 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
280 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
281 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
283 regmap_read(asrc
->regmap
,
284 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, id
),
285 &asrc
->lane
[id
].int_part
);
287 ucontrol
->value
.integer
.value
[0] = asrc
->lane
[id
].int_part
;
292 static int tegra186_asrc_put_ratio_int(struct snd_kcontrol
*kcontrol
,
293 struct snd_ctl_elem_value
*ucontrol
)
295 struct soc_mixer_control
*asrc_private
=
296 (struct soc_mixer_control
*)kcontrol
->private_value
;
297 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
298 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
299 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
302 if (asrc
->lane
[id
].ratio_source
== TEGRA186_ASRC_RATIO_SOURCE_ARAD
) {
304 "Lane %d ratio source is ARAD, invalid SW update\n",
309 asrc
->lane
[id
].int_part
= ucontrol
->value
.integer
.value
[0];
311 regmap_update_bits_check(asrc
->regmap
,
312 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
,
314 TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK
,
315 asrc
->lane
[id
].int_part
, &change
);
317 tegra186_asrc_lock_stream(asrc
, id
);
319 return change
? 1 : 0;
322 static int tegra186_asrc_get_ratio_frac(struct snd_kcontrol
*kcontrol
,
323 struct snd_ctl_elem_value
*ucontrol
)
325 struct soc_mreg_control
*asrc_private
=
326 (struct soc_mreg_control
*)kcontrol
->private_value
;
327 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
328 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
329 unsigned int id
= asrc_private
->regbase
/ TEGRA186_ASRC_STREAM_STRIDE
;
331 regmap_read(asrc
->regmap
,
332 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, id
),
333 &asrc
->lane
[id
].frac_part
);
335 ucontrol
->value
.integer
.value
[0] = asrc
->lane
[id
].frac_part
;
340 static int tegra186_asrc_put_ratio_frac(struct snd_kcontrol
*kcontrol
,
341 struct snd_ctl_elem_value
*ucontrol
)
343 struct soc_mreg_control
*asrc_private
=
344 (struct soc_mreg_control
*)kcontrol
->private_value
;
345 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
346 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
347 unsigned int id
= asrc_private
->regbase
/ TEGRA186_ASRC_STREAM_STRIDE
;
350 if (asrc
->lane
[id
].ratio_source
== TEGRA186_ASRC_RATIO_SOURCE_ARAD
) {
352 "Lane %d ratio source is ARAD, invalid SW update\n",
357 asrc
->lane
[id
].frac_part
= ucontrol
->value
.integer
.value
[0];
359 regmap_update_bits_check(asrc
->regmap
,
360 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
,
362 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK
,
363 asrc
->lane
[id
].frac_part
, &change
);
365 tegra186_asrc_lock_stream(asrc
, id
);
367 return change
? 1 : 0;
370 static int tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol
*kcontrol
,
371 struct snd_ctl_elem_value
*ucontrol
)
373 struct soc_mixer_control
*asrc_private
=
374 (struct soc_mixer_control
*)kcontrol
->private_value
;
375 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
376 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
377 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
379 ucontrol
->value
.integer
.value
[0] = asrc
->lane
[id
].hwcomp_disable
;
384 static int tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol
*kcontrol
,
385 struct snd_ctl_elem_value
*ucontrol
)
387 struct soc_mixer_control
*asrc_private
=
388 (struct soc_mixer_control
*)kcontrol
->private_value
;
389 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
390 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
391 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
392 int value
= ucontrol
->value
.integer
.value
[0];
394 if (value
== asrc
->lane
[id
].hwcomp_disable
)
397 asrc
->lane
[id
].hwcomp_disable
= value
;
402 static int tegra186_asrc_get_input_threshold(struct snd_kcontrol
*kcontrol
,
403 struct snd_ctl_elem_value
*ucontrol
)
405 struct soc_mixer_control
*asrc_private
=
406 (struct soc_mixer_control
*)kcontrol
->private_value
;
407 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
408 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
409 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
411 ucontrol
->value
.integer
.value
[0] = (asrc
->lane
[id
].input_thresh
& 0x3);
416 static int tegra186_asrc_put_input_threshold(struct snd_kcontrol
*kcontrol
,
417 struct snd_ctl_elem_value
*ucontrol
)
419 struct soc_mixer_control
*asrc_private
=
420 (struct soc_mixer_control
*)kcontrol
->private_value
;
421 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
422 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
423 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
424 int value
= (asrc
->lane
[id
].input_thresh
& ~(0x3)) |
425 ucontrol
->value
.integer
.value
[0];
427 if (value
== asrc
->lane
[id
].input_thresh
)
430 asrc
->lane
[id
].input_thresh
= value
;
435 static int tegra186_asrc_get_output_threshold(struct snd_kcontrol
*kcontrol
,
436 struct snd_ctl_elem_value
*ucontrol
)
438 struct soc_mixer_control
*asrc_private
=
439 (struct soc_mixer_control
*)kcontrol
->private_value
;
440 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
441 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
442 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
444 ucontrol
->value
.integer
.value
[0] = (asrc
->lane
[id
].output_thresh
& 0x3);
449 static int tegra186_asrc_put_output_threshold(struct snd_kcontrol
*kcontrol
,
450 struct snd_ctl_elem_value
*ucontrol
)
452 struct soc_mixer_control
*asrc_private
=
453 (struct soc_mixer_control
*)kcontrol
->private_value
;
454 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
455 struct tegra186_asrc
*asrc
= snd_soc_component_get_drvdata(cmpnt
);
456 unsigned int id
= asrc_private
->reg
/ TEGRA186_ASRC_STREAM_STRIDE
;
457 int value
= (asrc
->lane
[id
].output_thresh
& ~(0x3)) |
458 ucontrol
->value
.integer
.value
[0];
460 if (value
== asrc
->lane
[id
].output_thresh
)
463 asrc
->lane
[id
].output_thresh
= value
;
468 static int tegra186_asrc_widget_event(struct snd_soc_dapm_widget
*w
,
469 struct snd_kcontrol
*kcontrol
, int event
)
471 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
472 struct tegra186_asrc
*asrc
= dev_get_drvdata(cmpnt
->dev
);
474 (w
->reg
- TEGRA186_ASRC_ENABLE
) / TEGRA186_ASRC_STREAM_STRIDE
;
476 regmap_write(asrc
->regmap
,
477 ASRC_STREAM_REG(TEGRA186_ASRC_SOFT_RESET
, id
),
483 static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops
= {
484 .hw_params
= tegra186_asrc_in_hw_params
,
487 static const struct snd_soc_dai_ops tegra186_asrc_out_dai_ops
= {
488 .hw_params
= tegra186_asrc_out_hw_params
,
493 .name = "ASRC-RX-CIF"#id, \
495 .stream_name = "RX" #id "-CIF-Playback",\
497 .channels_max = 12, \
498 .rates = SNDRV_PCM_RATE_8000_192000, \
499 .formats = SNDRV_PCM_FMTBIT_S8 | \
500 SNDRV_PCM_FMTBIT_S16_LE | \
501 SNDRV_PCM_FMTBIT_S24_LE | \
502 SNDRV_PCM_FMTBIT_S32_LE, \
505 .stream_name = "RX" #id "-CIF-Capture", \
507 .channels_max = 12, \
508 .rates = SNDRV_PCM_RATE_8000_192000, \
509 .formats = SNDRV_PCM_FMTBIT_S8 | \
510 SNDRV_PCM_FMTBIT_S16_LE | \
511 SNDRV_PCM_FMTBIT_S24_LE | \
512 SNDRV_PCM_FMTBIT_S32_LE, \
514 .ops = &tegra186_asrc_in_dai_ops, \
517 #define OUT_DAI(id) \
519 .name = "ASRC-TX-CIF"#id, \
521 .stream_name = "TX" #id "-CIF-Playback",\
523 .channels_max = 12, \
524 .rates = SNDRV_PCM_RATE_8000_192000, \
525 .formats = SNDRV_PCM_FMTBIT_S8 | \
526 SNDRV_PCM_FMTBIT_S16_LE | \
527 SNDRV_PCM_FMTBIT_S24_LE | \
528 SNDRV_PCM_FMTBIT_S32_LE, \
531 .stream_name = "TX" #id "-CIF-Capture", \
533 .channels_max = 12, \
534 .rates = SNDRV_PCM_RATE_8000_192000, \
535 .formats = SNDRV_PCM_FMTBIT_S8 | \
536 SNDRV_PCM_FMTBIT_S16_LE | \
537 SNDRV_PCM_FMTBIT_S24_LE | \
538 SNDRV_PCM_FMTBIT_S32_LE, \
540 .ops = &tegra186_asrc_out_dai_ops, \
543 static struct snd_soc_dai_driver tegra186_asrc_dais
[] = {
561 static const struct snd_soc_dapm_widget tegra186_asrc_widgets
[] = {
562 SND_SOC_DAPM_AIF_IN("RX1", NULL
, 0, SND_SOC_NOPM
, 0, 0),
563 SND_SOC_DAPM_AIF_IN("RX2", NULL
, 0, SND_SOC_NOPM
, 0, 0),
564 SND_SOC_DAPM_AIF_IN("RX3", NULL
, 0, SND_SOC_NOPM
, 0, 0),
565 SND_SOC_DAPM_AIF_IN("RX4", NULL
, 0, SND_SOC_NOPM
, 0, 0),
566 SND_SOC_DAPM_AIF_IN("RX5", NULL
, 0, SND_SOC_NOPM
, 0, 0),
567 SND_SOC_DAPM_AIF_IN("RX6", NULL
, 0, SND_SOC_NOPM
, 0, 0),
568 SND_SOC_DAPM_AIF_IN("RX7", NULL
, 0, SND_SOC_NOPM
, 0, 0),
570 SND_SOC_DAPM_AIF_OUT_E("TX1", NULL
, 0,
571 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE
, 0),
572 TEGRA186_ASRC_STREAM_EN_SHIFT
, 0,
573 tegra186_asrc_widget_event
,
574 SND_SOC_DAPM_POST_PMD
),
576 SND_SOC_DAPM_AIF_OUT_E("TX2", NULL
, 0,
577 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE
, 1),
578 TEGRA186_ASRC_STREAM_EN_SHIFT
, 0,
579 tegra186_asrc_widget_event
,
580 SND_SOC_DAPM_POST_PMD
),
582 SND_SOC_DAPM_AIF_OUT_E("TX3", NULL
, 0,
583 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE
, 2),
584 TEGRA186_ASRC_STREAM_EN_SHIFT
, 0,
585 tegra186_asrc_widget_event
,
586 SND_SOC_DAPM_POST_PMD
),
588 SND_SOC_DAPM_AIF_OUT_E("TX4", NULL
, 0,
589 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE
, 3),
590 TEGRA186_ASRC_STREAM_EN_SHIFT
, 0,
591 tegra186_asrc_widget_event
,
592 SND_SOC_DAPM_POST_PMD
),
594 SND_SOC_DAPM_AIF_OUT_E("TX5", NULL
, 0,
595 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE
, 4),
596 TEGRA186_ASRC_STREAM_EN_SHIFT
, 0,
597 tegra186_asrc_widget_event
,
598 SND_SOC_DAPM_POST_PMD
),
600 SND_SOC_DAPM_AIF_OUT_E("TX6", NULL
, 0,
601 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE
, 5),
602 TEGRA186_ASRC_STREAM_EN_SHIFT
, 0,
603 tegra186_asrc_widget_event
,
604 SND_SOC_DAPM_POST_PMD
),
606 SND_SOC_DAPM_SPK("Depacketizer", NULL
),
609 #define ASRC_STREAM_ROUTE(id, sname) \
610 { "RX" #id " XBAR-" sname, NULL, "RX" #id " XBAR-TX" }, \
611 { "RX" #id "-CIF-" sname, NULL, "RX" #id " XBAR-" sname }, \
612 { "RX" #id, NULL, "RX" #id "-CIF-" sname }, \
613 { "TX" #id, NULL, "RX" #id }, \
614 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \
615 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \
616 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname },
618 #define ASRC_ROUTE(id) \
619 ASRC_STREAM_ROUTE(id, "Playback") \
620 ASRC_STREAM_ROUTE(id, "Capture")
622 #define ASRC_RATIO_ROUTE(sname) \
623 { "RX7 XBAR-" sname, NULL, "RX7 XBAR-TX" }, \
624 { "RX7-CIF-" sname, NULL, "RX7 XBAR-" sname }, \
625 { "RX7", NULL, "RX7-CIF-" sname }, \
626 { "Depacketizer", NULL, "RX7" },
628 static const struct snd_soc_dapm_route tegra186_asrc_routes
[] = {
635 ASRC_RATIO_ROUTE("Playback")
636 ASRC_RATIO_ROUTE("Capture")
639 static const char * const tegra186_asrc_ratio_source_text
[] = {
644 #define ASRC_SOURCE_DECL(name, id) \
645 static const struct soc_enum name = \
646 SOC_ENUM_SINGLE(ASRC_STREAM_SOURCE_SELECT(id), \
647 0, 2, tegra186_asrc_ratio_source_text)
649 ASRC_SOURCE_DECL(src_select1
, 0);
650 ASRC_SOURCE_DECL(src_select2
, 1);
651 ASRC_SOURCE_DECL(src_select3
, 2);
652 ASRC_SOURCE_DECL(src_select4
, 3);
653 ASRC_SOURCE_DECL(src_select5
, 4);
654 ASRC_SOURCE_DECL(src_select6
, 5);
656 #define SOC_SINGLE_EXT_FRAC(xname, xregbase, xmax, xget, xput) \
658 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
660 .info = snd_soc_info_xr_sx, \
664 .private_value = (unsigned long)&(struct soc_mreg_control) \
666 .regbase = xregbase, \
675 static const struct snd_kcontrol_new tegra186_asrc_controls
[] = {
676 /* Controls for integer part of ratio */
677 SOC_SINGLE_EXT("Ratio1 Integer Part",
678 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, 0),
679 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK
, 0,
680 tegra186_asrc_get_ratio_int
,
681 tegra186_asrc_put_ratio_int
),
683 SOC_SINGLE_EXT("Ratio2 Integer Part",
684 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, 1),
685 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK
, 0,
686 tegra186_asrc_get_ratio_int
,
687 tegra186_asrc_put_ratio_int
),
689 SOC_SINGLE_EXT("Ratio3 Integer Part",
690 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, 2),
691 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK
, 0,
692 tegra186_asrc_get_ratio_int
,
693 tegra186_asrc_put_ratio_int
),
695 SOC_SINGLE_EXT("Ratio4 Integer Part",
696 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, 3),
697 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK
, 0,
698 tegra186_asrc_get_ratio_int
,
699 tegra186_asrc_put_ratio_int
),
701 SOC_SINGLE_EXT("Ratio5 Integer Part",
702 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, 4),
703 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK
, 0,
704 tegra186_asrc_get_ratio_int
,
705 tegra186_asrc_put_ratio_int
),
707 SOC_SINGLE_EXT("Ratio6 Integer Part",
708 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART
, 5),
709 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK
, 0,
710 tegra186_asrc_get_ratio_int
,
711 tegra186_asrc_put_ratio_int
),
713 /* Controls for fractional part of ratio */
714 SOC_SINGLE_EXT_FRAC("Ratio1 Fractional Part",
715 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, 0),
716 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK
,
717 tegra186_asrc_get_ratio_frac
,
718 tegra186_asrc_put_ratio_frac
),
720 SOC_SINGLE_EXT_FRAC("Ratio2 Fractional Part",
721 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, 1),
722 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK
,
723 tegra186_asrc_get_ratio_frac
,
724 tegra186_asrc_put_ratio_frac
),
726 SOC_SINGLE_EXT_FRAC("Ratio3 Fractional Part",
727 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, 2),
728 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK
,
729 tegra186_asrc_get_ratio_frac
,
730 tegra186_asrc_put_ratio_frac
),
732 SOC_SINGLE_EXT_FRAC("Ratio4 Fractional Part",
733 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, 3),
734 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK
,
735 tegra186_asrc_get_ratio_frac
,
736 tegra186_asrc_put_ratio_frac
),
738 SOC_SINGLE_EXT_FRAC("Ratio5 Fractional Part",
739 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, 4),
740 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK
,
741 tegra186_asrc_get_ratio_frac
,
742 tegra186_asrc_put_ratio_frac
),
744 SOC_SINGLE_EXT_FRAC("Ratio6 Fractional Part",
745 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART
, 5),
746 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK
,
747 tegra186_asrc_get_ratio_frac
,
748 tegra186_asrc_put_ratio_frac
),
750 /* Source of ratio provider */
751 SOC_ENUM_EXT("Ratio1 Source", src_select1
,
752 tegra186_asrc_get_ratio_source
,
753 tegra186_asrc_put_ratio_source
),
755 SOC_ENUM_EXT("Ratio2 Source", src_select2
,
756 tegra186_asrc_get_ratio_source
,
757 tegra186_asrc_put_ratio_source
),
759 SOC_ENUM_EXT("Ratio3 Source", src_select3
,
760 tegra186_asrc_get_ratio_source
,
761 tegra186_asrc_put_ratio_source
),
763 SOC_ENUM_EXT("Ratio4 Source", src_select4
,
764 tegra186_asrc_get_ratio_source
,
765 tegra186_asrc_put_ratio_source
),
767 SOC_ENUM_EXT("Ratio5 Source", src_select5
,
768 tegra186_asrc_get_ratio_source
,
769 tegra186_asrc_put_ratio_source
),
771 SOC_ENUM_EXT("Ratio6 Source", src_select6
,
772 tegra186_asrc_get_ratio_source
,
773 tegra186_asrc_put_ratio_source
),
775 /* Disable HW managed overflow/underflow issue at input and output */
776 SOC_SINGLE_EXT("Stream1 HW Component Disable",
777 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, 0), 0, 1, 0,
778 tegra186_asrc_get_hwcomp_disable
,
779 tegra186_asrc_put_hwcomp_disable
),
781 SOC_SINGLE_EXT("Stream2 HW Component Disable",
782 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, 1), 0, 1, 0,
783 tegra186_asrc_get_hwcomp_disable
,
784 tegra186_asrc_put_hwcomp_disable
),
786 SOC_SINGLE_EXT("Stream3 HW Component Disable",
787 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, 2), 0, 1, 0,
788 tegra186_asrc_get_hwcomp_disable
,
789 tegra186_asrc_put_hwcomp_disable
),
791 SOC_SINGLE_EXT("Stream4 HW Component Disable",
792 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, 3), 0, 1, 0,
793 tegra186_asrc_get_hwcomp_disable
,
794 tegra186_asrc_put_hwcomp_disable
),
796 SOC_SINGLE_EXT("Stream5 HW Component Disable",
797 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, 4), 0, 1, 0,
798 tegra186_asrc_get_hwcomp_disable
,
799 tegra186_asrc_put_hwcomp_disable
),
801 SOC_SINGLE_EXT("Stream6 HW Component Disable",
802 ASRC_STREAM_REG(TEGRA186_ASRC_CFG
, 5), 0, 1, 0,
803 tegra186_asrc_get_hwcomp_disable
,
804 tegra186_asrc_put_hwcomp_disable
),
806 /* Input threshold for watermark fields */
807 SOC_SINGLE_EXT("Stream1 Input Threshold",
808 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD
, 0), 0, 3, 0,
809 tegra186_asrc_get_input_threshold
,
810 tegra186_asrc_put_input_threshold
),
812 SOC_SINGLE_EXT("Stream2 Input Threshold",
813 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD
, 1), 0, 3, 0,
814 tegra186_asrc_get_input_threshold
,
815 tegra186_asrc_put_input_threshold
),
817 SOC_SINGLE_EXT("Stream3 Input Threshold",
818 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD
, 2), 0, 3, 0,
819 tegra186_asrc_get_input_threshold
,
820 tegra186_asrc_put_input_threshold
),
822 SOC_SINGLE_EXT("Stream4 Input Threshold",
823 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD
, 3), 0, 3, 0,
824 tegra186_asrc_get_input_threshold
,
825 tegra186_asrc_put_input_threshold
),
827 SOC_SINGLE_EXT("Stream5 Input Threshold",
828 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD
, 4), 0, 3, 0,
829 tegra186_asrc_get_input_threshold
,
830 tegra186_asrc_put_input_threshold
),
832 SOC_SINGLE_EXT("Stream6 Input Threshold",
833 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD
, 4), 0, 3, 0,
834 tegra186_asrc_get_input_threshold
,
835 tegra186_asrc_put_input_threshold
),
837 /* Output threshold for watermark fields */
838 SOC_SINGLE_EXT("Stream1 Output Threshold",
839 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD
, 0), 0, 3, 0,
840 tegra186_asrc_get_output_threshold
,
841 tegra186_asrc_put_output_threshold
),
843 SOC_SINGLE_EXT("Stream2 Output Threshold",
844 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD
, 1), 0, 3, 0,
845 tegra186_asrc_get_output_threshold
,
846 tegra186_asrc_put_output_threshold
),
848 SOC_SINGLE_EXT("Stream3 Output Threshold",
849 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD
, 2), 0, 3, 0,
850 tegra186_asrc_get_output_threshold
,
851 tegra186_asrc_put_output_threshold
),
853 SOC_SINGLE_EXT("Stream4 Output Threshold",
854 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD
, 3), 0, 3, 0,
855 tegra186_asrc_get_output_threshold
,
856 tegra186_asrc_put_output_threshold
),
858 SOC_SINGLE_EXT("Stream5 Output Threshold",
859 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD
, 4), 0, 3, 0,
860 tegra186_asrc_get_output_threshold
,
861 tegra186_asrc_put_output_threshold
),
863 SOC_SINGLE_EXT("Stream6 Output Threshold",
864 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD
, 5), 0, 3, 0,
865 tegra186_asrc_get_output_threshold
,
866 tegra186_asrc_put_output_threshold
),
869 static const struct snd_soc_component_driver tegra186_asrc_cmpnt
= {
870 .dapm_widgets
= tegra186_asrc_widgets
,
871 .num_dapm_widgets
= ARRAY_SIZE(tegra186_asrc_widgets
),
872 .dapm_routes
= tegra186_asrc_routes
,
873 .num_dapm_routes
= ARRAY_SIZE(tegra186_asrc_routes
),
874 .controls
= tegra186_asrc_controls
,
875 .num_controls
= ARRAY_SIZE(tegra186_asrc_controls
),
878 static bool tegra186_asrc_wr_reg(struct device
*dev
, unsigned int reg
)
880 if (reg
< TEGRA186_ASRC_STREAM_LIMIT
)
881 reg
%= TEGRA186_ASRC_STREAM_STRIDE
;
884 case TEGRA186_ASRC_CFG
... TEGRA186_ASRC_RATIO_COMP
:
885 case TEGRA186_ASRC_RX_CIF_CTRL
:
886 case TEGRA186_ASRC_TX_CIF_CTRL
:
887 case TEGRA186_ASRC_ENABLE
:
888 case TEGRA186_ASRC_SOFT_RESET
:
889 case TEGRA186_ASRC_GLOBAL_ENB
... TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL
:
890 case TEGRA186_ASRC_GLOBAL_INT_MASK
... TEGRA186_ASRC_GLOBAL_INT_CLEAR
:
891 case TEGRA186_ASRC_GLOBAL_APR_CTRL
... TEGRA186_ASRC_CYA
:
898 static bool tegra186_asrc_rd_reg(struct device
*dev
, unsigned int reg
)
900 if (reg
< TEGRA186_ASRC_STREAM_LIMIT
)
901 reg
%= TEGRA186_ASRC_STREAM_STRIDE
;
903 if (tegra186_asrc_wr_reg(dev
, reg
))
907 case TEGRA186_ASRC_RX_STATUS
:
908 case TEGRA186_ASRC_TX_STATUS
:
909 case TEGRA186_ASRC_STATUS
... TEGRA186_ASRC_OUTSAMPLEBUF_CFG
:
910 case TEGRA186_ASRC_RATIO_UPD_RX_STATUS
:
911 case TEGRA186_ASRC_GLOBAL_STATUS
... TEGRA186_ASRC_GLOBAL_INT_STATUS
:
912 case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG
:
919 static bool tegra186_asrc_volatile_reg(struct device
*dev
, unsigned int reg
)
921 if (reg
< TEGRA186_ASRC_STREAM_LIMIT
)
922 reg
%= TEGRA186_ASRC_STREAM_STRIDE
;
925 case TEGRA186_ASRC_RX_STATUS
:
926 case TEGRA186_ASRC_TX_STATUS
:
927 case TEGRA186_ASRC_SOFT_RESET
:
928 case TEGRA186_ASRC_RATIO_INT_PART
:
929 case TEGRA186_ASRC_RATIO_FRAC_PART
:
930 case TEGRA186_ASRC_STATUS
:
931 case TEGRA186_ASRC_RATIO_LOCK_STATUS
:
932 case TEGRA186_ASRC_RATIO_UPD_RX_STATUS
:
933 case TEGRA186_ASRC_GLOBAL_SOFT_RESET
:
934 case TEGRA186_ASRC_GLOBAL_STATUS
:
935 case TEGRA186_ASRC_GLOBAL_STREAM_ENABLE_STATUS
:
936 case TEGRA186_ASRC_GLOBAL_INT_STATUS
:
937 case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG
:
944 static const struct regmap_config tegra186_asrc_regmap_config
= {
948 .max_register
= TEGRA186_ASRC_CYA
,
949 .writeable_reg
= tegra186_asrc_wr_reg
,
950 .readable_reg
= tegra186_asrc_rd_reg
,
951 .volatile_reg
= tegra186_asrc_volatile_reg
,
952 .reg_defaults
= tegra186_asrc_reg_defaults
,
953 .num_reg_defaults
= ARRAY_SIZE(tegra186_asrc_reg_defaults
),
954 .cache_type
= REGCACHE_FLAT
,
957 static const struct of_device_id tegra186_asrc_of_match
[] = {
958 { .compatible
= "nvidia,tegra186-asrc" },
961 MODULE_DEVICE_TABLE(of
, tegra186_asrc_of_match
);
963 static int tegra186_asrc_platform_probe(struct platform_device
*pdev
)
965 struct device
*dev
= &pdev
->dev
;
966 struct tegra186_asrc
*asrc
;
971 asrc
= devm_kzalloc(dev
, sizeof(*asrc
), GFP_KERNEL
);
975 dev_set_drvdata(dev
, asrc
);
977 regs
= devm_platform_ioremap_resource(pdev
, 0);
979 return PTR_ERR(regs
);
981 asrc
->regmap
= devm_regmap_init_mmio(dev
, regs
,
982 &tegra186_asrc_regmap_config
);
983 if (IS_ERR(asrc
->regmap
)) {
984 dev_err(dev
, "regmap init failed\n");
985 return PTR_ERR(asrc
->regmap
);
988 regcache_cache_only(asrc
->regmap
, true);
990 regmap_write(asrc
->regmap
, TEGRA186_ASRC_GLOBAL_CFG
,
991 TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION
);
993 /* Initialize default output srate */
994 for (i
= 0; i
< TEGRA186_ASRC_STREAM_MAX
; i
++) {
995 asrc
->lane
[i
].ratio_source
= TEGRA186_ASRC_RATIO_SOURCE_SW
;
996 asrc
->lane
[i
].int_part
= 1;
997 asrc
->lane
[i
].frac_part
= 0;
998 asrc
->lane
[i
].hwcomp_disable
= 0;
999 asrc
->lane
[i
].input_thresh
=
1000 TEGRA186_ASRC_STREAM_DEFAULT_INPUT_HW_COMP_THRESH_CFG
;
1001 asrc
->lane
[i
].output_thresh
=
1002 TEGRA186_ASRC_STREAM_DEFAULT_OUTPUT_HW_COMP_THRESH_CFG
;
1005 err
= devm_snd_soc_register_component(dev
, &tegra186_asrc_cmpnt
,
1007 ARRAY_SIZE(tegra186_asrc_dais
));
1009 dev_err(dev
, "can't register ASRC component, err: %d\n", err
);
1013 pm_runtime_enable(dev
);
1018 static void tegra186_asrc_platform_remove(struct platform_device
*pdev
)
1020 pm_runtime_disable(&pdev
->dev
);
1023 static const struct dev_pm_ops tegra186_asrc_pm_ops
= {
1024 SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend
,
1025 tegra186_asrc_runtime_resume
, NULL
)
1026 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
1027 pm_runtime_force_resume
)
1030 static struct platform_driver tegra186_asrc_driver
= {
1032 .name
= "tegra186-asrc",
1033 .of_match_table
= tegra186_asrc_of_match
,
1034 .pm
= &tegra186_asrc_pm_ops
,
1036 .probe
= tegra186_asrc_platform_probe
,
1037 .remove
= tegra186_asrc_platform_remove
,
1039 module_platform_driver(tegra186_asrc_driver
)
1041 MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
1042 MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
1043 MODULE_LICENSE("GPL");