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
43static 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
70static 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
79static 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
89static 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
129static 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
162static 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
185static 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
240static 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
254static 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
274static 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
292static 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
322static 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
340static 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
370static 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
384static 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
402static 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
416static 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
435static 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
449static 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
468static 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
483static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops = {
484	.hw_params	= tegra186_asrc_in_hw_params,
485};
486
487static 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
543static 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
561static 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
628static 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
639static 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
649ASRC_SOURCE_DECL(src_select1, 0);
650ASRC_SOURCE_DECL(src_select2, 1);
651ASRC_SOURCE_DECL(src_select3, 2);
652ASRC_SOURCE_DECL(src_select4, 3);
653ASRC_SOURCE_DECL(src_select5, 4);
654ASRC_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
675static 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
869static 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
878static 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
898static 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
919static 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
944static 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
957static const struct of_device_id tegra186_asrc_of_match[] = {
958	{ .compatible = "nvidia,tegra186-asrc" },
959	{},
960};
961MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
962
963static 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
1018static void tegra186_asrc_platform_remove(struct platform_device *pdev)
1019{
1020	pm_runtime_disable(&pdev->dev);
1021}
1022
1023static 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
1030static 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_new = tegra186_asrc_platform_remove,
1038};
1039module_platform_driver(tegra186_asrc_driver)
1040
1041MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
1042MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
1043MODULE_LICENSE("GPL");
1044