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