Merge tag 'kconfig-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux-2.6-microblaze.git] / sound / soc / tegra / tegra210_ahub.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // tegra210_ahub.c - Tegra210 AHUB driver
4 //
5 // Copyright (c) 2020 NVIDIA CORPORATION.  All rights reserved.
6
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/module.h>
10 #include <linux/of_platform.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14 #include <sound/soc.h>
15 #include "tegra210_ahub.h"
16
17 static int tegra_ahub_get_value_enum(struct snd_kcontrol *kctl,
18                                      struct snd_ctl_elem_value *uctl)
19 {
20         struct snd_soc_component *cmpnt = snd_soc_dapm_kcontrol_component(kctl);
21         struct tegra_ahub *ahub = snd_soc_component_get_drvdata(cmpnt);
22         struct soc_enum *e = (struct soc_enum *)kctl->private_value;
23         unsigned int reg, i, bit_pos = 0;
24
25         /*
26          * Find the bit position of current MUX input.
27          * If nothing is set, position would be 0 and it corresponds to 'None'.
28          */
29         for (i = 0; i < ahub->soc_data->reg_count; i++) {
30                 unsigned int reg_val;
31
32                 reg = e->reg + (TEGRA210_XBAR_PART1_RX * i);
33                 reg_val = snd_soc_component_read(cmpnt, reg);
34                 reg_val &= ahub->soc_data->mask[i];
35
36                 if (reg_val) {
37                         bit_pos = ffs(reg_val) +
38                                   (8 * cmpnt->val_bytes * i);
39                         break;
40                 }
41         }
42
43         /* Find index related to the item in array *_ahub_mux_texts[] */
44         for (i = 0; i < e->items; i++) {
45                 if (bit_pos == e->values[i]) {
46                         uctl->value.enumerated.item[0] = i;
47                         break;
48                 }
49         }
50
51         return 0;
52 }
53
54 static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
55                                      struct snd_ctl_elem_value *uctl)
56 {
57         struct snd_soc_component *cmpnt = snd_soc_dapm_kcontrol_component(kctl);
58         struct tegra_ahub *ahub = snd_soc_component_get_drvdata(cmpnt);
59         struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctl);
60         struct soc_enum *e = (struct soc_enum *)kctl->private_value;
61         struct snd_soc_dapm_update update[TEGRA_XBAR_UPDATE_MAX_REG] = { };
62         unsigned int *item = uctl->value.enumerated.item;
63         unsigned int value = e->values[item[0]];
64         unsigned int i, bit_pos, reg_idx = 0, reg_val = 0;
65
66         if (item[0] >= e->items)
67                 return -EINVAL;
68
69         if (value) {
70                 /* Get the register index and value to set */
71                 reg_idx = (value - 1) / (8 * cmpnt->val_bytes);
72                 bit_pos = (value - 1) % (8 * cmpnt->val_bytes);
73                 reg_val = BIT(bit_pos);
74         }
75
76         /*
77          * Run through all parts of a MUX register to find the state changes.
78          * There will be an additional update if new MUX input value is from
79          * different part of the MUX register.
80          */
81         for (i = 0; i < ahub->soc_data->reg_count; i++) {
82                 update[i].reg = e->reg + (TEGRA210_XBAR_PART1_RX * i);
83                 update[i].val = (i == reg_idx) ? reg_val : 0;
84                 update[i].mask = ahub->soc_data->mask[i];
85                 update[i].kcontrol = kctl;
86
87                 /* Update widget power if state has changed */
88                 if (snd_soc_component_test_bits(cmpnt, update[i].reg,
89                                                 update[i].mask, update[i].val))
90                         snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e,
91                                                       &update[i]);
92         }
93
94         return 0;
95 }
96
97 static struct snd_soc_dai_driver tegra210_ahub_dais[] = {
98         DAI(ADMAIF1),
99         DAI(ADMAIF2),
100         DAI(ADMAIF3),
101         DAI(ADMAIF4),
102         DAI(ADMAIF5),
103         DAI(ADMAIF6),
104         DAI(ADMAIF7),
105         DAI(ADMAIF8),
106         DAI(ADMAIF9),
107         DAI(ADMAIF10),
108         DAI(I2S1),
109         DAI(I2S2),
110         DAI(I2S3),
111         DAI(I2S4),
112         DAI(I2S5),
113         DAI(DMIC1),
114         DAI(DMIC2),
115         DAI(DMIC3),
116 };
117
118 static struct snd_soc_dai_driver tegra186_ahub_dais[] = {
119         DAI(ADMAIF1),
120         DAI(ADMAIF2),
121         DAI(ADMAIF3),
122         DAI(ADMAIF4),
123         DAI(ADMAIF5),
124         DAI(ADMAIF6),
125         DAI(ADMAIF7),
126         DAI(ADMAIF8),
127         DAI(ADMAIF9),
128         DAI(ADMAIF10),
129         DAI(ADMAIF11),
130         DAI(ADMAIF12),
131         DAI(ADMAIF13),
132         DAI(ADMAIF14),
133         DAI(ADMAIF15),
134         DAI(ADMAIF16),
135         DAI(ADMAIF17),
136         DAI(ADMAIF18),
137         DAI(ADMAIF19),
138         DAI(ADMAIF20),
139         DAI(I2S1),
140         DAI(I2S2),
141         DAI(I2S3),
142         DAI(I2S4),
143         DAI(I2S5),
144         DAI(I2S6),
145         DAI(DMIC1),
146         DAI(DMIC2),
147         DAI(DMIC3),
148         DAI(DMIC4),
149         DAI(DSPK1),
150         DAI(DSPK2),
151 };
152
153 static const char * const tegra210_ahub_mux_texts[] = {
154         "None",
155         "ADMAIF1",
156         "ADMAIF2",
157         "ADMAIF3",
158         "ADMAIF4",
159         "ADMAIF5",
160         "ADMAIF6",
161         "ADMAIF7",
162         "ADMAIF8",
163         "ADMAIF9",
164         "ADMAIF10",
165         "I2S1",
166         "I2S2",
167         "I2S3",
168         "I2S4",
169         "I2S5",
170         "DMIC1",
171         "DMIC2",
172         "DMIC3",
173 };
174
175 static const char * const tegra186_ahub_mux_texts[] = {
176         "None",
177         "ADMAIF1",
178         "ADMAIF2",
179         "ADMAIF3",
180         "ADMAIF4",
181         "ADMAIF5",
182         "ADMAIF6",
183         "ADMAIF7",
184         "ADMAIF8",
185         "ADMAIF9",
186         "ADMAIF10",
187         "ADMAIF11",
188         "ADMAIF12",
189         "ADMAIF13",
190         "ADMAIF14",
191         "ADMAIF15",
192         "ADMAIF16",
193         "I2S1",
194         "I2S2",
195         "I2S3",
196         "I2S4",
197         "I2S5",
198         "I2S6",
199         "ADMAIF17",
200         "ADMAIF18",
201         "ADMAIF19",
202         "ADMAIF20",
203         "DMIC1",
204         "DMIC2",
205         "DMIC3",
206         "DMIC4",
207 };
208
209 static const unsigned int tegra210_ahub_mux_values[] = {
210         0,
211         MUX_VALUE(0, 0),
212         MUX_VALUE(0, 1),
213         MUX_VALUE(0, 2),
214         MUX_VALUE(0, 3),
215         MUX_VALUE(0, 4),
216         MUX_VALUE(0, 5),
217         MUX_VALUE(0, 6),
218         MUX_VALUE(0, 7),
219         MUX_VALUE(0, 8),
220         MUX_VALUE(0, 9),
221         MUX_VALUE(0, 16),
222         MUX_VALUE(0, 17),
223         MUX_VALUE(0, 18),
224         MUX_VALUE(0, 19),
225         MUX_VALUE(0, 20),
226         MUX_VALUE(2, 18),
227         MUX_VALUE(2, 19),
228         MUX_VALUE(2, 20),
229 };
230
231 static const unsigned int tegra186_ahub_mux_values[] = {
232         0,
233         MUX_VALUE(0, 0),
234         MUX_VALUE(0, 1),
235         MUX_VALUE(0, 2),
236         MUX_VALUE(0, 3),
237         MUX_VALUE(0, 4),
238         MUX_VALUE(0, 5),
239         MUX_VALUE(0, 6),
240         MUX_VALUE(0, 7),
241         MUX_VALUE(0, 8),
242         MUX_VALUE(0, 9),
243         MUX_VALUE(0, 10),
244         MUX_VALUE(0, 11),
245         MUX_VALUE(0, 12),
246         MUX_VALUE(0, 13),
247         MUX_VALUE(0, 14),
248         MUX_VALUE(0, 15),
249         MUX_VALUE(0, 16),
250         MUX_VALUE(0, 17),
251         MUX_VALUE(0, 18),
252         MUX_VALUE(0, 19),
253         MUX_VALUE(0, 20),
254         MUX_VALUE(0, 21),
255         MUX_VALUE(3, 16),
256         MUX_VALUE(3, 17),
257         MUX_VALUE(3, 18),
258         MUX_VALUE(3, 19),
259         MUX_VALUE(2, 18),
260         MUX_VALUE(2, 19),
261         MUX_VALUE(2, 20),
262         MUX_VALUE(2, 21),
263 };
264
265 /* Controls for t210 */
266 MUX_ENUM_CTRL_DECL(t210_admaif1_tx, 0x00);
267 MUX_ENUM_CTRL_DECL(t210_admaif2_tx, 0x01);
268 MUX_ENUM_CTRL_DECL(t210_admaif3_tx, 0x02);
269 MUX_ENUM_CTRL_DECL(t210_admaif4_tx, 0x03);
270 MUX_ENUM_CTRL_DECL(t210_admaif5_tx, 0x04);
271 MUX_ENUM_CTRL_DECL(t210_admaif6_tx, 0x05);
272 MUX_ENUM_CTRL_DECL(t210_admaif7_tx, 0x06);
273 MUX_ENUM_CTRL_DECL(t210_admaif8_tx, 0x07);
274 MUX_ENUM_CTRL_DECL(t210_admaif9_tx, 0x08);
275 MUX_ENUM_CTRL_DECL(t210_admaif10_tx, 0x09);
276 MUX_ENUM_CTRL_DECL(t210_i2s1_tx, 0x10);
277 MUX_ENUM_CTRL_DECL(t210_i2s2_tx, 0x11);
278 MUX_ENUM_CTRL_DECL(t210_i2s3_tx, 0x12);
279 MUX_ENUM_CTRL_DECL(t210_i2s4_tx, 0x13);
280 MUX_ENUM_CTRL_DECL(t210_i2s5_tx, 0x14);
281
282 /* Controls for t186 */
283 MUX_ENUM_CTRL_DECL_186(t186_admaif1_tx, 0x00);
284 MUX_ENUM_CTRL_DECL_186(t186_admaif2_tx, 0x01);
285 MUX_ENUM_CTRL_DECL_186(t186_admaif3_tx, 0x02);
286 MUX_ENUM_CTRL_DECL_186(t186_admaif4_tx, 0x03);
287 MUX_ENUM_CTRL_DECL_186(t186_admaif5_tx, 0x04);
288 MUX_ENUM_CTRL_DECL_186(t186_admaif6_tx, 0x05);
289 MUX_ENUM_CTRL_DECL_186(t186_admaif7_tx, 0x06);
290 MUX_ENUM_CTRL_DECL_186(t186_admaif8_tx, 0x07);
291 MUX_ENUM_CTRL_DECL_186(t186_admaif9_tx, 0x08);
292 MUX_ENUM_CTRL_DECL_186(t186_admaif10_tx, 0x09);
293 MUX_ENUM_CTRL_DECL_186(t186_i2s1_tx, 0x10);
294 MUX_ENUM_CTRL_DECL_186(t186_i2s2_tx, 0x11);
295 MUX_ENUM_CTRL_DECL_186(t186_i2s3_tx, 0x12);
296 MUX_ENUM_CTRL_DECL_186(t186_i2s4_tx, 0x13);
297 MUX_ENUM_CTRL_DECL_186(t186_i2s5_tx, 0x14);
298 MUX_ENUM_CTRL_DECL_186(t186_admaif11_tx, 0x0a);
299 MUX_ENUM_CTRL_DECL_186(t186_admaif12_tx, 0x0b);
300 MUX_ENUM_CTRL_DECL_186(t186_admaif13_tx, 0x0c);
301 MUX_ENUM_CTRL_DECL_186(t186_admaif14_tx, 0x0d);
302 MUX_ENUM_CTRL_DECL_186(t186_admaif15_tx, 0x0e);
303 MUX_ENUM_CTRL_DECL_186(t186_admaif16_tx, 0x0f);
304 MUX_ENUM_CTRL_DECL_186(t186_i2s6_tx, 0x15);
305 MUX_ENUM_CTRL_DECL_186(t186_dspk1_tx, 0x30);
306 MUX_ENUM_CTRL_DECL_186(t186_dspk2_tx, 0x31);
307 MUX_ENUM_CTRL_DECL_186(t186_admaif17_tx, 0x68);
308 MUX_ENUM_CTRL_DECL_186(t186_admaif18_tx, 0x69);
309 MUX_ENUM_CTRL_DECL_186(t186_admaif19_tx, 0x6a);
310 MUX_ENUM_CTRL_DECL_186(t186_admaif20_tx, 0x6b);
311
312 /*
313  * The number of entries in, and order of, this array is closely tied to the
314  * calculation of tegra210_ahub_codec.num_dapm_widgets near the end of
315  * tegra210_ahub_probe()
316  */
317 static const struct snd_soc_dapm_widget tegra210_ahub_widgets[] = {
318         WIDGETS("ADMAIF1", t210_admaif1_tx),
319         WIDGETS("ADMAIF2", t210_admaif2_tx),
320         WIDGETS("ADMAIF3", t210_admaif3_tx),
321         WIDGETS("ADMAIF4", t210_admaif4_tx),
322         WIDGETS("ADMAIF5", t210_admaif5_tx),
323         WIDGETS("ADMAIF6", t210_admaif6_tx),
324         WIDGETS("ADMAIF7", t210_admaif7_tx),
325         WIDGETS("ADMAIF8", t210_admaif8_tx),
326         WIDGETS("ADMAIF9", t210_admaif9_tx),
327         WIDGETS("ADMAIF10", t210_admaif10_tx),
328         WIDGETS("I2S1", t210_i2s1_tx),
329         WIDGETS("I2S2", t210_i2s2_tx),
330         WIDGETS("I2S3", t210_i2s3_tx),
331         WIDGETS("I2S4", t210_i2s4_tx),
332         WIDGETS("I2S5", t210_i2s5_tx),
333         TX_WIDGETS("DMIC1"),
334         TX_WIDGETS("DMIC2"),
335         TX_WIDGETS("DMIC3"),
336 };
337
338 static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = {
339         WIDGETS("ADMAIF1", t186_admaif1_tx),
340         WIDGETS("ADMAIF2", t186_admaif2_tx),
341         WIDGETS("ADMAIF3", t186_admaif3_tx),
342         WIDGETS("ADMAIF4", t186_admaif4_tx),
343         WIDGETS("ADMAIF5", t186_admaif5_tx),
344         WIDGETS("ADMAIF6", t186_admaif6_tx),
345         WIDGETS("ADMAIF7", t186_admaif7_tx),
346         WIDGETS("ADMAIF8", t186_admaif8_tx),
347         WIDGETS("ADMAIF9", t186_admaif9_tx),
348         WIDGETS("ADMAIF10", t186_admaif10_tx),
349         WIDGETS("ADMAIF11", t186_admaif11_tx),
350         WIDGETS("ADMAIF12", t186_admaif12_tx),
351         WIDGETS("ADMAIF13", t186_admaif13_tx),
352         WIDGETS("ADMAIF14", t186_admaif14_tx),
353         WIDGETS("ADMAIF15", t186_admaif15_tx),
354         WIDGETS("ADMAIF16", t186_admaif16_tx),
355         WIDGETS("ADMAIF17", t186_admaif17_tx),
356         WIDGETS("ADMAIF18", t186_admaif18_tx),
357         WIDGETS("ADMAIF19", t186_admaif19_tx),
358         WIDGETS("ADMAIF20", t186_admaif20_tx),
359         WIDGETS("I2S1", t186_i2s1_tx),
360         WIDGETS("I2S2", t186_i2s2_tx),
361         WIDGETS("I2S3", t186_i2s3_tx),
362         WIDGETS("I2S4", t186_i2s4_tx),
363         WIDGETS("I2S5", t186_i2s5_tx),
364         WIDGETS("I2S6", t186_i2s6_tx),
365         TX_WIDGETS("DMIC1"),
366         TX_WIDGETS("DMIC2"),
367         TX_WIDGETS("DMIC3"),
368         TX_WIDGETS("DMIC4"),
369         WIDGETS("DSPK1", t186_dspk1_tx),
370         WIDGETS("DSPK2", t186_dspk2_tx),
371 };
372
373 #define TEGRA_COMMON_MUX_ROUTES(name)                                   \
374         { name " XBAR-TX",       NULL,          name " Mux" },          \
375         { name " Mux",          "ADMAIF1",      "ADMAIF1 XBAR-RX" },    \
376         { name " Mux",          "ADMAIF2",      "ADMAIF2 XBAR-RX" },    \
377         { name " Mux",          "ADMAIF3",      "ADMAIF3 XBAR-RX" },    \
378         { name " Mux",          "ADMAIF4",      "ADMAIF4 XBAR-RX" },    \
379         { name " Mux",          "ADMAIF5",      "ADMAIF5 XBAR-RX" },    \
380         { name " Mux",          "ADMAIF6",      "ADMAIF6 XBAR-RX" },    \
381         { name " Mux",          "ADMAIF7",      "ADMAIF7 XBAR-RX" },    \
382         { name " Mux",          "ADMAIF8",      "ADMAIF8 XBAR-RX" },    \
383         { name " Mux",          "ADMAIF9",      "ADMAIF9 XBAR-RX" },    \
384         { name " Mux",          "ADMAIF10",     "ADMAIF10 XBAR-RX" },   \
385         { name " Mux",          "I2S1",         "I2S1 XBAR-RX" },       \
386         { name " Mux",          "I2S2",         "I2S2 XBAR-RX" },       \
387         { name " Mux",          "I2S3",         "I2S3 XBAR-RX" },       \
388         { name " Mux",          "I2S4",         "I2S4 XBAR-RX" },       \
389         { name " Mux",          "I2S5",         "I2S5 XBAR-RX" },       \
390         { name " Mux",          "DMIC1",        "DMIC1 XBAR-RX" },      \
391         { name " Mux",          "DMIC2",        "DMIC2 XBAR-RX" },      \
392         { name " Mux",          "DMIC3",        "DMIC3 XBAR-RX" },
393
394 #define TEGRA186_ONLY_MUX_ROUTES(name)                                  \
395         { name " Mux",          "ADMAIF11",     "ADMAIF11 XBAR-RX" },   \
396         { name " Mux",          "ADMAIF12",     "ADMAIF12 XBAR-RX" },   \
397         { name " Mux",          "ADMAIF13",     "ADMAIF13 XBAR-RX" },   \
398         { name " Mux",          "ADMAIF14",     "ADMAIF14 XBAR-RX" },   \
399         { name " Mux",          "ADMAIF15",     "ADMAIF15 XBAR-RX" },   \
400         { name " Mux",          "ADMAIF16",     "ADMAIF16 XBAR-RX" },   \
401         { name " Mux",          "ADMAIF17",     "ADMAIF17 XBAR-RX" },   \
402         { name " Mux",          "ADMAIF18",     "ADMAIF18 XBAR-RX" },   \
403         { name " Mux",          "ADMAIF19",     "ADMAIF19 XBAR-RX" },   \
404         { name " Mux",          "ADMAIF20",     "ADMAIF20 XBAR-RX" },   \
405         { name " Mux",          "I2S6",         "I2S6 XBAR-RX" },       \
406         { name " Mux",          "DMIC4",        "DMIC4 XBAR-RX" },
407
408 #define TEGRA210_MUX_ROUTES(name)                                               \
409         TEGRA_COMMON_MUX_ROUTES(name)
410
411 #define TEGRA186_MUX_ROUTES(name)                                               \
412         TEGRA_COMMON_MUX_ROUTES(name)                                   \
413         TEGRA186_ONLY_MUX_ROUTES(name)
414
415 /* Connect FEs with XBAR */
416 #define TEGRA_FE_ROUTES(name) \
417         { name " XBAR-Playback",        NULL,   name " Playback" },     \
418         { name " XBAR-RX",              NULL,   name " XBAR-Playback"}, \
419         { name " XBAR-Capture",         NULL,   name " XBAR-TX" },      \
420         { name " Capture",              NULL,   name " XBAR-Capture" },
421
422 /*
423  * The number of entries in, and order of, this array is closely tied to the
424  * calculation of tegra210_ahub_codec.num_dapm_routes near the end of
425  * tegra210_ahub_probe()
426  */
427 static const struct snd_soc_dapm_route tegra210_ahub_routes[] = {
428         TEGRA_FE_ROUTES("ADMAIF1")
429         TEGRA_FE_ROUTES("ADMAIF2")
430         TEGRA_FE_ROUTES("ADMAIF3")
431         TEGRA_FE_ROUTES("ADMAIF4")
432         TEGRA_FE_ROUTES("ADMAIF5")
433         TEGRA_FE_ROUTES("ADMAIF6")
434         TEGRA_FE_ROUTES("ADMAIF7")
435         TEGRA_FE_ROUTES("ADMAIF8")
436         TEGRA_FE_ROUTES("ADMAIF9")
437         TEGRA_FE_ROUTES("ADMAIF10")
438         TEGRA210_MUX_ROUTES("ADMAIF1")
439         TEGRA210_MUX_ROUTES("ADMAIF2")
440         TEGRA210_MUX_ROUTES("ADMAIF3")
441         TEGRA210_MUX_ROUTES("ADMAIF4")
442         TEGRA210_MUX_ROUTES("ADMAIF5")
443         TEGRA210_MUX_ROUTES("ADMAIF6")
444         TEGRA210_MUX_ROUTES("ADMAIF7")
445         TEGRA210_MUX_ROUTES("ADMAIF8")
446         TEGRA210_MUX_ROUTES("ADMAIF9")
447         TEGRA210_MUX_ROUTES("ADMAIF10")
448         TEGRA210_MUX_ROUTES("I2S1")
449         TEGRA210_MUX_ROUTES("I2S2")
450         TEGRA210_MUX_ROUTES("I2S3")
451         TEGRA210_MUX_ROUTES("I2S4")
452         TEGRA210_MUX_ROUTES("I2S5")
453 };
454
455 static const struct snd_soc_dapm_route tegra186_ahub_routes[] = {
456         TEGRA_FE_ROUTES("ADMAIF1")
457         TEGRA_FE_ROUTES("ADMAIF2")
458         TEGRA_FE_ROUTES("ADMAIF3")
459         TEGRA_FE_ROUTES("ADMAIF4")
460         TEGRA_FE_ROUTES("ADMAIF5")
461         TEGRA_FE_ROUTES("ADMAIF6")
462         TEGRA_FE_ROUTES("ADMAIF7")
463         TEGRA_FE_ROUTES("ADMAIF8")
464         TEGRA_FE_ROUTES("ADMAIF9")
465         TEGRA_FE_ROUTES("ADMAIF10")
466         TEGRA_FE_ROUTES("ADMAIF11")
467         TEGRA_FE_ROUTES("ADMAIF12")
468         TEGRA_FE_ROUTES("ADMAIF13")
469         TEGRA_FE_ROUTES("ADMAIF14")
470         TEGRA_FE_ROUTES("ADMAIF15")
471         TEGRA_FE_ROUTES("ADMAIF16")
472         TEGRA_FE_ROUTES("ADMAIF17")
473         TEGRA_FE_ROUTES("ADMAIF18")
474         TEGRA_FE_ROUTES("ADMAIF19")
475         TEGRA_FE_ROUTES("ADMAIF20")
476         TEGRA186_MUX_ROUTES("ADMAIF1")
477         TEGRA186_MUX_ROUTES("ADMAIF2")
478         TEGRA186_MUX_ROUTES("ADMAIF3")
479         TEGRA186_MUX_ROUTES("ADMAIF4")
480         TEGRA186_MUX_ROUTES("ADMAIF5")
481         TEGRA186_MUX_ROUTES("ADMAIF6")
482         TEGRA186_MUX_ROUTES("ADMAIF7")
483         TEGRA186_MUX_ROUTES("ADMAIF8")
484         TEGRA186_MUX_ROUTES("ADMAIF9")
485         TEGRA186_MUX_ROUTES("ADMAIF10")
486         TEGRA186_MUX_ROUTES("ADMAIF11")
487         TEGRA186_MUX_ROUTES("ADMAIF12")
488         TEGRA186_MUX_ROUTES("ADMAIF13")
489         TEGRA186_MUX_ROUTES("ADMAIF14")
490         TEGRA186_MUX_ROUTES("ADMAIF15")
491         TEGRA186_MUX_ROUTES("ADMAIF16")
492         TEGRA186_MUX_ROUTES("ADMAIF17")
493         TEGRA186_MUX_ROUTES("ADMAIF18")
494         TEGRA186_MUX_ROUTES("ADMAIF19")
495         TEGRA186_MUX_ROUTES("ADMAIF20")
496         TEGRA186_MUX_ROUTES("I2S1")
497         TEGRA186_MUX_ROUTES("I2S2")
498         TEGRA186_MUX_ROUTES("I2S3")
499         TEGRA186_MUX_ROUTES("I2S4")
500         TEGRA186_MUX_ROUTES("I2S5")
501         TEGRA186_MUX_ROUTES("I2S6")
502         TEGRA186_MUX_ROUTES("DSPK1")
503         TEGRA186_MUX_ROUTES("DSPK2")
504 };
505
506 static const struct snd_soc_component_driver tegra210_ahub_component = {
507         .dapm_widgets           = tegra210_ahub_widgets,
508         .num_dapm_widgets       = ARRAY_SIZE(tegra210_ahub_widgets),
509         .dapm_routes            = tegra210_ahub_routes,
510         .num_dapm_routes        = ARRAY_SIZE(tegra210_ahub_routes),
511 };
512
513 static const struct snd_soc_component_driver tegra186_ahub_component = {
514         .dapm_widgets = tegra186_ahub_widgets,
515         .num_dapm_widgets = ARRAY_SIZE(tegra186_ahub_widgets),
516         .dapm_routes = tegra186_ahub_routes,
517         .num_dapm_routes = ARRAY_SIZE(tegra186_ahub_routes),
518 };
519
520 static const struct regmap_config tegra210_ahub_regmap_config = {
521         .reg_bits               = 32,
522         .val_bits               = 32,
523         .reg_stride             = 4,
524         .max_register           = TEGRA210_MAX_REGISTER_ADDR,
525         .cache_type             = REGCACHE_FLAT,
526 };
527
528 static const struct regmap_config tegra186_ahub_regmap_config = {
529         .reg_bits               = 32,
530         .val_bits               = 32,
531         .reg_stride             = 4,
532         .max_register           = TEGRA186_MAX_REGISTER_ADDR,
533         .cache_type             = REGCACHE_FLAT,
534 };
535
536 static const struct tegra_ahub_soc_data soc_data_tegra210 = {
537         .cmpnt_drv      = &tegra210_ahub_component,
538         .dai_drv        = tegra210_ahub_dais,
539         .num_dais       = ARRAY_SIZE(tegra210_ahub_dais),
540         .regmap_config  = &tegra210_ahub_regmap_config,
541         .mask[0]        = TEGRA210_XBAR_REG_MASK_0,
542         .mask[1]        = TEGRA210_XBAR_REG_MASK_1,
543         .mask[2]        = TEGRA210_XBAR_REG_MASK_2,
544         .mask[3]        = TEGRA210_XBAR_REG_MASK_3,
545         .reg_count      = TEGRA210_XBAR_UPDATE_MAX_REG,
546 };
547
548 static const struct tegra_ahub_soc_data soc_data_tegra186 = {
549         .cmpnt_drv      = &tegra186_ahub_component,
550         .dai_drv        = tegra186_ahub_dais,
551         .num_dais       = ARRAY_SIZE(tegra186_ahub_dais),
552         .regmap_config  = &tegra186_ahub_regmap_config,
553         .mask[0]        = TEGRA186_XBAR_REG_MASK_0,
554         .mask[1]        = TEGRA186_XBAR_REG_MASK_1,
555         .mask[2]        = TEGRA186_XBAR_REG_MASK_2,
556         .mask[3]        = TEGRA186_XBAR_REG_MASK_3,
557         .reg_count      = TEGRA186_XBAR_UPDATE_MAX_REG,
558 };
559
560 static const struct of_device_id tegra_ahub_of_match[] = {
561         { .compatible = "nvidia,tegra210-ahub", .data = &soc_data_tegra210 },
562         { .compatible = "nvidia,tegra186-ahub", .data = &soc_data_tegra186 },
563         {},
564 };
565 MODULE_DEVICE_TABLE(of, tegra_ahub_of_match);
566
567 static int __maybe_unused tegra_ahub_runtime_suspend(struct device *dev)
568 {
569         struct tegra_ahub *ahub = dev_get_drvdata(dev);
570
571         regcache_cache_only(ahub->regmap, true);
572         regcache_mark_dirty(ahub->regmap);
573
574         clk_disable_unprepare(ahub->clk);
575
576         return 0;
577 }
578
579 static int __maybe_unused tegra_ahub_runtime_resume(struct device *dev)
580 {
581         struct tegra_ahub *ahub = dev_get_drvdata(dev);
582         int err;
583
584         err = clk_prepare_enable(ahub->clk);
585         if (err) {
586                 dev_err(dev, "failed to enable AHUB clock, err: %d\n", err);
587                 return err;
588         }
589
590         regcache_cache_only(ahub->regmap, false);
591         regcache_sync(ahub->regmap);
592
593         return 0;
594 }
595
596 static int tegra_ahub_probe(struct platform_device *pdev)
597 {
598         struct tegra_ahub *ahub;
599         void __iomem *regs;
600         int err;
601
602         ahub = devm_kzalloc(&pdev->dev, sizeof(*ahub), GFP_KERNEL);
603         if (!ahub)
604                 return -ENOMEM;
605
606         ahub->soc_data = of_device_get_match_data(&pdev->dev);
607
608         platform_set_drvdata(pdev, ahub);
609
610         ahub->clk = devm_clk_get(&pdev->dev, "ahub");
611         if (IS_ERR(ahub->clk)) {
612                 dev_err(&pdev->dev, "can't retrieve AHUB clock\n");
613                 return PTR_ERR(ahub->clk);
614         }
615
616         regs = devm_platform_ioremap_resource(pdev, 0);
617         if (IS_ERR(regs))
618                 return PTR_ERR(regs);
619
620         ahub->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
621                                              ahub->soc_data->regmap_config);
622         if (IS_ERR(ahub->regmap)) {
623                 dev_err(&pdev->dev, "regmap init failed\n");
624                 return PTR_ERR(ahub->regmap);
625         }
626
627         regcache_cache_only(ahub->regmap, true);
628
629         err = devm_snd_soc_register_component(&pdev->dev,
630                                               ahub->soc_data->cmpnt_drv,
631                                               ahub->soc_data->dai_drv,
632                                               ahub->soc_data->num_dais);
633         if (err) {
634                 dev_err(&pdev->dev, "can't register AHUB component, err: %d\n",
635                         err);
636                 return err;
637         }
638
639         err = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
640         if (err)
641                 return err;
642
643         pm_runtime_enable(&pdev->dev);
644
645         return 0;
646 }
647
648 static int tegra_ahub_remove(struct platform_device *pdev)
649 {
650         pm_runtime_disable(&pdev->dev);
651
652         return 0;
653 }
654
655 static const struct dev_pm_ops tegra_ahub_pm_ops = {
656         SET_RUNTIME_PM_OPS(tegra_ahub_runtime_suspend,
657                            tegra_ahub_runtime_resume, NULL)
658         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
659                                 pm_runtime_force_resume)
660 };
661
662 static struct platform_driver tegra_ahub_driver = {
663         .probe = tegra_ahub_probe,
664         .remove = tegra_ahub_remove,
665         .driver = {
666                 .name = "tegra210-ahub",
667                 .of_match_table = tegra_ahub_of_match,
668                 .pm = &tegra_ahub_pm_ops,
669         },
670 };
671 module_platform_driver(tegra_ahub_driver);
672
673 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
674 MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>");
675 MODULE_DESCRIPTION("Tegra210 ASoC AHUB driver");
676 MODULE_LICENSE("GPL v2");