drm/mediatek: add connection from RDMA0 to DSI1
[linux-2.6-microblaze.git] / drivers / gpu / drm / mediatek / mtk_drm_ddp.c
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 DSI1_SEL_IN_RDMA1               0x1
128 #define DSI1_SEL_IN_RDMA2               0x4
129 #define DSI2_SEL_IN_RDMA1               (0x1 << 16)
130 #define DSI2_SEL_IN_RDMA2               (0x4 << 16)
131 #define DSI3_SEL_IN_RDMA1               (0x1 << 16)
132 #define DSI3_SEL_IN_RDMA2               (0x4 << 16)
133 #define COLOR1_SEL_IN_OVL1              0x1
134
135 #define OVL_MOUT_EN_RDMA                0x1
136 #define BLS_TO_DSI_RDMA1_TO_DPI1        0x8
137 #define DSI_SEL_IN_BLS                  0x0
138
139 struct mtk_disp_mutex {
140         int id;
141         bool claimed;
142 };
143
144 struct mtk_ddp {
145         struct device                   *dev;
146         struct clk                      *clk;
147         void __iomem                    *regs;
148         struct mtk_disp_mutex           mutex[10];
149         const unsigned int              *mutex_mod;
150 };
151
152 static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
153         [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
154         [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
155         [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
156         [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0,
157         [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1,
158         [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
159 };
160
161 static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
162         [DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0,
163         [DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
164         [DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
165         [DDP_COMPONENT_COLOR1] = MT2712_MUTEX_MOD_DISP_COLOR1,
166         [DDP_COMPONENT_OD0] = MT2712_MUTEX_MOD_DISP_OD0,
167         [DDP_COMPONENT_OD1] = MT2712_MUTEX_MOD2_DISP_OD1,
168         [DDP_COMPONENT_OVL0] = MT2712_MUTEX_MOD_DISP_OVL0,
169         [DDP_COMPONENT_OVL1] = MT2712_MUTEX_MOD_DISP_OVL1,
170         [DDP_COMPONENT_PWM0] = MT2712_MUTEX_MOD_DISP_PWM0,
171         [DDP_COMPONENT_PWM1] = MT2712_MUTEX_MOD_DISP_PWM1,
172         [DDP_COMPONENT_PWM2] = MT2712_MUTEX_MOD_DISP_PWM2,
173         [DDP_COMPONENT_RDMA0] = MT2712_MUTEX_MOD_DISP_RDMA0,
174         [DDP_COMPONENT_RDMA1] = MT2712_MUTEX_MOD_DISP_RDMA1,
175         [DDP_COMPONENT_RDMA2] = MT2712_MUTEX_MOD_DISP_RDMA2,
176         [DDP_COMPONENT_UFOE] = MT2712_MUTEX_MOD_DISP_UFOE,
177         [DDP_COMPONENT_WDMA0] = MT2712_MUTEX_MOD_DISP_WDMA0,
178         [DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
179 };
180
181 static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
182         [DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL,
183         [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
184         [DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
185         [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA,
186         [DDP_COMPONENT_OD0] = MT8173_MUTEX_MOD_DISP_OD,
187         [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0,
188         [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1,
189         [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0,
190         [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1,
191         [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0,
192         [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1,
193         [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2,
194         [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE,
195         [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0,
196         [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
197 };
198
199 static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
200                                     enum mtk_ddp_comp_id next,
201                                     unsigned int *addr)
202 {
203         unsigned int value;
204
205         if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
206                 *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
207                 value = OVL0_MOUT_EN_COLOR0;
208         } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
209                 *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
210                 value = OVL_MOUT_EN_RDMA;
211         } else if (cur == DDP_COMPONENT_OD0 && next == DDP_COMPONENT_RDMA0) {
212                 *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
213                 value = OD_MOUT_EN_RDMA0;
214         } else if (cur == DDP_COMPONENT_UFOE && next == DDP_COMPONENT_DSI0) {
215                 *addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN;
216                 value = UFOE_MOUT_EN_DSI0;
217         } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
218                 *addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN;
219                 value = OVL1_MOUT_EN_COLOR1;
220         } else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) {
221                 *addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN;
222                 value = GAMMA_MOUT_EN_RDMA1;
223         } else if (cur == DDP_COMPONENT_OD1 && next == DDP_COMPONENT_RDMA1) {
224                 *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
225                 value = OD1_MOUT_EN_RDMA1;
226         } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI0) {
227                 *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
228                 value = RDMA0_SOUT_DPI0;
229         } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI1) {
230                 *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
231                 value = RDMA0_SOUT_DPI1;
232         } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI1) {
233                 *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
234                 value = RDMA0_SOUT_DSI1;
235         } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI2) {
236                 *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
237                 value = RDMA0_SOUT_DSI2;
238         } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI3) {
239                 *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN;
240                 value = RDMA0_SOUT_DSI3;
241         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
242                 *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
243                 value = RDMA1_SOUT_DSI1;
244         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
245                 *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
246                 value = RDMA1_SOUT_DSI2;
247         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
248                 *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
249                 value = RDMA1_SOUT_DSI3;
250         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
251                 *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
252                 value = RDMA1_SOUT_DPI0;
253         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
254                 *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN;
255                 value = RDMA1_SOUT_DPI1;
256         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
257                 *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
258                 value = RDMA2_SOUT_DPI0;
259         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
260                 *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
261                 value = RDMA2_SOUT_DPI1;
262         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
263                 *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
264                 value = RDMA2_SOUT_DSI1;
265         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
266                 *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
267                 value = RDMA2_SOUT_DSI2;
268         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
269                 *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT;
270                 value = RDMA2_SOUT_DSI3;
271         } else {
272                 value = 0;
273         }
274
275         return value;
276 }
277
278 static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
279                                    enum mtk_ddp_comp_id next,
280                                    unsigned int *addr)
281 {
282         unsigned int value;
283
284         if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
285                 *addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN;
286                 value = COLOR0_SEL_IN_OVL0;
287         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
288                 *addr = DISP_REG_CONFIG_DPI_SEL_IN;
289                 value = DPI0_SEL_IN_RDMA1;
290         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) {
291                 *addr = DISP_REG_CONFIG_DPI_SEL_IN;
292                 value = DPI1_SEL_IN_RDMA1;
293         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) {
294                 *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
295                 value = DSI1_SEL_IN_RDMA1;
296         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) {
297                 *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
298                 value = DSI2_SEL_IN_RDMA1;
299         } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) {
300                 *addr = DISP_REG_CONFIG_DSIO_SEL_IN;
301                 value = DSI3_SEL_IN_RDMA1;
302         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) {
303                 *addr = DISP_REG_CONFIG_DPI_SEL_IN;
304                 value = DPI0_SEL_IN_RDMA2;
305         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) {
306                 *addr = DISP_REG_CONFIG_DPI_SEL_IN;
307                 value = DPI1_SEL_IN_RDMA2;
308         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) {
309                 *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
310                 value = DSI1_SEL_IN_RDMA2;
311         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) {
312                 *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
313                 value = DSI2_SEL_IN_RDMA2;
314         } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) {
315                 *addr = DISP_REG_CONFIG_DSIE_SEL_IN;
316                 value = DSI3_SEL_IN_RDMA2;
317         } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
318                 *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
319                 value = COLOR1_SEL_IN_OVL1;
320         } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
321                 *addr = DISP_REG_CONFIG_DSI_SEL;
322                 value = DSI_SEL_IN_BLS;
323         } else {
324                 value = 0;
325         }
326
327         return value;
328 }
329
330 static void mtk_ddp_sout_sel(void __iomem *config_regs,
331                              enum mtk_ddp_comp_id cur,
332                              enum mtk_ddp_comp_id next)
333 {
334         if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0)
335                 writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
336                                config_regs + DISP_REG_CONFIG_OUT_SEL);
337 }
338
339 void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
340                               enum mtk_ddp_comp_id cur,
341                               enum mtk_ddp_comp_id next)
342 {
343         unsigned int addr, value, reg;
344
345         value = mtk_ddp_mout_en(cur, next, &addr);
346         if (value) {
347                 reg = readl_relaxed(config_regs + addr) | value;
348                 writel_relaxed(reg, config_regs + addr);
349         }
350
351         mtk_ddp_sout_sel(config_regs, cur, next);
352
353         value = mtk_ddp_sel_in(cur, next, &addr);
354         if (value) {
355                 reg = readl_relaxed(config_regs + addr) | value;
356                 writel_relaxed(reg, config_regs + addr);
357         }
358 }
359
360 void mtk_ddp_remove_comp_from_path(void __iomem *config_regs,
361                                    enum mtk_ddp_comp_id cur,
362                                    enum mtk_ddp_comp_id next)
363 {
364         unsigned int addr, value, reg;
365
366         value = mtk_ddp_mout_en(cur, next, &addr);
367         if (value) {
368                 reg = readl_relaxed(config_regs + addr) & ~value;
369                 writel_relaxed(reg, config_regs + addr);
370         }
371
372         value = mtk_ddp_sel_in(cur, next, &addr);
373         if (value) {
374                 reg = readl_relaxed(config_regs + addr) & ~value;
375                 writel_relaxed(reg, config_regs + addr);
376         }
377 }
378
379 struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id)
380 {
381         struct mtk_ddp *ddp = dev_get_drvdata(dev);
382
383         if (id >= 10)
384                 return ERR_PTR(-EINVAL);
385         if (ddp->mutex[id].claimed)
386                 return ERR_PTR(-EBUSY);
387
388         ddp->mutex[id].claimed = true;
389
390         return &ddp->mutex[id];
391 }
392
393 void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex)
394 {
395         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
396                                            mutex[mutex->id]);
397
398         WARN_ON(&ddp->mutex[mutex->id] != mutex);
399
400         mutex->claimed = false;
401 }
402
403 int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex)
404 {
405         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
406                                            mutex[mutex->id]);
407         return clk_prepare_enable(ddp->clk);
408 }
409
410 void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex)
411 {
412         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
413                                            mutex[mutex->id]);
414         clk_disable_unprepare(ddp->clk);
415 }
416
417 void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
418                              enum mtk_ddp_comp_id id)
419 {
420         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
421                                            mutex[mutex->id]);
422         unsigned int reg;
423         unsigned int offset;
424
425         WARN_ON(&ddp->mutex[mutex->id] != mutex);
426
427         switch (id) {
428         case DDP_COMPONENT_DSI0:
429                 reg = MUTEX_SOF_DSI0;
430                 break;
431         case DDP_COMPONENT_DSI1:
432                 reg = MUTEX_SOF_DSI0;
433                 break;
434         case DDP_COMPONENT_DSI2:
435                 reg = MUTEX_SOF_DSI2;
436                 break;
437         case DDP_COMPONENT_DSI3:
438                 reg = MUTEX_SOF_DSI3;
439                 break;
440         case DDP_COMPONENT_DPI0:
441                 reg = MUTEX_SOF_DPI0;
442                 break;
443         case DDP_COMPONENT_DPI1:
444                 reg = MUTEX_SOF_DPI1;
445                 break;
446         default:
447                 if (ddp->mutex_mod[id] < 32) {
448                         offset = DISP_REG_MUTEX_MOD(mutex->id);
449                         reg = readl_relaxed(ddp->regs + offset);
450                         reg |= 1 << ddp->mutex_mod[id];
451                         writel_relaxed(reg, ddp->regs + offset);
452                 } else {
453                         offset = DISP_REG_MUTEX_MOD2(mutex->id);
454                         reg = readl_relaxed(ddp->regs + offset);
455                         reg |= 1 << (ddp->mutex_mod[id] - 32);
456                         writel_relaxed(reg, ddp->regs + offset);
457                 }
458                 return;
459         }
460
461         writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
462 }
463
464 void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
465                                 enum mtk_ddp_comp_id id)
466 {
467         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
468                                            mutex[mutex->id]);
469         unsigned int reg;
470         unsigned int offset;
471
472         WARN_ON(&ddp->mutex[mutex->id] != mutex);
473
474         switch (id) {
475         case DDP_COMPONENT_DSI0:
476         case DDP_COMPONENT_DSI1:
477         case DDP_COMPONENT_DSI2:
478         case DDP_COMPONENT_DSI3:
479         case DDP_COMPONENT_DPI0:
480         case DDP_COMPONENT_DPI1:
481                 writel_relaxed(MUTEX_SOF_SINGLE_MODE,
482                                ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
483                 break;
484         default:
485                 if (ddp->mutex_mod[id] < 32) {
486                         offset = DISP_REG_MUTEX_MOD(mutex->id);
487                         reg = readl_relaxed(ddp->regs + offset);
488                         reg &= ~(1 << ddp->mutex_mod[id]);
489                         writel_relaxed(reg, ddp->regs + offset);
490                 } else {
491                         offset = DISP_REG_MUTEX_MOD2(mutex->id);
492                         reg = readl_relaxed(ddp->regs + offset);
493                         reg &= ~(1 << (ddp->mutex_mod[id] - 32));
494                         writel_relaxed(reg, ddp->regs + offset);
495                 }
496                 break;
497         }
498 }
499
500 void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex)
501 {
502         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
503                                            mutex[mutex->id]);
504
505         WARN_ON(&ddp->mutex[mutex->id] != mutex);
506
507         writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
508 }
509
510 void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
511 {
512         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
513                                            mutex[mutex->id]);
514
515         WARN_ON(&ddp->mutex[mutex->id] != mutex);
516
517         writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
518 }
519
520 void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex)
521 {
522         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
523                                            mutex[mutex->id]);
524         u32 tmp;
525
526         writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
527         writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id));
528         if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id),
529                                       tmp, tmp & INT_MUTEX, 1, 10000))
530                 pr_err("could not acquire mutex %d\n", mutex->id);
531 }
532
533 void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex)
534 {
535         struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
536                                            mutex[mutex->id]);
537
538         writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id));
539 }
540
541 static int mtk_ddp_probe(struct platform_device *pdev)
542 {
543         struct device *dev = &pdev->dev;
544         struct mtk_ddp *ddp;
545         struct resource *regs;
546         int i;
547
548         ddp = devm_kzalloc(dev, sizeof(*ddp), GFP_KERNEL);
549         if (!ddp)
550                 return -ENOMEM;
551
552         for (i = 0; i < 10; i++)
553                 ddp->mutex[i].id = i;
554
555         ddp->clk = devm_clk_get(dev, NULL);
556         if (IS_ERR(ddp->clk)) {
557                 dev_err(dev, "Failed to get clock\n");
558                 return PTR_ERR(ddp->clk);
559         }
560
561         regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
562         ddp->regs = devm_ioremap_resource(dev, regs);
563         if (IS_ERR(ddp->regs)) {
564                 dev_err(dev, "Failed to map mutex registers\n");
565                 return PTR_ERR(ddp->regs);
566         }
567
568         ddp->mutex_mod = of_device_get_match_data(dev);
569
570         platform_set_drvdata(pdev, ddp);
571
572         return 0;
573 }
574
575 static int mtk_ddp_remove(struct platform_device *pdev)
576 {
577         return 0;
578 }
579
580 static const struct of_device_id ddp_driver_dt_match[] = {
581         { .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod},
582         { .compatible = "mediatek,mt2712-disp-mutex", .data = mt2712_mutex_mod},
583         { .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
584         {},
585 };
586 MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
587
588 struct platform_driver mtk_ddp_driver = {
589         .probe          = mtk_ddp_probe,
590         .remove         = mtk_ddp_remove,
591         .driver         = {
592                 .name   = "mediatek-ddp",
593                 .owner  = THIS_MODULE,
594                 .of_match_table = ddp_driver_dt_match,
595         },
596 };