0001
0002
0003
0004
0005
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
0099
0100
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
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
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
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
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
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
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
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
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
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
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
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
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
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");