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