Merge tag 'drm-misc-next-fixes-2021-09-09' of git://anongit.freedesktop.org/drm/drm...
[linux-2.6-microblaze.git] / drivers / gpu / drm / mediatek / mtk_drm_ddp_comp.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015 MediaTek Inc.
4  * Authors:
5  *      YT Shen <yt.shen@mediatek.com>
6  *      CK Hu <ck.hu@mediatek.com>
7  */
8
9 #include <linux/clk.h>
10 #include <linux/of.h>
11 #include <linux/of_address.h>
12 #include <linux/of_platform.h>
13 #include <linux/platform_device.h>
14 #include <linux/soc/mediatek/mtk-cmdq.h>
15 #include <drm/drm_print.h>
16
17 #include "mtk_disp_drv.h"
18 #include "mtk_drm_drv.h"
19 #include "mtk_drm_plane.h"
20 #include "mtk_drm_ddp_comp.h"
21 #include "mtk_drm_crtc.h"
22
23 #define DISP_OD_EN                              0x0000
24 #define DISP_OD_INTEN                           0x0008
25 #define DISP_OD_INTSTA                          0x000c
26 #define DISP_OD_CFG                             0x0020
27 #define DISP_OD_SIZE                            0x0030
28 #define DISP_DITHER_5                           0x0114
29 #define DISP_DITHER_7                           0x011c
30 #define DISP_DITHER_15                          0x013c
31 #define DISP_DITHER_16                          0x0140
32
33 #define DISP_REG_UFO_START                      0x0000
34
35 #define DISP_DITHER_EN                          0x0000
36 #define DITHER_EN                               BIT(0)
37 #define DISP_DITHER_CFG                         0x0020
38 #define DITHER_RELAY_MODE                       BIT(0)
39 #define DITHER_ENGINE_EN                        BIT(1)
40 #define DISP_DITHER_SIZE                        0x0030
41
42 #define LUT_10BIT_MASK                          0x03ff
43
44 #define OD_RELAYMODE                            BIT(0)
45
46 #define UFO_BYPASS                              BIT(2)
47
48 #define DISP_DITHERING                          BIT(2)
49 #define DITHER_LSB_ERR_SHIFT_R(x)               (((x) & 0x7) << 28)
50 #define DITHER_OVFLW_BIT_R(x)                   (((x) & 0x7) << 24)
51 #define DITHER_ADD_LSHIFT_R(x)                  (((x) & 0x7) << 20)
52 #define DITHER_ADD_RSHIFT_R(x)                  (((x) & 0x7) << 16)
53 #define DITHER_NEW_BIT_MODE                     BIT(0)
54 #define DITHER_LSB_ERR_SHIFT_B(x)               (((x) & 0x7) << 28)
55 #define DITHER_OVFLW_BIT_B(x)                   (((x) & 0x7) << 24)
56 #define DITHER_ADD_LSHIFT_B(x)                  (((x) & 0x7) << 20)
57 #define DITHER_ADD_RSHIFT_B(x)                  (((x) & 0x7) << 16)
58 #define DITHER_LSB_ERR_SHIFT_G(x)               (((x) & 0x7) << 12)
59 #define DITHER_OVFLW_BIT_G(x)                   (((x) & 0x7) << 8)
60 #define DITHER_ADD_LSHIFT_G(x)                  (((x) & 0x7) << 4)
61 #define DITHER_ADD_RSHIFT_G(x)                  (((x) & 0x7) << 0)
62
63 struct mtk_ddp_comp_dev {
64         struct clk *clk;
65         void __iomem *regs;
66         struct cmdq_client_reg cmdq_reg;
67 };
68
69 void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
70                    struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
71                    unsigned int offset)
72 {
73 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
74         if (cmdq_pkt)
75                 cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
76                                cmdq_reg->offset + offset, value);
77         else
78 #endif
79                 writel(value, regs + offset);
80 }
81
82 void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
83                            struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
84                            unsigned int offset)
85 {
86 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
87         if (cmdq_pkt)
88                 cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
89                                cmdq_reg->offset + offset, value);
90         else
91 #endif
92                 writel_relaxed(value, regs + offset);
93 }
94
95 void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value,
96                         struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
97                         unsigned int offset, unsigned int mask)
98 {
99 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
100         if (cmdq_pkt) {
101                 cmdq_pkt_write_mask(cmdq_pkt, cmdq_reg->subsys,
102                                     cmdq_reg->offset + offset, value, mask);
103         } else {
104 #endif
105                 u32 tmp = readl(regs + offset);
106
107                 tmp = (tmp & ~mask) | (value & mask);
108                 writel(tmp, regs + offset);
109 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
110         }
111 #endif
112 }
113
114 static int mtk_ddp_clk_enable(struct device *dev)
115 {
116         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
117
118         return clk_prepare_enable(priv->clk);
119 }
120
121 static void mtk_ddp_clk_disable(struct device *dev)
122 {
123         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
124
125         clk_disable_unprepare(priv->clk);
126 }
127
128 void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
129                            unsigned int bpc, unsigned int cfg,
130                            unsigned int dither_en, struct cmdq_pkt *cmdq_pkt)
131 {
132         /* If bpc equal to 0, the dithering function didn't be enabled */
133         if (bpc == 0)
134                 return;
135
136         if (bpc >= MTK_MIN_BPC) {
137                 mtk_ddp_write(cmdq_pkt, 0, cmdq_reg, regs, DISP_DITHER_5);
138                 mtk_ddp_write(cmdq_pkt, 0, cmdq_reg, regs, DISP_DITHER_7);
139                 mtk_ddp_write(cmdq_pkt,
140                               DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) |
141                               DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) |
142                               DITHER_NEW_BIT_MODE,
143                               cmdq_reg, regs, DISP_DITHER_15);
144                 mtk_ddp_write(cmdq_pkt,
145                               DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) |
146                               DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) |
147                               DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) |
148                               DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc),
149                               cmdq_reg, regs, DISP_DITHER_16);
150                 mtk_ddp_write(cmdq_pkt, dither_en, cmdq_reg, regs, cfg);
151         }
152 }
153
154 static void mtk_dither_set(struct device *dev, unsigned int bpc,
155                     unsigned int cfg, struct cmdq_pkt *cmdq_pkt)
156 {
157         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
158
159         mtk_dither_set_common(priv->regs, &priv->cmdq_reg, bpc, cfg,
160                               DISP_DITHERING, cmdq_pkt);
161 }
162
163 static void mtk_od_config(struct device *dev, unsigned int w,
164                           unsigned int h, unsigned int vrefresh,
165                           unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
166 {
167         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
168
169         mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_OD_SIZE);
170         mtk_ddp_write(cmdq_pkt, OD_RELAYMODE, &priv->cmdq_reg, priv->regs, DISP_OD_CFG);
171         mtk_dither_set(dev, bpc, DISP_OD_CFG, cmdq_pkt);
172 }
173
174 static void mtk_od_start(struct device *dev)
175 {
176         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
177
178         writel(1, priv->regs + DISP_OD_EN);
179 }
180
181 static void mtk_ufoe_start(struct device *dev)
182 {
183         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
184
185         writel(UFO_BYPASS, priv->regs + DISP_REG_UFO_START);
186 }
187
188 static void mtk_dither_config(struct device *dev, unsigned int w,
189                               unsigned int h, unsigned int vrefresh,
190                               unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
191 {
192         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
193
194         mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs, DISP_DITHER_SIZE);
195         mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, &priv->cmdq_reg, priv->regs, DISP_DITHER_CFG);
196         mtk_dither_set_common(priv->regs, &priv->cmdq_reg, bpc, DISP_DITHER_CFG,
197                               DITHER_ENGINE_EN, cmdq_pkt);
198 }
199
200 static void mtk_dither_start(struct device *dev)
201 {
202         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
203
204         writel(DITHER_EN, priv->regs + DISP_DITHER_EN);
205 }
206
207 static void mtk_dither_stop(struct device *dev)
208 {
209         struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
210
211         writel_relaxed(0x0, priv->regs + DISP_DITHER_EN);
212 }
213
214 static const struct mtk_ddp_comp_funcs ddp_aal = {
215         .clk_enable = mtk_aal_clk_enable,
216         .clk_disable = mtk_aal_clk_disable,
217         .gamma_set = mtk_aal_gamma_set,
218         .config = mtk_aal_config,
219         .start = mtk_aal_start,
220         .stop = mtk_aal_stop,
221 };
222
223 static const struct mtk_ddp_comp_funcs ddp_ccorr = {
224         .clk_enable = mtk_ccorr_clk_enable,
225         .clk_disable = mtk_ccorr_clk_disable,
226         .config = mtk_ccorr_config,
227         .start = mtk_ccorr_start,
228         .stop = mtk_ccorr_stop,
229         .ctm_set = mtk_ccorr_ctm_set,
230 };
231
232 static const struct mtk_ddp_comp_funcs ddp_color = {
233         .clk_enable = mtk_color_clk_enable,
234         .clk_disable = mtk_color_clk_disable,
235         .config = mtk_color_config,
236         .start = mtk_color_start,
237 };
238
239 static const struct mtk_ddp_comp_funcs ddp_dither = {
240         .clk_enable = mtk_ddp_clk_enable,
241         .clk_disable = mtk_ddp_clk_disable,
242         .config = mtk_dither_config,
243         .start = mtk_dither_start,
244         .stop = mtk_dither_stop,
245 };
246
247 static const struct mtk_ddp_comp_funcs ddp_dpi = {
248         .start = mtk_dpi_start,
249         .stop = mtk_dpi_stop,
250 };
251
252 static const struct mtk_ddp_comp_funcs ddp_dsi = {
253         .start = mtk_dsi_ddp_start,
254         .stop = mtk_dsi_ddp_stop,
255 };
256
257 static const struct mtk_ddp_comp_funcs ddp_gamma = {
258         .clk_enable = mtk_gamma_clk_enable,
259         .clk_disable = mtk_gamma_clk_disable,
260         .gamma_set = mtk_gamma_set,
261         .config = mtk_gamma_config,
262         .start = mtk_gamma_start,
263         .stop = mtk_gamma_stop,
264 };
265
266 static const struct mtk_ddp_comp_funcs ddp_od = {
267         .clk_enable = mtk_ddp_clk_enable,
268         .clk_disable = mtk_ddp_clk_disable,
269         .config = mtk_od_config,
270         .start = mtk_od_start,
271 };
272
273 static const struct mtk_ddp_comp_funcs ddp_ovl = {
274         .clk_enable = mtk_ovl_clk_enable,
275         .clk_disable = mtk_ovl_clk_disable,
276         .config = mtk_ovl_config,
277         .start = mtk_ovl_start,
278         .stop = mtk_ovl_stop,
279         .enable_vblank = mtk_ovl_enable_vblank,
280         .disable_vblank = mtk_ovl_disable_vblank,
281         .supported_rotations = mtk_ovl_supported_rotations,
282         .layer_nr = mtk_ovl_layer_nr,
283         .layer_check = mtk_ovl_layer_check,
284         .layer_config = mtk_ovl_layer_config,
285         .bgclr_in_on = mtk_ovl_bgclr_in_on,
286         .bgclr_in_off = mtk_ovl_bgclr_in_off,
287 };
288
289 static const struct mtk_ddp_comp_funcs ddp_rdma = {
290         .clk_enable = mtk_rdma_clk_enable,
291         .clk_disable = mtk_rdma_clk_disable,
292         .config = mtk_rdma_config,
293         .start = mtk_rdma_start,
294         .stop = mtk_rdma_stop,
295         .enable_vblank = mtk_rdma_enable_vblank,
296         .disable_vblank = mtk_rdma_disable_vblank,
297         .layer_nr = mtk_rdma_layer_nr,
298         .layer_config = mtk_rdma_layer_config,
299 };
300
301 static const struct mtk_ddp_comp_funcs ddp_ufoe = {
302         .clk_enable = mtk_ddp_clk_enable,
303         .clk_disable = mtk_ddp_clk_disable,
304         .start = mtk_ufoe_start,
305 };
306
307 static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
308         [MTK_DISP_OVL] = "ovl",
309         [MTK_DISP_OVL_2L] = "ovl-2l",
310         [MTK_DISP_RDMA] = "rdma",
311         [MTK_DISP_WDMA] = "wdma",
312         [MTK_DISP_COLOR] = "color",
313         [MTK_DISP_CCORR] = "ccorr",
314         [MTK_DISP_AAL] = "aal",
315         [MTK_DISP_GAMMA] = "gamma",
316         [MTK_DISP_DITHER] = "dither",
317         [MTK_DISP_UFOE] = "ufoe",
318         [MTK_DSI] = "dsi",
319         [MTK_DPI] = "dpi",
320         [MTK_DISP_PWM] = "pwm",
321         [MTK_DISP_MUTEX] = "mutex",
322         [MTK_DISP_OD] = "od",
323         [MTK_DISP_BLS] = "bls",
324 };
325
326 struct mtk_ddp_comp_match {
327         enum mtk_ddp_comp_type type;
328         int alias_id;
329         const struct mtk_ddp_comp_funcs *funcs;
330 };
331
332 static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
333         [DDP_COMPONENT_AAL0]    = { MTK_DISP_AAL,       0, &ddp_aal },
334         [DDP_COMPONENT_AAL1]    = { MTK_DISP_AAL,       1, &ddp_aal },
335         [DDP_COMPONENT_BLS]     = { MTK_DISP_BLS,       0, NULL },
336         [DDP_COMPONENT_CCORR]   = { MTK_DISP_CCORR,     0, &ddp_ccorr },
337         [DDP_COMPONENT_COLOR0]  = { MTK_DISP_COLOR,     0, &ddp_color },
338         [DDP_COMPONENT_COLOR1]  = { MTK_DISP_COLOR,     1, &ddp_color },
339         [DDP_COMPONENT_DITHER]  = { MTK_DISP_DITHER,    0, &ddp_dither },
340         [DDP_COMPONENT_DPI0]    = { MTK_DPI,            0, &ddp_dpi },
341         [DDP_COMPONENT_DPI1]    = { MTK_DPI,            1, &ddp_dpi },
342         [DDP_COMPONENT_DSI0]    = { MTK_DSI,            0, &ddp_dsi },
343         [DDP_COMPONENT_DSI1]    = { MTK_DSI,            1, &ddp_dsi },
344         [DDP_COMPONENT_DSI2]    = { MTK_DSI,            2, &ddp_dsi },
345         [DDP_COMPONENT_DSI3]    = { MTK_DSI,            3, &ddp_dsi },
346         [DDP_COMPONENT_GAMMA]   = { MTK_DISP_GAMMA,     0, &ddp_gamma },
347         [DDP_COMPONENT_OD0]     = { MTK_DISP_OD,        0, &ddp_od },
348         [DDP_COMPONENT_OD1]     = { MTK_DISP_OD,        1, &ddp_od },
349         [DDP_COMPONENT_OVL0]    = { MTK_DISP_OVL,       0, &ddp_ovl },
350         [DDP_COMPONENT_OVL1]    = { MTK_DISP_OVL,       1, &ddp_ovl },
351         [DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L,    0, &ddp_ovl },
352         [DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L,    1, &ddp_ovl },
353         [DDP_COMPONENT_PWM0]    = { MTK_DISP_PWM,       0, NULL },
354         [DDP_COMPONENT_PWM1]    = { MTK_DISP_PWM,       1, NULL },
355         [DDP_COMPONENT_PWM2]    = { MTK_DISP_PWM,       2, NULL },
356         [DDP_COMPONENT_RDMA0]   = { MTK_DISP_RDMA,      0, &ddp_rdma },
357         [DDP_COMPONENT_RDMA1]   = { MTK_DISP_RDMA,      1, &ddp_rdma },
358         [DDP_COMPONENT_RDMA2]   = { MTK_DISP_RDMA,      2, &ddp_rdma },
359         [DDP_COMPONENT_UFOE]    = { MTK_DISP_UFOE,      0, &ddp_ufoe },
360         [DDP_COMPONENT_WDMA0]   = { MTK_DISP_WDMA,      0, NULL },
361         [DDP_COMPONENT_WDMA1]   = { MTK_DISP_WDMA,      1, NULL },
362 };
363
364 static bool mtk_drm_find_comp_in_ddp(struct device *dev,
365                                      const enum mtk_ddp_comp_id *path,
366                                      unsigned int path_len,
367                                      struct mtk_ddp_comp *ddp_comp)
368 {
369         unsigned int i;
370
371         if (path == NULL)
372                 return false;
373
374         for (i = 0U; i < path_len; i++)
375                 if (dev == ddp_comp[path[i]].dev)
376                         return true;
377
378         return false;
379 }
380
381 int mtk_ddp_comp_get_id(struct device_node *node,
382                         enum mtk_ddp_comp_type comp_type)
383 {
384         int id = of_alias_get_id(node, mtk_ddp_comp_stem[comp_type]);
385         int i;
386
387         for (i = 0; i < ARRAY_SIZE(mtk_ddp_matches); i++) {
388                 if (comp_type == mtk_ddp_matches[i].type &&
389                     (id < 0 || id == mtk_ddp_matches[i].alias_id))
390                         return i;
391         }
392
393         return -EINVAL;
394 }
395
396 unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
397                                                 struct device *dev)
398 {
399         struct mtk_drm_private *private = drm->dev_private;
400         unsigned int ret = 0;
401
402         if (mtk_drm_find_comp_in_ddp(dev, private->data->main_path, private->data->main_len,
403                                      private->ddp_comp))
404                 ret = BIT(0);
405         else if (mtk_drm_find_comp_in_ddp(dev, private->data->ext_path,
406                                           private->data->ext_len, private->ddp_comp))
407                 ret = BIT(1);
408         else if (mtk_drm_find_comp_in_ddp(dev, private->data->third_path,
409                                           private->data->third_len, private->ddp_comp))
410                 ret = BIT(2);
411         else
412                 DRM_INFO("Failed to find comp in ddp table\n");
413
414         return ret;
415 }
416
417 static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp *comp,
418                                 struct device *dev)
419 {
420         struct device_node *larb_node;
421         struct platform_device *larb_pdev;
422
423         larb_node = of_parse_phandle(node, "mediatek,larb", 0);
424         if (!larb_node) {
425                 dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", node);
426                 return -EINVAL;
427         }
428
429         larb_pdev = of_find_device_by_node(larb_node);
430         if (!larb_pdev) {
431                 dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
432                 of_node_put(larb_node);
433                 return -EPROBE_DEFER;
434         }
435         of_node_put(larb_node);
436         comp->larb_dev = &larb_pdev->dev;
437
438         return 0;
439 }
440
441 int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
442                       enum mtk_ddp_comp_id comp_id)
443 {
444         struct platform_device *comp_pdev;
445         enum mtk_ddp_comp_type type;
446         struct mtk_ddp_comp_dev *priv;
447         int ret;
448
449         if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
450                 return -EINVAL;
451
452         type = mtk_ddp_matches[comp_id].type;
453
454         comp->id = comp_id;
455         comp->funcs = mtk_ddp_matches[comp_id].funcs;
456         comp_pdev = of_find_device_by_node(node);
457         if (!comp_pdev) {
458                 DRM_INFO("Waiting for device %s\n", node->full_name);
459                 return -EPROBE_DEFER;
460         }
461         comp->dev = &comp_pdev->dev;
462
463         /* Only DMA capable components need the LARB property */
464         if (type == MTK_DISP_OVL ||
465             type == MTK_DISP_OVL_2L ||
466             type == MTK_DISP_RDMA ||
467             type == MTK_DISP_WDMA) {
468                 ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
469                 if (ret)
470                         return ret;
471         }
472
473         if (type == MTK_DISP_AAL ||
474             type == MTK_DISP_BLS ||
475             type == MTK_DISP_CCORR ||
476             type == MTK_DISP_COLOR ||
477             type == MTK_DISP_GAMMA ||
478             type == MTK_DPI ||
479             type == MTK_DSI ||
480             type == MTK_DISP_OVL ||
481             type == MTK_DISP_OVL_2L ||
482             type == MTK_DISP_PWM ||
483             type == MTK_DISP_RDMA)
484                 return 0;
485
486         priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL);
487         if (!priv)
488                 return -ENOMEM;
489
490         priv->regs = of_iomap(node, 0);
491         priv->clk = of_clk_get(node, 0);
492         if (IS_ERR(priv->clk))
493                 return PTR_ERR(priv->clk);
494
495 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
496         ret = cmdq_dev_get_client_reg(comp->dev, &priv->cmdq_reg, 0);
497         if (ret)
498                 dev_dbg(comp->dev, "get mediatek,gce-client-reg fail!\n");
499 #endif
500
501         platform_set_drvdata(comp_pdev, priv);
502
503         return 0;
504 }