3785cade2d9a94b21a6e31cfdddd2019f616d351
[sfrench/cifs-2.6.git] / sound / soc / tegra / tegra210_adx.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // tegra210_adx.c - Tegra210 ADX driver
4 //
5 // Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
6
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/io.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/of_device.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/regmap.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20
21 #include "tegra210_adx.h"
22 #include "tegra_cif.h"
23
24 static const struct reg_default tegra210_adx_reg_defaults[] = {
25         { TEGRA210_ADX_RX_INT_MASK, 0x00000001},
26         { TEGRA210_ADX_RX_CIF_CTRL, 0x00007000},
27         { TEGRA210_ADX_TX_INT_MASK, 0x0000000f },
28         { TEGRA210_ADX_TX1_CIF_CTRL, 0x00007000},
29         { TEGRA210_ADX_TX2_CIF_CTRL, 0x00007000},
30         { TEGRA210_ADX_TX3_CIF_CTRL, 0x00007000},
31         { TEGRA210_ADX_TX4_CIF_CTRL, 0x00007000},
32         { TEGRA210_ADX_CG, 0x1},
33         { TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000},
34 };
35
36 static void tegra210_adx_write_map_ram(struct tegra210_adx *adx)
37 {
38         int i;
39
40         regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL,
41                      TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
42                      TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN |
43                      TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE);
44
45         for (i = 0; i < TEGRA210_ADX_RAM_DEPTH; i++)
46                 regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA,
47                              adx->map[i]);
48
49         regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN0, adx->byte_mask[0]);
50         regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN1, adx->byte_mask[1]);
51 }
52
53 static int tegra210_adx_startup(struct snd_pcm_substream *substream,
54                                 struct snd_soc_dai *dai)
55 {
56         struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
57         unsigned int val;
58         int err;
59
60         /* Ensure if ADX status is disabled */
61         err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS,
62                                               val, !(val & 0x1), 10, 10000);
63         if (err < 0) {
64                 dev_err(dai->dev, "failed to stop ADX, err = %d\n", err);
65                 return err;
66         }
67
68         /*
69          * Soft Reset: Below performs module soft reset which clears
70          * all FSM logic, flushes flow control of FIFO and resets the
71          * state register. It also brings module back to disabled
72          * state (without flushing the data in the pipe).
73          */
74         regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET,
75                            TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK,
76                            TEGRA210_ADX_SOFT_RESET_SOFT_EN);
77
78         err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET,
79                                        val, !(val & 0x1), 10, 10000);
80         if (err < 0) {
81                 dev_err(dai->dev, "failed to reset ADX, err = %d\n", err);
82                 return err;
83         }
84
85         return 0;
86 }
87
88 static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev)
89 {
90         struct tegra210_adx *adx = dev_get_drvdata(dev);
91
92         regcache_cache_only(adx->regmap, true);
93         regcache_mark_dirty(adx->regmap);
94
95         return 0;
96 }
97
98 static int __maybe_unused tegra210_adx_runtime_resume(struct device *dev)
99 {
100         struct tegra210_adx *adx = dev_get_drvdata(dev);
101
102         regcache_cache_only(adx->regmap, false);
103         regcache_sync(adx->regmap);
104
105         tegra210_adx_write_map_ram(adx);
106
107         return 0;
108 }
109
110 static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
111                                       unsigned int channels,
112                                       unsigned int format,
113                                       unsigned int reg)
114 {
115         struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
116         struct tegra_cif_conf cif_conf;
117         int audio_bits;
118
119         memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
120
121         if (channels < 1 || channels > 16)
122                 return -EINVAL;
123
124         switch (format) {
125         case SNDRV_PCM_FORMAT_S8:
126                 audio_bits = TEGRA_ACIF_BITS_8;
127                 break;
128         case SNDRV_PCM_FORMAT_S16_LE:
129                 audio_bits = TEGRA_ACIF_BITS_16;
130                 break;
131         case SNDRV_PCM_FORMAT_S32_LE:
132                 audio_bits = TEGRA_ACIF_BITS_32;
133                 break;
134         default:
135                 return -EINVAL;
136         }
137
138         cif_conf.audio_ch = channels;
139         cif_conf.client_ch = channels;
140         cif_conf.audio_bits = audio_bits;
141         cif_conf.client_bits = audio_bits;
142
143         tegra_set_cif(adx->regmap, reg, &cif_conf);
144
145         return 0;
146 }
147
148 static int tegra210_adx_out_hw_params(struct snd_pcm_substream *substream,
149                                       struct snd_pcm_hw_params *params,
150                                       struct snd_soc_dai *dai)
151 {
152         return tegra210_adx_set_audio_cif(dai, params_channels(params),
153                         params_format(params),
154                         TEGRA210_ADX_TX1_CIF_CTRL + ((dai->id - 1) * TEGRA210_ADX_AUDIOCIF_CH_STRIDE));
155 }
156
157 static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream,
158                                      struct snd_pcm_hw_params *params,
159                                      struct snd_soc_dai *dai)
160 {
161         return tegra210_adx_set_audio_cif(dai, params_channels(params),
162                                           params_format(params),
163                                           TEGRA210_ADX_RX_CIF_CTRL);
164 }
165
166 static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
167                                      struct snd_ctl_elem_value *ucontrol)
168 {
169         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
170         struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
171         struct soc_mixer_control *mc;
172         unsigned char *bytes_map = (unsigned char *)&adx->map;
173         int enabled;
174
175         mc = (struct soc_mixer_control *)kcontrol->private_value;
176         enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
177
178         if (enabled)
179                 ucontrol->value.integer.value[0] = bytes_map[mc->reg];
180         else
181                 ucontrol->value.integer.value[0] = 0;
182
183         return 0;
184 }
185
186 static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
187                                      struct snd_ctl_elem_value *ucontrol)
188 {
189         struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
190         struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
191         unsigned char *bytes_map = (unsigned char *)&adx->map;
192         int value = ucontrol->value.integer.value[0];
193         struct soc_mixer_control *mc =
194                 (struct soc_mixer_control *)kcontrol->private_value;;
195
196         if (value == bytes_map[mc->reg])
197                 return 0;
198
199         if (value >= 0 && value <= 255) {
200                 /* update byte map and enable slot */
201                 bytes_map[mc->reg] = value;
202                 adx->byte_mask[mc->reg / 32] |= (1 << (mc->reg % 32));
203         } else {
204                 /* reset byte map and disable slot */
205                 bytes_map[mc->reg] = 0;
206                 adx->byte_mask[mc->reg / 32] &= ~(1 << (mc->reg % 32));
207         }
208
209         return 1;
210 }
211
212 static const struct snd_soc_dai_ops tegra210_adx_in_dai_ops = {
213         .hw_params      = tegra210_adx_in_hw_params,
214         .startup        = tegra210_adx_startup,
215 };
216
217 static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
218         .hw_params      = tegra210_adx_out_hw_params,
219 };
220
221 #define IN_DAI                                                  \
222         {                                                       \
223                 .name = "ADX-RX-CIF",                           \
224                 .playback = {                                   \
225                         .stream_name = "RX-CIF-Playback",       \
226                         .channels_min = 1,                      \
227                         .channels_max = 16,                     \
228                         .rates = SNDRV_PCM_RATE_8000_192000,    \
229                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
230                                    SNDRV_PCM_FMTBIT_S16_LE |    \
231                                    SNDRV_PCM_FMTBIT_S32_LE,     \
232                 },                                              \
233                 .capture = {                                    \
234                         .stream_name = "RX-CIF-Capture",        \
235                         .channels_min = 1,                      \
236                         .channels_max = 16,                     \
237                         .rates = SNDRV_PCM_RATE_8000_192000,    \
238                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
239                                    SNDRV_PCM_FMTBIT_S16_LE |    \
240                                    SNDRV_PCM_FMTBIT_S32_LE,     \
241                 },                                              \
242                 .ops = &tegra210_adx_in_dai_ops,                \
243         }
244
245 #define OUT_DAI(id)                                             \
246         {                                                       \
247                 .name = "ADX-TX" #id "-CIF",                    \
248                 .playback = {                                   \
249                         .stream_name = "TX" #id "-CIF-Playback",\
250                         .channels_min = 1,                      \
251                         .channels_max = 16,                     \
252                         .rates = SNDRV_PCM_RATE_8000_192000,    \
253                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
254                                    SNDRV_PCM_FMTBIT_S16_LE |    \
255                                    SNDRV_PCM_FMTBIT_S32_LE,     \
256                 },                                              \
257                 .capture = {                                    \
258                         .stream_name = "TX" #id "-CIF-Capture", \
259                         .channels_min = 1,                      \
260                         .channels_max = 16,                     \
261                         .rates = SNDRV_PCM_RATE_8000_192000,    \
262                         .formats = SNDRV_PCM_FMTBIT_S8 |        \
263                                    SNDRV_PCM_FMTBIT_S16_LE |    \
264                                    SNDRV_PCM_FMTBIT_S32_LE,     \
265                 },                                              \
266                 .ops = &tegra210_adx_out_dai_ops,               \
267         }
268
269 static struct snd_soc_dai_driver tegra210_adx_dais[] = {
270         IN_DAI,
271         OUT_DAI(1),
272         OUT_DAI(2),
273         OUT_DAI(3),
274         OUT_DAI(4),
275 };
276
277 static const struct snd_soc_dapm_widget tegra210_adx_widgets[] = {
278         SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA210_ADX_ENABLE,
279                             TEGRA210_ADX_ENABLE_SHIFT, 0),
280         SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_ADX_CTRL, 0, 0),
281         SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_ADX_CTRL, 1, 0),
282         SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_ADX_CTRL, 2, 0),
283         SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_ADX_CTRL, 3, 0),
284 };
285
286 #define STREAM_ROUTES(id, sname)                                          \
287         { "XBAR-" sname,                NULL,   "XBAR-TX" },              \
288         { "RX-CIF-" sname,              NULL,   "XBAR-" sname },          \
289         { "RX",                         NULL,   "RX-CIF-" sname },        \
290         { "TX" #id,                     NULL,   "RX" },                   \
291         { "TX" #id "-CIF-" sname,       NULL,   "TX" #id },               \
292         { "TX" #id " XBAR-" sname,      NULL,   "TX" #id "-CIF-" sname }, \
293         { "TX" #id " XBAR-RX",          NULL,   "TX" #id " XBAR-" sname }
294
295 #define ADX_ROUTES(id)                  \
296         STREAM_ROUTES(id, "Playback"),  \
297         STREAM_ROUTES(id, "Capture")
298
299 #define STREAM_ROUTES(id, sname)                                          \
300         { "XBAR-" sname,                NULL,   "XBAR-TX" },              \
301         { "RX-CIF-" sname,              NULL,   "XBAR-" sname },          \
302         { "RX",                         NULL,   "RX-CIF-" sname },        \
303         { "TX" #id,                     NULL,   "RX" },                   \
304         { "TX" #id "-CIF-" sname,       NULL,   "TX" #id },               \
305         { "TX" #id " XBAR-" sname,      NULL,   "TX" #id "-CIF-" sname }, \
306         { "TX" #id " XBAR-RX",          NULL,   "TX" #id " XBAR-" sname }
307
308 #define ADX_ROUTES(id)                  \
309         STREAM_ROUTES(id, "Playback"),  \
310         STREAM_ROUTES(id, "Capture")
311
312 static const struct snd_soc_dapm_route tegra210_adx_routes[] = {
313         ADX_ROUTES(1),
314         ADX_ROUTES(2),
315         ADX_ROUTES(3),
316         ADX_ROUTES(4),
317 };
318
319 #define TEGRA210_ADX_BYTE_MAP_CTRL(reg)                  \
320         SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0, \
321                        tegra210_adx_get_byte_map,        \
322                        tegra210_adx_put_byte_map)
323
324 static struct snd_kcontrol_new tegra210_adx_controls[] = {
325         TEGRA210_ADX_BYTE_MAP_CTRL(0),
326         TEGRA210_ADX_BYTE_MAP_CTRL(1),
327         TEGRA210_ADX_BYTE_MAP_CTRL(2),
328         TEGRA210_ADX_BYTE_MAP_CTRL(3),
329         TEGRA210_ADX_BYTE_MAP_CTRL(4),
330         TEGRA210_ADX_BYTE_MAP_CTRL(5),
331         TEGRA210_ADX_BYTE_MAP_CTRL(6),
332         TEGRA210_ADX_BYTE_MAP_CTRL(7),
333         TEGRA210_ADX_BYTE_MAP_CTRL(8),
334         TEGRA210_ADX_BYTE_MAP_CTRL(9),
335         TEGRA210_ADX_BYTE_MAP_CTRL(10),
336         TEGRA210_ADX_BYTE_MAP_CTRL(11),
337         TEGRA210_ADX_BYTE_MAP_CTRL(12),
338         TEGRA210_ADX_BYTE_MAP_CTRL(13),
339         TEGRA210_ADX_BYTE_MAP_CTRL(14),
340         TEGRA210_ADX_BYTE_MAP_CTRL(15),
341         TEGRA210_ADX_BYTE_MAP_CTRL(16),
342         TEGRA210_ADX_BYTE_MAP_CTRL(17),
343         TEGRA210_ADX_BYTE_MAP_CTRL(18),
344         TEGRA210_ADX_BYTE_MAP_CTRL(19),
345         TEGRA210_ADX_BYTE_MAP_CTRL(20),
346         TEGRA210_ADX_BYTE_MAP_CTRL(21),
347         TEGRA210_ADX_BYTE_MAP_CTRL(22),
348         TEGRA210_ADX_BYTE_MAP_CTRL(23),
349         TEGRA210_ADX_BYTE_MAP_CTRL(24),
350         TEGRA210_ADX_BYTE_MAP_CTRL(25),
351         TEGRA210_ADX_BYTE_MAP_CTRL(26),
352         TEGRA210_ADX_BYTE_MAP_CTRL(27),
353         TEGRA210_ADX_BYTE_MAP_CTRL(28),
354         TEGRA210_ADX_BYTE_MAP_CTRL(29),
355         TEGRA210_ADX_BYTE_MAP_CTRL(30),
356         TEGRA210_ADX_BYTE_MAP_CTRL(31),
357         TEGRA210_ADX_BYTE_MAP_CTRL(32),
358         TEGRA210_ADX_BYTE_MAP_CTRL(33),
359         TEGRA210_ADX_BYTE_MAP_CTRL(34),
360         TEGRA210_ADX_BYTE_MAP_CTRL(35),
361         TEGRA210_ADX_BYTE_MAP_CTRL(36),
362         TEGRA210_ADX_BYTE_MAP_CTRL(37),
363         TEGRA210_ADX_BYTE_MAP_CTRL(38),
364         TEGRA210_ADX_BYTE_MAP_CTRL(39),
365         TEGRA210_ADX_BYTE_MAP_CTRL(40),
366         TEGRA210_ADX_BYTE_MAP_CTRL(41),
367         TEGRA210_ADX_BYTE_MAP_CTRL(42),
368         TEGRA210_ADX_BYTE_MAP_CTRL(43),
369         TEGRA210_ADX_BYTE_MAP_CTRL(44),
370         TEGRA210_ADX_BYTE_MAP_CTRL(45),
371         TEGRA210_ADX_BYTE_MAP_CTRL(46),
372         TEGRA210_ADX_BYTE_MAP_CTRL(47),
373         TEGRA210_ADX_BYTE_MAP_CTRL(48),
374         TEGRA210_ADX_BYTE_MAP_CTRL(49),
375         TEGRA210_ADX_BYTE_MAP_CTRL(50),
376         TEGRA210_ADX_BYTE_MAP_CTRL(51),
377         TEGRA210_ADX_BYTE_MAP_CTRL(52),
378         TEGRA210_ADX_BYTE_MAP_CTRL(53),
379         TEGRA210_ADX_BYTE_MAP_CTRL(54),
380         TEGRA210_ADX_BYTE_MAP_CTRL(55),
381         TEGRA210_ADX_BYTE_MAP_CTRL(56),
382         TEGRA210_ADX_BYTE_MAP_CTRL(57),
383         TEGRA210_ADX_BYTE_MAP_CTRL(58),
384         TEGRA210_ADX_BYTE_MAP_CTRL(59),
385         TEGRA210_ADX_BYTE_MAP_CTRL(60),
386         TEGRA210_ADX_BYTE_MAP_CTRL(61),
387         TEGRA210_ADX_BYTE_MAP_CTRL(62),
388         TEGRA210_ADX_BYTE_MAP_CTRL(63),
389 };
390
391 static const struct snd_soc_component_driver tegra210_adx_cmpnt = {
392         .dapm_widgets           = tegra210_adx_widgets,
393         .num_dapm_widgets       = ARRAY_SIZE(tegra210_adx_widgets),
394         .dapm_routes            = tegra210_adx_routes,
395         .num_dapm_routes        = ARRAY_SIZE(tegra210_adx_routes),
396         .controls               = tegra210_adx_controls,
397         .num_controls           = ARRAY_SIZE(tegra210_adx_controls),
398 };
399
400 static bool tegra210_adx_wr_reg(struct device *dev,
401                                 unsigned int reg)
402 {
403         switch (reg) {
404         case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL:
405         case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL:
406         case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG:
407         case TEGRA210_ADX_CTRL ... TEGRA210_ADX_IN_BYTE_EN1:
408         case TEGRA210_ADX_CFG_RAM_CTRL ... TEGRA210_ADX_CFG_RAM_DATA:
409                 return true;
410         default:
411                 return false;
412         }
413 }
414
415 static bool tegra210_adx_rd_reg(struct device *dev,
416                                 unsigned int reg)
417 {
418         switch (reg) {
419         case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_CFG_RAM_DATA:
420                 return true;
421         default:
422                 return false;
423         }
424 }
425
426 static bool tegra210_adx_volatile_reg(struct device *dev,
427                                 unsigned int reg)
428 {
429         switch (reg) {
430         case TEGRA210_ADX_RX_STATUS:
431         case TEGRA210_ADX_RX_INT_STATUS:
432         case TEGRA210_ADX_RX_INT_SET:
433         case TEGRA210_ADX_TX_STATUS:
434         case TEGRA210_ADX_TX_INT_STATUS:
435         case TEGRA210_ADX_TX_INT_SET:
436         case TEGRA210_ADX_SOFT_RESET:
437         case TEGRA210_ADX_STATUS:
438         case TEGRA210_ADX_INT_STATUS:
439         case TEGRA210_ADX_CFG_RAM_CTRL:
440         case TEGRA210_ADX_CFG_RAM_DATA:
441                 return true;
442         default:
443                 break;
444         }
445
446         return false;
447 }
448
449 static const struct regmap_config tegra210_adx_regmap_config = {
450         .reg_bits               = 32,
451         .reg_stride             = 4,
452         .val_bits               = 32,
453         .max_register           = TEGRA210_ADX_CFG_RAM_DATA,
454         .writeable_reg          = tegra210_adx_wr_reg,
455         .readable_reg           = tegra210_adx_rd_reg,
456         .volatile_reg           = tegra210_adx_volatile_reg,
457         .reg_defaults           = tegra210_adx_reg_defaults,
458         .num_reg_defaults       = ARRAY_SIZE(tegra210_adx_reg_defaults),
459         .cache_type             = REGCACHE_FLAT,
460 };
461
462 static const struct of_device_id tegra210_adx_of_match[] = {
463         { .compatible = "nvidia,tegra210-adx" },
464         {},
465 };
466 MODULE_DEVICE_TABLE(of, tegra210_adx_of_match);
467
468 static int tegra210_adx_platform_probe(struct platform_device *pdev)
469 {
470         struct device *dev = &pdev->dev;
471         struct tegra210_adx *adx;
472         void __iomem *regs;
473         int err;
474
475         adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL);
476         if (!adx)
477                 return -ENOMEM;
478
479         dev_set_drvdata(dev, adx);
480
481         regs = devm_platform_ioremap_resource(pdev, 0);
482         if (IS_ERR(regs))
483                 return PTR_ERR(regs);
484
485         adx->regmap = devm_regmap_init_mmio(dev, regs,
486                                             &tegra210_adx_regmap_config);
487         if (IS_ERR(adx->regmap)) {
488                 dev_err(dev, "regmap init failed\n");
489                 return PTR_ERR(adx->regmap);
490         }
491
492         regcache_cache_only(adx->regmap, true);
493
494         err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt,
495                                               tegra210_adx_dais,
496                                               ARRAY_SIZE(tegra210_adx_dais));
497         if (err) {
498                 dev_err(dev, "can't register ADX component, err: %d\n", err);
499                 return err;
500         }
501
502         pm_runtime_enable(dev);
503
504         return 0;
505 }
506
507 static int tegra210_adx_platform_remove(struct platform_device *pdev)
508 {
509         pm_runtime_disable(&pdev->dev);
510
511         return 0;
512 }
513
514 static const struct dev_pm_ops tegra210_adx_pm_ops = {
515         SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
516                            tegra210_adx_runtime_resume, NULL)
517         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
518                                 pm_runtime_force_resume)
519 };
520
521 static struct platform_driver tegra210_adx_driver = {
522         .driver = {
523                 .name = "tegra210-adx",
524                 .of_match_table = tegra210_adx_of_match,
525                 .pm = &tegra210_adx_pm_ops,
526         },
527         .probe = tegra210_adx_platform_probe,
528         .remove = tegra210_adx_platform_remove,
529 };
530 module_platform_driver(tegra210_adx_driver);
531
532 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
533 MODULE_DESCRIPTION("Tegra210 ADX ASoC driver");
534 MODULE_LICENSE("GPL v2");