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_disp_rdma.c
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/component.h>
8 #include <linux/module.h>
9 #include <linux/of_device.h>
10 #include <linux/of_irq.h>
11 #include <linux/platform_device.h>
12 #include <linux/soc/mediatek/mtk-cmdq.h>
13
14 #include "mtk_disp_drv.h"
15 #include "mtk_drm_crtc.h"
16 #include "mtk_drm_ddp_comp.h"
17
18 #define DISP_REG_RDMA_INT_ENABLE                0x0000
19 #define DISP_REG_RDMA_INT_STATUS                0x0004
20 #define RDMA_TARGET_LINE_INT                            BIT(5)
21 #define RDMA_FIFO_UNDERFLOW_INT                         BIT(4)
22 #define RDMA_EOF_ABNORMAL_INT                           BIT(3)
23 #define RDMA_FRAME_END_INT                              BIT(2)
24 #define RDMA_FRAME_START_INT                            BIT(1)
25 #define RDMA_REG_UPDATE_INT                             BIT(0)
26 #define DISP_REG_RDMA_GLOBAL_CON                0x0010
27 #define RDMA_ENGINE_EN                                  BIT(0)
28 #define RDMA_MODE_MEMORY                                BIT(1)
29 #define DISP_REG_RDMA_SIZE_CON_0                0x0014
30 #define RDMA_MATRIX_ENABLE                              BIT(17)
31 #define RDMA_MATRIX_INT_MTX_SEL                         GENMASK(23, 20)
32 #define RDMA_MATRIX_INT_MTX_BT601_to_RGB                (6 << 20)
33 #define DISP_REG_RDMA_SIZE_CON_1                0x0018
34 #define DISP_REG_RDMA_TARGET_LINE               0x001c
35 #define DISP_RDMA_MEM_CON                       0x0024
36 #define MEM_MODE_INPUT_FORMAT_RGB565                    (0x000 << 4)
37 #define MEM_MODE_INPUT_FORMAT_RGB888                    (0x001 << 4)
38 #define MEM_MODE_INPUT_FORMAT_RGBA8888                  (0x002 << 4)
39 #define MEM_MODE_INPUT_FORMAT_ARGB8888                  (0x003 << 4)
40 #define MEM_MODE_INPUT_FORMAT_UYVY                      (0x004 << 4)
41 #define MEM_MODE_INPUT_FORMAT_YUYV                      (0x005 << 4)
42 #define MEM_MODE_INPUT_SWAP                             BIT(8)
43 #define DISP_RDMA_MEM_SRC_PITCH                 0x002c
44 #define DISP_RDMA_MEM_GMC_SETTING_0             0x0030
45 #define DISP_REG_RDMA_FIFO_CON                  0x0040
46 #define RDMA_FIFO_UNDERFLOW_EN                          BIT(31)
47 #define RDMA_FIFO_PSEUDO_SIZE(bytes)                    (((bytes) / 16) << 16)
48 #define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes)         ((bytes) / 16)
49 #define RDMA_FIFO_SIZE(rdma)                    ((rdma)->data->fifo_size)
50 #define DISP_RDMA_MEM_START_ADDR                0x0f00
51
52 #define RDMA_MEM_GMC                            0x40402020
53
54 struct mtk_disp_rdma_data {
55         unsigned int fifo_size;
56 };
57
58 /*
59  * struct mtk_disp_rdma - DISP_RDMA driver structure
60  * @data: local driver data
61  */
62 struct mtk_disp_rdma {
63         struct clk                      *clk;
64         void __iomem                    *regs;
65         struct cmdq_client_reg          cmdq_reg;
66         const struct mtk_disp_rdma_data *data;
67         void                            (*vblank_cb)(void *data);
68         void                            *vblank_cb_data;
69         u32                             fifo_size;
70 };
71
72 static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id)
73 {
74         struct mtk_disp_rdma *priv = dev_id;
75
76         /* Clear frame completion interrupt */
77         writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
78
79         if (!priv->vblank_cb)
80                 return IRQ_NONE;
81
82         priv->vblank_cb(priv->vblank_cb_data);
83
84         return IRQ_HANDLED;
85 }
86
87 static void rdma_update_bits(struct device *dev, unsigned int reg,
88                              unsigned int mask, unsigned int val)
89 {
90         struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
91         unsigned int tmp = readl(rdma->regs + reg);
92
93         tmp = (tmp & ~mask) | (val & mask);
94         writel(tmp, rdma->regs + reg);
95 }
96
97 void mtk_rdma_enable_vblank(struct device *dev,
98                             void (*vblank_cb)(void *),
99                             void *vblank_cb_data)
100 {
101         struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
102
103         rdma->vblank_cb = vblank_cb;
104         rdma->vblank_cb_data = vblank_cb_data;
105         rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
106                          RDMA_FRAME_END_INT);
107 }
108
109 void mtk_rdma_disable_vblank(struct device *dev)
110 {
111         struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
112
113         rdma->vblank_cb = NULL;
114         rdma->vblank_cb_data = NULL;
115         rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
116 }
117
118 int mtk_rdma_clk_enable(struct device *dev)
119 {
120         struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
121
122         return clk_prepare_enable(rdma->clk);
123 }
124
125 void mtk_rdma_clk_disable(struct device *dev)
126 {
127         struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
128
129         clk_disable_unprepare(rdma->clk);
130 }
131
132 void mtk_rdma_start(struct device *dev)
133 {
134         rdma_update_bits(dev, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN,
135                          RDMA_ENGINE_EN);
136 }
137
138 void mtk_rdma_stop(struct device *dev)
139 {
140         rdma_update_bits(dev, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN, 0);
141 }
142
143 void mtk_rdma_config(struct device *dev, unsigned int width,
144                      unsigned int height, unsigned int vrefresh,
145                      unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
146 {
147         unsigned int threshold;
148         unsigned int reg;
149         struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
150         u32 rdma_fifo_size;
151
152         mtk_ddp_write_mask(cmdq_pkt, width, &rdma->cmdq_reg, rdma->regs,
153                            DISP_REG_RDMA_SIZE_CON_0, 0xfff);
154         mtk_ddp_write_mask(cmdq_pkt, height, &rdma->cmdq_reg, rdma->regs,
155                            DISP_REG_RDMA_SIZE_CON_1, 0xfffff);
156
157         if (rdma->fifo_size)
158                 rdma_fifo_size = rdma->fifo_size;
159         else
160                 rdma_fifo_size = RDMA_FIFO_SIZE(rdma);
161
162         /*
163          * Enable FIFO underflow since DSI and DPI can't be blocked.
164          * Keep the FIFO pseudo size reset default of 8 KiB. Set the
165          * output threshold to 70% of max fifo size to make sure the
166          * threhold will not overflow
167          */
168         threshold = rdma_fifo_size * 7 / 10;
169         reg = RDMA_FIFO_UNDERFLOW_EN |
170               RDMA_FIFO_PSEUDO_SIZE(rdma_fifo_size) |
171               RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
172         mtk_ddp_write(cmdq_pkt, reg, &rdma->cmdq_reg, rdma->regs, DISP_REG_RDMA_FIFO_CON);
173 }
174
175 static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma,
176                                      unsigned int fmt)
177 {
178         /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX"
179          * is defined in mediatek HW data sheet.
180          * The alphabet order in XXX is no relation to data
181          * arrangement in memory.
182          */
183         switch (fmt) {
184         default:
185         case DRM_FORMAT_RGB565:
186                 return MEM_MODE_INPUT_FORMAT_RGB565;
187         case DRM_FORMAT_BGR565:
188                 return MEM_MODE_INPUT_FORMAT_RGB565 | MEM_MODE_INPUT_SWAP;
189         case DRM_FORMAT_RGB888:
190                 return MEM_MODE_INPUT_FORMAT_RGB888;
191         case DRM_FORMAT_BGR888:
192                 return MEM_MODE_INPUT_FORMAT_RGB888 | MEM_MODE_INPUT_SWAP;
193         case DRM_FORMAT_RGBX8888:
194         case DRM_FORMAT_RGBA8888:
195                 return MEM_MODE_INPUT_FORMAT_ARGB8888;
196         case DRM_FORMAT_BGRX8888:
197         case DRM_FORMAT_BGRA8888:
198                 return MEM_MODE_INPUT_FORMAT_ARGB8888 | MEM_MODE_INPUT_SWAP;
199         case DRM_FORMAT_XRGB8888:
200         case DRM_FORMAT_ARGB8888:
201                 return MEM_MODE_INPUT_FORMAT_RGBA8888;
202         case DRM_FORMAT_XBGR8888:
203         case DRM_FORMAT_ABGR8888:
204                 return MEM_MODE_INPUT_FORMAT_RGBA8888 | MEM_MODE_INPUT_SWAP;
205         case DRM_FORMAT_UYVY:
206                 return MEM_MODE_INPUT_FORMAT_UYVY;
207         case DRM_FORMAT_YUYV:
208                 return MEM_MODE_INPUT_FORMAT_YUYV;
209         }
210 }
211
212 unsigned int mtk_rdma_layer_nr(struct device *dev)
213 {
214         return 1;
215 }
216
217 void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
218                            struct mtk_plane_state *state,
219                            struct cmdq_pkt *cmdq_pkt)
220 {
221         struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
222         struct mtk_plane_pending_state *pending = &state->pending;
223         unsigned int addr = pending->addr;
224         unsigned int pitch = pending->pitch & 0xffff;
225         unsigned int fmt = pending->format;
226         unsigned int con;
227
228         con = rdma_fmt_convert(rdma, fmt);
229         mtk_ddp_write_relaxed(cmdq_pkt, con, &rdma->cmdq_reg, rdma->regs, DISP_RDMA_MEM_CON);
230
231         if (fmt == DRM_FORMAT_UYVY || fmt == DRM_FORMAT_YUYV) {
232                 mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_ENABLE, &rdma->cmdq_reg, rdma->regs,
233                                    DISP_REG_RDMA_SIZE_CON_0,
234                                    RDMA_MATRIX_ENABLE);
235                 mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_INT_MTX_BT601_to_RGB,
236                                    &rdma->cmdq_reg, rdma->regs, DISP_REG_RDMA_SIZE_CON_0,
237                                    RDMA_MATRIX_INT_MTX_SEL);
238         } else {
239                 mtk_ddp_write_mask(cmdq_pkt, 0, &rdma->cmdq_reg, rdma->regs,
240                                    DISP_REG_RDMA_SIZE_CON_0,
241                                    RDMA_MATRIX_ENABLE);
242         }
243         mtk_ddp_write_relaxed(cmdq_pkt, addr, &rdma->cmdq_reg, rdma->regs,
244                               DISP_RDMA_MEM_START_ADDR);
245         mtk_ddp_write_relaxed(cmdq_pkt, pitch, &rdma->cmdq_reg, rdma->regs,
246                               DISP_RDMA_MEM_SRC_PITCH);
247         mtk_ddp_write(cmdq_pkt, RDMA_MEM_GMC, &rdma->cmdq_reg, rdma->regs,
248                       DISP_RDMA_MEM_GMC_SETTING_0);
249         mtk_ddp_write_mask(cmdq_pkt, RDMA_MODE_MEMORY, &rdma->cmdq_reg, rdma->regs,
250                            DISP_REG_RDMA_GLOBAL_CON, RDMA_MODE_MEMORY);
251
252 }
253
254 static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
255                               void *data)
256 {
257         return 0;
258
259 }
260
261 static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
262                                  void *data)
263 {
264 }
265
266 static const struct component_ops mtk_disp_rdma_component_ops = {
267         .bind   = mtk_disp_rdma_bind,
268         .unbind = mtk_disp_rdma_unbind,
269 };
270
271 static int mtk_disp_rdma_probe(struct platform_device *pdev)
272 {
273         struct device *dev = &pdev->dev;
274         struct mtk_disp_rdma *priv;
275         struct resource *res;
276         int irq;
277         int ret;
278
279         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
280         if (!priv)
281                 return -ENOMEM;
282
283         irq = platform_get_irq(pdev, 0);
284         if (irq < 0)
285                 return irq;
286
287         priv->clk = devm_clk_get(dev, NULL);
288         if (IS_ERR(priv->clk)) {
289                 dev_err(dev, "failed to get rdma clk\n");
290                 return PTR_ERR(priv->clk);
291         }
292
293         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
294         priv->regs = devm_ioremap_resource(dev, res);
295         if (IS_ERR(priv->regs)) {
296                 dev_err(dev, "failed to ioremap rdma\n");
297                 return PTR_ERR(priv->regs);
298         }
299 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
300         ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
301         if (ret)
302                 dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
303 #endif
304
305         if (of_find_property(dev->of_node, "mediatek,rdma-fifo-size", &ret)) {
306                 ret = of_property_read_u32(dev->of_node,
307                                            "mediatek,rdma-fifo-size",
308                                            &priv->fifo_size);
309                 if (ret) {
310                         dev_err(dev, "Failed to get rdma fifo size\n");
311                         return ret;
312                 }
313         }
314
315         /* Disable and clear pending interrupts */
316         writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
317         writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
318
319         ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
320                                IRQF_TRIGGER_NONE, dev_name(dev), priv);
321         if (ret < 0) {
322                 dev_err(dev, "Failed to request irq %d: %d\n", irq, ret);
323                 return ret;
324         }
325
326         priv->data = of_device_get_match_data(dev);
327
328         platform_set_drvdata(pdev, priv);
329
330         ret = component_add(dev, &mtk_disp_rdma_component_ops);
331         if (ret)
332                 dev_err(dev, "Failed to add component: %d\n", ret);
333
334         return ret;
335 }
336
337 static int mtk_disp_rdma_remove(struct platform_device *pdev)
338 {
339         component_del(&pdev->dev, &mtk_disp_rdma_component_ops);
340
341         return 0;
342 }
343
344 static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = {
345         .fifo_size = SZ_4K,
346 };
347
348 static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = {
349         .fifo_size = SZ_8K,
350 };
351
352 static const struct mtk_disp_rdma_data mt8183_rdma_driver_data = {
353         .fifo_size = 5 * SZ_1K,
354 };
355
356 static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
357         { .compatible = "mediatek,mt2701-disp-rdma",
358           .data = &mt2701_rdma_driver_data},
359         { .compatible = "mediatek,mt8173-disp-rdma",
360           .data = &mt8173_rdma_driver_data},
361         { .compatible = "mediatek,mt8183-disp-rdma",
362           .data = &mt8183_rdma_driver_data},
363         {},
364 };
365 MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
366
367 struct platform_driver mtk_disp_rdma_driver = {
368         .probe          = mtk_disp_rdma_probe,
369         .remove         = mtk_disp_rdma_remove,
370         .driver         = {
371                 .name   = "mediatek-disp-rdma",
372                 .owner  = THIS_MODULE,
373                 .of_match_table = mtk_disp_rdma_driver_dt_match,
374         },
375 };