1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // tegra210_mvc.c - Tegra210 MVC driver 4 // 5 // Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. 6 7 #include <linux/clk.h> 8 #include <linux/device.h> 9 #include <linux/io.h> 10 #include <linux/module.h> 11 #include <linux/of.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_mvc.h" 22 #include "tegra_cif.h" 23 24 static const struct reg_default tegra210_mvc_reg_defaults[] = { 25 { TEGRA210_MVC_RX_INT_MASK, 0x00000001}, 26 { TEGRA210_MVC_RX_CIF_CTRL, 0x00007700}, 27 { TEGRA210_MVC_TX_INT_MASK, 0x00000001}, 28 { TEGRA210_MVC_TX_CIF_CTRL, 0x00007700}, 29 { TEGRA210_MVC_CG, 0x1}, 30 { TEGRA210_MVC_CTRL, TEGRA210_MVC_CTRL_DEFAULT}, 31 { TEGRA210_MVC_INIT_VOL, 0x00800000}, 32 { TEGRA210_MVC_TARGET_VOL, 0x00800000}, 33 { TEGRA210_MVC_DURATION, 0x000012c0}, 34 { TEGRA210_MVC_DURATION_INV, 0x0006d3a0}, 35 { TEGRA210_MVC_POLY_N1, 0x0000007d}, 36 { TEGRA210_MVC_POLY_N2, 0x00000271}, 37 { TEGRA210_MVC_PEAK_CTRL, 0x000012c0}, 38 { TEGRA210_MVC_CFG_RAM_CTRL, 0x00004000}, 39 }; 40 41 static const struct tegra210_mvc_gain_params gain_params = { 42 .poly_coeff = { 23738319, 659403, -3680, 43 15546680, 2530732, -120985, 44 12048422, 5527252, -785042 }, 45 .poly_n1 = 16, 46 .poly_n2 = 63, 47 .duration = 150, 48 .duration_inv = 14316558, 49 }; 50 51 static int __maybe_unused tegra210_mvc_runtime_suspend(struct device *dev) 52 { 53 struct tegra210_mvc *mvc = dev_get_drvdata(dev); 54 55 regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &(mvc->ctrl_value)); 56 57 regcache_cache_only(mvc->regmap, true); 58 regcache_mark_dirty(mvc->regmap); 59 60 return 0; 61 } 62 63 static int __maybe_unused tegra210_mvc_runtime_resume(struct device *dev) 64 { 65 struct tegra210_mvc *mvc = dev_get_drvdata(dev); 66 67 regcache_cache_only(mvc->regmap, false); 68 regcache_sync(mvc->regmap); 69 70 regmap_write(mvc->regmap, TEGRA210_MVC_CTRL, mvc->ctrl_value); 71 regmap_update_bits(mvc->regmap, 72 TEGRA210_MVC_SWITCH, 73 TEGRA210_MVC_VOLUME_SWITCH_MASK, 74 TEGRA210_MVC_VOLUME_SWITCH_TRIGGER); 75 76 return 0; 77 } 78 79 static void tegra210_mvc_write_ram(struct regmap *regmap) 80 { 81 int i; 82 83 regmap_write(regmap, TEGRA210_MVC_CFG_RAM_CTRL, 84 TEGRA210_MVC_CFG_RAM_CTRL_SEQ_ACCESS_EN | 85 TEGRA210_MVC_CFG_RAM_CTRL_ADDR_INIT_EN | 86 TEGRA210_MVC_CFG_RAM_CTRL_RW_WRITE); 87 88 for (i = 0; i < NUM_GAIN_POLY_COEFFS; i++) 89 regmap_write(regmap, TEGRA210_MVC_CFG_RAM_DATA, 90 gain_params.poly_coeff[i]); 91 } 92 93 static void tegra210_mvc_conv_vol(struct tegra210_mvc *mvc, u8 chan, s32 val) 94 { 95 /* 96 * Volume control read from mixer control is with 97 * 100x scaling; for CURVE_POLY the reg range 98 * is 0-100 (linear, Q24) and for CURVE_LINEAR 99 * it is -120dB to +40dB (Q8) 100 */ 101 if (mvc->curve_type == CURVE_POLY) { 102 if (val > 10000) 103 val = 10000; 104 mvc->volume[chan] = ((val * (1<<8)) / 100) << 16; 105 } else { 106 val -= 12000; 107 mvc->volume[chan] = (val * (1<<8)) / 100; 108 } 109 } 110 111 static u32 tegra210_mvc_get_ctrl_reg(struct snd_kcontrol *kcontrol) 112 { 113 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 114 struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); 115 u32 val; 116 117 pm_runtime_get_sync(cmpnt->dev); 118 regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &val); 119 pm_runtime_put(cmpnt->dev); 120 121 return val; 122 } 123 124 static int tegra210_mvc_get_mute(struct snd_kcontrol *kcontrol, 125 struct snd_ctl_elem_value *ucontrol) 126 { 127 u32 val = tegra210_mvc_get_ctrl_reg(kcontrol); 128 u8 mute_mask = TEGRA210_GET_MUTE_VAL(val); 129 130 /* 131 * If per channel control is enabled, then return 132 * exact mute/unmute setting of all channels. 133 * 134 * Else report setting based on CH0 bit to reflect 135 * the correct HW state. 136 */ 137 if (val & TEGRA210_MVC_PER_CHAN_CTRL_EN) { 138 ucontrol->value.integer.value[0] = mute_mask; 139 } else { 140 if (mute_mask & TEGRA210_MVC_CH0_MUTE_EN) 141 ucontrol->value.integer.value[0] = 142 TEGRA210_MUTE_MASK_EN; 143 else 144 ucontrol->value.integer.value[0] = 0; 145 } 146 147 return 0; 148 } 149 150 static int tegra210_mvc_get_master_mute(struct snd_kcontrol *kcontrol, 151 struct snd_ctl_elem_value *ucontrol) 152 { 153 u32 val = tegra210_mvc_get_ctrl_reg(kcontrol); 154 u8 mute_mask = TEGRA210_GET_MUTE_VAL(val); 155 156 /* 157 * If per channel control is disabled, then return 158 * master mute/unmute setting based on CH0 bit. 159 * 160 * Else report settings based on state of all 161 * channels. 162 */ 163 if (!(val & TEGRA210_MVC_PER_CHAN_CTRL_EN)) { 164 ucontrol->value.integer.value[0] = 165 mute_mask & TEGRA210_MVC_CH0_MUTE_EN; 166 } else { 167 if (mute_mask == TEGRA210_MUTE_MASK_EN) 168 ucontrol->value.integer.value[0] = 169 TEGRA210_MVC_CH0_MUTE_EN; 170 else 171 ucontrol->value.integer.value[0] = 0; 172 } 173 174 return 0; 175 } 176 177 static int tegra210_mvc_volume_switch_timeout(struct snd_soc_component *cmpnt) 178 { 179 struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); 180 u32 value; 181 int err; 182 183 err = regmap_read_poll_timeout(mvc->regmap, TEGRA210_MVC_SWITCH, 184 value, !(value & TEGRA210_MVC_VOLUME_SWITCH_MASK), 185 10, 10000); 186 if (err < 0) 187 dev_err(cmpnt->dev, 188 "Volume switch trigger is still active, err = %d\n", 189 err); 190 191 return err; 192 } 193 194 static int tegra210_mvc_update_mute(struct snd_kcontrol *kcontrol, 195 struct snd_ctl_elem_value *ucontrol, 196 bool per_chan_ctrl) 197 { 198 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 199 struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); 200 u32 mute_val = ucontrol->value.integer.value[0]; 201 u32 per_ch_ctrl_val; 202 bool change = false; 203 int err; 204 205 pm_runtime_get_sync(cmpnt->dev); 206 207 err = tegra210_mvc_volume_switch_timeout(cmpnt); 208 if (err < 0) 209 goto end; 210 211 if (per_chan_ctrl) { 212 per_ch_ctrl_val = TEGRA210_MVC_PER_CHAN_CTRL_EN; 213 } else { 214 per_ch_ctrl_val = 0; 215 216 if (mute_val) 217 mute_val = TEGRA210_MUTE_MASK_EN; 218 } 219 220 regmap_update_bits_check(mvc->regmap, TEGRA210_MVC_CTRL, 221 TEGRA210_MVC_MUTE_MASK, 222 mute_val << TEGRA210_MVC_MUTE_SHIFT, 223 &change); 224 225 if (change) { 226 regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL, 227 TEGRA210_MVC_PER_CHAN_CTRL_EN_MASK, 228 per_ch_ctrl_val); 229 230 regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH, 231 TEGRA210_MVC_VOLUME_SWITCH_MASK, 232 TEGRA210_MVC_VOLUME_SWITCH_TRIGGER); 233 } 234 235 end: 236 pm_runtime_put(cmpnt->dev); 237 238 if (err < 0) 239 return err; 240 241 if (change) 242 return 1; 243 244 return 0; 245 } 246 247 static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol, 248 struct snd_ctl_elem_value *ucontrol) 249 { 250 return tegra210_mvc_update_mute(kcontrol, ucontrol, true); 251 } 252 253 static int tegra210_mvc_put_master_mute(struct snd_kcontrol *kcontrol, 254 struct snd_ctl_elem_value *ucontrol) 255 { 256 return tegra210_mvc_update_mute(kcontrol, ucontrol, false); 257 } 258 259 static int tegra210_mvc_get_vol(struct snd_kcontrol *kcontrol, 260 struct snd_ctl_elem_value *ucontrol) 261 { 262 struct soc_mixer_control *mc = 263 (struct soc_mixer_control *)kcontrol->private_value; 264 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 265 struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); 266 u8 chan = TEGRA210_MVC_GET_CHAN(mc->reg, TEGRA210_MVC_TARGET_VOL); 267 s32 val = mvc->volume[chan]; 268 269 if (mvc->curve_type == CURVE_POLY) { 270 val = ((val >> 16) * 100) >> 8; 271 } else { 272 val = (val * 100) >> 8; 273 val += 12000; 274 } 275 276 ucontrol->value.integer.value[0] = val; 277 278 return 0; 279 } 280 281 static int tegra210_mvc_get_master_vol(struct snd_kcontrol *kcontrol, 282 struct snd_ctl_elem_value *ucontrol) 283 { 284 return tegra210_mvc_get_vol(kcontrol, ucontrol); 285 } 286 287 static int tegra210_mvc_update_vol(struct snd_kcontrol *kcontrol, 288 struct snd_ctl_elem_value *ucontrol, 289 bool per_ch_enable) 290 { 291 struct soc_mixer_control *mc = 292 (struct soc_mixer_control *)kcontrol->private_value; 293 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 294 struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); 295 u8 chan = TEGRA210_MVC_GET_CHAN(mc->reg, TEGRA210_MVC_TARGET_VOL); 296 int old_volume = mvc->volume[chan]; 297 int err, i; 298 299 pm_runtime_get_sync(cmpnt->dev); 300 301 err = tegra210_mvc_volume_switch_timeout(cmpnt); 302 if (err < 0) 303 goto end; 304 305 tegra210_mvc_conv_vol(mvc, chan, ucontrol->value.integer.value[0]); 306 307 if (mvc->volume[chan] == old_volume) { 308 err = 0; 309 goto end; 310 } 311 312 if (per_ch_enable) { 313 regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL, 314 TEGRA210_MVC_PER_CHAN_CTRL_EN_MASK, 315 TEGRA210_MVC_PER_CHAN_CTRL_EN); 316 } else { 317 regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL, 318 TEGRA210_MVC_PER_CHAN_CTRL_EN_MASK, 0); 319 320 for (i = 1; i < TEGRA210_MVC_MAX_CHAN_COUNT; i++) 321 mvc->volume[i] = mvc->volume[chan]; 322 } 323 324 /* Configure init volume same as target volume */ 325 regmap_write(mvc->regmap, 326 TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, chan), 327 mvc->volume[chan]); 328 329 regmap_write(mvc->regmap, mc->reg, mvc->volume[chan]); 330 331 regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH, 332 TEGRA210_MVC_VOLUME_SWITCH_MASK, 333 TEGRA210_MVC_VOLUME_SWITCH_TRIGGER); 334 335 err = 1; 336 337 end: 338 pm_runtime_put(cmpnt->dev); 339 340 return err; 341 } 342 343 static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, 344 struct snd_ctl_elem_value *ucontrol) 345 { 346 return tegra210_mvc_update_vol(kcontrol, ucontrol, true); 347 } 348 349 static int tegra210_mvc_put_master_vol(struct snd_kcontrol *kcontrol, 350 struct snd_ctl_elem_value *ucontrol) 351 { 352 return tegra210_mvc_update_vol(kcontrol, ucontrol, false); 353 } 354 355 static void tegra210_mvc_reset_vol_settings(struct tegra210_mvc *mvc, 356 struct device *dev) 357 { 358 int i; 359 360 /* Change volume to default init for new curve type */ 361 if (mvc->curve_type == CURVE_POLY) { 362 for (i = 0; i < TEGRA210_MVC_MAX_CHAN_COUNT; i++) 363 mvc->volume[i] = TEGRA210_MVC_INIT_VOL_DEFAULT_POLY; 364 } else { 365 for (i = 0; i < TEGRA210_MVC_MAX_CHAN_COUNT; i++) 366 mvc->volume[i] = TEGRA210_MVC_INIT_VOL_DEFAULT_LINEAR; 367 } 368 369 pm_runtime_get_sync(dev); 370 371 /* Program curve type */ 372 regmap_update_bits(mvc->regmap, TEGRA210_MVC_CTRL, 373 TEGRA210_MVC_CURVE_TYPE_MASK, 374 mvc->curve_type << 375 TEGRA210_MVC_CURVE_TYPE_SHIFT); 376 377 /* Init volume for all channels */ 378 for (i = 0; i < TEGRA210_MVC_MAX_CHAN_COUNT; i++) { 379 regmap_write(mvc->regmap, 380 TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, i), 381 mvc->volume[i]); 382 regmap_write(mvc->regmap, 383 TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_TARGET_VOL, i), 384 mvc->volume[i]); 385 } 386 387 /* Trigger volume switch */ 388 regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH, 389 TEGRA210_MVC_VOLUME_SWITCH_MASK, 390 TEGRA210_MVC_VOLUME_SWITCH_TRIGGER); 391 392 pm_runtime_put(dev); 393 } 394 395 static int tegra210_mvc_get_curve_type(struct snd_kcontrol *kcontrol, 396 struct snd_ctl_elem_value *ucontrol) 397 { 398 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 399 struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); 400 401 ucontrol->value.enumerated.item[0] = mvc->curve_type; 402 403 return 0; 404 } 405 406 static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol, 407 struct snd_ctl_elem_value *ucontrol) 408 { 409 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); 410 struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); 411 unsigned int value; 412 413 regmap_read(mvc->regmap, TEGRA210_MVC_ENABLE, &value); 414 if (value & TEGRA210_MVC_EN) { 415 dev_err(cmpnt->dev, 416 "Curve type can't be set when MVC is running\n"); 417 return -EINVAL; 418 } 419 420 if (mvc->curve_type == ucontrol->value.enumerated.item[0]) 421 return 0; 422 423 mvc->curve_type = ucontrol->value.enumerated.item[0]; 424 425 tegra210_mvc_reset_vol_settings(mvc, cmpnt->dev); 426 427 return 1; 428 } 429 430 static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc, 431 struct snd_pcm_hw_params *params, 432 unsigned int reg) 433 { 434 unsigned int channels, audio_bits; 435 struct tegra_cif_conf cif_conf; 436 437 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); 438 439 channels = params_channels(params); 440 441 switch (params_format(params)) { 442 case SNDRV_PCM_FORMAT_S16_LE: 443 audio_bits = TEGRA_ACIF_BITS_16; 444 break; 445 case SNDRV_PCM_FORMAT_S32_LE: 446 audio_bits = TEGRA_ACIF_BITS_32; 447 break; 448 default: 449 return -EINVAL; 450 } 451 452 cif_conf.audio_ch = channels; 453 cif_conf.client_ch = channels; 454 cif_conf.audio_bits = audio_bits; 455 cif_conf.client_bits = audio_bits; 456 457 tegra_set_cif(mvc->regmap, reg, &cif_conf); 458 459 return 0; 460 } 461 462 static int tegra210_mvc_hw_params(struct snd_pcm_substream *substream, 463 struct snd_pcm_hw_params *params, 464 struct snd_soc_dai *dai) 465 { 466 struct device *dev = dai->dev; 467 struct tegra210_mvc *mvc = snd_soc_dai_get_drvdata(dai); 468 int err, val; 469 470 /* 471 * Soft Reset: Below performs module soft reset which clears 472 * all FSM logic, flushes flow control of FIFO and resets the 473 * state register. It also brings module back to disabled 474 * state (without flushing the data in the pipe). 475 */ 476 regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1); 477 478 err = regmap_read_poll_timeout(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 479 val, !val, 10, 10000); 480 if (err < 0) { 481 dev_err(dev, "SW reset failed, err = %d\n", err); 482 return err; 483 } 484 485 /* Set RX CIF */ 486 err = tegra210_mvc_set_audio_cif(mvc, params, TEGRA210_MVC_RX_CIF_CTRL); 487 if (err) { 488 dev_err(dev, "Can't set MVC RX CIF: %d\n", err); 489 return err; 490 } 491 492 /* Set TX CIF */ 493 err = tegra210_mvc_set_audio_cif(mvc, params, TEGRA210_MVC_TX_CIF_CTRL); 494 if (err) { 495 dev_err(dev, "Can't set MVC TX CIF: %d\n", err); 496 return err; 497 } 498 499 tegra210_mvc_write_ram(mvc->regmap); 500 501 /* Program poly_n1, poly_n2, duration */ 502 regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N1, gain_params.poly_n1); 503 regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N2, gain_params.poly_n2); 504 regmap_write(mvc->regmap, TEGRA210_MVC_DURATION, gain_params.duration); 505 506 /* Program duration_inv */ 507 regmap_write(mvc->regmap, TEGRA210_MVC_DURATION_INV, 508 gain_params.duration_inv); 509 510 return 0; 511 } 512 513 static const struct snd_soc_dai_ops tegra210_mvc_dai_ops = { 514 .hw_params = tegra210_mvc_hw_params, 515 }; 516 517 static const char * const tegra210_mvc_curve_type_text[] = { 518 "Poly", 519 "Linear", 520 }; 521 522 static const struct soc_enum tegra210_mvc_curve_type_ctrl = 523 SOC_ENUM_SINGLE_EXT(2, tegra210_mvc_curve_type_text); 524 525 #define TEGRA210_MVC_VOL_CTRL(chan) \ 526 SOC_SINGLE_EXT("Channel" #chan " Volume", \ 527 TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_TARGET_VOL, \ 528 (chan - 1)), \ 529 0, 16000, 0, tegra210_mvc_get_vol, \ 530 tegra210_mvc_put_vol) 531 532 static const struct snd_kcontrol_new tegra210_mvc_vol_ctrl[] = { 533 /* Per channel volume control */ 534 TEGRA210_MVC_VOL_CTRL(1), 535 TEGRA210_MVC_VOL_CTRL(2), 536 TEGRA210_MVC_VOL_CTRL(3), 537 TEGRA210_MVC_VOL_CTRL(4), 538 TEGRA210_MVC_VOL_CTRL(5), 539 TEGRA210_MVC_VOL_CTRL(6), 540 TEGRA210_MVC_VOL_CTRL(7), 541 TEGRA210_MVC_VOL_CTRL(8), 542 543 /* Per channel mute */ 544 SOC_SINGLE_EXT("Per Chan Mute Mask", 545 TEGRA210_MVC_CTRL, 0, TEGRA210_MUTE_MASK_EN, 0, 546 tegra210_mvc_get_mute, tegra210_mvc_put_mute), 547 548 /* Master volume */ 549 SOC_SINGLE_EXT("Volume", TEGRA210_MVC_TARGET_VOL, 0, 16000, 0, 550 tegra210_mvc_get_master_vol, 551 tegra210_mvc_put_master_vol), 552 553 /* Master mute */ 554 SOC_SINGLE_EXT("Mute", TEGRA210_MVC_CTRL, 0, 1, 0, 555 tegra210_mvc_get_master_mute, 556 tegra210_mvc_put_master_mute), 557 558 SOC_ENUM_EXT("Curve Type", tegra210_mvc_curve_type_ctrl, 559 tegra210_mvc_get_curve_type, tegra210_mvc_put_curve_type), 560 }; 561 562 static struct snd_soc_dai_driver tegra210_mvc_dais[] = { 563 /* Input */ 564 { 565 .name = "MVC-RX-CIF", 566 .playback = { 567 .stream_name = "RX-CIF-Playback", 568 .channels_min = 1, 569 .channels_max = 8, 570 .rates = SNDRV_PCM_RATE_8000_192000, 571 .formats = SNDRV_PCM_FMTBIT_S8 | 572 SNDRV_PCM_FMTBIT_S16_LE | 573 SNDRV_PCM_FMTBIT_S32_LE, 574 }, 575 .capture = { 576 .stream_name = "RX-CIF-Capture", 577 .channels_min = 1, 578 .channels_max = 8, 579 .rates = SNDRV_PCM_RATE_8000_192000, 580 .formats = SNDRV_PCM_FMTBIT_S8 | 581 SNDRV_PCM_FMTBIT_S16_LE | 582 SNDRV_PCM_FMTBIT_S32_LE, 583 }, 584 }, 585 586 /* Output */ 587 { 588 .name = "MVC-TX-CIF", 589 .playback = { 590 .stream_name = "TX-CIF-Playback", 591 .channels_min = 1, 592 .channels_max = 8, 593 .rates = SNDRV_PCM_RATE_8000_192000, 594 .formats = SNDRV_PCM_FMTBIT_S8 | 595 SNDRV_PCM_FMTBIT_S16_LE | 596 SNDRV_PCM_FMTBIT_S32_LE, 597 }, 598 .capture = { 599 .stream_name = "TX-CIF-Capture", 600 .channels_min = 1, 601 .channels_max = 8, 602 .rates = SNDRV_PCM_RATE_8000_192000, 603 .formats = SNDRV_PCM_FMTBIT_S8 | 604 SNDRV_PCM_FMTBIT_S16_LE | 605 SNDRV_PCM_FMTBIT_S32_LE, 606 }, 607 .ops = &tegra210_mvc_dai_ops, 608 } 609 }; 610 611 static const struct snd_soc_dapm_widget tegra210_mvc_widgets[] = { 612 SND_SOC_DAPM_AIF_IN("RX", NULL, 0, SND_SOC_NOPM, 0, 0), 613 SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_MVC_ENABLE, 614 TEGRA210_MVC_EN_SHIFT, 0), 615 }; 616 617 #define MVC_ROUTES(sname) \ 618 { "RX XBAR-" sname, NULL, "XBAR-TX" }, \ 619 { "RX-CIF-" sname, NULL, "RX XBAR-" sname }, \ 620 { "RX", NULL, "RX-CIF-" sname }, \ 621 { "TX-CIF-" sname, NULL, "TX" }, \ 622 { "TX XBAR-" sname, NULL, "TX-CIF-" sname }, \ 623 { "XBAR-RX", NULL, "TX XBAR-" sname } 624 625 static const struct snd_soc_dapm_route tegra210_mvc_routes[] = { 626 { "TX", NULL, "RX" }, 627 MVC_ROUTES("Playback"), 628 MVC_ROUTES("Capture"), 629 }; 630 631 static const struct snd_soc_component_driver tegra210_mvc_cmpnt = { 632 .dapm_widgets = tegra210_mvc_widgets, 633 .num_dapm_widgets = ARRAY_SIZE(tegra210_mvc_widgets), 634 .dapm_routes = tegra210_mvc_routes, 635 .num_dapm_routes = ARRAY_SIZE(tegra210_mvc_routes), 636 .controls = tegra210_mvc_vol_ctrl, 637 .num_controls = ARRAY_SIZE(tegra210_mvc_vol_ctrl), 638 }; 639 640 static bool tegra210_mvc_rd_reg(struct device *dev, unsigned int reg) 641 { 642 switch (reg) { 643 case TEGRA210_MVC_RX_STATUS ... TEGRA210_MVC_CONFIG_ERR_TYPE: 644 return true; 645 default: 646 return false; 647 }; 648 } 649 650 static bool tegra210_mvc_wr_reg(struct device *dev, unsigned int reg) 651 { 652 switch (reg) { 653 case TEGRA210_MVC_RX_INT_MASK ... TEGRA210_MVC_RX_CIF_CTRL: 654 case TEGRA210_MVC_TX_INT_MASK ... TEGRA210_MVC_TX_CIF_CTRL: 655 case TEGRA210_MVC_ENABLE ... TEGRA210_MVC_CG: 656 case TEGRA210_MVC_CTRL ... TEGRA210_MVC_CFG_RAM_DATA: 657 return true; 658 default: 659 return false; 660 } 661 } 662 663 static bool tegra210_mvc_volatile_reg(struct device *dev, unsigned int reg) 664 { 665 switch (reg) { 666 case TEGRA210_MVC_RX_STATUS: 667 case TEGRA210_MVC_RX_INT_STATUS: 668 case TEGRA210_MVC_RX_INT_SET: 669 670 case TEGRA210_MVC_TX_STATUS: 671 case TEGRA210_MVC_TX_INT_STATUS: 672 case TEGRA210_MVC_TX_INT_SET: 673 674 case TEGRA210_MVC_SOFT_RESET: 675 case TEGRA210_MVC_STATUS: 676 case TEGRA210_MVC_INT_STATUS: 677 case TEGRA210_MVC_SWITCH: 678 case TEGRA210_MVC_CFG_RAM_CTRL: 679 case TEGRA210_MVC_CFG_RAM_DATA: 680 case TEGRA210_MVC_PEAK_VALUE: 681 case TEGRA210_MVC_CTRL: 682 return true; 683 default: 684 return false; 685 } 686 } 687 688 static const struct regmap_config tegra210_mvc_regmap_config = { 689 .reg_bits = 32, 690 .reg_stride = 4, 691 .val_bits = 32, 692 .max_register = TEGRA210_MVC_CONFIG_ERR_TYPE, 693 .writeable_reg = tegra210_mvc_wr_reg, 694 .readable_reg = tegra210_mvc_rd_reg, 695 .volatile_reg = tegra210_mvc_volatile_reg, 696 .reg_defaults = tegra210_mvc_reg_defaults, 697 .num_reg_defaults = ARRAY_SIZE(tegra210_mvc_reg_defaults), 698 .cache_type = REGCACHE_FLAT, 699 }; 700 701 static const struct of_device_id tegra210_mvc_of_match[] = { 702 { .compatible = "nvidia,tegra210-mvc" }, 703 {}, 704 }; 705 MODULE_DEVICE_TABLE(of, tegra210_mvc_of_match); 706 707 static int tegra210_mvc_platform_probe(struct platform_device *pdev) 708 { 709 struct device *dev = &pdev->dev; 710 struct tegra210_mvc *mvc; 711 void __iomem *regs; 712 int err; 713 714 mvc = devm_kzalloc(dev, sizeof(*mvc), GFP_KERNEL); 715 if (!mvc) 716 return -ENOMEM; 717 718 dev_set_drvdata(dev, mvc); 719 720 mvc->curve_type = CURVE_LINEAR; 721 mvc->ctrl_value = TEGRA210_MVC_CTRL_DEFAULT; 722 723 regs = devm_platform_ioremap_resource(pdev, 0); 724 if (IS_ERR(regs)) 725 return PTR_ERR(regs); 726 727 mvc->regmap = devm_regmap_init_mmio(dev, regs, 728 &tegra210_mvc_regmap_config); 729 if (IS_ERR(mvc->regmap)) { 730 dev_err(dev, "regmap init failed\n"); 731 return PTR_ERR(mvc->regmap); 732 } 733 734 regcache_cache_only(mvc->regmap, true); 735 736 err = devm_snd_soc_register_component(dev, &tegra210_mvc_cmpnt, 737 tegra210_mvc_dais, 738 ARRAY_SIZE(tegra210_mvc_dais)); 739 if (err) { 740 dev_err(dev, "can't register MVC component, err: %d\n", err); 741 return err; 742 } 743 744 pm_runtime_enable(dev); 745 746 tegra210_mvc_reset_vol_settings(mvc, &pdev->dev); 747 748 return 0; 749 } 750 751 static int tegra210_mvc_platform_remove(struct platform_device *pdev) 752 { 753 pm_runtime_disable(&pdev->dev); 754 755 return 0; 756 } 757 758 static const struct dev_pm_ops tegra210_mvc_pm_ops = { 759 SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend, 760 tegra210_mvc_runtime_resume, NULL) 761 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 762 pm_runtime_force_resume) 763 }; 764 765 static struct platform_driver tegra210_mvc_driver = { 766 .driver = { 767 .name = "tegra210-mvc", 768 .of_match_table = tegra210_mvc_of_match, 769 .pm = &tegra210_mvc_pm_ops, 770 }, 771 .probe = tegra210_mvc_platform_probe, 772 .remove = tegra210_mvc_platform_remove, 773 }; 774 module_platform_driver(tegra210_mvc_driver) 775 776 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>"); 777 MODULE_DESCRIPTION("Tegra210 MVC ASoC driver"); 778 MODULE_LICENSE("GPL v2"); 779