1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015 MediaTek Inc.
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>
13 #include "mtk_drm_ddp.h"
14 #include "mtk_drm_ddp_comp.h"
16 #define MT2701_DISP_MUTEX0_MOD0 0x2c
17 #define MT2701_DISP_MUTEX0_SOF0 0x30
19 #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
20 #define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
21 #define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
22 #define DISP_REG_MUTEX_MOD(mutex_mod_reg, n) (mutex_mod_reg + 0x20 * (n))
23 #define DISP_REG_MUTEX_SOF(mutex_sof_reg, n) (mutex_sof_reg + 0x20 * (n))
24 #define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
26 #define INT_MUTEX BIT(1)
28 #define MT8167_MUTEX_MOD_DISP_PWM 1
29 #define MT8167_MUTEX_MOD_DISP_OVL0 6
30 #define MT8167_MUTEX_MOD_DISP_OVL1 7
31 #define MT8167_MUTEX_MOD_DISP_RDMA0 8
32 #define MT8167_MUTEX_MOD_DISP_RDMA1 9
33 #define MT8167_MUTEX_MOD_DISP_WDMA0 10
34 #define MT8167_MUTEX_MOD_DISP_CCORR 11
35 #define MT8167_MUTEX_MOD_DISP_COLOR 12
36 #define MT8167_MUTEX_MOD_DISP_AAL 13
37 #define MT8167_MUTEX_MOD_DISP_GAMMA 14
38 #define MT8167_MUTEX_MOD_DISP_DITHER 15
39 #define MT8167_MUTEX_MOD_DISP_UFOE 16
41 #define MT8173_MUTEX_MOD_DISP_OVL0 11
42 #define MT8173_MUTEX_MOD_DISP_OVL1 12
43 #define MT8173_MUTEX_MOD_DISP_RDMA0 13
44 #define MT8173_MUTEX_MOD_DISP_RDMA1 14
45 #define MT8173_MUTEX_MOD_DISP_RDMA2 15
46 #define MT8173_MUTEX_MOD_DISP_WDMA0 16
47 #define MT8173_MUTEX_MOD_DISP_WDMA1 17
48 #define MT8173_MUTEX_MOD_DISP_COLOR0 18
49 #define MT8173_MUTEX_MOD_DISP_COLOR1 19
50 #define MT8173_MUTEX_MOD_DISP_AAL 20
51 #define MT8173_MUTEX_MOD_DISP_GAMMA 21
52 #define MT8173_MUTEX_MOD_DISP_UFOE 22
53 #define MT8173_MUTEX_MOD_DISP_PWM0 23
54 #define MT8173_MUTEX_MOD_DISP_PWM1 24
55 #define MT8173_MUTEX_MOD_DISP_OD 25
57 #define MT2712_MUTEX_MOD_DISP_PWM2 10
58 #define MT2712_MUTEX_MOD_DISP_OVL0 11
59 #define MT2712_MUTEX_MOD_DISP_OVL1 12
60 #define MT2712_MUTEX_MOD_DISP_RDMA0 13
61 #define MT2712_MUTEX_MOD_DISP_RDMA1 14
62 #define MT2712_MUTEX_MOD_DISP_RDMA2 15
63 #define MT2712_MUTEX_MOD_DISP_WDMA0 16
64 #define MT2712_MUTEX_MOD_DISP_WDMA1 17
65 #define MT2712_MUTEX_MOD_DISP_COLOR0 18
66 #define MT2712_MUTEX_MOD_DISP_COLOR1 19
67 #define MT2712_MUTEX_MOD_DISP_AAL0 20
68 #define MT2712_MUTEX_MOD_DISP_UFOE 22
69 #define MT2712_MUTEX_MOD_DISP_PWM0 23
70 #define MT2712_MUTEX_MOD_DISP_PWM1 24
71 #define MT2712_MUTEX_MOD_DISP_OD0 25
72 #define MT2712_MUTEX_MOD2_DISP_AAL1 33
73 #define MT2712_MUTEX_MOD2_DISP_OD1 34
75 #define MT2701_MUTEX_MOD_DISP_OVL 3
76 #define MT2701_MUTEX_MOD_DISP_WDMA 6
77 #define MT2701_MUTEX_MOD_DISP_COLOR 7
78 #define MT2701_MUTEX_MOD_DISP_BLS 9
79 #define MT2701_MUTEX_MOD_DISP_RDMA0 10
80 #define MT2701_MUTEX_MOD_DISP_RDMA1 12
82 #define MUTEX_SOF_SINGLE_MODE 0
83 #define MUTEX_SOF_DSI0 1
84 #define MUTEX_SOF_DSI1 2
85 #define MUTEX_SOF_DPI0 3
86 #define MUTEX_SOF_DPI1 4
87 #define MUTEX_SOF_DSI2 5
88 #define MUTEX_SOF_DSI3 6
89 #define MT8167_MUTEX_SOF_DPI0 2
90 #define MT8167_MUTEX_SOF_DPI1 3
93 struct mtk_disp_mutex
{
98 enum mtk_ddp_mutex_sof_id
{
99 DDP_MUTEX_SOF_SINGLE_MODE
,
108 struct mtk_ddp_data
{
109 const unsigned int *mutex_mod
;
110 const unsigned int *mutex_sof
;
111 const unsigned int mutex_mod_reg
;
112 const unsigned int mutex_sof_reg
;
120 struct mtk_disp_mutex mutex
[10];
121 const struct mtk_ddp_data
*data
;
124 static const unsigned int mt2701_mutex_mod
[DDP_COMPONENT_ID_MAX
] = {
125 [DDP_COMPONENT_BLS
] = MT2701_MUTEX_MOD_DISP_BLS
,
126 [DDP_COMPONENT_COLOR0
] = MT2701_MUTEX_MOD_DISP_COLOR
,
127 [DDP_COMPONENT_OVL0
] = MT2701_MUTEX_MOD_DISP_OVL
,
128 [DDP_COMPONENT_RDMA0
] = MT2701_MUTEX_MOD_DISP_RDMA0
,
129 [DDP_COMPONENT_RDMA1
] = MT2701_MUTEX_MOD_DISP_RDMA1
,
130 [DDP_COMPONENT_WDMA0
] = MT2701_MUTEX_MOD_DISP_WDMA
,
133 static const unsigned int mt2712_mutex_mod
[DDP_COMPONENT_ID_MAX
] = {
134 [DDP_COMPONENT_AAL0
] = MT2712_MUTEX_MOD_DISP_AAL0
,
135 [DDP_COMPONENT_AAL1
] = MT2712_MUTEX_MOD2_DISP_AAL1
,
136 [DDP_COMPONENT_COLOR0
] = MT2712_MUTEX_MOD_DISP_COLOR0
,
137 [DDP_COMPONENT_COLOR1
] = MT2712_MUTEX_MOD_DISP_COLOR1
,
138 [DDP_COMPONENT_OD0
] = MT2712_MUTEX_MOD_DISP_OD0
,
139 [DDP_COMPONENT_OD1
] = MT2712_MUTEX_MOD2_DISP_OD1
,
140 [DDP_COMPONENT_OVL0
] = MT2712_MUTEX_MOD_DISP_OVL0
,
141 [DDP_COMPONENT_OVL1
] = MT2712_MUTEX_MOD_DISP_OVL1
,
142 [DDP_COMPONENT_PWM0
] = MT2712_MUTEX_MOD_DISP_PWM0
,
143 [DDP_COMPONENT_PWM1
] = MT2712_MUTEX_MOD_DISP_PWM1
,
144 [DDP_COMPONENT_PWM2
] = MT2712_MUTEX_MOD_DISP_PWM2
,
145 [DDP_COMPONENT_RDMA0
] = MT2712_MUTEX_MOD_DISP_RDMA0
,
146 [DDP_COMPONENT_RDMA1
] = MT2712_MUTEX_MOD_DISP_RDMA1
,
147 [DDP_COMPONENT_RDMA2
] = MT2712_MUTEX_MOD_DISP_RDMA2
,
148 [DDP_COMPONENT_UFOE
] = MT2712_MUTEX_MOD_DISP_UFOE
,
149 [DDP_COMPONENT_WDMA0
] = MT2712_MUTEX_MOD_DISP_WDMA0
,
150 [DDP_COMPONENT_WDMA1
] = MT2712_MUTEX_MOD_DISP_WDMA1
,
153 static const unsigned int mt8167_mutex_mod
[DDP_COMPONENT_ID_MAX
] = {
154 [DDP_COMPONENT_AAL0
] = MT8167_MUTEX_MOD_DISP_AAL
,
155 [DDP_COMPONENT_CCORR
] = MT8167_MUTEX_MOD_DISP_CCORR
,
156 [DDP_COMPONENT_COLOR0
] = MT8167_MUTEX_MOD_DISP_COLOR
,
157 [DDP_COMPONENT_DITHER
] = MT8167_MUTEX_MOD_DISP_DITHER
,
158 [DDP_COMPONENT_GAMMA
] = MT8167_MUTEX_MOD_DISP_GAMMA
,
159 [DDP_COMPONENT_OVL0
] = MT8167_MUTEX_MOD_DISP_OVL0
,
160 [DDP_COMPONENT_OVL1
] = MT8167_MUTEX_MOD_DISP_OVL1
,
161 [DDP_COMPONENT_PWM0
] = MT8167_MUTEX_MOD_DISP_PWM
,
162 [DDP_COMPONENT_RDMA0
] = MT8167_MUTEX_MOD_DISP_RDMA0
,
163 [DDP_COMPONENT_RDMA1
] = MT8167_MUTEX_MOD_DISP_RDMA1
,
164 [DDP_COMPONENT_UFOE
] = MT8167_MUTEX_MOD_DISP_UFOE
,
165 [DDP_COMPONENT_WDMA0
] = MT8167_MUTEX_MOD_DISP_WDMA0
,
168 static const unsigned int mt8173_mutex_mod
[DDP_COMPONENT_ID_MAX
] = {
169 [DDP_COMPONENT_AAL0
] = MT8173_MUTEX_MOD_DISP_AAL
,
170 [DDP_COMPONENT_COLOR0
] = MT8173_MUTEX_MOD_DISP_COLOR0
,
171 [DDP_COMPONENT_COLOR1
] = MT8173_MUTEX_MOD_DISP_COLOR1
,
172 [DDP_COMPONENT_GAMMA
] = MT8173_MUTEX_MOD_DISP_GAMMA
,
173 [DDP_COMPONENT_OD0
] = MT8173_MUTEX_MOD_DISP_OD
,
174 [DDP_COMPONENT_OVL0
] = MT8173_MUTEX_MOD_DISP_OVL0
,
175 [DDP_COMPONENT_OVL1
] = MT8173_MUTEX_MOD_DISP_OVL1
,
176 [DDP_COMPONENT_PWM0
] = MT8173_MUTEX_MOD_DISP_PWM0
,
177 [DDP_COMPONENT_PWM1
] = MT8173_MUTEX_MOD_DISP_PWM1
,
178 [DDP_COMPONENT_RDMA0
] = MT8173_MUTEX_MOD_DISP_RDMA0
,
179 [DDP_COMPONENT_RDMA1
] = MT8173_MUTEX_MOD_DISP_RDMA1
,
180 [DDP_COMPONENT_RDMA2
] = MT8173_MUTEX_MOD_DISP_RDMA2
,
181 [DDP_COMPONENT_UFOE
] = MT8173_MUTEX_MOD_DISP_UFOE
,
182 [DDP_COMPONENT_WDMA0
] = MT8173_MUTEX_MOD_DISP_WDMA0
,
183 [DDP_COMPONENT_WDMA1
] = MT8173_MUTEX_MOD_DISP_WDMA1
,
186 static const unsigned int mt2712_mutex_sof
[DDP_MUTEX_SOF_DSI3
+ 1] = {
187 [DDP_MUTEX_SOF_SINGLE_MODE
] = MUTEX_SOF_SINGLE_MODE
,
188 [DDP_MUTEX_SOF_DSI0
] = MUTEX_SOF_DSI0
,
189 [DDP_MUTEX_SOF_DSI1
] = MUTEX_SOF_DSI1
,
190 [DDP_MUTEX_SOF_DPI0
] = MUTEX_SOF_DPI0
,
191 [DDP_MUTEX_SOF_DPI1
] = MUTEX_SOF_DPI1
,
192 [DDP_MUTEX_SOF_DSI2
] = MUTEX_SOF_DSI2
,
193 [DDP_MUTEX_SOF_DSI3
] = MUTEX_SOF_DSI3
,
196 static const unsigned int mt8167_mutex_sof
[DDP_MUTEX_SOF_DSI3
+ 1] = {
197 [DDP_MUTEX_SOF_SINGLE_MODE
] = MUTEX_SOF_SINGLE_MODE
,
198 [DDP_MUTEX_SOF_DSI0
] = MUTEX_SOF_DSI0
,
199 [DDP_MUTEX_SOF_DPI0
] = MT8167_MUTEX_SOF_DPI0
,
200 [DDP_MUTEX_SOF_DPI1
] = MT8167_MUTEX_SOF_DPI1
,
203 static const struct mtk_ddp_data mt2701_ddp_driver_data
= {
204 .mutex_mod
= mt2701_mutex_mod
,
205 .mutex_sof
= mt2712_mutex_sof
,
206 .mutex_mod_reg
= MT2701_DISP_MUTEX0_MOD0
,
207 .mutex_sof_reg
= MT2701_DISP_MUTEX0_SOF0
,
210 static const struct mtk_ddp_data mt2712_ddp_driver_data
= {
211 .mutex_mod
= mt2712_mutex_mod
,
212 .mutex_sof
= mt2712_mutex_sof
,
213 .mutex_mod_reg
= MT2701_DISP_MUTEX0_MOD0
,
214 .mutex_sof_reg
= MT2701_DISP_MUTEX0_SOF0
,
217 static const struct mtk_ddp_data mt8167_ddp_driver_data
= {
218 .mutex_mod
= mt8167_mutex_mod
,
219 .mutex_sof
= mt8167_mutex_sof
,
220 .mutex_mod_reg
= MT2701_DISP_MUTEX0_MOD0
,
221 .mutex_sof_reg
= MT2701_DISP_MUTEX0_SOF0
,
225 static const struct mtk_ddp_data mt8173_ddp_driver_data
= {
226 .mutex_mod
= mt8173_mutex_mod
,
227 .mutex_sof
= mt2712_mutex_sof
,
228 .mutex_mod_reg
= MT2701_DISP_MUTEX0_MOD0
,
229 .mutex_sof_reg
= MT2701_DISP_MUTEX0_SOF0
,
232 struct mtk_disp_mutex
*mtk_disp_mutex_get(struct device
*dev
, unsigned int id
)
234 struct mtk_ddp
*ddp
= dev_get_drvdata(dev
);
237 return ERR_PTR(-EINVAL
);
238 if (ddp
->mutex
[id
].claimed
)
239 return ERR_PTR(-EBUSY
);
241 ddp
->mutex
[id
].claimed
= true;
243 return &ddp
->mutex
[id
];
246 void mtk_disp_mutex_put(struct mtk_disp_mutex
*mutex
)
248 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
251 WARN_ON(&ddp
->mutex
[mutex
->id
] != mutex
);
253 mutex
->claimed
= false;
256 int mtk_disp_mutex_prepare(struct mtk_disp_mutex
*mutex
)
258 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
260 return clk_prepare_enable(ddp
->clk
);
263 void mtk_disp_mutex_unprepare(struct mtk_disp_mutex
*mutex
)
265 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
267 clk_disable_unprepare(ddp
->clk
);
270 void mtk_disp_mutex_add_comp(struct mtk_disp_mutex
*mutex
,
271 enum mtk_ddp_comp_id id
)
273 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
279 WARN_ON(&ddp
->mutex
[mutex
->id
] != mutex
);
282 case DDP_COMPONENT_DSI0
:
283 sof_id
= DDP_MUTEX_SOF_DSI0
;
285 case DDP_COMPONENT_DSI1
:
286 sof_id
= DDP_MUTEX_SOF_DSI0
;
288 case DDP_COMPONENT_DSI2
:
289 sof_id
= DDP_MUTEX_SOF_DSI2
;
291 case DDP_COMPONENT_DSI3
:
292 sof_id
= DDP_MUTEX_SOF_DSI3
;
294 case DDP_COMPONENT_DPI0
:
295 sof_id
= DDP_MUTEX_SOF_DPI0
;
297 case DDP_COMPONENT_DPI1
:
298 sof_id
= DDP_MUTEX_SOF_DPI1
;
301 if (ddp
->data
->mutex_mod
[id
] < 32) {
302 offset
= DISP_REG_MUTEX_MOD(ddp
->data
->mutex_mod_reg
,
304 reg
= readl_relaxed(ddp
->regs
+ offset
);
305 reg
|= 1 << ddp
->data
->mutex_mod
[id
];
306 writel_relaxed(reg
, ddp
->regs
+ offset
);
308 offset
= DISP_REG_MUTEX_MOD2(mutex
->id
);
309 reg
= readl_relaxed(ddp
->regs
+ offset
);
310 reg
|= 1 << (ddp
->data
->mutex_mod
[id
] - 32);
311 writel_relaxed(reg
, ddp
->regs
+ offset
);
316 writel_relaxed(ddp
->data
->mutex_sof
[sof_id
],
318 DISP_REG_MUTEX_SOF(ddp
->data
->mutex_sof_reg
, mutex
->id
));
321 void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex
*mutex
,
322 enum mtk_ddp_comp_id id
)
324 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
329 WARN_ON(&ddp
->mutex
[mutex
->id
] != mutex
);
332 case DDP_COMPONENT_DSI0
:
333 case DDP_COMPONENT_DSI1
:
334 case DDP_COMPONENT_DSI2
:
335 case DDP_COMPONENT_DSI3
:
336 case DDP_COMPONENT_DPI0
:
337 case DDP_COMPONENT_DPI1
:
338 writel_relaxed(MUTEX_SOF_SINGLE_MODE
,
340 DISP_REG_MUTEX_SOF(ddp
->data
->mutex_sof_reg
,
344 if (ddp
->data
->mutex_mod
[id
] < 32) {
345 offset
= DISP_REG_MUTEX_MOD(ddp
->data
->mutex_mod_reg
,
347 reg
= readl_relaxed(ddp
->regs
+ offset
);
348 reg
&= ~(1 << ddp
->data
->mutex_mod
[id
]);
349 writel_relaxed(reg
, ddp
->regs
+ offset
);
351 offset
= DISP_REG_MUTEX_MOD2(mutex
->id
);
352 reg
= readl_relaxed(ddp
->regs
+ offset
);
353 reg
&= ~(1 << (ddp
->data
->mutex_mod
[id
] - 32));
354 writel_relaxed(reg
, ddp
->regs
+ offset
);
360 void mtk_disp_mutex_enable(struct mtk_disp_mutex
*mutex
)
362 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
365 WARN_ON(&ddp
->mutex
[mutex
->id
] != mutex
);
367 writel(1, ddp
->regs
+ DISP_REG_MUTEX_EN(mutex
->id
));
370 void mtk_disp_mutex_disable(struct mtk_disp_mutex
*mutex
)
372 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
375 WARN_ON(&ddp
->mutex
[mutex
->id
] != mutex
);
377 writel(0, ddp
->regs
+ DISP_REG_MUTEX_EN(mutex
->id
));
380 void mtk_disp_mutex_acquire(struct mtk_disp_mutex
*mutex
)
382 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
386 writel(1, ddp
->regs
+ DISP_REG_MUTEX_EN(mutex
->id
));
387 writel(1, ddp
->regs
+ DISP_REG_MUTEX(mutex
->id
));
388 if (readl_poll_timeout_atomic(ddp
->regs
+ DISP_REG_MUTEX(mutex
->id
),
389 tmp
, tmp
& INT_MUTEX
, 1, 10000))
390 pr_err("could not acquire mutex %d\n", mutex
->id
);
393 void mtk_disp_mutex_release(struct mtk_disp_mutex
*mutex
)
395 struct mtk_ddp
*ddp
= container_of(mutex
, struct mtk_ddp
,
398 writel(0, ddp
->regs
+ DISP_REG_MUTEX(mutex
->id
));
401 static int mtk_ddp_probe(struct platform_device
*pdev
)
403 struct device
*dev
= &pdev
->dev
;
405 struct resource
*regs
;
408 ddp
= devm_kzalloc(dev
, sizeof(*ddp
), GFP_KERNEL
);
412 for (i
= 0; i
< 10; i
++)
413 ddp
->mutex
[i
].id
= i
;
415 ddp
->data
= of_device_get_match_data(dev
);
417 if (!ddp
->data
->no_clk
) {
418 ddp
->clk
= devm_clk_get(dev
, NULL
);
419 if (IS_ERR(ddp
->clk
)) {
420 if (PTR_ERR(ddp
->clk
) != -EPROBE_DEFER
)
421 dev_err(dev
, "Failed to get clock\n");
422 return PTR_ERR(ddp
->clk
);
426 regs
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
427 ddp
->regs
= devm_ioremap_resource(dev
, regs
);
428 if (IS_ERR(ddp
->regs
)) {
429 dev_err(dev
, "Failed to map mutex registers\n");
430 return PTR_ERR(ddp
->regs
);
433 platform_set_drvdata(pdev
, ddp
);
438 static int mtk_ddp_remove(struct platform_device
*pdev
)
443 static const struct of_device_id ddp_driver_dt_match
[] = {
444 { .compatible
= "mediatek,mt2701-disp-mutex",
445 .data
= &mt2701_ddp_driver_data
},
446 { .compatible
= "mediatek,mt2712-disp-mutex",
447 .data
= &mt2712_ddp_driver_data
},
448 { .compatible
= "mediatek,mt8167-disp-mutex",
449 .data
= &mt8167_ddp_driver_data
},
450 { .compatible
= "mediatek,mt8173-disp-mutex",
451 .data
= &mt8173_ddp_driver_data
},
454 MODULE_DEVICE_TABLE(of
, ddp_driver_dt_match
);
456 struct platform_driver mtk_ddp_driver
= {
457 .probe
= mtk_ddp_probe
,
458 .remove
= mtk_ddp_remove
,
460 .name
= "mediatek-ddp",
461 .owner
= THIS_MODULE
,
462 .of_match_table
= ddp_driver_dt_match
,