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