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