Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 //
0003 // tegra186_asrc.c - Tegra186 ASRC driver
0004 //
0005 // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
0006 
0007 #include <linux/clk.h>
0008 #include <linux/delay.h>
0009 #include <linux/device.h>
0010 #include <linux/io.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_device.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/regmap.h>
0017 #include <sound/core.h>
0018 #include <sound/pcm.h>
0019 #include <sound/pcm_params.h>
0020 #include <sound/soc.h>
0021 
0022 #include "tegra186_asrc.h"
0023 #include "tegra_cif.h"
0024 
0025 #define ASRC_STREAM_SOURCE_SELECT(id)                          \
0026     (TEGRA186_ASRC_CFG + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
0027 
0028 #define ASRC_STREAM_REG(reg, id) ((reg) + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
0029 
0030 #define ASRC_STREAM_REG_DEFAULTS(id)                           \
0031     { ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),                  \
0032       (((id) + 1) << 4) },                             \
0033     { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),               \
0034       0x1 },                                   \
0035     { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),              \
0036       0x0 },                                   \
0037     { ASRC_STREAM_REG(TEGRA186_ASRC_MUTE_UNMUTE_DURATION, id),         \
0038       0x400 },                                 \
0039     { ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, id),              \
0040       0x7500 },                                \
0041     { ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id),              \
0042       0x7500 }
0043 
0044 static const struct reg_default tegra186_asrc_reg_defaults[] = {
0045     ASRC_STREAM_REG_DEFAULTS(0),
0046     ASRC_STREAM_REG_DEFAULTS(1),
0047     ASRC_STREAM_REG_DEFAULTS(2),
0048     ASRC_STREAM_REG_DEFAULTS(3),
0049     ASRC_STREAM_REG_DEFAULTS(4),
0050     ASRC_STREAM_REG_DEFAULTS(5),
0051 
0052     { TEGRA186_ASRC_GLOBAL_ENB, 0},
0053     { TEGRA186_ASRC_GLOBAL_SOFT_RESET, 0},
0054     { TEGRA186_ASRC_GLOBAL_CG, 0x1 },
0055     { TEGRA186_ASRC_GLOBAL_CFG, 0x0 },
0056     { TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR, 0},
0057     { TEGRA186_ASRC_GLOBAL_SCRATCH_CFG, 0x0c207980 },
0058     { TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL, 0x00115500 },
0059     { TEGRA186_ASRC_GLOBAL_INT_MASK, 0x0},
0060     { TEGRA186_ASRC_GLOBAL_INT_SET, 0x0},
0061     { TEGRA186_ASRC_GLOBAL_INT_CLEAR, 0x0},
0062     { TEGRA186_ASRC_GLOBAL_APR_CTRL, 0x0},
0063     { TEGRA186_ASRC_GLOBAL_APR_CTRL_ACCESS_CTRL, 0x0},
0064     { TEGRA186_ASRC_GLOBAL_DISARM_APR, 0x0},
0065     { TEGRA186_ASRC_GLOBAL_DISARM_APR_ACCESS_CTRL, 0x0},
0066     { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS, 0x0},
0067     { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS_CTRL, 0x0},
0068     { TEGRA186_ASRC_CYA, 0x0},
0069 };
0070 
0071 static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc,
0072                       unsigned int id)
0073 {
0074     regmap_write(asrc->regmap,
0075              ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_LOCK_STATUS,
0076                      id),
0077              1);
0078 }
0079 
0080 static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev)
0081 {
0082     struct tegra186_asrc *asrc = dev_get_drvdata(dev);
0083 
0084     regcache_cache_only(asrc->regmap, true);
0085     regcache_mark_dirty(asrc->regmap);
0086 
0087     return 0;
0088 }
0089 
0090 static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev)
0091 {
0092     struct tegra186_asrc *asrc = dev_get_drvdata(dev);
0093     int id;
0094 
0095     regcache_cache_only(asrc->regmap, false);
0096 
0097     /*
0098      * Below sequence is recommended after a runtime PM cycle.
0099      * This otherwise leads to transfer failures. The cache
0100      * sync is done after this to restore other settings.
0101      */
0102     regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR,
0103              TEGRA186_ASRC_ARAM_START_ADDR);
0104     regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_ENB,
0105              TEGRA186_ASRC_GLOBAL_EN);
0106 
0107     regcache_sync(asrc->regmap);
0108 
0109     for (id = 0; id < TEGRA186_ASRC_STREAM_MAX; id++) {
0110         if (asrc->lane[id].ratio_source !=
0111             TEGRA186_ASRC_RATIO_SOURCE_SW)
0112             continue;
0113 
0114         regmap_write(asrc->regmap,
0115             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
0116                     id),
0117             asrc->lane[id].int_part);
0118 
0119         regmap_write(asrc->regmap,
0120             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
0121                     id),
0122             asrc->lane[id].frac_part);
0123 
0124         tegra186_asrc_lock_stream(asrc, id);
0125     }
0126 
0127     return 0;
0128 }
0129 
0130 static int tegra186_asrc_set_audio_cif(struct tegra186_asrc *asrc,
0131                        struct snd_pcm_hw_params *params,
0132                        unsigned int reg)
0133 {
0134     int channels, audio_bits;
0135     struct tegra_cif_conf cif_conf;
0136 
0137     memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
0138 
0139     channels = params_channels(params);
0140 
0141     switch (params_format(params)) {
0142     case SNDRV_PCM_FORMAT_S16_LE:
0143         audio_bits = TEGRA_ACIF_BITS_16;
0144         break;
0145     case SNDRV_PCM_FORMAT_S24_LE:
0146     case SNDRV_PCM_FORMAT_S32_LE:
0147         audio_bits = TEGRA_ACIF_BITS_32;
0148         break;
0149     default:
0150         return -EINVAL;
0151     }
0152 
0153     cif_conf.audio_ch = channels;
0154     cif_conf.client_ch = channels;
0155     cif_conf.audio_bits = audio_bits;
0156     cif_conf.client_bits = TEGRA_ACIF_BITS_24;
0157 
0158     tegra_set_cif(asrc->regmap, reg, &cif_conf);
0159 
0160     return 0;
0161 }
0162 
0163 static int tegra186_asrc_in_hw_params(struct snd_pcm_substream *substream,
0164                       struct snd_pcm_hw_params *params,
0165                       struct snd_soc_dai *dai)
0166 {
0167     struct device *dev = dai->dev;
0168     struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
0169     int ret, id = dai->id;
0170 
0171     /* Set input threshold */
0172     regmap_write(asrc->regmap,
0173              ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, dai->id),
0174              asrc->lane[id].input_thresh);
0175 
0176     ret = tegra186_asrc_set_audio_cif(asrc, params,
0177         ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, dai->id));
0178     if (ret) {
0179         dev_err(dev, "Can't set ASRC RX%d CIF: %d\n", dai->id, ret);
0180         return ret;
0181     }
0182 
0183     return ret;
0184 }
0185 
0186 static int tegra186_asrc_out_hw_params(struct snd_pcm_substream *substream,
0187                        struct snd_pcm_hw_params *params,
0188                        struct snd_soc_dai *dai)
0189 {
0190     struct device *dev = dai->dev;
0191     struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
0192     int ret, id = dai->id - 7;
0193 
0194      /* Set output threshold */
0195     regmap_write(asrc->regmap,
0196              ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, id),
0197              asrc->lane[id].output_thresh);
0198 
0199     ret = tegra186_asrc_set_audio_cif(asrc, params,
0200         ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id));
0201     if (ret) {
0202         dev_err(dev, "Can't set ASRC TX%d CIF: %d\n", id, ret);
0203         return ret;
0204     }
0205 
0206     /* Set ENABLE_HW_RATIO_COMP */
0207     if (asrc->lane[id].hwcomp_disable) {
0208         regmap_update_bits(asrc->regmap,
0209             ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
0210             TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
0211             TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_DISABLE);
0212     } else {
0213         regmap_update_bits(asrc->regmap,
0214             ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
0215             TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
0216             TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_ENABLE);
0217 
0218         regmap_write(asrc->regmap,
0219             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_COMP, id),
0220             TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE);
0221     }
0222 
0223     /* Set lock */
0224     regmap_update_bits(asrc->regmap,
0225                ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
0226                1, asrc->lane[id].ratio_source);
0227 
0228     if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_SW) {
0229         regmap_write(asrc->regmap,
0230             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
0231             asrc->lane[id].int_part);
0232         regmap_write(asrc->regmap,
0233             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
0234             asrc->lane[id].frac_part);
0235         tegra186_asrc_lock_stream(asrc, id);
0236     }
0237 
0238     return ret;
0239 }
0240 
0241 static int tegra186_asrc_get_ratio_source(struct snd_kcontrol *kcontrol,
0242                       struct snd_ctl_elem_value *ucontrol)
0243 {
0244     struct soc_enum *asrc_private =
0245         (struct soc_enum  *)kcontrol->private_value;
0246     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0247     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0248     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0249 
0250     ucontrol->value.enumerated.item[0] = asrc->lane[id].ratio_source;
0251 
0252     return 0;
0253 }
0254 
0255 static int tegra186_asrc_put_ratio_source(struct snd_kcontrol *kcontrol,
0256                       struct snd_ctl_elem_value *ucontrol)
0257 {
0258     struct soc_enum *asrc_private =
0259         (struct soc_enum  *)kcontrol->private_value;
0260     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0261     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0262     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0263     bool change = false;
0264 
0265     asrc->lane[id].ratio_source = ucontrol->value.enumerated.item[0];
0266 
0267     regmap_update_bits_check(asrc->regmap, asrc_private->reg,
0268                  TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK,
0269                  asrc->lane[id].ratio_source,
0270                  &change);
0271 
0272     return change ? 1 : 0;
0273 }
0274 
0275 static int tegra186_asrc_get_ratio_int(struct snd_kcontrol *kcontrol,
0276                        struct snd_ctl_elem_value *ucontrol)
0277 {
0278     struct soc_mixer_control *asrc_private =
0279         (struct soc_mixer_control *)kcontrol->private_value;
0280     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0281     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0282     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0283 
0284     regmap_read(asrc->regmap,
0285             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
0286             &asrc->lane[id].int_part);
0287 
0288     ucontrol->value.integer.value[0] = asrc->lane[id].int_part;
0289 
0290     return 0;
0291 }
0292 
0293 static int tegra186_asrc_put_ratio_int(struct snd_kcontrol *kcontrol,
0294                        struct snd_ctl_elem_value *ucontrol)
0295 {
0296     struct soc_mixer_control *asrc_private =
0297         (struct soc_mixer_control *)kcontrol->private_value;
0298     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0299     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0300     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0301     bool change = false;
0302 
0303     if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
0304         dev_err(cmpnt->dev,
0305             "Lane %d ratio source is ARAD, invalid SW update\n",
0306             id);
0307         return -EINVAL;
0308     }
0309 
0310     asrc->lane[id].int_part = ucontrol->value.integer.value[0];
0311 
0312     regmap_update_bits_check(asrc->regmap,
0313                  ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
0314                          id),
0315                  TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK,
0316                  asrc->lane[id].int_part, &change);
0317 
0318     tegra186_asrc_lock_stream(asrc, id);
0319 
0320     return change ? 1 : 0;
0321 }
0322 
0323 static int tegra186_asrc_get_ratio_frac(struct snd_kcontrol *kcontrol,
0324                     struct snd_ctl_elem_value *ucontrol)
0325 {
0326     struct soc_mreg_control *asrc_private =
0327         (struct soc_mreg_control *)kcontrol->private_value;
0328     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0329     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0330     unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
0331 
0332     regmap_read(asrc->regmap,
0333             ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
0334             &asrc->lane[id].frac_part);
0335 
0336     ucontrol->value.integer.value[0] = asrc->lane[id].frac_part;
0337 
0338     return 0;
0339 }
0340 
0341 static int tegra186_asrc_put_ratio_frac(struct snd_kcontrol *kcontrol,
0342                     struct snd_ctl_elem_value *ucontrol)
0343 {
0344     struct soc_mreg_control *asrc_private =
0345         (struct soc_mreg_control *)kcontrol->private_value;
0346     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0347     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0348     unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
0349     bool change = false;
0350 
0351     if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
0352         dev_err(cmpnt->dev,
0353             "Lane %d ratio source is ARAD, invalid SW update\n",
0354             id);
0355         return -EINVAL;
0356     }
0357 
0358     asrc->lane[id].frac_part = ucontrol->value.integer.value[0];
0359 
0360     regmap_update_bits_check(asrc->regmap,
0361                  ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
0362                          id),
0363                  TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
0364                  asrc->lane[id].frac_part, &change);
0365 
0366     tegra186_asrc_lock_stream(asrc, id);
0367 
0368     return change ? 1 : 0;
0369 }
0370 
0371 static int tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol *kcontrol,
0372                         struct snd_ctl_elem_value *ucontrol)
0373 {
0374     struct soc_mixer_control *asrc_private =
0375         (struct soc_mixer_control *)kcontrol->private_value;
0376     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0377     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0378     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0379 
0380     ucontrol->value.integer.value[0] = asrc->lane[id].hwcomp_disable;
0381 
0382     return 0;
0383 }
0384 
0385 static int tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol *kcontrol,
0386                         struct snd_ctl_elem_value *ucontrol)
0387 {
0388     struct soc_mixer_control *asrc_private =
0389         (struct soc_mixer_control *)kcontrol->private_value;
0390     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0391     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0392     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0393     int value = ucontrol->value.integer.value[0];
0394 
0395     if (value == asrc->lane[id].hwcomp_disable)
0396         return 0;
0397 
0398     asrc->lane[id].hwcomp_disable = value;
0399 
0400     return 1;
0401 }
0402 
0403 static int tegra186_asrc_get_input_threshold(struct snd_kcontrol *kcontrol,
0404                          struct snd_ctl_elem_value *ucontrol)
0405 {
0406     struct soc_mixer_control *asrc_private =
0407         (struct soc_mixer_control *)kcontrol->private_value;
0408     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0409     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0410     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0411 
0412     ucontrol->value.integer.value[0] = (asrc->lane[id].input_thresh & 0x3);
0413 
0414     return 0;
0415 }
0416 
0417 static int tegra186_asrc_put_input_threshold(struct snd_kcontrol *kcontrol,
0418                          struct snd_ctl_elem_value *ucontrol)
0419 {
0420     struct soc_mixer_control *asrc_private =
0421         (struct soc_mixer_control *)kcontrol->private_value;
0422     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0423     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0424     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0425     int value = (asrc->lane[id].input_thresh & ~(0x3)) |
0426             ucontrol->value.integer.value[0];
0427 
0428     if (value == asrc->lane[id].input_thresh)
0429         return 0;
0430 
0431     asrc->lane[id].input_thresh = value;
0432 
0433     return 1;
0434 }
0435 
0436 static int tegra186_asrc_get_output_threshold(struct snd_kcontrol *kcontrol,
0437                           struct snd_ctl_elem_value *ucontrol)
0438 {
0439     struct soc_mixer_control *asrc_private =
0440         (struct soc_mixer_control *)kcontrol->private_value;
0441     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0442     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0443     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0444 
0445     ucontrol->value.integer.value[0] = (asrc->lane[id].output_thresh & 0x3);
0446 
0447     return 0;
0448 }
0449 
0450 static int tegra186_asrc_put_output_threshold(struct snd_kcontrol *kcontrol,
0451                           struct snd_ctl_elem_value *ucontrol)
0452 {
0453     struct soc_mixer_control *asrc_private =
0454         (struct soc_mixer_control *)kcontrol->private_value;
0455     struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0456     struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
0457     unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
0458     int value = (asrc->lane[id].output_thresh & ~(0x3)) |
0459             ucontrol->value.integer.value[0];
0460 
0461     if (value == asrc->lane[id].output_thresh)
0462         return 0;
0463 
0464     asrc->lane[id].output_thresh = value;
0465 
0466     return 1;
0467 }
0468 
0469 static int tegra186_asrc_widget_event(struct snd_soc_dapm_widget *w,
0470                     struct snd_kcontrol *kcontrol, int event)
0471 {
0472     struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
0473     struct tegra186_asrc *asrc = dev_get_drvdata(cmpnt->dev);
0474     unsigned int id =
0475         (w->reg - TEGRA186_ASRC_ENABLE) / TEGRA186_ASRC_STREAM_STRIDE;
0476 
0477     regmap_write(asrc->regmap,
0478              ASRC_STREAM_REG(TEGRA186_ASRC_SOFT_RESET, id),
0479              0x1);
0480 
0481     return 0;
0482 }
0483 
0484 static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops = {
0485     .hw_params  = tegra186_asrc_in_hw_params,
0486 };
0487 
0488 static const struct snd_soc_dai_ops tegra186_asrc_out_dai_ops = {
0489     .hw_params  = tegra186_asrc_out_hw_params,
0490 };
0491 
0492 #define IN_DAI(id)                      \
0493     {                           \
0494         .name = "ASRC-RX-CIF"#id,           \
0495         .playback = {                   \
0496             .stream_name = "RX" #id "-CIF-Playback",\
0497             .channels_min = 1,          \
0498             .channels_max = 12,         \
0499             .rates = SNDRV_PCM_RATE_8000_192000,    \
0500             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0501                 SNDRV_PCM_FMTBIT_S16_LE |   \
0502                 SNDRV_PCM_FMTBIT_S24_LE |   \
0503                 SNDRV_PCM_FMTBIT_S32_LE,    \
0504         },                      \
0505         .capture = {                    \
0506             .stream_name = "RX" #id "-CIF-Capture", \
0507             .channels_min = 1,          \
0508             .channels_max = 12,         \
0509             .rates = SNDRV_PCM_RATE_8000_192000,    \
0510             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0511                 SNDRV_PCM_FMTBIT_S16_LE |   \
0512                 SNDRV_PCM_FMTBIT_S24_LE |   \
0513                 SNDRV_PCM_FMTBIT_S32_LE,    \
0514         },                      \
0515         .ops = &tegra186_asrc_in_dai_ops,       \
0516     }
0517 
0518 #define OUT_DAI(id)                     \
0519     {                           \
0520         .name = "ASRC-TX-CIF"#id,           \
0521         .playback = {                   \
0522             .stream_name = "TX" #id "-CIF-Playback",\
0523             .channels_min = 1,          \
0524             .channels_max = 12,         \
0525             .rates = SNDRV_PCM_RATE_8000_192000,    \
0526             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0527                 SNDRV_PCM_FMTBIT_S16_LE |   \
0528                 SNDRV_PCM_FMTBIT_S24_LE |   \
0529                 SNDRV_PCM_FMTBIT_S32_LE,    \
0530         },                      \
0531         .capture = {                    \
0532             .stream_name = "TX" #id "-CIF-Capture", \
0533             .channels_min = 1,          \
0534             .channels_max = 12,         \
0535             .rates = SNDRV_PCM_RATE_8000_192000,    \
0536             .formats = SNDRV_PCM_FMTBIT_S8 |    \
0537                 SNDRV_PCM_FMTBIT_S16_LE |   \
0538                 SNDRV_PCM_FMTBIT_S24_LE |   \
0539                 SNDRV_PCM_FMTBIT_S32_LE,    \
0540         },                      \
0541         .ops = &tegra186_asrc_out_dai_ops,      \
0542     }
0543 
0544 static struct snd_soc_dai_driver tegra186_asrc_dais[] = {
0545     /* ASRC Input */
0546     IN_DAI(1),
0547     IN_DAI(2),
0548     IN_DAI(3),
0549     IN_DAI(4),
0550     IN_DAI(5),
0551     IN_DAI(6),
0552     IN_DAI(7),
0553     /* ASRC Output */
0554     OUT_DAI(1),
0555     OUT_DAI(2),
0556     OUT_DAI(3),
0557     OUT_DAI(4),
0558     OUT_DAI(5),
0559     OUT_DAI(6),
0560 };
0561 
0562 static const struct snd_soc_dapm_widget tegra186_asrc_widgets[] = {
0563     SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
0564     SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
0565     SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
0566     SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, SND_SOC_NOPM, 0, 0),
0567     SND_SOC_DAPM_AIF_IN("RX5", NULL, 0, SND_SOC_NOPM, 0, 0),
0568     SND_SOC_DAPM_AIF_IN("RX6", NULL, 0, SND_SOC_NOPM, 0, 0),
0569     SND_SOC_DAPM_AIF_IN("RX7", NULL, 0, SND_SOC_NOPM, 0, 0),
0570 
0571     SND_SOC_DAPM_AIF_OUT_E("TX1", NULL, 0,
0572                    ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 0),
0573                    TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
0574                    tegra186_asrc_widget_event,
0575                    SND_SOC_DAPM_POST_PMD),
0576 
0577     SND_SOC_DAPM_AIF_OUT_E("TX2", NULL, 0,
0578                    ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 1),
0579                    TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
0580                    tegra186_asrc_widget_event,
0581                    SND_SOC_DAPM_POST_PMD),
0582 
0583     SND_SOC_DAPM_AIF_OUT_E("TX3", NULL, 0,
0584                    ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 2),
0585                    TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
0586                    tegra186_asrc_widget_event,
0587                    SND_SOC_DAPM_POST_PMD),
0588 
0589     SND_SOC_DAPM_AIF_OUT_E("TX4", NULL, 0,
0590                    ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 3),
0591                    TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
0592                    tegra186_asrc_widget_event,
0593                    SND_SOC_DAPM_POST_PMD),
0594 
0595     SND_SOC_DAPM_AIF_OUT_E("TX5", NULL, 0,
0596                    ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 4),
0597                    TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
0598                    tegra186_asrc_widget_event,
0599                    SND_SOC_DAPM_POST_PMD),
0600 
0601     SND_SOC_DAPM_AIF_OUT_E("TX6", NULL, 0,
0602                    ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 5),
0603                    TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
0604                    tegra186_asrc_widget_event,
0605                    SND_SOC_DAPM_POST_PMD),
0606 
0607     SND_SOC_DAPM_SPK("Depacketizer", NULL),
0608 };
0609 
0610 #define ASRC_STREAM_ROUTE(id, sname)                       \
0611     { "RX" #id " XBAR-" sname,      NULL,   "RX" #id " XBAR-TX" },     \
0612     { "RX" #id "-CIF-" sname,       NULL,   "RX" #id " XBAR-" sname }, \
0613     { "RX" #id,                     NULL,   "RX" #id "-CIF-" sname },  \
0614     { "TX" #id,         NULL,   "RX" #id },        \
0615     { "TX" #id "-CIF-" sname,       NULL,   "TX" #id },        \
0616     { "TX" #id " XBAR-" sname,      NULL,   "TX" #id "-CIF-" sname },  \
0617     { "TX" #id " XBAR-RX",          NULL,   "TX" #id " XBAR-" sname },
0618 
0619 #define ASRC_ROUTE(id)                             \
0620     ASRC_STREAM_ROUTE(id, "Playback")                  \
0621     ASRC_STREAM_ROUTE(id, "Capture")
0622 
0623 #define ASRC_RATIO_ROUTE(sname)                        \
0624     { "RX7 XBAR-" sname,        NULL,   "RX7 XBAR-TX" },       \
0625     { "RX7-CIF-" sname,     NULL,   "RX7 XBAR-" sname },       \
0626     { "RX7",            NULL,   "RX7-CIF-" sname },    \
0627     { "Depacketizer",       NULL,   "RX7" },
0628 
0629 static const struct snd_soc_dapm_route tegra186_asrc_routes[] = {
0630     ASRC_ROUTE(1)
0631     ASRC_ROUTE(2)
0632     ASRC_ROUTE(3)
0633     ASRC_ROUTE(4)
0634     ASRC_ROUTE(5)
0635     ASRC_ROUTE(6)
0636     ASRC_RATIO_ROUTE("Playback")
0637     ASRC_RATIO_ROUTE("Capture")
0638 };
0639 
0640 static const char * const tegra186_asrc_ratio_source_text[] = {
0641     "ARAD",
0642     "SW",
0643 };
0644 
0645 #define ASRC_SOURCE_DECL(name, id)                  \
0646     static const struct soc_enum name =             \
0647         SOC_ENUM_SINGLE(ASRC_STREAM_SOURCE_SELECT(id),      \
0648                 0, 2, tegra186_asrc_ratio_source_text)
0649 
0650 ASRC_SOURCE_DECL(src_select1, 0);
0651 ASRC_SOURCE_DECL(src_select2, 1);
0652 ASRC_SOURCE_DECL(src_select3, 2);
0653 ASRC_SOURCE_DECL(src_select4, 3);
0654 ASRC_SOURCE_DECL(src_select5, 4);
0655 ASRC_SOURCE_DECL(src_select6, 5);
0656 
0657 #define SOC_SINGLE_EXT_FRAC(xname, xregbase, xmax, xget, xput)      \
0658 {                                   \
0659     .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,               \
0660     .name   = (xname),                      \
0661     .info   = snd_soc_info_xr_sx,                   \
0662     .get    = xget,                         \
0663     .put    = xput,                         \
0664                                     \
0665     .private_value = (unsigned long)&(struct soc_mreg_control)  \
0666     {                               \
0667         .regbase    = xregbase,             \
0668         .regcount   = 1,                    \
0669         .nbits      = 32,                   \
0670         .invert     = 0,                    \
0671         .min        = 0,                    \
0672         .max        = xmax                  \
0673     }                               \
0674 }
0675 
0676 static const struct snd_kcontrol_new tegra186_asrc_controls[] = {
0677     /* Controls for integer part of ratio */
0678     SOC_SINGLE_EXT("Ratio1 Integer Part",
0679                ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 0),
0680                0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
0681                tegra186_asrc_get_ratio_int,
0682                tegra186_asrc_put_ratio_int),
0683 
0684     SOC_SINGLE_EXT("Ratio2 Integer Part",
0685                ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 1),
0686                0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
0687                tegra186_asrc_get_ratio_int,
0688                tegra186_asrc_put_ratio_int),
0689 
0690     SOC_SINGLE_EXT("Ratio3 Integer Part",
0691                ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 2),
0692                0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
0693                tegra186_asrc_get_ratio_int,
0694                tegra186_asrc_put_ratio_int),
0695 
0696     SOC_SINGLE_EXT("Ratio4 Integer Part",
0697                ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 3),
0698                0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
0699                tegra186_asrc_get_ratio_int,
0700                tegra186_asrc_put_ratio_int),
0701 
0702     SOC_SINGLE_EXT("Ratio5 Integer Part",
0703                ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 4),
0704                0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
0705                tegra186_asrc_get_ratio_int,
0706                tegra186_asrc_put_ratio_int),
0707 
0708     SOC_SINGLE_EXT("Ratio6 Integer Part",
0709                ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 5),
0710                0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
0711                tegra186_asrc_get_ratio_int,
0712                tegra186_asrc_put_ratio_int),
0713 
0714     /* Controls for fractional part of ratio */
0715     SOC_SINGLE_EXT_FRAC("Ratio1 Fractional Part",
0716                 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 0),
0717                 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
0718                 tegra186_asrc_get_ratio_frac,
0719                 tegra186_asrc_put_ratio_frac),
0720 
0721     SOC_SINGLE_EXT_FRAC("Ratio2 Fractional Part",
0722                 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 1),
0723                 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
0724                 tegra186_asrc_get_ratio_frac,
0725                 tegra186_asrc_put_ratio_frac),
0726 
0727     SOC_SINGLE_EXT_FRAC("Ratio3 Fractional Part",
0728                 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 2),
0729                 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
0730                 tegra186_asrc_get_ratio_frac,
0731                 tegra186_asrc_put_ratio_frac),
0732 
0733     SOC_SINGLE_EXT_FRAC("Ratio4 Fractional Part",
0734                 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 3),
0735                 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
0736                 tegra186_asrc_get_ratio_frac,
0737                 tegra186_asrc_put_ratio_frac),
0738 
0739     SOC_SINGLE_EXT_FRAC("Ratio5 Fractional Part",
0740                 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 4),
0741                 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
0742                 tegra186_asrc_get_ratio_frac,
0743                 tegra186_asrc_put_ratio_frac),
0744 
0745     SOC_SINGLE_EXT_FRAC("Ratio6 Fractional Part",
0746                 ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 5),
0747                 TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
0748                 tegra186_asrc_get_ratio_frac,
0749                 tegra186_asrc_put_ratio_frac),
0750 
0751     /* Source of ratio provider */
0752     SOC_ENUM_EXT("Ratio1 Source", src_select1,
0753              tegra186_asrc_get_ratio_source,
0754              tegra186_asrc_put_ratio_source),
0755 
0756     SOC_ENUM_EXT("Ratio2 Source", src_select2,
0757              tegra186_asrc_get_ratio_source,
0758              tegra186_asrc_put_ratio_source),
0759 
0760     SOC_ENUM_EXT("Ratio3 Source", src_select3,
0761              tegra186_asrc_get_ratio_source,
0762              tegra186_asrc_put_ratio_source),
0763 
0764     SOC_ENUM_EXT("Ratio4 Source", src_select4,
0765              tegra186_asrc_get_ratio_source,
0766              tegra186_asrc_put_ratio_source),
0767 
0768     SOC_ENUM_EXT("Ratio5 Source", src_select5,
0769              tegra186_asrc_get_ratio_source,
0770              tegra186_asrc_put_ratio_source),
0771 
0772     SOC_ENUM_EXT("Ratio6 Source", src_select6,
0773              tegra186_asrc_get_ratio_source,
0774              tegra186_asrc_put_ratio_source),
0775 
0776     /* Disable HW managed overflow/underflow issue at input and output */
0777     SOC_SINGLE_EXT("Stream1 HW Component Disable",
0778                ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 0), 0, 1, 0,
0779                tegra186_asrc_get_hwcomp_disable,
0780                tegra186_asrc_put_hwcomp_disable),
0781 
0782     SOC_SINGLE_EXT("Stream2 HW Component Disable",
0783                ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 1), 0, 1, 0,
0784                tegra186_asrc_get_hwcomp_disable,
0785                tegra186_asrc_put_hwcomp_disable),
0786 
0787     SOC_SINGLE_EXT("Stream3 HW Component Disable",
0788                ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 2), 0, 1, 0,
0789                tegra186_asrc_get_hwcomp_disable,
0790                tegra186_asrc_put_hwcomp_disable),
0791 
0792     SOC_SINGLE_EXT("Stream4 HW Component Disable",
0793                ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 3), 0, 1, 0,
0794                tegra186_asrc_get_hwcomp_disable,
0795                tegra186_asrc_put_hwcomp_disable),
0796 
0797     SOC_SINGLE_EXT("Stream5 HW Component Disable",
0798                ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 4), 0, 1, 0,
0799                tegra186_asrc_get_hwcomp_disable,
0800                tegra186_asrc_put_hwcomp_disable),
0801 
0802     SOC_SINGLE_EXT("Stream6 HW Component Disable",
0803                ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 5), 0, 1, 0,
0804                tegra186_asrc_get_hwcomp_disable,
0805                tegra186_asrc_put_hwcomp_disable),
0806 
0807     /* Input threshold for watermark fields */
0808     SOC_SINGLE_EXT("Stream1 Input Threshold",
0809                ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 0), 0, 3, 0,
0810                tegra186_asrc_get_input_threshold,
0811                tegra186_asrc_put_input_threshold),
0812 
0813     SOC_SINGLE_EXT("Stream2 Input Threshold",
0814                ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 1), 0, 3, 0,
0815                tegra186_asrc_get_input_threshold,
0816                tegra186_asrc_put_input_threshold),
0817 
0818     SOC_SINGLE_EXT("Stream3 Input Threshold",
0819                ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 2), 0, 3, 0,
0820                tegra186_asrc_get_input_threshold,
0821                tegra186_asrc_put_input_threshold),
0822 
0823     SOC_SINGLE_EXT("Stream4 Input Threshold",
0824                ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 3), 0, 3, 0,
0825                tegra186_asrc_get_input_threshold,
0826                tegra186_asrc_put_input_threshold),
0827 
0828     SOC_SINGLE_EXT("Stream5 Input Threshold",
0829                ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
0830                tegra186_asrc_get_input_threshold,
0831                tegra186_asrc_put_input_threshold),
0832 
0833     SOC_SINGLE_EXT("Stream6 Input Threshold",
0834                ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
0835                tegra186_asrc_get_input_threshold,
0836                tegra186_asrc_put_input_threshold),
0837 
0838     /* Output threshold for watermark fields */
0839     SOC_SINGLE_EXT("Stream1 Output Threshold",
0840                ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 0), 0, 3, 0,
0841                tegra186_asrc_get_output_threshold,
0842                tegra186_asrc_put_output_threshold),
0843 
0844     SOC_SINGLE_EXT("Stream2 Output Threshold",
0845                ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 1), 0, 3, 0,
0846                tegra186_asrc_get_output_threshold,
0847                tegra186_asrc_put_output_threshold),
0848 
0849     SOC_SINGLE_EXT("Stream3 Output Threshold",
0850                ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 2), 0, 3, 0,
0851                tegra186_asrc_get_output_threshold,
0852                tegra186_asrc_put_output_threshold),
0853 
0854     SOC_SINGLE_EXT("Stream4 Output Threshold",
0855                ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 3), 0, 3, 0,
0856                tegra186_asrc_get_output_threshold,
0857                tegra186_asrc_put_output_threshold),
0858 
0859     SOC_SINGLE_EXT("Stream5 Output Threshold",
0860                ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 4), 0, 3, 0,
0861                tegra186_asrc_get_output_threshold,
0862                tegra186_asrc_put_output_threshold),
0863 
0864     SOC_SINGLE_EXT("Stream6 Output Threshold",
0865                ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 5), 0, 3, 0,
0866                tegra186_asrc_get_output_threshold,
0867                tegra186_asrc_put_output_threshold),
0868 };
0869 
0870 static const struct snd_soc_component_driver tegra186_asrc_cmpnt = {
0871     .dapm_widgets       = tegra186_asrc_widgets,
0872     .num_dapm_widgets   = ARRAY_SIZE(tegra186_asrc_widgets),
0873     .dapm_routes        = tegra186_asrc_routes,
0874     .num_dapm_routes    = ARRAY_SIZE(tegra186_asrc_routes),
0875     .controls       = tegra186_asrc_controls,
0876     .num_controls       = ARRAY_SIZE(tegra186_asrc_controls),
0877 };
0878 
0879 static bool tegra186_asrc_wr_reg(struct device *dev, unsigned int reg)
0880 {
0881     if (reg < TEGRA186_ASRC_STREAM_LIMIT)
0882         reg %= TEGRA186_ASRC_STREAM_STRIDE;
0883 
0884     switch (reg) {
0885     case TEGRA186_ASRC_CFG ... TEGRA186_ASRC_RATIO_COMP:
0886     case TEGRA186_ASRC_RX_CIF_CTRL:
0887     case TEGRA186_ASRC_TX_CIF_CTRL:
0888     case TEGRA186_ASRC_ENABLE:
0889     case TEGRA186_ASRC_SOFT_RESET:
0890     case TEGRA186_ASRC_GLOBAL_ENB ... TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL:
0891     case TEGRA186_ASRC_GLOBAL_INT_MASK ... TEGRA186_ASRC_GLOBAL_INT_CLEAR:
0892     case TEGRA186_ASRC_GLOBAL_APR_CTRL ... TEGRA186_ASRC_CYA:
0893         return true;
0894     default:
0895         return false;
0896     }
0897 }
0898 
0899 static bool tegra186_asrc_rd_reg(struct device *dev, unsigned int reg)
0900 {
0901     if (reg < TEGRA186_ASRC_STREAM_LIMIT)
0902         reg %= TEGRA186_ASRC_STREAM_STRIDE;
0903 
0904     if (tegra186_asrc_wr_reg(dev, reg))
0905         return true;
0906 
0907     switch (reg) {
0908     case TEGRA186_ASRC_RX_STATUS:
0909     case TEGRA186_ASRC_TX_STATUS:
0910     case TEGRA186_ASRC_STATUS ... TEGRA186_ASRC_OUTSAMPLEBUF_CFG:
0911     case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
0912     case TEGRA186_ASRC_GLOBAL_STATUS ... TEGRA186_ASRC_GLOBAL_INT_STATUS:
0913     case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
0914         return true;
0915     default:
0916         return false;
0917     }
0918 }
0919 
0920 static bool tegra186_asrc_volatile_reg(struct device *dev, unsigned int reg)
0921 {
0922     if (reg < TEGRA186_ASRC_STREAM_LIMIT)
0923         reg %= TEGRA186_ASRC_STREAM_STRIDE;
0924 
0925     switch (reg) {
0926     case TEGRA186_ASRC_RX_STATUS:
0927     case TEGRA186_ASRC_TX_STATUS:
0928     case TEGRA186_ASRC_SOFT_RESET:
0929     case TEGRA186_ASRC_RATIO_INT_PART:
0930     case TEGRA186_ASRC_RATIO_FRAC_PART:
0931     case TEGRA186_ASRC_STATUS:
0932     case TEGRA186_ASRC_RATIO_LOCK_STATUS:
0933     case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
0934     case TEGRA186_ASRC_GLOBAL_SOFT_RESET:
0935     case TEGRA186_ASRC_GLOBAL_STATUS:
0936     case TEGRA186_ASRC_GLOBAL_STREAM_ENABLE_STATUS:
0937     case TEGRA186_ASRC_GLOBAL_INT_STATUS:
0938     case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
0939         return true;
0940     default:
0941         return false;
0942     }
0943 }
0944 
0945 static const struct regmap_config tegra186_asrc_regmap_config = {
0946     .reg_bits       = 32,
0947     .reg_stride     = 4,
0948     .val_bits       = 32,
0949     .max_register       = TEGRA186_ASRC_CYA,
0950     .writeable_reg      = tegra186_asrc_wr_reg,
0951     .readable_reg       = tegra186_asrc_rd_reg,
0952     .volatile_reg       = tegra186_asrc_volatile_reg,
0953     .reg_defaults       = tegra186_asrc_reg_defaults,
0954     .num_reg_defaults   = ARRAY_SIZE(tegra186_asrc_reg_defaults),
0955     .cache_type     = REGCACHE_FLAT,
0956 };
0957 
0958 static const struct of_device_id tegra186_asrc_of_match[] = {
0959     { .compatible = "nvidia,tegra186-asrc" },
0960     {},
0961 };
0962 MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
0963 
0964 static int tegra186_asrc_platform_probe(struct platform_device *pdev)
0965 {
0966     struct device *dev = &pdev->dev;
0967     struct tegra186_asrc *asrc;
0968     void __iomem *regs;
0969     unsigned int i;
0970     int err;
0971 
0972     asrc = devm_kzalloc(dev, sizeof(*asrc), GFP_KERNEL);
0973     if (!asrc)
0974         return -ENOMEM;
0975 
0976     dev_set_drvdata(dev, asrc);
0977 
0978     regs = devm_platform_ioremap_resource(pdev, 0);
0979     if (IS_ERR(regs))
0980         return PTR_ERR(regs);
0981 
0982     asrc->regmap = devm_regmap_init_mmio(dev, regs,
0983                          &tegra186_asrc_regmap_config);
0984     if (IS_ERR(asrc->regmap)) {
0985         dev_err(dev, "regmap init failed\n");
0986         return PTR_ERR(asrc->regmap);
0987     }
0988 
0989     regcache_cache_only(asrc->regmap, true);
0990 
0991     regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_CFG,
0992              TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION);
0993 
0994     /* Initialize default output srate */
0995     for (i = 0; i < TEGRA186_ASRC_STREAM_MAX; i++) {
0996         asrc->lane[i].ratio_source = TEGRA186_ASRC_RATIO_SOURCE_SW;
0997         asrc->lane[i].int_part = 1;
0998         asrc->lane[i].frac_part = 0;
0999         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");