1 // SPDX-License-Identifier: GPL-2.0-only 2 // SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. 3 // All rights reserved. 4 // 5 // tegra210_adx.c - Tegra210 ADX driver 6 7 #include <linux/clk.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 "tegra210_adx.h" 21 #include "tegra_cif.h" 22 23 static const struct reg_default tegra210_adx_reg_defaults[] = { 24 { TEGRA210_ADX_RX_INT_MASK, 0x00000001}, 25 { TEGRA210_ADX_RX_CIF_CTRL, 0x00007000}, 26 { TEGRA210_ADX_TX_INT_MASK, 0x0000000f }, 27 { TEGRA210_ADX_TX1_CIF_CTRL, 0x00007000}, 28 { TEGRA210_ADX_TX2_CIF_CTRL, 0x00007000}, 29 { TEGRA210_ADX_TX3_CIF_CTRL, 0x00007000}, 30 { TEGRA210_ADX_TX4_CIF_CTRL, 0x00007000}, 31 { TEGRA210_ADX_CG, 0x1}, 32 { TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000}, 33 }; 34 35 static void tegra210_adx_write_map_ram(struct tegra210_adx *adx) 36 { 37 int i; 38 39 regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL, 40 TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN | 41 TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN | 42 TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE); 43 44 for (i = 0; i < TEGRA210_ADX_RAM_DEPTH; i++) 45 regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA, 46 adx->map[i]); 47 48 regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN0, adx->byte_mask[0]); 49 regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN1, adx->byte_mask[1]); 50 } 51 52 static int tegra210_adx_startup(struct snd_pcm_substream *substream, 53 struct snd_soc_dai *dai) 54 { 55 struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai); 56 unsigned int val; 57 int err; 58 59 /* Ensure if ADX status is disabled */ 60 err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS, 61 val, !(val & 0x1), 10, 10000); 62 if (err < 0) { 63 dev_err(dai->dev, "failed to stop ADX, err = %d\n", err); 64 return err; 65 } 66 67 /* 68 * Soft Reset: Below performs module soft reset which clears 69 * all FSM logic, flushes flow control of FIFO and resets the 70 * state register. It also brings module back to disabled 71 * state (without flushing the data in the pipe). 72 */ 73 regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET, 74 TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK, 75 TEGRA210_ADX_SOFT_RESET_SOFT_EN); 76 77 err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET, 78 val, !(val & 0x1), 10, 10000); 79 if (err < 0) { 80 dev_err(dai->dev, "failed to reset ADX, err = %d\n", err); 81 return err; 82 } 83 84 return 0; 85 } 86 87 static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev) 88 { 89 struct tegra210_adx *adx = dev_get_drvdata(dev); 90 91 regcache_cache_only(adx->regmap, true); 92 regcache_mark_dirty(adx->regmap); 93 94 return 0; 95 } 96 97 static int __maybe_unused tegra210_adx_runtime_resume(struct device *dev) 98 { 99 struct tegra210_adx *adx = dev_get_drvdata(dev); 100 101 regcache_cache_only(adx->regmap, false); 102 regcache_sync(adx->regmap); 103 104 tegra210_adx_write_map_ram(adx); 105 106 return 0; 107 } 108 109 static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai, 110 unsigned int channels, 111 snd_pcm_format_t format, 112 unsigned int reg) 113 { 114 struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai); 115 struct tegra_cif_conf cif_conf; 116 int audio_bits; 117 118 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); 119 120 if (channels < 1 || channels > 16) 121 return -EINVAL; 122 123 switch (format) { 124 case SNDRV_PCM_FORMAT_S8: 125 audio_bits = TEGRA_ACIF_BITS_8; 126 break; 127 case SNDRV_PCM_FORMAT_S16_LE: 128 audio_bits = TEGRA_ACIF_BITS_16; 129 break; 130 case SNDRV_PCM_FORMAT_S24_LE: 131 case SNDRV_PCM_FORMAT_S32_LE: 132 audio_bits = TEGRA_ACIF_BITS_32; 133 break; 134 default: 135 return -EINVAL; 136 } 137 138 cif_conf.audio_ch = channels; 139 cif_conf.client_ch = channels; 140 cif_conf.audio_bits = audio_bits; 141 cif_conf.client_bits = audio_bits; 142 143 tegra_set_cif(adx->regmap, reg, &cif_conf); 144 145 return 0; 146 } 147 148 static int tegra210_adx_out_hw_params(struct snd_pcm_substream *substream, 149 struct snd_pcm_hw_params *params, 150 struct snd_soc_dai *dai) 151 { 152 return tegra210_adx_set_audio_cif(dai, params_channels(params), 153 params_format(params), 154 TEGRA210_ADX_TX1_CIF_CTRL + ((dai->id - 1) * TEGRA210_ADX_AUDIOCIF_CH_STRIDE)); 155 } 156 157 static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream, 158 struct snd_pcm_hw_params *params, 159 struct snd_soc_dai *dai) 160 { 161 return tegra210_adx_set_audio_cif(dai, params_channels(params), 162 params_format(params), 163 TEGRA210_ADX_RX_CIF_CTRL); 164 } 165 166 static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol, 167 struct snd_ctl_elem_value *ucontrol) 168 { 169 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 170 struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt); 171 struct soc_mixer_control *mc; 172 unsigned char *bytes_map = (unsigned char *)&adx->map; 173 int enabled; 174 175 mc = (struct soc_mixer_control *)kcontrol->private_value; 176 enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32)); 177 178 /* 179 * TODO: Simplify this logic to just return from bytes_map[] 180 * 181 * Presently below is required since bytes_map[] is 182 * tightly packed and cannot store the control value of 256. 183 * Byte mask state is used to know if 256 needs to be returned. 184 * Note that for control value of 256, the put() call stores 0 185 * in the bytes_map[] and disables the corresponding bit in 186 * byte_mask[]. 187 */ 188 if (enabled) 189 ucontrol->value.integer.value[0] = bytes_map[mc->reg]; 190 else 191 ucontrol->value.integer.value[0] = 256; 192 193 return 0; 194 } 195 196 static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol, 197 struct snd_ctl_elem_value *ucontrol) 198 { 199 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 200 struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt); 201 unsigned char *bytes_map = (unsigned char *)&adx->map; 202 int value = ucontrol->value.integer.value[0]; 203 struct soc_mixer_control *mc = 204 (struct soc_mixer_control *)kcontrol->private_value; 205 unsigned int mask_val = adx->byte_mask[mc->reg / 32]; 206 207 if (value >= 0 && value <= 255) 208 mask_val |= (1 << (mc->reg % 32)); 209 else 210 mask_val &= ~(1 << (mc->reg % 32)); 211 212 if (mask_val == adx->byte_mask[mc->reg / 32]) 213 return 0; 214 215 /* Update byte map and slot */ 216 bytes_map[mc->reg] = value % 256; 217 adx->byte_mask[mc->reg / 32] = mask_val; 218 219 return 1; 220 } 221 222 static const struct snd_soc_dai_ops tegra210_adx_in_dai_ops = { 223 .hw_params = tegra210_adx_in_hw_params, 224 .startup = tegra210_adx_startup, 225 }; 226 227 static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { 228 .hw_params = tegra210_adx_out_hw_params, 229 }; 230 231 #define IN_DAI \ 232 { \ 233 .name = "ADX-RX-CIF", \ 234 .playback = { \ 235 .stream_name = "RX-CIF-Playback", \ 236 .channels_min = 1, \ 237 .channels_max = 16, \ 238 .rates = SNDRV_PCM_RATE_8000_192000, \ 239 .formats = SNDRV_PCM_FMTBIT_S8 | \ 240 SNDRV_PCM_FMTBIT_S16_LE | \ 241 SNDRV_PCM_FMTBIT_S24_LE | \ 242 SNDRV_PCM_FMTBIT_S32_LE, \ 243 }, \ 244 .capture = { \ 245 .stream_name = "RX-CIF-Capture", \ 246 .channels_min = 1, \ 247 .channels_max = 16, \ 248 .rates = SNDRV_PCM_RATE_8000_192000, \ 249 .formats = SNDRV_PCM_FMTBIT_S8 | \ 250 SNDRV_PCM_FMTBIT_S16_LE | \ 251 SNDRV_PCM_FMTBIT_S24_LE | \ 252 SNDRV_PCM_FMTBIT_S32_LE, \ 253 }, \ 254 .ops = &tegra210_adx_in_dai_ops, \ 255 } 256 257 #define OUT_DAI(id) \ 258 { \ 259 .name = "ADX-TX" #id "-CIF", \ 260 .playback = { \ 261 .stream_name = "TX" #id "-CIF-Playback",\ 262 .channels_min = 1, \ 263 .channels_max = 16, \ 264 .rates = SNDRV_PCM_RATE_8000_192000, \ 265 .formats = SNDRV_PCM_FMTBIT_S8 | \ 266 SNDRV_PCM_FMTBIT_S16_LE | \ 267 SNDRV_PCM_FMTBIT_S16_LE | \ 268 SNDRV_PCM_FMTBIT_S32_LE, \ 269 }, \ 270 .capture = { \ 271 .stream_name = "TX" #id "-CIF-Capture", \ 272 .channels_min = 1, \ 273 .channels_max = 16, \ 274 .rates = SNDRV_PCM_RATE_8000_192000, \ 275 .formats = SNDRV_PCM_FMTBIT_S8 | \ 276 SNDRV_PCM_FMTBIT_S16_LE | \ 277 SNDRV_PCM_FMTBIT_S16_LE | \ 278 SNDRV_PCM_FMTBIT_S32_LE, \ 279 }, \ 280 .ops = &tegra210_adx_out_dai_ops, \ 281 } 282 283 static struct snd_soc_dai_driver tegra210_adx_dais[] = { 284 IN_DAI, 285 OUT_DAI(1), 286 OUT_DAI(2), 287 OUT_DAI(3), 288 OUT_DAI(4), 289 }; 290 291 static const struct snd_soc_dapm_widget tegra210_adx_widgets[] = { 292 SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA210_ADX_ENABLE, 293 TEGRA210_ADX_ENABLE_SHIFT, 0), 294 SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_ADX_CTRL, 0, 0), 295 SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_ADX_CTRL, 1, 0), 296 SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_ADX_CTRL, 2, 0), 297 SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_ADX_CTRL, 3, 0), 298 }; 299 300 #define STREAM_ROUTES(id, sname) \ 301 { "XBAR-" sname, NULL, "XBAR-TX" }, \ 302 { "RX-CIF-" sname, NULL, "XBAR-" sname }, \ 303 { "RX", NULL, "RX-CIF-" sname }, \ 304 { "TX" #id, NULL, "RX" }, \ 305 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \ 306 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \ 307 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname } 308 309 #define ADX_ROUTES(id) \ 310 STREAM_ROUTES(id, "Playback"), \ 311 STREAM_ROUTES(id, "Capture") 312 313 #define STREAM_ROUTES(id, sname) \ 314 { "XBAR-" sname, NULL, "XBAR-TX" }, \ 315 { "RX-CIF-" sname, NULL, "XBAR-" sname }, \ 316 { "RX", NULL, "RX-CIF-" sname }, \ 317 { "TX" #id, NULL, "RX" }, \ 318 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \ 319 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \ 320 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname } 321 322 #define ADX_ROUTES(id) \ 323 STREAM_ROUTES(id, "Playback"), \ 324 STREAM_ROUTES(id, "Capture") 325 326 static const struct snd_soc_dapm_route tegra210_adx_routes[] = { 327 ADX_ROUTES(1), 328 ADX_ROUTES(2), 329 ADX_ROUTES(3), 330 ADX_ROUTES(4), 331 }; 332 333 #define TEGRA210_ADX_BYTE_MAP_CTRL(reg) \ 334 SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0, \ 335 tegra210_adx_get_byte_map, \ 336 tegra210_adx_put_byte_map) 337 338 static struct snd_kcontrol_new tegra210_adx_controls[] = { 339 TEGRA210_ADX_BYTE_MAP_CTRL(0), 340 TEGRA210_ADX_BYTE_MAP_CTRL(1), 341 TEGRA210_ADX_BYTE_MAP_CTRL(2), 342 TEGRA210_ADX_BYTE_MAP_CTRL(3), 343 TEGRA210_ADX_BYTE_MAP_CTRL(4), 344 TEGRA210_ADX_BYTE_MAP_CTRL(5), 345 TEGRA210_ADX_BYTE_MAP_CTRL(6), 346 TEGRA210_ADX_BYTE_MAP_CTRL(7), 347 TEGRA210_ADX_BYTE_MAP_CTRL(8), 348 TEGRA210_ADX_BYTE_MAP_CTRL(9), 349 TEGRA210_ADX_BYTE_MAP_CTRL(10), 350 TEGRA210_ADX_BYTE_MAP_CTRL(11), 351 TEGRA210_ADX_BYTE_MAP_CTRL(12), 352 TEGRA210_ADX_BYTE_MAP_CTRL(13), 353 TEGRA210_ADX_BYTE_MAP_CTRL(14), 354 TEGRA210_ADX_BYTE_MAP_CTRL(15), 355 TEGRA210_ADX_BYTE_MAP_CTRL(16), 356 TEGRA210_ADX_BYTE_MAP_CTRL(17), 357 TEGRA210_ADX_BYTE_MAP_CTRL(18), 358 TEGRA210_ADX_BYTE_MAP_CTRL(19), 359 TEGRA210_ADX_BYTE_MAP_CTRL(20), 360 TEGRA210_ADX_BYTE_MAP_CTRL(21), 361 TEGRA210_ADX_BYTE_MAP_CTRL(22), 362 TEGRA210_ADX_BYTE_MAP_CTRL(23), 363 TEGRA210_ADX_BYTE_MAP_CTRL(24), 364 TEGRA210_ADX_BYTE_MAP_CTRL(25), 365 TEGRA210_ADX_BYTE_MAP_CTRL(26), 366 TEGRA210_ADX_BYTE_MAP_CTRL(27), 367 TEGRA210_ADX_BYTE_MAP_CTRL(28), 368 TEGRA210_ADX_BYTE_MAP_CTRL(29), 369 TEGRA210_ADX_BYTE_MAP_CTRL(30), 370 TEGRA210_ADX_BYTE_MAP_CTRL(31), 371 TEGRA210_ADX_BYTE_MAP_CTRL(32), 372 TEGRA210_ADX_BYTE_MAP_CTRL(33), 373 TEGRA210_ADX_BYTE_MAP_CTRL(34), 374 TEGRA210_ADX_BYTE_MAP_CTRL(35), 375 TEGRA210_ADX_BYTE_MAP_CTRL(36), 376 TEGRA210_ADX_BYTE_MAP_CTRL(37), 377 TEGRA210_ADX_BYTE_MAP_CTRL(38), 378 TEGRA210_ADX_BYTE_MAP_CTRL(39), 379 TEGRA210_ADX_BYTE_MAP_CTRL(40), 380 TEGRA210_ADX_BYTE_MAP_CTRL(41), 381 TEGRA210_ADX_BYTE_MAP_CTRL(42), 382 TEGRA210_ADX_BYTE_MAP_CTRL(43), 383 TEGRA210_ADX_BYTE_MAP_CTRL(44), 384 TEGRA210_ADX_BYTE_MAP_CTRL(45), 385 TEGRA210_ADX_BYTE_MAP_CTRL(46), 386 TEGRA210_ADX_BYTE_MAP_CTRL(47), 387 TEGRA210_ADX_BYTE_MAP_CTRL(48), 388 TEGRA210_ADX_BYTE_MAP_CTRL(49), 389 TEGRA210_ADX_BYTE_MAP_CTRL(50), 390 TEGRA210_ADX_BYTE_MAP_CTRL(51), 391 TEGRA210_ADX_BYTE_MAP_CTRL(52), 392 TEGRA210_ADX_BYTE_MAP_CTRL(53), 393 TEGRA210_ADX_BYTE_MAP_CTRL(54), 394 TEGRA210_ADX_BYTE_MAP_CTRL(55), 395 TEGRA210_ADX_BYTE_MAP_CTRL(56), 396 TEGRA210_ADX_BYTE_MAP_CTRL(57), 397 TEGRA210_ADX_BYTE_MAP_CTRL(58), 398 TEGRA210_ADX_BYTE_MAP_CTRL(59), 399 TEGRA210_ADX_BYTE_MAP_CTRL(60), 400 TEGRA210_ADX_BYTE_MAP_CTRL(61), 401 TEGRA210_ADX_BYTE_MAP_CTRL(62), 402 TEGRA210_ADX_BYTE_MAP_CTRL(63), 403 }; 404 405 static const struct snd_soc_component_driver tegra210_adx_cmpnt = { 406 .dapm_widgets = tegra210_adx_widgets, 407 .num_dapm_widgets = ARRAY_SIZE(tegra210_adx_widgets), 408 .dapm_routes = tegra210_adx_routes, 409 .num_dapm_routes = ARRAY_SIZE(tegra210_adx_routes), 410 .controls = tegra210_adx_controls, 411 .num_controls = ARRAY_SIZE(tegra210_adx_controls), 412 }; 413 414 static bool tegra210_adx_wr_reg(struct device *dev, 415 unsigned int reg) 416 { 417 switch (reg) { 418 case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL: 419 case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL: 420 case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG: 421 case TEGRA210_ADX_CTRL ... TEGRA210_ADX_IN_BYTE_EN1: 422 case TEGRA210_ADX_CFG_RAM_CTRL ... TEGRA210_ADX_CFG_RAM_DATA: 423 return true; 424 default: 425 return false; 426 } 427 } 428 429 static bool tegra210_adx_rd_reg(struct device *dev, 430 unsigned int reg) 431 { 432 switch (reg) { 433 case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_CFG_RAM_DATA: 434 return true; 435 default: 436 return false; 437 } 438 } 439 440 static bool tegra210_adx_volatile_reg(struct device *dev, 441 unsigned int reg) 442 { 443 switch (reg) { 444 case TEGRA210_ADX_RX_STATUS: 445 case TEGRA210_ADX_RX_INT_STATUS: 446 case TEGRA210_ADX_RX_INT_SET: 447 case TEGRA210_ADX_TX_STATUS: 448 case TEGRA210_ADX_TX_INT_STATUS: 449 case TEGRA210_ADX_TX_INT_SET: 450 case TEGRA210_ADX_SOFT_RESET: 451 case TEGRA210_ADX_STATUS: 452 case TEGRA210_ADX_INT_STATUS: 453 case TEGRA210_ADX_CFG_RAM_CTRL: 454 case TEGRA210_ADX_CFG_RAM_DATA: 455 return true; 456 default: 457 break; 458 } 459 460 return false; 461 } 462 463 static const struct regmap_config tegra210_adx_regmap_config = { 464 .reg_bits = 32, 465 .reg_stride = 4, 466 .val_bits = 32, 467 .max_register = TEGRA210_ADX_CFG_RAM_DATA, 468 .writeable_reg = tegra210_adx_wr_reg, 469 .readable_reg = tegra210_adx_rd_reg, 470 .volatile_reg = tegra210_adx_volatile_reg, 471 .reg_defaults = tegra210_adx_reg_defaults, 472 .num_reg_defaults = ARRAY_SIZE(tegra210_adx_reg_defaults), 473 .cache_type = REGCACHE_FLAT, 474 }; 475 476 static const struct of_device_id tegra210_adx_of_match[] = { 477 { .compatible = "nvidia,tegra210-adx" }, 478 {}, 479 }; 480 MODULE_DEVICE_TABLE(of, tegra210_adx_of_match); 481 482 static int tegra210_adx_platform_probe(struct platform_device *pdev) 483 { 484 struct device *dev = &pdev->dev; 485 struct tegra210_adx *adx; 486 void __iomem *regs; 487 int err; 488 489 adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL); 490 if (!adx) 491 return -ENOMEM; 492 493 dev_set_drvdata(dev, adx); 494 495 regs = devm_platform_ioremap_resource(pdev, 0); 496 if (IS_ERR(regs)) 497 return PTR_ERR(regs); 498 499 adx->regmap = devm_regmap_init_mmio(dev, regs, 500 &tegra210_adx_regmap_config); 501 if (IS_ERR(adx->regmap)) { 502 dev_err(dev, "regmap init failed\n"); 503 return PTR_ERR(adx->regmap); 504 } 505 506 regcache_cache_only(adx->regmap, true); 507 508 err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt, 509 tegra210_adx_dais, 510 ARRAY_SIZE(tegra210_adx_dais)); 511 if (err) { 512 dev_err(dev, "can't register ADX component, err: %d\n", err); 513 return err; 514 } 515 516 pm_runtime_enable(dev); 517 518 return 0; 519 } 520 521 static void tegra210_adx_platform_remove(struct platform_device *pdev) 522 { 523 pm_runtime_disable(&pdev->dev); 524 } 525 526 static const struct dev_pm_ops tegra210_adx_pm_ops = { 527 SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend, 528 tegra210_adx_runtime_resume, NULL) 529 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 530 pm_runtime_force_resume) 531 }; 532 533 static struct platform_driver tegra210_adx_driver = { 534 .driver = { 535 .name = "tegra210-adx", 536 .of_match_table = tegra210_adx_of_match, 537 .pm = &tegra210_adx_pm_ops, 538 }, 539 .probe = tegra210_adx_platform_probe, 540 .remove = tegra210_adx_platform_remove, 541 }; 542 module_platform_driver(tegra210_adx_driver); 543 544 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>"); 545 MODULE_DESCRIPTION("Tegra210 ADX ASoC driver"); 546 MODULE_LICENSE("GPL v2"); 547