Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
[platform/kernel/linux-starfive.git] / sound / soc / tegra / tegra186_asrc.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1019 static int tegra186_asrc_platform_remove(struct platform_device *pdev)
1020 {
1021         pm_runtime_disable(&pdev->dev);
1022
1023         return 0;
1024 }
1025
1026 static const struct dev_pm_ops tegra186_asrc_pm_ops = {
1027         SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
1028                            tegra186_asrc_runtime_resume, NULL)
1029         SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1030                                      pm_runtime_force_resume)
1031 };
1032
1033 static struct platform_driver tegra186_asrc_driver = {
1034         .driver = {
1035                 .name = "tegra186-asrc",
1036                 .of_match_table = tegra186_asrc_of_match,
1037                 .pm = &tegra186_asrc_pm_ops,
1038         },
1039         .probe = tegra186_asrc_platform_probe,
1040         .remove = tegra186_asrc_platform_remove,
1041 };
1042 module_platform_driver(tegra186_asrc_driver)
1043
1044 MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
1045 MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
1046 MODULE_LICENSE("GPL");