xref: /linux/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c (revision 55a42f78ffd386e01a5404419f8c5ded7db70a21)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) Rockchip Electronics Co., Ltd.
4  * Author: Andy Yan <andy.yan@rock-chips.com>
5  */
6 
7 #include <linux/bitfield.h>
8 #include <linux/kernel.h>
9 #include <linux/component.h>
10 #include <linux/hw_bitfield.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/platform_device.h>
13 #include <linux/of.h>
14 #include <drm/drm_blend.h>
15 #include <drm/drm_fourcc.h>
16 #include <drm/drm_framebuffer.h>
17 #include <drm/drm_plane.h>
18 #include <drm/drm_print.h>
19 
20 #include "rockchip_drm_vop2.h"
21 
22 union vop2_alpha_ctrl {
23 	u32 val;
24 	struct {
25 		/* [0:1] */
26 		u32 color_mode:1;
27 		u32 alpha_mode:1;
28 		/* [2:3] */
29 		u32 blend_mode:2;
30 		u32 alpha_cal_mode:1;
31 		/* [5:7] */
32 		u32 factor_mode:3;
33 		/* [8:9] */
34 		u32 alpha_en:1;
35 		u32 src_dst_swap:1;
36 		u32 reserved:6;
37 		/* [16:23] */
38 		u32 glb_alpha:8;
39 	} bits;
40 };
41 
42 struct vop2_alpha {
43 	union vop2_alpha_ctrl src_color_ctrl;
44 	union vop2_alpha_ctrl dst_color_ctrl;
45 	union vop2_alpha_ctrl src_alpha_ctrl;
46 	union vop2_alpha_ctrl dst_alpha_ctrl;
47 };
48 
49 struct vop2_alpha_config {
50 	bool src_premulti_en;
51 	bool dst_premulti_en;
52 	bool src_pixel_alpha_en;
53 	bool dst_pixel_alpha_en;
54 	u16 src_glb_alpha_value;
55 	u16 dst_glb_alpha_value;
56 };
57 
58 static const uint32_t formats_cluster[] = {
59 	DRM_FORMAT_XRGB2101010,
60 	DRM_FORMAT_XBGR2101010,
61 	DRM_FORMAT_XRGB8888,
62 	DRM_FORMAT_ARGB8888,
63 	DRM_FORMAT_XBGR8888,
64 	DRM_FORMAT_ABGR8888,
65 	DRM_FORMAT_RGB888,
66 	DRM_FORMAT_BGR888,
67 	DRM_FORMAT_RGB565,
68 	DRM_FORMAT_BGR565,
69 	DRM_FORMAT_YUV420_8BIT, /* yuv420_8bit non-Linear mode only */
70 	DRM_FORMAT_YUV420_10BIT, /* yuv420_10bit non-Linear mode only */
71 	DRM_FORMAT_YUYV, /* yuv422_8bit non-Linear mode only*/
72 	DRM_FORMAT_Y210, /* yuv422_10bit non-Linear mode only */
73 };
74 
75 /*
76  * The cluster windows on rk3576 support:
77  * RGB: linear mode and afbc
78  * YUV: linear mode and rfbc
79  * rfbc is a rockchip defined non-linear mode, produced by
80  * Video decoder
81  */
82 static const uint32_t formats_rk3576_cluster[] = {
83 	DRM_FORMAT_XRGB2101010,
84 	DRM_FORMAT_XBGR2101010,
85 	DRM_FORMAT_ARGB2101010,
86 	DRM_FORMAT_ABGR2101010,
87 	DRM_FORMAT_XRGB8888,
88 	DRM_FORMAT_ARGB8888,
89 	DRM_FORMAT_XBGR8888,
90 	DRM_FORMAT_ABGR8888,
91 	DRM_FORMAT_RGB888,
92 	DRM_FORMAT_BGR888,
93 	DRM_FORMAT_RGB565,
94 	DRM_FORMAT_BGR565,
95 	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
96 	DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
97 	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
98 	DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
99 	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
100 	DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
101 	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
102 	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
103 	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
104 };
105 
106 static const uint32_t formats_esmart[] = {
107 	DRM_FORMAT_XRGB8888,
108 	DRM_FORMAT_ARGB8888,
109 	DRM_FORMAT_XBGR8888,
110 	DRM_FORMAT_ABGR8888,
111 	DRM_FORMAT_RGB888,
112 	DRM_FORMAT_BGR888,
113 	DRM_FORMAT_RGB565,
114 	DRM_FORMAT_BGR565,
115 	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
116 	DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
117 	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
118 	DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
119 	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
120 	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
121 	DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
122 	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
123 	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
124 	DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
125 	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
126 	DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */
127 	DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */
128 };
129 
130 static const uint32_t formats_rk356x_esmart[] = {
131 	DRM_FORMAT_XRGB8888,
132 	DRM_FORMAT_ARGB8888,
133 	DRM_FORMAT_XBGR8888,
134 	DRM_FORMAT_ABGR8888,
135 	DRM_FORMAT_RGB888,
136 	DRM_FORMAT_BGR888,
137 	DRM_FORMAT_RGB565,
138 	DRM_FORMAT_BGR565,
139 	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
140 	DRM_FORMAT_NV21, /* yuv420_8bit linear mode, 2 plane */
141 	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
142 	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
143 	DRM_FORMAT_NV61, /* yuv422_8bit linear mode, 2 plane */
144 	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
145 	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
146 	DRM_FORMAT_NV42, /* yuv444_8bit linear mode, 2 plane */
147 	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
148 	DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
149 	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
150 };
151 
152 /*
153  * Add XRGB2101010/ARGB2101010ARGB1555/XRGB1555
154  */
155 static const uint32_t formats_rk3576_esmart[] = {
156 	DRM_FORMAT_XRGB2101010,
157 	DRM_FORMAT_XBGR2101010,
158 	DRM_FORMAT_ARGB2101010,
159 	DRM_FORMAT_ABGR2101010,
160 	DRM_FORMAT_XRGB8888,
161 	DRM_FORMAT_ARGB8888,
162 	DRM_FORMAT_XBGR8888,
163 	DRM_FORMAT_ABGR8888,
164 	DRM_FORMAT_RGB888,
165 	DRM_FORMAT_BGR888,
166 	DRM_FORMAT_RGB565,
167 	DRM_FORMAT_BGR565,
168 	DRM_FORMAT_ARGB1555,
169 	DRM_FORMAT_ABGR1555,
170 	DRM_FORMAT_XRGB1555,
171 	DRM_FORMAT_XBGR1555,
172 	DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
173 	DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
174 	DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
175 	DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
176 	DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
177 	DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
178 	DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
179 	DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
180 	DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
181 	DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
182 	DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
183 	DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */
184 	DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */
185 };
186 
187 static const uint32_t formats_smart[] = {
188 	DRM_FORMAT_XRGB8888,
189 	DRM_FORMAT_ARGB8888,
190 	DRM_FORMAT_XBGR8888,
191 	DRM_FORMAT_ABGR8888,
192 	DRM_FORMAT_RGB888,
193 	DRM_FORMAT_BGR888,
194 	DRM_FORMAT_RGB565,
195 	DRM_FORMAT_BGR565,
196 };
197 
198 static const uint64_t format_modifiers[] = {
199 	DRM_FORMAT_MOD_LINEAR,
200 	DRM_FORMAT_MOD_INVALID,
201 };
202 
203 static const uint64_t format_modifiers_afbc[] = {
204 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
205 
206 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
207 				AFBC_FORMAT_MOD_SPARSE),
208 
209 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
210 				AFBC_FORMAT_MOD_YTR),
211 
212 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
213 				AFBC_FORMAT_MOD_CBR),
214 
215 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
216 				AFBC_FORMAT_MOD_YTR |
217 				AFBC_FORMAT_MOD_SPARSE),
218 
219 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
220 				AFBC_FORMAT_MOD_CBR |
221 				AFBC_FORMAT_MOD_SPARSE),
222 
223 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
224 				AFBC_FORMAT_MOD_YTR |
225 				AFBC_FORMAT_MOD_CBR),
226 
227 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
228 				AFBC_FORMAT_MOD_YTR |
229 				AFBC_FORMAT_MOD_CBR |
230 				AFBC_FORMAT_MOD_SPARSE),
231 
232 	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
233 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
234 				AFBC_FORMAT_MOD_YTR |
235 				AFBC_FORMAT_MOD_SPARSE |
236 				AFBC_FORMAT_MOD_SPLIT),
237 	DRM_FORMAT_MOD_INVALID,
238 };
239 
240 /* used from rk3576, afbc 32*8 half mode */
241 static const uint64_t format_modifiers_rk3576_afbc[] = {
242 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
243 				AFBC_FORMAT_MOD_SPLIT),
244 
245 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
246 				AFBC_FORMAT_MOD_SPARSE |
247 				AFBC_FORMAT_MOD_SPLIT),
248 
249 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
250 				AFBC_FORMAT_MOD_YTR |
251 				AFBC_FORMAT_MOD_SPLIT),
252 
253 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
254 				AFBC_FORMAT_MOD_CBR |
255 				AFBC_FORMAT_MOD_SPLIT),
256 
257 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
258 				AFBC_FORMAT_MOD_CBR |
259 				AFBC_FORMAT_MOD_SPARSE |
260 				AFBC_FORMAT_MOD_SPLIT),
261 
262 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
263 				AFBC_FORMAT_MOD_YTR |
264 				AFBC_FORMAT_MOD_CBR |
265 				AFBC_FORMAT_MOD_SPLIT),
266 
267 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
268 				AFBC_FORMAT_MOD_YTR |
269 				AFBC_FORMAT_MOD_CBR |
270 				AFBC_FORMAT_MOD_SPARSE |
271 				AFBC_FORMAT_MOD_SPLIT),
272 
273 	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
274 	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
275 				AFBC_FORMAT_MOD_YTR |
276 				AFBC_FORMAT_MOD_SPARSE |
277 				AFBC_FORMAT_MOD_SPLIT),
278 	DRM_FORMAT_MOD_LINEAR,
279 	DRM_FORMAT_MOD_INVALID,
280 };
281 
282 static const struct reg_field rk3568_vop_cluster_regs[VOP2_WIN_MAX_REG] = {
283 	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
284 	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
285 	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14),
286 	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18),
287 	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31),
288 	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31),
289 	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31),
290 	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31),
291 	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31),
292 	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19),
293 	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15),
294 	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31),
295 	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8),
296 	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9),
297 	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11),
298 	[VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 3),
299 	[VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 8),
300 	/* RK3588 only, reserved bit on rk3568*/
301 	[VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13),
302 
303 	/* Scale */
304 	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15),
305 	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31),
306 	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15),
307 	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13),
308 	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3),
309 	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28),
310 	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29),
311 
312 	/* cluster regs */
313 	[VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1),
314 	[VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0),
315 	[VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7),
316 
317 	/* afbc regs */
318 	[VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6),
319 	[VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9),
320 	[VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10),
321 	[VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4),
322 	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7),
323 	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8),
324 	[VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31),
325 	[VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31),
326 	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15),
327 	[VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31),
328 	[VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31),
329 	[VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31),
330 	[VOP2_WIN_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_TRANSFORM_OFFSET, 0, 31),
331 	[VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0),
332 	[VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1),
333 	[VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2),
334 	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3),
335 	[VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff },
336 	[VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff },
337 	[VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff },
338 	[VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
339 	[VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
340 	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
341 	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
342 	[VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff },
343 	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
344 	[VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
345 	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
346 	[VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff },
347 	[VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff },
348 };
349 
350 static const struct reg_field rk3568_vop_smart_regs[VOP2_WIN_MAX_REG] = {
351 	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0),
352 	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5),
353 	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12),
354 	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14),
355 	[VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16),
356 	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31),
357 	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31),
358 	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28),
359 	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31),
360 	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31),
361 	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17),
362 	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15),
363 	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31),
364 	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0),
365 	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1),
366 	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3),
367 	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31),
368 	[VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29),
369 	[VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31),
370 	[VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8),
371 	[VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16),
372 	/* RK3588 only, reserved register on rk3568 */
373 	[VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1),
374 
375 	/* Scale */
376 	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15),
377 	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31),
378 	[VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15),
379 	[VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31),
380 	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1),
381 	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3),
382 	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5),
383 	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7),
384 	[VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9),
385 	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11),
386 	[VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13),
387 	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15),
388 	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17),
389 	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8),
390 	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9),
391 	[VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10),
392 	[VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11),
393 	[VOP2_WIN_XMIRROR] = { .reg = 0xffffffff },
394 	[VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff },
395 	[VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff },
396 	[VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff },
397 	[VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff },
398 	[VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff },
399 	[VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff },
400 	[VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff },
401 	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff },
402 	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff },
403 	[VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff },
404 	[VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff },
405 	[VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff },
406 	[VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff },
407 	[VOP2_WIN_TRANSFORM_OFFSET] = { .reg = 0xffffffff },
408 	[VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff },
409 	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff },
410 	[VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff },
411 	[VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
412 };
413 
414 static const struct reg_field rk3576_vop_cluster_regs[VOP2_WIN_MAX_REG] = {
415 	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
416 	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
417 	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14),
418 	[VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 17, 17),
419 	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18),
420 	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31),
421 	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31),
422 	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31),
423 	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31),
424 	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31),
425 	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19),
426 	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15),
427 	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31),
428 	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8),
429 	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9),
430 	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11),
431 	[VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 4),
432 	[VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 9),
433 	/* Read only bit on rk3576, writing on this bit have no effect.*/
434 	[VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13),
435 
436 	[VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_CLUSTER_PORT_SEL_IMD, 0, 1),
437 	[VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_CLUSTER_DLY_NUM, 0, 7),
438 
439 	/* Scale */
440 	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15),
441 	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31),
442 	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3),
443 	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15),
444 	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 22, 23),
445 	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28),
446 	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29),
447 
448 	/* cluster regs */
449 	[VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1),
450 	[VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0),
451 	[VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7),
452 
453 	/* afbc regs */
454 	[VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6),
455 	[VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9),
456 	[VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10),
457 	[VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4),
458 	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7),
459 	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8),
460 	[VOP2_WIN_AFBC_PLD_OFFSET_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 16, 16),
461 	[VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31),
462 	[VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31),
463 	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15),
464 	[VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31),
465 	[VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31),
466 	[VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31),
467 	[VOP2_WIN_AFBC_PLD_OFFSET] = REG_FIELD(RK3576_CLUSTER_WIN_AFBCD_PLD_PTR_OFFSET, 0, 31),
468 	[VOP2_WIN_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_TRANSFORM_OFFSET, 0, 31),
469 	[VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0),
470 	[VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1),
471 	[VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2),
472 	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3),
473 	[VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff },
474 	[VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff },
475 	[VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
476 	[VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
477 	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
478 	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
479 	[VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff },
480 	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
481 	[VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
482 	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
483 	[VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff },
484 	[VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff },
485 };
486 
487 static const struct reg_field rk3576_vop_smart_regs[VOP2_WIN_MAX_REG] = {
488 	[VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0),
489 	[VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5),
490 	[VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12),
491 	[VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14),
492 	[VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16),
493 	[VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31),
494 	[VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31),
495 	[VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28),
496 	[VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31),
497 	[VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31),
498 	[VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17),
499 	[VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15),
500 	[VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31),
501 	[VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0),
502 	[VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1),
503 	[VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3),
504 	[VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31),
505 	[VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29),
506 	[VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31),
507 	[VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_SMART_PORT_SEL_IMD, 0, 1),
508 	[VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_SMART_DLY_NUM, 0, 7),
509 	[VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8),
510 	[VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16),
511 	[VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1),
512 
513 	/* Scale */
514 	[VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15),
515 	[VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31),
516 	[VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1),
517 	[VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3),
518 	[VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5),
519 	[VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7),
520 	[VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17),
521 	[VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8),
522 	[VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9),
523 	[VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10),
524 	[VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11),
525 	[VOP2_WIN_XMIRROR] = { .reg = 0xffffffff },
526 
527 	/* CBCR share the same scale factor as YRGB */
528 	[VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
529 	[VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
530 	[VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
531 	[VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff},
532 	[VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff},
533 	[VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff},
534 
535 	[VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff },
536 	[VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff },
537 	[VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff },
538 	[VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff },
539 	[VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff },
540 	[VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff },
541 	[VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff },
542 	[VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff },
543 	[VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff },
544 	[VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff },
545 	[VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff },
546 	[VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff },
547 	[VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff },
548 	[VOP2_WIN_TRANSFORM_OFFSET] = { .reg = 0xffffffff },
549 	[VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff },
550 	[VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff },
551 	[VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff },
552 	[VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
553 };
554 
555 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
556 	{
557 		.id = 0,
558 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
559 		.gamma_lut_len = 1024,
560 		.cubic_lut_len = 9 * 9 * 9,
561 		.max_output = { 4096, 2304 },
562 		.pre_scan_max_dly = { 69, 53, 53, 42 },
563 		.offset = 0xc00,
564 	}, {
565 		.id = 1,
566 		.gamma_lut_len = 1024,
567 		.max_output = { 2048, 1536 },
568 		.pre_scan_max_dly = { 40, 40, 40, 40 },
569 		.offset = 0xd00,
570 	}, {
571 		.id = 2,
572 		.gamma_lut_len = 1024,
573 		.max_output = { 1920, 1080 },
574 		.pre_scan_max_dly = { 40, 40, 40, 40 },
575 		.offset = 0xe00,
576 	},
577 };
578 
579 /*
580  * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
581  * Every cluster can work as 4K win or split into two win.
582  * All win in cluster support AFBCD.
583  *
584  * Every esmart win and smart win support 4 Multi-region.
585  *
586  * Scale filter mode:
587  *
588  * * Cluster:  bicubic for horizontal scale up, others use bilinear
589  * * ESmart:
590  *    * nearest-neighbor/bilinear/bicubic for scale up
591  *    * nearest-neighbor/bilinear/average for scale down
592  *
593  *
594  * @TODO describe the wind like cpu-map dt nodes;
595  */
596 static const struct vop2_win_data rk3568_vop_win_data[] = {
597 	{
598 		.name = "Smart0-win0",
599 		.phys_id = ROCKCHIP_VOP2_SMART0,
600 		.base = 0x1c00,
601 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
602 		.formats = formats_smart,
603 		.nformats = ARRAY_SIZE(formats_smart),
604 		.format_modifiers = format_modifiers,
605 		/* 0xf means this layer can't attached to this VP */
606 		.layer_sel_id = { 3, 3, 3, 0xf },
607 		.supported_rotations = DRM_MODE_REFLECT_Y,
608 		.type = DRM_PLANE_TYPE_PRIMARY,
609 		.max_upscale_factor = 8,
610 		.max_downscale_factor = 8,
611 		.dly = { 20, 47, 41 },
612 	}, {
613 		.name = "Smart1-win0",
614 		.phys_id = ROCKCHIP_VOP2_SMART1,
615 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
616 		.formats = formats_smart,
617 		.nformats = ARRAY_SIZE(formats_smart),
618 		.format_modifiers = format_modifiers,
619 		.base = 0x1e00,
620 		.layer_sel_id = { 7, 7, 7, 0xf },
621 		.supported_rotations = DRM_MODE_REFLECT_Y,
622 		.type = DRM_PLANE_TYPE_PRIMARY,
623 		.max_upscale_factor = 8,
624 		.max_downscale_factor = 8,
625 		.dly = { 20, 47, 41 },
626 	}, {
627 		.name = "Esmart1-win0",
628 		.phys_id = ROCKCHIP_VOP2_ESMART1,
629 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
630 		.formats = formats_rk356x_esmart,
631 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
632 		.format_modifiers = format_modifiers,
633 		.base = 0x1a00,
634 		.layer_sel_id = { 6, 6, 6, 0xf },
635 		.supported_rotations = DRM_MODE_REFLECT_Y,
636 		.type = DRM_PLANE_TYPE_PRIMARY,
637 		.max_upscale_factor = 8,
638 		.max_downscale_factor = 8,
639 		.dly = { 20, 47, 41 },
640 	}, {
641 		.name = "Esmart0-win0",
642 		.phys_id = ROCKCHIP_VOP2_ESMART0,
643 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
644 		.formats = formats_rk356x_esmart,
645 		.nformats = ARRAY_SIZE(formats_rk356x_esmart),
646 		.format_modifiers = format_modifiers,
647 		.base = 0x1800,
648 		.layer_sel_id = { 2, 2, 2, 0xf },
649 		.supported_rotations = DRM_MODE_REFLECT_Y,
650 		.type = DRM_PLANE_TYPE_PRIMARY,
651 		.max_upscale_factor = 8,
652 		.max_downscale_factor = 8,
653 		.dly = { 20, 47, 41 },
654 	}, {
655 		.name = "Cluster0-win0",
656 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
657 		.base = 0x1000,
658 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
659 		.formats = formats_cluster,
660 		.nformats = ARRAY_SIZE(formats_cluster),
661 		.format_modifiers = format_modifiers_afbc,
662 		.layer_sel_id = { 0, 0, 0, 0xf },
663 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
664 					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
665 		.max_upscale_factor = 4,
666 		.max_downscale_factor = 4,
667 		.dly = { 0, 27, 21 },
668 		.type = DRM_PLANE_TYPE_OVERLAY,
669 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
670 	}, {
671 		.name = "Cluster1-win0",
672 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
673 		.base = 0x1200,
674 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
675 		.formats = formats_cluster,
676 		.nformats = ARRAY_SIZE(formats_cluster),
677 		.format_modifiers = format_modifiers_afbc,
678 		.layer_sel_id = { 1, 1, 1, 0xf },
679 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
680 					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
681 		.type = DRM_PLANE_TYPE_OVERLAY,
682 		.max_upscale_factor = 4,
683 		.max_downscale_factor = 4,
684 		.dly = { 0, 27, 21 },
685 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
686 	},
687 };
688 
689 static const struct vop2_regs_dump rk3568_regs_dump[] = {
690 	{
691 		.name = "SYS",
692 		.base = RK3568_REG_CFG_DONE,
693 		.size = 0x100,
694 		.en_reg  = 0,
695 		.en_val = 0,
696 		.en_mask = 0
697 	}, {
698 		.name = "OVL",
699 		.base = RK3568_OVL_CTRL,
700 		.size = 0x100,
701 		.en_reg = 0,
702 		.en_val = 0,
703 		.en_mask = 0,
704 	}, {
705 		.name = "VP0",
706 		.base = RK3568_VP0_CTRL_BASE,
707 		.size = 0x100,
708 		.en_reg = RK3568_VP_DSP_CTRL,
709 		.en_val = 0,
710 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
711 	}, {
712 		.name = "VP1",
713 		.base = RK3568_VP1_CTRL_BASE,
714 		.size = 0x100,
715 		.en_reg = RK3568_VP_DSP_CTRL,
716 		.en_val = 0,
717 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
718 	}, {
719 		.name = "VP2",
720 		.base = RK3568_VP2_CTRL_BASE,
721 		.size = 0x100,
722 		.en_reg = RK3568_VP_DSP_CTRL,
723 		.en_val = 0,
724 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
725 
726 	}, {
727 		.name = "Cluster0",
728 		.base = RK3568_CLUSTER0_CTRL_BASE,
729 		.size = 0x110,
730 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
731 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
732 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
733 	}, {
734 		.name = "Cluster1",
735 		.base = RK3568_CLUSTER1_CTRL_BASE,
736 		.size = 0x110,
737 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
738 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
739 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
740 	}, {
741 		.name = "Esmart0",
742 		.base = RK3568_ESMART0_CTRL_BASE,
743 		.size = 0xf0,
744 		.en_reg = RK3568_SMART_REGION0_CTRL,
745 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
746 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
747 	}, {
748 		.name = "Esmart1",
749 		.base = RK3568_ESMART1_CTRL_BASE,
750 		.size = 0xf0,
751 		.en_reg = RK3568_SMART_REGION0_CTRL,
752 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
753 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
754 	}, {
755 		.name = "Smart0",
756 		.base = RK3568_SMART0_CTRL_BASE,
757 		.size = 0xf0,
758 		.en_reg = RK3568_SMART_REGION0_CTRL,
759 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
760 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
761 	}, {
762 		.name = "Smart1",
763 		.base = RK3568_SMART1_CTRL_BASE,
764 		.size = 0xf0,
765 		.en_reg = RK3568_SMART_REGION0_CTRL,
766 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
767 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
768 	},
769 };
770 
771 static const struct vop2_video_port_data rk3576_vop_video_ports[] = {
772 	{
773 		.id = 0,
774 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
775 		.gamma_lut_len = 1024,
776 		.cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
777 		.max_output = { 4096, 2304 },
778 		/* win layer_mix hdr  */
779 		.pre_scan_max_dly = { 10, 8, 2, 0 },
780 		.offset = 0xc00,
781 		.pixel_rate = 2,
782 	}, {
783 		.id = 1,
784 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
785 		.gamma_lut_len = 1024,
786 		.cubic_lut_len = 729, /* 9x9x9 */
787 		.max_output = { 2560, 1600 },
788 		/* win layer_mix hdr  */
789 		.pre_scan_max_dly = { 10, 6, 0, 0 },
790 		.offset = 0xd00,
791 		.pixel_rate = 1,
792 	}, {
793 		.id = 2,
794 		.gamma_lut_len = 1024,
795 		.max_output = { 1920, 1080 },
796 		/* win layer_mix hdr  */
797 		.pre_scan_max_dly = { 10, 6, 0, 0 },
798 		.offset = 0xe00,
799 		.pixel_rate = 1,
800 	},
801 };
802 
803 /*
804  * rk3576 vop with 2 cluster, 4 esmart win.
805  * Every cluster can work as 4K win or split into two 2K win.
806  * All win in cluster support AFBCD.
807  *
808  * Every esmart win support 4 Multi-region.
809  *
810  * VP0 can use Cluster0/1 and Esmart0/2
811  * VP1 can use Cluster0/1 and Esmart1/3
812  * VP2 can use Esmart0/1/2/3
813  *
814  * Scale filter mode:
815  *
816  * * Cluster:
817  * * Support prescale down:
818  * * H/V: gt2/avg2 or gt4/avg4
819  * * After prescale down:
820  *	* nearest-neighbor/bilinear/multi-phase filter for scale up
821  *	* nearest-neighbor/bilinear/multi-phase filter for scale down
822  *
823  * * Esmart:
824  * * Support prescale down:
825  * * H: gt2/avg2 or gt4/avg4
826  * * V: gt2 or gt4
827  * * After prescale down:
828  *	* nearest-neighbor/bilinear/bicubic for scale up
829  *	* nearest-neighbor/bilinear for scale down
830  *
831  * AXI config::
832  *
833  * * Cluster0 win0: 0xa,  0xb       [AXI0]
834  * * Cluster0 win1: 0xc,  0xd       [AXI0]
835  * * Cluster1 win0: 0x6,  0x7       [AXI0]
836  * * Cluster1 win1: 0x8,  0x9       [AXI0]
837  * * Esmart0:       0x10, 0x11      [AXI0]
838  * * Esmart1:       0x12, 0x13      [AXI0]
839  * * Esmart2:       0xa,  0xb       [AXI1]
840  * * Esmart3:       0xc,  0xd       [AXI1]
841  * * Lut dma rid:   0x1,  0x2,  0x3 [AXI0]
842  * * DCI dma rid:   0x4             [AXI0]
843  * * Metadata rid:  0x5             [AXI0]
844  *
845  * * Limit:
846  * * (1) Cluster0/1 are fixed on AXI0 by IC design
847  * * (2) 0x0 and 0xf can't be used;
848  * * (3) 5 Bits ID for eache axi bus
849  * * (3) cluster and lut/dci/metadata rid must smaller than 0xf,
850  * *     if Cluster rid is bigger than 0xf, VOP will dead at the
851  * *     system bandwidth very terrible scene.
852  */
853 static const struct vop2_win_data rk3576_vop_win_data[] = {
854 	{
855 		.name = "Cluster0-win0",
856 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
857 		.base = 0x1000,
858 		.possible_vp_mask = BIT(0) | BIT(1),
859 		.formats = formats_rk3576_cluster,
860 		.nformats = ARRAY_SIZE(formats_rk3576_cluster),
861 		.format_modifiers = format_modifiers_rk3576_afbc,
862 		.layer_sel_id = { 0, 0, 0xf, 0xf },
863 		.supported_rotations =  DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
864 		.type = DRM_PLANE_TYPE_PRIMARY,
865 		.axi_bus_id = 0,
866 		.axi_yrgb_r_id = 0xa,
867 		.axi_uv_r_id = 0xb,
868 		.max_upscale_factor = 4,
869 		.max_downscale_factor = 4,
870 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
871 	}, {
872 		.name = "Cluster1-win0",
873 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
874 		.base = 0x1200,
875 		.possible_vp_mask = BIT(0) | BIT(1),
876 		.formats = formats_rk3576_cluster,
877 		.nformats = ARRAY_SIZE(formats_rk3576_cluster),
878 		.format_modifiers = format_modifiers_rk3576_afbc,
879 		.layer_sel_id = { 1, 1, 0xf, 0xf },
880 		.supported_rotations =  DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
881 		.type = DRM_PLANE_TYPE_PRIMARY,
882 		.axi_bus_id = 0,
883 		.axi_yrgb_r_id = 6,
884 		.axi_uv_r_id = 7,
885 		.max_upscale_factor = 4,
886 		.max_downscale_factor = 4,
887 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
888 	}, {
889 		.name = "Esmart0-win0",
890 		.phys_id = ROCKCHIP_VOP2_ESMART0,
891 		.base = 0x1800,
892 		.possible_vp_mask = BIT(0) | BIT(2),
893 		.formats = formats_rk3576_esmart,
894 		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
895 		.format_modifiers = format_modifiers,
896 		.layer_sel_id = { 2, 0xf, 0, 0xf },
897 		.supported_rotations = DRM_MODE_REFLECT_Y,
898 		.type = DRM_PLANE_TYPE_OVERLAY,
899 		.axi_bus_id = 0,
900 		.axi_yrgb_r_id = 0x10,
901 		.axi_uv_r_id = 0x11,
902 		.max_upscale_factor = 8,
903 		.max_downscale_factor = 8,
904 	}, {
905 		.name = "Esmart1-win0",
906 		.phys_id = ROCKCHIP_VOP2_ESMART1,
907 		.base = 0x1a00,
908 		.possible_vp_mask = BIT(1) | BIT(2),
909 		.formats = formats_rk3576_esmart,
910 		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
911 		.format_modifiers = format_modifiers,
912 		.layer_sel_id = { 0xf, 2, 1, 0xf },
913 		.supported_rotations = DRM_MODE_REFLECT_Y,
914 		.type = DRM_PLANE_TYPE_OVERLAY,
915 		.axi_bus_id = 0,
916 		.axi_yrgb_r_id = 0x12,
917 		.axi_uv_r_id = 0x13,
918 		.max_upscale_factor = 8,
919 		.max_downscale_factor = 8,
920 	}, {
921 		.name = "Esmart2-win0",
922 		.phys_id = ROCKCHIP_VOP2_ESMART2,
923 		.base = 0x1c00,
924 		.possible_vp_mask = BIT(0) | BIT(2),
925 		.formats = formats_rk3576_esmart,
926 		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
927 		.format_modifiers = format_modifiers,
928 		.layer_sel_id = { 3, 0xf, 2, 0xf },
929 		.supported_rotations = DRM_MODE_REFLECT_Y,
930 		.type = DRM_PLANE_TYPE_OVERLAY,
931 		.axi_bus_id = 1,
932 		.axi_yrgb_r_id = 0x0a,
933 		.axi_uv_r_id = 0x0b,
934 		.max_upscale_factor = 8,
935 		.max_downscale_factor = 8,
936 	}, {
937 		.name = "Esmart3-win0",
938 		.phys_id = ROCKCHIP_VOP2_ESMART3,
939 		.base = 0x1e00,
940 		.possible_vp_mask = BIT(1) | BIT(2),
941 		.formats = formats_rk3576_esmart,
942 		.nformats = ARRAY_SIZE(formats_rk3576_esmart),
943 		.format_modifiers = format_modifiers,
944 		.layer_sel_id = { 0xf, 3, 3, 0xf },
945 		.supported_rotations = DRM_MODE_REFLECT_Y,
946 		.type = DRM_PLANE_TYPE_OVERLAY,
947 		.axi_bus_id = 1,
948 		.axi_yrgb_r_id = 0x0c,
949 		.axi_uv_r_id = 0x0d,
950 		.max_upscale_factor = 8,
951 		.max_downscale_factor = 8,
952 	},
953 };
954 
955 static const struct vop2_regs_dump rk3576_regs_dump[] = {
956 	{
957 		.name = "SYS",
958 		.base = RK3568_REG_CFG_DONE,
959 		.size = 0x200,
960 		.en_reg  = 0,
961 		.en_val = 0,
962 		.en_mask = 0
963 	}, {
964 		.name = "OVL_SYS",
965 		.base = RK3576_SYS_EXTRA_ALPHA_CTRL,
966 		.size = 0x50,
967 		.en_reg = 0,
968 		.en_val = 0,
969 		.en_mask = 0,
970 	}, {
971 		.name = "OVL_VP0",
972 		.base = RK3576_OVL_CTRL(0),
973 		.size = 0x80,
974 		.en_reg = 0,
975 		.en_val = 0,
976 		.en_mask = 0,
977 	}, {
978 		.name = "OVL_VP1",
979 		.base = RK3576_OVL_CTRL(1),
980 		.size = 0x80,
981 		.en_reg = 0,
982 		.en_val = 0,
983 		.en_mask = 0,
984 	}, {
985 		.name = "OVL_VP2",
986 		.base = RK3576_OVL_CTRL(2),
987 		.size = 0x80,
988 		.en_reg = 0,
989 		.en_val = 0,
990 		.en_mask = 0,
991 	}, {
992 		.name = "VP0",
993 		.base = RK3568_VP0_CTRL_BASE,
994 		.size = 0x100,
995 		.en_reg = RK3568_VP_DSP_CTRL,
996 		.en_val = 0,
997 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
998 	}, {
999 		.name = "VP1",
1000 		.base = RK3568_VP1_CTRL_BASE,
1001 		.size = 0x100,
1002 		.en_reg = RK3568_VP_DSP_CTRL,
1003 		.en_val = 0,
1004 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1005 	}, {
1006 		.name = "VP2",
1007 		.base = RK3568_VP2_CTRL_BASE,
1008 		.size = 0x100,
1009 		.en_reg = RK3568_VP_DSP_CTRL,
1010 		.en_val = 0,
1011 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1012 	}, {
1013 		.name = "Cluster0",
1014 		.base = RK3568_CLUSTER0_CTRL_BASE,
1015 		.size = 0x200,
1016 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
1017 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1018 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1019 	}, {
1020 		.name = "Cluster1",
1021 		.base = RK3568_CLUSTER1_CTRL_BASE,
1022 		.size = 0x200,
1023 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
1024 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1025 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1026 	}, {
1027 		.name = "Esmart0",
1028 		.base = RK3568_ESMART0_CTRL_BASE,
1029 		.size = 0xf0,
1030 		.en_reg = RK3568_SMART_REGION0_CTRL,
1031 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1032 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1033 	}, {
1034 		.name = "Esmart1",
1035 		.base = RK3568_ESMART1_CTRL_BASE,
1036 		.size = 0xf0,
1037 		.en_reg = RK3568_SMART_REGION0_CTRL,
1038 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1039 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1040 	}, {
1041 		.name = "Esmart2",
1042 		.base = RK3588_ESMART2_CTRL_BASE,
1043 		.size = 0xf0,
1044 		.en_reg = RK3568_SMART_REGION0_CTRL,
1045 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1046 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1047 	}, {
1048 		.name = "Esmart3",
1049 		.base = RK3588_ESMART3_CTRL_BASE,
1050 		.size = 0xf0,
1051 		.en_reg = RK3568_SMART_REGION0_CTRL,
1052 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1053 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1054 	},
1055 };
1056 
1057 static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
1058 	{
1059 		.id = 0,
1060 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
1061 		.gamma_lut_len = 1024,
1062 		.cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
1063 		.max_output = { 4096, 2304 },
1064 		/* hdr2sdr sdr2hdr hdr2hdr sdr2sdr */
1065 		.pre_scan_max_dly = { 76, 65, 65, 54 },
1066 		.offset = 0xc00,
1067 	}, {
1068 		.id = 1,
1069 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
1070 		.gamma_lut_len = 1024,
1071 		.cubic_lut_len = 729, /* 9x9x9 */
1072 		.max_output = { 4096, 2304 },
1073 		.pre_scan_max_dly = { 76, 65, 65, 54 },
1074 		.offset = 0xd00,
1075 	}, {
1076 		.id = 2,
1077 		.feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
1078 		.gamma_lut_len = 1024,
1079 		.cubic_lut_len = 17 * 17 * 17, /* 17x17x17 */
1080 		.max_output = { 4096, 2304 },
1081 		.pre_scan_max_dly = { 52, 52, 52, 52 },
1082 		.offset = 0xe00,
1083 	}, {
1084 		.id = 3,
1085 		.gamma_lut_len = 1024,
1086 		.max_output = { 2048, 1536 },
1087 		.pre_scan_max_dly = { 52, 52, 52, 52 },
1088 		.offset = 0xf00,
1089 	},
1090 };
1091 
1092 /*
1093  * rk3588 vop with 4 cluster, 4 esmart win.
1094  * Every cluster can work as 4K win or split into two win.
1095  * All win in cluster support AFBCD.
1096  *
1097  * Every esmart win and smart win support 4 Multi-region.
1098  *
1099  * Scale filter mode:
1100  *
1101  * * Cluster:  bicubic for horizontal scale up, others use bilinear
1102  * * ESmart:
1103  *    * nearest-neighbor/bilinear/bicubic for scale up
1104  *    * nearest-neighbor/bilinear/average for scale down
1105  *
1106  * AXI Read ID assignment:
1107  * Two AXI bus:
1108  * AXI0 is a read/write bus with a higher performance.
1109  * AXI1 is a read only bus.
1110  *
1111  * Every window on a AXI bus must assigned two unique
1112  * read id(yrgb_r_id/uv_r_id, valid id are 0x1~0xe).
1113  *
1114  * AXI0:
1115  * Cluster0/1, Esmart0/1, WriteBack
1116  *
1117  * AXI 1:
1118  * Cluster2/3, Esmart2/3
1119  *
1120  */
1121 static const struct vop2_win_data rk3588_vop_win_data[] = {
1122 	{
1123 		.name = "Cluster0-win0",
1124 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
1125 		.base = 0x1000,
1126 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1127 		.formats = formats_cluster,
1128 		.nformats = ARRAY_SIZE(formats_cluster),
1129 		.format_modifiers = format_modifiers_afbc,
1130 		.layer_sel_id = { 0, 0, 0, 0 },
1131 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1132 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1133 		.axi_bus_id = 0,
1134 		.axi_yrgb_r_id = 2,
1135 		.axi_uv_r_id = 3,
1136 		.max_upscale_factor = 4,
1137 		.max_downscale_factor = 4,
1138 		.dly = { 4, 26, 29 },
1139 		.type = DRM_PLANE_TYPE_PRIMARY,
1140 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1141 	}, {
1142 		.name = "Cluster1-win0",
1143 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
1144 		.base = 0x1200,
1145 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1146 		.formats = formats_cluster,
1147 		.nformats = ARRAY_SIZE(formats_cluster),
1148 		.format_modifiers = format_modifiers_afbc,
1149 		.layer_sel_id = { 1, 1, 1, 1 },
1150 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1151 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1152 		.type = DRM_PLANE_TYPE_PRIMARY,
1153 		.axi_bus_id = 0,
1154 		.axi_yrgb_r_id = 6,
1155 		.axi_uv_r_id = 7,
1156 		.max_upscale_factor = 4,
1157 		.max_downscale_factor = 4,
1158 		.dly = { 4, 26, 29 },
1159 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1160 	}, {
1161 		.name = "Cluster2-win0",
1162 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
1163 		.base = 0x1400,
1164 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1165 		.formats = formats_cluster,
1166 		.nformats = ARRAY_SIZE(formats_cluster),
1167 		.format_modifiers = format_modifiers_afbc,
1168 		.layer_sel_id = { 4, 4, 4, 4 },
1169 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1170 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1171 		.type = DRM_PLANE_TYPE_PRIMARY,
1172 		.axi_bus_id = 1,
1173 		.axi_yrgb_r_id = 2,
1174 		.axi_uv_r_id = 3,
1175 		.max_upscale_factor = 4,
1176 		.max_downscale_factor = 4,
1177 		.dly = { 4, 26, 29 },
1178 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1179 	}, {
1180 		.name = "Cluster3-win0",
1181 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
1182 		.base = 0x1600,
1183 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1184 		.formats = formats_cluster,
1185 		.nformats = ARRAY_SIZE(formats_cluster),
1186 		.format_modifiers = format_modifiers_afbc,
1187 		.layer_sel_id =  { 5, 5, 5, 5 },
1188 		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1189 				       DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1190 		.type = DRM_PLANE_TYPE_PRIMARY,
1191 		.axi_bus_id = 1,
1192 		.axi_yrgb_r_id = 6,
1193 		.axi_uv_r_id = 7,
1194 		.max_upscale_factor = 4,
1195 		.max_downscale_factor = 4,
1196 		.dly = { 4, 26, 29 },
1197 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1198 	}, {
1199 		.name = "Esmart0-win0",
1200 		.phys_id = ROCKCHIP_VOP2_ESMART0,
1201 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1202 		.formats = formats_esmart,
1203 		.nformats = ARRAY_SIZE(formats_esmart),
1204 		.format_modifiers = format_modifiers,
1205 		.base = 0x1800,
1206 		.layer_sel_id = { 2, 2, 2, 2 },
1207 		.supported_rotations = DRM_MODE_REFLECT_Y,
1208 		.type = DRM_PLANE_TYPE_OVERLAY,
1209 		.axi_bus_id = 0,
1210 		.axi_yrgb_r_id = 0x0a,
1211 		.axi_uv_r_id = 0x0b,
1212 		.max_upscale_factor = 8,
1213 		.max_downscale_factor = 8,
1214 		.dly = { 23, 45, 48 },
1215 	}, {
1216 		.name = "Esmart1-win0",
1217 		.phys_id = ROCKCHIP_VOP2_ESMART1,
1218 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1219 		.formats = formats_esmart,
1220 		.nformats = ARRAY_SIZE(formats_esmart),
1221 		.format_modifiers = format_modifiers,
1222 		.base = 0x1a00,
1223 		.layer_sel_id = { 3, 3, 3, 3 },
1224 		.supported_rotations = DRM_MODE_REFLECT_Y,
1225 		.type = DRM_PLANE_TYPE_OVERLAY,
1226 		.axi_bus_id = 0,
1227 		.axi_yrgb_r_id = 0x0c,
1228 		.axi_uv_r_id = 0x01,
1229 		.max_upscale_factor = 8,
1230 		.max_downscale_factor = 8,
1231 		.dly = { 23, 45, 48 },
1232 	}, {
1233 		.name = "Esmart2-win0",
1234 		.phys_id = ROCKCHIP_VOP2_ESMART2,
1235 		.base = 0x1c00,
1236 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1237 		.formats = formats_esmart,
1238 		.nformats = ARRAY_SIZE(formats_esmart),
1239 		.format_modifiers = format_modifiers,
1240 		.layer_sel_id =  { 6, 6, 6, 6 },
1241 		.supported_rotations = DRM_MODE_REFLECT_Y,
1242 		.type = DRM_PLANE_TYPE_OVERLAY,
1243 		.axi_bus_id = 1,
1244 		.axi_yrgb_r_id = 0x0a,
1245 		.axi_uv_r_id = 0x0b,
1246 		.max_upscale_factor = 8,
1247 		.max_downscale_factor = 8,
1248 		.dly = { 23, 45, 48 },
1249 	}, {
1250 		.name = "Esmart3-win0",
1251 		.phys_id = ROCKCHIP_VOP2_ESMART3,
1252 		.possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1253 		.formats = formats_esmart,
1254 		.nformats = ARRAY_SIZE(formats_esmart),
1255 		.format_modifiers = format_modifiers,
1256 		.base = 0x1e00,
1257 		.layer_sel_id =  { 7, 7, 7, 7 },
1258 		.supported_rotations = DRM_MODE_REFLECT_Y,
1259 		.type = DRM_PLANE_TYPE_OVERLAY,
1260 		.axi_bus_id = 1,
1261 		.axi_yrgb_r_id = 0x0c,
1262 		.axi_uv_r_id = 0x0d,
1263 		.max_upscale_factor = 8,
1264 		.max_downscale_factor = 8,
1265 		.dly = { 23, 45, 48 },
1266 	},
1267 };
1268 
1269 static const struct vop2_regs_dump rk3588_regs_dump[] = {
1270 	{
1271 		.name = "SYS",
1272 		.base = RK3568_REG_CFG_DONE,
1273 		.size = 0x100,
1274 		.en_reg  = 0,
1275 		.en_val = 0,
1276 		.en_mask = 0
1277 	}, {
1278 		.name = "OVL",
1279 		.base = RK3568_OVL_CTRL,
1280 		.size = 0x100,
1281 		.en_reg = 0,
1282 		.en_val = 0,
1283 		.en_mask = 0,
1284 	}, {
1285 		.name = "VP0",
1286 		.base = RK3568_VP0_CTRL_BASE,
1287 		.size = 0x100,
1288 		.en_reg = RK3568_VP_DSP_CTRL,
1289 		.en_val = 0,
1290 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1291 	}, {
1292 		.name = "VP1",
1293 		.base = RK3568_VP1_CTRL_BASE,
1294 		.size = 0x100,
1295 		.en_reg = RK3568_VP_DSP_CTRL,
1296 		.en_val = 0,
1297 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1298 	}, {
1299 		.name = "VP2",
1300 		.base = RK3568_VP2_CTRL_BASE,
1301 		.size = 0x100,
1302 		.en_reg = RK3568_VP_DSP_CTRL,
1303 		.en_val = 0,
1304 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1305 
1306 	}, {
1307 		.name = "VP3",
1308 		.base = RK3588_VP3_CTRL_BASE,
1309 		.size = 0x100,
1310 		.en_reg = RK3568_VP_DSP_CTRL,
1311 		.en_val = 0,
1312 		.en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1313 	}, {
1314 		.name = "Cluster0",
1315 		.base = RK3568_CLUSTER0_CTRL_BASE,
1316 		.size = 0x110,
1317 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
1318 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1319 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1320 	}, {
1321 		.name = "Cluster1",
1322 		.base = RK3568_CLUSTER1_CTRL_BASE,
1323 		.size = 0x110,
1324 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
1325 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1326 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1327 	}, {
1328 		.name = "Cluster2",
1329 		.base = RK3588_CLUSTER2_CTRL_BASE,
1330 		.size = 0x110,
1331 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
1332 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1333 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1334 	}, {
1335 		.name = "Cluster3",
1336 		.base = RK3588_CLUSTER3_CTRL_BASE,
1337 		.size = 0x110,
1338 		.en_reg = RK3568_CLUSTER_WIN_CTRL0,
1339 		.en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1340 		.en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1341 	}, {
1342 		.name = "Esmart0",
1343 		.base = RK3568_ESMART0_CTRL_BASE,
1344 		.size = 0xf0,
1345 		.en_reg = RK3568_SMART_REGION0_CTRL,
1346 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1347 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1348 	}, {
1349 		.name = "Esmart1",
1350 		.base = RK3568_ESMART1_CTRL_BASE,
1351 		.size = 0xf0,
1352 		.en_reg = RK3568_SMART_REGION0_CTRL,
1353 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1354 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1355 	}, {
1356 		.name = "Esmart2",
1357 		.base = RK3588_ESMART2_CTRL_BASE,
1358 		.size = 0xf0,
1359 		.en_reg = RK3568_SMART_REGION0_CTRL,
1360 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1361 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1362 	}, {
1363 		.name = "Esmart3",
1364 		.base = RK3588_ESMART3_CTRL_BASE,
1365 		.size = 0xf0,
1366 		.en_reg = RK3568_SMART_REGION0_CTRL,
1367 		.en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1368 		.en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1369 	},
1370 };
1371 
1372 static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
1373 {
1374 	struct vop2 *vop2 = vp->vop2;
1375 	struct drm_crtc *crtc = &vp->crtc;
1376 	u32 die, dip;
1377 
1378 	die = vop2_readl(vop2, RK3568_DSP_IF_EN);
1379 	dip = vop2_readl(vop2, RK3568_DSP_IF_POL);
1380 
1381 	switch (id) {
1382 	case ROCKCHIP_VOP2_EP_RGB0:
1383 		die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX;
1384 		die |= RK3568_SYS_DSP_INFACE_EN_RGB |
1385 			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id);
1386 		dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1387 		dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1388 		if (polflags & POLFLAG_DCLK_INV)
1389 			regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3));
1390 		else
1391 			regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16));
1392 		break;
1393 	case ROCKCHIP_VOP2_EP_HDMI0:
1394 		die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX;
1395 		die |= RK3568_SYS_DSP_INFACE_EN_HDMI |
1396 			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id);
1397 		dip &= ~RK3568_DSP_IF_POL__HDMI_PIN_POL;
1398 		dip |= FIELD_PREP(RK3568_DSP_IF_POL__HDMI_PIN_POL, polflags);
1399 		break;
1400 	case ROCKCHIP_VOP2_EP_EDP0:
1401 		die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX;
1402 		die |= RK3568_SYS_DSP_INFACE_EN_EDP |
1403 			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id);
1404 		dip &= ~RK3568_DSP_IF_POL__EDP_PIN_POL;
1405 		dip |= FIELD_PREP(RK3568_DSP_IF_POL__EDP_PIN_POL, polflags);
1406 		break;
1407 	case ROCKCHIP_VOP2_EP_MIPI0:
1408 		die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX;
1409 		die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 |
1410 			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id);
1411 		dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL;
1412 		dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags);
1413 		break;
1414 	case ROCKCHIP_VOP2_EP_MIPI1:
1415 		die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX;
1416 		die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 |
1417 			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id);
1418 		dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL;
1419 		dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags);
1420 		break;
1421 	case ROCKCHIP_VOP2_EP_LVDS0:
1422 		die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX;
1423 		die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 |
1424 			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id);
1425 		dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1426 		dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1427 		break;
1428 	case ROCKCHIP_VOP2_EP_LVDS1:
1429 		die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX;
1430 		die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 |
1431 			   FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id);
1432 		dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1433 		dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1434 		break;
1435 	default:
1436 		drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
1437 		return 0;
1438 	}
1439 
1440 	dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
1441 
1442 	vop2_writel(vop2, RK3568_DSP_IF_EN, die);
1443 	vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
1444 
1445 	return crtc->state->adjusted_mode.crtc_clock  * 1000LL;
1446 }
1447 
1448 static unsigned long rk3576_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
1449 {
1450 	struct vop2 *vop2 = vp->vop2;
1451 	struct drm_crtc *crtc = &vp->crtc;
1452 	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1453 	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1454 	u8 port_pix_rate = vp->data->pixel_rate;
1455 	int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_sel;
1456 	u32 ctrl, vp_clk_div, reg, dclk_div;
1457 	unsigned long dclk_in_rate, dclk_core_rate;
1458 
1459 	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420 || adjusted_mode->crtc_clock > 600000)
1460 		dclk_div = 2;
1461 	else
1462 		dclk_div = 1;
1463 
1464 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
1465 		dclk_core_rate = adjusted_mode->crtc_clock / 2;
1466 	else
1467 		dclk_core_rate = adjusted_mode->crtc_clock / port_pix_rate;
1468 
1469 	dclk_in_rate = adjusted_mode->crtc_clock / dclk_div;
1470 
1471 	dclk_core_div = dclk_in_rate > dclk_core_rate ? 1 : 0;
1472 
1473 	if (vop2_output_if_is_edp(id))
1474 		if_pixclk_div = port_pix_rate == 2 ? RK3576_DSP_IF_PCLK_DIV : 0;
1475 	else
1476 		if_pixclk_div = port_pix_rate == 1 ? RK3576_DSP_IF_PCLK_DIV : 0;
1477 
1478 	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
1479 		if_dclk_sel = RK3576_DSP_IF_DCLK_SEL_OUT;
1480 		dclk_out_div = 1;
1481 	} else {
1482 		if_dclk_sel = 0;
1483 		dclk_out_div = 0;
1484 	}
1485 
1486 	switch (id) {
1487 	case ROCKCHIP_VOP2_EP_HDMI0:
1488 		reg = RK3576_HDMI0_IF_CTRL;
1489 		break;
1490 	case ROCKCHIP_VOP2_EP_EDP0:
1491 		reg = RK3576_EDP0_IF_CTRL;
1492 		break;
1493 	case ROCKCHIP_VOP2_EP_MIPI0:
1494 		reg = RK3576_MIPI0_IF_CTRL;
1495 		break;
1496 	case ROCKCHIP_VOP2_EP_DP0:
1497 		reg = RK3576_DP0_IF_CTRL;
1498 		break;
1499 	case ROCKCHIP_VOP2_EP_DP1:
1500 		reg = RK3576_DP1_IF_CTRL;
1501 		break;
1502 	default:
1503 		drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
1504 		return 0;
1505 	}
1506 
1507 	ctrl = vop2_readl(vop2, reg);
1508 	ctrl &= ~RK3576_DSP_IF_DCLK_SEL_OUT;
1509 	ctrl &= ~RK3576_DSP_IF_PCLK_DIV;
1510 	ctrl &= ~RK3576_DSP_IF_MUX;
1511 	ctrl |= RK3576_DSP_IF_CFG_DONE_IMD;
1512 	ctrl |= if_dclk_sel | if_pixclk_div;
1513 	ctrl |= RK3576_DSP_IF_CLK_OUT_EN | RK3576_DSP_IF_EN;
1514 	ctrl |= FIELD_PREP(RK3576_DSP_IF_MUX, vp->id);
1515 	ctrl |= FIELD_PREP(RK3576_DSP_IF_PIN_POL, polflags);
1516 	vop2_writel(vop2, reg, ctrl);
1517 
1518 	vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div);
1519 	vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div);
1520 
1521 	vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div);
1522 
1523 	return dclk_in_rate * 1000LL;
1524 }
1525 
1526 /*
1527  * calc the dclk on rk3588
1528  * the available div of dclk is 1, 2, 4
1529  */
1530 static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
1531 {
1532 	if (child_clk * 4 <= max_dclk)
1533 		return child_clk * 4;
1534 	else if (child_clk * 2 <= max_dclk)
1535 		return child_clk * 2;
1536 	else if (child_clk <= max_dclk)
1537 		return child_clk;
1538 	else
1539 		return 0;
1540 }
1541 
1542 /*
1543  * 4 pixclk/cycle on rk3588
1544  * RGB/eDP/HDMI: if_pixclk >= dclk_core
1545  * DP: dp_pixclk = dclk_out <= dclk_core
1546  * DSI: mipi_pixclk <= dclk_out <= dclk_core
1547  */
1548 static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id,
1549 					 int *dclk_core_div, int *dclk_out_div,
1550 					 int *if_pixclk_div, int *if_dclk_div)
1551 {
1552 	struct vop2 *vop2 = vp->vop2;
1553 	struct drm_crtc *crtc = &vp->crtc;
1554 	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1555 	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1556 	int output_mode = vcstate->output_mode;
1557 	unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */
1558 	unsigned long dclk_core_rate = v_pixclk >> 2;
1559 	unsigned long dclk_rate = v_pixclk;
1560 	unsigned long dclk_out_rate;
1561 	unsigned long if_pixclk_rate;
1562 	int K = 1;
1563 
1564 	if (vop2_output_if_is_hdmi(id)) {
1565 		/*
1566 		 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
1567 		 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
1568 		 */
1569 		if (output_mode == ROCKCHIP_OUT_MODE_YUV420) {
1570 			dclk_rate = dclk_rate >> 1;
1571 			K = 2;
1572 		}
1573 
1574 		/*
1575 		 * if_pixclk_rate = (dclk_core_rate << 1) / K;
1576 		 * if_dclk_rate = dclk_core_rate / K;
1577 		 * *if_pixclk_div = dclk_rate / if_pixclk_rate;
1578 		 * *if_dclk_div = dclk_rate / if_dclk_rate;
1579 		 */
1580 		*if_pixclk_div = 2;
1581 		*if_dclk_div = 4;
1582 	} else if (vop2_output_if_is_edp(id)) {
1583 		/*
1584 		 * edp_pixclk = edp_dclk > dclk_core
1585 		 */
1586 		if_pixclk_rate = v_pixclk / K;
1587 		dclk_rate = if_pixclk_rate * K;
1588 		/*
1589 		 * *if_pixclk_div = dclk_rate / if_pixclk_rate;
1590 		 * *if_dclk_div = *if_pixclk_div;
1591 		 */
1592 		*if_pixclk_div = K;
1593 		*if_dclk_div = K;
1594 	} else if (vop2_output_if_is_dp(id)) {
1595 		if (output_mode == ROCKCHIP_OUT_MODE_YUV420)
1596 			dclk_out_rate = v_pixclk >> 3;
1597 		else
1598 			dclk_out_rate = v_pixclk >> 2;
1599 
1600 		dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000);
1601 		if (!dclk_rate) {
1602 			drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld Hz\n",
1603 				dclk_out_rate);
1604 			return 0;
1605 		}
1606 		*dclk_out_div = dclk_rate / dclk_out_rate;
1607 	} else if (vop2_output_if_is_mipi(id)) {
1608 		if_pixclk_rate = dclk_core_rate / K;
1609 		/*
1610 		 * dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4
1611 		 */
1612 		dclk_out_rate = if_pixclk_rate;
1613 		/*
1614 		 * dclk_rate = N * dclk_core_rate N = (1,2,4 ),
1615 		 * we get a little factor here
1616 		 */
1617 		dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000);
1618 		if (!dclk_rate) {
1619 			drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld Hz\n",
1620 				dclk_out_rate);
1621 			return 0;
1622 		}
1623 		*dclk_out_div = dclk_rate / dclk_out_rate;
1624 		/*
1625 		 * mipi pixclk == dclk_out
1626 		 */
1627 		*if_pixclk_div = 1;
1628 	} else if (vop2_output_if_is_dpi(id)) {
1629 		dclk_rate = v_pixclk;
1630 	}
1631 
1632 	*dclk_core_div = dclk_rate / dclk_core_rate;
1633 	*if_pixclk_div = ilog2(*if_pixclk_div);
1634 	*if_dclk_div = ilog2(*if_dclk_div);
1635 	*dclk_core_div = ilog2(*dclk_core_div);
1636 	*dclk_out_div = ilog2(*dclk_out_div);
1637 
1638 	drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n",
1639 		dclk_rate, *if_pixclk_div, *if_dclk_div);
1640 
1641 	return dclk_rate;
1642 }
1643 
1644 /*
1645  * MIPI port mux on rk3588:
1646  * 0: Video Port2
1647  * 1: Video Port3
1648  * 3: Video Port 1(MIPI1 only)
1649  */
1650 static u32 rk3588_get_mipi_port_mux(int vp_id)
1651 {
1652 	if (vp_id == 1)
1653 		return 3;
1654 	else if (vp_id == 3)
1655 		return 1;
1656 	else
1657 		return 0;
1658 }
1659 
1660 static u32 rk3588_get_hdmi_pol(u32 flags)
1661 {
1662 	u32 val;
1663 
1664 	val = (flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
1665 	val |= (flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
1666 
1667 	return val;
1668 }
1669 
1670 static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
1671 {
1672 	struct vop2 *vop2 = vp->vop2;
1673 	int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_div;
1674 	unsigned long clock;
1675 	u32 die, dip, div, vp_clk_div, val;
1676 
1677 	clock = rk3588_calc_cru_cfg(vp, id, &dclk_core_div, &dclk_out_div,
1678 				    &if_pixclk_div, &if_dclk_div);
1679 	if (!clock)
1680 		return 0;
1681 
1682 	vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div);
1683 	vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div);
1684 
1685 	die = vop2_readl(vop2, RK3568_DSP_IF_EN);
1686 	dip = vop2_readl(vop2, RK3568_DSP_IF_POL);
1687 	div = vop2_readl(vop2, RK3568_DSP_IF_CTRL);
1688 
1689 	switch (id) {
1690 	case ROCKCHIP_VOP2_EP_HDMI0:
1691 		div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV;
1692 		div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV;
1693 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
1694 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
1695 		die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX;
1696 		die |= RK3588_SYS_DSP_INFACE_EN_HDMI0 |
1697 			    FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id);
1698 		val = rk3588_get_hdmi_pol(polflags);
1699 		regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(1), 1));
1700 		regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0,
1701 			     FIELD_PREP_WM16(GENMASK(6, 5), val));
1702 		break;
1703 	case ROCKCHIP_VOP2_EP_HDMI1:
1704 		div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV;
1705 		div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV;
1706 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV, if_dclk_div);
1707 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV, if_pixclk_div);
1708 		die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX;
1709 		die |= RK3588_SYS_DSP_INFACE_EN_HDMI1 |
1710 			    FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id);
1711 		val = rk3588_get_hdmi_pol(polflags);
1712 		regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(4), 1));
1713 		regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0,
1714 			     FIELD_PREP_WM16(GENMASK(8, 7), val));
1715 		break;
1716 	case ROCKCHIP_VOP2_EP_EDP0:
1717 		div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV;
1718 		div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV;
1719 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
1720 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
1721 		die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX;
1722 		die |= RK3588_SYS_DSP_INFACE_EN_EDP0 |
1723 			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id);
1724 		regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(0), 1));
1725 		break;
1726 	case ROCKCHIP_VOP2_EP_EDP1:
1727 		div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV;
1728 		div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV;
1729 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
1730 		div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
1731 		die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX;
1732 		die |= RK3588_SYS_DSP_INFACE_EN_EDP1 |
1733 			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id);
1734 		regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(3), 1));
1735 		break;
1736 	case ROCKCHIP_VOP2_EP_MIPI0:
1737 		div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV;
1738 		div |= FIELD_PREP(RK3588_DSP_IF_MIPI0_PCLK_DIV, if_pixclk_div);
1739 		die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX;
1740 		val = rk3588_get_mipi_port_mux(vp->id);
1741 		die |= RK3588_SYS_DSP_INFACE_EN_MIPI0 |
1742 			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX, !!val);
1743 		break;
1744 	case ROCKCHIP_VOP2_EP_MIPI1:
1745 		div &= ~RK3588_DSP_IF_MIPI1_PCLK_DIV;
1746 		div |= FIELD_PREP(RK3588_DSP_IF_MIPI1_PCLK_DIV, if_pixclk_div);
1747 		die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX;
1748 		val = rk3588_get_mipi_port_mux(vp->id);
1749 		die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 |
1750 			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, val);
1751 		break;
1752 	case ROCKCHIP_VOP2_EP_DP0:
1753 		die &= ~RK3588_SYS_DSP_INFACE_EN_DP0_MUX;
1754 		die |= RK3588_SYS_DSP_INFACE_EN_DP0 |
1755 			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id);
1756 		dip &= ~RK3588_DSP_IF_POL__DP0_PIN_POL;
1757 		dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags);
1758 		break;
1759 	case ROCKCHIP_VOP2_EP_DP1:
1760 		die &= ~RK3588_SYS_DSP_INFACE_EN_DP1_MUX;
1761 		die |= RK3588_SYS_DSP_INFACE_EN_DP1 |
1762 			   FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP1_MUX, vp->id);
1763 		dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL;
1764 		dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags);
1765 		break;
1766 	default:
1767 		drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
1768 		return 0;
1769 	}
1770 
1771 	dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
1772 
1773 	vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div);
1774 	vop2_writel(vop2, RK3568_DSP_IF_EN, die);
1775 	vop2_writel(vop2, RK3568_DSP_IF_CTRL, div);
1776 	vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
1777 
1778 	return clock;
1779 }
1780 
1781 static bool is_opaque(u16 alpha)
1782 {
1783 	return (alpha >> 8) == 0xff;
1784 }
1785 
1786 static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config,
1787 			     struct vop2_alpha *alpha)
1788 {
1789 	int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1;
1790 	int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1;
1791 	int src_color_mode = alpha_config->src_premulti_en ?
1792 				ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
1793 	int dst_color_mode = alpha_config->dst_premulti_en ?
1794 				ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
1795 
1796 	alpha->src_color_ctrl.val = 0;
1797 	alpha->dst_color_ctrl.val = 0;
1798 	alpha->src_alpha_ctrl.val = 0;
1799 	alpha->dst_alpha_ctrl.val = 0;
1800 
1801 	if (!alpha_config->src_pixel_alpha_en)
1802 		alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
1803 	else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en)
1804 		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX;
1805 	else
1806 		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
1807 
1808 	alpha->src_color_ctrl.bits.alpha_en = 1;
1809 
1810 	if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) {
1811 		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
1812 		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
1813 	} else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) {
1814 		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
1815 		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE;
1816 	} else {
1817 		alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
1818 		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
1819 	}
1820 	alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8;
1821 	alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1822 	alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1823 
1824 	alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1825 	alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1826 	alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
1827 	alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8;
1828 	alpha->dst_color_ctrl.bits.color_mode = dst_color_mode;
1829 	alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
1830 
1831 	alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1832 	alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode;
1833 	alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1834 	alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE;
1835 
1836 	alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1837 	if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en)
1838 		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX;
1839 	else
1840 		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
1841 	alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
1842 	alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
1843 }
1844 
1845 static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id)
1846 {
1847 	struct vop2_video_port *vp;
1848 	int used_layer = 0;
1849 	int i;
1850 
1851 	for (i = 0; i < port_id; i++) {
1852 		vp = &vop2->vps[i];
1853 		used_layer += hweight32(vp->win_mask);
1854 	}
1855 
1856 	return used_layer;
1857 }
1858 
1859 static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win)
1860 {
1861 	struct vop2_alpha_config alpha_config;
1862 	struct vop2_alpha alpha;
1863 	struct drm_plane_state *bottom_win_pstate;
1864 	bool src_pixel_alpha_en = false;
1865 	u16 src_glb_alpha_val, dst_glb_alpha_val;
1866 	u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg;
1867 	u32 offset = 0;
1868 	bool premulti_en = false;
1869 	bool swap = false;
1870 
1871 	/* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
1872 	bottom_win_pstate = main_win->base.state;
1873 	src_glb_alpha_val = 0;
1874 	dst_glb_alpha_val = main_win->base.state->alpha;
1875 
1876 	if (!bottom_win_pstate->fb)
1877 		return;
1878 
1879 	alpha_config.src_premulti_en = premulti_en;
1880 	alpha_config.dst_premulti_en = false;
1881 	alpha_config.src_pixel_alpha_en = src_pixel_alpha_en;
1882 	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
1883 	alpha_config.src_glb_alpha_value = src_glb_alpha_val;
1884 	alpha_config.dst_glb_alpha_value = dst_glb_alpha_val;
1885 	vop2_parse_alpha(&alpha_config, &alpha);
1886 
1887 	alpha.src_color_ctrl.bits.src_dst_swap = swap;
1888 
1889 	switch (main_win->data->phys_id) {
1890 	case ROCKCHIP_VOP2_CLUSTER0:
1891 		offset = 0x0;
1892 		break;
1893 	case ROCKCHIP_VOP2_CLUSTER1:
1894 		offset = 0x10;
1895 		break;
1896 	case ROCKCHIP_VOP2_CLUSTER2:
1897 		offset = 0x20;
1898 		break;
1899 	case ROCKCHIP_VOP2_CLUSTER3:
1900 		offset = 0x30;
1901 		break;
1902 	}
1903 
1904 	if (vop2->version <= VOP_VERSION_RK3588) {
1905 		src_color_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL;
1906 		dst_color_ctrl_reg = RK3568_CLUSTER0_MIX_DST_COLOR_CTRL;
1907 		src_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL;
1908 		dst_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL;
1909 	} else {
1910 		src_color_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL;
1911 		dst_color_ctrl_reg = RK3576_CLUSTER0_MIX_DST_COLOR_CTRL;
1912 		src_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL;
1913 		dst_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL;
1914 	}
1915 
1916 	vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val);
1917 	vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val);
1918 	vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val);
1919 	vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val);
1920 }
1921 
1922 static void vop2_setup_alpha(struct vop2_video_port *vp)
1923 {
1924 	struct vop2 *vop2 = vp->vop2;
1925 	struct drm_framebuffer *fb;
1926 	struct vop2_alpha_config alpha_config;
1927 	struct vop2_alpha alpha;
1928 	struct drm_plane *plane;
1929 	int pixel_alpha_en;
1930 	int premulti_en, gpremulti_en = 0;
1931 	int mixer_id;
1932 	u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg;
1933 	u32 offset;
1934 	bool bottom_layer_alpha_en = false;
1935 	u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE;
1936 
1937 	if (vop2->version <= VOP_VERSION_RK3588)
1938 		mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
1939 	else
1940 		mixer_id = 0;
1941 
1942 	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
1943 
1944 	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
1945 		struct vop2_win *win = to_vop2_win(plane);
1946 
1947 		if (plane->state->normalized_zpos == 0 &&
1948 		    !is_opaque(plane->state->alpha) &&
1949 		    !vop2_cluster_window(win)) {
1950 			/*
1951 			 * If bottom layer have global alpha effect [except cluster layer,
1952 			 * because cluster have deal with bottom layer global alpha value
1953 			 * at cluster mix], bottom layer mix need deal with global alpha.
1954 			 */
1955 			bottom_layer_alpha_en = true;
1956 			dst_global_alpha = plane->state->alpha;
1957 		}
1958 	}
1959 
1960 	if (vop2->version <= VOP_VERSION_RK3588) {
1961 		src_color_ctrl_reg = RK3568_MIX0_SRC_COLOR_CTRL;
1962 		dst_color_ctrl_reg = RK3568_MIX0_DST_COLOR_CTRL;
1963 		src_alpha_ctrl_reg = RK3568_MIX0_SRC_ALPHA_CTRL;
1964 		dst_alpha_ctrl_reg = RK3568_MIX0_DST_ALPHA_CTRL;
1965 	} else {
1966 		src_color_ctrl_reg = RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp->id);
1967 		dst_color_ctrl_reg = RK3576_OVL_MIX0_DST_COLOR_CTRL(vp->id);
1968 		src_alpha_ctrl_reg = RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp->id);
1969 		dst_alpha_ctrl_reg = RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp->id);
1970 	}
1971 
1972 	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
1973 		struct vop2_win *win = to_vop2_win(plane);
1974 		int zpos = plane->state->normalized_zpos;
1975 
1976 		/*
1977 		 * Need to configure alpha from second layer.
1978 		 */
1979 		if (zpos == 0)
1980 			continue;
1981 
1982 		if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
1983 			premulti_en = 1;
1984 		else
1985 			premulti_en = 0;
1986 
1987 		plane = &win->base;
1988 		fb = plane->state->fb;
1989 
1990 		pixel_alpha_en = fb->format->has_alpha;
1991 
1992 		alpha_config.src_premulti_en = premulti_en;
1993 
1994 		if (bottom_layer_alpha_en && zpos == 1) {
1995 			gpremulti_en = premulti_en;
1996 			/* Cd = Cs + (1 - As) * Cd * Agd */
1997 			alpha_config.dst_premulti_en = false;
1998 			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
1999 			alpha_config.src_glb_alpha_value = plane->state->alpha;
2000 			alpha_config.dst_glb_alpha_value = dst_global_alpha;
2001 		} else if (vop2_cluster_window(win)) {
2002 			/* Mix output data only have pixel alpha */
2003 			alpha_config.dst_premulti_en = true;
2004 			alpha_config.src_pixel_alpha_en = true;
2005 			alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2006 			alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2007 		} else {
2008 			/* Cd = Cs + (1 - As) * Cd */
2009 			alpha_config.dst_premulti_en = true;
2010 			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
2011 			alpha_config.src_glb_alpha_value = plane->state->alpha;
2012 			alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2013 		}
2014 
2015 		vop2_parse_alpha(&alpha_config, &alpha);
2016 
2017 		offset = (mixer_id + zpos - 1) * 0x10;
2018 
2019 		vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val);
2020 		vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val);
2021 		vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val);
2022 		vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val);
2023 	}
2024 
2025 	if (vp->id == 0) {
2026 		if (vop2->version <= VOP_VERSION_RK3588) {
2027 			src_color_ctrl_reg = RK3568_HDR0_SRC_COLOR_CTRL;
2028 			dst_color_ctrl_reg = RK3568_HDR0_DST_COLOR_CTRL;
2029 			src_alpha_ctrl_reg = RK3568_HDR0_SRC_ALPHA_CTRL;
2030 			dst_alpha_ctrl_reg = RK3568_HDR0_DST_ALPHA_CTRL;
2031 		} else {
2032 			src_color_ctrl_reg = RK3576_OVL_HDR_SRC_COLOR_CTRL(vp->id);
2033 			dst_color_ctrl_reg = RK3576_OVL_HDR_DST_COLOR_CTRL(vp->id);
2034 			src_alpha_ctrl_reg = RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp->id);
2035 			dst_alpha_ctrl_reg = RK3576_OVL_HDR_DST_ALPHA_CTRL(vp->id);
2036 		}
2037 
2038 		if (bottom_layer_alpha_en) {
2039 			/* Transfer pixel alpha to hdr mix */
2040 			alpha_config.src_premulti_en = gpremulti_en;
2041 			alpha_config.dst_premulti_en = true;
2042 			alpha_config.src_pixel_alpha_en = true;
2043 			alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2044 			alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2045 
2046 			vop2_parse_alpha(&alpha_config, &alpha);
2047 
2048 			vop2_writel(vop2, src_color_ctrl_reg, alpha.src_color_ctrl.val);
2049 			vop2_writel(vop2, dst_color_ctrl_reg, alpha.dst_color_ctrl.val);
2050 			vop2_writel(vop2, src_alpha_ctrl_reg, alpha.src_alpha_ctrl.val);
2051 			vop2_writel(vop2, dst_alpha_ctrl_reg, alpha.dst_alpha_ctrl.val);
2052 		} else {
2053 			vop2_writel(vop2, src_color_ctrl_reg, 0);
2054 		}
2055 	}
2056 }
2057 
2058 static u32 rk3568_vop2_read_port_mux(struct vop2 *vop2)
2059 {
2060 	return vop2_readl(vop2, RK3568_OVL_PORT_SEL);
2061 }
2062 
2063 static void rk3568_vop2_wait_for_port_mux_done(struct vop2 *vop2)
2064 {
2065 	u32 port_mux_sel;
2066 	int ret;
2067 
2068 	/*
2069 	 * Spin until the previous port_mux figuration is done.
2070 	 */
2071 	ret = readx_poll_timeout_atomic(rk3568_vop2_read_port_mux, vop2, port_mux_sel,
2072 					port_mux_sel == vop2->old_port_sel, 0, 50 * 1000);
2073 	if (ret)
2074 		DRM_DEV_ERROR(vop2->dev, "wait port_mux done timeout: 0x%x--0x%x\n",
2075 			      port_mux_sel, vop2->old_port_sel);
2076 }
2077 
2078 static u32 rk3568_vop2_read_layer_cfg(struct vop2 *vop2)
2079 {
2080 	return vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
2081 }
2082 
2083 static void rk3568_vop2_wait_for_layer_cfg_done(struct vop2 *vop2, u32 cfg)
2084 {
2085 	u32 atv_layer_cfg;
2086 	int ret;
2087 
2088 	/*
2089 	 * Spin until the previous layer configuration is done.
2090 	 */
2091 	ret = readx_poll_timeout_atomic(rk3568_vop2_read_layer_cfg, vop2, atv_layer_cfg,
2092 					atv_layer_cfg == cfg, 0, 50 * 1000);
2093 	if (ret)
2094 		DRM_DEV_ERROR(vop2->dev, "wait layer cfg done timeout: 0x%x--0x%x\n",
2095 			      atv_layer_cfg, cfg);
2096 }
2097 
2098 static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp)
2099 {
2100 	struct vop2 *vop2 = vp->vop2;
2101 	struct drm_plane *plane;
2102 	u32 layer_sel = 0;
2103 	u32 port_sel;
2104 	u32 old_layer_sel = 0;
2105 	u32 atv_layer_sel = 0;
2106 	u32 old_port_sel = 0;
2107 	u8 layer_id;
2108 	u8 old_layer_id;
2109 	u8 layer_sel_id;
2110 	unsigned int ofs;
2111 	u32 ovl_ctrl;
2112 	int i;
2113 	struct vop2_video_port *vp0 = &vop2->vps[0];
2114 	struct vop2_video_port *vp1 = &vop2->vps[1];
2115 	struct vop2_video_port *vp2 = &vop2->vps[2];
2116 	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
2117 
2118 	mutex_lock(&vop2->ovl_lock);
2119 	ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL);
2120 	ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD;
2121 	ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL;
2122 
2123 	if (vcstate->yuv_overlay)
2124 		ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id);
2125 	else
2126 		ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id);
2127 
2128 	old_port_sel = vop2->old_port_sel;
2129 	port_sel = old_port_sel;
2130 	port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT;
2131 
2132 	if (vp0->nlayers)
2133 		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX,
2134 				     vp0->nlayers - 1);
2135 	else
2136 		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8);
2137 
2138 	if (vp1->nlayers)
2139 		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX,
2140 				     (vp0->nlayers + vp1->nlayers - 1));
2141 	else
2142 		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
2143 
2144 	if (vp2->nlayers)
2145 		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX,
2146 			(vp2->nlayers + vp1->nlayers + vp0->nlayers - 1));
2147 	else
2148 		port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8);
2149 
2150 	/* Fixed value for rk3588 */
2151 	if (vop2->version == VOP_VERSION_RK3588)
2152 		port_sel |= FIELD_PREP(RK3588_OVL_PORT_SET__PORT3_MUX, 7);
2153 
2154 	atv_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
2155 	old_layer_sel = vop2->old_layer_sel;
2156 	layer_sel = old_layer_sel;
2157 
2158 	ofs = 0;
2159 	for (i = 0; i < vp->id; i++)
2160 		ofs += vop2->vps[i].nlayers;
2161 
2162 	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
2163 		struct vop2_win *win = to_vop2_win(plane);
2164 		struct vop2_win *old_win;
2165 
2166 		layer_id = (u8)(plane->state->normalized_zpos + ofs);
2167 		/*
2168 		 * Find the layer this win bind in old state.
2169 		 */
2170 		for (old_layer_id = 0; old_layer_id < vop2->data->win_size; old_layer_id++) {
2171 			layer_sel_id = (layer_sel >> (4 * old_layer_id)) & 0xf;
2172 			if (layer_sel_id == win->data->layer_sel_id[vp->id])
2173 				break;
2174 		}
2175 
2176 		/*
2177 		 * Find the win bind to this layer in old state
2178 		 */
2179 		for (i = 0; i < vop2->data->win_size; i++) {
2180 			old_win = &vop2->win[i];
2181 			layer_sel_id = (layer_sel >> (4 * layer_id)) & 0xf;
2182 			if (layer_sel_id == old_win->data->layer_sel_id[vp->id])
2183 				break;
2184 		}
2185 
2186 		switch (win->data->phys_id) {
2187 		case ROCKCHIP_VOP2_CLUSTER0:
2188 			port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0;
2189 			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id);
2190 			break;
2191 		case ROCKCHIP_VOP2_CLUSTER1:
2192 			port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1;
2193 			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id);
2194 			break;
2195 		case ROCKCHIP_VOP2_CLUSTER2:
2196 			port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER2;
2197 			port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id);
2198 			break;
2199 		case ROCKCHIP_VOP2_CLUSTER3:
2200 			port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER3;
2201 			port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id);
2202 			break;
2203 		case ROCKCHIP_VOP2_ESMART0:
2204 			port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0;
2205 			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id);
2206 			break;
2207 		case ROCKCHIP_VOP2_ESMART1:
2208 			port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1;
2209 			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id);
2210 			break;
2211 		case ROCKCHIP_VOP2_ESMART2:
2212 			port_sel &= ~RK3588_OVL_PORT_SEL__ESMART2;
2213 			port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id);
2214 			break;
2215 		case ROCKCHIP_VOP2_ESMART3:
2216 			port_sel &= ~RK3588_OVL_PORT_SEL__ESMART3;
2217 			port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id);
2218 			break;
2219 		case ROCKCHIP_VOP2_SMART0:
2220 			port_sel &= ~RK3568_OVL_PORT_SEL__SMART0;
2221 			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id);
2222 			break;
2223 		case ROCKCHIP_VOP2_SMART1:
2224 			port_sel &= ~RK3568_OVL_PORT_SEL__SMART1;
2225 			port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id);
2226 			break;
2227 		}
2228 
2229 		layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(layer_id, 0x7);
2230 		layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(layer_id, win->data->layer_sel_id[vp->id]);
2231 		/*
2232 		 * When we bind a window from layerM to layerN, we also need to move the old
2233 		 * window on layerN to layerM to avoid one window selected by two or more layers.
2234 		 */
2235 		layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, 0x7);
2236 		layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(old_layer_id,
2237 			     old_win->data->layer_sel_id[vp->id]);
2238 	}
2239 
2240 	vop2->old_layer_sel = layer_sel;
2241 	vop2->old_port_sel = port_sel;
2242 	/*
2243 	 * As the RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are shared by all Video Ports,
2244 	 * and the configuration take effect by one Video Port's vsync.
2245 	 * When performing layer migration or change the zpos of layers, there are two things
2246 	 * to be observed and followed:
2247 	 * 1. When a layer is migrated from one VP to another, the configuration of the layer
2248 	 *    can only take effect after the Port mux configuration is enabled.
2249 	 *
2250 	 * 2. When we change the zpos of layers, we must ensure that the change for the previous
2251 	 *    VP takes effect before we proceed to change the next VP. Otherwise, the new
2252 	 *    configuration might overwrite the previous one for the previous VP, or it could
2253 	 *    lead to the configuration of the previous VP being take effect along with the VSYNC
2254 	 *    of the new VP.
2255 	 */
2256 	if (layer_sel != old_layer_sel || port_sel != old_port_sel)
2257 		ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id);
2258 	vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl);
2259 
2260 	if (port_sel != old_port_sel) {
2261 		vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel);
2262 		vop2_cfg_done(vp);
2263 		rk3568_vop2_wait_for_port_mux_done(vop2);
2264 	}
2265 
2266 	if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel)
2267 		rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel);
2268 
2269 	vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
2270 	mutex_unlock(&vop2->ovl_lock);
2271 }
2272 
2273 static void rk3568_vop2_setup_dly_for_windows(struct vop2_video_port *vp)
2274 {
2275 	struct vop2 *vop2 = vp->vop2;
2276 	struct vop2_win *win;
2277 	int i = 0;
2278 	u32 cdly = 0, sdly = 0;
2279 
2280 	for (i = 0; i < vop2->data->win_size; i++) {
2281 		u32 dly;
2282 
2283 		win = &vop2->win[i];
2284 		dly = win->delay;
2285 
2286 		switch (win->data->phys_id) {
2287 		case ROCKCHIP_VOP2_CLUSTER0:
2288 			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly);
2289 			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly);
2290 			break;
2291 		case ROCKCHIP_VOP2_CLUSTER1:
2292 			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly);
2293 			cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly);
2294 			break;
2295 		case ROCKCHIP_VOP2_ESMART0:
2296 			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly);
2297 			break;
2298 		case ROCKCHIP_VOP2_ESMART1:
2299 			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly);
2300 			break;
2301 		case ROCKCHIP_VOP2_SMART0:
2302 		case ROCKCHIP_VOP2_ESMART2:
2303 			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly);
2304 			break;
2305 		case ROCKCHIP_VOP2_SMART1:
2306 		case ROCKCHIP_VOP2_ESMART3:
2307 			sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly);
2308 			break;
2309 		}
2310 	}
2311 
2312 	vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly);
2313 	vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly);
2314 }
2315 
2316 static void rk3568_vop2_setup_overlay(struct vop2_video_port *vp)
2317 {
2318 	struct vop2 *vop2 = vp->vop2;
2319 	struct drm_crtc *crtc = &vp->crtc;
2320 	struct drm_plane *plane;
2321 
2322 	vp->win_mask = 0;
2323 
2324 	drm_atomic_crtc_for_each_plane(plane, crtc) {
2325 		struct vop2_win *win = to_vop2_win(plane);
2326 
2327 		win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
2328 
2329 		vp->win_mask |= BIT(win->data->phys_id);
2330 
2331 		if (vop2_cluster_window(win))
2332 			vop2_setup_cluster_alpha(vop2, win);
2333 	}
2334 
2335 	if (!vp->win_mask)
2336 		return;
2337 
2338 	rk3568_vop2_setup_layer_mixer(vp);
2339 	vop2_setup_alpha(vp);
2340 	rk3568_vop2_setup_dly_for_windows(vp);
2341 }
2342 
2343 static void rk3576_vop2_setup_layer_mixer(struct vop2_video_port *vp)
2344 {
2345 	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
2346 	struct vop2 *vop2 = vp->vop2;
2347 	struct drm_plane *plane;
2348 	u32 layer_sel = 0xffff; /* 0xf means this layer is disabled */
2349 	u32 ovl_ctrl;
2350 
2351 	ovl_ctrl = vop2_readl(vop2, RK3576_OVL_CTRL(vp->id));
2352 	if (vcstate->yuv_overlay)
2353 		ovl_ctrl |= RK3576_OVL_CTRL__YUV_MODE;
2354 	else
2355 		ovl_ctrl &= ~RK3576_OVL_CTRL__YUV_MODE;
2356 
2357 	vop2_writel(vop2, RK3576_OVL_CTRL(vp->id), ovl_ctrl);
2358 
2359 	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
2360 		struct vop2_win *win = to_vop2_win(plane);
2361 
2362 		layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos,
2363 							  0xf);
2364 		layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos,
2365 							 win->data->layer_sel_id[vp->id]);
2366 	}
2367 
2368 	vop2_writel(vop2, RK3576_OVL_LAYER_SEL(vp->id), layer_sel);
2369 }
2370 
2371 static void rk3576_vop2_setup_dly_for_windows(struct vop2_video_port *vp)
2372 {
2373 	struct drm_plane *plane;
2374 	struct vop2_win *win;
2375 
2376 	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
2377 		win = to_vop2_win(plane);
2378 		vop2_win_write(win, VOP2_WIN_DLY_NUM, 0);
2379 	}
2380 }
2381 
2382 static void rk3576_vop2_setup_overlay(struct vop2_video_port *vp)
2383 {
2384 	struct vop2 *vop2 = vp->vop2;
2385 	struct drm_crtc *crtc = &vp->crtc;
2386 	struct drm_plane *plane;
2387 
2388 	vp->win_mask = 0;
2389 
2390 	drm_atomic_crtc_for_each_plane(plane, crtc) {
2391 		struct vop2_win *win = to_vop2_win(plane);
2392 
2393 		win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
2394 		vp->win_mask |= BIT(win->data->phys_id);
2395 
2396 		if (vop2_cluster_window(win))
2397 			vop2_setup_cluster_alpha(vop2, win);
2398 	}
2399 
2400 	if (!vp->win_mask)
2401 		return;
2402 
2403 	rk3576_vop2_setup_layer_mixer(vp);
2404 	vop2_setup_alpha(vp);
2405 	rk3576_vop2_setup_dly_for_windows(vp);
2406 }
2407 
2408 static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp)
2409 {
2410 	struct drm_crtc *crtc = &vp->crtc;
2411 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
2412 	u16 hdisplay = mode->crtc_hdisplay;
2413 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2414 	u32 bg_dly;
2415 	u32 pre_scan_dly;
2416 
2417 	bg_dly = vp->data->pre_scan_max_dly[3];
2418 	vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id),
2419 		    FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly));
2420 
2421 	pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
2422 	vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
2423 }
2424 
2425 static void rk3576_vop2_setup_bg_dly(struct vop2_video_port *vp)
2426 {
2427 	struct drm_crtc *crtc = &vp->crtc;
2428 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
2429 	u16 hdisplay = mode->crtc_hdisplay;
2430 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2431 	u32 bg_dly;
2432 	u32 pre_scan_dly;
2433 
2434 	bg_dly = vp->data->pre_scan_max_dly[VOP2_DLY_WIN] +
2435 		 vp->data->pre_scan_max_dly[VOP2_DLY_LAYER_MIX] +
2436 		 vp->data->pre_scan_max_dly[VOP2_DLY_HDR_MIX];
2437 
2438 	vop2_writel(vp->vop2, RK3576_OVL_BG_MIX_CTRL(vp->id),
2439 		    FIELD_PREP(RK3576_OVL_BG_MIX_CTRL__BG_DLY, bg_dly));
2440 
2441 	pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
2442 	vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
2443 }
2444 
2445 static const struct vop2_ops rk3568_vop_ops = {
2446 	.setup_intf_mux = rk3568_set_intf_mux,
2447 	.setup_bg_dly = rk3568_vop2_setup_bg_dly,
2448 	.setup_overlay = rk3568_vop2_setup_overlay,
2449 };
2450 
2451 static const struct vop2_ops rk3576_vop_ops = {
2452 	.setup_intf_mux = rk3576_set_intf_mux,
2453 	.setup_bg_dly = rk3576_vop2_setup_bg_dly,
2454 	.setup_overlay = rk3576_vop2_setup_overlay,
2455 };
2456 
2457 static const struct vop2_ops rk3588_vop_ops = {
2458 	.setup_intf_mux = rk3588_set_intf_mux,
2459 	.setup_bg_dly = rk3568_vop2_setup_bg_dly,
2460 	.setup_overlay = rk3568_vop2_setup_overlay,
2461 };
2462 
2463 static const struct vop2_data rk3566_vop = {
2464 	.version = VOP_VERSION_RK3568,
2465 	.feature = VOP2_FEATURE_HAS_SYS_GRF,
2466 	.nr_vps = 3,
2467 	.max_input = { 4096, 2304 },
2468 	.max_output = { 4096, 2304 },
2469 	.vp = rk3568_vop_video_ports,
2470 	.win = rk3568_vop_win_data,
2471 	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
2472 	.cluster_reg = rk3568_vop_cluster_regs,
2473 	.nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs),
2474 	.smart_reg = rk3568_vop_smart_regs,
2475 	.nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs),
2476 	.regs_dump = rk3568_regs_dump,
2477 	.regs_dump_size = ARRAY_SIZE(rk3568_regs_dump),
2478 	.ops = &rk3568_vop_ops,
2479 	.soc_id = 3566,
2480 };
2481 
2482 static const struct vop2_data rk3568_vop = {
2483 	.version = VOP_VERSION_RK3568,
2484 	.feature = VOP2_FEATURE_HAS_SYS_GRF,
2485 	.nr_vps = 3,
2486 	.max_input = { 4096, 2304 },
2487 	.max_output = { 4096, 2304 },
2488 	.vp = rk3568_vop_video_ports,
2489 	.win = rk3568_vop_win_data,
2490 	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
2491 	.cluster_reg = rk3568_vop_cluster_regs,
2492 	.nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs),
2493 	.smart_reg = rk3568_vop_smart_regs,
2494 	.nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs),
2495 	.regs_dump = rk3568_regs_dump,
2496 	.regs_dump_size = ARRAY_SIZE(rk3568_regs_dump),
2497 	.ops = &rk3568_vop_ops,
2498 	.soc_id = 3568,
2499 };
2500 
2501 static const struct vop2_data rk3576_vop = {
2502 	.version = VOP_VERSION_RK3576,
2503 	.feature = VOP2_FEATURE_HAS_SYS_PMU,
2504 	.nr_vps = 3,
2505 	.max_input = { 4096, 4320 },
2506 	.max_output = { 4096, 4320 },
2507 	.vp = rk3576_vop_video_ports,
2508 	.win = rk3576_vop_win_data,
2509 	.win_size = ARRAY_SIZE(rk3576_vop_win_data),
2510 	.cluster_reg = rk3576_vop_cluster_regs,
2511 	.nr_cluster_regs = ARRAY_SIZE(rk3576_vop_cluster_regs),
2512 	.smart_reg = rk3576_vop_smart_regs,
2513 	.nr_smart_regs = ARRAY_SIZE(rk3576_vop_smart_regs),
2514 	.regs_dump = rk3576_regs_dump,
2515 	.regs_dump_size = ARRAY_SIZE(rk3576_regs_dump),
2516 	.ops = &rk3576_vop_ops,
2517 	.soc_id = 3576,
2518 };
2519 
2520 static const struct vop2_data rk3588_vop = {
2521 	.version = VOP_VERSION_RK3588,
2522 	.feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF |
2523 		   VOP2_FEATURE_HAS_VOP_GRF | VOP2_FEATURE_HAS_SYS_PMU,
2524 	.nr_vps = 4,
2525 	.max_input = { 4096, 4320 },
2526 	.max_output = { 4096, 4320 },
2527 	.vp = rk3588_vop_video_ports,
2528 	.win = rk3588_vop_win_data,
2529 	.win_size = ARRAY_SIZE(rk3588_vop_win_data),
2530 	.cluster_reg = rk3568_vop_cluster_regs,
2531 	.nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs),
2532 	.smart_reg = rk3568_vop_smart_regs,
2533 	.nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs),
2534 	.regs_dump = rk3588_regs_dump,
2535 	.regs_dump_size = ARRAY_SIZE(rk3588_regs_dump),
2536 	.ops = &rk3588_vop_ops,
2537 	.soc_id = 3588,
2538 };
2539 
2540 static const struct of_device_id vop2_dt_match[] = {
2541 	{
2542 		.compatible = "rockchip,rk3566-vop",
2543 		.data = &rk3566_vop,
2544 	}, {
2545 		.compatible = "rockchip,rk3568-vop",
2546 		.data = &rk3568_vop,
2547 	}, {
2548 		.compatible = "rockchip,rk3576-vop",
2549 		.data = &rk3576_vop,
2550 	}, {
2551 		.compatible = "rockchip,rk3588-vop",
2552 		.data = &rk3588_vop
2553 	}, {
2554 	},
2555 };
2556 MODULE_DEVICE_TABLE(of, vop2_dt_match);
2557 
2558 static int vop2_probe(struct platform_device *pdev)
2559 {
2560 	struct device *dev = &pdev->dev;
2561 
2562 	return component_add(dev, &vop2_component_ops);
2563 }
2564 
2565 static void vop2_remove(struct platform_device *pdev)
2566 {
2567 	component_del(&pdev->dev, &vop2_component_ops);
2568 }
2569 
2570 struct platform_driver vop2_platform_driver = {
2571 	.probe = vop2_probe,
2572 	.remove = vop2_remove,
2573 	.driver = {
2574 		.name = "rockchip-vop2",
2575 		.of_match_table = vop2_dt_match,
2576 	},
2577 };
2578