1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2021 MediaTek Inc.
6 #include <drm/drm_fourcc.h>
8 #include <linux/component.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/soc/mediatek/mtk-cmdq.h>
14 #include "mtk_disp_drv.h"
15 #include "mtk_drm_drv.h"
16 #include "mtk_mdp_rdma.h"
18 #define MDP_RDMA_EN 0x000
19 #define FLD_ROT_ENABLE BIT(0)
20 #define MDP_RDMA_RESET 0x008
21 #define MDP_RDMA_CON 0x020
22 #define FLD_OUTPUT_10B BIT(5)
23 #define FLD_SIMPLE_MODE BIT(4)
24 #define MDP_RDMA_GMCIF_CON 0x028
25 #define FLD_COMMAND_DIV BIT(0)
26 #define FLD_EXT_PREULTRA_EN BIT(3)
27 #define FLD_RD_REQ_TYPE GENMASK(7, 4)
28 #define VAL_RD_REQ_TYPE_BURST_8_ACCESS 7
29 #define FLD_ULTRA_EN GENMASK(13, 12)
30 #define VAL_ULTRA_EN_ENABLE 1
31 #define FLD_PRE_ULTRA_EN GENMASK(17, 16)
32 #define VAL_PRE_ULTRA_EN_ENABLE 1
33 #define FLD_EXT_ULTRA_EN BIT(18)
34 #define MDP_RDMA_SRC_CON 0x030
35 #define FLD_OUTPUT_ARGB BIT(25)
36 #define FLD_BIT_NUMBER GENMASK(19, 18)
37 #define FLD_SWAP BIT(14)
38 #define FLD_UNIFORM_CONFIG BIT(17)
39 #define RDMA_INPUT_10BIT BIT(18)
40 #define FLD_SRC_FORMAT GENMASK(3, 0)
41 #define MDP_RDMA_COMP_CON 0x038
42 #define FLD_AFBC_EN BIT(22)
43 #define FLD_AFBC_YUV_TRANSFORM BIT(21)
44 #define FLD_UFBDC_EN BIT(12)
45 #define MDP_RDMA_MF_BKGD_SIZE_IN_BYTE 0x060
46 #define FLD_MF_BKGD_WB GENMASK(22, 0)
47 #define MDP_RDMA_MF_SRC_SIZE 0x070
48 #define FLD_MF_SRC_H GENMASK(30, 16)
49 #define FLD_MF_SRC_W GENMASK(14, 0)
50 #define MDP_RDMA_MF_CLIP_SIZE 0x078
51 #define FLD_MF_CLIP_H GENMASK(30, 16)
52 #define FLD_MF_CLIP_W GENMASK(14, 0)
53 #define MDP_RDMA_SRC_OFFSET_0 0x118
54 #define FLD_SRC_OFFSET_0 GENMASK(31, 0)
55 #define MDP_RDMA_TRANSFORM_0 0x200
56 #define FLD_INT_MATRIX_SEL GENMASK(27, 23)
57 #define FLD_TRANS_EN BIT(16)
58 #define MDP_RDMA_SRC_BASE_0 0xf00
59 #define FLD_SRC_BASE_0 GENMASK(31, 0)
61 #define RDMA_CSC_FULL709_TO_RGB 5
62 #define RDMA_CSC_BT601_TO_RGB 6
64 static const u32 formats
[] = {
79 RDMA_INPUT_FORMAT_RGB565
= 0,
80 RDMA_INPUT_FORMAT_RGB888
= 1,
81 RDMA_INPUT_FORMAT_RGBA8888
= 2,
82 RDMA_INPUT_FORMAT_ARGB8888
= 3,
83 RDMA_INPUT_FORMAT_UYVY
= 4,
84 RDMA_INPUT_FORMAT_YUY2
= 5,
85 RDMA_INPUT_FORMAT_Y8
= 7,
86 RDMA_INPUT_FORMAT_YV12
= 8,
87 RDMA_INPUT_FORMAT_UYVY_3PL
= 9,
88 RDMA_INPUT_FORMAT_NV12
= 12,
89 RDMA_INPUT_FORMAT_UYVY_2PL
= 13,
90 RDMA_INPUT_FORMAT_Y410
= 14
96 struct cmdq_client_reg cmdq_reg
;
99 static unsigned int rdma_fmt_convert(unsigned int fmt
)
103 case DRM_FORMAT_RGB565
:
104 return RDMA_INPUT_FORMAT_RGB565
;
105 case DRM_FORMAT_BGR565
:
106 return RDMA_INPUT_FORMAT_RGB565
| FLD_SWAP
;
107 case DRM_FORMAT_RGB888
:
108 return RDMA_INPUT_FORMAT_RGB888
;
109 case DRM_FORMAT_BGR888
:
110 return RDMA_INPUT_FORMAT_RGB888
| FLD_SWAP
;
111 case DRM_FORMAT_RGBX8888
:
112 case DRM_FORMAT_RGBA8888
:
113 return RDMA_INPUT_FORMAT_ARGB8888
;
114 case DRM_FORMAT_BGRX8888
:
115 case DRM_FORMAT_BGRA8888
:
116 return RDMA_INPUT_FORMAT_ARGB8888
| FLD_SWAP
;
117 case DRM_FORMAT_XRGB8888
:
118 case DRM_FORMAT_ARGB8888
:
119 return RDMA_INPUT_FORMAT_RGBA8888
;
120 case DRM_FORMAT_XBGR8888
:
121 case DRM_FORMAT_ABGR8888
:
122 return RDMA_INPUT_FORMAT_RGBA8888
| FLD_SWAP
;
123 case DRM_FORMAT_ABGR2101010
:
124 return RDMA_INPUT_FORMAT_RGBA8888
| FLD_SWAP
| RDMA_INPUT_10BIT
;
125 case DRM_FORMAT_ARGB2101010
:
126 return RDMA_INPUT_FORMAT_RGBA8888
| RDMA_INPUT_10BIT
;
127 case DRM_FORMAT_RGBA1010102
:
128 return RDMA_INPUT_FORMAT_ARGB8888
| FLD_SWAP
| RDMA_INPUT_10BIT
;
129 case DRM_FORMAT_BGRA1010102
:
130 return RDMA_INPUT_FORMAT_ARGB8888
| RDMA_INPUT_10BIT
;
131 case DRM_FORMAT_UYVY
:
132 return RDMA_INPUT_FORMAT_UYVY
;
133 case DRM_FORMAT_YUYV
:
134 return RDMA_INPUT_FORMAT_YUY2
;
138 static unsigned int rdma_color_convert(unsigned int color_encoding
)
140 switch (color_encoding
) {
142 case DRM_COLOR_YCBCR_BT709
:
143 return RDMA_CSC_FULL709_TO_RGB
;
144 case DRM_COLOR_YCBCR_BT601
:
145 return RDMA_CSC_BT601_TO_RGB
;
149 static void mtk_mdp_rdma_fifo_config(struct device
*dev
, struct cmdq_pkt
*cmdq_pkt
)
151 struct mtk_mdp_rdma
*priv
= dev_get_drvdata(dev
);
153 mtk_ddp_write_mask(cmdq_pkt
, FLD_EXT_ULTRA_EN
| VAL_PRE_ULTRA_EN_ENABLE
<< 16 |
154 VAL_ULTRA_EN_ENABLE
<< 12 | VAL_RD_REQ_TYPE_BURST_8_ACCESS
<< 4 |
155 FLD_EXT_PREULTRA_EN
| FLD_COMMAND_DIV
, &priv
->cmdq_reg
,
156 priv
->regs
, MDP_RDMA_GMCIF_CON
, FLD_EXT_ULTRA_EN
|
157 FLD_PRE_ULTRA_EN
| FLD_ULTRA_EN
| FLD_RD_REQ_TYPE
|
158 FLD_EXT_PREULTRA_EN
| FLD_COMMAND_DIV
);
161 void mtk_mdp_rdma_start(struct device
*dev
, struct cmdq_pkt
*cmdq_pkt
)
163 struct mtk_mdp_rdma
*priv
= dev_get_drvdata(dev
);
165 mtk_ddp_write_mask(cmdq_pkt
, FLD_ROT_ENABLE
, &priv
->cmdq_reg
,
166 priv
->regs
, MDP_RDMA_EN
, FLD_ROT_ENABLE
);
169 void mtk_mdp_rdma_stop(struct device
*dev
, struct cmdq_pkt
*cmdq_pkt
)
171 struct mtk_mdp_rdma
*priv
= dev_get_drvdata(dev
);
173 mtk_ddp_write_mask(cmdq_pkt
, 0, &priv
->cmdq_reg
,
174 priv
->regs
, MDP_RDMA_EN
, FLD_ROT_ENABLE
);
175 mtk_ddp_write(cmdq_pkt
, 1, &priv
->cmdq_reg
, priv
->regs
, MDP_RDMA_RESET
);
176 mtk_ddp_write(cmdq_pkt
, 0, &priv
->cmdq_reg
, priv
->regs
, MDP_RDMA_RESET
);
179 void mtk_mdp_rdma_config(struct device
*dev
, struct mtk_mdp_rdma_cfg
*cfg
,
180 struct cmdq_pkt
*cmdq_pkt
)
182 struct mtk_mdp_rdma
*priv
= dev_get_drvdata(dev
);
183 const struct drm_format_info
*fmt_info
= drm_format_info(cfg
->fmt
);
184 bool csc_enable
= fmt_info
->is_yuv
? true : false;
185 unsigned int src_pitch_y
= cfg
->pitch
;
186 unsigned int offset_y
= 0;
188 mtk_mdp_rdma_fifo_config(dev
, cmdq_pkt
);
190 mtk_ddp_write_mask(cmdq_pkt
, FLD_UNIFORM_CONFIG
, &priv
->cmdq_reg
, priv
->regs
,
191 MDP_RDMA_SRC_CON
, FLD_UNIFORM_CONFIG
);
192 mtk_ddp_write_mask(cmdq_pkt
, rdma_fmt_convert(cfg
->fmt
), &priv
->cmdq_reg
, priv
->regs
,
193 MDP_RDMA_SRC_CON
, FLD_SWAP
| FLD_SRC_FORMAT
| FLD_BIT_NUMBER
);
195 if (!csc_enable
&& fmt_info
->has_alpha
)
196 mtk_ddp_write_mask(cmdq_pkt
, FLD_OUTPUT_ARGB
, &priv
->cmdq_reg
,
197 priv
->regs
, MDP_RDMA_SRC_CON
, FLD_OUTPUT_ARGB
);
199 mtk_ddp_write_mask(cmdq_pkt
, 0, &priv
->cmdq_reg
, priv
->regs
,
200 MDP_RDMA_SRC_CON
, FLD_OUTPUT_ARGB
);
202 mtk_ddp_write_mask(cmdq_pkt
, cfg
->addr0
, &priv
->cmdq_reg
, priv
->regs
,
203 MDP_RDMA_SRC_BASE_0
, FLD_SRC_BASE_0
);
205 mtk_ddp_write_mask(cmdq_pkt
, src_pitch_y
, &priv
->cmdq_reg
, priv
->regs
,
206 MDP_RDMA_MF_BKGD_SIZE_IN_BYTE
, FLD_MF_BKGD_WB
);
208 mtk_ddp_write_mask(cmdq_pkt
, 0, &priv
->cmdq_reg
, priv
->regs
, MDP_RDMA_COMP_CON
,
209 FLD_AFBC_YUV_TRANSFORM
| FLD_UFBDC_EN
| FLD_AFBC_EN
);
210 mtk_ddp_write_mask(cmdq_pkt
, FLD_OUTPUT_10B
, &priv
->cmdq_reg
, priv
->regs
,
211 MDP_RDMA_CON
, FLD_OUTPUT_10B
);
212 mtk_ddp_write_mask(cmdq_pkt
, FLD_SIMPLE_MODE
, &priv
->cmdq_reg
, priv
->regs
,
213 MDP_RDMA_CON
, FLD_SIMPLE_MODE
);
215 mtk_ddp_write_mask(cmdq_pkt
, rdma_color_convert(cfg
->color_encoding
) << 23,
216 &priv
->cmdq_reg
, priv
->regs
, MDP_RDMA_TRANSFORM_0
,
218 mtk_ddp_write_mask(cmdq_pkt
, csc_enable
<< 16, &priv
->cmdq_reg
, priv
->regs
,
219 MDP_RDMA_TRANSFORM_0
, FLD_TRANS_EN
);
221 offset_y
= cfg
->x_left
* fmt_info
->cpp
[0] + cfg
->y_top
* src_pitch_y
;
223 mtk_ddp_write_mask(cmdq_pkt
, offset_y
, &priv
->cmdq_reg
, priv
->regs
,
224 MDP_RDMA_SRC_OFFSET_0
, FLD_SRC_OFFSET_0
);
225 mtk_ddp_write_mask(cmdq_pkt
, cfg
->width
, &priv
->cmdq_reg
, priv
->regs
,
226 MDP_RDMA_MF_SRC_SIZE
, FLD_MF_SRC_W
);
227 mtk_ddp_write_mask(cmdq_pkt
, cfg
->height
<< 16, &priv
->cmdq_reg
, priv
->regs
,
228 MDP_RDMA_MF_SRC_SIZE
, FLD_MF_SRC_H
);
229 mtk_ddp_write_mask(cmdq_pkt
, cfg
->width
, &priv
->cmdq_reg
, priv
->regs
,
230 MDP_RDMA_MF_CLIP_SIZE
, FLD_MF_CLIP_W
);
231 mtk_ddp_write_mask(cmdq_pkt
, cfg
->height
<< 16, &priv
->cmdq_reg
, priv
->regs
,
232 MDP_RDMA_MF_CLIP_SIZE
, FLD_MF_CLIP_H
);
235 const u32
*mtk_mdp_rdma_get_formats(struct device
*dev
)
240 size_t mtk_mdp_rdma_get_num_formats(struct device
*dev
)
242 return ARRAY_SIZE(formats
);
245 int mtk_mdp_rdma_power_on(struct device
*dev
)
247 int ret
= pm_runtime_resume_and_get(dev
);
250 dev_err(dev
, "Failed to power on: %d\n", ret
);
256 void mtk_mdp_rdma_power_off(struct device
*dev
)
261 int mtk_mdp_rdma_clk_enable(struct device
*dev
)
263 struct mtk_mdp_rdma
*rdma
= dev_get_drvdata(dev
);
265 return clk_prepare_enable(rdma
->clk
);
268 void mtk_mdp_rdma_clk_disable(struct device
*dev
)
270 struct mtk_mdp_rdma
*rdma
= dev_get_drvdata(dev
);
272 clk_disable_unprepare(rdma
->clk
);
275 static int mtk_mdp_rdma_bind(struct device
*dev
, struct device
*master
,
281 static void mtk_mdp_rdma_unbind(struct device
*dev
, struct device
*master
,
286 static const struct component_ops mtk_mdp_rdma_component_ops
= {
287 .bind
= mtk_mdp_rdma_bind
,
288 .unbind
= mtk_mdp_rdma_unbind
,
291 static int mtk_mdp_rdma_probe(struct platform_device
*pdev
)
293 struct device
*dev
= &pdev
->dev
;
294 struct resource
*res
;
295 struct mtk_mdp_rdma
*priv
;
298 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
302 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
303 priv
->regs
= devm_ioremap_resource(dev
, res
);
304 if (IS_ERR(priv
->regs
))
305 return dev_err_probe(dev
, PTR_ERR(priv
->regs
),
306 "failed to ioremap rdma\n");
308 priv
->clk
= devm_clk_get(dev
, NULL
);
309 if (IS_ERR(priv
->clk
))
310 return dev_err_probe(dev
, PTR_ERR(priv
->clk
),
311 "failed to get rdma clk\n");
313 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
314 ret
= cmdq_dev_get_client_reg(dev
, &priv
->cmdq_reg
, 0);
316 dev_dbg(dev
, "get mediatek,gce-client-reg fail!\n");
318 platform_set_drvdata(pdev
, priv
);
320 pm_runtime_enable(dev
);
322 ret
= component_add(dev
, &mtk_mdp_rdma_component_ops
);
324 pm_runtime_disable(dev
);
325 return dev_err_probe(dev
, ret
, "Failed to add component\n");
330 static void mtk_mdp_rdma_remove(struct platform_device
*pdev
)
332 component_del(&pdev
->dev
, &mtk_mdp_rdma_component_ops
);
333 pm_runtime_disable(&pdev
->dev
);
336 static const struct of_device_id mtk_mdp_rdma_driver_dt_match
[] = {
337 { .compatible
= "mediatek,mt8195-vdo1-rdma", },
340 MODULE_DEVICE_TABLE(of
, mtk_mdp_rdma_driver_dt_match
);
342 struct platform_driver mtk_mdp_rdma_driver
= {
343 .probe
= mtk_mdp_rdma_probe
,
344 .remove
= mtk_mdp_rdma_remove
,
346 .name
= "mediatek-mdp-rdma",
347 .of_match_table
= mtk_mdp_rdma_driver_dt_match
,