1 // SPDX-License-Identifier: GPL-2.0-only 2 // SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 // 4 // tegra186_dspk.c - Tegra186 DSPK driver 5 6 #include <linux/clk.h> 7 #include <linux/device.h> 8 #include <linux/mod_devicetable.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/pm_runtime.h> 13 #include <linux/regmap.h> 14 #include <sound/core.h> 15 #include <sound/pcm_params.h> 16 #include <sound/soc.h> 17 #include "tegra186_dspk.h" 18 #include "tegra_cif.h" 19 20 static const struct reg_default tegra186_dspk_reg_defaults[] = { 21 { TEGRA186_DSPK_RX_INT_MASK, 0x00000007 }, 22 { TEGRA186_DSPK_RX_CIF_CTRL, 0x00007700 }, 23 { TEGRA186_DSPK_CG, 0x00000001 }, 24 { TEGRA186_DSPK_CORE_CTRL, 0x00000310 }, 25 { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, 26 }; 27 28 static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol, 29 struct snd_ctl_elem_value *ucontrol) 30 { 31 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 32 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 33 34 ucontrol->value.integer.value[0] = dspk->rx_fifo_th; 35 36 return 0; 37 } 38 39 static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol, 40 struct snd_ctl_elem_value *ucontrol) 41 { 42 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 43 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 44 int value = ucontrol->value.integer.value[0]; 45 46 if (value == dspk->rx_fifo_th) 47 return 0; 48 49 dspk->rx_fifo_th = value; 50 51 return 1; 52 } 53 54 static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol, 55 struct snd_ctl_elem_value *ucontrol) 56 { 57 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 58 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 59 60 ucontrol->value.enumerated.item[0] = dspk->osr_val; 61 62 return 0; 63 } 64 65 static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol, 66 struct snd_ctl_elem_value *ucontrol) 67 { 68 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 69 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 70 unsigned int value = ucontrol->value.enumerated.item[0]; 71 72 if (value == dspk->osr_val) 73 return 0; 74 75 dspk->osr_val = value; 76 77 return 1; 78 } 79 80 static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol, 81 struct snd_ctl_elem_value *ucontrol) 82 { 83 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 84 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 85 86 ucontrol->value.enumerated.item[0] = dspk->lrsel; 87 88 return 0; 89 } 90 91 static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol, 92 struct snd_ctl_elem_value *ucontrol) 93 { 94 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 95 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 96 unsigned int value = ucontrol->value.enumerated.item[0]; 97 98 if (value == dspk->lrsel) 99 return 0; 100 101 dspk->lrsel = value; 102 103 return 1; 104 } 105 106 static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol, 107 struct snd_ctl_elem_value *ucontrol) 108 { 109 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 110 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 111 112 ucontrol->value.enumerated.item[0] = dspk->ch_sel; 113 114 return 0; 115 } 116 117 static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol, 118 struct snd_ctl_elem_value *ucontrol) 119 { 120 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 121 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 122 unsigned int value = ucontrol->value.enumerated.item[0]; 123 124 if (value == dspk->ch_sel) 125 return 0; 126 127 dspk->ch_sel = value; 128 129 return 1; 130 } 131 132 static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol, 133 struct snd_ctl_elem_value *ucontrol) 134 { 135 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 136 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 137 138 ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo; 139 140 return 0; 141 } 142 143 static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol, 144 struct snd_ctl_elem_value *ucontrol) 145 { 146 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 147 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 148 unsigned int value = ucontrol->value.enumerated.item[0]; 149 150 if (value == dspk->mono_to_stereo) 151 return 0; 152 153 dspk->mono_to_stereo = value; 154 155 return 1; 156 } 157 158 static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol, 159 struct snd_ctl_elem_value *ucontrol) 160 { 161 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 162 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 163 164 ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono; 165 166 return 0; 167 } 168 169 static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol, 170 struct snd_ctl_elem_value *ucontrol) 171 { 172 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 173 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); 174 unsigned int value = ucontrol->value.enumerated.item[0]; 175 176 if (value == dspk->stereo_to_mono) 177 return 0; 178 179 dspk->stereo_to_mono = value; 180 181 return 1; 182 } 183 184 static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev) 185 { 186 struct tegra186_dspk *dspk = dev_get_drvdata(dev); 187 188 regcache_cache_only(dspk->regmap, true); 189 regcache_mark_dirty(dspk->regmap); 190 191 clk_disable_unprepare(dspk->clk_dspk); 192 193 return 0; 194 } 195 196 static int __maybe_unused tegra186_dspk_runtime_resume(struct device *dev) 197 { 198 struct tegra186_dspk *dspk = dev_get_drvdata(dev); 199 int err; 200 201 err = clk_prepare_enable(dspk->clk_dspk); 202 if (err) { 203 dev_err(dev, "failed to enable DSPK clock, err: %d\n", err); 204 return err; 205 } 206 207 regcache_cache_only(dspk->regmap, false); 208 regcache_sync(dspk->regmap); 209 210 return 0; 211 } 212 213 static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream, 214 struct snd_pcm_hw_params *params, 215 struct snd_soc_dai *dai) 216 { 217 struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai); 218 unsigned int channels, srate, dspk_clk; 219 struct device *dev = dai->dev; 220 struct tegra_cif_conf cif_conf; 221 unsigned int max_th; 222 int err; 223 224 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); 225 226 channels = params_channels(params); 227 cif_conf.audio_ch = channels; 228 229 /* Client channel */ 230 switch (dspk->ch_sel) { 231 case DSPK_CH_SELECT_LEFT: 232 case DSPK_CH_SELECT_RIGHT: 233 cif_conf.client_ch = 1; 234 break; 235 case DSPK_CH_SELECT_STEREO: 236 cif_conf.client_ch = 2; 237 break; 238 default: 239 dev_err(dev, "Invalid DSPK client channels\n"); 240 return -EINVAL; 241 } 242 243 switch (params_format(params)) { 244 case SNDRV_PCM_FORMAT_S16_LE: 245 cif_conf.audio_bits = TEGRA_ACIF_BITS_16; 246 cif_conf.client_bits = TEGRA_ACIF_BITS_16; 247 break; 248 case SNDRV_PCM_FORMAT_S24_LE: 249 case SNDRV_PCM_FORMAT_S32_LE: 250 cif_conf.audio_bits = TEGRA_ACIF_BITS_32; 251 cif_conf.client_bits = TEGRA_ACIF_BITS_24; 252 break; 253 default: 254 dev_err(dev, "unsupported format!\n"); 255 return -EOPNOTSUPP; 256 } 257 258 srate = params_rate(params); 259 260 /* RX FIFO threshold in terms of frames */ 261 max_th = (TEGRA186_DSPK_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1; 262 263 if (dspk->rx_fifo_th > max_th) 264 dspk->rx_fifo_th = max_th; 265 266 cif_conf.threshold = dspk->rx_fifo_th; 267 cif_conf.mono_conv = dspk->mono_to_stereo; 268 cif_conf.stereo_conv = dspk->stereo_to_mono; 269 270 tegra_set_cif(dspk->regmap, TEGRA186_DSPK_RX_CIF_CTRL, 271 &cif_conf); 272 273 /* 274 * DSPK clock and PDM codec clock should be synchronous with 4:1 ratio, 275 * this is because it takes 4 clock cycles to send out one sample to 276 * codec by sigma delta modulator. Finally the clock rate is a multiple 277 * of 'Over Sampling Ratio', 'Sample Rate' and 'Interface Clock Ratio'. 278 */ 279 dspk_clk = (DSPK_OSR_FACTOR << dspk->osr_val) * srate * DSPK_CLK_RATIO; 280 281 err = clk_set_rate(dspk->clk_dspk, dspk_clk); 282 if (err) { 283 dev_err(dev, "can't set DSPK clock rate %u, err: %d\n", 284 dspk_clk, err); 285 286 return err; 287 } 288 289 regmap_update_bits(dspk->regmap, 290 /* Reg */ 291 TEGRA186_DSPK_CORE_CTRL, 292 /* Mask */ 293 TEGRA186_DSPK_OSR_MASK | 294 TEGRA186_DSPK_CHANNEL_SELECT_MASK | 295 TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK, 296 /* Value */ 297 (dspk->osr_val << DSPK_OSR_SHIFT) | 298 ((dspk->ch_sel + 1) << CH_SEL_SHIFT) | 299 (dspk->lrsel << LRSEL_POL_SHIFT)); 300 301 return 0; 302 } 303 304 static const struct snd_soc_dai_ops tegra186_dspk_dai_ops = { 305 .hw_params = tegra186_dspk_hw_params, 306 }; 307 308 static struct snd_soc_dai_driver tegra186_dspk_dais[] = { 309 { 310 .name = "DSPK-CIF", 311 .playback = { 312 .stream_name = "CIF-Playback", 313 .channels_min = 1, 314 .channels_max = 2, 315 .rates = SNDRV_PCM_RATE_8000_48000, 316 .formats = SNDRV_PCM_FMTBIT_S16_LE | 317 SNDRV_PCM_FMTBIT_S24_LE | 318 SNDRV_PCM_FMTBIT_S32_LE, 319 }, 320 }, 321 { 322 .name = "DSPK-DAP", 323 .playback = { 324 .stream_name = "DAP-Playback", 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 .ops = &tegra186_dspk_dai_ops, 333 .symmetric_rate = 1, 334 }, 335 }; 336 337 static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = { 338 SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0), 339 SND_SOC_DAPM_SPK("SPK", NULL), 340 }; 341 342 static const struct snd_soc_dapm_route tegra186_dspk_routes[] = { 343 { "XBAR-Playback", NULL, "XBAR-TX" }, 344 { "CIF-Playback", NULL, "XBAR-Playback" }, 345 { "RX", NULL, "CIF-Playback" }, 346 { "DAP-Playback", NULL, "RX" }, 347 { "SPK", NULL, "DAP-Playback" }, 348 }; 349 350 static const char * const tegra186_dspk_ch_sel_text[] = { 351 "Left", "Right", "Stereo", 352 }; 353 354 static const struct soc_enum tegra186_dspk_ch_sel_enum = 355 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_ch_sel_text), 356 tegra186_dspk_ch_sel_text); 357 358 static const char * const tegra186_dspk_osr_text[] = { 359 "OSR_32", "OSR_64", "OSR_128", "OSR_256", 360 }; 361 362 static const struct soc_enum tegra186_dspk_osr_enum = 363 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_osr_text), 364 tegra186_dspk_osr_text); 365 366 static const char * const tegra186_dspk_lrsel_text[] = { 367 "Left", "Right", 368 }; 369 370 static const char * const tegra186_dspk_mono_conv_text[] = { 371 "Zero", "Copy", 372 }; 373 374 static const struct soc_enum tegra186_dspk_mono_conv_enum = 375 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 376 ARRAY_SIZE(tegra186_dspk_mono_conv_text), 377 tegra186_dspk_mono_conv_text); 378 379 static const char * const tegra186_dspk_stereo_conv_text[] = { 380 "CH0", "CH1", "AVG", 381 }; 382 383 static const struct soc_enum tegra186_dspk_stereo_conv_enum = 384 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 385 ARRAY_SIZE(tegra186_dspk_stereo_conv_text), 386 tegra186_dspk_stereo_conv_text); 387 388 static const struct soc_enum tegra186_dspk_lrsel_enum = 389 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_lrsel_text), 390 tegra186_dspk_lrsel_text); 391 392 static const struct snd_kcontrol_new tegrat186_dspk_controls[] = { 393 SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0, 394 TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0, 395 tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th), 396 SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum, 397 tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val), 398 SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum, 399 tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel), 400 SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum, 401 tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel), 402 SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum, 403 tegra186_dspk_get_mono_to_stereo, 404 tegra186_dspk_put_mono_to_stereo), 405 SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum, 406 tegra186_dspk_get_stereo_to_mono, 407 tegra186_dspk_put_stereo_to_mono), 408 }; 409 410 static const struct snd_soc_component_driver tegra186_dspk_cmpnt = { 411 .dapm_widgets = tegra186_dspk_widgets, 412 .num_dapm_widgets = ARRAY_SIZE(tegra186_dspk_widgets), 413 .dapm_routes = tegra186_dspk_routes, 414 .num_dapm_routes = ARRAY_SIZE(tegra186_dspk_routes), 415 .controls = tegrat186_dspk_controls, 416 .num_controls = ARRAY_SIZE(tegrat186_dspk_controls), 417 }; 418 419 static bool tegra186_dspk_wr_reg(struct device *dev, unsigned int reg) 420 { 421 switch (reg) { 422 case TEGRA186_DSPK_RX_INT_MASK ... TEGRA186_DSPK_RX_CIF_CTRL: 423 case TEGRA186_DSPK_ENABLE ... TEGRA186_DSPK_CG: 424 case TEGRA186_DSPK_CORE_CTRL ... TEGRA186_DSPK_CODEC_CTRL: 425 return true; 426 default: 427 return false; 428 } 429 } 430 431 static bool tegra186_dspk_rd_reg(struct device *dev, unsigned int reg) 432 { 433 if (tegra186_dspk_wr_reg(dev, reg)) 434 return true; 435 436 switch (reg) { 437 case TEGRA186_DSPK_RX_STATUS: 438 case TEGRA186_DSPK_RX_INT_STATUS: 439 case TEGRA186_DSPK_STATUS: 440 case TEGRA186_DSPK_INT_STATUS: 441 return true; 442 default: 443 return false; 444 } 445 } 446 447 static bool tegra186_dspk_volatile_reg(struct device *dev, unsigned int reg) 448 { 449 switch (reg) { 450 case TEGRA186_DSPK_RX_STATUS: 451 case TEGRA186_DSPK_RX_INT_STATUS: 452 case TEGRA186_DSPK_STATUS: 453 case TEGRA186_DSPK_INT_STATUS: 454 return true; 455 default: 456 return false; 457 } 458 } 459 460 static const struct regmap_config tegra186_dspk_regmap = { 461 .reg_bits = 32, 462 .reg_stride = 4, 463 .val_bits = 32, 464 .max_register = TEGRA186_DSPK_CODEC_CTRL, 465 .writeable_reg = tegra186_dspk_wr_reg, 466 .readable_reg = tegra186_dspk_rd_reg, 467 .volatile_reg = tegra186_dspk_volatile_reg, 468 .reg_defaults = tegra186_dspk_reg_defaults, 469 .num_reg_defaults = ARRAY_SIZE(tegra186_dspk_reg_defaults), 470 .cache_type = REGCACHE_FLAT, 471 }; 472 473 static const struct of_device_id tegra186_dspk_of_match[] = { 474 { .compatible = "nvidia,tegra186-dspk" }, 475 {}, 476 }; 477 MODULE_DEVICE_TABLE(of, tegra186_dspk_of_match); 478 479 static int tegra186_dspk_platform_probe(struct platform_device *pdev) 480 { 481 struct device *dev = &pdev->dev; 482 struct tegra186_dspk *dspk; 483 void __iomem *regs; 484 int err; 485 486 dspk = devm_kzalloc(dev, sizeof(*dspk), GFP_KERNEL); 487 if (!dspk) 488 return -ENOMEM; 489 490 dspk->osr_val = DSPK_OSR_64; 491 dspk->lrsel = DSPK_LRSEL_LEFT; 492 dspk->ch_sel = DSPK_CH_SELECT_STEREO; 493 dspk->mono_to_stereo = 0; /* "Zero" */ 494 495 dev_set_drvdata(dev, dspk); 496 497 dspk->clk_dspk = devm_clk_get(dev, "dspk"); 498 if (IS_ERR(dspk->clk_dspk)) { 499 dev_err(dev, "can't retrieve DSPK clock\n"); 500 return PTR_ERR(dspk->clk_dspk); 501 } 502 503 regs = devm_platform_ioremap_resource(pdev, 0); 504 if (IS_ERR(regs)) 505 return PTR_ERR(regs); 506 507 dspk->regmap = devm_regmap_init_mmio(dev, regs, &tegra186_dspk_regmap); 508 if (IS_ERR(dspk->regmap)) { 509 dev_err(dev, "regmap init failed\n"); 510 return PTR_ERR(dspk->regmap); 511 } 512 513 regcache_cache_only(dspk->regmap, true); 514 515 err = devm_snd_soc_register_component(dev, &tegra186_dspk_cmpnt, 516 tegra186_dspk_dais, 517 ARRAY_SIZE(tegra186_dspk_dais)); 518 if (err) { 519 dev_err(dev, "can't register DSPK component, err: %d\n", 520 err); 521 return err; 522 } 523 524 pm_runtime_enable(dev); 525 526 return 0; 527 } 528 529 static void tegra186_dspk_platform_remove(struct platform_device *pdev) 530 { 531 pm_runtime_disable(&pdev->dev); 532 } 533 534 static const struct dev_pm_ops tegra186_dspk_pm_ops = { 535 SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend, 536 tegra186_dspk_runtime_resume, NULL) 537 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 538 pm_runtime_force_resume) 539 }; 540 541 static struct platform_driver tegra186_dspk_driver = { 542 .driver = { 543 .name = "tegra186-dspk", 544 .of_match_table = tegra186_dspk_of_match, 545 .pm = &tegra186_dspk_pm_ops, 546 }, 547 .probe = tegra186_dspk_platform_probe, 548 .remove = tegra186_dspk_platform_remove, 549 }; 550 module_platform_driver(tegra186_dspk_driver); 551 552 MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>"); 553 MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>"); 554 MODULE_DESCRIPTION("Tegra186 ASoC DSPK driver"); 555 MODULE_LICENSE("GPL v2"); 556