0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/device.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/of_device.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/pm_runtime.h>
0014 #include <linux/regmap.h>
0015 #include <sound/core.h>
0016 #include <sound/pcm_params.h>
0017 #include <sound/soc.h>
0018 #include "tegra186_dspk.h"
0019 #include "tegra_cif.h"
0020
0021 static const struct reg_default tegra186_dspk_reg_defaults[] = {
0022 { TEGRA186_DSPK_RX_INT_MASK, 0x00000007 },
0023 { TEGRA186_DSPK_RX_CIF_CTRL, 0x00007700 },
0024 { TEGRA186_DSPK_CG, 0x00000001 },
0025 { TEGRA186_DSPK_CORE_CTRL, 0x00000310 },
0026 { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 },
0027 };
0028
0029 static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol,
0030 struct snd_ctl_elem_value *ucontrol)
0031 {
0032 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0033 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0034
0035 ucontrol->value.integer.value[0] = dspk->rx_fifo_th;
0036
0037 return 0;
0038 }
0039
0040 static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol,
0041 struct snd_ctl_elem_value *ucontrol)
0042 {
0043 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0044 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0045 int value = ucontrol->value.integer.value[0];
0046
0047 if (value == dspk->rx_fifo_th)
0048 return 0;
0049
0050 dspk->rx_fifo_th = value;
0051
0052 return 1;
0053 }
0054
0055 static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol,
0056 struct snd_ctl_elem_value *ucontrol)
0057 {
0058 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0059 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0060
0061 ucontrol->value.enumerated.item[0] = dspk->osr_val;
0062
0063 return 0;
0064 }
0065
0066 static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol,
0067 struct snd_ctl_elem_value *ucontrol)
0068 {
0069 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0070 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0071 unsigned int value = ucontrol->value.enumerated.item[0];
0072
0073 if (value == dspk->osr_val)
0074 return 0;
0075
0076 dspk->osr_val = value;
0077
0078 return 1;
0079 }
0080
0081 static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol,
0082 struct snd_ctl_elem_value *ucontrol)
0083 {
0084 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0085 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0086
0087 ucontrol->value.enumerated.item[0] = dspk->lrsel;
0088
0089 return 0;
0090 }
0091
0092 static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol,
0093 struct snd_ctl_elem_value *ucontrol)
0094 {
0095 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0096 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0097 unsigned int value = ucontrol->value.enumerated.item[0];
0098
0099 if (value == dspk->lrsel)
0100 return 0;
0101
0102 dspk->lrsel = value;
0103
0104 return 1;
0105 }
0106
0107 static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol,
0108 struct snd_ctl_elem_value *ucontrol)
0109 {
0110 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0111 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0112
0113 ucontrol->value.enumerated.item[0] = dspk->ch_sel;
0114
0115 return 0;
0116 }
0117
0118 static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol,
0119 struct snd_ctl_elem_value *ucontrol)
0120 {
0121 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0122 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0123 unsigned int value = ucontrol->value.enumerated.item[0];
0124
0125 if (value == dspk->ch_sel)
0126 return 0;
0127
0128 dspk->ch_sel = value;
0129
0130 return 1;
0131 }
0132
0133 static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
0134 struct snd_ctl_elem_value *ucontrol)
0135 {
0136 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0137 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0138
0139 ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo;
0140
0141 return 0;
0142 }
0143
0144 static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
0145 struct snd_ctl_elem_value *ucontrol)
0146 {
0147 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0148 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0149 unsigned int value = ucontrol->value.enumerated.item[0];
0150
0151 if (value == dspk->mono_to_stereo)
0152 return 0;
0153
0154 dspk->mono_to_stereo = value;
0155
0156 return 1;
0157 }
0158
0159 static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
0160 struct snd_ctl_elem_value *ucontrol)
0161 {
0162 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0163 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0164
0165 ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono;
0166
0167 return 0;
0168 }
0169
0170 static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
0171 struct snd_ctl_elem_value *ucontrol)
0172 {
0173 struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
0174 struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
0175 unsigned int value = ucontrol->value.enumerated.item[0];
0176
0177 if (value == dspk->stereo_to_mono)
0178 return 0;
0179
0180 dspk->stereo_to_mono = value;
0181
0182 return 1;
0183 }
0184
0185 static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
0186 {
0187 struct tegra186_dspk *dspk = dev_get_drvdata(dev);
0188
0189 regcache_cache_only(dspk->regmap, true);
0190 regcache_mark_dirty(dspk->regmap);
0191
0192 clk_disable_unprepare(dspk->clk_dspk);
0193
0194 return 0;
0195 }
0196
0197 static int __maybe_unused tegra186_dspk_runtime_resume(struct device *dev)
0198 {
0199 struct tegra186_dspk *dspk = dev_get_drvdata(dev);
0200 int err;
0201
0202 err = clk_prepare_enable(dspk->clk_dspk);
0203 if (err) {
0204 dev_err(dev, "failed to enable DSPK clock, err: %d\n", err);
0205 return err;
0206 }
0207
0208 regcache_cache_only(dspk->regmap, false);
0209 regcache_sync(dspk->regmap);
0210
0211 return 0;
0212 }
0213
0214 static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
0215 struct snd_pcm_hw_params *params,
0216 struct snd_soc_dai *dai)
0217 {
0218 struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai);
0219 unsigned int channels, srate, dspk_clk;
0220 struct device *dev = dai->dev;
0221 struct tegra_cif_conf cif_conf;
0222 unsigned int max_th;
0223 int err;
0224
0225 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
0226
0227 channels = params_channels(params);
0228 cif_conf.audio_ch = channels;
0229
0230
0231 switch (dspk->ch_sel) {
0232 case DSPK_CH_SELECT_LEFT:
0233 case DSPK_CH_SELECT_RIGHT:
0234 cif_conf.client_ch = 1;
0235 break;
0236 case DSPK_CH_SELECT_STEREO:
0237 cif_conf.client_ch = 2;
0238 break;
0239 default:
0240 dev_err(dev, "Invalid DSPK client channels\n");
0241 return -EINVAL;
0242 }
0243
0244 cif_conf.client_bits = TEGRA_ACIF_BITS_24;
0245
0246 switch (params_format(params)) {
0247 case SNDRV_PCM_FORMAT_S16_LE:
0248 cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
0249 break;
0250 case SNDRV_PCM_FORMAT_S32_LE:
0251 cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
0252 break;
0253 default:
0254 dev_err(dev, "unsupported format!\n");
0255 return -EOPNOTSUPP;
0256 }
0257
0258 srate = params_rate(params);
0259
0260
0261 max_th = (TEGRA186_DSPK_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1;
0262
0263 if (dspk->rx_fifo_th > max_th)
0264 dspk->rx_fifo_th = max_th;
0265
0266 cif_conf.threshold = dspk->rx_fifo_th;
0267 cif_conf.mono_conv = dspk->mono_to_stereo;
0268 cif_conf.stereo_conv = dspk->stereo_to_mono;
0269
0270 tegra_set_cif(dspk->regmap, TEGRA186_DSPK_RX_CIF_CTRL,
0271 &cif_conf);
0272
0273
0274
0275
0276
0277
0278
0279 dspk_clk = (DSPK_OSR_FACTOR << dspk->osr_val) * srate * DSPK_CLK_RATIO;
0280
0281 err = clk_set_rate(dspk->clk_dspk, dspk_clk);
0282 if (err) {
0283 dev_err(dev, "can't set DSPK clock rate %u, err: %d\n",
0284 dspk_clk, err);
0285
0286 return err;
0287 }
0288
0289 regmap_update_bits(dspk->regmap,
0290
0291 TEGRA186_DSPK_CORE_CTRL,
0292
0293 TEGRA186_DSPK_OSR_MASK |
0294 TEGRA186_DSPK_CHANNEL_SELECT_MASK |
0295 TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK,
0296
0297 (dspk->osr_val << DSPK_OSR_SHIFT) |
0298 ((dspk->ch_sel + 1) << CH_SEL_SHIFT) |
0299 (dspk->lrsel << LRSEL_POL_SHIFT));
0300
0301 return 0;
0302 }
0303
0304 static const struct snd_soc_dai_ops tegra186_dspk_dai_ops = {
0305 .hw_params = tegra186_dspk_hw_params,
0306 };
0307
0308 static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
0309 {
0310 .name = "DSPK-CIF",
0311 .playback = {
0312 .stream_name = "CIF-Playback",
0313 .channels_min = 1,
0314 .channels_max = 2,
0315 .rates = SNDRV_PCM_RATE_8000_48000,
0316 .formats = SNDRV_PCM_FMTBIT_S16_LE |
0317 SNDRV_PCM_FMTBIT_S32_LE,
0318 },
0319 },
0320 {
0321 .name = "DSPK-DAP",
0322 .playback = {
0323 .stream_name = "DAP-Playback",
0324 .channels_min = 1,
0325 .channels_max = 2,
0326 .rates = SNDRV_PCM_RATE_8000_48000,
0327 .formats = SNDRV_PCM_FMTBIT_S16_LE |
0328 SNDRV_PCM_FMTBIT_S32_LE,
0329 },
0330 .ops = &tegra186_dspk_dai_ops,
0331 .symmetric_rate = 1,
0332 },
0333 };
0334
0335 static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = {
0336 SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0),
0337 SND_SOC_DAPM_SPK("SPK", NULL),
0338 };
0339
0340 static const struct snd_soc_dapm_route tegra186_dspk_routes[] = {
0341 { "XBAR-Playback", NULL, "XBAR-TX" },
0342 { "CIF-Playback", NULL, "XBAR-Playback" },
0343 { "RX", NULL, "CIF-Playback" },
0344 { "DAP-Playback", NULL, "RX" },
0345 { "SPK", NULL, "DAP-Playback" },
0346 };
0347
0348 static const char * const tegra186_dspk_ch_sel_text[] = {
0349 "Left", "Right", "Stereo",
0350 };
0351
0352 static const struct soc_enum tegra186_dspk_ch_sel_enum =
0353 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_ch_sel_text),
0354 tegra186_dspk_ch_sel_text);
0355
0356 static const char * const tegra186_dspk_osr_text[] = {
0357 "OSR_32", "OSR_64", "OSR_128", "OSR_256",
0358 };
0359
0360 static const struct soc_enum tegra186_dspk_osr_enum =
0361 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_osr_text),
0362 tegra186_dspk_osr_text);
0363
0364 static const char * const tegra186_dspk_lrsel_text[] = {
0365 "Left", "Right",
0366 };
0367
0368 static const char * const tegra186_dspk_mono_conv_text[] = {
0369 "Zero", "Copy",
0370 };
0371
0372 static const struct soc_enum tegra186_dspk_mono_conv_enum =
0373 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
0374 ARRAY_SIZE(tegra186_dspk_mono_conv_text),
0375 tegra186_dspk_mono_conv_text);
0376
0377 static const char * const tegra186_dspk_stereo_conv_text[] = {
0378 "CH0", "CH1", "AVG",
0379 };
0380
0381 static const struct soc_enum tegra186_dspk_stereo_conv_enum =
0382 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
0383 ARRAY_SIZE(tegra186_dspk_stereo_conv_text),
0384 tegra186_dspk_stereo_conv_text);
0385
0386 static const struct soc_enum tegra186_dspk_lrsel_enum =
0387 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_lrsel_text),
0388 tegra186_dspk_lrsel_text);
0389
0390 static const struct snd_kcontrol_new tegrat186_dspk_controls[] = {
0391 SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0,
0392 TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0,
0393 tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th),
0394 SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum,
0395 tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val),
0396 SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum,
0397 tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel),
0398 SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum,
0399 tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel),
0400 SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum,
0401 tegra186_dspk_get_mono_to_stereo,
0402 tegra186_dspk_put_mono_to_stereo),
0403 SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum,
0404 tegra186_dspk_get_stereo_to_mono,
0405 tegra186_dspk_put_stereo_to_mono),
0406 };
0407
0408 static const struct snd_soc_component_driver tegra186_dspk_cmpnt = {
0409 .dapm_widgets = tegra186_dspk_widgets,
0410 .num_dapm_widgets = ARRAY_SIZE(tegra186_dspk_widgets),
0411 .dapm_routes = tegra186_dspk_routes,
0412 .num_dapm_routes = ARRAY_SIZE(tegra186_dspk_routes),
0413 .controls = tegrat186_dspk_controls,
0414 .num_controls = ARRAY_SIZE(tegrat186_dspk_controls),
0415 };
0416
0417 static bool tegra186_dspk_wr_reg(struct device *dev, unsigned int reg)
0418 {
0419 switch (reg) {
0420 case TEGRA186_DSPK_RX_INT_MASK ... TEGRA186_DSPK_RX_CIF_CTRL:
0421 case TEGRA186_DSPK_ENABLE ... TEGRA186_DSPK_CG:
0422 case TEGRA186_DSPK_CORE_CTRL ... TEGRA186_DSPK_CODEC_CTRL:
0423 return true;
0424 default:
0425 return false;
0426 }
0427 }
0428
0429 static bool tegra186_dspk_rd_reg(struct device *dev, unsigned int reg)
0430 {
0431 if (tegra186_dspk_wr_reg(dev, reg))
0432 return true;
0433
0434 switch (reg) {
0435 case TEGRA186_DSPK_RX_STATUS:
0436 case TEGRA186_DSPK_RX_INT_STATUS:
0437 case TEGRA186_DSPK_STATUS:
0438 case TEGRA186_DSPK_INT_STATUS:
0439 return true;
0440 default:
0441 return false;
0442 }
0443 }
0444
0445 static bool tegra186_dspk_volatile_reg(struct device *dev, unsigned int reg)
0446 {
0447 switch (reg) {
0448 case TEGRA186_DSPK_RX_STATUS:
0449 case TEGRA186_DSPK_RX_INT_STATUS:
0450 case TEGRA186_DSPK_STATUS:
0451 case TEGRA186_DSPK_INT_STATUS:
0452 return true;
0453 default:
0454 return false;
0455 }
0456 }
0457
0458 static const struct regmap_config tegra186_dspk_regmap = {
0459 .reg_bits = 32,
0460 .reg_stride = 4,
0461 .val_bits = 32,
0462 .max_register = TEGRA186_DSPK_CODEC_CTRL,
0463 .writeable_reg = tegra186_dspk_wr_reg,
0464 .readable_reg = tegra186_dspk_rd_reg,
0465 .volatile_reg = tegra186_dspk_volatile_reg,
0466 .reg_defaults = tegra186_dspk_reg_defaults,
0467 .num_reg_defaults = ARRAY_SIZE(tegra186_dspk_reg_defaults),
0468 .cache_type = REGCACHE_FLAT,
0469 };
0470
0471 static const struct of_device_id tegra186_dspk_of_match[] = {
0472 { .compatible = "nvidia,tegra186-dspk" },
0473 {},
0474 };
0475 MODULE_DEVICE_TABLE(of, tegra186_dspk_of_match);
0476
0477 static int tegra186_dspk_platform_probe(struct platform_device *pdev)
0478 {
0479 struct device *dev = &pdev->dev;
0480 struct tegra186_dspk *dspk;
0481 void __iomem *regs;
0482 int err;
0483
0484 dspk = devm_kzalloc(dev, sizeof(*dspk), GFP_KERNEL);
0485 if (!dspk)
0486 return -ENOMEM;
0487
0488 dspk->osr_val = DSPK_OSR_64;
0489 dspk->lrsel = DSPK_LRSEL_LEFT;
0490 dspk->ch_sel = DSPK_CH_SELECT_STEREO;
0491 dspk->mono_to_stereo = 0;
0492
0493 dev_set_drvdata(dev, dspk);
0494
0495 dspk->clk_dspk = devm_clk_get(dev, "dspk");
0496 if (IS_ERR(dspk->clk_dspk)) {
0497 dev_err(dev, "can't retrieve DSPK clock\n");
0498 return PTR_ERR(dspk->clk_dspk);
0499 }
0500
0501 regs = devm_platform_ioremap_resource(pdev, 0);
0502 if (IS_ERR(regs))
0503 return PTR_ERR(regs);
0504
0505 dspk->regmap = devm_regmap_init_mmio(dev, regs, &tegra186_dspk_regmap);
0506 if (IS_ERR(dspk->regmap)) {
0507 dev_err(dev, "regmap init failed\n");
0508 return PTR_ERR(dspk->regmap);
0509 }
0510
0511 regcache_cache_only(dspk->regmap, true);
0512
0513 err = devm_snd_soc_register_component(dev, &tegra186_dspk_cmpnt,
0514 tegra186_dspk_dais,
0515 ARRAY_SIZE(tegra186_dspk_dais));
0516 if (err) {
0517 dev_err(dev, "can't register DSPK component, err: %d\n",
0518 err);
0519 return err;
0520 }
0521
0522 pm_runtime_enable(dev);
0523
0524 return 0;
0525 }
0526
0527 static int tegra186_dspk_platform_remove(struct platform_device *pdev)
0528 {
0529 pm_runtime_disable(&pdev->dev);
0530
0531 return 0;
0532 }
0533
0534 static const struct dev_pm_ops tegra186_dspk_pm_ops = {
0535 SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend,
0536 tegra186_dspk_runtime_resume, NULL)
0537 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0538 pm_runtime_force_resume)
0539 };
0540
0541 static struct platform_driver tegra186_dspk_driver = {
0542 .driver = {
0543 .name = "tegra186-dspk",
0544 .of_match_table = tegra186_dspk_of_match,
0545 .pm = &tegra186_dspk_pm_ops,
0546 },
0547 .probe = tegra186_dspk_platform_probe,
0548 .remove = tegra186_dspk_platform_remove,
0549 };
0550 module_platform_driver(tegra186_dspk_driver);
0551
0552 MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>");
0553 MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>");
0554 MODULE_DESCRIPTION("Tegra186 ASoC DSPK driver");
0555 MODULE_LICENSE("GPL v2");