1 // SPDX-License-Identifier: GPL-2.0-only 2 // SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. 3 // All rights reserved. 4 // 5 // tegra210_dmic.c - Tegra210 DMIC driver 6 7 #include <linux/clk.h> 8 #include <linux/device.h> 9 #include <linux/math64.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_params.h> 17 #include <sound/soc.h> 18 #include "tegra210_dmic.h" 19 #include "tegra_cif.h" 20 21 static const struct reg_default tegra210_dmic_reg_defaults[] = { 22 { TEGRA210_DMIC_TX_INT_MASK, 0x00000001 }, 23 { TEGRA210_DMIC_TX_CIF_CTRL, 0x00007700 }, 24 { TEGRA210_DMIC_CG, 0x1 }, 25 { TEGRA210_DMIC_CTRL, 0x00000301 }, 26 /* Below enables all filters - DCR, LP and SC */ 27 { TEGRA210_DMIC_DBG_CTRL, 0xe }, 28 /* Below as per latest POR value */ 29 { TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4, 0x0 }, 30 /* LP filter is configured for pass through and used to apply gain */ 31 { TEGRA210_DMIC_LP_BIQUAD_0_COEF_0, 0x00800000 }, 32 { TEGRA210_DMIC_LP_BIQUAD_0_COEF_1, 0x0 }, 33 { TEGRA210_DMIC_LP_BIQUAD_0_COEF_2, 0x0 }, 34 { TEGRA210_DMIC_LP_BIQUAD_0_COEF_3, 0x0 }, 35 { TEGRA210_DMIC_LP_BIQUAD_0_COEF_4, 0x0 }, 36 { TEGRA210_DMIC_LP_BIQUAD_1_COEF_0, 0x00800000 }, 37 { TEGRA210_DMIC_LP_BIQUAD_1_COEF_1, 0x0 }, 38 { TEGRA210_DMIC_LP_BIQUAD_1_COEF_2, 0x0 }, 39 { TEGRA210_DMIC_LP_BIQUAD_1_COEF_3, 0x0 }, 40 { TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 0x0 }, 41 }; 42 43 static int __maybe_unused tegra210_dmic_runtime_suspend(struct device *dev) 44 { 45 struct tegra210_dmic *dmic = dev_get_drvdata(dev); 46 47 regcache_cache_only(dmic->regmap, true); 48 regcache_mark_dirty(dmic->regmap); 49 50 clk_disable_unprepare(dmic->clk_dmic); 51 52 return 0; 53 } 54 55 static int __maybe_unused tegra210_dmic_runtime_resume(struct device *dev) 56 { 57 struct tegra210_dmic *dmic = dev_get_drvdata(dev); 58 int err; 59 60 err = clk_prepare_enable(dmic->clk_dmic); 61 if (err) { 62 dev_err(dev, "failed to enable DMIC clock, err: %d\n", err); 63 return err; 64 } 65 66 regcache_cache_only(dmic->regmap, false); 67 regcache_sync(dmic->regmap); 68 69 return 0; 70 } 71 72 static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, 73 struct snd_pcm_hw_params *params, 74 struct snd_soc_dai *dai) 75 { 76 struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai); 77 unsigned int srate, clk_rate, channels; 78 struct tegra_cif_conf cif_conf; 79 unsigned long long gain_q23 = DEFAULT_GAIN_Q23; 80 int err; 81 82 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); 83 84 channels = params_channels(params); 85 86 cif_conf.audio_ch = channels; 87 88 switch (dmic->ch_select) { 89 case DMIC_CH_SELECT_LEFT: 90 case DMIC_CH_SELECT_RIGHT: 91 cif_conf.client_ch = 1; 92 break; 93 case DMIC_CH_SELECT_STEREO: 94 cif_conf.client_ch = 2; 95 break; 96 default: 97 dev_err(dai->dev, "invalid DMIC client channels\n"); 98 return -EINVAL; 99 } 100 101 srate = params_rate(params); 102 103 /* 104 * DMIC clock rate is a multiple of 'Over Sampling Ratio' and 105 * 'Sample Rate'. The supported OSR values are 64, 128 and 256. 106 */ 107 clk_rate = (DMIC_OSR_FACTOR << dmic->osr_val) * srate; 108 109 err = clk_set_rate(dmic->clk_dmic, clk_rate); 110 if (err) { 111 dev_err(dai->dev, "can't set DMIC clock rate %u, err: %d\n", 112 clk_rate, err); 113 return err; 114 } 115 116 regmap_update_bits(dmic->regmap, 117 /* Reg */ 118 TEGRA210_DMIC_CTRL, 119 /* Mask */ 120 TEGRA210_DMIC_CTRL_LRSEL_POLARITY_MASK | 121 TEGRA210_DMIC_CTRL_OSR_MASK | 122 TEGRA210_DMIC_CTRL_CHANNEL_SELECT_MASK, 123 /* Value */ 124 (dmic->lrsel << LRSEL_POL_SHIFT) | 125 (dmic->osr_val << OSR_SHIFT) | 126 ((dmic->ch_select + 1) << CH_SEL_SHIFT)); 127 128 /* 129 * Use LP filter gain register to apply boost. 130 * Boost Gain Volume control has 100x factor. 131 */ 132 if (dmic->boost_gain) 133 gain_q23 = div_u64(gain_q23 * dmic->boost_gain, 100); 134 135 regmap_write(dmic->regmap, TEGRA210_DMIC_LP_FILTER_GAIN, 136 (unsigned int)gain_q23); 137 138 switch (params_format(params)) { 139 case SNDRV_PCM_FORMAT_S16_LE: 140 cif_conf.audio_bits = TEGRA_ACIF_BITS_16; 141 break; 142 case SNDRV_PCM_FORMAT_S24_LE: 143 case SNDRV_PCM_FORMAT_S32_LE: 144 cif_conf.audio_bits = TEGRA_ACIF_BITS_32; 145 break; 146 default: 147 dev_err(dai->dev, "unsupported format!\n"); 148 return -EOPNOTSUPP; 149 } 150 151 cif_conf.client_bits = TEGRA_ACIF_BITS_24; 152 cif_conf.mono_conv = dmic->mono_to_stereo; 153 cif_conf.stereo_conv = dmic->stereo_to_mono; 154 155 tegra_set_cif(dmic->regmap, TEGRA210_DMIC_TX_CIF_CTRL, &cif_conf); 156 157 return 0; 158 } 159 160 static int tegra210_dmic_get_boost_gain(struct snd_kcontrol *kcontrol, 161 struct snd_ctl_elem_value *ucontrol) 162 { 163 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 164 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 165 166 ucontrol->value.integer.value[0] = dmic->boost_gain; 167 168 return 0; 169 } 170 171 static int tegra210_dmic_put_boost_gain(struct snd_kcontrol *kcontrol, 172 struct snd_ctl_elem_value *ucontrol) 173 { 174 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 175 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 176 int value = ucontrol->value.integer.value[0]; 177 178 if (value == dmic->boost_gain) 179 return 0; 180 181 dmic->boost_gain = value; 182 183 return 1; 184 } 185 186 static int tegra210_dmic_get_ch_select(struct snd_kcontrol *kcontrol, 187 struct snd_ctl_elem_value *ucontrol) 188 { 189 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 190 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 191 192 ucontrol->value.enumerated.item[0] = dmic->ch_select; 193 194 return 0; 195 } 196 197 static int tegra210_dmic_put_ch_select(struct snd_kcontrol *kcontrol, 198 struct snd_ctl_elem_value *ucontrol) 199 { 200 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 201 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 202 unsigned int value = ucontrol->value.enumerated.item[0]; 203 204 if (value == dmic->ch_select) 205 return 0; 206 207 dmic->ch_select = value; 208 209 return 1; 210 } 211 212 static int tegra210_dmic_get_mono_to_stereo(struct snd_kcontrol *kcontrol, 213 struct snd_ctl_elem_value *ucontrol) 214 { 215 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 216 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 217 218 ucontrol->value.enumerated.item[0] = dmic->mono_to_stereo; 219 220 return 0; 221 } 222 223 static int tegra210_dmic_put_mono_to_stereo(struct snd_kcontrol *kcontrol, 224 struct snd_ctl_elem_value *ucontrol) 225 { 226 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 227 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 228 unsigned int value = ucontrol->value.enumerated.item[0]; 229 230 if (value == dmic->mono_to_stereo) 231 return 0; 232 233 dmic->mono_to_stereo = value; 234 235 return 1; 236 } 237 238 static int tegra210_dmic_get_stereo_to_mono(struct snd_kcontrol *kcontrol, 239 struct snd_ctl_elem_value *ucontrol) 240 { 241 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 242 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 243 244 ucontrol->value.enumerated.item[0] = dmic->stereo_to_mono; 245 246 return 0; 247 } 248 249 static int tegra210_dmic_put_stereo_to_mono(struct snd_kcontrol *kcontrol, 250 struct snd_ctl_elem_value *ucontrol) 251 { 252 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 253 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 254 unsigned int value = ucontrol->value.enumerated.item[0]; 255 256 if (value == dmic->stereo_to_mono) 257 return 0; 258 259 dmic->stereo_to_mono = value; 260 261 return 1; 262 } 263 264 static int tegra210_dmic_get_osr_val(struct snd_kcontrol *kcontrol, 265 struct snd_ctl_elem_value *ucontrol) 266 { 267 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 268 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 269 270 ucontrol->value.enumerated.item[0] = dmic->osr_val; 271 272 return 0; 273 } 274 275 static int tegra210_dmic_put_osr_val(struct snd_kcontrol *kcontrol, 276 struct snd_ctl_elem_value *ucontrol) 277 { 278 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 279 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 280 unsigned int value = ucontrol->value.enumerated.item[0]; 281 282 if (value == dmic->osr_val) 283 return 0; 284 285 dmic->osr_val = value; 286 287 return 1; 288 } 289 290 static int tegra210_dmic_get_pol_sel(struct snd_kcontrol *kcontrol, 291 struct snd_ctl_elem_value *ucontrol) 292 { 293 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 294 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 295 296 ucontrol->value.enumerated.item[0] = dmic->lrsel; 297 298 return 0; 299 } 300 301 static int tegra210_dmic_put_pol_sel(struct snd_kcontrol *kcontrol, 302 struct snd_ctl_elem_value *ucontrol) 303 { 304 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 305 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 306 unsigned int value = ucontrol->value.enumerated.item[0]; 307 308 if (value == dmic->lrsel) 309 return 0; 310 311 dmic->lrsel = value; 312 313 return 1; 314 } 315 316 static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { 317 .hw_params = tegra210_dmic_hw_params, 318 }; 319 320 static struct snd_soc_dai_driver tegra210_dmic_dais[] = { 321 { 322 .name = "DMIC-CIF", 323 .capture = { 324 .stream_name = "CIF-Capture", 325 .channels_min = 1, 326 .channels_max = 2, 327 .rates = SNDRV_PCM_RATE_8000_48000, 328 .formats = SNDRV_PCM_FMTBIT_S16_LE | 329 SNDRV_PCM_FMTBIT_S24_LE | 330 SNDRV_PCM_FMTBIT_S32_LE, 331 }, 332 }, 333 { 334 .name = "DMIC-DAP", 335 .capture = { 336 .stream_name = "DAP-Capture", 337 .channels_min = 1, 338 .channels_max = 2, 339 .rates = SNDRV_PCM_RATE_8000_48000, 340 .formats = SNDRV_PCM_FMTBIT_S16_LE | 341 SNDRV_PCM_FMTBIT_S24_LE | 342 SNDRV_PCM_FMTBIT_S32_LE, 343 }, 344 .ops = &tegra210_dmic_dai_ops, 345 .symmetric_rate = 1, 346 }, 347 }; 348 349 static const struct snd_soc_dapm_widget tegra210_dmic_widgets[] = { 350 SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_DMIC_ENABLE, 0, 0), 351 SND_SOC_DAPM_MIC("MIC", NULL), 352 }; 353 354 static const struct snd_soc_dapm_route tegra210_dmic_routes[] = { 355 { "XBAR-RX", NULL, "XBAR-Capture" }, 356 { "XBAR-Capture", NULL, "CIF-Capture" }, 357 { "CIF-Capture", NULL, "TX" }, 358 { "TX", NULL, "DAP-Capture" }, 359 { "DAP-Capture", NULL, "MIC" }, 360 }; 361 362 static const char * const tegra210_dmic_ch_select[] = { 363 "Left", "Right", "Stereo", 364 }; 365 366 static const struct soc_enum tegra210_dmic_ch_enum = 367 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_ch_select), 368 tegra210_dmic_ch_select); 369 370 static const char * const tegra210_dmic_mono_conv_text[] = { 371 "Zero", "Copy", 372 }; 373 374 static const char * const tegra210_dmic_stereo_conv_text[] = { 375 "CH0", "CH1", "AVG", 376 }; 377 378 static const struct soc_enum tegra210_dmic_mono_conv_enum = 379 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_mono_conv_text), 380 tegra210_dmic_mono_conv_text); 381 382 static const struct soc_enum tegra210_dmic_stereo_conv_enum = 383 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_stereo_conv_text), 384 tegra210_dmic_stereo_conv_text); 385 386 static const char * const tegra210_dmic_osr_text[] = { 387 "OSR_64", "OSR_128", "OSR_256", 388 }; 389 390 static const struct soc_enum tegra210_dmic_osr_enum = 391 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_osr_text), 392 tegra210_dmic_osr_text); 393 394 static const char * const tegra210_dmic_lrsel_text[] = { 395 "Left", "Right", 396 }; 397 398 static const struct soc_enum tegra210_dmic_lrsel_enum = 399 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_lrsel_text), 400 tegra210_dmic_lrsel_text); 401 402 static const struct snd_kcontrol_new tegra210_dmic_controls[] = { 403 SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, 404 tegra210_dmic_get_boost_gain, 405 tegra210_dmic_put_boost_gain), 406 SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, 407 tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select), 408 SOC_ENUM_EXT("Mono To Stereo", 409 tegra210_dmic_mono_conv_enum, 410 tegra210_dmic_get_mono_to_stereo, 411 tegra210_dmic_put_mono_to_stereo), 412 SOC_ENUM_EXT("Stereo To Mono", 413 tegra210_dmic_stereo_conv_enum, 414 tegra210_dmic_get_stereo_to_mono, 415 tegra210_dmic_put_stereo_to_mono), 416 SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, 417 tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val), 418 SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, 419 tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel), 420 }; 421 422 static const struct snd_soc_component_driver tegra210_dmic_compnt = { 423 .dapm_widgets = tegra210_dmic_widgets, 424 .num_dapm_widgets = ARRAY_SIZE(tegra210_dmic_widgets), 425 .dapm_routes = tegra210_dmic_routes, 426 .num_dapm_routes = ARRAY_SIZE(tegra210_dmic_routes), 427 .controls = tegra210_dmic_controls, 428 .num_controls = ARRAY_SIZE(tegra210_dmic_controls), 429 }; 430 431 static bool tegra210_dmic_wr_reg(struct device *dev, unsigned int reg) 432 { 433 switch (reg) { 434 case TEGRA210_DMIC_TX_INT_MASK ... TEGRA210_DMIC_TX_CIF_CTRL: 435 case TEGRA210_DMIC_ENABLE ... TEGRA210_DMIC_CG: 436 case TEGRA210_DMIC_CTRL: 437 case TEGRA210_DMIC_DBG_CTRL: 438 case TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4 ... TEGRA210_DMIC_LP_BIQUAD_1_COEF_4: 439 return true; 440 default: 441 return false; 442 } 443 } 444 445 static bool tegra210_dmic_rd_reg(struct device *dev, unsigned int reg) 446 { 447 if (tegra210_dmic_wr_reg(dev, reg)) 448 return true; 449 450 switch (reg) { 451 case TEGRA210_DMIC_TX_STATUS: 452 case TEGRA210_DMIC_TX_INT_STATUS: 453 case TEGRA210_DMIC_STATUS: 454 case TEGRA210_DMIC_INT_STATUS: 455 return true; 456 default: 457 return false; 458 } 459 } 460 461 static bool tegra210_dmic_volatile_reg(struct device *dev, unsigned int reg) 462 { 463 switch (reg) { 464 case TEGRA210_DMIC_TX_STATUS: 465 case TEGRA210_DMIC_TX_INT_STATUS: 466 case TEGRA210_DMIC_TX_INT_SET: 467 case TEGRA210_DMIC_SOFT_RESET: 468 case TEGRA210_DMIC_STATUS: 469 case TEGRA210_DMIC_INT_STATUS: 470 return true; 471 default: 472 return false; 473 } 474 } 475 476 static const struct regmap_config tegra210_dmic_regmap_config = { 477 .reg_bits = 32, 478 .reg_stride = 4, 479 .val_bits = 32, 480 .max_register = TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 481 .writeable_reg = tegra210_dmic_wr_reg, 482 .readable_reg = tegra210_dmic_rd_reg, 483 .volatile_reg = tegra210_dmic_volatile_reg, 484 .reg_defaults = tegra210_dmic_reg_defaults, 485 .num_reg_defaults = ARRAY_SIZE(tegra210_dmic_reg_defaults), 486 .cache_type = REGCACHE_FLAT, 487 }; 488 489 static int tegra210_dmic_probe(struct platform_device *pdev) 490 { 491 struct device *dev = &pdev->dev; 492 struct tegra210_dmic *dmic; 493 void __iomem *regs; 494 int err; 495 496 dmic = devm_kzalloc(dev, sizeof(*dmic), GFP_KERNEL); 497 if (!dmic) 498 return -ENOMEM; 499 500 dmic->osr_val = DMIC_OSR_64; 501 dmic->ch_select = DMIC_CH_SELECT_STEREO; 502 dmic->lrsel = DMIC_LRSEL_LEFT; 503 dmic->boost_gain = 0; 504 dmic->stereo_to_mono = 0; /* "CH0" */ 505 506 dev_set_drvdata(dev, dmic); 507 508 dmic->clk_dmic = devm_clk_get(dev, "dmic"); 509 if (IS_ERR(dmic->clk_dmic)) { 510 dev_err(dev, "can't retrieve DMIC clock\n"); 511 return PTR_ERR(dmic->clk_dmic); 512 } 513 514 regs = devm_platform_ioremap_resource(pdev, 0); 515 if (IS_ERR(regs)) 516 return PTR_ERR(regs); 517 518 dmic->regmap = devm_regmap_init_mmio(dev, regs, 519 &tegra210_dmic_regmap_config); 520 if (IS_ERR(dmic->regmap)) { 521 dev_err(dev, "regmap init failed\n"); 522 return PTR_ERR(dmic->regmap); 523 } 524 525 regcache_cache_only(dmic->regmap, true); 526 527 err = devm_snd_soc_register_component(dev, &tegra210_dmic_compnt, 528 tegra210_dmic_dais, 529 ARRAY_SIZE(tegra210_dmic_dais)); 530 if (err) { 531 dev_err(dev, "can't register DMIC component, err: %d\n", err); 532 return err; 533 } 534 535 pm_runtime_enable(dev); 536 537 return 0; 538 } 539 540 static void tegra210_dmic_remove(struct platform_device *pdev) 541 { 542 pm_runtime_disable(&pdev->dev); 543 } 544 545 static const struct dev_pm_ops tegra210_dmic_pm_ops = { 546 SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend, 547 tegra210_dmic_runtime_resume, NULL) 548 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 549 pm_runtime_force_resume) 550 }; 551 552 static const struct of_device_id tegra210_dmic_of_match[] = { 553 { .compatible = "nvidia,tegra210-dmic" }, 554 {}, 555 }; 556 MODULE_DEVICE_TABLE(of, tegra210_dmic_of_match); 557 558 static struct platform_driver tegra210_dmic_driver = { 559 .driver = { 560 .name = "tegra210-dmic", 561 .of_match_table = tegra210_dmic_of_match, 562 .pm = &tegra210_dmic_pm_ops, 563 }, 564 .probe = tegra210_dmic_probe, 565 .remove = tegra210_dmic_remove, 566 }; 567 module_platform_driver(tegra210_dmic_driver) 568 569 MODULE_AUTHOR("Rahul Mittal <rmittal@nvidia.com>"); 570 MODULE_DESCRIPTION("Tegra210 ASoC DMIC driver"); 571 MODULE_LICENSE("GPL v2"); 572