Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 //
0003 // tegra186_dspk.c - Tegra186 DSPK driver
0004 //
0005 // Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
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     /* Client channel */
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     /* RX FIFO threshold in terms of frames */
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      * DSPK clock and PDM codec clock should be synchronous with 4:1 ratio,
0275      * this is because it takes 4 clock cycles to send out one sample to
0276      * codec by sigma delta modulator. Finally the clock rate is a multiple
0277      * of 'Over Sampling Ratio', 'Sample Rate' and 'Interface Clock Ratio'.
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                /* Reg */
0291                TEGRA186_DSPK_CORE_CTRL,
0292                /* Mask */
0293                TEGRA186_DSPK_OSR_MASK |
0294                TEGRA186_DSPK_CHANNEL_SELECT_MASK |
0295                TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK,
0296                /* Value */
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; /* "Zero" */
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");