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