1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // tegra210_dmic.c - Tegra210 DMIC driver 4 // 5 // Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. 6 7 #include <linux/clk.h> 8 #include <linux/device.h> 9 #include <linux/math64.h> 10 #include <linux/module.h> 11 #include <linux/of_device.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_S32_LE: 143 cif_conf.audio_bits = TEGRA_ACIF_BITS_32; 144 break; 145 default: 146 dev_err(dai->dev, "unsupported format!\n"); 147 return -EOPNOTSUPP; 148 } 149 150 cif_conf.client_bits = TEGRA_ACIF_BITS_24; 151 cif_conf.mono_conv = dmic->mono_to_stereo; 152 cif_conf.stereo_conv = dmic->stereo_to_mono; 153 154 tegra_set_cif(dmic->regmap, TEGRA210_DMIC_TX_CIF_CTRL, &cif_conf); 155 156 return 0; 157 } 158 159 static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol, 160 struct snd_ctl_elem_value *ucontrol) 161 { 162 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 163 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 164 165 if (strstr(kcontrol->id.name, "Boost Gain Volume")) 166 ucontrol->value.integer.value[0] = dmic->boost_gain; 167 else if (strstr(kcontrol->id.name, "Channel Select")) 168 ucontrol->value.integer.value[0] = dmic->ch_select; 169 else if (strstr(kcontrol->id.name, "Mono To Stereo")) 170 ucontrol->value.integer.value[0] = dmic->mono_to_stereo; 171 else if (strstr(kcontrol->id.name, "Stereo To Mono")) 172 ucontrol->value.integer.value[0] = dmic->stereo_to_mono; 173 else if (strstr(kcontrol->id.name, "OSR Value")) 174 ucontrol->value.integer.value[0] = dmic->osr_val; 175 else if (strstr(kcontrol->id.name, "LR Polarity Select")) 176 ucontrol->value.integer.value[0] = dmic->lrsel; 177 178 return 0; 179 } 180 181 static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, 182 struct snd_ctl_elem_value *ucontrol) 183 { 184 struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 185 struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); 186 int value = ucontrol->value.integer.value[0]; 187 188 if (strstr(kcontrol->id.name, "Boost Gain Volume")) 189 dmic->boost_gain = value; 190 else if (strstr(kcontrol->id.name, "Channel Select")) 191 dmic->ch_select = ucontrol->value.integer.value[0]; 192 else if (strstr(kcontrol->id.name, "Mono To Stereo")) 193 dmic->mono_to_stereo = value; 194 else if (strstr(kcontrol->id.name, "Stereo To Mono")) 195 dmic->stereo_to_mono = value; 196 else if (strstr(kcontrol->id.name, "OSR Value")) 197 dmic->osr_val = value; 198 else if (strstr(kcontrol->id.name, "LR Polarity Select")) 199 dmic->lrsel = value; 200 201 return 0; 202 } 203 204 static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { 205 .hw_params = tegra210_dmic_hw_params, 206 }; 207 208 static struct snd_soc_dai_driver tegra210_dmic_dais[] = { 209 { 210 .name = "DMIC-CIF", 211 .capture = { 212 .stream_name = "CIF-Capture", 213 .channels_min = 1, 214 .channels_max = 2, 215 .rates = SNDRV_PCM_RATE_8000_48000, 216 .formats = SNDRV_PCM_FMTBIT_S16_LE | 217 SNDRV_PCM_FMTBIT_S32_LE, 218 }, 219 }, 220 { 221 .name = "DMIC-DAP", 222 .capture = { 223 .stream_name = "DAP-Capture", 224 .channels_min = 1, 225 .channels_max = 2, 226 .rates = SNDRV_PCM_RATE_8000_48000, 227 .formats = SNDRV_PCM_FMTBIT_S16_LE | 228 SNDRV_PCM_FMTBIT_S32_LE, 229 }, 230 .ops = &tegra210_dmic_dai_ops, 231 .symmetric_rate = 1, 232 }, 233 }; 234 235 static const struct snd_soc_dapm_widget tegra210_dmic_widgets[] = { 236 SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_DMIC_ENABLE, 0, 0), 237 SND_SOC_DAPM_MIC("MIC", NULL), 238 }; 239 240 static const struct snd_soc_dapm_route tegra210_dmic_routes[] = { 241 { "XBAR-RX", NULL, "XBAR-Capture" }, 242 { "XBAR-Capture", NULL, "CIF-Capture" }, 243 { "CIF-Capture", NULL, "TX" }, 244 { "TX", NULL, "DAP-Capture" }, 245 { "DAP-Capture", NULL, "MIC" }, 246 }; 247 248 static const char * const tegra210_dmic_ch_select[] = { 249 "Left", "Right", "Stereo", 250 }; 251 252 static const struct soc_enum tegra210_dmic_ch_enum = 253 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_ch_select), 254 tegra210_dmic_ch_select); 255 256 static const char * const tegra210_dmic_mono_conv_text[] = { 257 "Zero", "Copy", 258 }; 259 260 static const char * const tegra210_dmic_stereo_conv_text[] = { 261 "CH0", "CH1", "AVG", 262 }; 263 264 static const struct soc_enum tegra210_dmic_mono_conv_enum = 265 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_mono_conv_text), 266 tegra210_dmic_mono_conv_text); 267 268 static const struct soc_enum tegra210_dmic_stereo_conv_enum = 269 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_stereo_conv_text), 270 tegra210_dmic_stereo_conv_text); 271 272 static const char * const tegra210_dmic_osr_text[] = { 273 "OSR_64", "OSR_128", "OSR_256", 274 }; 275 276 static const struct soc_enum tegra210_dmic_osr_enum = 277 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_osr_text), 278 tegra210_dmic_osr_text); 279 280 static const char * const tegra210_dmic_lrsel_text[] = { 281 "Left", "Right", 282 }; 283 284 static const struct soc_enum tegra210_dmic_lrsel_enum = 285 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_lrsel_text), 286 tegra210_dmic_lrsel_text); 287 288 static const struct snd_kcontrol_new tegra210_dmic_controls[] = { 289 SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, 290 tegra210_dmic_get_control, tegra210_dmic_put_control), 291 SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, 292 tegra210_dmic_get_control, tegra210_dmic_put_control), 293 SOC_ENUM_EXT("Mono To Stereo", 294 tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, 295 tegra210_dmic_put_control), 296 SOC_ENUM_EXT("Stereo To Mono", 297 tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, 298 tegra210_dmic_put_control), 299 SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, 300 tegra210_dmic_get_control, tegra210_dmic_put_control), 301 SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, 302 tegra210_dmic_get_control, tegra210_dmic_put_control), 303 }; 304 305 static const struct snd_soc_component_driver tegra210_dmic_compnt = { 306 .dapm_widgets = tegra210_dmic_widgets, 307 .num_dapm_widgets = ARRAY_SIZE(tegra210_dmic_widgets), 308 .dapm_routes = tegra210_dmic_routes, 309 .num_dapm_routes = ARRAY_SIZE(tegra210_dmic_routes), 310 .controls = tegra210_dmic_controls, 311 .num_controls = ARRAY_SIZE(tegra210_dmic_controls), 312 }; 313 314 static bool tegra210_dmic_wr_reg(struct device *dev, unsigned int reg) 315 { 316 switch (reg) { 317 case TEGRA210_DMIC_TX_INT_MASK ... TEGRA210_DMIC_TX_CIF_CTRL: 318 case TEGRA210_DMIC_ENABLE ... TEGRA210_DMIC_CG: 319 case TEGRA210_DMIC_CTRL: 320 case TEGRA210_DMIC_DBG_CTRL: 321 case TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4 ... TEGRA210_DMIC_LP_BIQUAD_1_COEF_4: 322 return true; 323 default: 324 return false; 325 } 326 } 327 328 static bool tegra210_dmic_rd_reg(struct device *dev, unsigned int reg) 329 { 330 if (tegra210_dmic_wr_reg(dev, reg)) 331 return true; 332 333 switch (reg) { 334 case TEGRA210_DMIC_TX_STATUS: 335 case TEGRA210_DMIC_TX_INT_STATUS: 336 case TEGRA210_DMIC_STATUS: 337 case TEGRA210_DMIC_INT_STATUS: 338 return true; 339 default: 340 return false; 341 } 342 } 343 344 static bool tegra210_dmic_volatile_reg(struct device *dev, unsigned int reg) 345 { 346 switch (reg) { 347 case TEGRA210_DMIC_TX_STATUS: 348 case TEGRA210_DMIC_TX_INT_STATUS: 349 case TEGRA210_DMIC_TX_INT_SET: 350 case TEGRA210_DMIC_SOFT_RESET: 351 case TEGRA210_DMIC_STATUS: 352 case TEGRA210_DMIC_INT_STATUS: 353 return true; 354 default: 355 return false; 356 } 357 } 358 359 static const struct regmap_config tegra210_dmic_regmap_config = { 360 .reg_bits = 32, 361 .reg_stride = 4, 362 .val_bits = 32, 363 .max_register = TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 364 .writeable_reg = tegra210_dmic_wr_reg, 365 .readable_reg = tegra210_dmic_rd_reg, 366 .volatile_reg = tegra210_dmic_volatile_reg, 367 .reg_defaults = tegra210_dmic_reg_defaults, 368 .num_reg_defaults = ARRAY_SIZE(tegra210_dmic_reg_defaults), 369 .cache_type = REGCACHE_FLAT, 370 }; 371 372 static int tegra210_dmic_probe(struct platform_device *pdev) 373 { 374 struct device *dev = &pdev->dev; 375 struct tegra210_dmic *dmic; 376 void __iomem *regs; 377 int err; 378 379 dmic = devm_kzalloc(dev, sizeof(*dmic), GFP_KERNEL); 380 if (!dmic) 381 return -ENOMEM; 382 383 dmic->osr_val = DMIC_OSR_64; 384 dmic->ch_select = DMIC_CH_SELECT_STEREO; 385 dmic->lrsel = DMIC_LRSEL_LEFT; 386 dmic->boost_gain = 0; 387 dmic->stereo_to_mono = 0; /* "CH0" */ 388 389 dev_set_drvdata(dev, dmic); 390 391 dmic->clk_dmic = devm_clk_get(dev, "dmic"); 392 if (IS_ERR(dmic->clk_dmic)) { 393 dev_err(dev, "can't retrieve DMIC clock\n"); 394 return PTR_ERR(dmic->clk_dmic); 395 } 396 397 regs = devm_platform_ioremap_resource(pdev, 0); 398 if (IS_ERR(regs)) 399 return PTR_ERR(regs); 400 401 dmic->regmap = devm_regmap_init_mmio(dev, regs, 402 &tegra210_dmic_regmap_config); 403 if (IS_ERR(dmic->regmap)) { 404 dev_err(dev, "regmap init failed\n"); 405 return PTR_ERR(dmic->regmap); 406 } 407 408 regcache_cache_only(dmic->regmap, true); 409 410 err = devm_snd_soc_register_component(dev, &tegra210_dmic_compnt, 411 tegra210_dmic_dais, 412 ARRAY_SIZE(tegra210_dmic_dais)); 413 if (err) { 414 dev_err(dev, "can't register DMIC component, err: %d\n", err); 415 return err; 416 } 417 418 pm_runtime_enable(dev); 419 420 return 0; 421 } 422 423 static int tegra210_dmic_remove(struct platform_device *pdev) 424 { 425 pm_runtime_disable(&pdev->dev); 426 427 return 0; 428 } 429 430 static const struct dev_pm_ops tegra210_dmic_pm_ops = { 431 SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend, 432 tegra210_dmic_runtime_resume, NULL) 433 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 434 pm_runtime_force_resume) 435 }; 436 437 static const struct of_device_id tegra210_dmic_of_match[] = { 438 { .compatible = "nvidia,tegra210-dmic" }, 439 {}, 440 }; 441 MODULE_DEVICE_TABLE(of, tegra210_dmic_of_match); 442 443 static struct platform_driver tegra210_dmic_driver = { 444 .driver = { 445 .name = "tegra210-dmic", 446 .of_match_table = tegra210_dmic_of_match, 447 .pm = &tegra210_dmic_pm_ops, 448 }, 449 .probe = tegra210_dmic_probe, 450 .remove = tegra210_dmic_remove, 451 }; 452 module_platform_driver(tegra210_dmic_driver) 453 454 MODULE_AUTHOR("Rahul Mittal <rmittal@nvidia.com>"); 455 MODULE_DESCRIPTION("Tegra210 ASoC DMIC driver"); 456 MODULE_LICENSE("GPL v2"); 457