0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/device.h>
0009 #include <linux/io.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/of_device.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/regmap.h>
0016 #include <sound/core.h>
0017 #include <sound/pcm.h>
0018 #include <sound/pcm_params.h>
0019 #include <sound/soc.h>
0020
0021 #include "tegra210_adx.h"
0022 #include "tegra_cif.h"
0023
0024 static const struct reg_default tegra210_adx_reg_defaults[] = {
0025 { TEGRA210_ADX_RX_INT_MASK, 0x00000001},
0026 { TEGRA210_ADX_RX_CIF_CTRL, 0x00007000},
0027 { TEGRA210_ADX_TX_INT_MASK, 0x0000000f },
0028 { TEGRA210_ADX_TX1_CIF_CTRL, 0x00007000},
0029 { TEGRA210_ADX_TX2_CIF_CTRL, 0x00007000},
0030 { TEGRA210_ADX_TX3_CIF_CTRL, 0x00007000},
0031 { TEGRA210_ADX_TX4_CIF_CTRL, 0x00007000},
0032 { TEGRA210_ADX_CG, 0x1},
0033 { TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000},
0034 };
0035
0036 static void tegra210_adx_write_map_ram(struct tegra210_adx *adx)
0037 {
0038 int i;
0039
0040 regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL,
0041 TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
0042 TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN |
0043 TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE);
0044
0045 for (i = 0; i < TEGRA210_ADX_RAM_DEPTH; i++)
0046 regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA,
0047 adx->map[i]);
0048
0049 regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN0, adx->byte_mask[0]);
0050 regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN1, adx->byte_mask[1]);
0051 }
0052
0053 static int tegra210_adx_startup(struct snd_pcm_substream *substream,
0054 struct snd_soc_dai *dai)
0055 {
0056 struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
0057 unsigned int val;
0058 int err;
0059
0060
0061 err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS,
0062 val, !(val & 0x1), 10, 10000);
0063 if (err < 0) {
0064 dev_err(dai->dev, "failed to stop ADX, err = %d\n", err);
0065 return err;
0066 }
0067
0068
0069
0070
0071
0072
0073
0074 regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET,
0075 TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK,
0076 TEGRA210_ADX_SOFT_RESET_SOFT_EN);
0077
0078 err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET,
0079 val, !(val & 0x1), 10, 10000);
0080 if (err < 0) {
0081 dev_err(dai->dev, "failed to reset ADX, err = %d\n", err);
0082 return err;
0083 }
0084
0085 return 0;
0086 }
0087
0088 static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev)
0089 {
0090 struct tegra210_adx *adx = dev_get_drvdata(dev);
0091
0092 regcache_cache_only(adx->regmap, true);
0093 regcache_mark_dirty(adx->regmap);
0094
0095 return 0;
0096 }
0097
0098 static int __maybe_unused tegra210_adx_runtime_resume(struct device *dev)
0099 {
0100 struct tegra210_adx *adx = dev_get_drvdata(dev);
0101
0102 regcache_cache_only(adx->regmap, false);
0103 regcache_sync(adx->regmap);
0104
0105 tegra210_adx_write_map_ram(adx);
0106
0107 return 0;
0108 }
0109
0110 static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
0111 unsigned int channels,
0112 unsigned int format,
0113 unsigned int reg)
0114 {
0115 struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
0116 struct tegra_cif_conf cif_conf;
0117 int audio_bits;
0118
0119 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
0120
0121 if (channels < 1 || channels > 16)
0122 return -EINVAL;
0123
0124 switch (format) {
0125 case SNDRV_PCM_FORMAT_S8:
0126 audio_bits = TEGRA_ACIF_BITS_8;
0127 break;
0128 case SNDRV_PCM_FORMAT_S16_LE:
0129 audio_bits = TEGRA_ACIF_BITS_16;
0130 break;
0131 case SNDRV_PCM_FORMAT_S32_LE:
0132 audio_bits = TEGRA_ACIF_BITS_32;
0133 break;
0134 default:
0135 return -EINVAL;
0136 }
0137
0138 cif_conf.audio_ch = channels;
0139 cif_conf.client_ch = channels;
0140 cif_conf.audio_bits = audio_bits;
0141 cif_conf.client_bits = audio_bits;
0142
0143 tegra_set_cif(adx->regmap, reg, &cif_conf);
0144
0145 return 0;
0146 }
0147
0148 static int tegra210_adx_out_hw_params(struct snd_pcm_substream *substream,
0149 struct snd_pcm_hw_params *params,
0150 struct snd_soc_dai *dai)
0151 {
0152 return tegra210_adx_set_audio_cif(dai, params_channels(params),
0153 params_format(params),
0154 TEGRA210_ADX_TX1_CIF_CTRL + ((dai->id - 1) * TEGRA210_ADX_AUDIOCIF_CH_STRIDE));
0155 }
0156
0157 static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream,
0158 struct snd_pcm_hw_params *params,
0159 struct snd_soc_dai *dai)
0160 {
0161 return tegra210_adx_set_audio_cif(dai, params_channels(params),
0162 params_format(params),
0163 TEGRA210_ADX_RX_CIF_CTRL);
0164 }
0165
0166 static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
0167 struct snd_ctl_elem_value *ucontrol)
0168 {
0169 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0170 struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
0171 struct soc_mixer_control *mc;
0172 unsigned char *bytes_map = (unsigned char *)&adx->map;
0173 int enabled;
0174
0175 mc = (struct soc_mixer_control *)kcontrol->private_value;
0176 enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
0177
0178 if (enabled)
0179 ucontrol->value.integer.value[0] = bytes_map[mc->reg];
0180 else
0181 ucontrol->value.integer.value[0] = 0;
0182
0183 return 0;
0184 }
0185
0186 static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
0187 struct snd_ctl_elem_value *ucontrol)
0188 {
0189 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
0190 struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
0191 unsigned char *bytes_map = (unsigned char *)&adx->map;
0192 int value = ucontrol->value.integer.value[0];
0193 struct soc_mixer_control *mc =
0194 (struct soc_mixer_control *)kcontrol->private_value;
0195
0196 if (value == bytes_map[mc->reg])
0197 return 0;
0198
0199 if (value >= 0 && value <= 255) {
0200
0201 bytes_map[mc->reg] = value;
0202 adx->byte_mask[mc->reg / 32] |= (1 << (mc->reg % 32));
0203 } else {
0204
0205 bytes_map[mc->reg] = 0;
0206 adx->byte_mask[mc->reg / 32] &= ~(1 << (mc->reg % 32));
0207 }
0208
0209 return 1;
0210 }
0211
0212 static const struct snd_soc_dai_ops tegra210_adx_in_dai_ops = {
0213 .hw_params = tegra210_adx_in_hw_params,
0214 .startup = tegra210_adx_startup,
0215 };
0216
0217 static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
0218 .hw_params = tegra210_adx_out_hw_params,
0219 };
0220
0221 #define IN_DAI \
0222 { \
0223 .name = "ADX-RX-CIF", \
0224 .playback = { \
0225 .stream_name = "RX-CIF-Playback", \
0226 .channels_min = 1, \
0227 .channels_max = 16, \
0228 .rates = SNDRV_PCM_RATE_8000_192000, \
0229 .formats = SNDRV_PCM_FMTBIT_S8 | \
0230 SNDRV_PCM_FMTBIT_S16_LE | \
0231 SNDRV_PCM_FMTBIT_S32_LE, \
0232 }, \
0233 .capture = { \
0234 .stream_name = "RX-CIF-Capture", \
0235 .channels_min = 1, \
0236 .channels_max = 16, \
0237 .rates = SNDRV_PCM_RATE_8000_192000, \
0238 .formats = SNDRV_PCM_FMTBIT_S8 | \
0239 SNDRV_PCM_FMTBIT_S16_LE | \
0240 SNDRV_PCM_FMTBIT_S32_LE, \
0241 }, \
0242 .ops = &tegra210_adx_in_dai_ops, \
0243 }
0244
0245 #define OUT_DAI(id) \
0246 { \
0247 .name = "ADX-TX" #id "-CIF", \
0248 .playback = { \
0249 .stream_name = "TX" #id "-CIF-Playback",\
0250 .channels_min = 1, \
0251 .channels_max = 16, \
0252 .rates = SNDRV_PCM_RATE_8000_192000, \
0253 .formats = SNDRV_PCM_FMTBIT_S8 | \
0254 SNDRV_PCM_FMTBIT_S16_LE | \
0255 SNDRV_PCM_FMTBIT_S32_LE, \
0256 }, \
0257 .capture = { \
0258 .stream_name = "TX" #id "-CIF-Capture", \
0259 .channels_min = 1, \
0260 .channels_max = 16, \
0261 .rates = SNDRV_PCM_RATE_8000_192000, \
0262 .formats = SNDRV_PCM_FMTBIT_S8 | \
0263 SNDRV_PCM_FMTBIT_S16_LE | \
0264 SNDRV_PCM_FMTBIT_S32_LE, \
0265 }, \
0266 .ops = &tegra210_adx_out_dai_ops, \
0267 }
0268
0269 static struct snd_soc_dai_driver tegra210_adx_dais[] = {
0270 IN_DAI,
0271 OUT_DAI(1),
0272 OUT_DAI(2),
0273 OUT_DAI(3),
0274 OUT_DAI(4),
0275 };
0276
0277 static const struct snd_soc_dapm_widget tegra210_adx_widgets[] = {
0278 SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA210_ADX_ENABLE,
0279 TEGRA210_ADX_ENABLE_SHIFT, 0),
0280 SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_ADX_CTRL, 0, 0),
0281 SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_ADX_CTRL, 1, 0),
0282 SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_ADX_CTRL, 2, 0),
0283 SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_ADX_CTRL, 3, 0),
0284 };
0285
0286 #define STREAM_ROUTES(id, sname) \
0287 { "XBAR-" sname, NULL, "XBAR-TX" }, \
0288 { "RX-CIF-" sname, NULL, "XBAR-" sname }, \
0289 { "RX", NULL, "RX-CIF-" sname }, \
0290 { "TX" #id, NULL, "RX" }, \
0291 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \
0292 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \
0293 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname }
0294
0295 #define ADX_ROUTES(id) \
0296 STREAM_ROUTES(id, "Playback"), \
0297 STREAM_ROUTES(id, "Capture")
0298
0299 #define STREAM_ROUTES(id, sname) \
0300 { "XBAR-" sname, NULL, "XBAR-TX" }, \
0301 { "RX-CIF-" sname, NULL, "XBAR-" sname }, \
0302 { "RX", NULL, "RX-CIF-" sname }, \
0303 { "TX" #id, NULL, "RX" }, \
0304 { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \
0305 { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \
0306 { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname }
0307
0308 #define ADX_ROUTES(id) \
0309 STREAM_ROUTES(id, "Playback"), \
0310 STREAM_ROUTES(id, "Capture")
0311
0312 static const struct snd_soc_dapm_route tegra210_adx_routes[] = {
0313 ADX_ROUTES(1),
0314 ADX_ROUTES(2),
0315 ADX_ROUTES(3),
0316 ADX_ROUTES(4),
0317 };
0318
0319 #define TEGRA210_ADX_BYTE_MAP_CTRL(reg) \
0320 SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0, \
0321 tegra210_adx_get_byte_map, \
0322 tegra210_adx_put_byte_map)
0323
0324 static struct snd_kcontrol_new tegra210_adx_controls[] = {
0325 TEGRA210_ADX_BYTE_MAP_CTRL(0),
0326 TEGRA210_ADX_BYTE_MAP_CTRL(1),
0327 TEGRA210_ADX_BYTE_MAP_CTRL(2),
0328 TEGRA210_ADX_BYTE_MAP_CTRL(3),
0329 TEGRA210_ADX_BYTE_MAP_CTRL(4),
0330 TEGRA210_ADX_BYTE_MAP_CTRL(5),
0331 TEGRA210_ADX_BYTE_MAP_CTRL(6),
0332 TEGRA210_ADX_BYTE_MAP_CTRL(7),
0333 TEGRA210_ADX_BYTE_MAP_CTRL(8),
0334 TEGRA210_ADX_BYTE_MAP_CTRL(9),
0335 TEGRA210_ADX_BYTE_MAP_CTRL(10),
0336 TEGRA210_ADX_BYTE_MAP_CTRL(11),
0337 TEGRA210_ADX_BYTE_MAP_CTRL(12),
0338 TEGRA210_ADX_BYTE_MAP_CTRL(13),
0339 TEGRA210_ADX_BYTE_MAP_CTRL(14),
0340 TEGRA210_ADX_BYTE_MAP_CTRL(15),
0341 TEGRA210_ADX_BYTE_MAP_CTRL(16),
0342 TEGRA210_ADX_BYTE_MAP_CTRL(17),
0343 TEGRA210_ADX_BYTE_MAP_CTRL(18),
0344 TEGRA210_ADX_BYTE_MAP_CTRL(19),
0345 TEGRA210_ADX_BYTE_MAP_CTRL(20),
0346 TEGRA210_ADX_BYTE_MAP_CTRL(21),
0347 TEGRA210_ADX_BYTE_MAP_CTRL(22),
0348 TEGRA210_ADX_BYTE_MAP_CTRL(23),
0349 TEGRA210_ADX_BYTE_MAP_CTRL(24),
0350 TEGRA210_ADX_BYTE_MAP_CTRL(25),
0351 TEGRA210_ADX_BYTE_MAP_CTRL(26),
0352 TEGRA210_ADX_BYTE_MAP_CTRL(27),
0353 TEGRA210_ADX_BYTE_MAP_CTRL(28),
0354 TEGRA210_ADX_BYTE_MAP_CTRL(29),
0355 TEGRA210_ADX_BYTE_MAP_CTRL(30),
0356 TEGRA210_ADX_BYTE_MAP_CTRL(31),
0357 TEGRA210_ADX_BYTE_MAP_CTRL(32),
0358 TEGRA210_ADX_BYTE_MAP_CTRL(33),
0359 TEGRA210_ADX_BYTE_MAP_CTRL(34),
0360 TEGRA210_ADX_BYTE_MAP_CTRL(35),
0361 TEGRA210_ADX_BYTE_MAP_CTRL(36),
0362 TEGRA210_ADX_BYTE_MAP_CTRL(37),
0363 TEGRA210_ADX_BYTE_MAP_CTRL(38),
0364 TEGRA210_ADX_BYTE_MAP_CTRL(39),
0365 TEGRA210_ADX_BYTE_MAP_CTRL(40),
0366 TEGRA210_ADX_BYTE_MAP_CTRL(41),
0367 TEGRA210_ADX_BYTE_MAP_CTRL(42),
0368 TEGRA210_ADX_BYTE_MAP_CTRL(43),
0369 TEGRA210_ADX_BYTE_MAP_CTRL(44),
0370 TEGRA210_ADX_BYTE_MAP_CTRL(45),
0371 TEGRA210_ADX_BYTE_MAP_CTRL(46),
0372 TEGRA210_ADX_BYTE_MAP_CTRL(47),
0373 TEGRA210_ADX_BYTE_MAP_CTRL(48),
0374 TEGRA210_ADX_BYTE_MAP_CTRL(49),
0375 TEGRA210_ADX_BYTE_MAP_CTRL(50),
0376 TEGRA210_ADX_BYTE_MAP_CTRL(51),
0377 TEGRA210_ADX_BYTE_MAP_CTRL(52),
0378 TEGRA210_ADX_BYTE_MAP_CTRL(53),
0379 TEGRA210_ADX_BYTE_MAP_CTRL(54),
0380 TEGRA210_ADX_BYTE_MAP_CTRL(55),
0381 TEGRA210_ADX_BYTE_MAP_CTRL(56),
0382 TEGRA210_ADX_BYTE_MAP_CTRL(57),
0383 TEGRA210_ADX_BYTE_MAP_CTRL(58),
0384 TEGRA210_ADX_BYTE_MAP_CTRL(59),
0385 TEGRA210_ADX_BYTE_MAP_CTRL(60),
0386 TEGRA210_ADX_BYTE_MAP_CTRL(61),
0387 TEGRA210_ADX_BYTE_MAP_CTRL(62),
0388 TEGRA210_ADX_BYTE_MAP_CTRL(63),
0389 };
0390
0391 static const struct snd_soc_component_driver tegra210_adx_cmpnt = {
0392 .dapm_widgets = tegra210_adx_widgets,
0393 .num_dapm_widgets = ARRAY_SIZE(tegra210_adx_widgets),
0394 .dapm_routes = tegra210_adx_routes,
0395 .num_dapm_routes = ARRAY_SIZE(tegra210_adx_routes),
0396 .controls = tegra210_adx_controls,
0397 .num_controls = ARRAY_SIZE(tegra210_adx_controls),
0398 };
0399
0400 static bool tegra210_adx_wr_reg(struct device *dev,
0401 unsigned int reg)
0402 {
0403 switch (reg) {
0404 case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL:
0405 case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL:
0406 case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG:
0407 case TEGRA210_ADX_CTRL ... TEGRA210_ADX_IN_BYTE_EN1:
0408 case TEGRA210_ADX_CFG_RAM_CTRL ... TEGRA210_ADX_CFG_RAM_DATA:
0409 return true;
0410 default:
0411 return false;
0412 }
0413 }
0414
0415 static bool tegra210_adx_rd_reg(struct device *dev,
0416 unsigned int reg)
0417 {
0418 switch (reg) {
0419 case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_CFG_RAM_DATA:
0420 return true;
0421 default:
0422 return false;
0423 }
0424 }
0425
0426 static bool tegra210_adx_volatile_reg(struct device *dev,
0427 unsigned int reg)
0428 {
0429 switch (reg) {
0430 case TEGRA210_ADX_RX_STATUS:
0431 case TEGRA210_ADX_RX_INT_STATUS:
0432 case TEGRA210_ADX_RX_INT_SET:
0433 case TEGRA210_ADX_TX_STATUS:
0434 case TEGRA210_ADX_TX_INT_STATUS:
0435 case TEGRA210_ADX_TX_INT_SET:
0436 case TEGRA210_ADX_SOFT_RESET:
0437 case TEGRA210_ADX_STATUS:
0438 case TEGRA210_ADX_INT_STATUS:
0439 case TEGRA210_ADX_CFG_RAM_CTRL:
0440 case TEGRA210_ADX_CFG_RAM_DATA:
0441 return true;
0442 default:
0443 break;
0444 }
0445
0446 return false;
0447 }
0448
0449 static const struct regmap_config tegra210_adx_regmap_config = {
0450 .reg_bits = 32,
0451 .reg_stride = 4,
0452 .val_bits = 32,
0453 .max_register = TEGRA210_ADX_CFG_RAM_DATA,
0454 .writeable_reg = tegra210_adx_wr_reg,
0455 .readable_reg = tegra210_adx_rd_reg,
0456 .volatile_reg = tegra210_adx_volatile_reg,
0457 .reg_defaults = tegra210_adx_reg_defaults,
0458 .num_reg_defaults = ARRAY_SIZE(tegra210_adx_reg_defaults),
0459 .cache_type = REGCACHE_FLAT,
0460 };
0461
0462 static const struct of_device_id tegra210_adx_of_match[] = {
0463 { .compatible = "nvidia,tegra210-adx" },
0464 {},
0465 };
0466 MODULE_DEVICE_TABLE(of, tegra210_adx_of_match);
0467
0468 static int tegra210_adx_platform_probe(struct platform_device *pdev)
0469 {
0470 struct device *dev = &pdev->dev;
0471 struct tegra210_adx *adx;
0472 void __iomem *regs;
0473 int err;
0474
0475 adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL);
0476 if (!adx)
0477 return -ENOMEM;
0478
0479 dev_set_drvdata(dev, adx);
0480
0481 regs = devm_platform_ioremap_resource(pdev, 0);
0482 if (IS_ERR(regs))
0483 return PTR_ERR(regs);
0484
0485 adx->regmap = devm_regmap_init_mmio(dev, regs,
0486 &tegra210_adx_regmap_config);
0487 if (IS_ERR(adx->regmap)) {
0488 dev_err(dev, "regmap init failed\n");
0489 return PTR_ERR(adx->regmap);
0490 }
0491
0492 regcache_cache_only(adx->regmap, true);
0493
0494 err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt,
0495 tegra210_adx_dais,
0496 ARRAY_SIZE(tegra210_adx_dais));
0497 if (err) {
0498 dev_err(dev, "can't register ADX component, err: %d\n", err);
0499 return err;
0500 }
0501
0502 pm_runtime_enable(dev);
0503
0504 return 0;
0505 }
0506
0507 static int tegra210_adx_platform_remove(struct platform_device *pdev)
0508 {
0509 pm_runtime_disable(&pdev->dev);
0510
0511 return 0;
0512 }
0513
0514 static const struct dev_pm_ops tegra210_adx_pm_ops = {
0515 SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
0516 tegra210_adx_runtime_resume, NULL)
0517 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0518 pm_runtime_force_resume)
0519 };
0520
0521 static struct platform_driver tegra210_adx_driver = {
0522 .driver = {
0523 .name = "tegra210-adx",
0524 .of_match_table = tegra210_adx_of_match,
0525 .pm = &tegra210_adx_pm_ops,
0526 },
0527 .probe = tegra210_adx_platform_probe,
0528 .remove = tegra210_adx_platform_remove,
0529 };
0530 module_platform_driver(tegra210_adx_driver);
0531
0532 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
0533 MODULE_DESCRIPTION("Tegra210 ADX ASoC driver");
0534 MODULE_LICENSE("GPL v2");