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