1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // tegra186_asrc.c - Tegra186 ASRC driver
4 //
5 // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
6
7 #include <linux/clk.h>
8 #include <linux/delay.h>
9 #include <linux/device.h>
10 #include <linux/io.h>
11 #include <linux/module.h>
12 #include <linux/of.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>
21
22 #include "tegra186_asrc.h"
23 #include "tegra_cif.h"
24
25 #define ASRC_STREAM_SOURCE_SELECT(id) \
26 (TEGRA186_ASRC_CFG + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
27
28 #define ASRC_STREAM_REG(reg, id) ((reg) + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
29
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), \
34 0x1 }, \
35 { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id), \
36 0x0 }, \
37 { ASRC_STREAM_REG(TEGRA186_ASRC_MUTE_UNMUTE_DURATION, id), \
38 0x400 }, \
39 { ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, id), \
40 0x7500 }, \
41 { ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id), \
42 0x7500 }
43
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),
51
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},
69 };
70
tegra186_asrc_lock_stream(struct tegra186_asrc * asrc,unsigned int id)71 static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc,
72 unsigned int id)
73 {
74 regmap_write(asrc->regmap,
75 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_LOCK_STATUS,
76 id),
77 1);
78 }
79
tegra186_asrc_runtime_suspend(struct device * dev)80 static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev)
81 {
82 struct tegra186_asrc *asrc = dev_get_drvdata(dev);
83
84 regcache_cache_only(asrc->regmap, true);
85 regcache_mark_dirty(asrc->regmap);
86
87 return 0;
88 }
89
tegra186_asrc_runtime_resume(struct device * dev)90 static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev)
91 {
92 struct tegra186_asrc *asrc = dev_get_drvdata(dev);
93 int id;
94
95 regcache_cache_only(asrc->regmap, false);
96
97 /*
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.
101 */
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);
106
107 regcache_sync(asrc->regmap);
108
109 for (id = 0; id < TEGRA186_ASRC_STREAM_MAX; id++) {
110 if (asrc->lane[id].ratio_source !=
111 TEGRA186_ASRC_RATIO_SOURCE_SW)
112 continue;
113
114 regmap_write(asrc->regmap,
115 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
116 id),
117 asrc->lane[id].int_part);
118
119 regmap_write(asrc->regmap,
120 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
121 id),
122 asrc->lane[id].frac_part);
123
124 tegra186_asrc_lock_stream(asrc, id);
125 }
126
127 return 0;
128 }
129
tegra186_asrc_set_audio_cif(struct tegra186_asrc * asrc,struct snd_pcm_hw_params * params,unsigned int reg)130 static int tegra186_asrc_set_audio_cif(struct tegra186_asrc *asrc,
131 struct snd_pcm_hw_params *params,
132 unsigned int reg)
133 {
134 int channels, audio_bits;
135 struct tegra_cif_conf cif_conf;
136
137 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
138
139 channels = params_channels(params);
140
141 switch (params_format(params)) {
142 case SNDRV_PCM_FORMAT_S16_LE:
143 audio_bits = TEGRA_ACIF_BITS_16;
144 break;
145 case SNDRV_PCM_FORMAT_S24_LE:
146 case SNDRV_PCM_FORMAT_S32_LE:
147 audio_bits = TEGRA_ACIF_BITS_32;
148 break;
149 default:
150 return -EINVAL;
151 }
152
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;
157
158 tegra_set_cif(asrc->regmap, reg, &cif_conf);
159
160 return 0;
161 }
162
tegra186_asrc_in_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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)
166 {
167 struct device *dev = dai->dev;
168 struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
169 int ret, id = dai->id;
170
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);
175
176 ret = tegra186_asrc_set_audio_cif(asrc, params,
177 ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, dai->id));
178 if (ret) {
179 dev_err(dev, "Can't set ASRC RX%d CIF: %d\n", dai->id, ret);
180 return ret;
181 }
182
183 return ret;
184 }
185
tegra186_asrc_out_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)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)
189 {
190 struct device *dev = dai->dev;
191 struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
192 int ret, id = dai->id - 7;
193
194 /* Set output threshold */
195 regmap_write(asrc->regmap,
196 ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, id),
197 asrc->lane[id].output_thresh);
198
199 ret = tegra186_asrc_set_audio_cif(asrc, params,
200 ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id));
201 if (ret) {
202 dev_err(dev, "Can't set ASRC TX%d CIF: %d\n", id, ret);
203 return ret;
204 }
205
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);
212 } else {
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);
217
218 regmap_write(asrc->regmap,
219 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_COMP, id),
220 TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE);
221 }
222
223 /* Set lock */
224 regmap_update_bits(asrc->regmap,
225 ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
226 1, asrc->lane[id].ratio_source);
227
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);
236 }
237
238 return ret;
239 }
240
tegra186_asrc_get_ratio_source(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)241 static int tegra186_asrc_get_ratio_source(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
243 {
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;
249
250 ucontrol->value.enumerated.item[0] = asrc->lane[id].ratio_source;
251
252 return 0;
253 }
254
tegra186_asrc_put_ratio_source(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)255 static int tegra186_asrc_put_ratio_source(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_value *ucontrol)
257 {
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;
263 bool change = false;
264
265 asrc->lane[id].ratio_source = ucontrol->value.enumerated.item[0];
266
267 regmap_update_bits_check(asrc->regmap, asrc_private->reg,
268 TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK,
269 asrc->lane[id].ratio_source,
270 &change);
271
272 return change ? 1 : 0;
273 }
274
tegra186_asrc_get_ratio_int(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)275 static int tegra186_asrc_get_ratio_int(struct snd_kcontrol *kcontrol,
276 struct snd_ctl_elem_value *ucontrol)
277 {
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;
283
284 regmap_read(asrc->regmap,
285 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
286 &asrc->lane[id].int_part);
287
288 ucontrol->value.integer.value[0] = asrc->lane[id].int_part;
289
290 return 0;
291 }
292
tegra186_asrc_put_ratio_int(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)293 static int tegra186_asrc_put_ratio_int(struct snd_kcontrol *kcontrol,
294 struct snd_ctl_elem_value *ucontrol)
295 {
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;
301 bool change = false;
302
303 if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
304 dev_err(cmpnt->dev,
305 "Lane %d ratio source is ARAD, invalid SW update\n",
306 id);
307 return -EINVAL;
308 }
309
310 asrc->lane[id].int_part = ucontrol->value.integer.value[0];
311
312 regmap_update_bits_check(asrc->regmap,
313 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
314 id),
315 TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK,
316 asrc->lane[id].int_part, &change);
317
318 tegra186_asrc_lock_stream(asrc, id);
319
320 return change ? 1 : 0;
321 }
322
tegra186_asrc_get_ratio_frac(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)323 static int tegra186_asrc_get_ratio_frac(struct snd_kcontrol *kcontrol,
324 struct snd_ctl_elem_value *ucontrol)
325 {
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;
331
332 regmap_read(asrc->regmap,
333 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
334 &asrc->lane[id].frac_part);
335
336 ucontrol->value.integer.value[0] = asrc->lane[id].frac_part;
337
338 return 0;
339 }
340
tegra186_asrc_put_ratio_frac(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)341 static int tegra186_asrc_put_ratio_frac(struct snd_kcontrol *kcontrol,
342 struct snd_ctl_elem_value *ucontrol)
343 {
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;
349 bool change = false;
350
351 if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
352 dev_err(cmpnt->dev,
353 "Lane %d ratio source is ARAD, invalid SW update\n",
354 id);
355 return -EINVAL;
356 }
357
358 asrc->lane[id].frac_part = ucontrol->value.integer.value[0];
359
360 regmap_update_bits_check(asrc->regmap,
361 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
362 id),
363 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
364 asrc->lane[id].frac_part, &change);
365
366 tegra186_asrc_lock_stream(asrc, id);
367
368 return change ? 1 : 0;
369 }
370
tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)371 static int tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol *kcontrol,
372 struct snd_ctl_elem_value *ucontrol)
373 {
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;
379
380 ucontrol->value.integer.value[0] = asrc->lane[id].hwcomp_disable;
381
382 return 0;
383 }
384
tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)385 static int tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol *kcontrol,
386 struct snd_ctl_elem_value *ucontrol)
387 {
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];
394
395 if (value == asrc->lane[id].hwcomp_disable)
396 return 0;
397
398 asrc->lane[id].hwcomp_disable = value;
399
400 return 1;
401 }
402
tegra186_asrc_get_input_threshold(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)403 static int tegra186_asrc_get_input_threshold(struct snd_kcontrol *kcontrol,
404 struct snd_ctl_elem_value *ucontrol)
405 {
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;
411
412 ucontrol->value.integer.value[0] = (asrc->lane[id].input_thresh & 0x3);
413
414 return 0;
415 }
416
tegra186_asrc_put_input_threshold(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)417 static int tegra186_asrc_put_input_threshold(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
419 {
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];
427
428 if (value == asrc->lane[id].input_thresh)
429 return 0;
430
431 asrc->lane[id].input_thresh = value;
432
433 return 1;
434 }
435
tegra186_asrc_get_output_threshold(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)436 static int tegra186_asrc_get_output_threshold(struct snd_kcontrol *kcontrol,
437 struct snd_ctl_elem_value *ucontrol)
438 {
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;
444
445 ucontrol->value.integer.value[0] = (asrc->lane[id].output_thresh & 0x3);
446
447 return 0;
448 }
449
tegra186_asrc_put_output_threshold(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)450 static int tegra186_asrc_put_output_threshold(struct snd_kcontrol *kcontrol,
451 struct snd_ctl_elem_value *ucontrol)
452 {
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];
460
461 if (value == asrc->lane[id].output_thresh)
462 return 0;
463
464 asrc->lane[id].output_thresh = value;
465
466 return 1;
467 }
468
tegra186_asrc_widget_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)469 static int tegra186_asrc_widget_event(struct snd_soc_dapm_widget *w,
470 struct snd_kcontrol *kcontrol, int event)
471 {
472 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
473 struct tegra186_asrc *asrc = dev_get_drvdata(cmpnt->dev);
474 unsigned int id =
475 (w->reg - TEGRA186_ASRC_ENABLE) / TEGRA186_ASRC_STREAM_STRIDE;
476
477 regmap_write(asrc->regmap,
478 ASRC_STREAM_REG(TEGRA186_ASRC_SOFT_RESET, id),
479 0x1);
480
481 return 0;
482 }
483
484 static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops = {
485 .hw_params = tegra186_asrc_in_hw_params,
486 };
487
488 static const struct snd_soc_dai_ops tegra186_asrc_out_dai_ops = {
489 .hw_params = tegra186_asrc_out_hw_params,
490 };
491
492 #define IN_DAI(id) \
493 { \
494 .name = "ASRC-RX-CIF"#id, \
495 .playback = { \
496 .stream_name = "RX" #id "-CIF-Playback",\
497 .channels_min = 1, \
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, \
504 }, \
505 .capture = { \
506 .stream_name = "RX" #id "-CIF-Capture", \
507 .channels_min = 1, \
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, \
514 }, \
515 .ops = &tegra186_asrc_in_dai_ops, \
516 }
517
518 #define OUT_DAI(id) \
519 { \
520 .name = "ASRC-TX-CIF"#id, \
521 .playback = { \
522 .stream_name = "TX" #id "-CIF-Playback",\
523 .channels_min = 1, \
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, \
530 }, \
531 .capture = { \
532 .stream_name = "TX" #id "-CIF-Capture", \
533 .channels_min = 1, \
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, \
540 }, \
541 .ops = &tegra186_asrc_out_dai_ops, \
542 }
543
544 static struct snd_soc_dai_driver tegra186_asrc_dais[] = {
545 /* ASRC Input */
546 IN_DAI(1),
547 IN_DAI(2),
548 IN_DAI(3),
549 IN_DAI(4),
550 IN_DAI(5),
551 IN_DAI(6),
552 IN_DAI(7),
553 /* ASRC Output */
554 OUT_DAI(1),
555 OUT_DAI(2),
556 OUT_DAI(3),
557 OUT_DAI(4),
558 OUT_DAI(5),
559 OUT_DAI(6),
560 };
561
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),
570
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),
576
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),
582
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),
588
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),
594
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),
600
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),
606
607 SND_SOC_DAPM_SPK("Depacketizer", NULL),
608 };
609
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 },
618
619 #define ASRC_ROUTE(id) \
620 ASRC_STREAM_ROUTE(id, "Playback") \
621 ASRC_STREAM_ROUTE(id, "Capture")
622
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" },
628
629 static const struct snd_soc_dapm_route tegra186_asrc_routes[] = {
630 ASRC_ROUTE(1)
631 ASRC_ROUTE(2)
632 ASRC_ROUTE(3)
633 ASRC_ROUTE(4)
634 ASRC_ROUTE(5)
635 ASRC_ROUTE(6)
636 ASRC_RATIO_ROUTE("Playback")
637 ASRC_RATIO_ROUTE("Capture")
638 };
639
640 static const char * const tegra186_asrc_ratio_source_text[] = {
641 "ARAD",
642 "SW",
643 };
644
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)
649
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);
656
657 #define SOC_SINGLE_EXT_FRAC(xname, xregbase, xmax, xget, xput) \
658 { \
659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
660 .name = (xname), \
661 .info = snd_soc_info_xr_sx, \
662 .get = xget, \
663 .put = xput, \
664 \
665 .private_value = (unsigned long)&(struct soc_mreg_control) \
666 { \
667 .regbase = xregbase, \
668 .regcount = 1, \
669 .nbits = 32, \
670 .invert = 0, \
671 .min = 0, \
672 .max = xmax \
673 } \
674 }
675
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),
683
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),
689
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),
695
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),
701
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),
707
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),
713
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),
720
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),
726
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),
732
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),
738
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),
744
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),
750
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),
755
756 SOC_ENUM_EXT("Ratio2 Source", src_select2,
757 tegra186_asrc_get_ratio_source,
758 tegra186_asrc_put_ratio_source),
759
760 SOC_ENUM_EXT("Ratio3 Source", src_select3,
761 tegra186_asrc_get_ratio_source,
762 tegra186_asrc_put_ratio_source),
763
764 SOC_ENUM_EXT("Ratio4 Source", src_select4,
765 tegra186_asrc_get_ratio_source,
766 tegra186_asrc_put_ratio_source),
767
768 SOC_ENUM_EXT("Ratio5 Source", src_select5,
769 tegra186_asrc_get_ratio_source,
770 tegra186_asrc_put_ratio_source),
771
772 SOC_ENUM_EXT("Ratio6 Source", src_select6,
773 tegra186_asrc_get_ratio_source,
774 tegra186_asrc_put_ratio_source),
775
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),
781
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),
786
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),
791
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),
796
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),
801
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),
806
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),
812
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),
817
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),
822
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),
827
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),
832
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),
837
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),
843
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),
848
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),
853
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),
858
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),
863
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),
868 };
869
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),
877 };
878
tegra186_asrc_wr_reg(struct device * dev,unsigned int reg)879 static bool tegra186_asrc_wr_reg(struct device *dev, unsigned int reg)
880 {
881 if (reg < TEGRA186_ASRC_STREAM_LIMIT)
882 reg %= TEGRA186_ASRC_STREAM_STRIDE;
883
884 switch (reg) {
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:
893 return true;
894 default:
895 return false;
896 }
897 }
898
tegra186_asrc_rd_reg(struct device * dev,unsigned int reg)899 static bool tegra186_asrc_rd_reg(struct device *dev, unsigned int reg)
900 {
901 if (reg < TEGRA186_ASRC_STREAM_LIMIT)
902 reg %= TEGRA186_ASRC_STREAM_STRIDE;
903
904 if (tegra186_asrc_wr_reg(dev, reg))
905 return true;
906
907 switch (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:
914 return true;
915 default:
916 return false;
917 }
918 }
919
tegra186_asrc_volatile_reg(struct device * dev,unsigned int reg)920 static bool tegra186_asrc_volatile_reg(struct device *dev, unsigned int reg)
921 {
922 if (reg < TEGRA186_ASRC_STREAM_LIMIT)
923 reg %= TEGRA186_ASRC_STREAM_STRIDE;
924
925 switch (reg) {
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:
939 return true;
940 default:
941 return false;
942 }
943 }
944
945 static const struct regmap_config tegra186_asrc_regmap_config = {
946 .reg_bits = 32,
947 .reg_stride = 4,
948 .val_bits = 32,
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,
956 };
957
958 static const struct of_device_id tegra186_asrc_of_match[] = {
959 { .compatible = "nvidia,tegra186-asrc" },
960 {},
961 };
962 MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
963
tegra186_asrc_platform_probe(struct platform_device * pdev)964 static int tegra186_asrc_platform_probe(struct platform_device *pdev)
965 {
966 struct device *dev = &pdev->dev;
967 struct tegra186_asrc *asrc;
968 void __iomem *regs;
969 unsigned int i;
970 int err;
971
972 asrc = devm_kzalloc(dev, sizeof(*asrc), GFP_KERNEL);
973 if (!asrc)
974 return -ENOMEM;
975
976 dev_set_drvdata(dev, asrc);
977
978 regs = devm_platform_ioremap_resource(pdev, 0);
979 if (IS_ERR(regs))
980 return PTR_ERR(regs);
981
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);
987 }
988
989 regcache_cache_only(asrc->regmap, true);
990
991 regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_CFG,
992 TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION);
993
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;
1004 }
1005
1006 err = devm_snd_soc_register_component(dev, &tegra186_asrc_cmpnt,
1007 tegra186_asrc_dais,
1008 ARRAY_SIZE(tegra186_asrc_dais));
1009 if (err) {
1010 dev_err(dev, "can't register ASRC component, err: %d\n", err);
1011 return err;
1012 }
1013
1014 pm_runtime_enable(dev);
1015
1016 return 0;
1017 }
1018
tegra186_asrc_platform_remove(struct platform_device * pdev)1019 static void tegra186_asrc_platform_remove(struct platform_device *pdev)
1020 {
1021 pm_runtime_disable(&pdev->dev);
1022 }
1023
1024 static const struct dev_pm_ops tegra186_asrc_pm_ops = {
1025 SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
1026 tegra186_asrc_runtime_resume, NULL)
1027 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1028 pm_runtime_force_resume)
1029 };
1030
1031 static struct platform_driver tegra186_asrc_driver = {
1032 .driver = {
1033 .name = "tegra186-asrc",
1034 .of_match_table = tegra186_asrc_of_match,
1035 .pm = &tegra186_asrc_pm_ops,
1036 },
1037 .probe = tegra186_asrc_platform_probe,
1038 .remove_new = tegra186_asrc_platform_remove,
1039 };
1040 module_platform_driver(tegra186_asrc_driver)
1041
1042 MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
1043 MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
1044 MODULE_LICENSE("GPL");
1045