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