xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_vop2.c (revision 25dca6d04b4fbb4a0424c943a24de393294de2b2)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
4  *
5  */
6 
7 #include <config.h>
8 #include <common.h>
9 #include <errno.h>
10 #include <malloc.h>
11 #include <fdtdec.h>
12 #include <fdt_support.h>
13 #include <asm/arch/cpu.h>
14 #include <asm/unaligned.h>
15 #include <asm/io.h>
16 #include <linux/list.h>
17 #include <linux/log2.h>
18 #include <linux/media-bus-format.h>
19 #include <clk.h>
20 #include <asm/arch/clock.h>
21 #include <linux/err.h>
22 #include <linux/ioport.h>
23 #include <dm/device.h>
24 #include <dm/read.h>
25 #include <fixp-arith.h>
26 #include <syscon.h>
27 #include <linux/iopoll.h>
28 
29 #include "rockchip_display.h"
30 #include "rockchip_crtc.h"
31 #include "rockchip_connector.h"
32 
33 /* System registers definition */
34 #define RK3568_REG_CFG_DONE			0x000
35 #define	CFG_DONE_EN				BIT(15)
36 
37 #define RK3568_VERSION_INFO			0x004
38 #define EN_MASK					1
39 
40 #define RK3568_AUTO_GATING_CTRL			0x008
41 
42 #define RK3568_SYS_AXI_LUT_CTRL			0x024
43 #define LUT_DMA_EN_SHIFT			0
44 
45 #define RK3568_DSP_IF_EN			0x028
46 #define RGB_EN_SHIFT				0
47 #define RK3588_DP0_EN_SHIFT			0
48 #define RK3588_DP1_EN_SHIFT			1
49 #define RK3588_RGB_EN_SHIFT			8
50 #define HDMI0_EN_SHIFT				1
51 #define EDP0_EN_SHIFT				3
52 #define RK3588_EDP0_EN_SHIFT			2
53 #define RK3588_HDMI0_EN_SHIFT			3
54 #define MIPI0_EN_SHIFT				4
55 #define RK3588_EDP1_EN_SHIFT			4
56 #define RK3588_HDMI1_EN_SHIFT			5
57 #define RK3588_MIPI0_EN_SHIFT                   6
58 #define MIPI1_EN_SHIFT				20
59 #define RK3588_MIPI1_EN_SHIFT                   7
60 #define LVDS0_EN_SHIFT				5
61 #define LVDS1_EN_SHIFT				24
62 #define BT1120_EN_SHIFT				6
63 #define BT656_EN_SHIFT				7
64 #define IF_MUX_MASK				3
65 #define RGB_MUX_SHIFT				8
66 #define HDMI0_MUX_SHIFT				10
67 #define RK3588_DP0_MUX_SHIFT			12
68 #define RK3588_DP1_MUX_SHIFT			14
69 #define EDP0_MUX_SHIFT				14
70 #define RK3588_HDMI_EDP0_MUX_SHIFT		16
71 #define RK3588_HDMI_EDP1_MUX_SHIFT		18
72 #define MIPI0_MUX_SHIFT				16
73 #define RK3588_MIPI0_MUX_SHIFT			20
74 #define MIPI1_MUX_SHIFT				21
75 #define LVDS0_MUX_SHIFT				18
76 #define LVDS1_MUX_SHIFT				25
77 
78 #define RK3568_DSP_IF_CTRL			0x02c
79 #define LVDS_DUAL_EN_SHIFT			0
80 #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT		1
81 #define LVDS_DUAL_SWAP_EN_SHIFT			2
82 #define RK3568_MIPI_DUAL_EN_SHIFT		10
83 #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT		11
84 #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT		12
85 
86 #define RK3568_DSP_IF_POL			0x030
87 #define IF_CTRL_REG_DONE_IMD_MASK		1
88 #define IF_CTRL_REG_DONE_IMD_SHIFT		28
89 #define IF_CRTL_MIPI_DCLK_POL_SHIT		19
90 #define IF_CRTL_EDP_DCLK_POL_SHIT		15
91 #define IF_CRTL_HDMI_DCLK_POL_SHIT		7
92 #define IF_CRTL_HDMI_PIN_POL_MASK		0x7
93 #define IF_CRTL_HDMI_PIN_POL_SHIT		4
94 
95 #define RK3588_DP0_PIN_POL_SHIFT		8
96 #define RK3588_DP1_PIN_POL_SHIFT		12
97 #define RK3588_IF_PIN_POL_MASK			0x7
98 
99 #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT		3
100 
101 #define HDMI_EDP0_DCLK_DIV_SHIFT		16
102 #define HDMI_EDP0_PIXCLK_DIV_SHIFT		18
103 #define HDMI_EDP1_DCLK_DIV_SHIFT		20
104 #define HDMI_EDP1_PIXCLK_DIV_SHIFT		22
105 #define MIPI0_PIXCLK_DIV_SHIFT			24
106 #define MIPI1_PIXCLK_DIV_SHIFT			26
107 
108 #define RK3568_SYS_OTP_WIN_EN			0x50
109 #define OTP_WIN_EN_SHIFT			0
110 #define RK3568_SYS_LUT_PORT_SEL			0x58
111 #define GAMMA_PORT_SEL_MASK			0x3
112 #define GAMMA_PORT_SEL_SHIFT			0
113 
114 #define RK3568_SYS_PD_CTRL			0x034
115 #define RK3568_VP0_LINE_FLAG			0x70
116 #define RK3568_VP1_LINE_FLAG			0x74
117 #define RK3568_VP2_LINE_FLAG			0x78
118 #define RK3568_SYS0_INT_EN			0x80
119 #define RK3568_SYS0_INT_CLR			0x84
120 #define RK3568_SYS0_INT_STATUS			0x88
121 #define RK3568_SYS1_INT_EN			0x90
122 #define RK3568_SYS1_INT_CLR			0x94
123 #define RK3568_SYS1_INT_STATUS			0x98
124 #define RK3568_VP0_INT_EN			0xA0
125 #define RK3568_VP0_INT_CLR			0xA4
126 #define RK3568_VP0_INT_STATUS			0xA8
127 #define RK3568_VP1_INT_EN			0xB0
128 #define RK3568_VP1_INT_CLR			0xB4
129 #define RK3568_VP1_INT_STATUS			0xB8
130 #define RK3568_VP2_INT_EN			0xC0
131 #define RK3568_VP2_INT_CLR			0xC4
132 #define RK3568_VP2_INT_STATUS			0xC8
133 #define RK3588_CLUSTER0_PD_EN_SHIFT		0
134 #define RK3588_CLUSTER1_PD_EN_SHIFT		1
135 #define RK3588_CLUSTER2_PD_EN_SHIFT		2
136 #define RK3588_CLUSTER3_PD_EN_SHIFT		3
137 #define RK3588_ESMART_PD_EN_SHIFT		7
138 
139 #define RK3568_SYS_STATUS0			0x60
140 #define RK3588_CLUSTER0_PD_STATUS_SHIFT		8
141 #define RK3588_CLUSTER1_PD_STATUS_SHIFT		9
142 #define RK3588_CLUSTER2_PD_STATUS_SHIFT		10
143 #define RK3588_CLUSTER3_PD_STATUS_SHIFT		11
144 #define RK3588_ESMART_PD_STATUS_SHIFT		15
145 
146 /* Overlay registers definition    */
147 #define RK3568_OVL_CTRL				0x600
148 #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
149 #define RK3568_OVL_LAYER_SEL			0x604
150 #define LAYER_SEL_MASK				0xf
151 
152 #define RK3568_OVL_PORT_SEL			0x608
153 #define PORT_MUX_MASK				0xf
154 #define PORT_MUX_SHIFT				0
155 #define LAYER_SEL_PORT_MASK			0x3
156 #define LAYER_SEL_PORT_SHIFT			16
157 
158 #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
159 #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
160 #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
161 #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
162 #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
163 #define RK3568_MIX0_DST_COLOR_CTRL		0x654
164 #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
165 #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
166 #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
167 #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
168 #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
169 #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
170 #define RK3568_VP0_BG_MIX_CTRL			0x6E0
171 #define BG_MIX_CTRL_MASK			0xff
172 #define BG_MIX_CTRL_SHIFT			24
173 #define RK3568_VP1_BG_MIX_CTRL			0x6E4
174 #define RK3568_VP2_BG_MIX_CTRL			0x6E8
175 #define RK3568_CLUSTER_DLY_NUM			0x6F0
176 #define RK3568_SMART_DLY_NUM			0x6F8
177 
178 /* Video Port registers definition */
179 #define RK3568_VP0_DSP_CTRL			0xC00
180 #define OUT_MODE_MASK				0xf
181 #define OUT_MODE_SHIFT				0
182 #define DATA_SWAP_MASK				0x1f
183 #define DATA_SWAP_SHIFT				8
184 #define DSP_RB_SWAP				2
185 #define CORE_DCLK_DIV_EN_SHIFT			4
186 #define P2I_EN_SHIFT				5
187 #define DSP_FILED_POL				6
188 #define INTERLACE_EN_SHIFT			7
189 #define POST_DSP_OUT_R2Y_SHIFT			15
190 #define PRE_DITHER_DOWN_EN_SHIFT		16
191 #define DITHER_DOWN_EN_SHIFT			17
192 #define DSP_LUT_EN_SHIFT			28
193 
194 #define STANDBY_EN_SHIFT			31
195 
196 #define RK3568_VP0_MIPI_CTRL			0xC04
197 #define DCLK_DIV2_SHIFT				4
198 #define DCLK_DIV2_MASK				0x3
199 #define MIPI_DUAL_EN_SHIFT			20
200 #define MIPI_DUAL_SWAP_EN_SHIFT			21
201 #define EDPI_TE_EN				28
202 #define EDPI_WMS_HOLD_EN			30
203 #define EDPI_WMS_FS				31
204 
205 
206 #define RK3568_VP0_COLOR_BAR_CTRL		0xC08
207 #define RK3568_VP0_3D_LUT_CTRL			0xC10
208 #define VP0_3D_LUT_EN_SHIFT				0
209 #define VP0_3D_LUT_UPDATE_SHIFT			2
210 
211 #define RK3588_VP0_CLK_CTRL			0xC0C
212 #define DCLK_CORE_DIV_SHIFT			0
213 #define DCLK_OUT_DIV_SHIFT			2
214 
215 #define RK3568_VP0_3D_LUT_MST			0xC20
216 
217 #define RK3568_VP0_DSP_BG			0xC2C
218 #define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
219 #define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
220 #define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
221 #define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
222 #define RK3568_VP0_POST_SCL_CTRL		0xC40
223 #define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
224 #define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
225 #define RK3568_VP0_DSP_HACT_ST_END		0xC4C
226 #define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
227 #define RK3568_VP0_DSP_VACT_ST_END		0xC54
228 #define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
229 #define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
230 
231 #define RK3568_VP0_BCSH_CTRL			0xC60
232 #define BCSH_CTRL_Y2R_SHIFT			0
233 #define BCSH_CTRL_Y2R_MASK			0x1
234 #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT		2
235 #define BCSH_CTRL_Y2R_CSC_MODE_MASK		0x3
236 #define BCSH_CTRL_R2Y_SHIFT			4
237 #define BCSH_CTRL_R2Y_MASK			0x1
238 #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT		6
239 #define BCSH_CTRL_R2Y_CSC_MODE_MASK		0x3
240 
241 #define RK3568_VP0_BCSH_BCS			0xC64
242 #define BCSH_BRIGHTNESS_SHIFT			0
243 #define BCSH_BRIGHTNESS_MASK			0xFF
244 #define BCSH_CONTRAST_SHIFT			8
245 #define BCSH_CONTRAST_MASK			0x1FF
246 #define BCSH_SATURATION_SHIFT			20
247 #define BCSH_SATURATION_MASK			0x3FF
248 #define BCSH_OUT_MODE_SHIFT			30
249 #define BCSH_OUT_MODE_MASK			0x3
250 
251 #define RK3568_VP0_BCSH_H			0xC68
252 #define BCSH_SIN_HUE_SHIFT			0
253 #define BCSH_SIN_HUE_MASK			0x1FF
254 #define BCSH_COS_HUE_SHIFT			16
255 #define BCSH_COS_HUE_MASK			0x1FF
256 
257 #define RK3568_VP0_BCSH_COLOR			0xC6C
258 #define BCSH_EN_SHIFT				31
259 #define BCSH_EN_MASK				1
260 
261 #define RK3568_VP1_DSP_CTRL			0xD00
262 #define RK3568_VP1_MIPI_CTRL			0xD04
263 #define RK3568_VP1_COLOR_BAR_CTRL		0xD08
264 #define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
265 #define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
266 #define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
267 #define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
268 #define RK3568_VP1_POST_SCL_CTRL		0xD40
269 #define RK3568_VP1_DSP_HACT_INFO		0xD34
270 #define RK3568_VP1_DSP_VACT_INFO		0xD38
271 #define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
272 #define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
273 #define RK3568_VP1_DSP_HACT_ST_END		0xD4C
274 #define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
275 #define RK3568_VP1_DSP_VACT_ST_END		0xD54
276 #define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
277 #define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
278 
279 #define RK3568_VP2_DSP_CTRL			0xE00
280 #define RK3568_VP2_MIPI_CTRL			0xE04
281 #define RK3568_VP2_COLOR_BAR_CTRL		0xE08
282 #define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
283 #define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
284 #define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
285 #define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
286 #define RK3568_VP2_POST_SCL_CTRL		0xE40
287 #define RK3568_VP2_DSP_HACT_INFO		0xE34
288 #define RK3568_VP2_DSP_VACT_INFO		0xE38
289 #define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
290 #define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
291 #define RK3568_VP2_DSP_HACT_ST_END		0xE4C
292 #define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
293 #define RK3568_VP2_DSP_VACT_ST_END		0xE54
294 #define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
295 #define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
296 
297 /* Cluster0 register definition */
298 #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
299 #define CLUSTER_YUV2RGB_EN_SHIFT		8
300 #define CLUSTER_RGB2YUV_EN_SHIFT		9
301 #define CLUSTER_CSC_MODE_SHIFT			10
302 #define CLUSTER_YRGB_XSCL_MODE_SHIFT		12
303 #define CLUSTER_YRGB_YSCL_MODE_SHIFT		14
304 #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
305 #define CLUSTER_YRGB_GT2_SHIFT			28
306 #define CLUSTER_YRGB_GT4_SHIFT			29
307 #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
308 #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
309 #define RK3568_CLUSTER0_WIN0_VIR		0x1018
310 #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
311 #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
312 #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
313 #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
314 #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
315 #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
316 #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
317 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
318 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
319 #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
320 #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
321 
322 #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
323 #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
324 #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
325 #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
326 #define RK3568_CLUSTER0_WIN1_VIR		0x1098
327 #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
328 #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
329 #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
330 #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
331 #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
332 #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
333 #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
334 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
335 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
336 #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
337 #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
338 
339 #define RK3568_CLUSTER0_CTRL			0x1100
340 #define CLUSTER_EN_SHIFT			0
341 
342 #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
343 #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
344 #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
345 #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
346 #define RK3568_CLUSTER1_WIN0_VIR		0x1218
347 #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
348 #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
349 #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
350 #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
351 #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
352 #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
353 #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
354 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
355 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
356 #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
357 #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
358 
359 #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
360 #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
361 #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
362 #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
363 #define RK3568_CLUSTER1_WIN1_VIR		0x1298
364 #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
365 #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
366 #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
367 #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
368 #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
369 #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
370 #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
371 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
372 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
373 #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
374 #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
375 
376 #define RK3568_CLUSTER1_CTRL			0x1300
377 
378 /* Esmart register definition */
379 #define RK3568_ESMART0_CTRL0			0x1800
380 #define RGB2YUV_EN_SHIFT			1
381 #define CSC_MODE_SHIFT				2
382 #define CSC_MODE_MASK				0x3
383 
384 #define RK3568_ESMART0_CTRL1			0x1804
385 #define YMIRROR_EN_SHIFT			31
386 #define RK3568_ESMART0_REGION0_CTRL		0x1810
387 #define REGION0_RB_SWAP_SHIFT			14
388 #define WIN_EN_SHIFT				0
389 #define WIN_FORMAT_MASK				0x1f
390 #define WIN_FORMAT_SHIFT			1
391 
392 #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
393 #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
394 #define RK3568_ESMART0_REGION0_VIR		0x181C
395 #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
396 #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
397 #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
398 #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
399 #define YRGB_XSCL_MODE_MASK			0x3
400 #define YRGB_XSCL_MODE_SHIFT			0
401 #define YRGB_XSCL_FILTER_MODE_MASK		0x3
402 #define YRGB_XSCL_FILTER_MODE_SHIFT		2
403 #define YRGB_YSCL_MODE_MASK			0x3
404 #define YRGB_YSCL_MODE_SHIFT			4
405 #define YRGB_YSCL_FILTER_MODE_MASK		0x3
406 #define YRGB_YSCL_FILTER_MODE_SHIFT		6
407 
408 #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
409 #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
410 #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
411 #define RK3568_ESMART0_REGION1_CTRL		0x1840
412 #define YRGB_GT2_MASK				0x1
413 #define YRGB_GT2_SHIFT				8
414 #define YRGB_GT4_MASK				0x1
415 #define YRGB_GT4_SHIFT				9
416 
417 #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
418 #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
419 #define RK3568_ESMART0_REGION1_VIR		0x184C
420 #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
421 #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
422 #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
423 #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
424 #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
425 #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
426 #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
427 #define RK3568_ESMART0_REGION2_CTRL		0x1870
428 #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
429 #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
430 #define RK3568_ESMART0_REGION2_VIR		0x187C
431 #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
432 #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
433 #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
434 #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
435 #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
436 #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
437 #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
438 #define RK3568_ESMART0_REGION3_CTRL		0x18A0
439 #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
440 #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
441 #define RK3568_ESMART0_REGION3_VIR		0x18AC
442 #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
443 #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
444 #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
445 #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
446 #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
447 #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
448 #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
449 
450 #define RK3568_ESMART1_CTRL0			0x1A00
451 #define RK3568_ESMART1_CTRL1			0x1A04
452 #define RK3568_ESMART1_REGION0_CTRL		0x1A10
453 #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
454 #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
455 #define RK3568_ESMART1_REGION0_VIR		0x1A1C
456 #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
457 #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
458 #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
459 #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
460 #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
461 #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
462 #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
463 #define RK3568_ESMART1_REGION1_CTRL		0x1A40
464 #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
465 #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
466 #define RK3568_ESMART1_REGION1_VIR		0x1A4C
467 #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
468 #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
469 #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
470 #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
471 #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
472 #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
473 #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
474 #define RK3568_ESMART1_REGION2_CTRL		0x1A70
475 #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
476 #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
477 #define RK3568_ESMART1_REGION2_VIR		0x1A7C
478 #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
479 #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
480 #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
481 #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
482 #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
483 #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
484 #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
485 #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
486 #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
487 #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
488 #define RK3568_ESMART1_REGION3_VIR		0x1AAC
489 #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
490 #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
491 #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
492 #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
493 #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
494 #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
495 #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
496 
497 #define RK3568_SMART0_CTRL0			0x1C00
498 #define RK3568_SMART0_CTRL1			0x1C04
499 #define RK3568_SMART0_REGION0_CTRL		0x1C10
500 #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
501 #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
502 #define RK3568_SMART0_REGION0_VIR		0x1C1C
503 #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
504 #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
505 #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
506 #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
507 #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
508 #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
509 #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
510 #define RK3568_SMART0_REGION1_CTRL		0x1C40
511 #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
512 #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
513 #define RK3568_SMART0_REGION1_VIR		0x1C4C
514 #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
515 #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
516 #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
517 #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
518 #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
519 #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
520 #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
521 #define RK3568_SMART0_REGION2_CTRL		0x1C70
522 #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
523 #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
524 #define RK3568_SMART0_REGION2_VIR		0x1C7C
525 #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
526 #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
527 #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
528 #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
529 #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
530 #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
531 #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
532 #define RK3568_SMART0_REGION3_CTRL		0x1CA0
533 #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
534 #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
535 #define RK3568_SMART0_REGION3_VIR		0x1CAC
536 #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
537 #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
538 #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
539 #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
540 #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
541 #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
542 #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
543 
544 #define RK3568_SMART1_CTRL0			0x1E00
545 #define RK3568_SMART1_CTRL1			0x1E04
546 #define RK3568_SMART1_REGION0_CTRL		0x1E10
547 #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
548 #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
549 #define RK3568_SMART1_REGION0_VIR		0x1E1C
550 #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
551 #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
552 #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
553 #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
554 #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
555 #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
556 #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
557 #define RK3568_SMART1_REGION1_CTRL		0x1E40
558 #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
559 #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
560 #define RK3568_SMART1_REGION1_VIR		0x1E4C
561 #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
562 #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
563 #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
564 #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
565 #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
566 #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
567 #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
568 #define RK3568_SMART1_REGION2_CTRL		0x1E70
569 #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
570 #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
571 #define RK3568_SMART1_REGION2_VIR		0x1E7C
572 #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
573 #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
574 #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
575 #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
576 #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
577 #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
578 #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
579 #define RK3568_SMART1_REGION3_CTRL		0x1EA0
580 #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
581 #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
582 #define RK3568_SMART1_REGION3_VIR		0x1EAC
583 #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
584 #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
585 #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
586 #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
587 #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
588 #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
589 #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
590 
591 #define RK3568_MAX_REG				0x1ED0
592 
593 #define RK3568_GRF_VO_CON1			0x0364
594 #define GRF_BT656_CLK_INV_SHIFT			1
595 #define GRF_BT1120_CLK_INV_SHIFT		2
596 #define GRF_RGB_DCLK_INV_SHIFT			3
597 
598 #define RK3588_GRF_VOP_CON2			0x0008
599 #define RK3588_GRF_EDP0_ENABLE_SHIFT		0
600 #define RK3588_GRF_HDMITX0_ENABLE_SHIFT		1
601 #define RK3588_GRF_EDP1_ENABLE_SHIFT		3
602 #define RK3588_GRF_HDMITX1_ENABLE_SHIFT		4
603 
604 #define RK3588_PMU_BISR_CON3			0x20C
605 #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT	9
606 #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT	10
607 #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT	11
608 #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT	12
609 #define RK3588_PD_ESMART_REPAIR_EN_SHIFT	15
610 
611 #define RK3588_PMU_BISR_STATUS5			0x294
612 #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI	9
613 #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI	10
614 #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI	11
615 #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI	12
616 #define RK3588_PD_ESMART_PWR_STAT_SHIFI		15
617 
618 #define VOP2_LAYER_MAX				8
619 
620 #define VOP_FEATURE_OUTPUT_10BIT		BIT(0)
621 
622 enum vop2_csc_format {
623 	CSC_BT601L,
624 	CSC_BT709L,
625 	CSC_BT601F,
626 	CSC_BT2020,
627 };
628 
629 enum vop2_pol {
630 	HSYNC_POSITIVE = 0,
631 	VSYNC_POSITIVE = 1,
632 	DEN_NEGATIVE   = 2,
633 	DCLK_INVERT    = 3
634 };
635 
636 enum vop2_bcsh_out_mode {
637 	BCSH_OUT_MODE_BLACK,
638 	BCSH_OUT_MODE_BLUE,
639 	BCSH_OUT_MODE_COLOR_BAR,
640 	BCSH_OUT_MODE_NORMAL_VIDEO,
641 };
642 
643 #define _VOP_REG(off, _mask, _shift, _write_mask) \
644 		{ \
645 		 .offset = off, \
646 		 .mask = _mask, \
647 		 .shift = _shift, \
648 		 .write_mask = _write_mask, \
649 		}
650 
651 #define VOP_REG(off, _mask, _shift) \
652 		_VOP_REG(off, _mask, _shift, false)
653 enum dither_down_mode {
654 	RGB888_TO_RGB565 = 0x0,
655 	RGB888_TO_RGB666 = 0x1
656 };
657 
658 enum vop2_video_ports_id {
659 	VOP2_VP0,
660 	VOP2_VP1,
661 	VOP2_VP2,
662 	VOP2_VP3,
663 	VOP2_VP_MAX,
664 };
665 
666 enum vop2_layer_type {
667 	CLUSTER_LAYER = 0,
668 	ESMART_LAYER = 1,
669 	SMART_LAYER = 2,
670 };
671 
672 /* This define must same with kernel win phy id */
673 enum vop2_layer_phy_id {
674 	ROCKCHIP_VOP2_CLUSTER0 = 0,
675 	ROCKCHIP_VOP2_CLUSTER1,
676 	ROCKCHIP_VOP2_ESMART0,
677 	ROCKCHIP_VOP2_ESMART1,
678 	ROCKCHIP_VOP2_SMART0,
679 	ROCKCHIP_VOP2_SMART1,
680 	ROCKCHIP_VOP2_CLUSTER2,
681 	ROCKCHIP_VOP2_CLUSTER3,
682 	ROCKCHIP_VOP2_ESMART2,
683 	ROCKCHIP_VOP2_ESMART3,
684 	ROCKCHIP_VOP2_LAYER_MAX,
685 };
686 
687 enum vop2_scale_up_mode {
688 	VOP2_SCALE_UP_NRST_NBOR,
689 	VOP2_SCALE_UP_BIL,
690 	VOP2_SCALE_UP_BIC,
691 };
692 
693 enum vop2_scale_down_mode {
694 	VOP2_SCALE_DOWN_NRST_NBOR,
695 	VOP2_SCALE_DOWN_BIL,
696 	VOP2_SCALE_DOWN_AVG,
697 };
698 
699 enum scale_mode {
700 	SCALE_NONE = 0x0,
701 	SCALE_UP   = 0x1,
702 	SCALE_DOWN = 0x2
703 };
704 
705 struct vop2_layer {
706 	u8 id;
707 	/**
708 	 * @win_phys_id: window id of the layer selected.
709 	 * Every layer must make sure to select different
710 	 * windows of others.
711 	 */
712 	u8 win_phys_id;
713 };
714 
715 struct vop2_power_domain_data {
716 	bool is_parent_needed;
717 	u8 pd_en_shift;
718 	u8 pd_status_shift;
719 	u8 pmu_status_shift;
720 	u8 bisr_en_status_shift;
721 	u8 parent_phy_id;
722 };
723 
724 struct vop2_win_data {
725 	char *name;
726 	u8 phys_id;
727 	enum vop2_layer_type type;
728 	u8 win_sel_port_offset;
729 	u8 layer_sel_win_id;
730 	u32 reg_offset;
731 	struct vop2_power_domain_data *pd_data;
732 };
733 
734 struct vop2_vp_data {
735 	u32 feature;
736 	u8 pre_scan_max_dly;
737 	struct vop_rect max_output;
738 	u32 max_dclk;
739 };
740 
741 struct vop2_plane_table {
742 	enum vop2_layer_phy_id plane_id;
743 	enum vop2_layer_type plane_type;
744 };
745 
746 struct vop2_vp_plane_mask {
747 	u8 primary_plane_id; /* use this win to show logo */
748 	u8 attached_layers_nr; /* number layers attach to this vp */
749 	u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
750 	u32 plane_mask;
751 	int cursor_plane_id;
752 };
753 
754 struct vop2_data {
755 	u32 version;
756 	struct vop2_vp_data *vp_data;
757 	struct vop2_win_data *win_data;
758 	struct vop2_vp_plane_mask *plane_mask;
759 	struct vop2_plane_table *plane_table;
760 	u8 nr_vps;
761 	u8 nr_layers;
762 	u8 nr_mixers;
763 	u8 nr_gammas;
764 	u8 nr_dscs;
765 	u32 reg_len;
766 };
767 
768 struct vop2 {
769 	u32 *regsbak;
770 	void *regs;
771 	void *grf;
772 	void *vop_grf;
773 	void *vo1_grf;
774 	void *sys_pmu;
775 	u32 reg_len;
776 	u32 version;
777 	bool global_init;
778 	const struct vop2_data *data;
779 	struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
780 };
781 
782 static struct vop2 *rockchip_vop2;
783 /*
784  * bli_sd_factor = (src - 1) / (dst - 1) << 12;
785  * avg_sd_factor:
786  * bli_su_factor:
787  * bic_su_factor:
788  * = (src - 1) / (dst - 1) << 16;
789  *
790  * gt2 enable: dst get one line from two line of the src
791  * gt4 enable: dst get one line from four line of the src.
792  *
793  */
794 #define VOP2_BILI_SCL_DN(src, dst)	(((src - 1) << 12) / (dst - 1))
795 #define VOP2_COMMON_SCL(src, dst)	(((src - 1) << 16) / (dst - 1))
796 
797 #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)	 \
798 				(fac * (dst - 1) >> 12 < (src - 1))
799 #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
800 				(fac * (dst - 1) >> 16 < (src - 1))
801 
802 static uint16_t vop2_scale_factor(enum scale_mode mode,
803 				  int32_t filter_mode,
804 				  uint32_t src, uint32_t dst)
805 {
806 	uint32_t fac = 0;
807 	int i = 0;
808 
809 	if (mode == SCALE_NONE)
810 		return 0;
811 
812 	/*
813 	 * A workaround to avoid zero div.
814 	 */
815 	if ((dst == 1) || (src == 1)) {
816 		dst = dst + 1;
817 		src = src + 1;
818 	}
819 
820 	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
821 		fac = VOP2_BILI_SCL_DN(src, dst);
822 		for (i = 0; i < 100; i++) {
823 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
824 				break;
825 			fac -= 1;
826 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
827 		}
828 	} else {
829 		fac = VOP2_COMMON_SCL(src, dst);
830 		for (i = 0; i < 100; i++) {
831 			if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
832 				break;
833 			fac -= 1;
834 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
835 		}
836 	}
837 
838 	return fac;
839 }
840 
841 static inline enum scale_mode scl_get_scl_mode(int src, int dst)
842 {
843 	if (src < dst)
844 		return SCALE_UP;
845 	else if (src > dst)
846 		return SCALE_DOWN;
847 
848 	return SCALE_NONE;
849 }
850 
851 static u8 rk3588_vop2_vp_primary_plane_order[VOP2_VP_MAX] = {
852 	ROCKCHIP_VOP2_ESMART0,
853 	ROCKCHIP_VOP2_ESMART1,
854 	ROCKCHIP_VOP2_ESMART2,
855 	ROCKCHIP_VOP2_ESMART3,
856 };
857 
858 static u8 rk3568_vop2_vp_primary_plane_order[VOP2_VP_MAX] = {
859 	ROCKCHIP_VOP2_SMART0,
860 	ROCKCHIP_VOP2_SMART1,
861 	ROCKCHIP_VOP2_ESMART1,
862 };
863 
864 static inline int interpolate(int x1, int y1, int x2, int y2, int x)
865 {
866 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
867 }
868 
869 static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask)
870 {
871 	int i = 0;
872 	u8 *vop2_vp_primary_plane_order;
873 	u8 default_primary_plane;
874 
875 	if (vop2->version == VOP_VERSION_RK3588) {
876 		vop2_vp_primary_plane_order = rk3588_vop2_vp_primary_plane_order;
877 		default_primary_plane = ROCKCHIP_VOP2_ESMART0;
878 	} else {
879 		vop2_vp_primary_plane_order = rk3568_vop2_vp_primary_plane_order;
880 		default_primary_plane = ROCKCHIP_VOP2_SMART0;
881 	}
882 
883 	for (i = 0; i < vop2->data->nr_vps; i++) {
884 		if (plane_mask & BIT(vop2_vp_primary_plane_order[i]))
885 			return vop2_vp_primary_plane_order[i];
886 	}
887 
888 	return default_primary_plane;
889 }
890 
891 static inline u16 scl_cal_scale(int src, int dst, int shift)
892 {
893 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
894 }
895 
896 static inline u16 scl_cal_scale2(int src, int dst)
897 {
898 	return ((src - 1) << 12) / (dst - 1);
899 }
900 
901 static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
902 {
903 	writel(v, vop2->regs + offset);
904 	vop2->regsbak[offset >> 2] = v;
905 }
906 
907 static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
908 {
909 	return readl(vop2->regs + offset);
910 }
911 
912 static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
913 				   u32 mask, u32 shift, u32 v,
914 				   bool write_mask)
915 {
916 	if (!mask)
917 		return;
918 
919 	if (write_mask) {
920 		v = ((v & mask) << shift) | (mask << (shift + 16));
921 	} else {
922 		u32 cached_val = vop2->regsbak[offset >> 2];
923 
924 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
925 		vop2->regsbak[offset >> 2] = v;
926 	}
927 
928 	writel(v, vop2->regs + offset);
929 }
930 
931 static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
932 				   u32 mask, u32 shift, u32 v)
933 {
934 	u32 val = 0;
935 
936 	val = (v << shift) | (mask << (shift + 16));
937 	writel(val, grf_base + offset);
938 }
939 
940 static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
941 				  u32 mask, u32 shift)
942 {
943 	return (readl(grf_base + offset) >> shift) & mask;
944 }
945 
946 static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
947 {
948 	return us * mode->clock / mode->htotal / 1000;
949 }
950 
951 static char* get_output_if_name(u32 output_if, char *name)
952 {
953 	if (output_if & VOP_OUTPUT_IF_RGB)
954 		strcat(name, " RGB");
955 	if (output_if & VOP_OUTPUT_IF_BT1120)
956 		strcat(name, " BT1120");
957 	if (output_if & VOP_OUTPUT_IF_BT656)
958 		strcat(name, " BT656");
959 	if (output_if & VOP_OUTPUT_IF_LVDS0)
960 		strcat(name, " LVDS0");
961 	if (output_if & VOP_OUTPUT_IF_LVDS1)
962 		strcat(name, " LVDS1");
963 	if (output_if & VOP_OUTPUT_IF_MIPI0)
964 		strcat(name, " MIPI0");
965 	if (output_if & VOP_OUTPUT_IF_MIPI1)
966 		strcat(name, " MIPI1");
967 	if (output_if & VOP_OUTPUT_IF_eDP0)
968 		strcat(name, " eDP0");
969 	if (output_if & VOP_OUTPUT_IF_eDP1)
970 		strcat(name, " eDP1");
971 	if (output_if & VOP_OUTPUT_IF_DP0)
972 		strcat(name, " DP0");
973 	if (output_if & VOP_OUTPUT_IF_DP1)
974 		strcat(name, " DP1");
975 	if (output_if & VOP_OUTPUT_IF_HDMI0)
976 		strcat(name, " HDMI0");
977 	if (output_if & VOP_OUTPUT_IF_HDMI1)
978 		strcat(name, " HDMI1");
979 
980 	return name;
981 }
982 
983 static char *get_plane_name(int plane_id, char *name)
984 {
985 	switch (plane_id) {
986 	case ROCKCHIP_VOP2_CLUSTER0:
987 		strcat(name, "Cluster0");
988 		break;
989 	case ROCKCHIP_VOP2_CLUSTER1:
990 		strcat(name, "Cluster1");
991 		break;
992 	case ROCKCHIP_VOP2_ESMART0:
993 		strcat(name, "Esmart0");
994 		break;
995 	case ROCKCHIP_VOP2_ESMART1:
996 		strcat(name, "Esmart1");
997 		break;
998 	case ROCKCHIP_VOP2_SMART0:
999 		strcat(name, "Smart0");
1000 		break;
1001 	case ROCKCHIP_VOP2_SMART1:
1002 		strcat(name, "Smart1");
1003 		break;
1004 	case ROCKCHIP_VOP2_CLUSTER2:
1005 		strcat(name, "Cluster2");
1006 		break;
1007 	case ROCKCHIP_VOP2_CLUSTER3:
1008 		strcat(name, "Cluster3");
1009 		break;
1010 	case ROCKCHIP_VOP2_ESMART2:
1011 		strcat(name, "Esmart2");
1012 		break;
1013 	case ROCKCHIP_VOP2_ESMART3:
1014 		strcat(name, "Esmart3");
1015 		break;
1016 	}
1017 
1018 	return name;
1019 }
1020 
1021 static bool is_yuv_output(u32 bus_format)
1022 {
1023 	switch (bus_format) {
1024 	case MEDIA_BUS_FMT_YUV8_1X24:
1025 	case MEDIA_BUS_FMT_YUV10_1X30:
1026 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1027 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1028 	case MEDIA_BUS_FMT_YUYV8_2X8:
1029 	case MEDIA_BUS_FMT_YVYU8_2X8:
1030 	case MEDIA_BUS_FMT_UYVY8_2X8:
1031 	case MEDIA_BUS_FMT_VYUY8_2X8:
1032 	case MEDIA_BUS_FMT_YUYV8_1X16:
1033 	case MEDIA_BUS_FMT_YVYU8_1X16:
1034 	case MEDIA_BUS_FMT_UYVY8_1X16:
1035 	case MEDIA_BUS_FMT_VYUY8_1X16:
1036 		return true;
1037 	default:
1038 		return false;
1039 	}
1040 }
1041 
1042 static int vop2_convert_csc_mode(int csc_mode)
1043 {
1044 	switch (csc_mode) {
1045 	case V4L2_COLORSPACE_SMPTE170M:
1046 	case V4L2_COLORSPACE_470_SYSTEM_M:
1047 	case V4L2_COLORSPACE_470_SYSTEM_BG:
1048 		return CSC_BT601L;
1049 	case V4L2_COLORSPACE_REC709:
1050 	case V4L2_COLORSPACE_SMPTE240M:
1051 	case V4L2_COLORSPACE_DEFAULT:
1052 		return CSC_BT709L;
1053 	case V4L2_COLORSPACE_JPEG:
1054 		return CSC_BT601F;
1055 	case V4L2_COLORSPACE_BT2020:
1056 		return CSC_BT2020;
1057 	default:
1058 		return CSC_BT709L;
1059 	}
1060 }
1061 
1062 static bool is_uv_swap(u32 bus_format, u32 output_mode)
1063 {
1064 	/*
1065 	 * FIXME:
1066 	 *
1067 	 * There is no media type for YUV444 output,
1068 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
1069 	 * yuv format.
1070 	 *
1071 	 * From H/W testing, YUV444 mode need a rb swap.
1072 	 */
1073 	if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1074 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1075 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
1076 	     output_mode == ROCKCHIP_OUT_MODE_P888))
1077 		return true;
1078 	else
1079 		return false;
1080 }
1081 
1082 static inline bool is_hot_plug_devices(int output_type)
1083 {
1084 	switch (output_type) {
1085 	case DRM_MODE_CONNECTOR_HDMIA:
1086 	case DRM_MODE_CONNECTOR_HDMIB:
1087 	case DRM_MODE_CONNECTOR_TV:
1088 	case DRM_MODE_CONNECTOR_DisplayPort:
1089 	case DRM_MODE_CONNECTOR_VGA:
1090 	case DRM_MODE_CONNECTOR_Unknown:
1091 		return true;
1092 	default:
1093 		return false;
1094 	}
1095 }
1096 
1097 static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1098 {
1099 	int i = 0;
1100 
1101 	for (i = 0; i < vop2->data->nr_layers; i++) {
1102 		if (vop2->data->win_data[i].phys_id == phys_id)
1103 			return &vop2->data->win_data[i];
1104 	}
1105 
1106 	return NULL;
1107 }
1108 
1109 static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1110 					struct display_state *state)
1111 {
1112 	struct connector_state *conn_state = &state->conn_state;
1113 	struct crtc_state *cstate = &state->crtc_state;
1114 	struct resource gamma_res;
1115 	fdt_size_t lut_size;
1116 	int i, lut_len, ret = 0;
1117 	u32 *lut_regs;
1118 	u32 *lut_val;
1119 	u32 r, g, b;
1120 	u32 vp_offset = cstate->crtc_id * 0x100;
1121 	struct base2_disp_info *disp_info = conn_state->disp_info;
1122 	static int gamma_lut_en_num = 1;
1123 
1124 	if (gamma_lut_en_num > vop2->data->nr_gammas) {
1125 		printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
1126 		return 0;
1127 	}
1128 
1129 	if (!disp_info)
1130 		return 0;
1131 
1132 	if (!disp_info->gamma_lut_data.size)
1133 		return 0;
1134 
1135 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
1136 	if (ret)
1137 		printf("failed to get gamma lut res\n");
1138 	lut_regs = (u32 *)gamma_res.start;
1139 	lut_size = gamma_res.end - gamma_res.start + 1;
1140 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
1141 		printf("failed to get gamma lut register\n");
1142 		return 0;
1143 	}
1144 	lut_len = lut_size / 4;
1145 	if (lut_len != 256 && lut_len != 1024) {
1146 		printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
1147 		return 0;
1148 	}
1149 	lut_val = (u32 *)calloc(1, lut_size);
1150 	for (i = 0; i < lut_len; i++) {
1151 		r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
1152 		g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
1153 		b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
1154 
1155 		lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
1156 	}
1157 
1158 	for (i = 0; i < lut_len; i++)
1159 		writel(lut_val[i], lut_regs + i);
1160 
1161 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1162 			GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1163 			cstate->crtc_id , false);
1164 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1165 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1166 	gamma_lut_en_num++;
1167 
1168 	return 0;
1169 }
1170 
1171 static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
1172 					struct display_state *state)
1173 {
1174 	struct connector_state *conn_state = &state->conn_state;
1175 	struct crtc_state *cstate = &state->crtc_state;
1176 	int i, cubic_lut_len;
1177 	u32 vp_offset = cstate->crtc_id * 0x100;
1178 	struct base2_disp_info *disp_info = conn_state->disp_info;
1179 	struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
1180 	u32 *cubic_lut_addr;
1181 
1182 	if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
1183 		return 0;
1184 
1185 	if (!disp_info->cubic_lut_data.size)
1186 		return 0;
1187 
1188 	cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
1189 	cubic_lut_len = disp_info->cubic_lut_data.size;
1190 
1191 	for (i = 0; i < cubic_lut_len / 2; i++) {
1192 		*cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
1193 					((lut->lgreen[2 * i] & 0xfff) << 12) +
1194 					((lut->lblue[2 * i] & 0xff) << 24);
1195 		*cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
1196 					((lut->lred[2 * i + 1] & 0xfff) << 4) +
1197 					((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
1198 					((lut->lblue[2 * i + 1] & 0xf) << 28);
1199 		*cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
1200 		*cubic_lut_addr++ = 0;
1201 	}
1202 
1203 	if (cubic_lut_len % 2) {
1204 		*cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
1205 					((lut->lgreen[2 * i] & 0xfff) << 12) +
1206 					((lut->lblue[2 * i] & 0xff) << 24);
1207 		*cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
1208 		*cubic_lut_addr++ = 0;
1209 		*cubic_lut_addr = 0;
1210 	}
1211 
1212 	vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
1213 		    get_cubic_lut_buffer(cstate->crtc_id));
1214 	vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
1215 			EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
1216 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
1217 			EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
1218 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
1219 			EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
1220 
1221 	return 0;
1222 }
1223 
1224 static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
1225 {
1226 	struct connector_state *conn_state = &state->conn_state;
1227 	struct base_bcsh_info *bcsh_info;
1228 	struct crtc_state *cstate = &state->crtc_state;
1229 	int brightness, contrast, saturation, hue, sin_hue, cos_hue;
1230 	bool bcsh_en = false, post_r2y_en = false, post_y2r_en = false;
1231 	u32 vp_offset = (cstate->crtc_id * 0x100);
1232 	int post_csc_mode;
1233 
1234 	if (!conn_state->disp_info)
1235 		return;
1236 	bcsh_info = &conn_state->disp_info->bcsh_info;
1237 	if (!bcsh_info)
1238 		return;
1239 
1240 	if (bcsh_info->brightness != 50 ||
1241 	    bcsh_info->contrast != 50 ||
1242 	    bcsh_info->saturation != 50 || bcsh_info->hue != 50)
1243 		bcsh_en = true;
1244 
1245 	if (bcsh_en) {
1246 		if (!cstate->yuv_overlay)
1247 			post_r2y_en = 1;
1248 		if (!is_yuv_output(conn_state->bus_format))
1249 			post_y2r_en = 1;
1250 	} else {
1251 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
1252 			post_r2y_en = 1;
1253 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
1254 			post_y2r_en = 1;
1255 	}
1256 
1257 	post_csc_mode = vop2_convert_csc_mode(conn_state->color_space);
1258 
1259 
1260 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
1261 			BCSH_CTRL_R2Y_SHIFT, post_r2y_en, false);
1262 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
1263 			BCSH_CTRL_Y2R_SHIFT, post_y2r_en, false);
1264 
1265 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
1266 			BCSH_CTRL_R2Y_CSC_MODE_SHIFT, post_csc_mode, false);
1267 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
1268 			BCSH_CTRL_Y2R_CSC_MODE_SHIFT, post_csc_mode, false);
1269 	if (!bcsh_en) {
1270 		vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1271 				BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
1272 		return;
1273 	}
1274 
1275 	if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
1276 		brightness = interpolate(0, -128, 100, 127,
1277 					 bcsh_info->brightness);
1278 	else
1279 		brightness = interpolate(0, -32, 100, 31,
1280 					 bcsh_info->brightness);
1281 	contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
1282 	saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
1283 	hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
1284 
1285 
1286 	/*
1287 	 *  a:[-30~0):
1288 	 *    sin_hue = 0x100 - sin(a)*256;
1289 	 *    cos_hue = cos(a)*256;
1290 	 *  a:[0~30]
1291 	 *    sin_hue = sin(a)*256;
1292 	 *    cos_hue = cos(a)*256;
1293 	 */
1294 	sin_hue = fixp_sin32(hue) >> 23;
1295 	cos_hue = fixp_cos32(hue) >> 23;
1296 
1297 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1298 			BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
1299 			brightness, false);
1300 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1301 			BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, contrast, false);
1302 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1303 			BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
1304 			saturation * contrast / 0x100, false);
1305 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1306 			BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, sin_hue, false);
1307 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1308 			BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, cos_hue, false);
1309 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1310 			 BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
1311 			BCSH_OUT_MODE_NORMAL_VIDEO, false);
1312 	vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1313 			BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
1314 }
1315 
1316 static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
1317 {
1318 	struct connector_state *conn_state = &state->conn_state;
1319 	struct drm_display_mode *mode = &conn_state->mode;
1320 	struct crtc_state *cstate = &state->crtc_state;
1321 	u32 vp_offset = (cstate->crtc_id * 0x100);
1322 	u16 vtotal = mode->crtc_vtotal;
1323 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
1324 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
1325 	u16 hdisplay = mode->crtc_hdisplay;
1326 	u16 vdisplay = mode->crtc_vdisplay;
1327 	u16 hsize =
1328 	    hdisplay * (conn_state->overscan.left_margin +
1329 			conn_state->overscan.right_margin) / 200;
1330 	u16 vsize =
1331 	    vdisplay * (conn_state->overscan.top_margin +
1332 			conn_state->overscan.bottom_margin) / 200;
1333 	u16 hact_end, vact_end;
1334 	u32 val;
1335 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
1336 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
1337 
1338 	hsize = round_down(hsize, 2);
1339 	vsize = round_down(vsize, 2);
1340 
1341 	hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
1342 	hact_end = hact_st + hsize;
1343 	val = hact_st << 16;
1344 	val |= hact_end;
1345 
1346 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
1347 	vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
1348 	vact_end = vact_st + vsize;
1349 	val = vact_st << 16;
1350 	val |= vact_end;
1351 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
1352 	val = scl_cal_scale2(vdisplay, vsize) << 16;
1353 	val |= scl_cal_scale2(hdisplay, hsize);
1354 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
1355 #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
1356 #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
1357 	vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
1358 		    POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
1359 		    POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
1360 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1361 		u16 vact_st_f1 = vtotal + vact_st + 1;
1362 		u16 vact_end_f1 = vact_st_f1 + vsize;
1363 
1364 		val = vact_st_f1 << 16 | vact_end_f1;
1365 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
1366 	}
1367 
1368 	bg_ovl_dly = cstate->crtc->vps[cstate->crtc_id].bg_ovl_dly;
1369 	bg_dly =  vop2->data->vp_data[cstate->crtc_id].pre_scan_max_dly;
1370 	bg_dly -= bg_ovl_dly;
1371 	pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
1372 	if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
1373 		hsync_len = 8;
1374 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
1375 	vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + cstate->crtc_id * 4,
1376 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
1377 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + vp_offset, pre_scan_dly);
1378 }
1379 
1380 static int vop2_wait_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
1381 {
1382 	int val = 0;
1383 	int shift = 0;
1384 	bool is_bisr_en = false;
1385 
1386 	is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK,
1387 				    pd_data->bisr_en_status_shift);
1388 	if (is_bisr_en) {
1389 		shift = pd_data->pmu_status_shift;
1390 		return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
1391 					  !((val >> shift) & 0x1), 50 * 1000);
1392 	} else {
1393 		shift = pd_data->pd_status_shift;
1394 		return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
1395 					  !((val >> shift) & 0x1), 50 * 1000);
1396 	}
1397 }
1398 
1399 static int vop2_power_domain_on(struct vop2 *vop2, int plane_id)
1400 {
1401 	struct vop2_win_data *win_data;
1402 	struct vop2_power_domain_data *pd_data;
1403 	int ret = 0;
1404 
1405 	win_data = vop2_find_win_by_phys_id(vop2, plane_id);
1406 	if (!win_data) {
1407 		printf("can't find win_data by phys_id\n");
1408 		return -EINVAL;
1409 	}
1410 	pd_data = win_data->pd_data;
1411 	if (pd_data->is_parent_needed) {
1412 		ret = vop2_power_domain_on(vop2, pd_data->parent_phy_id);
1413 		if (ret) {
1414 			printf("can't open parent power domain\n");
1415 			return -EINVAL;
1416 		}
1417 	}
1418 
1419 	vop2_mask_write(vop2, RK3568_SYS_PD_CTRL, EN_MASK, pd_data->pd_en_shift, 0, false);
1420 	ret = vop2_wait_power_domain_on(vop2, pd_data);
1421 	if (ret) {
1422 		printf("wait vop2 power domain timeout\n");
1423 		return ret;
1424 	}
1425 
1426 	return 0;
1427 }
1428 
1429 static void rk3588_vop2_regsbak(struct vop2 *vop2)
1430 {
1431 	u32 *base = vop2->regs;
1432 	int i = 0;
1433 
1434 	/*
1435 	 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
1436 	 */
1437 	for (i = 0; i < (vop2->reg_len >> 2); i++)
1438 		vop2->regsbak[i] = base[i];
1439 }
1440 
1441 static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
1442 {
1443 	struct crtc_state *cstate = &state->crtc_state;
1444 	int i, j, port_mux = 0, total_used_layer = 0;
1445 	u8 shift = 0;
1446 	int layer_phy_id = 0;
1447 	u32 layer_nr = 0;
1448 	struct vop2_win_data *win_data;
1449 	struct vop2_vp_plane_mask *plane_mask;
1450 
1451 	if (vop2->global_init)
1452 		return;
1453 
1454 	/* OTP must enable at the first time, otherwise mirror layer register is error */
1455 	if (soc_is_rk3566())
1456 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
1457 				OTP_WIN_EN_SHIFT, 1, false);
1458 
1459 	if (cstate->crtc->assign_plane) {/* dts assign plane */
1460 		u32 plane_mask;
1461 		int primary_plane_id;
1462 
1463 		for (i = 0; i < vop2->data->nr_vps; i++) {
1464 			plane_mask = cstate->crtc->vps[i].plane_mask;
1465 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
1466 			layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */
1467 			vop2->vp_plane_mask[i].attached_layers_nr = layer_nr;
1468 			primary_plane_id = vop2_get_primary_plane(vop2, plane_mask);
1469 			vop2->vp_plane_mask[i].primary_plane_id =  primary_plane_id;
1470 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
1471 
1472 			/* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/
1473 			for (j = 0; j < layer_nr; j++) {
1474 				vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
1475 				plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
1476 			}
1477 		}
1478 	} else {/* need soft assign plane mask */
1479 		/* find the first unplug devices and set it as main display */
1480 		int main_vp_index = -1;
1481 		int active_vp_num = 0;
1482 
1483 		for (i = 0; i < vop2->data->nr_vps; i++) {
1484 			if (cstate->crtc->vps[i].enable)
1485 				active_vp_num++;
1486 		}
1487 		printf("VOP have %d active VP\n", active_vp_num);
1488 
1489 		if (soc_is_rk3566() && active_vp_num > 2)
1490 			printf("ERROR: rk3566 only support 2 display output!!\n");
1491 		plane_mask = vop2->data->plane_mask;
1492 		plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
1493 
1494 		for (i = 0; i < vop2->data->nr_vps; i++) {
1495 			if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
1496 				vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/
1497 				main_vp_index = i;
1498 				break;
1499 			}
1500 		}
1501 
1502 		/* if no find unplug devices, use vp0 as main display */
1503 		if (main_vp_index < 0) {
1504 			main_vp_index = 0;
1505 			vop2->vp_plane_mask[0] = plane_mask[0];
1506 		}
1507 
1508 		j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */
1509 
1510 		/* init other display except main display */
1511 		for (i = 0; i < vop2->data->nr_vps; i++) {
1512 			if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */
1513 				continue;
1514 			vop2->vp_plane_mask[i] = plane_mask[j++];
1515 		}
1516 
1517 		/* store plane mask for vop2_fixup_dts */
1518 		for (i = 0; i < vop2->data->nr_vps; i++) {
1519 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
1520 			/* rk3566 only support 3+3 policy */
1521 			if (soc_is_rk3566() && active_vp_num == 1) {
1522 				if (cstate->crtc->vps[i].enable) {
1523 					for (j = 0; j < 3; j++) {
1524 						layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1525 						vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
1526 					}
1527 				}
1528 			} else {
1529 				for (j = 0; j < layer_nr; j++) {
1530 					layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1531 					vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
1532 				}
1533 			}
1534 		}
1535 	}
1536 
1537 	if (vop2->version == VOP_VERSION_RK3588) {
1538 		for (i = 0; i < vop2->data->nr_vps; i++) {
1539 			if (cstate->crtc->vps[i].enable) {
1540 				if (vop2_power_domain_on(vop2, vop2->vp_plane_mask[i].primary_plane_id))
1541 					printf("open vp[%d] plane pd fail\n", i);
1542 			}
1543 		}
1544 	}
1545 
1546 	if (vop2->version == VOP_VERSION_RK3588)
1547 		rk3588_vop2_regsbak(vop2);
1548 	else
1549 		memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
1550 
1551 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
1552 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
1553 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
1554 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
1555 
1556 	for (i = 0; i < vop2->data->nr_vps; i++) {
1557 		printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
1558 		for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
1559 			printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]);
1560 		printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id);
1561 	}
1562 
1563 	shift = 0;
1564 	/* layer sel win id */
1565 	for (i = 0; i < vop2->data->nr_vps; i++) {
1566 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
1567 		for (j = 0; j < layer_nr; j++) {
1568 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1569 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
1570 			vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
1571 					shift, win_data->layer_sel_win_id, false);
1572 			shift += 4;
1573 		}
1574 	}
1575 
1576 	/* win sel port */
1577 	for (i = 0; i < vop2->data->nr_vps; i++) {
1578 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
1579 		for (j = 0; j < layer_nr; j++) {
1580 			if (!vop2->vp_plane_mask[i].attached_layers[j])
1581 				continue;
1582 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1583 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
1584 			shift = win_data->win_sel_port_offset * 2;
1585 			vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
1586 					LAYER_SEL_PORT_SHIFT + shift, i, false);
1587 		}
1588 	}
1589 
1590 	/**
1591 	 * port mux config
1592 	 */
1593 	for (i = 0; i < vop2->data->nr_vps; i++) {
1594 		shift = i * 4;
1595 		if (vop2->vp_plane_mask[i].attached_layers_nr) {
1596 			total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
1597 			port_mux = total_used_layer - 1;
1598 		} else {
1599 			port_mux = 8;
1600 		}
1601 
1602 		if (i == vop2->data->nr_vps - 1)
1603 			port_mux = vop2->data->nr_mixers;
1604 
1605 		cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
1606 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
1607 				PORT_MUX_SHIFT + shift, port_mux, false);
1608 	}
1609 
1610 	if (vop2->version == VOP_VERSION_RK3568)
1611 		vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
1612 
1613 	vop2->global_init = true;
1614 }
1615 
1616 static int vop2_initial(struct vop2 *vop2, struct display_state *state)
1617 {
1618 	struct crtc_state *cstate = &state->crtc_state;
1619 	int ret;
1620 
1621 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1622 	ret = clk_set_defaults(cstate->dev);
1623 	if (ret)
1624 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1625 
1626 	rockchip_vop2_gamma_lut_init(vop2, state);
1627 	rockchip_vop2_cubic_lut_init(vop2, state);
1628 
1629 	return 0;
1630 }
1631 
1632 /*
1633  * VOP2 have multi video ports.
1634  * video port ------- crtc
1635  */
1636 static int rockchip_vop2_preinit(struct display_state *state)
1637 {
1638 	struct crtc_state *cstate = &state->crtc_state;
1639 	const struct vop2_data *vop2_data = cstate->crtc->data;
1640 
1641 	if (!rockchip_vop2) {
1642 		rockchip_vop2 = calloc(1, sizeof(struct vop2));
1643 		if (!rockchip_vop2)
1644 			return -ENOMEM;
1645 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
1646 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
1647 		rockchip_vop2->reg_len = RK3568_MAX_REG;
1648 		rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1649 		if (rockchip_vop2->grf <= 0)
1650 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
1651 		rockchip_vop2->version = vop2_data->version;
1652 		rockchip_vop2->data = vop2_data;
1653 		if (rockchip_vop2->version == VOP_VERSION_RK3588) {
1654 			rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF);
1655 			if (rockchip_vop2->vop_grf <= 0)
1656 				printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf);
1657 			rockchip_vop2->vo1_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VO_GRF);
1658 			if (rockchip_vop2->vo1_grf <= 0)
1659 				printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf);
1660 			rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
1661 			if (rockchip_vop2->vo1_grf <= 0)
1662 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu);
1663 		}
1664 	}
1665 
1666 	cstate->private = rockchip_vop2;
1667 	cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
1668 	cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
1669 
1670 	vop2_global_initial(rockchip_vop2, state);
1671 
1672 	return 0;
1673 }
1674 
1675 /*
1676  * calc the dclk on rk3588
1677  * the available div of dclk is 1, 2, 4
1678  *
1679  */
1680 static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
1681 {
1682 	if (child_clk * 4 <= max_dclk)
1683 		return child_clk * 4;
1684 	else if (child_clk * 2 <= max_dclk)
1685 		return child_clk * 2;
1686 	else if (child_clk <= max_dclk)
1687 		return child_clk;
1688 	else
1689 		return 0;
1690 }
1691 
1692 /*
1693  * 4 pixclk/cycle on rk3588
1694  * RGB/eDP/HDMI: if_pixclk >= dclk_core
1695  * DP: dp_pixclk = dclk_out <= dclk_core
1696  * DSI: mipi_pixclk <= dclk_out <= dclk_core
1697  */
1698 static unsigned long vop2_calc_cru_cfg(struct display_state *state,
1699 				       int *dclk_core_div, int *dclk_out_div,
1700 				       int *if_pixclk_div, int *if_dclk_div)
1701 {
1702 	struct crtc_state *cstate = &state->crtc_state;
1703 	struct connector_state *conn_state = &state->conn_state;
1704 	struct drm_display_mode *mode = &conn_state->mode;
1705 	struct vop2 *vop2 = cstate->private;
1706 	unsigned long v_pixclk = mode->clock;
1707 	unsigned long dclk_core_rate = v_pixclk >> 2;
1708 	unsigned long dclk_rate = v_pixclk;
1709 	unsigned long dclk_out_rate;
1710 	u64 if_dclk_rate;
1711 	u64 if_pixclk_rate;
1712 	int output_type = conn_state->type;
1713 	int output_mode = conn_state->output_mode;
1714 	int K = 1;
1715 
1716 	if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
1717 		/*
1718 		 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
1719 		 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
1720 		 */
1721 		if (output_mode == ROCKCHIP_OUT_MODE_YUV420)
1722 			K = 2;
1723 		if (conn_state->dsc_enable) {
1724 			if_pixclk_rate = conn_state->dsc_cds_clk << 1;
1725 			if_dclk_rate = conn_state->dsc_cds_clk;
1726 		} else {
1727 			if_pixclk_rate = (dclk_core_rate << 1) / K;
1728 			if_dclk_rate = dclk_core_rate / K;
1729 		}
1730 
1731 		dclk_rate = vop2_calc_dclk(if_pixclk_rate, vop2->data->vp_data->max_dclk);
1732 		if (!dclk_rate) {
1733 			printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n",
1734 			       vop2->data->vp_data->max_dclk, if_pixclk_rate);
1735 			return -EINVAL;
1736 		}
1737 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
1738 		*if_dclk_div = dclk_rate / if_dclk_rate;
1739 
1740 	} else if (output_type == DRM_MODE_CONNECTOR_eDP) {
1741 		/* edp_pixclk = edp_dclk > dclk_core */
1742 		if_pixclk_rate = v_pixclk / K;
1743 		if_dclk_rate = v_pixclk / K;
1744 		dclk_rate = if_pixclk_rate * K;
1745 		*dclk_core_div = dclk_rate / dclk_core_rate;
1746 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
1747 		*if_dclk_div = *if_pixclk_div;
1748 	} else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
1749 		if (output_mode == ROCKCHIP_OUT_MODE_YUV420)
1750 			dclk_out_rate = v_pixclk >> 3;
1751 		else
1752 			dclk_out_rate = v_pixclk >> 2;
1753 
1754 		dclk_rate = vop2_calc_dclk(dclk_core_rate, vop2->data->vp_data->max_dclk);
1755 		if (!dclk_rate) {
1756 			printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n",
1757 			       vop2->data->vp_data->max_dclk, dclk_core_rate);
1758 			return -EINVAL;
1759 		}
1760 		*dclk_out_div = dclk_rate / dclk_out_rate;
1761 		*dclk_core_div = dclk_rate / dclk_core_rate;
1762 
1763 	} else if (output_type == DRM_MODE_CONNECTOR_DSI) {
1764 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
1765 			K = 2;
1766 		if (conn_state->dsc_enable)
1767 			if_pixclk_rate = conn_state->dsc_cds_clk >> 1;
1768 		else
1769 			if_pixclk_rate = dclk_core_rate / K;
1770 		/* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
1771 		dclk_out_rate = if_pixclk_rate;
1772 		/* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
1773 		dclk_rate = dclk_core_rate;
1774 		*dclk_out_div = dclk_rate / dclk_out_rate;
1775 		*dclk_core_div = dclk_rate / dclk_core_rate;
1776 		*if_pixclk_div = 1;       /*mipi pixclk == dclk_out*/
1777 
1778 	} else if (output_type == DRM_MODE_CONNECTOR_DPI) {
1779 		dclk_rate = v_pixclk;
1780 		*dclk_core_div = dclk_rate / dclk_core_rate;
1781 	}
1782 
1783 	*if_pixclk_div = ilog2(*if_pixclk_div);
1784 	*if_dclk_div = ilog2(*if_dclk_div);
1785 	*dclk_core_div = ilog2(*dclk_core_div);
1786 	*dclk_out_div = ilog2(*dclk_out_div);
1787 
1788 	return dclk_rate;
1789 }
1790 
1791 static int vop2_calc_dsc_clk(struct connector_state *conn_state)
1792 {
1793 	struct drm_display_mode *mode = &conn_state->mode;
1794 	u64 v_pixclk = mode->clock * 1000LL; /* video timing pixclk */
1795 	u8 k = 1;
1796 
1797 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
1798 		k = 2;
1799 
1800 	conn_state->dsc_pxl_clk = v_pixclk;
1801 	do_div(conn_state->dsc_pxl_clk, (conn_state->dsc_slice_num * k));
1802 
1803 	conn_state->dsc_txp_clk = v_pixclk;
1804 	do_div(conn_state->dsc_txp_clk, (conn_state->dsc_pixel_num * k));
1805 
1806 	/* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
1807 	 * cds_dat_width = 96;
1808 	 * bits_per_pixel = [8-12];
1809 	 * As only support 1/2/4 div, so we set dsc_cds = crtc_clock / 8;
1810 	 */
1811 	conn_state->dsc_cds_clk = mode->crtc_clock / 8 * 1000;
1812 
1813 	return 0;
1814 }
1815 
1816 static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
1817 {
1818 	struct crtc_state *cstate = &state->crtc_state;
1819 	struct connector_state *conn_state = &state->conn_state;
1820 	struct drm_display_mode *mode = &conn_state->mode;
1821 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &conn_state->dsc_sink_cap;
1822 	struct vop2 *vop2 = cstate->private;
1823 	u32 vp_offset = (cstate->crtc_id * 0x100);
1824 	u16 hdisplay = mode->crtc_hdisplay;
1825 	int output_if = conn_state->output_if;
1826 	int dclk_core_div = 0;
1827 	int dclk_out_div = 0;
1828 	int if_pixclk_div = 0;
1829 	int if_dclk_div = 0;
1830 	unsigned long dclk_rate;
1831 	u32 val;
1832 
1833 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
1834 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
1835 
1836 	if (conn_state->dsc_enable) {
1837 		if (!vop2->data->nr_dscs) {
1838 			printf("No DSC\n");
1839 			return 0;
1840 		}
1841 		conn_state->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
1842 		conn_state->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width;
1843 		conn_state->dsc_pixel_num = conn_state->dsc_slice_num >= 4 ?
1844 					    4 : conn_state->dsc_slice_num >= 2 ? 2 : 1;
1845 		vop2_calc_dsc_clk(conn_state);
1846 	}
1847 
1848 	dclk_rate = vop2_calc_cru_cfg(state, &dclk_core_div, &dclk_out_div, &if_pixclk_div, &if_dclk_div);
1849 
1850 	if (output_if & VOP_OUTPUT_IF_RGB) {
1851 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
1852 				4, false);
1853 	}
1854 
1855 	if (output_if & VOP_OUTPUT_IF_BT1120) {
1856 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
1857 				3, false);
1858 	}
1859 
1860 	if (output_if & VOP_OUTPUT_IF_BT656) {
1861 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
1862 				2, false);
1863 	}
1864 
1865 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
1866 		if (cstate->crtc_id == 2)
1867 			val = 0;
1868 		else
1869 			val = 1;
1870 
1871 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
1872 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
1873 					RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
1874 
1875 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
1876 				1, false);
1877 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
1878 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
1879 				if_pixclk_div, false);
1880 
1881 		if (conn_state->hold_mode) {
1882 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
1883 					EN_MASK, EDPI_TE_EN, 1, false);
1884 
1885 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
1886 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
1887 		}
1888 	}
1889 
1890 	if (output_if & VOP_OUTPUT_IF_MIPI1) {
1891 		if (cstate->crtc_id == 2)
1892 			val = 0;
1893 		else if (cstate->crtc_id == 3)
1894 			val = 1;
1895 		else
1896 			val = 3; /*VP1*/
1897 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
1898 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
1899 					RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
1900 
1901 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
1902 				1, false);
1903 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
1904 				val, false);
1905 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
1906 				if_pixclk_div, false);
1907 
1908 		if (conn_state->hold_mode) {
1909 			/* UNDO: RK3588 VP1->DSC1->DSI1 only can support soft TE mode */
1910 			if (vop2->version == VOP_VERSION_RK3588 && val == 3)
1911 				vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
1912 						EN_MASK, EDPI_TE_EN, 0, false);
1913 			else
1914 				vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
1915 						EN_MASK, EDPI_TE_EN, 1, false);
1916 
1917 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
1918 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
1919 		}
1920 	}
1921 
1922 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
1923 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
1924 				RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
1925 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
1926 				MIPI_DUAL_EN_SHIFT, 1, false);
1927 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
1928 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
1929 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
1930 					false);
1931 	}
1932 
1933 	if (output_if & VOP_OUTPUT_IF_eDP0) {
1934 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
1935 				1, false);
1936 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
1937 				cstate->crtc_id, false);
1938 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
1939 				if_dclk_div, false);
1940 
1941 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
1942 				if_pixclk_div, false);
1943 
1944 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
1945 				RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
1946 	}
1947 
1948 	if (output_if & VOP_OUTPUT_IF_eDP1) {
1949 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
1950 				1, false);
1951 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
1952 				cstate->crtc_id, false);
1953 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
1954 				if_dclk_div, false);
1955 
1956 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
1957 				if_pixclk_div, false);
1958 	}
1959 
1960 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
1961 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
1962 				1, false);
1963 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
1964 				cstate->crtc_id, false);
1965 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
1966 				if_dclk_div, false);
1967 
1968 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
1969 				if_pixclk_div, false);
1970 	}
1971 
1972 	if (output_if & VOP_OUTPUT_IF_HDMI1) {
1973 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
1974 				1, false);
1975 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
1976 				cstate->crtc_id, false);
1977 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
1978 				if_dclk_div, false);
1979 
1980 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
1981 				if_pixclk_div, false);
1982 	}
1983 
1984 	if (output_if & VOP_OUTPUT_IF_DP0) {
1985 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
1986 				1, false);
1987 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
1988 				cstate->crtc_id, false);
1989 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
1990 				RK3588_DP0_PIN_POL_SHIFT, val, false);
1991 	}
1992 
1993 	if (output_if & VOP_OUTPUT_IF_DP1) {
1994 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
1995 				1, false);
1996 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
1997 				cstate->crtc_id, false);
1998 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
1999 				RK3588_DP1_PIN_POL_SHIFT, val, false);
2000 	}
2001 
2002 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
2003 			DCLK_CORE_DIV_SHIFT, dclk_core_div, false);
2004 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
2005 			DCLK_OUT_DIV_SHIFT, dclk_out_div, false);
2006 
2007 	return dclk_rate;
2008 }
2009 
2010 static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
2011 {
2012 	struct crtc_state *cstate = &state->crtc_state;
2013 	struct connector_state *conn_state = &state->conn_state;
2014 	struct drm_display_mode *mode = &conn_state->mode;
2015 	struct vop2 *vop2 = cstate->private;
2016 	u32 vp_offset = (cstate->crtc_id * 0x100);
2017 	bool dclk_inv;
2018 	u32 val;
2019 
2020 	dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1;
2021 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
2022 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
2023 
2024 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
2025 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
2026 				1, false);
2027 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2028 				RGB_MUX_SHIFT, cstate->crtc_id, false);
2029 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
2030 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
2031 	}
2032 
2033 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
2034 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
2035 				1, false);
2036 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
2037 				BT1120_EN_SHIFT, 1, false);
2038 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2039 				RGB_MUX_SHIFT, cstate->crtc_id, false);
2040 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
2041 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
2042 	}
2043 
2044 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
2045 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
2046 				1, false);
2047 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2048 				RGB_MUX_SHIFT, cstate->crtc_id, false);
2049 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
2050 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
2051 	}
2052 
2053 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
2054 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
2055 				1, false);
2056 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2057 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
2058 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
2059 				IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false);
2060 	}
2061 
2062 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
2063 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
2064 				1, false);
2065 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2066 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
2067 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
2068 				IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false);
2069 	}
2070 
2071 	if (conn_state->output_flags &
2072 	    (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE |
2073 	     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) {
2074 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2075 				LVDS_DUAL_EN_SHIFT, 1, false);
2076 		if (conn_state->output_flags &
2077 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
2078 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2079 					LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1,
2080 					false);
2081 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
2082 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2083 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
2084 	}
2085 
2086 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
2087 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
2088 				1, false);
2089 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2090 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
2091 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
2092 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
2093 	}
2094 
2095 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
2096 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
2097 				1, false);
2098 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2099 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
2100 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
2101 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
2102 	}
2103 
2104 	if (conn_state->output_flags &
2105 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
2106 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
2107 				MIPI_DUAL_EN_SHIFT, 1, false);
2108 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
2109 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2110 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
2111 					false);
2112 	}
2113 
2114 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
2115 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
2116 				1, false);
2117 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2118 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
2119 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
2120 				IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
2121 	}
2122 
2123 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
2124 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
2125 				1, false);
2126 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
2127 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
2128 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
2129 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
2130 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
2131 				IF_CRTL_HDMI_PIN_POL_MASK,
2132 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
2133 	}
2134 
2135 	return mode->clock;
2136 }
2137 
2138 static int rockchip_vop2_init(struct display_state *state)
2139 {
2140 	struct crtc_state *cstate = &state->crtc_state;
2141 	struct connector_state *conn_state = &state->conn_state;
2142 	struct drm_display_mode *mode = &conn_state->mode;
2143 	struct vop2 *vop2 = cstate->private;
2144 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2145 	u16 hdisplay = mode->crtc_hdisplay;
2146 	u16 htotal = mode->crtc_htotal;
2147 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
2148 	u16 hact_end = hact_st + hdisplay;
2149 	u16 vdisplay = mode->crtc_vdisplay;
2150 	u16 vtotal = mode->crtc_vtotal;
2151 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
2152 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
2153 	u16 vact_end = vact_st + vdisplay;
2154 	bool yuv_overlay = false;
2155 	u32 vp_offset = (cstate->crtc_id * 0x100);
2156 	u32 val;
2157 	u8 dither_down_en = 0;
2158 	u8 pre_dither_down_en = 0;
2159 	char output_type_name[30] = {0};
2160 	char dclk_name[9];
2161 	struct clk dclk;
2162 	unsigned long dclk_rate;
2163 	int ret;
2164 
2165 	printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
2166 	       mode->hdisplay, mode->vdisplay,
2167 	       mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
2168 	       mode->vscan,
2169 	       get_output_if_name(conn_state->output_if, output_type_name),
2170 	       cstate->crtc_id);
2171 
2172 	vop2_initial(vop2, state);
2173 	if (vop2->version == VOP_VERSION_RK3588)
2174 		dclk_rate = rk3588_vop2_if_cfg(state);
2175 	else
2176 		dclk_rate = rk3568_vop2_if_cfg(state);
2177 
2178 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
2179 	    !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT))
2180 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
2181 
2182 	if (is_uv_swap(conn_state->bus_format, conn_state->output_mode))
2183 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
2184 				DATA_SWAP_MASK, DATA_SWAP_SHIFT, DSP_RB_SWAP,
2185 				false);
2186 	else
2187 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
2188 				DATA_SWAP_MASK, DATA_SWAP_SHIFT, 0,
2189 				false);
2190 
2191 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
2192 			OUT_MODE_SHIFT, conn_state->output_mode, false);
2193 
2194 	switch (conn_state->bus_format) {
2195 	case MEDIA_BUS_FMT_RGB565_1X16:
2196 		dither_down_en = 1;
2197 		break;
2198 	case MEDIA_BUS_FMT_RGB666_1X18:
2199 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
2200 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
2201 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
2202 		dither_down_en = 1;
2203 		break;
2204 	case MEDIA_BUS_FMT_YUV8_1X24:
2205 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
2206 		dither_down_en = 0;
2207 		pre_dither_down_en = 1;
2208 		break;
2209 	case MEDIA_BUS_FMT_YUV10_1X30:
2210 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
2211 	case MEDIA_BUS_FMT_RGB888_1X24:
2212 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
2213 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
2214 	default:
2215 		dither_down_en = 0;
2216 		pre_dither_down_en = 0;
2217 		break;
2218 	}
2219 
2220 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA)
2221 		pre_dither_down_en = 0;
2222 	else
2223 		pre_dither_down_en = 1;
2224 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2225 			DITHER_DOWN_EN_SHIFT, dither_down_en, false);
2226 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2227 			PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
2228 
2229 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
2230 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
2231 			yuv_overlay, false);
2232 
2233 	cstate->yuv_overlay = yuv_overlay;
2234 
2235 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
2236 		    (htotal << 16) | hsync_len);
2237 	val = hact_st << 16;
2238 	val |= hact_end;
2239 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
2240 	val = vact_st << 16;
2241 	val |= vact_end;
2242 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
2243 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
2244 		u16 vact_st_f1 = vtotal + vact_st + 1;
2245 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
2246 
2247 		val = vact_st_f1 << 16 | vact_end_f1;
2248 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
2249 			    val);
2250 
2251 		val = vtotal << 16 | (vtotal + vsync_len);
2252 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
2253 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2254 				INTERLACE_EN_SHIFT, 1, false);
2255 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2256 				DSP_FILED_POL, 1, false);
2257 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2258 				P2I_EN_SHIFT, 1, false);
2259 		vtotal += vtotal + 1;
2260 	} else {
2261 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2262 				INTERLACE_EN_SHIFT, 0, false);
2263 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2264 				P2I_EN_SHIFT, 0, false);
2265 	}
2266 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
2267 		    (vtotal << 16) | vsync_len);
2268 	val = !!(mode->flags & DRM_MODE_FLAG_DBLCLK);
2269 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2270 			CORE_DCLK_DIV_EN_SHIFT, val, false);
2271 
2272 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
2273 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2274 				DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
2275 	else
2276 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2277 				DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
2278 
2279 	if (yuv_overlay)
2280 		val = 0x20010200;
2281 	else
2282 		val = 0;
2283 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
2284 
2285 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2286 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
2287 
2288 	vop2_tv_config_update(state, vop2);
2289 	vop2_post_config(state, vop2);
2290 
2291 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
2292 	ret = clk_get_by_name(cstate->dev, dclk_name, &dclk);
2293 	if (!ret)
2294 		ret = clk_set_rate(&dclk, dclk_rate * 1000);
2295 	if (IS_ERR_VALUE(ret)) {
2296 		printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
2297 		       __func__, cstate->crtc_id, dclk_rate, ret);
2298 		return ret;
2299 	}
2300 
2301 	return 0;
2302 }
2303 
2304 static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
2305 			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
2306 			     uint32_t dst_h)
2307 {
2308 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
2309 	uint16_t hscl_filter_mode, vscl_filter_mode;
2310 	uint8_t gt2 = 0, gt4 = 0;
2311 	uint32_t xfac = 0, yfac = 0;
2312 	uint16_t hsu_filter_mode = VOP2_SCALE_UP_BIC;
2313 	uint16_t hsd_filter_mode = VOP2_SCALE_DOWN_BIL;
2314 	uint16_t vsu_filter_mode = VOP2_SCALE_UP_BIL;
2315 	uint16_t vsd_filter_mode = VOP2_SCALE_DOWN_BIL;
2316 	u32 win_offset = win->reg_offset;
2317 
2318 	if (src_h >= (4 * dst_h))
2319 		gt4 = 1;
2320 	else if (src_h >= (2 * dst_h))
2321 		gt2 = 1;
2322 
2323 	if (gt4)
2324 		src_h >>= 2;
2325 	else if (gt2)
2326 		src_h >>= 1;
2327 
2328 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
2329 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
2330 
2331 	if (yrgb_hor_scl_mode == SCALE_UP)
2332 		hscl_filter_mode = hsu_filter_mode;
2333 	else
2334 		hscl_filter_mode = hsd_filter_mode;
2335 
2336 	if (yrgb_ver_scl_mode == SCALE_UP)
2337 		vscl_filter_mode = vsu_filter_mode;
2338 	else
2339 		vscl_filter_mode = vsd_filter_mode;
2340 
2341 	/*
2342 	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
2343 	 * at scale down mode
2344 	 */
2345 	if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) {
2346 		printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
2347 		dst_w += 1;
2348 	}
2349 
2350 	xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
2351 	yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
2352 
2353 	if (win->type == CLUSTER_LAYER) {
2354 		vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
2355 			    yfac << 16 | xfac);
2356 
2357 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
2358 				YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, gt2, false);
2359 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
2360 				YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, gt4, false);
2361 
2362 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
2363 				YRGB_XSCL_MODE_MASK, CLUSTER_YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
2364 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
2365 				YRGB_YSCL_MODE_MASK, CLUSTER_YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
2366 
2367 	} else {
2368 		vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
2369 			    yfac << 16 | xfac);
2370 
2371 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
2372 				YRGB_GT2_MASK, YRGB_GT2_SHIFT, gt2, false);
2373 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
2374 				YRGB_GT4_MASK, YRGB_GT4_SHIFT, gt4, false);
2375 
2376 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
2377 				YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
2378 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
2379 				YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
2380 
2381 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
2382 				YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
2383 				hscl_filter_mode, false);
2384 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
2385 				YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
2386 				vscl_filter_mode, false);
2387 	}
2388 }
2389 
2390 static void vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
2391 {
2392 	struct crtc_state *cstate = &state->crtc_state;
2393 	struct connector_state *conn_state = &state->conn_state;
2394 	struct drm_display_mode *mode = &conn_state->mode;
2395 	struct vop2 *vop2 = cstate->private;
2396 	int src_w = cstate->src_w;
2397 	int src_h = cstate->src_h;
2398 	int crtc_x = cstate->crtc_x;
2399 	int crtc_y = cstate->crtc_y;
2400 	int crtc_w = cstate->crtc_w;
2401 	int crtc_h = cstate->crtc_h;
2402 	int xvir = cstate->xvir;
2403 	int y_mirror = 0;
2404 	int csc_mode;
2405 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
2406 	u32 win_offset = win->reg_offset;
2407 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
2408 
2409 	act_info = (src_h - 1) << 16;
2410 	act_info |= (src_w - 1) & 0xffff;
2411 
2412 	dsp_info = (crtc_h - 1) << 16;
2413 	dsp_info |= (crtc_w - 1) & 0xffff;
2414 
2415 	dsp_stx = crtc_x;
2416 	dsp_sty = crtc_y;
2417 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
2418 
2419 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
2420 		y_mirror = 1;
2421 	else
2422 		y_mirror = 0;
2423 
2424 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
2425 
2426 	if (y_mirror)
2427 		printf("WARN: y mirror is unsupported by cluster window\n");
2428 
2429 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
2430 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
2431 			false);
2432 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
2433 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, cstate->dma_addr);
2434 
2435 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
2436 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
2437 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
2438 
2439 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
2440 
2441 	csc_mode = vop2_convert_csc_mode(conn_state->color_space);
2442 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
2443 			CLUSTER_RGB2YUV_EN_SHIFT,
2444 			is_yuv_output(conn_state->bus_format), false);
2445 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
2446 			CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
2447 	vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
2448 
2449 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
2450 }
2451 
2452 static void vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
2453 {
2454 	struct crtc_state *cstate = &state->crtc_state;
2455 	struct connector_state *conn_state = &state->conn_state;
2456 	struct drm_display_mode *mode = &conn_state->mode;
2457 	struct vop2 *vop2 = cstate->private;
2458 	int src_w = cstate->src_w;
2459 	int src_h = cstate->src_h;
2460 	int crtc_x = cstate->crtc_x;
2461 	int crtc_y = cstate->crtc_y;
2462 	int crtc_w = cstate->crtc_w;
2463 	int crtc_h = cstate->crtc_h;
2464 	int xvir = cstate->xvir;
2465 	int y_mirror = 0;
2466 	int csc_mode;
2467 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
2468 	u32 win_offset = win->reg_offset;
2469 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
2470 
2471 	/*
2472 	 * This is workaround solution for IC design:
2473 	 * esmart can't support scale down when actual_w % 16 == 1.
2474 	 */
2475 	if (src_w > crtc_w && (src_w & 0xf) == 1) {
2476 		printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
2477 		src_w -= 1;
2478 	}
2479 
2480 	act_info = (src_h - 1) << 16;
2481 	act_info |= (src_w - 1) & 0xffff;
2482 
2483 	dsp_info = (crtc_h - 1) << 16;
2484 	dsp_info |= (crtc_w - 1) & 0xffff;
2485 
2486 	dsp_stx = crtc_x;
2487 	dsp_sty = crtc_y;
2488 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
2489 
2490 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
2491 		y_mirror = 1;
2492 	else
2493 		y_mirror = 0;
2494 
2495 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
2496 
2497 	if (y_mirror)
2498 		cstate->dma_addr += (src_h - 1) * xvir * 4;
2499 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
2500 			YMIRROR_EN_SHIFT, y_mirror, false);
2501 
2502 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
2503 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
2504 			false);
2505 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
2506 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
2507 		    cstate->dma_addr);
2508 
2509 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
2510 		    act_info);
2511 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
2512 		    dsp_info);
2513 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
2514 
2515 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
2516 			WIN_EN_SHIFT, 1, false);
2517 
2518 	csc_mode = vop2_convert_csc_mode(conn_state->color_space);
2519 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
2520 			RGB2YUV_EN_SHIFT,
2521 			is_yuv_output(conn_state->bus_format), false);
2522 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
2523 			CSC_MODE_SHIFT, csc_mode, false);
2524 
2525 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
2526 }
2527 
2528 static int rockchip_vop2_set_plane(struct display_state *state)
2529 {
2530 	struct crtc_state *cstate = &state->crtc_state;
2531 	struct vop2 *vop2 = cstate->private;
2532 	struct vop2_win_data *win_data;
2533 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
2534 	char plane_name[10] = {0};
2535 
2536 	if (cstate->crtc_w > cstate->max_output.width) {
2537 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
2538 		       cstate->crtc_w, cstate->max_output.width);
2539 		return -EINVAL;
2540 	}
2541 
2542 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
2543 	if (!win_data) {
2544 		printf("invalid win id %d\n", primary_plane_id);
2545 		return -ENODEV;
2546 	}
2547 
2548 	if (win_data->type == CLUSTER_LAYER)
2549 		vop2_set_cluster_win(state, win_data);
2550 	else
2551 		vop2_set_smart_win(state, win_data);
2552 
2553 	printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
2554 		cstate->crtc_id, get_plane_name(primary_plane_id, plane_name),
2555 		cstate->src_w, cstate->src_h, cstate->crtc_w, cstate->crtc_h,
2556 		cstate->crtc_x, cstate->crtc_y, cstate->format,
2557 		cstate->dma_addr);
2558 
2559 	return 0;
2560 }
2561 
2562 static int rockchip_vop2_prepare(struct display_state *state)
2563 {
2564 	return 0;
2565 }
2566 
2567 static int rockchip_vop2_enable(struct display_state *state)
2568 {
2569 	struct crtc_state *cstate = &state->crtc_state;
2570 	struct vop2 *vop2 = cstate->private;
2571 	u32 vp_offset = (cstate->crtc_id * 0x100);
2572 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
2573 
2574 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2575 			STANDBY_EN_SHIFT, 0, false);
2576 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
2577 
2578 	return 0;
2579 }
2580 
2581 static int rockchip_vop2_disable(struct display_state *state)
2582 {
2583 	struct crtc_state *cstate = &state->crtc_state;
2584 	struct vop2 *vop2 = cstate->private;
2585 	u32 vp_offset = (cstate->crtc_id * 0x100);
2586 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
2587 
2588 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
2589 			STANDBY_EN_SHIFT, 1, false);
2590 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
2591 
2592 	return 0;
2593 }
2594 
2595 static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane)
2596 {
2597 	struct crtc_state *cstate = &state->crtc_state;
2598 	struct vop2 *vop2 = cstate->private;
2599 	int i = 0;
2600 	int correct_cursor_plane = -1;
2601 	int plane_type = -1;
2602 
2603 	if (cursor_plane < 0)
2604 		return -1;
2605 
2606 	if (plane_mask & (1 << cursor_plane))
2607 		return cursor_plane;
2608 
2609 	/* Get current cursor plane type */
2610 	for (i = 0; i < vop2->data->nr_layers; i++) {
2611 		if (vop2->data->plane_table[i].plane_id == cursor_plane) {
2612 			plane_type = vop2->data->plane_table[i].plane_type;
2613 			break;
2614 		}
2615 	}
2616 
2617 	/* Get the other same plane type plane id */
2618 	for (i = 0; i < vop2->data->nr_layers; i++) {
2619 		if (vop2->data->plane_table[i].plane_type == plane_type &&
2620 		    vop2->data->plane_table[i].plane_id != cursor_plane) {
2621 			correct_cursor_plane = vop2->data->plane_table[i].plane_id;
2622 			break;
2623 		}
2624 	}
2625 
2626 	/* To check whether the new correct_cursor_plane is attach to current vp */
2627 	if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) {
2628 		printf("error: faild to find correct plane as cursor plane\n");
2629 		return -1;
2630 	}
2631 
2632 	printf("vp%d adjust cursor plane from %d to %d\n",
2633 	       cstate->crtc_id, cursor_plane, correct_cursor_plane);
2634 
2635 	return correct_cursor_plane;
2636 }
2637 
2638 static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
2639 {
2640 	struct crtc_state *cstate = &state->crtc_state;
2641 	struct vop2 *vop2 = cstate->private;
2642 	ofnode vp_node;
2643 	struct device_node *port_parent_node = cstate->ports_node;
2644 	static bool vop_fix_dts;
2645 	const char *path;
2646 	u32 plane_mask = 0;
2647 	int vp_id = 0;
2648 	int cursor_plane_id = -1;
2649 
2650 	if (vop_fix_dts)
2651 		return 0;
2652 
2653 	ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
2654 		path = vp_node.np->full_name;
2655 		plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
2656 
2657 		if (cstate->crtc->assign_plane)
2658 			continue;
2659 		cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask,
2660 								 cstate->crtc->vps[vp_id].cursor_plane);
2661 		printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
2662 		       vp_id, plane_mask,
2663 		       vop2->vp_plane_mask[vp_id].primary_plane_id,
2664 		       cursor_plane_id);
2665 
2666 		do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
2667 				     plane_mask, 1);
2668 		do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
2669 				     vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
2670 		if (cursor_plane_id >= 0)
2671 			do_fixup_by_path_u32(blob, path, "cursor-win-id",
2672 					     cursor_plane_id, 1);
2673 		vp_id++;
2674 	}
2675 
2676 	vop_fix_dts = true;
2677 
2678 	return 0;
2679 }
2680 
2681 static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
2682 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
2683 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
2684 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
2685 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
2686 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
2687 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
2688 };
2689 
2690 static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
2691 	{ /* one display policy */
2692 		{/* main display */
2693 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
2694 			.attached_layers_nr = 6,
2695 			.attached_layers = {
2696 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
2697 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
2698 				},
2699 		},
2700 		{/* second display */},
2701 		{/* third  display */},
2702 		{/* fourth display */},
2703 	},
2704 
2705 	{ /* two display policy */
2706 		{/* main display */
2707 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
2708 			.attached_layers_nr = 3,
2709 			.attached_layers = {
2710 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
2711 				},
2712 		},
2713 
2714 		{/* second display */
2715 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
2716 			.attached_layers_nr = 3,
2717 			.attached_layers = {
2718 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
2719 				},
2720 		},
2721 		{/* third  display */},
2722 		{/* fourth display */},
2723 	},
2724 
2725 	{ /* three display policy */
2726 		{/* main display */
2727 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
2728 			.attached_layers_nr = 3,
2729 			.attached_layers = {
2730 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
2731 				},
2732 		},
2733 
2734 		{/* second display */
2735 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
2736 			.attached_layers_nr = 2,
2737 			.attached_layers = {
2738 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
2739 				},
2740 		},
2741 
2742 		{/* third  display */
2743 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
2744 			.attached_layers_nr = 1,
2745 			.attached_layers = { ROCKCHIP_VOP2_ESMART1 },
2746 		},
2747 
2748 		{/* fourth display */},
2749 	},
2750 
2751 	{/* reserved for four display policy */},
2752 };
2753 
2754 static struct vop2_win_data rk3568_win_data[6] = {
2755 	{
2756 		.name = "Cluster0",
2757 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
2758 		.type = CLUSTER_LAYER,
2759 		.win_sel_port_offset = 0,
2760 		.layer_sel_win_id = 0,
2761 		.reg_offset = 0,
2762 	},
2763 
2764 	{
2765 		.name = "Cluster1",
2766 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
2767 		.type = CLUSTER_LAYER,
2768 		.win_sel_port_offset = 1,
2769 		.layer_sel_win_id = 1,
2770 		.reg_offset = 0x200,
2771 	},
2772 
2773 	{
2774 		.name = "Esmart0",
2775 		.phys_id = ROCKCHIP_VOP2_ESMART0,
2776 		.type = ESMART_LAYER,
2777 		.win_sel_port_offset = 4,
2778 		.layer_sel_win_id = 2,
2779 		.reg_offset = 0,
2780 	},
2781 
2782 	{
2783 		.name = "Esmart1",
2784 		.phys_id = ROCKCHIP_VOP2_ESMART1,
2785 		.type = ESMART_LAYER,
2786 		.win_sel_port_offset = 5,
2787 		.layer_sel_win_id = 6,
2788 		.reg_offset = 0x200,
2789 	},
2790 
2791 	{
2792 		.name = "Smart0",
2793 		.phys_id = ROCKCHIP_VOP2_SMART0,
2794 		.type = SMART_LAYER,
2795 		.win_sel_port_offset = 6,
2796 		.layer_sel_win_id = 3,
2797 		.reg_offset = 0x400,
2798 	},
2799 
2800 	{
2801 		.name = "Smart1",
2802 		.phys_id = ROCKCHIP_VOP2_SMART1,
2803 		.type = SMART_LAYER,
2804 		.win_sel_port_offset = 7,
2805 		.layer_sel_win_id = 7,
2806 		.reg_offset = 0x600,
2807 	},
2808 };
2809 
2810 static struct vop2_vp_data rk3568_vp_data[3] = {
2811 	{
2812 		.feature = VOP_FEATURE_OUTPUT_10BIT,
2813 		.pre_scan_max_dly = 42,
2814 		.max_output = {4096, 2304},
2815 	},
2816 	{
2817 		.feature = 0,
2818 		.pre_scan_max_dly = 40,
2819 		.max_output = {2048, 1536},
2820 	},
2821 	{
2822 		.feature = 0,
2823 		.pre_scan_max_dly = 40,
2824 		.max_output = {1920, 1080},
2825 	},
2826 };
2827 
2828 const struct vop2_data rk3568_vop = {
2829 	.version = VOP_VERSION_RK3568,
2830 	.nr_vps = 3,
2831 	.vp_data = rk3568_vp_data,
2832 	.win_data = rk3568_win_data,
2833 	.plane_mask = rk356x_vp_plane_mask[0],
2834 	.plane_table = rk356x_plane_table,
2835 	.nr_layers = 6,
2836 	.nr_mixers = 5,
2837 	.nr_gammas = 1,
2838 };
2839 
2840 static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
2841 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
2842 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
2843 	{ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER},
2844 	{ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER},
2845 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
2846 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
2847 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
2848 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
2849 };
2850 
2851 static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
2852 	{ /* one display policy */
2853 		{/* main display */
2854 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER0,
2855 			.attached_layers_nr = 8,
2856 			.attached_layers = {
2857 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2,
2858 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3,
2859 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3
2860 			},
2861 		},
2862 		{/* second display */},
2863 		{/* third  display */},
2864 		{/* fourth display */},
2865 	},
2866 
2867 	{ /* two display policy */
2868 		{/* main display */
2869 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER0,
2870 			.attached_layers_nr = 4,
2871 			.attached_layers = {
2872 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
2873 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1
2874 			},
2875 		},
2876 
2877 		{/* second display */
2878 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER2,
2879 			.attached_layers_nr = 4,
2880 			.attached_layers = {
2881 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2,
2882 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
2883 			},
2884 		},
2885 		{/* third  display */},
2886 		{/* fourth display */},
2887 	},
2888 
2889 	{ /* three display policy */
2890 		{/* main display */
2891 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER0,
2892 			.attached_layers_nr = 3,
2893 			.attached_layers = {
2894 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0
2895 			},
2896 		},
2897 
2898 		{/* second display */
2899 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER2,
2900 			.attached_layers_nr = 3,
2901 			.attached_layers = {
2902 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1
2903 			},
2904 		},
2905 
2906 		{/* third  display */
2907 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
2908 			.attached_layers_nr = 2,
2909 			.attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
2910 		},
2911 
2912 		{/* fourth display */},
2913 	},
2914 
2915 	{ /* four display policy */
2916 		{/* main display */
2917 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER0,
2918 			.attached_layers_nr = 2,
2919 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
2920 		},
2921 
2922 		{/* second display */
2923 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER1,
2924 			.attached_layers_nr = 2,
2925 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
2926 		},
2927 
2928 		{/* third  display */
2929 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER2,
2930 			.attached_layers_nr = 2,
2931 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
2932 		},
2933 
2934 		{/* fourth display */
2935 			.primary_plane_id = ROCKCHIP_VOP2_CLUSTER3,
2936 			.attached_layers_nr = 2,
2937 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
2938 		},
2939 	},
2940 
2941 };
2942 
2943 static struct vop2_power_domain_data rk3588_cluster0_pd_data = {
2944 	.pd_en_shift = RK3588_CLUSTER0_PD_EN_SHIFT,
2945 	.pd_status_shift = RK3588_CLUSTER0_PD_STATUS_SHIFT,
2946 	.pmu_status_shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI,
2947 	.bisr_en_status_shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT,
2948 };
2949 
2950 static struct vop2_power_domain_data rk3588_cluster1_pd_data = {
2951 	.is_parent_needed = true,
2952 	.pd_en_shift = RK3588_CLUSTER1_PD_EN_SHIFT,
2953 	.pd_status_shift = RK3588_CLUSTER1_PD_STATUS_SHIFT,
2954 	.pmu_status_shift = RK3588_PD_CLUSTER1_PWR_STAT_SHIFI,
2955 	.bisr_en_status_shift = RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT,
2956 	.parent_phy_id = ROCKCHIP_VOP2_CLUSTER0,
2957 };
2958 
2959 static struct vop2_power_domain_data rk3588_cluster2_pd_data = {
2960 	.is_parent_needed = true,
2961 	.pd_en_shift = RK3588_CLUSTER2_PD_EN_SHIFT,
2962 	.pd_status_shift = RK3588_CLUSTER2_PD_STATUS_SHIFT,
2963 	.pmu_status_shift = RK3588_PD_CLUSTER2_PWR_STAT_SHIFI,
2964 	.bisr_en_status_shift = RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT,
2965 	.parent_phy_id = ROCKCHIP_VOP2_CLUSTER0,
2966 };
2967 
2968 static struct vop2_power_domain_data rk3588_cluster3_pd_data = {
2969 	.is_parent_needed = true,
2970 	.pd_en_shift = RK3588_CLUSTER3_PD_EN_SHIFT,
2971 	.pd_status_shift = RK3588_CLUSTER3_PD_STATUS_SHIFT,
2972 	.pmu_status_shift = RK3588_PD_CLUSTER3_PWR_STAT_SHIFI,
2973 	.bisr_en_status_shift = RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT,
2974 	.parent_phy_id = ROCKCHIP_VOP2_CLUSTER0,
2975 };
2976 
2977 static struct vop2_power_domain_data rk3588_esmart_pd_data = {
2978 	.pd_en_shift = RK3588_ESMART_PD_EN_SHIFT,
2979 	.pd_status_shift = RK3588_ESMART_PD_STATUS_SHIFT,
2980 	.pmu_status_shift = RK3588_PD_ESMART_PWR_STAT_SHIFI,
2981 	.bisr_en_status_shift = RK3588_PD_ESMART_REPAIR_EN_SHIFT,
2982 };
2983 
2984 static struct vop2_win_data rk3588_win_data[8] = {
2985 	{
2986 		.name = "Cluster0",
2987 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
2988 		.type = CLUSTER_LAYER,
2989 		.win_sel_port_offset = 0,
2990 		.layer_sel_win_id = 0,
2991 		.reg_offset = 0,
2992 		.pd_data = &rk3588_cluster0_pd_data,
2993 	},
2994 
2995 	{
2996 		.name = "Cluster1",
2997 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
2998 		.type = CLUSTER_LAYER,
2999 		.win_sel_port_offset = 1,
3000 		.layer_sel_win_id = 1,
3001 		.reg_offset = 0x200,
3002 		.pd_data = &rk3588_cluster1_pd_data,
3003 	},
3004 
3005 	{
3006 		.name = "Cluster2",
3007 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
3008 		.type = CLUSTER_LAYER,
3009 		.win_sel_port_offset = 2,
3010 		.layer_sel_win_id = 4,
3011 		.reg_offset = 0x400,
3012 		.pd_data = &rk3588_cluster2_pd_data,
3013 	},
3014 
3015 	{
3016 		.name = "Cluster3",
3017 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
3018 		.type = CLUSTER_LAYER,
3019 		.win_sel_port_offset = 3,
3020 		.layer_sel_win_id = 5,
3021 		.reg_offset = 0x600,
3022 		.pd_data = &rk3588_cluster3_pd_data,
3023 	},
3024 
3025 	{
3026 		.name = "Esmart0",
3027 		.phys_id = ROCKCHIP_VOP2_ESMART0,
3028 		.type = ESMART_LAYER,
3029 		.win_sel_port_offset = 4,
3030 		.layer_sel_win_id = 2,
3031 		.reg_offset = 0,
3032 		.pd_data = &rk3588_esmart_pd_data,
3033 	},
3034 
3035 	{
3036 		.name = "Esmart1",
3037 		.phys_id = ROCKCHIP_VOP2_ESMART1,
3038 		.type = ESMART_LAYER,
3039 		.win_sel_port_offset = 5,
3040 		.layer_sel_win_id = 3,
3041 		.reg_offset = 0x200,
3042 		.pd_data = &rk3588_esmart_pd_data,
3043 	},
3044 
3045 	{
3046 		.name = "Esmart2",
3047 		.phys_id = ROCKCHIP_VOP2_ESMART2,
3048 		.type = ESMART_LAYER,
3049 		.win_sel_port_offset = 6,
3050 		.layer_sel_win_id = 6,
3051 		.reg_offset = 0x400,
3052 		.pd_data = &rk3588_esmart_pd_data,
3053 	},
3054 
3055 	{
3056 		.name = "Esmart3",
3057 		.phys_id = ROCKCHIP_VOP2_ESMART3,
3058 		.type = ESMART_LAYER,
3059 		.win_sel_port_offset = 7,
3060 		.layer_sel_win_id = 7,
3061 		.reg_offset = 0x600,
3062 		.pd_data = &rk3588_esmart_pd_data,
3063 	},
3064 };
3065 
3066 static struct vop2_vp_data rk3588_vp_data[4] = {
3067 	{
3068 		.feature = VOP_FEATURE_OUTPUT_10BIT,
3069 		.pre_scan_max_dly = 42,
3070 		.max_dclk = 600000,
3071 		.max_output = {7680, 4320},
3072 	},
3073 	{
3074 		.feature = VOP_FEATURE_OUTPUT_10BIT,
3075 		.pre_scan_max_dly = 40,
3076 		.max_dclk = 600000,
3077 		.max_output = {4096, 2304},
3078 	},
3079 	{
3080 		.feature = VOP_FEATURE_OUTPUT_10BIT,
3081 		.pre_scan_max_dly = 52,
3082 		.max_dclk = 600000,
3083 		.max_output = {4096, 2304},
3084 	},
3085 	{
3086 		.feature = 0,
3087 		.pre_scan_max_dly = 52,
3088 		.max_dclk = 200000,
3089 		.max_output = {1920, 1080},
3090 	},
3091 };
3092 
3093 const struct vop2_data rk3588_vop = {
3094 	.version = VOP_VERSION_RK3588,
3095 	.nr_vps = 4,
3096 	.vp_data = rk3588_vp_data,
3097 	.win_data = rk3588_win_data,
3098 	.plane_mask = rk3588_vp_plane_mask[0],
3099 	.plane_table = rk3588_plane_table,
3100 	.nr_layers = 8,
3101 	.nr_mixers = 7,
3102 	.nr_gammas = 4,
3103 	.nr_dscs = 2,
3104 };
3105 
3106 const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
3107 	.preinit = rockchip_vop2_preinit,
3108 	.prepare = rockchip_vop2_prepare,
3109 	.init = rockchip_vop2_init,
3110 	.set_plane = rockchip_vop2_set_plane,
3111 	.enable = rockchip_vop2_enable,
3112 	.disable = rockchip_vop2_disable,
3113 	.fixup_dts = rockchip_vop2_fixup_dts,
3114 };
3115