Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 756 lines 22 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2// SPDX-FileCopyrightText: Copyright (c) 2021-2025 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/of_device.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 "tegra210_adx.h" 22#include "tegra_cif.h" 23 24static const struct reg_default tegra210_adx_reg_defaults[] = { 25 { TEGRA210_ADX_RX_INT_MASK, 0x00000001}, 26 { TEGRA210_ADX_RX_CIF_CTRL, 0x00007000}, 27 { TEGRA210_ADX_TX_INT_MASK, 0x0000000f }, 28 { TEGRA210_ADX_TX1_CIF_CTRL, 0x00007000}, 29 { TEGRA210_ADX_TX2_CIF_CTRL, 0x00007000}, 30 { TEGRA210_ADX_TX3_CIF_CTRL, 0x00007000}, 31 { TEGRA210_ADX_TX4_CIF_CTRL, 0x00007000}, 32 { TEGRA210_ADX_CG, 0x1}, 33 { TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000}, 34}; 35 36static const struct reg_default tegra264_adx_reg_defaults[] = { 37 { TEGRA210_ADX_RX_INT_MASK, 0x00000001}, 38 { TEGRA210_ADX_RX_CIF_CTRL, 0x00003800}, 39 { TEGRA210_ADX_TX_INT_MASK, 0x0000000f }, 40 { TEGRA210_ADX_TX1_CIF_CTRL, 0x00003800}, 41 { TEGRA210_ADX_TX2_CIF_CTRL, 0x00003800}, 42 { TEGRA210_ADX_TX3_CIF_CTRL, 0x00003800}, 43 { TEGRA210_ADX_TX4_CIF_CTRL, 0x00003800}, 44 { TEGRA210_ADX_CG, 0x1}, 45 { TEGRA264_ADX_CFG_RAM_CTRL, 0x00004000}, 46}; 47 48static void tegra210_adx_write_map_ram(struct tegra210_adx *adx) 49{ 50 int i; 51 52 regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL + 53 adx->soc_data->cya_offset, 54 TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN | 55 TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN | 56 TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE); 57 58 for (i = 0; i < adx->soc_data->ram_depth; i++) 59 regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA + 60 adx->soc_data->cya_offset, 61 adx->map[i]); 62 63 for (i = 0; i < adx->soc_data->byte_mask_size; i++) 64 regmap_write(adx->regmap, 65 TEGRA210_ADX_IN_BYTE_EN0 + (i * TEGRA210_ADX_AUDIOCIF_CH_STRIDE), 66 adx->byte_mask[i]); 67} 68 69static int tegra210_adx_startup(struct snd_pcm_substream *substream, 70 struct snd_soc_dai *dai) 71{ 72 struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai); 73 unsigned int val; 74 int err; 75 76 /* Ensure if ADX status is disabled */ 77 err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_STATUS, 78 val, !(val & 0x1), 10, 10000); 79 if (err < 0) { 80 dev_err(dai->dev, "failed to stop ADX, err = %d\n", err); 81 return err; 82 } 83 84 /* 85 * Soft Reset: Below performs module soft reset which clears 86 * all FSM logic, flushes flow control of FIFO and resets the 87 * state register. It also brings module back to disabled 88 * state (without flushing the data in the pipe). 89 */ 90 regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET, 91 TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK, 92 TEGRA210_ADX_SOFT_RESET_SOFT_EN); 93 94 err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET, 95 val, !(val & 0x1), 10, 10000); 96 if (err < 0) { 97 dev_err(dai->dev, "failed to reset ADX, err = %d\n", err); 98 return err; 99 } 100 101 return 0; 102} 103 104static int tegra210_adx_runtime_suspend(struct device *dev) 105{ 106 struct tegra210_adx *adx = dev_get_drvdata(dev); 107 108 regcache_cache_only(adx->regmap, true); 109 regcache_mark_dirty(adx->regmap); 110 111 return 0; 112} 113 114static int tegra210_adx_runtime_resume(struct device *dev) 115{ 116 struct tegra210_adx *adx = dev_get_drvdata(dev); 117 118 regcache_cache_only(adx->regmap, false); 119 regcache_sync(adx->regmap); 120 121 tegra210_adx_write_map_ram(adx); 122 123 return 0; 124} 125 126static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai, 127 unsigned int channels, 128 snd_pcm_format_t format, 129 unsigned int reg) 130{ 131 struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai); 132 struct tegra_cif_conf cif_conf; 133 int audio_bits; 134 135 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); 136 137 if (channels < 1 || channels > adx->soc_data->max_ch) { 138 dev_err(dai->dev, "invalid channels: %u (max %u)\n", 139 channels, adx->soc_data->max_ch); 140 return -EINVAL; 141 } 142 143 switch (format) { 144 case SNDRV_PCM_FORMAT_S8: 145 audio_bits = TEGRA_ACIF_BITS_8; 146 break; 147 case SNDRV_PCM_FORMAT_S16_LE: 148 audio_bits = TEGRA_ACIF_BITS_16; 149 break; 150 case SNDRV_PCM_FORMAT_S24_LE: 151 case SNDRV_PCM_FORMAT_S32_LE: 152 audio_bits = TEGRA_ACIF_BITS_32; 153 break; 154 default: 155 dev_err(dai->dev, "unsupported format: %d\n", format); 156 return -EINVAL; 157 } 158 159 cif_conf.audio_ch = channels; 160 cif_conf.client_ch = channels; 161 cif_conf.audio_bits = audio_bits; 162 cif_conf.client_bits = audio_bits; 163 164 if (adx->soc_data->max_ch == 32) 165 tegra264_set_cif(adx->regmap, reg, &cif_conf); 166 else 167 tegra_set_cif(adx->regmap, reg, &cif_conf); 168 169 return 0; 170} 171 172static int tegra210_adx_out_hw_params(struct snd_pcm_substream *substream, 173 struct snd_pcm_hw_params *params, 174 struct snd_soc_dai *dai) 175{ 176 return tegra210_adx_set_audio_cif(dai, params_channels(params), 177 params_format(params), 178 TEGRA210_ADX_TX1_CIF_CTRL + ((dai->id - 1) * TEGRA210_ADX_AUDIOCIF_CH_STRIDE)); 179} 180 181static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream, 182 struct snd_pcm_hw_params *params, 183 struct snd_soc_dai *dai) 184{ 185 return tegra210_adx_set_audio_cif(dai, params_channels(params), 186 params_format(params), 187 TEGRA210_ADX_RX_CIF_CTRL); 188} 189 190static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol, 191 struct snd_ctl_elem_value *ucontrol) 192{ 193 struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); 194 struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt); 195 struct soc_mixer_control *mc; 196 unsigned char *bytes_map = (unsigned char *)adx->map; 197 int enabled; 198 199 mc = (struct soc_mixer_control *)kcontrol->private_value; 200 enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32)); 201 202 /* 203 * TODO: Simplify this logic to just return from bytes_map[] 204 * 205 * Presently below is required since bytes_map[] is 206 * tightly packed and cannot store the control value of 256. 207 * Byte mask state is used to know if 256 needs to be returned. 208 * Note that for control value of 256, the put() call stores 0 209 * in the bytes_map[] and disables the corresponding bit in 210 * byte_mask[]. 211 */ 212 if (enabled) 213 ucontrol->value.integer.value[0] = bytes_map[mc->reg]; 214 else 215 ucontrol->value.integer.value[0] = 256; 216 217 return 0; 218} 219 220static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol, 221 struct snd_ctl_elem_value *ucontrol) 222{ 223 struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); 224 struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt); 225 unsigned char *bytes_map = (unsigned char *)adx->map; 226 int value = ucontrol->value.integer.value[0]; 227 struct soc_mixer_control *mc = 228 (struct soc_mixer_control *)kcontrol->private_value; 229 unsigned int mask_val = adx->byte_mask[mc->reg / 32]; 230 231 if (value >= 0 && value <= 255) 232 mask_val |= (1 << (mc->reg % 32)); 233 else 234 mask_val &= ~(1 << (mc->reg % 32)); 235 236 if (mask_val == adx->byte_mask[mc->reg / 32]) 237 return 0; 238 239 /* Update byte map and slot */ 240 bytes_map[mc->reg] = value % 256; 241 adx->byte_mask[mc->reg / 32] = mask_val; 242 243 return 1; 244} 245 246static const struct snd_soc_dai_ops tegra210_adx_in_dai_ops = { 247 .hw_params = tegra210_adx_in_hw_params, 248 .startup = tegra210_adx_startup, 249}; 250 251static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = { 252 .hw_params = tegra210_adx_out_hw_params, 253}; 254 255#define IN_DAI \ 256 { \ 257 .name = "ADX-RX-CIF", \ 258 .playback = { \ 259 .stream_name = "RX-CIF-Playback", \ 260 .channels_min = 1, \ 261 .channels_max = 16, \ 262 .rates = SNDRV_PCM_RATE_8000_192000, \ 263 .formats = SNDRV_PCM_FMTBIT_S8 | \ 264 SNDRV_PCM_FMTBIT_S16_LE | \ 265 SNDRV_PCM_FMTBIT_S24_LE | \ 266 SNDRV_PCM_FMTBIT_S32_LE, \ 267 }, \ 268 .capture = { \ 269 .stream_name = "RX-CIF-Capture", \ 270 .channels_min = 1, \ 271 .channels_max = 16, \ 272 .rates = SNDRV_PCM_RATE_8000_192000, \ 273 .formats = SNDRV_PCM_FMTBIT_S8 | \ 274 SNDRV_PCM_FMTBIT_S16_LE | \ 275 SNDRV_PCM_FMTBIT_S24_LE | \ 276 SNDRV_PCM_FMTBIT_S32_LE, \ 277 }, \ 278 .ops = &tegra210_adx_in_dai_ops, \ 279 } 280 281#define OUT_DAI(id) \ 282 { \ 283 .name = "ADX-TX" #id "-CIF", \ 284 .playback = { \ 285 .stream_name = "TX" #id "-CIF-Playback",\ 286 .channels_min = 1, \ 287 .channels_max = 16, \ 288 .rates = SNDRV_PCM_RATE_8000_192000, \ 289 .formats = SNDRV_PCM_FMTBIT_S8 | \ 290 SNDRV_PCM_FMTBIT_S16_LE | \ 291 SNDRV_PCM_FMTBIT_S24_LE | \ 292 SNDRV_PCM_FMTBIT_S32_LE, \ 293 }, \ 294 .capture = { \ 295 .stream_name = "TX" #id "-CIF-Capture", \ 296 .channels_min = 1, \ 297 .channels_max = 16, \ 298 .rates = SNDRV_PCM_RATE_8000_192000, \ 299 .formats = SNDRV_PCM_FMTBIT_S8 | \ 300 SNDRV_PCM_FMTBIT_S16_LE | \ 301 SNDRV_PCM_FMTBIT_S24_LE | \ 302 SNDRV_PCM_FMTBIT_S32_LE, \ 303 }, \ 304 .ops = &tegra210_adx_out_dai_ops, \ 305 } 306 307static struct snd_soc_dai_driver tegra210_adx_dais[] = { 308 IN_DAI, 309 OUT_DAI(1), 310 OUT_DAI(2), 311 OUT_DAI(3), 312 OUT_DAI(4), 313}; 314 315static const struct snd_soc_dapm_widget tegra210_adx_widgets[] = { 316 SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA210_ADX_ENABLE, 317 TEGRA210_ADX_ENABLE_SHIFT, 0), 318 SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_ADX_CTRL, 0, 0), 319 SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_ADX_CTRL, 1, 0), 320 SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_ADX_CTRL, 2, 0), 321 SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_ADX_CTRL, 3, 0), 322}; 323 324#define STREAM_ROUTES(id, sname) \ 325 { "XBAR-" sname, NULL, "XBAR-TX" }, \ 326 { "RX-CIF-" sname, NULL, "XBAR-" sname }, \ 327 { "RX", NULL, "RX-CIF-" sname }, \ 328 { "TX" #id, NULL, "RX" }, \ 329 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \ 330 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \ 331 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname } 332 333#define ADX_ROUTES(id) \ 334 STREAM_ROUTES(id, "Playback"), \ 335 STREAM_ROUTES(id, "Capture") 336 337#define STREAM_ROUTES(id, sname) \ 338 { "XBAR-" sname, NULL, "XBAR-TX" }, \ 339 { "RX-CIF-" sname, NULL, "XBAR-" sname }, \ 340 { "RX", NULL, "RX-CIF-" sname }, \ 341 { "TX" #id, NULL, "RX" }, \ 342 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \ 343 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \ 344 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname } 345 346#define ADX_ROUTES(id) \ 347 STREAM_ROUTES(id, "Playback"), \ 348 STREAM_ROUTES(id, "Capture") 349 350static const struct snd_soc_dapm_route tegra210_adx_routes[] = { 351 ADX_ROUTES(1), 352 ADX_ROUTES(2), 353 ADX_ROUTES(3), 354 ADX_ROUTES(4), 355}; 356 357#define TEGRA210_ADX_BYTE_MAP_CTRL(reg) \ 358 SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0, \ 359 tegra210_adx_get_byte_map, \ 360 tegra210_adx_put_byte_map) 361 362static struct snd_kcontrol_new tegra210_adx_controls[] = { 363 TEGRA210_ADX_BYTE_MAP_CTRL(0), 364 TEGRA210_ADX_BYTE_MAP_CTRL(1), 365 TEGRA210_ADX_BYTE_MAP_CTRL(2), 366 TEGRA210_ADX_BYTE_MAP_CTRL(3), 367 TEGRA210_ADX_BYTE_MAP_CTRL(4), 368 TEGRA210_ADX_BYTE_MAP_CTRL(5), 369 TEGRA210_ADX_BYTE_MAP_CTRL(6), 370 TEGRA210_ADX_BYTE_MAP_CTRL(7), 371 TEGRA210_ADX_BYTE_MAP_CTRL(8), 372 TEGRA210_ADX_BYTE_MAP_CTRL(9), 373 TEGRA210_ADX_BYTE_MAP_CTRL(10), 374 TEGRA210_ADX_BYTE_MAP_CTRL(11), 375 TEGRA210_ADX_BYTE_MAP_CTRL(12), 376 TEGRA210_ADX_BYTE_MAP_CTRL(13), 377 TEGRA210_ADX_BYTE_MAP_CTRL(14), 378 TEGRA210_ADX_BYTE_MAP_CTRL(15), 379 TEGRA210_ADX_BYTE_MAP_CTRL(16), 380 TEGRA210_ADX_BYTE_MAP_CTRL(17), 381 TEGRA210_ADX_BYTE_MAP_CTRL(18), 382 TEGRA210_ADX_BYTE_MAP_CTRL(19), 383 TEGRA210_ADX_BYTE_MAP_CTRL(20), 384 TEGRA210_ADX_BYTE_MAP_CTRL(21), 385 TEGRA210_ADX_BYTE_MAP_CTRL(22), 386 TEGRA210_ADX_BYTE_MAP_CTRL(23), 387 TEGRA210_ADX_BYTE_MAP_CTRL(24), 388 TEGRA210_ADX_BYTE_MAP_CTRL(25), 389 TEGRA210_ADX_BYTE_MAP_CTRL(26), 390 TEGRA210_ADX_BYTE_MAP_CTRL(27), 391 TEGRA210_ADX_BYTE_MAP_CTRL(28), 392 TEGRA210_ADX_BYTE_MAP_CTRL(29), 393 TEGRA210_ADX_BYTE_MAP_CTRL(30), 394 TEGRA210_ADX_BYTE_MAP_CTRL(31), 395 TEGRA210_ADX_BYTE_MAP_CTRL(32), 396 TEGRA210_ADX_BYTE_MAP_CTRL(33), 397 TEGRA210_ADX_BYTE_MAP_CTRL(34), 398 TEGRA210_ADX_BYTE_MAP_CTRL(35), 399 TEGRA210_ADX_BYTE_MAP_CTRL(36), 400 TEGRA210_ADX_BYTE_MAP_CTRL(37), 401 TEGRA210_ADX_BYTE_MAP_CTRL(38), 402 TEGRA210_ADX_BYTE_MAP_CTRL(39), 403 TEGRA210_ADX_BYTE_MAP_CTRL(40), 404 TEGRA210_ADX_BYTE_MAP_CTRL(41), 405 TEGRA210_ADX_BYTE_MAP_CTRL(42), 406 TEGRA210_ADX_BYTE_MAP_CTRL(43), 407 TEGRA210_ADX_BYTE_MAP_CTRL(44), 408 TEGRA210_ADX_BYTE_MAP_CTRL(45), 409 TEGRA210_ADX_BYTE_MAP_CTRL(46), 410 TEGRA210_ADX_BYTE_MAP_CTRL(47), 411 TEGRA210_ADX_BYTE_MAP_CTRL(48), 412 TEGRA210_ADX_BYTE_MAP_CTRL(49), 413 TEGRA210_ADX_BYTE_MAP_CTRL(50), 414 TEGRA210_ADX_BYTE_MAP_CTRL(51), 415 TEGRA210_ADX_BYTE_MAP_CTRL(52), 416 TEGRA210_ADX_BYTE_MAP_CTRL(53), 417 TEGRA210_ADX_BYTE_MAP_CTRL(54), 418 TEGRA210_ADX_BYTE_MAP_CTRL(55), 419 TEGRA210_ADX_BYTE_MAP_CTRL(56), 420 TEGRA210_ADX_BYTE_MAP_CTRL(57), 421 TEGRA210_ADX_BYTE_MAP_CTRL(58), 422 TEGRA210_ADX_BYTE_MAP_CTRL(59), 423 TEGRA210_ADX_BYTE_MAP_CTRL(60), 424 TEGRA210_ADX_BYTE_MAP_CTRL(61), 425 TEGRA210_ADX_BYTE_MAP_CTRL(62), 426 TEGRA210_ADX_BYTE_MAP_CTRL(63), 427}; 428 429static struct snd_kcontrol_new tegra264_adx_controls[] = { 430 TEGRA210_ADX_BYTE_MAP_CTRL(64), 431 TEGRA210_ADX_BYTE_MAP_CTRL(65), 432 TEGRA210_ADX_BYTE_MAP_CTRL(66), 433 TEGRA210_ADX_BYTE_MAP_CTRL(67), 434 TEGRA210_ADX_BYTE_MAP_CTRL(68), 435 TEGRA210_ADX_BYTE_MAP_CTRL(69), 436 TEGRA210_ADX_BYTE_MAP_CTRL(70), 437 TEGRA210_ADX_BYTE_MAP_CTRL(71), 438 TEGRA210_ADX_BYTE_MAP_CTRL(72), 439 TEGRA210_ADX_BYTE_MAP_CTRL(73), 440 TEGRA210_ADX_BYTE_MAP_CTRL(74), 441 TEGRA210_ADX_BYTE_MAP_CTRL(75), 442 TEGRA210_ADX_BYTE_MAP_CTRL(76), 443 TEGRA210_ADX_BYTE_MAP_CTRL(77), 444 TEGRA210_ADX_BYTE_MAP_CTRL(78), 445 TEGRA210_ADX_BYTE_MAP_CTRL(79), 446 TEGRA210_ADX_BYTE_MAP_CTRL(80), 447 TEGRA210_ADX_BYTE_MAP_CTRL(81), 448 TEGRA210_ADX_BYTE_MAP_CTRL(82), 449 TEGRA210_ADX_BYTE_MAP_CTRL(83), 450 TEGRA210_ADX_BYTE_MAP_CTRL(84), 451 TEGRA210_ADX_BYTE_MAP_CTRL(85), 452 TEGRA210_ADX_BYTE_MAP_CTRL(86), 453 TEGRA210_ADX_BYTE_MAP_CTRL(87), 454 TEGRA210_ADX_BYTE_MAP_CTRL(88), 455 TEGRA210_ADX_BYTE_MAP_CTRL(89), 456 TEGRA210_ADX_BYTE_MAP_CTRL(90), 457 TEGRA210_ADX_BYTE_MAP_CTRL(91), 458 TEGRA210_ADX_BYTE_MAP_CTRL(92), 459 TEGRA210_ADX_BYTE_MAP_CTRL(93), 460 TEGRA210_ADX_BYTE_MAP_CTRL(94), 461 TEGRA210_ADX_BYTE_MAP_CTRL(95), 462 TEGRA210_ADX_BYTE_MAP_CTRL(96), 463 TEGRA210_ADX_BYTE_MAP_CTRL(97), 464 TEGRA210_ADX_BYTE_MAP_CTRL(98), 465 TEGRA210_ADX_BYTE_MAP_CTRL(99), 466 TEGRA210_ADX_BYTE_MAP_CTRL(100), 467 TEGRA210_ADX_BYTE_MAP_CTRL(101), 468 TEGRA210_ADX_BYTE_MAP_CTRL(102), 469 TEGRA210_ADX_BYTE_MAP_CTRL(103), 470 TEGRA210_ADX_BYTE_MAP_CTRL(104), 471 TEGRA210_ADX_BYTE_MAP_CTRL(105), 472 TEGRA210_ADX_BYTE_MAP_CTRL(106), 473 TEGRA210_ADX_BYTE_MAP_CTRL(107), 474 TEGRA210_ADX_BYTE_MAP_CTRL(108), 475 TEGRA210_ADX_BYTE_MAP_CTRL(109), 476 TEGRA210_ADX_BYTE_MAP_CTRL(110), 477 TEGRA210_ADX_BYTE_MAP_CTRL(111), 478 TEGRA210_ADX_BYTE_MAP_CTRL(112), 479 TEGRA210_ADX_BYTE_MAP_CTRL(113), 480 TEGRA210_ADX_BYTE_MAP_CTRL(114), 481 TEGRA210_ADX_BYTE_MAP_CTRL(115), 482 TEGRA210_ADX_BYTE_MAP_CTRL(116), 483 TEGRA210_ADX_BYTE_MAP_CTRL(117), 484 TEGRA210_ADX_BYTE_MAP_CTRL(118), 485 TEGRA210_ADX_BYTE_MAP_CTRL(119), 486 TEGRA210_ADX_BYTE_MAP_CTRL(120), 487 TEGRA210_ADX_BYTE_MAP_CTRL(121), 488 TEGRA210_ADX_BYTE_MAP_CTRL(122), 489 TEGRA210_ADX_BYTE_MAP_CTRL(123), 490 TEGRA210_ADX_BYTE_MAP_CTRL(124), 491 TEGRA210_ADX_BYTE_MAP_CTRL(125), 492 TEGRA210_ADX_BYTE_MAP_CTRL(126), 493 TEGRA210_ADX_BYTE_MAP_CTRL(127), 494}; 495 496static int tegra210_adx_component_probe(struct snd_soc_component *component) 497{ 498 struct tegra210_adx *adx = snd_soc_component_get_drvdata(component); 499 int err = 0; 500 501 if (adx->soc_data->num_controls) { 502 err = snd_soc_add_component_controls(component, adx->soc_data->controls, 503 adx->soc_data->num_controls); 504 if (err) 505 dev_err(component->dev, "can't add ADX controls, err: %d\n", err); 506 } 507 508 return err; 509} 510 511static const struct snd_soc_component_driver tegra210_adx_cmpnt = { 512 .probe = tegra210_adx_component_probe, 513 .dapm_widgets = tegra210_adx_widgets, 514 .num_dapm_widgets = ARRAY_SIZE(tegra210_adx_widgets), 515 .dapm_routes = tegra210_adx_routes, 516 .num_dapm_routes = ARRAY_SIZE(tegra210_adx_routes), 517 .controls = tegra210_adx_controls, 518 .num_controls = ARRAY_SIZE(tegra210_adx_controls), 519}; 520 521static bool tegra210_adx_wr_reg(struct device *dev, 522 unsigned int reg) 523{ 524 switch (reg) { 525 case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL: 526 case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL: 527 case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG: 528 case TEGRA210_ADX_CTRL ... TEGRA210_ADX_IN_BYTE_EN1: 529 case TEGRA210_ADX_CFG_RAM_CTRL ... TEGRA210_ADX_CFG_RAM_DATA: 530 return true; 531 default: 532 return false; 533 } 534} 535 536static bool tegra210_adx_rd_reg(struct device *dev, 537 unsigned int reg) 538{ 539 switch (reg) { 540 case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_CFG_RAM_DATA: 541 return true; 542 default: 543 return false; 544 } 545} 546 547static bool tegra210_adx_volatile_reg(struct device *dev, 548 unsigned int reg) 549{ 550 switch (reg) { 551 case TEGRA210_ADX_RX_STATUS: 552 case TEGRA210_ADX_RX_INT_STATUS: 553 case TEGRA210_ADX_RX_INT_SET: 554 case TEGRA210_ADX_TX_STATUS: 555 case TEGRA210_ADX_TX_INT_STATUS: 556 case TEGRA210_ADX_TX_INT_SET: 557 case TEGRA210_ADX_SOFT_RESET: 558 case TEGRA210_ADX_STATUS: 559 case TEGRA210_ADX_INT_STATUS: 560 case TEGRA210_ADX_CFG_RAM_CTRL: 561 case TEGRA210_ADX_CFG_RAM_DATA: 562 return true; 563 default: 564 break; 565 } 566 567 return false; 568} 569 570static bool tegra264_adx_wr_reg(struct device *dev, 571 unsigned int reg) 572{ 573 switch (reg) { 574 case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL: 575 case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL: 576 case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG: 577 case TEGRA210_ADX_CTRL ... TEGRA264_ADX_CYA: 578 case TEGRA264_ADX_CFG_RAM_CTRL ... TEGRA264_ADX_CFG_RAM_DATA: 579 return true; 580 default: 581 return false; 582 } 583} 584 585static bool tegra264_adx_rd_reg(struct device *dev, 586 unsigned int reg) 587{ 588 switch (reg) { 589 case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_RX_CIF_CTRL: 590 case TEGRA210_ADX_TX_STATUS ... TEGRA210_ADX_TX4_CIF_CTRL: 591 case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_INT_STATUS: 592 case TEGRA210_ADX_CTRL ... TEGRA264_ADX_CFG_RAM_DATA: 593 return true; 594 default: 595 return false; 596 } 597} 598 599static bool tegra264_adx_volatile_reg(struct device *dev, 600 unsigned int reg) 601{ 602 switch (reg) { 603 case TEGRA210_ADX_RX_STATUS: 604 case TEGRA210_ADX_RX_INT_STATUS: 605 case TEGRA210_ADX_RX_INT_SET: 606 case TEGRA210_ADX_TX_STATUS: 607 case TEGRA210_ADX_TX_INT_STATUS: 608 case TEGRA210_ADX_TX_INT_SET: 609 case TEGRA210_ADX_SOFT_RESET: 610 case TEGRA210_ADX_STATUS: 611 case TEGRA210_ADX_INT_STATUS: 612 case TEGRA264_ADX_CFG_RAM_CTRL: 613 case TEGRA264_ADX_CFG_RAM_DATA: 614 return true; 615 default: 616 break; 617 } 618 619 return false; 620} 621 622static const struct regmap_config tegra210_adx_regmap_config = { 623 .reg_bits = 32, 624 .reg_stride = 4, 625 .val_bits = 32, 626 .max_register = TEGRA210_ADX_CFG_RAM_DATA, 627 .writeable_reg = tegra210_adx_wr_reg, 628 .readable_reg = tegra210_adx_rd_reg, 629 .volatile_reg = tegra210_adx_volatile_reg, 630 .reg_defaults = tegra210_adx_reg_defaults, 631 .num_reg_defaults = ARRAY_SIZE(tegra210_adx_reg_defaults), 632 .reg_default_cb = regmap_default_zero_cb, 633 .cache_type = REGCACHE_FLAT, 634}; 635 636static const struct regmap_config tegra264_adx_regmap_config = { 637 .reg_bits = 32, 638 .reg_stride = 4, 639 .val_bits = 32, 640 .max_register = TEGRA264_ADX_CFG_RAM_DATA, 641 .writeable_reg = tegra264_adx_wr_reg, 642 .readable_reg = tegra264_adx_rd_reg, 643 .volatile_reg = tegra264_adx_volatile_reg, 644 .reg_defaults = tegra264_adx_reg_defaults, 645 .num_reg_defaults = ARRAY_SIZE(tegra264_adx_reg_defaults), 646 .reg_default_cb = regmap_default_zero_cb, 647 .cache_type = REGCACHE_FLAT, 648}; 649 650static const struct tegra210_adx_soc_data soc_data_tegra210 = { 651 .regmap_conf = &tegra210_adx_regmap_config, 652 .max_ch = TEGRA210_ADX_MAX_CHANNEL, 653 .ram_depth = TEGRA210_ADX_RAM_DEPTH, 654 .byte_mask_size = TEGRA210_ADX_BYTE_MASK_COUNT, 655 .cya_offset = TEGRA210_ADX_CYA_OFFSET, 656}; 657 658static const struct tegra210_adx_soc_data soc_data_tegra264 = { 659 .regmap_conf = &tegra264_adx_regmap_config, 660 .max_ch = TEGRA264_ADX_MAX_CHANNEL, 661 .ram_depth = TEGRA264_ADX_RAM_DEPTH, 662 .byte_mask_size = TEGRA264_ADX_BYTE_MASK_COUNT, 663 .cya_offset = TEGRA264_ADX_CYA_OFFSET, 664 .controls = tegra264_adx_controls, 665 .num_controls = ARRAY_SIZE(tegra264_adx_controls), 666}; 667 668static const struct of_device_id tegra210_adx_of_match[] = { 669 { .compatible = "nvidia,tegra210-adx", .data = &soc_data_tegra210 }, 670 { .compatible = "nvidia,tegra264-adx", .data = &soc_data_tegra264 }, 671 {}, 672}; 673MODULE_DEVICE_TABLE(of, tegra210_adx_of_match); 674 675static int tegra210_adx_platform_probe(struct platform_device *pdev) 676{ 677 struct device *dev = &pdev->dev; 678 struct tegra210_adx *adx; 679 const struct of_device_id *match; 680 struct tegra210_adx_soc_data *soc_data; 681 void __iomem *regs; 682 int err; 683 684 adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL); 685 if (!adx) 686 return -ENOMEM; 687 688 match = of_match_device(tegra210_adx_of_match, dev); 689 soc_data = (struct tegra210_adx_soc_data *)match->data; 690 adx->soc_data = soc_data; 691 692 dev_set_drvdata(dev, adx); 693 694 regs = devm_platform_ioremap_resource(pdev, 0); 695 if (IS_ERR(regs)) 696 return PTR_ERR(regs); 697 698 adx->regmap = devm_regmap_init_mmio(dev, regs, 699 soc_data->regmap_conf); 700 if (IS_ERR(adx->regmap)) 701 return dev_err_probe(dev, PTR_ERR(adx->regmap), 702 "regmap init failed\n"); 703 704 regcache_cache_only(adx->regmap, true); 705 706 adx->map = devm_kzalloc(dev, soc_data->ram_depth * sizeof(*adx->map), 707 GFP_KERNEL); 708 if (!adx->map) 709 return -ENOMEM; 710 711 adx->byte_mask = devm_kzalloc(dev, 712 soc_data->byte_mask_size * sizeof(*adx->byte_mask), 713 GFP_KERNEL); 714 if (!adx->byte_mask) 715 return -ENOMEM; 716 717 tegra210_adx_dais[TEGRA_ADX_IN_DAI_ID].playback.channels_max = 718 adx->soc_data->max_ch; 719 720 err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt, 721 tegra210_adx_dais, 722 ARRAY_SIZE(tegra210_adx_dais)); 723 if (err) 724 return dev_err_probe(dev, err, 725 "can't register ADX component\n"); 726 727 pm_runtime_enable(dev); 728 729 return 0; 730} 731 732static void tegra210_adx_platform_remove(struct platform_device *pdev) 733{ 734 pm_runtime_disable(&pdev->dev); 735} 736 737static const struct dev_pm_ops tegra210_adx_pm_ops = { 738 RUNTIME_PM_OPS(tegra210_adx_runtime_suspend, 739 tegra210_adx_runtime_resume, NULL) 740 SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 741}; 742 743static struct platform_driver tegra210_adx_driver = { 744 .driver = { 745 .name = "tegra210-adx", 746 .of_match_table = tegra210_adx_of_match, 747 .pm = pm_ptr(&tegra210_adx_pm_ops), 748 }, 749 .probe = tegra210_adx_platform_probe, 750 .remove = tegra210_adx_platform_remove, 751}; 752module_platform_driver(tegra210_adx_driver); 753 754MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>"); 755MODULE_DESCRIPTION("Tegra210 ADX ASoC driver"); 756MODULE_LICENSE("GPL v2");