xref: /openbmc/linux/sound/soc/tegra/tegra186_asrc.c (revision 2cc41db7)
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