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