~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/tegra/tegra186_asrc.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 //
  3 // tegra186_asrc.c - Tegra186 ASRC driver
  4 //
  5 // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
  6 
  7 #include <linux/clk.h>
  8 #include <linux/delay.h>
  9 #include <linux/device.h>
 10 #include <linux/io.h>
 11 #include <linux/mod_devicetable.h>
 12 #include <linux/module.h>
 13 #include <linux/platform_device.h>
 14 #include <linux/pm_runtime.h>
 15 #include <linux/regmap.h>
 16 #include <sound/core.h>
 17 #include <sound/pcm.h>
 18 #include <sound/pcm_params.h>
 19 #include <sound/soc.h>
 20 
 21 #include "tegra186_asrc.h"
 22 #include "tegra_cif.h"
 23 
 24 #define ASRC_STREAM_SOURCE_SELECT(id)                                          \
 25         (TEGRA186_ASRC_CFG + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
 26 
 27 #define ASRC_STREAM_REG(reg, id) ((reg) + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
 28 
 29 #define ASRC_STREAM_REG_DEFAULTS(id)                                           \
 30         { ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),                              \
 31           (((id) + 1) << 4) },                                                 \
 32         { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),                   \
 33           0x1 },                                                               \
 34         { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),                  \
 35           0x0 },                                                               \
 36         { ASRC_STREAM_REG(TEGRA186_ASRC_MUTE_UNMUTE_DURATION, id),             \
 37           0x400 },                                                             \
 38         { ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, id),                      \
 39           0x7500 },                                                            \
 40         { ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id),                      \
 41           0x7500 }
 42 
 43 static const struct reg_default tegra186_asrc_reg_defaults[] = {
 44         ASRC_STREAM_REG_DEFAULTS(0),
 45         ASRC_STREAM_REG_DEFAULTS(1),
 46         ASRC_STREAM_REG_DEFAULTS(2),
 47         ASRC_STREAM_REG_DEFAULTS(3),
 48         ASRC_STREAM_REG_DEFAULTS(4),
 49         ASRC_STREAM_REG_DEFAULTS(5),
 50 
 51         { TEGRA186_ASRC_GLOBAL_ENB, 0},
 52         { TEGRA186_ASRC_GLOBAL_SOFT_RESET, 0},
 53         { TEGRA186_ASRC_GLOBAL_CG, 0x1 },
 54         { TEGRA186_ASRC_GLOBAL_CFG, 0x0 },
 55         { TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR, 0},
 56         { TEGRA186_ASRC_GLOBAL_SCRATCH_CFG, 0x0c207980 },
 57         { TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL, 0x00115500 },
 58         { TEGRA186_ASRC_GLOBAL_INT_MASK, 0x0},
 59         { TEGRA186_ASRC_GLOBAL_INT_SET, 0x0},
 60         { TEGRA186_ASRC_GLOBAL_INT_CLEAR, 0x0},
 61         { TEGRA186_ASRC_GLOBAL_APR_CTRL, 0x0},
 62         { TEGRA186_ASRC_GLOBAL_APR_CTRL_ACCESS_CTRL, 0x0},
 63         { TEGRA186_ASRC_GLOBAL_DISARM_APR, 0x0},
 64         { TEGRA186_ASRC_GLOBAL_DISARM_APR_ACCESS_CTRL, 0x0},
 65         { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS, 0x0},
 66         { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS_CTRL, 0x0},
 67         { TEGRA186_ASRC_CYA, 0x0},
 68 };
 69 
 70 static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc,
 71                                       unsigned int id)
 72 {
 73         regmap_write(asrc->regmap,
 74                      ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_LOCK_STATUS,
 75                                      id),
 76                      1);
 77 }
 78 
 79 static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev)
 80 {
 81         struct tegra186_asrc *asrc = dev_get_drvdata(dev);
 82 
 83         regcache_cache_only(asrc->regmap, true);
 84         regcache_mark_dirty(asrc->regmap);
 85 
 86         return 0;
 87 }
 88 
 89 static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev)
 90 {
 91         struct tegra186_asrc *asrc = dev_get_drvdata(dev);
 92         int id;
 93 
 94         regcache_cache_only(asrc->regmap, false);
 95 
 96         /*
 97          * Below sequence is recommended after a runtime PM cycle.
 98          * This otherwise leads to transfer failures. The cache
 99          * sync is done after this to restore other settings.
100          */
101         regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR,
102                      TEGRA186_ASRC_ARAM_START_ADDR);
103         regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_ENB,
104                      TEGRA186_ASRC_GLOBAL_EN);
105 
106         regcache_sync(asrc->regmap);
107 
108         for (id = 0; id < TEGRA186_ASRC_STREAM_MAX; id++) {
109                 if (asrc->lane[id].ratio_source !=
110                     TEGRA186_ASRC_RATIO_SOURCE_SW)
111                         continue;
112 
113                 regmap_write(asrc->regmap,
114                         ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
115                                         id),
116                         asrc->lane[id].int_part);
117 
118                 regmap_write(asrc->regmap,
119                         ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
120                                         id),
121                         asrc->lane[id].frac_part);
122 
123                 tegra186_asrc_lock_stream(asrc, id);
124         }
125 
126         return 0;
127 }
128 
129 static int tegra186_asrc_set_audio_cif(struct tegra186_asrc *asrc,
130                                        struct snd_pcm_hw_params *params,
131                                        unsigned int reg)
132 {
133         int channels, audio_bits;
134         struct tegra_cif_conf cif_conf;
135 
136         memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
137 
138         channels = params_channels(params);
139 
140         switch (params_format(params)) {
141         case SNDRV_PCM_FORMAT_S16_LE:
142                 audio_bits = TEGRA_ACIF_BITS_16;
143                 break;
144         case SNDRV_PCM_FORMAT_S24_LE:
145         case SNDRV_PCM_FORMAT_S32_LE:
146                 audio_bits = TEGRA_ACIF_BITS_32;
147                 break;
148         default:
149                 return -EINVAL;
150         }
151 
152         cif_conf.audio_ch = channels;
153         cif_conf.client_ch = channels;
154         cif_conf.audio_bits = audio_bits;
155         cif_conf.client_bits = TEGRA_ACIF_BITS_24;
156 
157         tegra_set_cif(asrc->regmap, reg, &cif_conf);
158 
159         return 0;
160 }
161 
162 static int tegra186_asrc_in_hw_params(struct snd_pcm_substream *substream,
163                                       struct snd_pcm_hw_params *params,
164                                       struct snd_soc_dai *dai)
165 {
166         struct device *dev = dai->dev;
167         struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
168         int ret, id = dai->id;
169 
170         /* Set input threshold */
171         regmap_write(asrc->regmap,
172                      ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, dai->id),
173                      asrc->lane[id].input_thresh);
174 
175         ret = tegra186_asrc_set_audio_cif(asrc, params,
176                 ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, dai->id));
177         if (ret) {
178                 dev_err(dev, "Can't set ASRC RX%d CIF: %d\n", dai->id, ret);
179                 return ret;
180         }
181 
182         return ret;
183 }
184 
185 static int tegra186_asrc_out_hw_params(struct snd_pcm_substream *substream,
186                                        struct snd_pcm_hw_params *params,
187                                        struct snd_soc_dai *dai)
188 {
189         struct device *dev = dai->dev;
190         struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
191         int ret, id = dai->id - 7;
192 
193          /* Set output threshold */
194         regmap_write(asrc->regmap,
195                      ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, id),
196                      asrc->lane[id].output_thresh);
197 
198         ret = tegra186_asrc_set_audio_cif(asrc, params,
199                 ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id));
200         if (ret) {
201                 dev_err(dev, "Can't set ASRC TX%d CIF: %d\n", id, ret);
202                 return ret;
203         }
204 
205         /* Set ENABLE_HW_RATIO_COMP */
206         if (asrc->lane[id].hwcomp_disable) {
207                 regmap_update_bits(asrc->regmap,
208                         ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
209                         TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
210                         TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_DISABLE);
211         } else {
212                 regmap_update_bits(asrc->regmap,
213                         ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
214                         TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
215                         TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_ENABLE);
216 
217                 regmap_write(asrc->regmap,
218                         ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_COMP, id),
219                         TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE);
220         }
221 
222         /* Set lock */
223         regmap_update_bits(asrc->regmap,
224                            ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
225                            1, asrc->lane[id].ratio_source);
226 
227         if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_SW) {
228                 regmap_write(asrc->regmap,
229                         ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
230                         asrc->lane[id].int_part);
231                 regmap_write(asrc->regmap,
232                         ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
233                         asrc->lane[id].frac_part);
234                 tegra186_asrc_lock_stream(asrc, id);
235         }
236 
237         return ret;
238 }
239 
240 static int tegra186_asrc_get_ratio_source(struct snd_kcontrol *kcontrol,
241                                           struct snd_ctl_elem_value *ucontrol)
242 {
243         struct soc_enum *asrc_private =
244                 (struct soc_enum  *)kcontrol->private_value;
245         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
246         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
247         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
248 
249         ucontrol->value.enumerated.item[0] = asrc->lane[id].ratio_source;
250 
251         return 0;
252 }
253 
254 static int tegra186_asrc_put_ratio_source(struct snd_kcontrol *kcontrol,
255                                           struct snd_ctl_elem_value *ucontrol)
256 {
257         struct soc_enum *asrc_private =
258                 (struct soc_enum  *)kcontrol->private_value;
259         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
260         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
261         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
262         bool change = false;
263 
264         asrc->lane[id].ratio_source = ucontrol->value.enumerated.item[0];
265 
266         regmap_update_bits_check(asrc->regmap, asrc_private->reg,
267                                  TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK,
268                                  asrc->lane[id].ratio_source,
269                                  &change);
270 
271         return change ? 1 : 0;
272 }
273 
274 static int tegra186_asrc_get_ratio_int(struct snd_kcontrol *kcontrol,
275                                        struct snd_ctl_elem_value *ucontrol)
276 {
277         struct soc_mixer_control *asrc_private =
278                 (struct soc_mixer_control *)kcontrol->private_value;
279         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
280         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
281         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
282 
283         regmap_read(asrc->regmap,
284                     ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
285                     &asrc->lane[id].int_part);
286 
287         ucontrol->value.integer.value[0] = asrc->lane[id].int_part;
288 
289         return 0;
290 }
291 
292 static int tegra186_asrc_put_ratio_int(struct snd_kcontrol *kcontrol,
293                                        struct snd_ctl_elem_value *ucontrol)
294 {
295         struct soc_mixer_control *asrc_private =
296                 (struct soc_mixer_control *)kcontrol->private_value;
297         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
298         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
299         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
300         bool change = false;
301 
302         if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
303                 dev_err(cmpnt->dev,
304                         "Lane %d ratio source is ARAD, invalid SW update\n",
305                         id);
306                 return -EINVAL;
307         }
308 
309         asrc->lane[id].int_part = ucontrol->value.integer.value[0];
310 
311         regmap_update_bits_check(asrc->regmap,
312                                  ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
313                                                  id),
314                                  TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK,
315                                  asrc->lane[id].int_part, &change);
316 
317         tegra186_asrc_lock_stream(asrc, id);
318 
319         return change ? 1 : 0;
320 }
321 
322 static int tegra186_asrc_get_ratio_frac(struct snd_kcontrol *kcontrol,
323                                         struct snd_ctl_elem_value *ucontrol)
324 {
325         struct soc_mreg_control *asrc_private =
326                 (struct soc_mreg_control *)kcontrol->private_value;
327         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
328         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
329         unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
330 
331         regmap_read(asrc->regmap,
332                     ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
333                     &asrc->lane[id].frac_part);
334 
335         ucontrol->value.integer.value[0] = asrc->lane[id].frac_part;
336 
337         return 0;
338 }
339 
340 static int tegra186_asrc_put_ratio_frac(struct snd_kcontrol *kcontrol,
341                                         struct snd_ctl_elem_value *ucontrol)
342 {
343         struct soc_mreg_control *asrc_private =
344                 (struct soc_mreg_control *)kcontrol->private_value;
345         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
346         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
347         unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
348         bool change = false;
349 
350         if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
351                 dev_err(cmpnt->dev,
352                         "Lane %d ratio source is ARAD, invalid SW update\n",
353                         id);
354                 return -EINVAL;
355         }
356 
357         asrc->lane[id].frac_part = ucontrol->value.integer.value[0];
358 
359         regmap_update_bits_check(asrc->regmap,
360                                  ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
361                                                  id),
362                                  TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
363                                  asrc->lane[id].frac_part, &change);
364 
365         tegra186_asrc_lock_stream(asrc, id);
366 
367         return change ? 1 : 0;
368 }
369 
370 static int tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol *kcontrol,
371                                             struct snd_ctl_elem_value *ucontrol)
372 {
373         struct soc_mixer_control *asrc_private =
374                 (struct soc_mixer_control *)kcontrol->private_value;
375         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
376         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
377         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
378 
379         ucontrol->value.integer.value[0] = asrc->lane[id].hwcomp_disable;
380 
381         return 0;
382 }
383 
384 static int tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol *kcontrol,
385                                             struct snd_ctl_elem_value *ucontrol)
386 {
387         struct soc_mixer_control *asrc_private =
388                 (struct soc_mixer_control *)kcontrol->private_value;
389         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
390         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
391         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
392         int value = ucontrol->value.integer.value[0];
393 
394         if (value == asrc->lane[id].hwcomp_disable)
395                 return 0;
396 
397         asrc->lane[id].hwcomp_disable = value;
398 
399         return 1;
400 }
401 
402 static int tegra186_asrc_get_input_threshold(struct snd_kcontrol *kcontrol,
403                                              struct snd_ctl_elem_value *ucontrol)
404 {
405         struct soc_mixer_control *asrc_private =
406                 (struct soc_mixer_control *)kcontrol->private_value;
407         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
408         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
409         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
410 
411         ucontrol->value.integer.value[0] = (asrc->lane[id].input_thresh & 0x3);
412 
413         return 0;
414 }
415 
416 static int tegra186_asrc_put_input_threshold(struct snd_kcontrol *kcontrol,
417                                              struct snd_ctl_elem_value *ucontrol)
418 {
419         struct soc_mixer_control *asrc_private =
420                 (struct soc_mixer_control *)kcontrol->private_value;
421         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
422         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
423         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
424         int value = (asrc->lane[id].input_thresh & ~(0x3)) |
425                     ucontrol->value.integer.value[0];
426 
427         if (value == asrc->lane[id].input_thresh)
428                 return 0;
429 
430         asrc->lane[id].input_thresh = value;
431 
432         return 1;
433 }
434 
435 static int tegra186_asrc_get_output_threshold(struct snd_kcontrol *kcontrol,
436                                               struct snd_ctl_elem_value *ucontrol)
437 {
438         struct soc_mixer_control *asrc_private =
439                 (struct soc_mixer_control *)kcontrol->private_value;
440         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
441         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
442         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
443 
444         ucontrol->value.integer.value[0] = (asrc->lane[id].output_thresh & 0x3);
445 
446         return 0;
447 }
448 
449 static int tegra186_asrc_put_output_threshold(struct snd_kcontrol *kcontrol,
450                                               struct snd_ctl_elem_value *ucontrol)
451 {
452         struct soc_mixer_control *asrc_private =
453                 (struct soc_mixer_control *)kcontrol->private_value;
454         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
455         struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
456         unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
457         int value = (asrc->lane[id].output_thresh & ~(0x3)) |
458                     ucontrol->value.integer.value[0];
459 
460         if (value == asrc->lane[id].output_thresh)
461                 return 0;
462 
463         asrc->lane[id].output_thresh = value;
464 
465         return 1;
466 }
467 
468 static int tegra186_asrc_widget_event(struct snd_soc_dapm_widget *w,
469                                         struct snd_kcontrol *kcontrol, int event)
470 {
471         struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
472         struct tegra186_asrc *asrc = dev_get_drvdata(cmpnt->dev);
473         unsigned int id =
474                 (w->reg - TEGRA186_ASRC_ENABLE) / TEGRA186_ASRC_STREAM_STRIDE;
475 
476         regmap_write(asrc->regmap,
477                      ASRC_STREAM_REG(TEGRA186_ASRC_SOFT_RESET, id),
478                      0x1);
479 
480         return 0;
481 }
482 
483 static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops = {
484         .hw_params      = tegra186_asrc_in_hw_params,
485 };
486 
487 static const struct snd_soc_dai_ops tegra186_asrc_out_dai_ops = {
488         .hw_params      = tegra186_asrc_out_hw_params,
489 };
490 
491 #define IN_DAI(id)                                              \
492         {                                                       \
493                 .name = "ASRC-RX-CIF"#id,                       \
494                 .playback = {                                   \
495                         .stream_name = "RX" #id "-CIF-Playback",\
496                         .channels_min = 1,                      \
497                         .channels_max = 12,                     \
498                         .rates = SNDRV_PCM_RATE_8000_192000,    \
499                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
500                                 SNDRV_PCM_FMTBIT_S16_LE |       \
501                                 SNDRV_PCM_FMTBIT_S24_LE |       \
502                                 SNDRV_PCM_FMTBIT_S32_LE,        \
503                 },                                              \
504                 .capture = {                                    \
505                         .stream_name = "RX" #id "-CIF-Capture", \
506                         .channels_min = 1,                      \
507                         .channels_max = 12,                     \
508                         .rates = SNDRV_PCM_RATE_8000_192000,    \
509                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
510                                 SNDRV_PCM_FMTBIT_S16_LE |       \
511                                 SNDRV_PCM_FMTBIT_S24_LE |       \
512                                 SNDRV_PCM_FMTBIT_S32_LE,        \
513                 },                                              \
514                 .ops = &tegra186_asrc_in_dai_ops,               \
515         }
516 
517 #define OUT_DAI(id)                                             \
518         {                                                       \
519                 .name = "ASRC-TX-CIF"#id,                       \
520                 .playback = {                                   \
521                         .stream_name = "TX" #id "-CIF-Playback",\
522                         .channels_min = 1,                      \
523                         .channels_max = 12,                     \
524                         .rates = SNDRV_PCM_RATE_8000_192000,    \
525                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
526                                 SNDRV_PCM_FMTBIT_S16_LE |       \
527                                 SNDRV_PCM_FMTBIT_S24_LE |       \
528                                 SNDRV_PCM_FMTBIT_S32_LE,        \
529                 },                                              \
530                 .capture = {                                    \
531                         .stream_name = "TX" #id "-CIF-Capture", \
532                         .channels_min = 1,                      \
533                         .channels_max = 12,                     \
534                         .rates = SNDRV_PCM_RATE_8000_192000,    \
535                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
536                                 SNDRV_PCM_FMTBIT_S16_LE |       \
537                                 SNDRV_PCM_FMTBIT_S24_LE |       \
538                                 SNDRV_PCM_FMTBIT_S32_LE,        \
539                 },                                              \
540                 .ops = &tegra186_asrc_out_dai_ops,              \
541         }
542 
543 static struct snd_soc_dai_driver tegra186_asrc_dais[] = {
544         /* ASRC Input */
545         IN_DAI(1),
546         IN_DAI(2),
547         IN_DAI(3),
548         IN_DAI(4),
549         IN_DAI(5),
550         IN_DAI(6),
551         IN_DAI(7),
552         /* ASRC Output */
553         OUT_DAI(1),
554         OUT_DAI(2),
555         OUT_DAI(3),
556         OUT_DAI(4),
557         OUT_DAI(5),
558         OUT_DAI(6),
559 };
560 
561 static const struct snd_soc_dapm_widget tegra186_asrc_widgets[] = {
562         SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
563         SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
564         SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
565         SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, SND_SOC_NOPM, 0, 0),
566         SND_SOC_DAPM_AIF_IN("RX5", NULL, 0, SND_SOC_NOPM, 0, 0),
567         SND_SOC_DAPM_AIF_IN("RX6", NULL, 0, SND_SOC_NOPM, 0, 0),
568         SND_SOC_DAPM_AIF_IN("RX7", NULL, 0, SND_SOC_NOPM, 0, 0),
569 
570         SND_SOC_DAPM_AIF_OUT_E("TX1", NULL, 0,
571                                ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 0),
572                                TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
573                                tegra186_asrc_widget_event,
574                                SND_SOC_DAPM_POST_PMD),
575 
576         SND_SOC_DAPM_AIF_OUT_E("TX2", NULL, 0,
577                                ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 1),
578                                TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
579                                tegra186_asrc_widget_event,
580                                SND_SOC_DAPM_POST_PMD),
581 
582         SND_SOC_DAPM_AIF_OUT_E("TX3", NULL, 0,
583                                ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 2),
584                                TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
585                                tegra186_asrc_widget_event,
586                                SND_SOC_DAPM_POST_PMD),
587 
588         SND_SOC_DAPM_AIF_OUT_E("TX4", NULL, 0,
589                                ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 3),
590                                TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
591                                tegra186_asrc_widget_event,
592                                SND_SOC_DAPM_POST_PMD),
593 
594         SND_SOC_DAPM_AIF_OUT_E("TX5", NULL, 0,
595                                ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 4),
596                                TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
597                                tegra186_asrc_widget_event,
598                                SND_SOC_DAPM_POST_PMD),
599 
600         SND_SOC_DAPM_AIF_OUT_E("TX6", NULL, 0,
601                                ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 5),
602                                TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
603                                tegra186_asrc_widget_event,
604                                SND_SOC_DAPM_POST_PMD),
605 
606         SND_SOC_DAPM_SPK("Depacketizer", NULL),
607 };
608 
609 #define ASRC_STREAM_ROUTE(id, sname)                                       \
610         { "RX" #id " XBAR-" sname,      NULL,   "RX" #id " XBAR-TX" },     \
611         { "RX" #id "-CIF-" sname,       NULL,   "RX" #id " XBAR-" sname }, \
612         { "RX" #id,                     NULL,   "RX" #id "-CIF-" sname },  \
613         { "TX" #id,                     NULL,   "RX" #id },                \
614         { "TX" #id "-CIF-" sname,       NULL,   "TX" #id },                \
615         { "TX" #id " XBAR-" sname,      NULL,   "TX" #id "-CIF-" sname },  \
616         { "TX" #id " XBAR-RX",          NULL,   "TX" #id " XBAR-" sname },
617 
618 #define ASRC_ROUTE(id)                                                     \
619         ASRC_STREAM_ROUTE(id, "Playback")                                  \
620         ASRC_STREAM_ROUTE(id, "Capture")
621 
622 #define ASRC_RATIO_ROUTE(sname)                                            \
623         { "RX7 XBAR-" sname,            NULL,   "RX7 XBAR-TX" },           \
624         { "RX7-CIF-" sname,             NULL,   "RX7 XBAR-" sname },       \
625         { "RX7",                        NULL,   "RX7-CIF-" sname },        \
626         { "Depacketizer",               NULL,   "RX7" },
627 
628 static const struct snd_soc_dapm_route tegra186_asrc_routes[] = {
629         ASRC_ROUTE(1)
630         ASRC_ROUTE(2)
631         ASRC_ROUTE(3)
632         ASRC_ROUTE(4)
633         ASRC_ROUTE(5)
634         ASRC_ROUTE(6)
635         ASRC_RATIO_ROUTE("Playback")
636         ASRC_RATIO_ROUTE("Capture")
637 };
638 
639 static const char * const tegra186_asrc_ratio_source_text[] = {
640         "ARAD",
641         "SW",
642 };
643 
644 #define ASRC_SOURCE_DECL(name, id)                                      \
645         static const struct soc_enum name =                             \
646                 SOC_ENUM_SINGLE(ASRC_STREAM_SOURCE_SELECT(id),          \
647                                 0, 2, tegra186_asrc_ratio_source_text)
648 
649 ASRC_SOURCE_DECL(src_select1, 0);
650 ASRC_SOURCE_DECL(src_select2, 1);
651 ASRC_SOURCE_DECL(src_select3, 2);
652 ASRC_SOURCE_DECL(src_select4, 3);
653 ASRC_SOURCE_DECL(src_select5, 4);
654 ASRC_SOURCE_DECL(src_select6, 5);
655 
656 #define SOC_SINGLE_EXT_FRAC(xname, xregbase, xmax, xget, xput)          \
657 {                                                                       \
658         .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,                           \
659         .name   = (xname),                                              \
660         .info   = snd_soc_info_xr_sx,                                   \
661         .get    = xget,                                                 \
662         .put    = xput,                                                 \
663                                                                         \
664         .private_value = (unsigned long)&(struct soc_mreg_control)      \
665         {                                                               \
666                 .regbase        = xregbase,                             \
667                 .regcount       = 1,                                    \
668                 .nbits          = 32,                                   \
669                 .invert         = 0,                                    \
670                 .min            = 0,                                    \
671                 .max            = xmax                                  \
672         }                                                               \
673 }
674 
675 static const struct snd_kcontrol_new tegra186_asrc_controls[] = {
676         /* Controls for integer part of ratio */
677         SOC_SINGLE_EXT("Ratio1 Integer Part",
678                        ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 0),
679                        0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
680                        tegra186_asrc_get_ratio_int,
681                        tegra186_asrc_put_ratio_int),
682 
683         SOC_SINGLE_EXT("Ratio2 Integer Part",
684                        ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 1),
685                        0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
686                        tegra186_asrc_get_ratio_int,
687                        tegra186_asrc_put_ratio_int),
688 
689         SOC_SINGLE_EXT("Ratio3 Integer Part",
690                        ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 2),
691                        0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
692                        tegra186_asrc_get_ratio_int,
693                        tegra186_asrc_put_ratio_int),
694 
695         SOC_SINGLE_EXT("Ratio4 Integer Part",
696                        ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 3),
697                        0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
698                        tegra186_asrc_get_ratio_int,
699                        tegra186_asrc_put_ratio_int),
700 
701         SOC_SINGLE_EXT("Ratio5 Integer Part",
702                        ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 4),
703                        0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
704                        tegra186_asrc_get_ratio_int,
705                        tegra186_asrc_put_ratio_int),
706 
707         SOC_SINGLE_EXT("Ratio6 Integer Part",
708                        ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 5),
709                        0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
710                        tegra186_asrc_get_ratio_int,
711                        tegra186_asrc_put_ratio_int),
712 
713         /* Controls for fractional part of ratio */
714         SOC_SINGLE_EXT_FRAC("Ratio1 Fractional Part",
715                             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 0),
716                             TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
717                             tegra186_asrc_get_ratio_frac,
718                             tegra186_asrc_put_ratio_frac),
719 
720         SOC_SINGLE_EXT_FRAC("Ratio2 Fractional Part",
721                             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 1),
722                             TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
723                             tegra186_asrc_get_ratio_frac,
724                             tegra186_asrc_put_ratio_frac),
725 
726         SOC_SINGLE_EXT_FRAC("Ratio3 Fractional Part",
727                             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 2),
728                             TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
729                             tegra186_asrc_get_ratio_frac,
730                             tegra186_asrc_put_ratio_frac),
731 
732         SOC_SINGLE_EXT_FRAC("Ratio4 Fractional Part",
733                             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 3),
734                             TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
735                             tegra186_asrc_get_ratio_frac,
736                             tegra186_asrc_put_ratio_frac),
737 
738         SOC_SINGLE_EXT_FRAC("Ratio5 Fractional Part",
739                             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 4),
740                             TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
741                             tegra186_asrc_get_ratio_frac,
742                             tegra186_asrc_put_ratio_frac),
743 
744         SOC_SINGLE_EXT_FRAC("Ratio6 Fractional Part",
745                             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 5),
746                             TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
747                             tegra186_asrc_get_ratio_frac,
748                             tegra186_asrc_put_ratio_frac),
749 
750         /* Source of ratio provider */
751         SOC_ENUM_EXT("Ratio1 Source", src_select1,
752                      tegra186_asrc_get_ratio_source,
753                      tegra186_asrc_put_ratio_source),
754 
755         SOC_ENUM_EXT("Ratio2 Source", src_select2,
756                      tegra186_asrc_get_ratio_source,
757                      tegra186_asrc_put_ratio_source),
758 
759         SOC_ENUM_EXT("Ratio3 Source", src_select3,
760                      tegra186_asrc_get_ratio_source,
761                      tegra186_asrc_put_ratio_source),
762 
763         SOC_ENUM_EXT("Ratio4 Source", src_select4,
764                      tegra186_asrc_get_ratio_source,
765                      tegra186_asrc_put_ratio_source),
766 
767         SOC_ENUM_EXT("Ratio5 Source", src_select5,
768                      tegra186_asrc_get_ratio_source,
769                      tegra186_asrc_put_ratio_source),
770 
771         SOC_ENUM_EXT("Ratio6 Source", src_select6,
772                      tegra186_asrc_get_ratio_source,
773                      tegra186_asrc_put_ratio_source),
774 
775         /* Disable HW managed overflow/underflow issue at input and output */
776         SOC_SINGLE_EXT("Stream1 HW Component Disable",
777                        ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 0), 0, 1, 0,
778                        tegra186_asrc_get_hwcomp_disable,
779                        tegra186_asrc_put_hwcomp_disable),
780 
781         SOC_SINGLE_EXT("Stream2 HW Component Disable",
782                        ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 1), 0, 1, 0,
783                        tegra186_asrc_get_hwcomp_disable,
784                        tegra186_asrc_put_hwcomp_disable),
785 
786         SOC_SINGLE_EXT("Stream3 HW Component Disable",
787                        ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 2), 0, 1, 0,
788                        tegra186_asrc_get_hwcomp_disable,
789                        tegra186_asrc_put_hwcomp_disable),
790 
791         SOC_SINGLE_EXT("Stream4 HW Component Disable",
792                        ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 3), 0, 1, 0,
793                        tegra186_asrc_get_hwcomp_disable,
794                        tegra186_asrc_put_hwcomp_disable),
795 
796         SOC_SINGLE_EXT("Stream5 HW Component Disable",
797                        ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 4), 0, 1, 0,
798                        tegra186_asrc_get_hwcomp_disable,
799                        tegra186_asrc_put_hwcomp_disable),
800 
801         SOC_SINGLE_EXT("Stream6 HW Component Disable",
802                        ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 5), 0, 1, 0,
803                        tegra186_asrc_get_hwcomp_disable,
804                        tegra186_asrc_put_hwcomp_disable),
805 
806         /* Input threshold for watermark fields */
807         SOC_SINGLE_EXT("Stream1 Input Threshold",
808                        ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 0), 0, 3, 0,
809                        tegra186_asrc_get_input_threshold,
810                        tegra186_asrc_put_input_threshold),
811 
812         SOC_SINGLE_EXT("Stream2 Input Threshold",
813                        ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 1), 0, 3, 0,
814                        tegra186_asrc_get_input_threshold,
815                        tegra186_asrc_put_input_threshold),
816 
817         SOC_SINGLE_EXT("Stream3 Input Threshold",
818                        ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 2), 0, 3, 0,
819                        tegra186_asrc_get_input_threshold,
820                        tegra186_asrc_put_input_threshold),
821 
822         SOC_SINGLE_EXT("Stream4 Input Threshold",
823                        ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 3), 0, 3, 0,
824                        tegra186_asrc_get_input_threshold,
825                        tegra186_asrc_put_input_threshold),
826 
827         SOC_SINGLE_EXT("Stream5 Input Threshold",
828                        ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
829                        tegra186_asrc_get_input_threshold,
830                        tegra186_asrc_put_input_threshold),
831 
832         SOC_SINGLE_EXT("Stream6 Input Threshold",
833                        ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
834                        tegra186_asrc_get_input_threshold,
835                        tegra186_asrc_put_input_threshold),
836 
837         /* Output threshold for watermark fields */
838         SOC_SINGLE_EXT("Stream1 Output Threshold",
839                        ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 0), 0, 3, 0,
840                        tegra186_asrc_get_output_threshold,
841                        tegra186_asrc_put_output_threshold),
842 
843         SOC_SINGLE_EXT("Stream2 Output Threshold",
844                        ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 1), 0, 3, 0,
845                        tegra186_asrc_get_output_threshold,
846                        tegra186_asrc_put_output_threshold),
847 
848         SOC_SINGLE_EXT("Stream3 Output Threshold",
849                        ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 2), 0, 3, 0,
850                        tegra186_asrc_get_output_threshold,
851                        tegra186_asrc_put_output_threshold),
852 
853         SOC_SINGLE_EXT("Stream4 Output Threshold",
854                        ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 3), 0, 3, 0,
855                        tegra186_asrc_get_output_threshold,
856                        tegra186_asrc_put_output_threshold),
857 
858         SOC_SINGLE_EXT("Stream5 Output Threshold",
859                        ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 4), 0, 3, 0,
860                        tegra186_asrc_get_output_threshold,
861                        tegra186_asrc_put_output_threshold),
862 
863         SOC_SINGLE_EXT("Stream6 Output Threshold",
864                        ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 5), 0, 3, 0,
865                        tegra186_asrc_get_output_threshold,
866                        tegra186_asrc_put_output_threshold),
867 };
868 
869 static const struct snd_soc_component_driver tegra186_asrc_cmpnt = {
870         .dapm_widgets           = tegra186_asrc_widgets,
871         .num_dapm_widgets       = ARRAY_SIZE(tegra186_asrc_widgets),
872         .dapm_routes            = tegra186_asrc_routes,
873         .num_dapm_routes        = ARRAY_SIZE(tegra186_asrc_routes),
874         .controls               = tegra186_asrc_controls,
875         .num_controls           = ARRAY_SIZE(tegra186_asrc_controls),
876 };
877 
878 static bool tegra186_asrc_wr_reg(struct device *dev, unsigned int reg)
879 {
880         if (reg < TEGRA186_ASRC_STREAM_LIMIT)
881                 reg %= TEGRA186_ASRC_STREAM_STRIDE;
882 
883         switch (reg) {
884         case TEGRA186_ASRC_CFG ... TEGRA186_ASRC_RATIO_COMP:
885         case TEGRA186_ASRC_RX_CIF_CTRL:
886         case TEGRA186_ASRC_TX_CIF_CTRL:
887         case TEGRA186_ASRC_ENABLE:
888         case TEGRA186_ASRC_SOFT_RESET:
889         case TEGRA186_ASRC_GLOBAL_ENB ... TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL:
890         case TEGRA186_ASRC_GLOBAL_INT_MASK ... TEGRA186_ASRC_GLOBAL_INT_CLEAR:
891         case TEGRA186_ASRC_GLOBAL_APR_CTRL ... TEGRA186_ASRC_CYA:
892                 return true;
893         default:
894                 return false;
895         }
896 }
897 
898 static bool tegra186_asrc_rd_reg(struct device *dev, unsigned int reg)
899 {
900         if (reg < TEGRA186_ASRC_STREAM_LIMIT)
901                 reg %= TEGRA186_ASRC_STREAM_STRIDE;
902 
903         if (tegra186_asrc_wr_reg(dev, reg))
904                 return true;
905 
906         switch (reg) {
907         case TEGRA186_ASRC_RX_STATUS:
908         case TEGRA186_ASRC_TX_STATUS:
909         case TEGRA186_ASRC_STATUS ... TEGRA186_ASRC_OUTSAMPLEBUF_CFG:
910         case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
911         case TEGRA186_ASRC_GLOBAL_STATUS ... TEGRA186_ASRC_GLOBAL_INT_STATUS:
912         case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
913                 return true;
914         default:
915                 return false;
916         }
917 }
918 
919 static bool tegra186_asrc_volatile_reg(struct device *dev, unsigned int reg)
920 {
921         if (reg < TEGRA186_ASRC_STREAM_LIMIT)
922                 reg %= TEGRA186_ASRC_STREAM_STRIDE;
923 
924         switch (reg) {
925         case TEGRA186_ASRC_RX_STATUS:
926         case TEGRA186_ASRC_TX_STATUS:
927         case TEGRA186_ASRC_SOFT_RESET:
928         case TEGRA186_ASRC_RATIO_INT_PART:
929         case TEGRA186_ASRC_RATIO_FRAC_PART:
930         case TEGRA186_ASRC_STATUS:
931         case TEGRA186_ASRC_RATIO_LOCK_STATUS:
932         case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
933         case TEGRA186_ASRC_GLOBAL_SOFT_RESET:
934         case TEGRA186_ASRC_GLOBAL_STATUS:
935         case TEGRA186_ASRC_GLOBAL_STREAM_ENABLE_STATUS:
936         case TEGRA186_ASRC_GLOBAL_INT_STATUS:
937         case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
938                 return true;
939         default:
940                 return false;
941         }
942 }
943 
944 static const struct regmap_config tegra186_asrc_regmap_config = {
945         .reg_bits               = 32,
946         .reg_stride             = 4,
947         .val_bits               = 32,
948         .max_register           = TEGRA186_ASRC_CYA,
949         .writeable_reg          = tegra186_asrc_wr_reg,
950         .readable_reg           = tegra186_asrc_rd_reg,
951         .volatile_reg           = tegra186_asrc_volatile_reg,
952         .reg_defaults           = tegra186_asrc_reg_defaults,
953         .num_reg_defaults       = ARRAY_SIZE(tegra186_asrc_reg_defaults),
954         .cache_type             = REGCACHE_FLAT,
955 };
956 
957 static const struct of_device_id tegra186_asrc_of_match[] = {
958         { .compatible = "nvidia,tegra186-asrc" },
959         {},
960 };
961 MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
962 
963 static int tegra186_asrc_platform_probe(struct platform_device *pdev)
964 {
965         struct device *dev = &pdev->dev;
966         struct tegra186_asrc *asrc;
967         void __iomem *regs;
968         unsigned int i;
969         int err;
970 
971         asrc = devm_kzalloc(dev, sizeof(*asrc), GFP_KERNEL);
972         if (!asrc)
973                 return -ENOMEM;
974 
975         dev_set_drvdata(dev, asrc);
976 
977         regs = devm_platform_ioremap_resource(pdev, 0);
978         if (IS_ERR(regs))
979                 return PTR_ERR(regs);
980 
981         asrc->regmap = devm_regmap_init_mmio(dev, regs,
982                                              &tegra186_asrc_regmap_config);
983         if (IS_ERR(asrc->regmap)) {
984                 dev_err(dev, "regmap init failed\n");
985                 return PTR_ERR(asrc->regmap);
986         }
987 
988         regcache_cache_only(asrc->regmap, true);
989 
990         regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_CFG,
991                      TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION);
992 
993         /* Initialize default output srate */
994         for (i = 0; i < TEGRA186_ASRC_STREAM_MAX; i++) {
995                 asrc->lane[i].ratio_source = TEGRA186_ASRC_RATIO_SOURCE_SW;
996                 asrc->lane[i].int_part = 1;
997                 asrc->lane[i].frac_part = 0;
998                 asrc->lane[i].hwcomp_disable = 0;
999                 asrc->lane[i].input_thresh =
1000                         TEGRA186_ASRC_STREAM_DEFAULT_INPUT_HW_COMP_THRESH_CFG;
1001                 asrc->lane[i].output_thresh =
1002                         TEGRA186_ASRC_STREAM_DEFAULT_OUTPUT_HW_COMP_THRESH_CFG;
1003         }
1004 
1005         err = devm_snd_soc_register_component(dev, &tegra186_asrc_cmpnt,
1006                                               tegra186_asrc_dais,
1007                                               ARRAY_SIZE(tegra186_asrc_dais));
1008         if (err) {
1009                 dev_err(dev, "can't register ASRC component, err: %d\n", err);
1010                 return err;
1011         }
1012 
1013         pm_runtime_enable(dev);
1014 
1015         return 0;
1016 }
1017 
1018 static void tegra186_asrc_platform_remove(struct platform_device *pdev)
1019 {
1020         pm_runtime_disable(&pdev->dev);
1021 }
1022 
1023 static const struct dev_pm_ops tegra186_asrc_pm_ops = {
1024         SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
1025                            tegra186_asrc_runtime_resume, NULL)
1026         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1027                                 pm_runtime_force_resume)
1028 };
1029 
1030 static struct platform_driver tegra186_asrc_driver = {
1031         .driver = {
1032                 .name = "tegra186-asrc",
1033                 .of_match_table = tegra186_asrc_of_match,
1034                 .pm = &tegra186_asrc_pm_ops,
1035         },
1036         .probe = tegra186_asrc_platform_probe,
1037         .remove_new = tegra186_asrc_platform_remove,
1038 };
1039 module_platform_driver(tegra186_asrc_driver)
1040 
1041 MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
1042 MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
1043 MODULE_LICENSE("GPL");
1044 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php