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