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