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/module.h>
13 #include <linux/of_device.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/regmap.h>
17 #include <sound/core.h>
18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
22 #include "tegra186_asrc.h"
23 #include "tegra_cif.h"
25 #define ASRC_STREAM_SOURCE_SELECT(id) \
26 (TEGRA186_ASRC_CFG + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
28 #define ASRC_STREAM_REG(reg, id) ((reg) + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
30 #define ASRC_STREAM_REG_DEFAULTS(id) \
31 { ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id), \
32 (((id) + 1) << 4) }, \
33 { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id), \
35 { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id), \
37 { ASRC_STREAM_REG(TEGRA186_ASRC_MUTE_UNMUTE_DURATION, id), \
39 { ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, id), \
41 { ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id), \
44 static const struct reg_default tegra186_asrc_reg_defaults[] = {
45 ASRC_STREAM_REG_DEFAULTS(0),
46 ASRC_STREAM_REG_DEFAULTS(1),
47 ASRC_STREAM_REG_DEFAULTS(2),
48 ASRC_STREAM_REG_DEFAULTS(3),
49 ASRC_STREAM_REG_DEFAULTS(4),
50 ASRC_STREAM_REG_DEFAULTS(5),
52 { TEGRA186_ASRC_GLOBAL_ENB, 0},
53 { TEGRA186_ASRC_GLOBAL_SOFT_RESET, 0},
54 { TEGRA186_ASRC_GLOBAL_CG, 0x1 },
55 { TEGRA186_ASRC_GLOBAL_CFG, 0x0 },
56 { TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR, 0},
57 { TEGRA186_ASRC_GLOBAL_SCRATCH_CFG, 0x0c207980 },
58 { TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL, 0x00115500 },
59 { TEGRA186_ASRC_GLOBAL_INT_MASK, 0x0},
60 { TEGRA186_ASRC_GLOBAL_INT_SET, 0x0},
61 { TEGRA186_ASRC_GLOBAL_INT_CLEAR, 0x0},
62 { TEGRA186_ASRC_GLOBAL_APR_CTRL, 0x0},
63 { TEGRA186_ASRC_GLOBAL_APR_CTRL_ACCESS_CTRL, 0x0},
64 { TEGRA186_ASRC_GLOBAL_DISARM_APR, 0x0},
65 { TEGRA186_ASRC_GLOBAL_DISARM_APR_ACCESS_CTRL, 0x0},
66 { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS, 0x0},
67 { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS_CTRL, 0x0},
68 { TEGRA186_ASRC_CYA, 0x0},
71 static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc,
74 regmap_write(asrc->regmap,
75 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_LOCK_STATUS,
80 static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev)
82 struct tegra186_asrc *asrc = dev_get_drvdata(dev);
84 regcache_cache_only(asrc->regmap, true);
85 regcache_mark_dirty(asrc->regmap);
90 static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev)
92 struct tegra186_asrc *asrc = dev_get_drvdata(dev);
95 regcache_cache_only(asrc->regmap, false);
98 * Below sequence is recommended after a runtime PM cycle.
99 * This otherwise leads to transfer failures. The cache
100 * sync is done after this to restore other settings.
102 regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR,
103 TEGRA186_ASRC_ARAM_START_ADDR);
104 regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_ENB,
105 TEGRA186_ASRC_GLOBAL_EN);
107 regcache_sync(asrc->regmap);
109 for (id = 0; id < TEGRA186_ASRC_STREAM_MAX; id++) {
110 if (asrc->lane[id].ratio_source !=
111 TEGRA186_ASRC_RATIO_SOURCE_SW)
114 regmap_write(asrc->regmap,
115 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
117 asrc->lane[id].int_part);
119 regmap_write(asrc->regmap,
120 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
122 asrc->lane[id].frac_part);
124 tegra186_asrc_lock_stream(asrc, id);
130 static int tegra186_asrc_set_audio_cif(struct tegra186_asrc *asrc,
131 struct snd_pcm_hw_params *params,
134 int channels, audio_bits;
135 struct tegra_cif_conf cif_conf;
137 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
139 channels = params_channels(params);
141 switch (params_format(params)) {
142 case SNDRV_PCM_FORMAT_S16_LE:
143 audio_bits = TEGRA_ACIF_BITS_16;
145 case SNDRV_PCM_FORMAT_S24_LE:
146 case SNDRV_PCM_FORMAT_S32_LE:
147 audio_bits = TEGRA_ACIF_BITS_32;
153 cif_conf.audio_ch = channels;
154 cif_conf.client_ch = channels;
155 cif_conf.audio_bits = audio_bits;
156 cif_conf.client_bits = TEGRA_ACIF_BITS_24;
158 tegra_set_cif(asrc->regmap, reg, &cif_conf);
163 static int tegra186_asrc_in_hw_params(struct snd_pcm_substream *substream,
164 struct snd_pcm_hw_params *params,
165 struct snd_soc_dai *dai)
167 struct device *dev = dai->dev;
168 struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
169 int ret, id = dai->id;
171 /* Set input threshold */
172 regmap_write(asrc->regmap,
173 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, dai->id),
174 asrc->lane[id].input_thresh);
176 ret = tegra186_asrc_set_audio_cif(asrc, params,
177 ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, dai->id));
179 dev_err(dev, "Can't set ASRC RX%d CIF: %d\n", dai->id, ret);
186 static int tegra186_asrc_out_hw_params(struct snd_pcm_substream *substream,
187 struct snd_pcm_hw_params *params,
188 struct snd_soc_dai *dai)
190 struct device *dev = dai->dev;
191 struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
192 int ret, id = dai->id - 7;
194 /* Set output threshold */
195 regmap_write(asrc->regmap,
196 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, id),
197 asrc->lane[id].output_thresh);
199 ret = tegra186_asrc_set_audio_cif(asrc, params,
200 ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id));
202 dev_err(dev, "Can't set ASRC TX%d CIF: %d\n", id, ret);
206 /* Set ENABLE_HW_RATIO_COMP */
207 if (asrc->lane[id].hwcomp_disable) {
208 regmap_update_bits(asrc->regmap,
209 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
210 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
211 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_DISABLE);
213 regmap_update_bits(asrc->regmap,
214 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
215 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
216 TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_ENABLE);
218 regmap_write(asrc->regmap,
219 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_COMP, id),
220 TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE);
224 regmap_update_bits(asrc->regmap,
225 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
226 1, asrc->lane[id].ratio_source);
228 if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_SW) {
229 regmap_write(asrc->regmap,
230 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
231 asrc->lane[id].int_part);
232 regmap_write(asrc->regmap,
233 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
234 asrc->lane[id].frac_part);
235 tegra186_asrc_lock_stream(asrc, id);
241 static int tegra186_asrc_get_ratio_source(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
244 struct soc_enum *asrc_private =
245 (struct soc_enum *)kcontrol->private_value;
246 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
247 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
248 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
250 ucontrol->value.enumerated.item[0] = asrc->lane[id].ratio_source;
255 static int tegra186_asrc_put_ratio_source(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_value *ucontrol)
258 struct soc_enum *asrc_private =
259 (struct soc_enum *)kcontrol->private_value;
260 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
261 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
262 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
265 asrc->lane[id].ratio_source = ucontrol->value.enumerated.item[0];
267 regmap_update_bits_check(asrc->regmap, asrc_private->reg,
268 TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK,
269 asrc->lane[id].ratio_source,
272 return change ? 1 : 0;
275 static int tegra186_asrc_get_ratio_int(struct snd_kcontrol *kcontrol,
276 struct snd_ctl_elem_value *ucontrol)
278 struct soc_mixer_control *asrc_private =
279 (struct soc_mixer_control *)kcontrol->private_value;
280 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
281 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
282 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
284 regmap_read(asrc->regmap,
285 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
286 &asrc->lane[id].int_part);
288 ucontrol->value.integer.value[0] = asrc->lane[id].int_part;
293 static int tegra186_asrc_put_ratio_int(struct snd_kcontrol *kcontrol,
294 struct snd_ctl_elem_value *ucontrol)
296 struct soc_mixer_control *asrc_private =
297 (struct soc_mixer_control *)kcontrol->private_value;
298 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
299 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
300 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
303 if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
305 "Lane %d ratio source is ARAD, invalid SW update\n",
310 asrc->lane[id].int_part = ucontrol->value.integer.value[0];
312 regmap_update_bits_check(asrc->regmap,
313 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
315 TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK,
316 asrc->lane[id].int_part, &change);
318 tegra186_asrc_lock_stream(asrc, id);
320 return change ? 1 : 0;
323 static int tegra186_asrc_get_ratio_frac(struct snd_kcontrol *kcontrol,
324 struct snd_ctl_elem_value *ucontrol)
326 struct soc_mreg_control *asrc_private =
327 (struct soc_mreg_control *)kcontrol->private_value;
328 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
329 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
330 unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
332 regmap_read(asrc->regmap,
333 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
334 &asrc->lane[id].frac_part);
336 ucontrol->value.integer.value[0] = asrc->lane[id].frac_part;
341 static int tegra186_asrc_put_ratio_frac(struct snd_kcontrol *kcontrol,
342 struct snd_ctl_elem_value *ucontrol)
344 struct soc_mreg_control *asrc_private =
345 (struct soc_mreg_control *)kcontrol->private_value;
346 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
347 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
348 unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
351 if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
353 "Lane %d ratio source is ARAD, invalid SW update\n",
358 asrc->lane[id].frac_part = ucontrol->value.integer.value[0];
360 regmap_update_bits_check(asrc->regmap,
361 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
363 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
364 asrc->lane[id].frac_part, &change);
366 tegra186_asrc_lock_stream(asrc, id);
368 return change ? 1 : 0;
371 static int tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol *kcontrol,
372 struct snd_ctl_elem_value *ucontrol)
374 struct soc_mixer_control *asrc_private =
375 (struct soc_mixer_control *)kcontrol->private_value;
376 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
377 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
378 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
380 ucontrol->value.integer.value[0] = asrc->lane[id].hwcomp_disable;
385 static int tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol *kcontrol,
386 struct snd_ctl_elem_value *ucontrol)
388 struct soc_mixer_control *asrc_private =
389 (struct soc_mixer_control *)kcontrol->private_value;
390 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
391 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
392 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
393 int value = ucontrol->value.integer.value[0];
395 if (value == asrc->lane[id].hwcomp_disable)
398 asrc->lane[id].hwcomp_disable = value;
403 static int tegra186_asrc_get_input_threshold(struct snd_kcontrol *kcontrol,
404 struct snd_ctl_elem_value *ucontrol)
406 struct soc_mixer_control *asrc_private =
407 (struct soc_mixer_control *)kcontrol->private_value;
408 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
409 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
410 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
412 ucontrol->value.integer.value[0] = (asrc->lane[id].input_thresh & 0x3);
417 static int tegra186_asrc_put_input_threshold(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
420 struct soc_mixer_control *asrc_private =
421 (struct soc_mixer_control *)kcontrol->private_value;
422 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
423 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
424 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
425 int value = (asrc->lane[id].input_thresh & ~(0x3)) |
426 ucontrol->value.integer.value[0];
428 if (value == asrc->lane[id].input_thresh)
431 asrc->lane[id].input_thresh = value;
436 static int tegra186_asrc_get_output_threshold(struct snd_kcontrol *kcontrol,
437 struct snd_ctl_elem_value *ucontrol)
439 struct soc_mixer_control *asrc_private =
440 (struct soc_mixer_control *)kcontrol->private_value;
441 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
442 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
443 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
445 ucontrol->value.integer.value[0] = (asrc->lane[id].output_thresh & 0x3);
450 static int tegra186_asrc_put_output_threshold(struct snd_kcontrol *kcontrol,
451 struct snd_ctl_elem_value *ucontrol)
453 struct soc_mixer_control *asrc_private =
454 (struct soc_mixer_control *)kcontrol->private_value;
455 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
456 struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
457 unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
458 int value = (asrc->lane[id].output_thresh & ~(0x3)) |
459 ucontrol->value.integer.value[0];
461 if (value == asrc->lane[id].output_thresh)
464 asrc->lane[id].output_thresh = value;
469 static int tegra186_asrc_widget_event(struct snd_soc_dapm_widget *w,
470 struct snd_kcontrol *kcontrol, int event)
472 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
473 struct tegra186_asrc *asrc = dev_get_drvdata(cmpnt->dev);
475 (w->reg - TEGRA186_ASRC_ENABLE) / TEGRA186_ASRC_STREAM_STRIDE;
477 regmap_write(asrc->regmap,
478 ASRC_STREAM_REG(TEGRA186_ASRC_SOFT_RESET, id),
484 static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops = {
485 .hw_params = tegra186_asrc_in_hw_params,
488 static const struct snd_soc_dai_ops tegra186_asrc_out_dai_ops = {
489 .hw_params = tegra186_asrc_out_hw_params,
494 .name = "ASRC-RX-CIF"#id, \
496 .stream_name = "RX" #id "-CIF-Playback",\
498 .channels_max = 12, \
499 .rates = SNDRV_PCM_RATE_8000_192000, \
500 .formats = SNDRV_PCM_FMTBIT_S8 | \
501 SNDRV_PCM_FMTBIT_S16_LE | \
502 SNDRV_PCM_FMTBIT_S24_LE | \
503 SNDRV_PCM_FMTBIT_S32_LE, \
506 .stream_name = "RX" #id "-CIF-Capture", \
508 .channels_max = 12, \
509 .rates = SNDRV_PCM_RATE_8000_192000, \
510 .formats = SNDRV_PCM_FMTBIT_S8 | \
511 SNDRV_PCM_FMTBIT_S16_LE | \
512 SNDRV_PCM_FMTBIT_S24_LE | \
513 SNDRV_PCM_FMTBIT_S32_LE, \
515 .ops = &tegra186_asrc_in_dai_ops, \
518 #define OUT_DAI(id) \
520 .name = "ASRC-TX-CIF"#id, \
522 .stream_name = "TX" #id "-CIF-Playback",\
524 .channels_max = 12, \
525 .rates = SNDRV_PCM_RATE_8000_192000, \
526 .formats = SNDRV_PCM_FMTBIT_S8 | \
527 SNDRV_PCM_FMTBIT_S16_LE | \
528 SNDRV_PCM_FMTBIT_S24_LE | \
529 SNDRV_PCM_FMTBIT_S32_LE, \
532 .stream_name = "TX" #id "-CIF-Capture", \
534 .channels_max = 12, \
535 .rates = SNDRV_PCM_RATE_8000_192000, \
536 .formats = SNDRV_PCM_FMTBIT_S8 | \
537 SNDRV_PCM_FMTBIT_S16_LE | \
538 SNDRV_PCM_FMTBIT_S24_LE | \
539 SNDRV_PCM_FMTBIT_S32_LE, \
541 .ops = &tegra186_asrc_out_dai_ops, \
544 static struct snd_soc_dai_driver tegra186_asrc_dais[] = {
562 static const struct snd_soc_dapm_widget tegra186_asrc_widgets[] = {
563 SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
564 SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
565 SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
566 SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, SND_SOC_NOPM, 0, 0),
567 SND_SOC_DAPM_AIF_IN("RX5", NULL, 0, SND_SOC_NOPM, 0, 0),
568 SND_SOC_DAPM_AIF_IN("RX6", NULL, 0, SND_SOC_NOPM, 0, 0),
569 SND_SOC_DAPM_AIF_IN("RX7", NULL, 0, SND_SOC_NOPM, 0, 0),
571 SND_SOC_DAPM_AIF_OUT_E("TX1", NULL, 0,
572 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 0),
573 TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
574 tegra186_asrc_widget_event,
575 SND_SOC_DAPM_POST_PMD),
577 SND_SOC_DAPM_AIF_OUT_E("TX2", NULL, 0,
578 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 1),
579 TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
580 tegra186_asrc_widget_event,
581 SND_SOC_DAPM_POST_PMD),
583 SND_SOC_DAPM_AIF_OUT_E("TX3", NULL, 0,
584 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 2),
585 TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
586 tegra186_asrc_widget_event,
587 SND_SOC_DAPM_POST_PMD),
589 SND_SOC_DAPM_AIF_OUT_E("TX4", NULL, 0,
590 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 3),
591 TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
592 tegra186_asrc_widget_event,
593 SND_SOC_DAPM_POST_PMD),
595 SND_SOC_DAPM_AIF_OUT_E("TX5", NULL, 0,
596 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 4),
597 TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
598 tegra186_asrc_widget_event,
599 SND_SOC_DAPM_POST_PMD),
601 SND_SOC_DAPM_AIF_OUT_E("TX6", NULL, 0,
602 ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 5),
603 TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
604 tegra186_asrc_widget_event,
605 SND_SOC_DAPM_POST_PMD),
607 SND_SOC_DAPM_SPK("Depacketizer", NULL),
610 #define ASRC_STREAM_ROUTE(id, sname) \
611 { "RX" #id " XBAR-" sname, NULL, "RX" #id " XBAR-TX" }, \
612 { "RX" #id "-CIF-" sname, NULL, "RX" #id " XBAR-" sname }, \
613 { "RX" #id, NULL, "RX" #id "-CIF-" sname }, \
614 { "TX" #id, NULL, "RX" #id }, \
615 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \
616 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \
617 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname },
619 #define ASRC_ROUTE(id) \
620 ASRC_STREAM_ROUTE(id, "Playback") \
621 ASRC_STREAM_ROUTE(id, "Capture")
623 #define ASRC_RATIO_ROUTE(sname) \
624 { "RX7 XBAR-" sname, NULL, "RX7 XBAR-TX" }, \
625 { "RX7-CIF-" sname, NULL, "RX7 XBAR-" sname }, \
626 { "RX7", NULL, "RX7-CIF-" sname }, \
627 { "Depacketizer", NULL, "RX7" },
629 static const struct snd_soc_dapm_route tegra186_asrc_routes[] = {
636 ASRC_RATIO_ROUTE("Playback")
637 ASRC_RATIO_ROUTE("Capture")
640 static const char * const tegra186_asrc_ratio_source_text[] = {
645 #define ASRC_SOURCE_DECL(name, id) \
646 static const struct soc_enum name = \
647 SOC_ENUM_SINGLE(ASRC_STREAM_SOURCE_SELECT(id), \
648 0, 2, tegra186_asrc_ratio_source_text)
650 ASRC_SOURCE_DECL(src_select1, 0);
651 ASRC_SOURCE_DECL(src_select2, 1);
652 ASRC_SOURCE_DECL(src_select3, 2);
653 ASRC_SOURCE_DECL(src_select4, 3);
654 ASRC_SOURCE_DECL(src_select5, 4);
655 ASRC_SOURCE_DECL(src_select6, 5);
657 #define SOC_SINGLE_EXT_FRAC(xname, xregbase, xmax, xget, xput) \
659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
661 .info = snd_soc_info_xr_sx, \
665 .private_value = (unsigned long)&(struct soc_mreg_control) \
667 .regbase = xregbase, \
676 static const struct snd_kcontrol_new tegra186_asrc_controls[] = {
677 /* Controls for integer part of ratio */
678 SOC_SINGLE_EXT("Ratio1 Integer Part",
679 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 0),
680 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
681 tegra186_asrc_get_ratio_int,
682 tegra186_asrc_put_ratio_int),
684 SOC_SINGLE_EXT("Ratio2 Integer Part",
685 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 1),
686 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
687 tegra186_asrc_get_ratio_int,
688 tegra186_asrc_put_ratio_int),
690 SOC_SINGLE_EXT("Ratio3 Integer Part",
691 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 2),
692 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
693 tegra186_asrc_get_ratio_int,
694 tegra186_asrc_put_ratio_int),
696 SOC_SINGLE_EXT("Ratio4 Integer Part",
697 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 3),
698 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
699 tegra186_asrc_get_ratio_int,
700 tegra186_asrc_put_ratio_int),
702 SOC_SINGLE_EXT("Ratio5 Integer Part",
703 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 4),
704 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
705 tegra186_asrc_get_ratio_int,
706 tegra186_asrc_put_ratio_int),
708 SOC_SINGLE_EXT("Ratio6 Integer Part",
709 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 5),
710 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
711 tegra186_asrc_get_ratio_int,
712 tegra186_asrc_put_ratio_int),
714 /* Controls for fractional part of ratio */
715 SOC_SINGLE_EXT_FRAC("Ratio1 Fractional Part",
716 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 0),
717 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
718 tegra186_asrc_get_ratio_frac,
719 tegra186_asrc_put_ratio_frac),
721 SOC_SINGLE_EXT_FRAC("Ratio2 Fractional Part",
722 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 1),
723 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
724 tegra186_asrc_get_ratio_frac,
725 tegra186_asrc_put_ratio_frac),
727 SOC_SINGLE_EXT_FRAC("Ratio3 Fractional Part",
728 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 2),
729 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
730 tegra186_asrc_get_ratio_frac,
731 tegra186_asrc_put_ratio_frac),
733 SOC_SINGLE_EXT_FRAC("Ratio4 Fractional Part",
734 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 3),
735 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
736 tegra186_asrc_get_ratio_frac,
737 tegra186_asrc_put_ratio_frac),
739 SOC_SINGLE_EXT_FRAC("Ratio5 Fractional Part",
740 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 4),
741 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
742 tegra186_asrc_get_ratio_frac,
743 tegra186_asrc_put_ratio_frac),
745 SOC_SINGLE_EXT_FRAC("Ratio6 Fractional Part",
746 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 5),
747 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
748 tegra186_asrc_get_ratio_frac,
749 tegra186_asrc_put_ratio_frac),
751 /* Source of ratio provider */
752 SOC_ENUM_EXT("Ratio1 Source", src_select1,
753 tegra186_asrc_get_ratio_source,
754 tegra186_asrc_put_ratio_source),
756 SOC_ENUM_EXT("Ratio2 Source", src_select2,
757 tegra186_asrc_get_ratio_source,
758 tegra186_asrc_put_ratio_source),
760 SOC_ENUM_EXT("Ratio3 Source", src_select3,
761 tegra186_asrc_get_ratio_source,
762 tegra186_asrc_put_ratio_source),
764 SOC_ENUM_EXT("Ratio4 Source", src_select4,
765 tegra186_asrc_get_ratio_source,
766 tegra186_asrc_put_ratio_source),
768 SOC_ENUM_EXT("Ratio5 Source", src_select5,
769 tegra186_asrc_get_ratio_source,
770 tegra186_asrc_put_ratio_source),
772 SOC_ENUM_EXT("Ratio6 Source", src_select6,
773 tegra186_asrc_get_ratio_source,
774 tegra186_asrc_put_ratio_source),
776 /* Disable HW managed overflow/underflow issue at input and output */
777 SOC_SINGLE_EXT("Stream1 HW Component Disable",
778 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 0), 0, 1, 0,
779 tegra186_asrc_get_hwcomp_disable,
780 tegra186_asrc_put_hwcomp_disable),
782 SOC_SINGLE_EXT("Stream2 HW Component Disable",
783 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 1), 0, 1, 0,
784 tegra186_asrc_get_hwcomp_disable,
785 tegra186_asrc_put_hwcomp_disable),
787 SOC_SINGLE_EXT("Stream3 HW Component Disable",
788 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 2), 0, 1, 0,
789 tegra186_asrc_get_hwcomp_disable,
790 tegra186_asrc_put_hwcomp_disable),
792 SOC_SINGLE_EXT("Stream4 HW Component Disable",
793 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 3), 0, 1, 0,
794 tegra186_asrc_get_hwcomp_disable,
795 tegra186_asrc_put_hwcomp_disable),
797 SOC_SINGLE_EXT("Stream5 HW Component Disable",
798 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 4), 0, 1, 0,
799 tegra186_asrc_get_hwcomp_disable,
800 tegra186_asrc_put_hwcomp_disable),
802 SOC_SINGLE_EXT("Stream6 HW Component Disable",
803 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 5), 0, 1, 0,
804 tegra186_asrc_get_hwcomp_disable,
805 tegra186_asrc_put_hwcomp_disable),
807 /* Input threshold for watermark fields */
808 SOC_SINGLE_EXT("Stream1 Input Threshold",
809 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 0), 0, 3, 0,
810 tegra186_asrc_get_input_threshold,
811 tegra186_asrc_put_input_threshold),
813 SOC_SINGLE_EXT("Stream2 Input Threshold",
814 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 1), 0, 3, 0,
815 tegra186_asrc_get_input_threshold,
816 tegra186_asrc_put_input_threshold),
818 SOC_SINGLE_EXT("Stream3 Input Threshold",
819 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 2), 0, 3, 0,
820 tegra186_asrc_get_input_threshold,
821 tegra186_asrc_put_input_threshold),
823 SOC_SINGLE_EXT("Stream4 Input Threshold",
824 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 3), 0, 3, 0,
825 tegra186_asrc_get_input_threshold,
826 tegra186_asrc_put_input_threshold),
828 SOC_SINGLE_EXT("Stream5 Input Threshold",
829 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
830 tegra186_asrc_get_input_threshold,
831 tegra186_asrc_put_input_threshold),
833 SOC_SINGLE_EXT("Stream6 Input Threshold",
834 ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
835 tegra186_asrc_get_input_threshold,
836 tegra186_asrc_put_input_threshold),
838 /* Output threshold for watermark fields */
839 SOC_SINGLE_EXT("Stream1 Output Threshold",
840 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 0), 0, 3, 0,
841 tegra186_asrc_get_output_threshold,
842 tegra186_asrc_put_output_threshold),
844 SOC_SINGLE_EXT("Stream2 Output Threshold",
845 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 1), 0, 3, 0,
846 tegra186_asrc_get_output_threshold,
847 tegra186_asrc_put_output_threshold),
849 SOC_SINGLE_EXT("Stream3 Output Threshold",
850 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 2), 0, 3, 0,
851 tegra186_asrc_get_output_threshold,
852 tegra186_asrc_put_output_threshold),
854 SOC_SINGLE_EXT("Stream4 Output Threshold",
855 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 3), 0, 3, 0,
856 tegra186_asrc_get_output_threshold,
857 tegra186_asrc_put_output_threshold),
859 SOC_SINGLE_EXT("Stream5 Output Threshold",
860 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 4), 0, 3, 0,
861 tegra186_asrc_get_output_threshold,
862 tegra186_asrc_put_output_threshold),
864 SOC_SINGLE_EXT("Stream6 Output Threshold",
865 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 5), 0, 3, 0,
866 tegra186_asrc_get_output_threshold,
867 tegra186_asrc_put_output_threshold),
870 static const struct snd_soc_component_driver tegra186_asrc_cmpnt = {
871 .dapm_widgets = tegra186_asrc_widgets,
872 .num_dapm_widgets = ARRAY_SIZE(tegra186_asrc_widgets),
873 .dapm_routes = tegra186_asrc_routes,
874 .num_dapm_routes = ARRAY_SIZE(tegra186_asrc_routes),
875 .controls = tegra186_asrc_controls,
876 .num_controls = ARRAY_SIZE(tegra186_asrc_controls),
879 static bool tegra186_asrc_wr_reg(struct device *dev, unsigned int reg)
881 if (reg < TEGRA186_ASRC_STREAM_LIMIT)
882 reg %= TEGRA186_ASRC_STREAM_STRIDE;
885 case TEGRA186_ASRC_CFG ... TEGRA186_ASRC_RATIO_COMP:
886 case TEGRA186_ASRC_RX_CIF_CTRL:
887 case TEGRA186_ASRC_TX_CIF_CTRL:
888 case TEGRA186_ASRC_ENABLE:
889 case TEGRA186_ASRC_SOFT_RESET:
890 case TEGRA186_ASRC_GLOBAL_ENB ... TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL:
891 case TEGRA186_ASRC_GLOBAL_INT_MASK ... TEGRA186_ASRC_GLOBAL_INT_CLEAR:
892 case TEGRA186_ASRC_GLOBAL_APR_CTRL ... TEGRA186_ASRC_CYA:
899 static bool tegra186_asrc_rd_reg(struct device *dev, unsigned int reg)
901 if (reg < TEGRA186_ASRC_STREAM_LIMIT)
902 reg %= TEGRA186_ASRC_STREAM_STRIDE;
904 if (tegra186_asrc_wr_reg(dev, reg))
908 case TEGRA186_ASRC_RX_STATUS:
909 case TEGRA186_ASRC_TX_STATUS:
910 case TEGRA186_ASRC_STATUS ... TEGRA186_ASRC_OUTSAMPLEBUF_CFG:
911 case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
912 case TEGRA186_ASRC_GLOBAL_STATUS ... TEGRA186_ASRC_GLOBAL_INT_STATUS:
913 case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
920 static bool tegra186_asrc_volatile_reg(struct device *dev, unsigned int reg)
922 if (reg < TEGRA186_ASRC_STREAM_LIMIT)
923 reg %= TEGRA186_ASRC_STREAM_STRIDE;
926 case TEGRA186_ASRC_RX_STATUS:
927 case TEGRA186_ASRC_TX_STATUS:
928 case TEGRA186_ASRC_SOFT_RESET:
929 case TEGRA186_ASRC_RATIO_INT_PART:
930 case TEGRA186_ASRC_RATIO_FRAC_PART:
931 case TEGRA186_ASRC_STATUS:
932 case TEGRA186_ASRC_RATIO_LOCK_STATUS:
933 case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
934 case TEGRA186_ASRC_GLOBAL_SOFT_RESET:
935 case TEGRA186_ASRC_GLOBAL_STATUS:
936 case TEGRA186_ASRC_GLOBAL_STREAM_ENABLE_STATUS:
937 case TEGRA186_ASRC_GLOBAL_INT_STATUS:
938 case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
945 static const struct regmap_config tegra186_asrc_regmap_config = {
949 .max_register = TEGRA186_ASRC_CYA,
950 .writeable_reg = tegra186_asrc_wr_reg,
951 .readable_reg = tegra186_asrc_rd_reg,
952 .volatile_reg = tegra186_asrc_volatile_reg,
953 .reg_defaults = tegra186_asrc_reg_defaults,
954 .num_reg_defaults = ARRAY_SIZE(tegra186_asrc_reg_defaults),
955 .cache_type = REGCACHE_FLAT,
958 static const struct of_device_id tegra186_asrc_of_match[] = {
959 { .compatible = "nvidia,tegra186-asrc" },
962 MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
964 static int tegra186_asrc_platform_probe(struct platform_device *pdev)
966 struct device *dev = &pdev->dev;
967 struct tegra186_asrc *asrc;
972 asrc = devm_kzalloc(dev, sizeof(*asrc), GFP_KERNEL);
976 dev_set_drvdata(dev, asrc);
978 regs = devm_platform_ioremap_resource(pdev, 0);
980 return PTR_ERR(regs);
982 asrc->regmap = devm_regmap_init_mmio(dev, regs,
983 &tegra186_asrc_regmap_config);
984 if (IS_ERR(asrc->regmap)) {
985 dev_err(dev, "regmap init failed\n");
986 return PTR_ERR(asrc->regmap);
989 regcache_cache_only(asrc->regmap, true);
991 regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_CFG,
992 TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION);
994 /* Initialize default output srate */
995 for (i = 0; i < TEGRA186_ASRC_STREAM_MAX; i++) {
996 asrc->lane[i].ratio_source = TEGRA186_ASRC_RATIO_SOURCE_SW;
997 asrc->lane[i].int_part = 1;
998 asrc->lane[i].frac_part = 0;
999 asrc->lane[i].hwcomp_disable = 0;
1000 asrc->lane[i].input_thresh =
1001 TEGRA186_ASRC_STREAM_DEFAULT_INPUT_HW_COMP_THRESH_CFG;
1002 asrc->lane[i].output_thresh =
1003 TEGRA186_ASRC_STREAM_DEFAULT_OUTPUT_HW_COMP_THRESH_CFG;
1006 err = devm_snd_soc_register_component(dev, &tegra186_asrc_cmpnt,
1008 ARRAY_SIZE(tegra186_asrc_dais));
1010 dev_err(dev, "can't register ASRC component, err: %d\n", err);
1014 pm_runtime_enable(dev);
1019 static int tegra186_asrc_platform_remove(struct platform_device *pdev)
1021 pm_runtime_disable(&pdev->dev);
1026 static const struct dev_pm_ops tegra186_asrc_pm_ops = {
1027 SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
1028 tegra186_asrc_runtime_resume, NULL)
1029 SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1030 pm_runtime_force_resume)
1033 static struct platform_driver tegra186_asrc_driver = {
1035 .name = "tegra186-asrc",
1036 .of_match_table = tegra186_asrc_of_match,
1037 .pm = &tegra186_asrc_pm_ops,
1039 .probe = tegra186_asrc_platform_probe,
1040 .remove = tegra186_asrc_platform_remove,
1042 module_platform_driver(tegra186_asrc_driver)
1044 MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
1045 MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
1046 MODULE_LICENSE("GPL");