1 /*
2  * Copyright (c) 2015 MediaTek Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 
14 #include <linux/clk.h>
15 #include <linux/iopoll.h>
16 #include <linux/module.h>
17 #include <linux/of_device.h>
18 #include <linux/platform_device.h>
19 #include <linux/regmap.h>
20 
21 #include "mtk_drm_ddp.h"
22 #include "mtk_drm_ddp_comp.h"
23 
24 #define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN	0x040
25 #define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN	0x044
26 #define DISP_REG_CONFIG_DISP_OD_MOUT_EN		0x048
27 #define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN	0x04c
28 #define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN	0x050
29 #define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN	0x084
30 #define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN	0x088
31 #define DISP_REG_CONFIG_DSIE_SEL_IN		0x0a4
32 #define DISP_REG_CONFIG_DSIO_SEL_IN		0x0a8
33 #define DISP_REG_CONFIG_DPI_SEL_IN		0x0ac
34 #define DISP_REG_CONFIG_DISP_RDMA2_SOUT		0x0b8
35 #define DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN	0x0c4
36 #define DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN	0x0c8
37 #define DISP_REG_CONFIG_MMSYS_CG_CON0		0x100
38 
39 #define DISP_REG_CONFIG_DISP_OVL_MOUT_EN	0x030
40 #define DISP_REG_CONFIG_OUT_SEL			0x04c
41 #define DISP_REG_CONFIG_DSI_SEL			0x050
42 
43 #define DISP_REG_MUTEX_EN(n)	(0x20 + 0x20 * (n))
44 #define DISP_REG_MUTEX(n)	(0x24 + 0x20 * (n))
45 #define DISP_REG_MUTEX_RST(n)	(0x28 + 0x20 * (n))
46 #define DISP_REG_MUTEX_MOD(n)	(0x2c + 0x20 * (n))
47 #define DISP_REG_MUTEX_SOF(n)	(0x30 + 0x20 * (n))
48 #define DISP_REG_MUTEX_MOD2(n)	(0x34 + 0x20 * (n))
49 
50 #define INT_MUTEX				BIT(1)
51 
52 #define MT8173_MUTEX_MOD_DISP_OVL0		11
53 #define MT8173_MUTEX_MOD_DISP_OVL1		12
54 #define MT8173_MUTEX_MOD_DISP_RDMA0		13
55 #define MT8173_MUTEX_MOD_DISP_RDMA1		14
56 #define MT8173_MUTEX_MOD_DISP_RDMA2		15
57 #define MT8173_MUTEX_MOD_DISP_WDMA0		16
58 #define MT8173_MUTEX_MOD_DISP_WDMA1		17
59 #define MT8173_MUTEX_MOD_DISP_COLOR0		18
60 #define MT8173_MUTEX_MOD_DISP_COLOR1		19
61 #define MT8173_MUTEX_MOD_DISP_AAL		20
62 #define MT8173_MUTEX_MOD_DISP_GAMMA		21
63 #define MT8173_MUTEX_MOD_DISP_UFOE		22
64 #define MT8173_MUTEX_MOD_DISP_PWM0		23
65 #define MT8173_MUTEX_MOD_DISP_PWM1		24
66 #define MT8173_MUTEX_MOD_DISP_OD		25
67 
68 #define MT2712_MUTEX_MOD_DISP_PWM2		10
69 #define MT2712_MUTEX_MOD_DISP_OVL0		11
70 #define MT2712_MUTEX_MOD_DISP_OVL1		12
71 #define MT2712_MUTEX_MOD_DISP_RDMA0		13
72 #define MT2712_MUTEX_MOD_DISP_RDMA1		14
73 #define MT2712_MUTEX_MOD_DISP_RDMA2		15
74 #define MT2712_MUTEX_MOD_DISP_WDMA0		16
75 #define MT2712_MUTEX_MOD_DISP_WDMA1		17
76 #define MT2712_MUTEX_MOD_DISP_COLOR0		18
77 #define MT2712_MUTEX_MOD_DISP_COLOR1		19
78 #define MT2712_MUTEX_MOD_DISP_AAL0		20
79 #define MT2712_MUTEX_MOD_DISP_UFOE		22
80 #define MT2712_MUTEX_MOD_DISP_PWM0		23
81 #define MT2712_MUTEX_MOD_DISP_PWM1		24
82 #define MT2712_MUTEX_MOD_DISP_OD0		25
83 #define MT2712_MUTEX_MOD2_DISP_AAL1		33
84 #define MT2712_MUTEX_MOD2_DISP_OD1		34
85 
86 #define MT2701_MUTEX_MOD_DISP_OVL		3
87 #define MT2701_MUTEX_MOD_DISP_WDMA		6
88 #define MT2701_MUTEX_MOD_DISP_COLOR		7
89 #define MT2701_MUTEX_MOD_DISP_BLS		9
90 #define MT2701_MUTEX_MOD_DISP_RDMA0		10
91 #define MT2701_MUTEX_MOD_DISP_RDMA1		12
92 
93 #define MUTEX_SOF_SINGLE_MODE		0
94 #define MUTEX_SOF_DSI0			1
95 #define MUTEX_SOF_DSI1			2
96 #define MUTEX_SOF_DPI0			3
97 #define MUTEX_SOF_DPI1			4
98 #define MUTEX_SOF_DSI2			5
99 #define MUTEX_SOF_DSI3			6
100 
101 #define OVL0_MOUT_EN_COLOR0		0x1
102 #define OD_MOUT_EN_RDMA0		0x1
103 #define OD1_MOUT_EN_RDMA1		BIT(16)
104 #define UFOE_MOUT_EN_DSI0		0x1
105 #define COLOR0_SEL_IN_OVL0		0x1
106 #define OVL1_MOUT_EN_COLOR1		0x1
107 #define GAMMA_MOUT_EN_RDMA1		0x1
108 #define RDMA0_SOUT_DPI0			0x2
109 #define RDMA0_SOUT_DPI1			0x3
110 #define RDMA0_SOUT_DSI1			0x1
111 #define RDMA0_SOUT_DSI2			0x4
112 #define RDMA0_SOUT_DSI3			0x5
113 #define RDMA1_SOUT_DPI0			0x2
114 #define RDMA1_SOUT_DPI1			0x3
115 #define RDMA1_SOUT_DSI1			0x1
116 #define RDMA1_SOUT_DSI2			0x4
117 #define RDMA1_SOUT_DSI3			0x5
118 #define RDMA2_SOUT_DPI0			0x2
119 #define RDMA2_SOUT_DPI1			0x3
120 #define RDMA2_SOUT_DSI1			0x1
121 #define RDMA2_SOUT_DSI2			0x4
122 #define RDMA2_SOUT_DSI3			0x5
123 #define DPI0_SEL_IN_RDMA1		0x1
124 #define DPI0_SEL_IN_RDMA2		0x3
125 #define DPI1_SEL_IN_RDMA1		(0x1 << 8)
126 #define DPI1_SEL_IN_RDMA2		(0x3 << 8)
127 #define DSI0_SEL_IN_RDMA1		0x1
128 #define DSI0_SEL_IN_RDMA2		0x4
129 #define DSI1_SEL_IN_RDMA1		0x1
130 #define DSI1_SEL_IN_RDMA2		0x4
131 #define DSI2_SEL_IN_RDMA1		(0x1 << 16)
132 #define DSI2_SEL_IN_RDMA2		(0x4 << 16)
133 #define DSI3_SEL_IN_RDMA1		(0x1 << 16)
134 #define DSI3_SEL_IN_RDMA2		(0x4 << 16)
135 #define COLOR1_SEL_IN_OVL1		0x1
136 
137 #define OVL_MOUT_EN_RDMA		0x1
138 #define BLS_TO_DSI_RDMA1_TO_DPI1	0x8
139 #define DSI_SEL_IN_BLS			0x0
140 
141 struct mtk_disp_mutex {
142 	int id;
143 	bool claimed;
144 };
145 
146 struct mtk_ddp {
147 	struct device			*dev;
148 	struct clk			*clk;
149 	void __iomem			*regs;
150 	struct mtk_disp_mutex		mutex[10];
151 	const unsigned int		*mutex_mod;
152 };
153 
154 static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
155 	[DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
156 	[DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
157 	[DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
158 	[DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0,
159 	[DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1,
160 	[DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
161 };
162 
163 static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
164 	[DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0,
165 	[DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
166 	[DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
167 	[DDP_COMPONENT_COLOR1] = MT2712_MUTEX_MOD_DISP_COLOR1,
168 	[DDP_COMPONENT_OD0] = MT2712_MUTEX_MOD_DISP_OD0,
169 	[DDP_COMPONENT_OD1] = MT2712_MUTEX_MOD2_DISP_OD1,
170 	[DDP_COMPONENT_OVL0] = MT2712_MUTEX_MOD_DISP_OVL0,
171 	[DDP_COMPONENT_OVL1] = MT2712_MUTEX_MOD_DISP_OVL1,
172 	[DDP_COMPONENT_PWM0] = MT2712_MUTEX_MOD_DISP_PWM0,
173 	[DDP_COMPONENT_PWM1] = MT2712_MUTEX_MOD_DISP_PWM1,
174 	[DDP_COMPONENT_PWM2] = MT2712_MUTEX_MOD_DISP_PWM2,
175 	[DDP_COMPONENT_RDMA0] = MT2712_MUTEX_MOD_DISP_RDMA0,
176 	[DDP_COMPONENT_RDMA1] = MT2712_MUTEX_MOD_DISP_RDMA1,
177 	[DDP_COMPONENT_RDMA2] = MT2712_MUTEX_MOD_DISP_RDMA2,
178 	[DDP_COMPONENT_UFOE] = MT2712_MUTEX_MOD_DISP_UFOE,
179 	[DDP_COMPONENT_WDMA0] = MT2712_MUTEX_MOD_DISP_WDMA0,
180 	[DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
181 };
182 
183 static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
184 	[DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL,
185 	[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
186 	[DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
187 	[DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA,
188 	[DDP_COMPONENT_OD0] = MT8173_MUTEX_MOD_DISP_OD,
189 	[DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0,
190 	[DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1,
191 	[DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0,
192 	[DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1,
193 	[DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0,
194 	[DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1,
195 	[DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2,
196 	[DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE,
197 	[DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0,
198 	[DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
199 };
200 
mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,enum mtk_ddp_comp_id next,unsigned int * addr)201 static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
202 				    enum mtk_ddp_comp_id next,
203 				    unsigned int *addr)
204 {
205 	unsigned int value;
206 
207 	if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
208 		*addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
209 		value = OVL0_MOUT_EN_COLOR0;
210 	} else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
211 		*addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
212 		value = OVL_MOUT_EN_RDMA;
213 	} else if (cur == DDP_COMPONENT_OD0 && next == DDP_COMPONENT_RDMA0) {
214 		*addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
215 		value = OD_MOUT_EN_RDMA0;
216 	} else if (cur == DDP_COMPONENT_UFOE && next == DDP_COMPONENT_DSI0) {
217 		*addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN;
218 		value = UFOE_MOUT_EN_DSI0;
219 	} else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
220 		*addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN;
221 		value = OVL1_MOUT_EN_COLOR1;
222 	} else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) {
223 		*addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN;
224 		value = GAMMA_MOUT_EN_RDMA1;
225 	} else if (cur == DDP_COMPONENT_OD1 && next == DDP_COMPONENT_RDMA1) {
226 		*addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
227 		value = OD1_MOUT_EN_RDMA1;
228 	} else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI0) {
229 		*addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
230 		value = RDMA0_SOUT_DPI0;
231 	} else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI1) {
232 		*addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
233 		value = RDMA0_SOUT_DPI1;
234 	} else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI1) {
235 		*addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
236 		value = RDMA0_SOUT_DSI1;
237 	} else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI2) {
238 		*addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
239 		value = RDMA0_SOUT_DSI2;
240 	} else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI3) {
241 		*addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
242 		value = RDMA0_SOUT_DSI3;
243 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
244 		*addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
245 		value = RDMA1_SOUT_DSI1;
246 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
247 		*addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
248 		value = RDMA1_SOUT_DSI2;
249 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
250 		*addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
251 		value = RDMA1_SOUT_DSI3;
252 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
253 		*addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
254 		value = RDMA1_SOUT_DPI0;
255 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
256 		*addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
257 		value = RDMA1_SOUT_DPI1;
258 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
259 		*addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
260 		value = RDMA2_SOUT_DPI0;
261 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
262 		*addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
263 		value = RDMA2_SOUT_DPI1;
264 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
265 		*addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
266 		value = RDMA2_SOUT_DSI1;
267 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
268 		*addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
269 		value = RDMA2_SOUT_DSI2;
270 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
271 		*addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
272 		value = RDMA2_SOUT_DSI3;
273 	} else {
274 		value = 0;
275 	}
276 
277 	return value;
278 }
279 
mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,enum mtk_ddp_comp_id next,unsigned int * addr)280 static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
281 				   enum mtk_ddp_comp_id next,
282 				   unsigned int *addr)
283 {
284 	unsigned int value;
285 
286 	if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
287 		*addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN;
288 		value = COLOR0_SEL_IN_OVL0;
289 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
290 		*addr = DISP_REG_CONFIG_DPI_SEL_IN;
291 		value = DPI0_SEL_IN_RDMA1;
292 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
293 		*addr = DISP_REG_CONFIG_DPI_SEL_IN;
294 		value = DPI1_SEL_IN_RDMA1;
295 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI0) {
296 		*addr = DISP_REG_CONFIG_DSIE_SEL_IN;
297 		value = DSI0_SEL_IN_RDMA1;
298 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
299 		*addr = DISP_REG_CONFIG_DSIO_SEL_IN;
300 		value = DSI1_SEL_IN_RDMA1;
301 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
302 		*addr = DISP_REG_CONFIG_DSIE_SEL_IN;
303 		value = DSI2_SEL_IN_RDMA1;
304 	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
305 		*addr = DISP_REG_CONFIG_DSIO_SEL_IN;
306 		value = DSI3_SEL_IN_RDMA1;
307 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
308 		*addr = DISP_REG_CONFIG_DPI_SEL_IN;
309 		value = DPI0_SEL_IN_RDMA2;
310 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
311 		*addr = DISP_REG_CONFIG_DPI_SEL_IN;
312 		value = DPI1_SEL_IN_RDMA2;
313 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI0) {
314 		*addr = DISP_REG_CONFIG_DSIE_SEL_IN;
315 		value = DSI0_SEL_IN_RDMA2;
316 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
317 		*addr = DISP_REG_CONFIG_DSIO_SEL_IN;
318 		value = DSI1_SEL_IN_RDMA2;
319 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
320 		*addr = DISP_REG_CONFIG_DSIE_SEL_IN;
321 		value = DSI2_SEL_IN_RDMA2;
322 	} else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
323 		*addr = DISP_REG_CONFIG_DSIE_SEL_IN;
324 		value = DSI3_SEL_IN_RDMA2;
325 	} else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
326 		*addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
327 		value = COLOR1_SEL_IN_OVL1;
328 	} else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
329 		*addr = DISP_REG_CONFIG_DSI_SEL;
330 		value = DSI_SEL_IN_BLS;
331 	} else {
332 		value = 0;
333 	}
334 
335 	return value;
336 }
337 
mtk_ddp_sout_sel(void __iomem * config_regs,enum mtk_ddp_comp_id cur,enum mtk_ddp_comp_id next)338 static void mtk_ddp_sout_sel(void __iomem *config_regs,
339 			     enum mtk_ddp_comp_id cur,
340 			     enum mtk_ddp_comp_id next)
341 {
342 	if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0)
343 		writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
344 			       config_regs + DISP_REG_CONFIG_OUT_SEL);
345 }
346 
mtk_ddp_add_comp_to_path(void __iomem * config_regs,enum mtk_ddp_comp_id cur,enum mtk_ddp_comp_id next)347 void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
348 			      enum mtk_ddp_comp_id cur,
349 			      enum mtk_ddp_comp_id next)
350 {
351 	unsigned int addr, value, reg;
352 
353 	value = mtk_ddp_mout_en(cur, next, &addr);
354 	if (value) {
355 		reg = readl_relaxed(config_regs + addr) | value;
356 		writel_relaxed(reg, config_regs + addr);
357 	}
358 
359 	mtk_ddp_sout_sel(config_regs, cur, next);
360 
361 	value = mtk_ddp_sel_in(cur, next, &addr);
362 	if (value) {
363 		reg = readl_relaxed(config_regs + addr) | value;
364 		writel_relaxed(reg, config_regs + addr);
365 	}
366 }
367 
mtk_ddp_remove_comp_from_path(void __iomem * config_regs,enum mtk_ddp_comp_id cur,enum mtk_ddp_comp_id next)368 void mtk_ddp_remove_comp_from_path(void __iomem *config_regs,
369 				   enum mtk_ddp_comp_id cur,
370 				   enum mtk_ddp_comp_id next)
371 {
372 	unsigned int addr, value, reg;
373 
374 	value = mtk_ddp_mout_en(cur, next, &addr);
375 	if (value) {
376 		reg = readl_relaxed(config_regs + addr) & ~value;
377 		writel_relaxed(reg, config_regs + addr);
378 	}
379 
380 	value = mtk_ddp_sel_in(cur, next, &addr);
381 	if (value) {
382 		reg = readl_relaxed(config_regs + addr) & ~value;
383 		writel_relaxed(reg, config_regs + addr);
384 	}
385 }
386 
mtk_disp_mutex_get(struct device * dev,unsigned int id)387 struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id)
388 {
389 	struct mtk_ddp *ddp = dev_get_drvdata(dev);
390 
391 	if (id >= 10)
392 		return ERR_PTR(-EINVAL);
393 	if (ddp->mutex[id].claimed)
394 		return ERR_PTR(-EBUSY);
395 
396 	ddp->mutex[id].claimed = true;
397 
398 	return &ddp->mutex[id];
399 }
400 
mtk_disp_mutex_put(struct mtk_disp_mutex * mutex)401 void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex)
402 {
403 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
404 					   mutex[mutex->id]);
405 
406 	WARN_ON(&ddp->mutex[mutex->id] != mutex);
407 
408 	mutex->claimed = false;
409 }
410 
mtk_disp_mutex_prepare(struct mtk_disp_mutex * mutex)411 int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex)
412 {
413 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
414 					   mutex[mutex->id]);
415 	return clk_prepare_enable(ddp->clk);
416 }
417 
mtk_disp_mutex_unprepare(struct mtk_disp_mutex * mutex)418 void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex)
419 {
420 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
421 					   mutex[mutex->id]);
422 	clk_disable_unprepare(ddp->clk);
423 }
424 
mtk_disp_mutex_add_comp(struct mtk_disp_mutex * mutex,enum mtk_ddp_comp_id id)425 void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
426 			     enum mtk_ddp_comp_id id)
427 {
428 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
429 					   mutex[mutex->id]);
430 	unsigned int reg;
431 	unsigned int offset;
432 
433 	WARN_ON(&ddp->mutex[mutex->id] != mutex);
434 
435 	switch (id) {
436 	case DDP_COMPONENT_DSI0:
437 		reg = MUTEX_SOF_DSI0;
438 		break;
439 	case DDP_COMPONENT_DSI1:
440 		reg = MUTEX_SOF_DSI0;
441 		break;
442 	case DDP_COMPONENT_DSI2:
443 		reg = MUTEX_SOF_DSI2;
444 		break;
445 	case DDP_COMPONENT_DSI3:
446 		reg = MUTEX_SOF_DSI3;
447 		break;
448 	case DDP_COMPONENT_DPI0:
449 		reg = MUTEX_SOF_DPI0;
450 		break;
451 	case DDP_COMPONENT_DPI1:
452 		reg = MUTEX_SOF_DPI1;
453 		break;
454 	default:
455 		if (ddp->mutex_mod[id] < 32) {
456 			offset = DISP_REG_MUTEX_MOD(mutex->id);
457 			reg = readl_relaxed(ddp->regs + offset);
458 			reg |= 1 << ddp->mutex_mod[id];
459 			writel_relaxed(reg, ddp->regs + offset);
460 		} else {
461 			offset = DISP_REG_MUTEX_MOD2(mutex->id);
462 			reg = readl_relaxed(ddp->regs + offset);
463 			reg |= 1 << (ddp->mutex_mod[id] - 32);
464 			writel_relaxed(reg, ddp->regs + offset);
465 		}
466 		return;
467 	}
468 
469 	writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
470 }
471 
mtk_disp_mutex_remove_comp(struct mtk_disp_mutex * mutex,enum mtk_ddp_comp_id id)472 void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
473 				enum mtk_ddp_comp_id id)
474 {
475 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
476 					   mutex[mutex->id]);
477 	unsigned int reg;
478 	unsigned int offset;
479 
480 	WARN_ON(&ddp->mutex[mutex->id] != mutex);
481 
482 	switch (id) {
483 	case DDP_COMPONENT_DSI0:
484 	case DDP_COMPONENT_DSI1:
485 	case DDP_COMPONENT_DSI2:
486 	case DDP_COMPONENT_DSI3:
487 	case DDP_COMPONENT_DPI0:
488 	case DDP_COMPONENT_DPI1:
489 		writel_relaxed(MUTEX_SOF_SINGLE_MODE,
490 			       ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
491 		break;
492 	default:
493 		if (ddp->mutex_mod[id] < 32) {
494 			offset = DISP_REG_MUTEX_MOD(mutex->id);
495 			reg = readl_relaxed(ddp->regs + offset);
496 			reg &= ~(1 << ddp->mutex_mod[id]);
497 			writel_relaxed(reg, ddp->regs + offset);
498 		} else {
499 			offset = DISP_REG_MUTEX_MOD2(mutex->id);
500 			reg = readl_relaxed(ddp->regs + offset);
501 			reg &= ~(1 << (ddp->mutex_mod[id] - 32));
502 			writel_relaxed(reg, ddp->regs + offset);
503 		}
504 		break;
505 	}
506 }
507 
mtk_disp_mutex_enable(struct mtk_disp_mutex * mutex)508 void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex)
509 {
510 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
511 					   mutex[mutex->id]);
512 
513 	WARN_ON(&ddp->mutex[mutex->id] != mutex);
514 
515 	writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
516 }
517 
mtk_disp_mutex_disable(struct mtk_disp_mutex * mutex)518 void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
519 {
520 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
521 					   mutex[mutex->id]);
522 
523 	WARN_ON(&ddp->mutex[mutex->id] != mutex);
524 
525 	writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
526 }
527 
mtk_disp_mutex_acquire(struct mtk_disp_mutex * mutex)528 void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex)
529 {
530 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
531 					   mutex[mutex->id]);
532 	u32 tmp;
533 
534 	writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
535 	writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id));
536 	if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id),
537 				      tmp, tmp & INT_MUTEX, 1, 10000))
538 		pr_err("could not acquire mutex %d\n", mutex->id);
539 }
540 
mtk_disp_mutex_release(struct mtk_disp_mutex * mutex)541 void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex)
542 {
543 	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
544 					   mutex[mutex->id]);
545 
546 	writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id));
547 }
548 
mtk_ddp_probe(struct platform_device * pdev)549 static int mtk_ddp_probe(struct platform_device *pdev)
550 {
551 	struct device *dev = &pdev->dev;
552 	struct mtk_ddp *ddp;
553 	struct resource *regs;
554 	int i;
555 
556 	ddp = devm_kzalloc(dev, sizeof(*ddp), GFP_KERNEL);
557 	if (!ddp)
558 		return -ENOMEM;
559 
560 	for (i = 0; i < 10; i++)
561 		ddp->mutex[i].id = i;
562 
563 	ddp->clk = devm_clk_get(dev, NULL);
564 	if (IS_ERR(ddp->clk)) {
565 		dev_err(dev, "Failed to get clock\n");
566 		return PTR_ERR(ddp->clk);
567 	}
568 
569 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
570 	ddp->regs = devm_ioremap_resource(dev, regs);
571 	if (IS_ERR(ddp->regs)) {
572 		dev_err(dev, "Failed to map mutex registers\n");
573 		return PTR_ERR(ddp->regs);
574 	}
575 
576 	ddp->mutex_mod = of_device_get_match_data(dev);
577 
578 	platform_set_drvdata(pdev, ddp);
579 
580 	return 0;
581 }
582 
mtk_ddp_remove(struct platform_device * pdev)583 static int mtk_ddp_remove(struct platform_device *pdev)
584 {
585 	return 0;
586 }
587 
588 static const struct of_device_id ddp_driver_dt_match[] = {
589 	{ .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod},
590 	{ .compatible = "mediatek,mt2712-disp-mutex", .data = mt2712_mutex_mod},
591 	{ .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
592 	{},
593 };
594 MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
595 
596 struct platform_driver mtk_ddp_driver = {
597 	.probe		= mtk_ddp_probe,
598 	.remove		= mtk_ddp_remove,
599 	.driver		= {
600 		.name	= "mediatek-ddp",
601 		.owner	= THIS_MODULE,
602 		.of_match_table = ddp_driver_dt_match,
603 	},
604 };
605