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