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