xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_vop2.c (revision e2bdb3b3da8b4876dbeeadae32c2d2f399e90e91)
1d0408543SAndy Yan // SPDX-License-Identifier: GPL-2.0-only
2d0408543SAndy Yan /*
3d0408543SAndy Yan  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
4d0408543SAndy Yan  *
5d0408543SAndy Yan  */
6d0408543SAndy Yan 
7d0408543SAndy Yan #include <config.h>
8d0408543SAndy Yan #include <common.h>
9d0408543SAndy Yan #include <errno.h>
10d0408543SAndy Yan #include <malloc.h>
11d0408543SAndy Yan #include <fdtdec.h>
12d0408543SAndy Yan #include <fdt_support.h>
13b890760eSAlgea Cao #include <regmap.h>
14feffd38eSSandy Huang #include <asm/arch/cpu.h>
15d0408543SAndy Yan #include <asm/unaligned.h>
16d0408543SAndy Yan #include <asm/io.h>
17d0408543SAndy Yan #include <linux/list.h>
18ecc31b6eSAndy Yan #include <linux/log2.h>
19d0408543SAndy Yan #include <linux/media-bus-format.h>
20d0408543SAndy Yan #include <asm/arch/clock.h>
218e7ef808SDamon Ding #include <asm/gpio.h>
22d0408543SAndy Yan #include <linux/err.h>
231147facaSSandy Huang #include <linux/ioport.h>
24d0408543SAndy Yan #include <dm/device.h>
25d0408543SAndy Yan #include <dm/read.h>
265fa6e665SDamon Ding #include <dm/ofnode.h>
27ac500a1fSSandy Huang #include <fixp-arith.h>
28d0408543SAndy Yan #include <syscon.h>
2960e469f5SDamon Ding #include <linux/iopoll.h>
305f1357a2SZhang Yubing #include <dm/uclass-internal.h>
31452afb13SDamon Ding #include <stdlib.h>
32d0408543SAndy Yan 
33d0408543SAndy Yan #include "rockchip_display.h"
34d0408543SAndy Yan #include "rockchip_crtc.h"
35d0408543SAndy Yan #include "rockchip_connector.h"
36d8e7f4a5SSandy Huang #include "rockchip_phy.h"
376027c871SZhang Yubing #include "rockchip_post_csc.h"
38d0408543SAndy Yan 
39d0408543SAndy Yan /* System registers definition */
40d0408543SAndy Yan #define RK3568_REG_CFG_DONE			0x000
41d0408543SAndy Yan #define	CFG_DONE_EN				BIT(15)
42d0408543SAndy Yan 
43d0408543SAndy Yan #define RK3568_VERSION_INFO			0x004
44d0408543SAndy Yan #define EN_MASK					1
45d0408543SAndy Yan 
4663cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL			0x008
470675a2a4SDamon Ding #define AUTO_GATING_EN_SHIFT			31
480675a2a4SDamon Ding #define PORT_DCLK_AUTO_GATING_EN_SHIFT		14
4963cb669fSSandy Huang 
50a552a69cSDamon Ding #define RK3576_SYS_MMU_CTRL			0x020
51a552a69cSDamon Ding #define RKMMU_V2_EN_SHIFT			0
52a552a69cSDamon Ding #define RKMMU_V2_SEL_AXI_SHIFT			1
53a552a69cSDamon Ding 
546414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL			0x024
556414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT			0
56aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT			16
576414e3bcSSandy Huang 
58d0408543SAndy Yan #define RK3568_DSP_IF_EN			0x028
59d0408543SAndy Yan #define RGB_EN_SHIFT				0
60ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT			0
61ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT			1
62ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT			8
63d0408543SAndy Yan #define HDMI0_EN_SHIFT				1
64d0408543SAndy Yan #define EDP0_EN_SHIFT				3
65ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT			2
66ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT			3
67d0408543SAndy Yan #define MIPI0_EN_SHIFT				4
68ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT			4
69ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT			5
70ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT			6
71d0408543SAndy Yan #define MIPI1_EN_SHIFT				20
72ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT			7
73d0408543SAndy Yan #define LVDS0_EN_SHIFT				5
74d0408543SAndy Yan #define LVDS1_EN_SHIFT				24
75d0408543SAndy Yan #define BT1120_EN_SHIFT				6
76d0408543SAndy Yan #define BT656_EN_SHIFT				7
77d0408543SAndy Yan #define IF_MUX_MASK				3
78d0408543SAndy Yan #define RGB_MUX_SHIFT				8
79d0408543SAndy Yan #define HDMI0_MUX_SHIFT				10
80ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT			12
81ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT			14
82d0408543SAndy Yan #define EDP0_MUX_SHIFT				14
83ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT		16
84ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT		18
85d0408543SAndy Yan #define MIPI0_MUX_SHIFT				16
86ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT			20
87d0408543SAndy Yan #define MIPI1_MUX_SHIFT				21
8811f53190SSandy Huang #define LVDS0_MUX_SHIFT				18
89d0408543SAndy Yan #define LVDS1_MUX_SHIFT				25
90d0408543SAndy Yan 
91a552a69cSDamon Ding #define RK3576_SYS_PORT_CTRL			0x028
92a552a69cSDamon Ding #define VP_INTR_MERGE_EN_SHIFT			14
93a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_MASK		0x7
94a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_SHIFT		0
95a552a69cSDamon Ding 
96d0408543SAndy Yan #define RK3568_DSP_IF_CTRL			0x02c
97d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT			0
985d2768f7SDamon Ding #define RK3588_BT656_UV_SWAP_SHIFT		0
99d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT		1
1005d2768f7SDamon Ding #define RK3588_BT656_YC_SWAP_SHIFT		1
101d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT			2
1025fa6e665SDamon Ding #define BT656_UV_SWAP				4
1035d2768f7SDamon Ding #define RK3588_BT1120_UV_SWAP_SHIFT		4
1045fa6e665SDamon Ding #define BT656_YC_SWAP				5
1055d2768f7SDamon Ding #define RK3588_BT1120_YC_SWAP_SHIFT		5
1065fa6e665SDamon Ding #define BT656_DCLK_POL				6
1070a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT		8
1080a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT		8
1090a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT			9
11041874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT		10
11141874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT		11
11241874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT		12
11341874944SGuochun Huang 
114d0408543SAndy Yan #define RK3568_DSP_IF_POL			0x030
115d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT		28
116d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT		19
117d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT		15
1187bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_MASK		0x7
1197bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_SHIFT		12
120d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT		7
12110ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK		0x7
12210ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT		4
12315f69071SDamon Ding #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT		3
12415f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_MASK		0x7
12515f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT		0
126ecc31b6eSAndy Yan 
127452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT		15
128452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT		12
129452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK			0x7
130452afb13SDamon Ding 
131ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT		8
132ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT		12
133ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK			0x7
134ecc31b6eSAndy Yan 
135ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT		16
136ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT		18
137ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT		20
138ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT		22
139ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT			24
140ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT			26
141ecc31b6eSAndy Yan 
142a552a69cSDamon Ding #define RK3576_SYS_CLUSTER_PD_CTRL		0x030
143a552a69cSDamon Ding #define RK3576_CLUSTER_PD_EN_SHIFT		0
144a552a69cSDamon Ding 
145a552a69cSDamon Ding #define RK3588_SYS_PD_CTRL			0x034
146a552a69cSDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT		0
147a552a69cSDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT		1
148a552a69cSDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT		2
149a552a69cSDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT		3
150a552a69cSDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT		5
151a552a69cSDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT		6
152a552a69cSDamon Ding #define RK3588_ESMART_PD_EN_SHIFT		7
153a552a69cSDamon Ding 
154a552a69cSDamon Ding #define RK3576_SYS_ESMART_PD_CTRL		0x034
155a552a69cSDamon Ding #define RK3576_ESMART_PD_EN_SHIFT		0
156a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_SHIFT		6
157a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_MASK		0x3
158a552a69cSDamon Ding 
159feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN			0x50
160feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT			0
1611147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL			0x58
1621147facaSSandy Huang #define GAMMA_PORT_SEL_MASK			0x3
1631147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT			0
164db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK		0x3
165db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT		12
166ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT			16
1675fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK			0x3
1685fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT		26
1691147facaSSandy Huang 
170d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG			0x70
171d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG			0x74
172d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG			0x78
173d0408543SAndy Yan #define RK3568_SYS0_INT_EN			0x80
174d0408543SAndy Yan #define RK3568_SYS0_INT_CLR			0x84
175d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS			0x88
176d0408543SAndy Yan #define RK3568_SYS1_INT_EN			0x90
177d0408543SAndy Yan #define RK3568_SYS1_INT_CLR			0x94
178d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS			0x98
179d0408543SAndy Yan #define RK3568_VP0_INT_EN			0xA0
180d0408543SAndy Yan #define RK3568_VP0_INT_CLR			0xA4
181d0408543SAndy Yan #define RK3568_VP0_INT_STATUS			0xA8
182d0408543SAndy Yan #define RK3568_VP1_INT_EN			0xB0
183d0408543SAndy Yan #define RK3568_VP1_INT_CLR			0xB4
184d0408543SAndy Yan #define RK3568_VP1_INT_STATUS			0xB8
185d0408543SAndy Yan #define RK3568_VP2_INT_EN			0xC0
186d0408543SAndy Yan #define RK3568_VP2_INT_CLR			0xC4
187d0408543SAndy Yan #define RK3568_VP2_INT_STATUS			0xC8
188a552a69cSDamon Ding #define RK3568_VP2_INT_RAW_STATUS		0xCC
189a552a69cSDamon Ding #define RK3588_VP3_INT_EN			0xD0
190a552a69cSDamon Ding #define RK3588_VP3_INT_CLR			0xD4
191a552a69cSDamon Ding #define RK3588_VP3_INT_STATUS			0xD8
192a552a69cSDamon Ding #define RK3576_WB_CTRL				0x100
193a552a69cSDamon Ding #define RK3576_WB_XSCAL_FACTOR			0x104
194a552a69cSDamon Ding #define RK3576_WB_YRGB_MST			0x108
195a552a69cSDamon Ding #define RK3576_WB_CBR_MST			0x10C
196a552a69cSDamon Ding #define RK3576_WB_VIR_STRIDE			0x110
197a552a69cSDamon Ding #define RK3576_WB_TIMEOUT_CTRL			0x114
198a552a69cSDamon Ding #define RK3576_MIPI0_IF_CTRL			0x180
199a552a69cSDamon Ding #define RK3576_IF_OUT_EN_SHIFT			0
200a552a69cSDamon Ding #define RK3576_IF_CLK_OUT_EN_SHIFT		1
201a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_SHIFT		2
202a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_MASK			0x3
203a552a69cSDamon Ding #define RK3576_IF_PIN_POL_SHIFT			4
204a552a69cSDamon Ding #define RK3576_IF_PIN_POL_MASK			0x7
205a552a69cSDamon Ding #define RK3576_IF_SPLIT_EN_SHIFT		8
206a552a69cSDamon Ding #define RK3576_IF_DATA1_SEL_SHIFT		9
207a552a69cSDamon Ding #define RK3576_MIPI_CMD_MODE_SHIFT		11
208a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_SHIFT		21
209a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_MASK			0x1
210a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_SHIFT		20
211a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_MASK		0x1
212a552a69cSDamon Ding #define RK3576_IF_REGDONE_IMD_EN_SHIFT		31
213a552a69cSDamon Ding #define RK3576_HDMI0_IF_CTRL			0x184
214a552a69cSDamon Ding #define RK3576_EDP0_IF_CTRL			0x188
215a552a69cSDamon Ding #define RK3576_DP0_IF_CTRL			0x18C
216a552a69cSDamon Ding #define RK3576_RGB_IF_CTRL			0x194
217a552a69cSDamon Ding #define RK3576_BT656_OUT_EN_SHIFT		12
218a552a69cSDamon Ding #define RK3576_BT656_UV_SWAP_SHIFT		13
219a552a69cSDamon Ding #define RK3576_BT656_YC_SWAP_SHIFT		14
220a552a69cSDamon Ding #define RK3576_BT1120_OUT_EN_SHIFT		16
221a552a69cSDamon Ding #define RK3576_BT1120_UV_SWAP_SHIFT		17
222a552a69cSDamon Ding #define RK3576_BT1120_YC_SWAP_SHIFT		18
223a552a69cSDamon Ding #define RK3576_DP1_IF_CTRL			0x1A4
224a552a69cSDamon Ding #define RK3576_DP2_IF_CTRL			0x1B0
22560e469f5SDamon Ding 
226cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL		0x038
227cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT	20
228cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT		24
229cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT	28
230cd6c85a9SDamon Ding 
23160e469f5SDamon Ding #define RK3568_SYS_STATUS0			0x60
23260e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT		8
23360e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT		9
23460e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT		10
23560e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT		11
236b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT		13
237b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT		14
23860e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT		15
239d0408543SAndy Yan 
24066724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0		0x70
24166724b9cSDamon Ding #define LINE_FLAG_NUM_MASK			0x1fff
24266724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT		0
24366724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT		16
24466724b9cSDamon Ding 
24512ee5af0SDamon Ding /* DSC CTRL registers definition */
24612ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL			0x200
24712ee5af0SDamon Ding #define DSC_PORT_SEL_MASK			0x3
24812ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT			0
24912ee5af0SDamon Ding #define DSC_MAN_MODE_MASK			0x1
25012ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT			2
25112ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK			0x3
25212ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT		4
25312ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK			0x3
25412ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT			6
25512ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK			0x1
25612ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT			8
25712ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK			0x3
25812ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT			12
25912ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK			0x3
26012ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT			14
26112ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK			0x1
26212ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT			16
26312ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT			17
26412ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT			18
26512ee5af0SDamon Ding 
26612ee5af0SDamon Ding #define RK3588_DSC_8K_RST			0x204
26712ee5af0SDamon Ding #define RST_DEASSERT_MASK			0x1
26812ee5af0SDamon Ding #define RST_DEASSERT_SHIFT			0
26912ee5af0SDamon Ding 
27012ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE			0x208
27112ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT			0
27212ee5af0SDamon Ding 
27312ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY			0x20C
27412ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK			0xffff
27512ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT			0
27612ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT		16
27712ee5af0SDamon Ding 
27812ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END		0x210
27912ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK			0xffffffff
28012ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT			0
28112ee5af0SDamon Ding 
28212ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END		0x214
28312ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK			0xffffffff
28412ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT			0
28512ee5af0SDamon Ding 
28612ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END		0x218
28712ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK			0xffffffff
28812ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT			0
28912ee5af0SDamon Ding 
29012ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END		0x21C
29112ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK			0xffffffff
29212ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT			0
29312ee5af0SDamon Ding 
29412ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS			0x220
29512ee5af0SDamon Ding 
29663cb669fSSandy Huang /* Overlay registers definition    */
2975fa6e665SDamon Ding #define RK3528_OVL_SYS				0x500
298a552a69cSDamon Ding #define RK3528_OVL_SYS_PORT_SEL			0x504
299a552a69cSDamon Ding #define RK3528_OVL_SYS_GATING_EN		0x508
3005fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL		0x510
3015fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL		0x520
302452afb13SDamon Ding #define ESMART_DLY_NUM_MASK			0xff
303452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT			0
3045fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL		0x524
3055fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL		0x528
3065fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL		0x52C
3075fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL	0x530
3085fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL	0x534
3095fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x538
3105fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL	0x53c
311a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL	0x540
312a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL	0x544
313a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL	0x548
314a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL	0x54c
3155fa6e665SDamon Ding 
3165fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL			0x600
31763cb669fSSandy Huang #define RK3568_OVL_CTRL				0x600
318ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK			0x1
319ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT			0
32063cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
3215fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL		0x604
32263cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL			0x604
32363cb669fSSandy Huang #define LAYER_SEL_MASK				0xf
32463cb669fSSandy Huang 
32563cb669fSSandy Huang #define RK3568_OVL_PORT_SEL			0x608
32663cb669fSSandy Huang #define PORT_MUX_MASK				0xf
32763cb669fSSandy Huang #define PORT_MUX_SHIFT				0
32863cb669fSSandy Huang #define LAYER_SEL_PORT_MASK			0x3
32963cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT			16
33063cb669fSSandy Huang 
33163cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
33263cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
33363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
33463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
3355fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL	0x620
3365fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL	0x624
3375fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL	0x628
3385fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL	0x62C
3395fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL	0x630
3405fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL	0x634
3415fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL	0x638
3425fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL	0x63C
3435fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL	0x640
3445fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL	0x644
3455fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL	0x648
3465fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL	0x64C
34763cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
34863cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL		0x654
34963cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
35063cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
351a552a69cSDamon Ding #define RK3576_EXTRA_SRC_COLOR_CTRL		0x650
352a552a69cSDamon Ding #define RK3576_EXTRA_DST_COLOR_CTRL		0x654
353a552a69cSDamon Ding #define RK3576_EXTRA_SRC_ALPHA_CTRL		0x658
354a552a69cSDamon Ding #define RK3576_EXTRA_DST_ALPHA_CTRL		0x65C
3555fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL		0x660
3565fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL		0x664
3575fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL		0x668
3585fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL		0x66C
3595fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL		0x670
36063cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
36163cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
36263cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
36363cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
36463cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL			0x6E0
36563cb669fSSandy Huang #define BG_MIX_CTRL_MASK			0xff
36663cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT			24
36763cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL			0x6E4
36863cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL			0x6E8
36963cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM			0x6F0
37063cb669fSSandy Huang #define RK3568_SMART_DLY_NUM			0x6F8
37163cb669fSSandy Huang 
3725fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL			0x700
3735fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL		0x704
3745fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL	0x720
3755fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL	0x724
3765fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL	0x728
3775fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL	0x72C
3785fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL	0x730
3795fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL	0x734
3805fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL	0x738
3815fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL	0x73C
3825fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL	0x740
3835fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL	0x744
3845fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL	0x748
3855fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL	0x74C
3865fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL		0x770
387a552a69cSDamon Ding #define RK3576_OVL_PORT2_CTRL			0x800
388a552a69cSDamon Ding #define RK3576_OVL_PORT2_LAYER_SEL		0x804
389a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL	0x820
390a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL	0x824
391a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL	0x828
392a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL	0x82C
393a552a69cSDamon Ding #define RK3576_OVL_PORT2_BG_MIX_CTRL		0x870
3945fa6e665SDamon Ding 
395d0408543SAndy Yan /* Video Port registers definition */
396d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL			0xC00
397d0408543SAndy Yan #define OUT_MODE_MASK				0xf
398d0408543SAndy Yan #define OUT_MODE_SHIFT				0
39910ee9f5bSAlgea Cao #define DATA_SWAP_MASK				0x1f
40010ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT				8
40165747de7SDamon Ding #define DSP_BG_SWAP				0x1
40265747de7SDamon Ding #define DSP_RB_SWAP				0x2
40365747de7SDamon Ding #define DSP_RG_SWAP				0x4
40465747de7SDamon Ding #define DSP_DELTA_SWAP				0x8
40510ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT			4
406d0408543SAndy Yan #define P2I_EN_SHIFT				5
4077a20be36SSandy Huang #define DSP_FILED_POL				6
408d0408543SAndy Yan #define INTERLACE_EN_SHIFT			7
409c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT			13
41010ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT			15
411d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT		16
412d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT			17
413*e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_SHIFT			18
414*e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_MASK			0x3
415452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT			20
416db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT			22
4171147facaSSandy Huang #define DSP_LUT_EN_SHIFT			28
4181147facaSSandy Huang 
419d0408543SAndy Yan #define STANDBY_EN_SHIFT			31
420d0408543SAndy Yan 
421d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL			0xC04
42210ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT				4
42310ee9f5bSAlgea Cao #define DCLK_DIV2_MASK				0x3
424d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT			20
425d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT			21
42641874944SGuochun Huang #define EDPI_TE_EN				28
42741874944SGuochun Huang #define EDPI_WMS_HOLD_EN			30
42841874944SGuochun Huang #define EDPI_WMS_FS				31
42941874944SGuochun Huang 
430d0408543SAndy Yan 
431d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL		0xC08
4325fa6e665SDamon Ding 
4335fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL			0xC0C
434a552a69cSDamon Ding #define RK3576_DCLK_CORE_SEL_SHIFT		0
435a552a69cSDamon Ding #define RK3576_DCLK_OUT_SEL_SHIFT		2
4365fa6e665SDamon Ding 
4376414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL			0xC10
4386414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT				0
4396414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT			2
4406414e3bcSSandy Huang 
441ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL			0xC0C
442ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT			0
443ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT			2
444ecc31b6eSAndy Yan 
4456414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST			0xC20
4466414e3bcSSandy Huang 
447d0408543SAndy Yan #define RK3568_VP0_DSP_BG			0xC2C
448d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
449d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
450d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
451d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
452d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL		0xC40
453d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
454d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
455d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END		0xC4C
456d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
457d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END		0xC54
458d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
459d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
460d0408543SAndy Yan 
461ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL			0xC60
462ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT			0
463ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK			0x1
464ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT		2
465ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK		0x3
466ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT			4
467ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK			0x1
468ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT		6
469ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK		0x3
470ac500a1fSSandy Huang 
471ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS			0xC64
472ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT			0
473ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK			0xFF
474ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT			8
475ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK			0x1FF
476ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT			20
477ac500a1fSSandy Huang #define BCSH_SATURATION_MASK			0x3FF
478ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT			30
479ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK			0x3
480ac500a1fSSandy Huang 
481ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H			0xC68
482ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT			0
483ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK			0x1FF
484ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT			16
485ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK			0x1FF
486ac500a1fSSandy Huang 
487ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR			0xC6C
488ac500a1fSSandy Huang #define BCSH_EN_SHIFT				31
489ac500a1fSSandy Huang #define BCSH_EN_MASK				1
490ac500a1fSSandy Huang 
491a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_0		0xCA0
492a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_1		0xCA4
493a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_2		0xCA8
494a552a69cSDamon Ding 
4956027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL			0xCD0
4966027c871SZhang Yubing #define POST_CSC_COE00_MASK			0xFFFF
4976027c871SZhang Yubing #define POST_CSC_COE00_SHIFT			16
4986027c871SZhang Yubing #define POST_R2Y_MODE_MASK			0x7
4996027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT			8
5006027c871SZhang Yubing #define POST_CSC_MODE_MASK			0x7
5016027c871SZhang Yubing #define POST_CSC_MODE_SHIFT			3
5026027c871SZhang Yubing #define POST_R2Y_EN_MASK			0x1
5036027c871SZhang Yubing #define POST_R2Y_EN_SHIFT			2
5046027c871SZhang Yubing #define POST_CSC_EN_MASK			0x1
5056027c871SZhang Yubing #define POST_CSC_EN_SHIFT			1
5066027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK			0x1
5076027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT		0
5086027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02			0xCD4
5096027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11			0xCD8
5106027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20			0xCDC
5116027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22			0xCE0
5126027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0			0xCE4
5136027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1			0xCE8
5146027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2			0xCEC
5156027c871SZhang Yubing 
5160675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL			0xCF8
5170675a2a4SDamon Ding #define MCU_TYPE_SHIFT				31
5180675a2a4SDamon Ding #define MCU_BYPASS_SHIFT			30
5190675a2a4SDamon Ding #define MCU_RS_SHIFT				29
5200675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT			28
5210675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT			27
5220675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT			26
5230675a2a4SDamon Ding #define MCU_CLK_SEL_MASK			0x1
5240675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT			20
5250675a2a4SDamon Ding #define MCU_RW_PEND_MASK			0x3F
5260675a2a4SDamon Ding #define MCU_RW_PST_SHIFT			16
5270675a2a4SDamon Ding #define MCU_RW_PST_MASK				0xF
5280675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT			10
5290675a2a4SDamon Ding #define MCU_CS_PEND_MASK			0x3F
5300675a2a4SDamon Ding #define MCU_CS_PST_SHIFT			6
5310675a2a4SDamon Ding #define MCU_CS_PST_MASK				0xF
5320675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT			0
5330675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK			0x3F
5340675a2a4SDamon Ding 
5350675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT		0xCFC
5360675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT		0
5370675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK		0xFFFFFFFF
5380675a2a4SDamon Ding 
539d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL			0xD00
540d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL			0xD04
541d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL		0xD08
542d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
543d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
544d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
545d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
546d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL		0xD40
547d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO		0xD34
548d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO		0xD38
549d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
550d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
551d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END		0xD4C
552d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
553d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END		0xD54
554d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
555d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
556d0408543SAndy Yan 
557d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL			0xE00
558d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL			0xE04
559d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL		0xE08
560d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
561d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
562d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
563d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
564d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL		0xE40
565d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO		0xE34
566d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO		0xE38
567d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
568d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
569d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END		0xE4C
570d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
571d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END		0xE54
572d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
573d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
574a552a69cSDamon Ding #define RK3568_VP2_BCSH_CTRL			0xE60
575a552a69cSDamon Ding #define RK3568_VP2_BCSH_BCS			0xE64
576a552a69cSDamon Ding #define RK3568_VP2_BCSH_H			0xE68
577a552a69cSDamon Ding #define RK3568_VP2_BCSH_COLOR_BAR		0xE6C
578a552a69cSDamon Ding #define RK3576_VP2_MCU_CTRL			0xEF8
579a552a69cSDamon Ding #define RK3576_VP2_MCU_RW_BYPASS_PORT		0xEFC
580d0408543SAndy Yan 
581d0408543SAndy Yan /* Cluster0 register definition */
582d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
583ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT		8
584ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT		9
585ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT			10
586840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT		18
587d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
5885fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT	12
5895fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
5905fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
5915fa6e665SDamon Ding #define AVG2_MASK				0x1
5925fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT			18
5935fa6e665SDamon Ding #define AVG4_MASK				0x1
5945fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT			19
5955fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT	22
5965fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT			24
5975fa6e665SDamon Ding #define XGT_MODE_MASK				0x3
5985fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT			25
5995fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT			27
600ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT			28
601ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT			29
602a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2		0x1008
603a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK		0x1f
604a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT		0
605a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK			0x1f
606a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT			5
607a33b790fSDamon Ding 
608d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
609d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
610d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR		0x1018
611d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
612d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
613d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
614d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
615a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_CTRL		0x1040
616a552a69cSDamon Ding #define WIN0_ZME_DERING_EN_SHIFT		3
617a552a69cSDamon Ding #define WIN0_ZME_GATING_EN_SHIFT		31
618a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA	0x1044
619d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
620d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
621d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
622d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
623d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
624d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
625d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
626a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT		7
627a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET	0x1078
628a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE	0x107C
629d0408543SAndy Yan 
630d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
631d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
632d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
633d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
634d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR		0x1098
635d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
636d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
637d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
638d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
639d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
640d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
641d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
642d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
643d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
644d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
645d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
646a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET	0x10F8
647a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE	0x10FC
648d0408543SAndy Yan 
649d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL			0x1100
650ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT			0
651a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK			0x1
652a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT			13
653a552a69cSDamon Ding #define RK3576_CLUSTER0_PORT_SEL		0x11F4
654a552a69cSDamon Ding #define CLUSTER_PORT_SEL_SHIFT			0
655a552a69cSDamon Ding #define CLUSTER_PORT_SEL_MASK			0x3
656a552a69cSDamon Ding #define RK3576_CLUSTER0_DLY_NUM			0x11F8
657a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_SHIFT		0
658a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_MASK		0xff
659a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_SHIFT		0
660a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_MASK		0xff
661d0408543SAndy Yan 
662d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
663d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
664d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
665d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
666d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR		0x1218
667d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
668d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
669d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
670d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
671a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_CTRL		0x1240
672a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA	0x1244
673d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
674d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
675d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
676d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
677d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
678d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
679d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
680a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET	0x1278
681a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE	0x127C
682d0408543SAndy Yan 
683d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
684d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
685d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
686d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
687d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR		0x1298
688d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
689d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
690d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
691d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
692d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
693d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
694d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
695d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
696d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
697d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
698d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
699a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET	0x12F8
700a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE	0x12FC
701d0408543SAndy Yan 
702d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL			0x1300
703a552a69cSDamon Ding #define RK3576_CLUSTER1_PORT_SEL		0x13F4
704a552a69cSDamon Ding #define RK3576_CLUSTER1_DLY_NUM			0x13F8
705d0408543SAndy Yan 
706d0408543SAndy Yan /* Esmart register definition */
707d0408543SAndy Yan #define RK3568_ESMART0_CTRL0			0x1800
70810ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT			1
70910ee9f5bSAlgea Cao #define CSC_MODE_SHIFT				2
71010ee9f5bSAlgea Cao #define CSC_MODE_MASK				0x3
7115fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT			12
7125fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK			0x3
713d0408543SAndy Yan 
714d0408543SAndy Yan #define RK3568_ESMART0_CTRL1			0x1804
715a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK			0x1f
716a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT		4
717a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK			0x1f
718a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT			12
719d0408543SAndy Yan #define YMIRROR_EN_SHIFT			31
720a33b790fSDamon Ding 
721a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL			0x1808
722a33b790fSDamon Ding #define ESMART_AXI_ID_MASK			0x1
723a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT			1
724a33b790fSDamon Ding 
725d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL		0x1810
726d0408543SAndy Yan #define WIN_EN_SHIFT				0
727d0408543SAndy Yan #define WIN_FORMAT_MASK				0x1f
728d0408543SAndy Yan #define WIN_FORMAT_SHIFT			1
729840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT		12
7305fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT			14
7315fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT			20
7325fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT			21
7335fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT			22
734d0408543SAndy Yan 
735d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
736d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
737d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR		0x181C
738d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
739d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
740d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
741d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
7423e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK			0x3
7433e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT			0
7443e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK		0x3
7453e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT		2
7463e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK			0x3
7473e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT			4
7483e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK		0x3
7493e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT		6
7503e39a5a1SSandy Huang 
751d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
752d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
753d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
754d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL		0x1840
7553e39a5a1SSandy Huang #define YRGB_GT2_MASK				0x1
7563e39a5a1SSandy Huang #define YRGB_GT2_SHIFT				8
7573e39a5a1SSandy Huang #define YRGB_GT4_MASK				0x1
7583e39a5a1SSandy Huang #define YRGB_GT4_SHIFT				9
7593e39a5a1SSandy Huang 
760d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
761d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
762d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR		0x184C
763d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
764d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
765d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
766d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
767d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
768d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
769d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
770d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL		0x1870
771d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
772d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
773d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR		0x187C
774d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
775d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
776d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
777d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
778d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
779d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
780d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
781d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL		0x18A0
782d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
783d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
784d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR		0x18AC
785d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
786d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
787d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
788d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
789d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
790d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
791d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
792a552a69cSDamon Ding #define RK3568_ESMART0_COLOR_KEY_CTRL		0x18D0
793a552a69cSDamon Ding #define RK3576_ESMART0_ALPHA_MAP		0x18D8
794a552a69cSDamon Ding #define RK3576_ESMART0_PORT_SEL			0x18F4
795a552a69cSDamon Ding #define ESMART_PORT_SEL_SHIFT			0
796a552a69cSDamon Ding #define ESMART_PORT_SEL_MASK			0x3
797a552a69cSDamon Ding #define RK3576_ESMART0_DLY_NUM			0x18F8
798d0408543SAndy Yan 
799d0408543SAndy Yan #define RK3568_ESMART1_CTRL0			0x1A00
800d0408543SAndy Yan #define RK3568_ESMART1_CTRL1			0x1A04
801d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL		0x1A10
802d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
803d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
804d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR		0x1A1C
805d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
806d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
807d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
808d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
809d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
810d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
811d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
812d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL		0x1A40
813d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
814d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
815d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR		0x1A4C
816d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
817d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
818d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
819d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
820d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
821d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
822d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
823d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL		0x1A70
824d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
825d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
826d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR		0x1A7C
827d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
828d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
829d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
830d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
831d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
832d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
833d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
834d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
835d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
836d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
837d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR		0x1AAC
838d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
839d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
840d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
841d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
842d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
843d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
844d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
845a552a69cSDamon Ding #define RK3576_ESMART1_ALPHA_MAP		0x1AD8
846a552a69cSDamon Ding #define RK3576_ESMART1_PORT_SEL			0x1AF4
847a552a69cSDamon Ding #define RK3576_ESMART1_DLY_NUM			0x1AF8
848d0408543SAndy Yan 
849d0408543SAndy Yan #define RK3568_SMART0_CTRL0			0x1C00
850d0408543SAndy Yan #define RK3568_SMART0_CTRL1			0x1C04
851d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL		0x1C10
852d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
853d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
854d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR		0x1C1C
855d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
856d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
857d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
858d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
859d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
860d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
861d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
862d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL		0x1C40
863d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
864d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
865d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR		0x1C4C
866d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
867d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
868d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
869d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
870d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
871d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
872d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
873d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL		0x1C70
874d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
875d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
876d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR		0x1C7C
877d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
878d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
879d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
880d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
881d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
882d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
883d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
884d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL		0x1CA0
885d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
886d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
887d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR		0x1CAC
888d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
889d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
890d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
891d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
892d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
893d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
894d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
895a552a69cSDamon Ding #define RK3576_ESMART2_ALPHA_MAP		0x1CD8
896a552a69cSDamon Ding #define RK3576_ESMART2_PORT_SEL			0x1CF4
897a552a69cSDamon Ding #define RK3576_ESMART2_DLY_NUM			0x1CF8
898d0408543SAndy Yan 
899d0408543SAndy Yan #define RK3568_SMART1_CTRL0			0x1E00
900d0408543SAndy Yan #define RK3568_SMART1_CTRL1			0x1E04
901d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL		0x1E10
902d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
903d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
904d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR		0x1E1C
905d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
906d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
907d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
908d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
909d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
910d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
911d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
912d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL		0x1E40
913d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
914d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
915d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR		0x1E4C
916d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
917d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
918d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
919d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
920d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
921d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
922d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
923d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL		0x1E70
924d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
925d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
926d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR		0x1E7C
927d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
928d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
929d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
930d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
931d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
932d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
933d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
934d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL		0x1EA0
935d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
936d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
937d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR		0x1EAC
938d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
939d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
940d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
941d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
942d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
943d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
944d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
945a552a69cSDamon Ding #define RK3576_ESMART3_ALPHA_MAP		0x1ED8
946a552a69cSDamon Ding #define RK3576_ESMART3_PORT_SEL			0x1EF4
947a552a69cSDamon Ding #define RK3576_ESMART3_DLY_NUM			0x1EF8
948d0408543SAndy Yan 
94972388c26SDamon Ding /* HDR register definition */
95072388c26SDamon Ding #define RK3568_HDR_LUT_CTRL			0x2000
95172388c26SDamon Ding 
95272388c26SDamon Ding #define RK3588_VP3_DSP_CTRL			0xF00
95372388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0		0x1400
95472388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0		0x1600
95572388c26SDamon Ding 
95612ee5af0SDamon Ding /* DSC 8K/4K register definition */
95712ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3			0x4000
95812ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0			0x40A0
95912ee5af0SDamon Ding #define DSC_EN_SHIFT				0
96012ee5af0SDamon Ding #define DSC_RBIT_SHIFT				2
96112ee5af0SDamon Ding #define DSC_RBYT_SHIFT				3
96212ee5af0SDamon Ding #define DSC_FLAL_SHIFT				4
96312ee5af0SDamon Ding #define DSC_MER_SHIFT				5
96412ee5af0SDamon Ding #define DSC_EPB_SHIFT				6
96512ee5af0SDamon Ding #define DSC_EPL_SHIFT				7
9661ace1b6dSDamon Ding #define DSC_NSLC_MASK				0x7
96712ee5af0SDamon Ding #define DSC_NSLC_SHIFT				16
96812ee5af0SDamon Ding #define DSC_SBO_SHIFT				28
96912ee5af0SDamon Ding #define DSC_IFEP_SHIFT				29
97012ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT			31
971baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT)   | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \
972baf2c414SDamon Ding 			   (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT)  | (0 << DSC_EPB_SHIFT)  | \
973baf2c414SDamon Ding 			   (1 << DSC_EPL_SHIFT)  | (1 << DSC_SBO_SHIFT))
97412ee5af0SDamon Ding 
97512ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1			0x40A4
97612ee5af0SDamon Ding #define RK3588_DSC_8K_STS0			0x40A8
97712ee5af0SDamon Ding #define RK3588_DSC_8K_ERS			0x40C4
97812ee5af0SDamon Ding 
97912ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3			0x4100
98012ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0			0x41A0
98112ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1			0x41A4
98212ee5af0SDamon Ding #define RK3588_DSC_4K_STS0			0x41A8
98312ee5af0SDamon Ding #define RK3588_DSC_4K_ERS			0x41C4
98412ee5af0SDamon Ding 
98572388c26SDamon Ding /* RK3528 HDR register definition */
98672388c26SDamon Ding #define RK3528_HDR_LUT_CTRL			0x2000
98772388c26SDamon Ding 
9886027c871SZhang Yubing /* RK3528 ACM register definition */
9896027c871SZhang Yubing #define RK3528_ACM_CTRL				0x6400
9906027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE			0x6404
9916027c871SZhang Yubing #define RK3528_ACM_FETCH_START			0x6408
9926027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE			0x6420
9936027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0		0x6500
9946027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152		0x6760
9956027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0		0x6764
9966027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220		0x6ad4
9976027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0		0x6ad8
9986027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64		0x6bd8
9996027c871SZhang Yubing 
1000d0408543SAndy Yan #define RK3568_MAX_REG				0x1ED0
1001d0408543SAndy Yan 
1002452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON		0x10500
100352ee18acSSandy Huang #define RK3568_GRF_VO_CON1			0x0364
100452ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT			1
100552ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT		2
100652ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT			3
100752ee18acSSandy Huang 
1008a552a69cSDamon Ding /* Base SYS_GRF: 0x2600a000*/
1009a552a69cSDamon Ding #define RK3576_SYS_GRF_MEMFAULT_STATUS0		0x0148
1010a552a69cSDamon Ding 
1011a552a69cSDamon Ding /* Base IOC_GRF: 0x26040000 */
1012a552a69cSDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8		0x6420
1013a552a69cSDamon Ding #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT	9
1014a552a69cSDamon Ding #define RK3576_IOC_VOPLITE_SEL_SHIFT		11
1015a552a69cSDamon Ding 
1016a552a69cSDamon Ding /* Base PMU2: 0x27380000 */
1017a552a69cSDamon Ding #define RK3576_PMU_PWR_GATE_STS			0x0230
1018a552a69cSDamon Ding #define PD_VOP_ESMART_DWN_STAT			12
1019a552a69cSDamon Ding #define PD_VOP_CLUSTER_DWN_STAT			13
1020a552a69cSDamon Ding #define RK3576_PMU_BISR_PDGEN_CON0		0x0510
1021a552a69cSDamon Ding #define PD_VOP_ESMART_REPAIR_ENA_SHIFT		12
1022a552a69cSDamon Ding #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT		13
1023a552a69cSDamon Ding #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0	0x0570
1024a552a69cSDamon Ding #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT	12
1025a552a69cSDamon Ding #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT	13
1026a552a69cSDamon Ding 
10275d2768f7SDamon Ding #define RK3588_GRF_SOC_CON1			0x0304
10285d2768f7SDamon Ding #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT	14
10295d2768f7SDamon Ding 
1030ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2			0x0008
1031ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT		0
1032ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT		1
1033ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT		3
1034ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT		4
1035ecc31b6eSAndy Yan 
1036b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0			0x0000
1037b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK			0x3
1038b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT			5
1039b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT			7
1040b890760eSAlgea Cao 
104160e469f5SDamon Ding #define RK3588_PMU_BISR_CON3			0x20C
104260e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT	9
104360e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT	10
104460e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT	11
104560e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT	12
1046b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT	13
1047b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT	14
104860e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT	15
104960e469f5SDamon Ding 
105060e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5			0x294
105160e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI	9
105260e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI	10
105360e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI	11
105460e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI	12
1055b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI		13
1056b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI		14
105760e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI		15
105860e469f5SDamon Ding 
1059d0408543SAndy Yan #define VOP2_LAYER_MAX				8
106063cb669fSSandy Huang 
1061ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH		4096
1062ee01dbb2SDamon Ding 
1063631ee99aSZhang Yubing /* KHz */
1064631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE			600000
1065631ee99aSZhang Yubing 
1066b6ba80b4SDamon Ding /*
1067b6ba80b4SDamon Ding  * vop2 dsc id
1068b6ba80b4SDamon Ding  */
1069b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K	0
1070b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K	1
1071b6ba80b4SDamon Ding 
1072b6ba80b4SDamon Ding /*
1073b6ba80b4SDamon Ding  * vop2 internal power domain id,
1074b6ba80b4SDamon Ding  * should be all none zero, 0 will be
1075b6ba80b4SDamon Ding  * treat as invalid;
1076b6ba80b4SDamon Ding  */
1077b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0			BIT(0)
1078b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1			BIT(1)
1079b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2			BIT(2)
1080b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3			BIT(3)
1081b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K				BIT(5)
1082b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K				BIT(6)
1083b6ba80b4SDamon Ding #define VOP2_PD_ESMART				BIT(7)
1084a552a69cSDamon Ding #define VOP2_PD_CLUSTER				BIT(8)
1085b6ba80b4SDamon Ding 
10864c765862SDamon Ding #define VOP2_PLANE_NO_SCALING			BIT(16)
10874c765862SDamon Ding 
10885fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT	BIT(0)
10895fa6e665SDamon Ding #define VOP_FEATURE_AFBDC		BIT(1)
10905fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE		BIT(2)
10915fa6e665SDamon Ding #define VOP_FEATURE_HDR10		BIT(3)
10925fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR		BIT(4)
10935fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */
10945fa6e665SDamon Ding #define VOP_FEATURE_SPLICE		BIT(5)
10955fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN		BIT(6)
10966027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR		BIT(7)
10976027c871SZhang Yubing #define VOP_FEATURE_POST_ACM		BIT(8)
10986027c871SZhang Yubing #define VOP_FEATURE_POST_CSC		BIT(9)
1099a552a69cSDamon Ding #define VOP_FEATURE_POST_FRC_V2		BIT(10)
1100a552a69cSDamon Ding #define VOP_FEATURE_POST_SHARP		BIT(11)
11015fa6e665SDamon Ding 
11025fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR		BIT(0)
11035fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR		BIT(1)
11045fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY		BIT(2)
11055fa6e665SDamon Ding #define WIN_FEATURE_AFBDC		BIT(3)
11065fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
11075fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB		BIT(5)
11085fa6e665SDamon Ding /* a mirror win can only get fb address
11095fa6e665SDamon Ding  * from source win:
11105fa6e665SDamon Ding  * Cluster1---->Cluster0
11115fa6e665SDamon Ding  * Esmart1 ---->Esmart0
11125fa6e665SDamon Ding  * Smart1  ---->Smart0
11135fa6e665SDamon Ding  * This is a feather on rk3566
11145fa6e665SDamon Ding  */
11155fa6e665SDamon Ding #define WIN_FEATURE_MIRROR		BIT(6)
11165fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA		BIT(7)
11175fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH	BIT(8)
1118a552a69cSDamon Ding #define WIN_FEATURE_DCI			BIT(9)
11195fa6e665SDamon Ding 
11205fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F		0xfe
11215fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F		0xff
11225fa6e665SDamon Ding 
11235fa6e665SDamon Ding enum vop_csc_format {
112410ee9f5bSAlgea Cao 	CSC_BT601L,
112510ee9f5bSAlgea Cao 	CSC_BT709L,
112610ee9f5bSAlgea Cao 	CSC_BT601F,
1127df0a5c43SDamon Ding 	CSC_BT2020L,
11285fa6e665SDamon Ding 	CSC_BT709L_13BIT,
11295fa6e665SDamon Ding 	CSC_BT709F_13BIT,
11305fa6e665SDamon Ding 	CSC_BT2020L_13BIT,
11315fa6e665SDamon Ding 	CSC_BT2020F_13BIT,
11325fa6e665SDamon Ding };
11335fa6e665SDamon Ding 
11345fa6e665SDamon Ding enum vop_csc_bit_depth {
11355fa6e665SDamon Ding 	CSC_10BIT_DEPTH,
11365fa6e665SDamon Ding 	CSC_13BIT_DEPTH,
113710ee9f5bSAlgea Cao };
113810ee9f5bSAlgea Cao 
113910ee9f5bSAlgea Cao enum vop2_pol {
114010ee9f5bSAlgea Cao 	HSYNC_POSITIVE = 0,
114110ee9f5bSAlgea Cao 	VSYNC_POSITIVE = 1,
114210ee9f5bSAlgea Cao 	DEN_NEGATIVE   = 2,
114310ee9f5bSAlgea Cao 	DCLK_INVERT    = 3
114410ee9f5bSAlgea Cao };
114510ee9f5bSAlgea Cao 
1146ac500a1fSSandy Huang enum vop2_bcsh_out_mode {
1147ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLACK,
1148ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLUE,
1149ac500a1fSSandy Huang 	BCSH_OUT_MODE_COLOR_BAR,
1150ac500a1fSSandy Huang 	BCSH_OUT_MODE_NORMAL_VIDEO,
1151ac500a1fSSandy Huang };
1152ac500a1fSSandy Huang 
1153d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \
1154d0408543SAndy Yan 		{ \
1155d0408543SAndy Yan 		 .offset = off, \
1156d0408543SAndy Yan 		 .mask = _mask, \
1157d0408543SAndy Yan 		 .shift = _shift, \
1158d0408543SAndy Yan 		 .write_mask = _write_mask, \
1159d0408543SAndy Yan 		}
1160d0408543SAndy Yan 
1161d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \
1162d0408543SAndy Yan 		_VOP_REG(off, _mask, _shift, false)
1163d0408543SAndy Yan enum dither_down_mode {
1164d0408543SAndy Yan 	RGB888_TO_RGB565 = 0x0,
1165d0408543SAndy Yan 	RGB888_TO_RGB666 = 0x1
1166d0408543SAndy Yan };
1167d0408543SAndy Yan 
1168a552a69cSDamon Ding enum dither_down_mode_sel {
1169a552a69cSDamon Ding 	DITHER_DOWN_ALLEGRO = 0x0,
1170a552a69cSDamon Ding 	DITHER_DOWN_FRC = 0x1
1171a552a69cSDamon Ding };
1172a552a69cSDamon Ding 
1173d0408543SAndy Yan enum vop2_video_ports_id {
1174d0408543SAndy Yan 	VOP2_VP0,
1175d0408543SAndy Yan 	VOP2_VP1,
1176d0408543SAndy Yan 	VOP2_VP2,
1177d0408543SAndy Yan 	VOP2_VP3,
1178d0408543SAndy Yan 	VOP2_VP_MAX,
1179d0408543SAndy Yan };
1180d0408543SAndy Yan 
1181ee008497SSandy Huang enum vop2_layer_type {
1182ee008497SSandy Huang 	CLUSTER_LAYER = 0,
1183ee008497SSandy Huang 	ESMART_LAYER = 1,
1184ee008497SSandy Huang 	SMART_LAYER = 2,
1185ee008497SSandy Huang };
1186ee008497SSandy Huang 
1187b0989546SSandy Huang /* This define must same with kernel win phy id */
1188b0989546SSandy Huang enum vop2_layer_phy_id {
1189b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER0 = 0,
1190b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER1,
1191b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART0,
1192b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART1,
1193b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART0,
1194b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART1,
1195b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER2,
1196b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER3,
1197b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART2,
1198b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART3,
1199ee008497SSandy Huang 	ROCKCHIP_VOP2_LAYER_MAX,
1200d0408543SAndy Yan };
1201d0408543SAndy Yan 
12023e39a5a1SSandy Huang enum vop2_scale_up_mode {
12033e39a5a1SSandy Huang 	VOP2_SCALE_UP_NRST_NBOR,
12043e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIL,
12053e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIC,
1206a552a69cSDamon Ding 	VOP2_SCALE_UP_ZME,
12073e39a5a1SSandy Huang };
12083e39a5a1SSandy Huang 
12093e39a5a1SSandy Huang enum vop2_scale_down_mode {
12103e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_NRST_NBOR,
12113e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_BIL,
12123e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_AVG,
1213a552a69cSDamon Ding 	VOP2_SCALE_DOWN_ZME,
12143e39a5a1SSandy Huang };
12153e39a5a1SSandy Huang 
12163e39a5a1SSandy Huang enum scale_mode {
12173e39a5a1SSandy Huang 	SCALE_NONE = 0x0,
12183e39a5a1SSandy Huang 	SCALE_UP   = 0x1,
12193e39a5a1SSandy Huang 	SCALE_DOWN = 0x2
12203e39a5a1SSandy Huang };
12213e39a5a1SSandy Huang 
122212ee5af0SDamon Ding enum vop_dsc_interface_mode {
122312ee5af0SDamon Ding 	VOP_DSC_IF_DISABLE = 0,
122412ee5af0SDamon Ding 	VOP_DSC_IF_HDMI = 1,
122512ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_DS_MODE = 2,
122612ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_VIDEO_MODE = 3,
122712ee5af0SDamon Ding };
122812ee5af0SDamon Ding 
12295fa6e665SDamon Ding enum vop3_pre_scale_down_mode {
12305fa6e665SDamon Ding 	VOP3_PRE_SCALE_UNSPPORT,
12315fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_GT,
12325fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_AVG,
12335fa6e665SDamon Ding };
12345fa6e665SDamon Ding 
12355fa6e665SDamon Ding enum vop3_esmart_lb_mode {
12365fa6e665SDamon Ding 	VOP3_ESMART_8K_MODE,
12375fa6e665SDamon Ding 	VOP3_ESMART_4K_4K_MODE,
12385fa6e665SDamon Ding 	VOP3_ESMART_4K_2K_2K_MODE,
12395fa6e665SDamon Ding 	VOP3_ESMART_2K_2K_2K_2K_MODE,
1240a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_4K_MODE,
1241a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_2K_2K_MODE,
12425fa6e665SDamon Ding };
12435fa6e665SDamon Ding 
12443e39a5a1SSandy Huang struct vop2_layer {
12453e39a5a1SSandy Huang 	u8 id;
12463e39a5a1SSandy Huang 	/**
12473e39a5a1SSandy Huang 	 * @win_phys_id: window id of the layer selected.
12483e39a5a1SSandy Huang 	 * Every layer must make sure to select different
12493e39a5a1SSandy Huang 	 * windows of others.
12503e39a5a1SSandy Huang 	 */
12513e39a5a1SSandy Huang 	u8 win_phys_id;
12523e39a5a1SSandy Huang };
12533e39a5a1SSandy Huang 
125460e469f5SDamon Ding struct vop2_power_domain_data {
1255a552a69cSDamon Ding 	u16 id;
1256a552a69cSDamon Ding 	u16 parent_id;
1257b6ba80b4SDamon Ding 	/*
1258b6ba80b4SDamon Ding 	 * @module_id_mask: module id of which module this power domain is belongs to.
1259b6ba80b4SDamon Ding 	 * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3
1260b6ba80b4SDamon Ding 	 */
1261b6ba80b4SDamon Ding 	u32 module_id_mask;
126260e469f5SDamon Ding };
126360e469f5SDamon Ding 
1264b0989546SSandy Huang struct vop2_win_data {
1265b0989546SSandy Huang 	char *name;
126663cb669fSSandy Huang 	u8 phys_id;
1267ecc31b6eSAndy Yan 	enum vop2_layer_type type;
1268b0989546SSandy Huang 	u8 win_sel_port_offset;
12695fa6e665SDamon Ding 	u8 layer_sel_win_id[VOP2_VP_MAX];
1270a33b790fSDamon Ding 	u8 axi_id;
1271a33b790fSDamon Ding 	u8 axi_uv_id;
1272a33b790fSDamon Ding 	u8 axi_yrgb_id;
1273ee01dbb2SDamon Ding 	u8 splice_win_id;
12745fa6e665SDamon Ding 	u8 hsu_filter_mode;
12755fa6e665SDamon Ding 	u8 hsd_filter_mode;
12765fa6e665SDamon Ding 	u8 vsu_filter_mode;
12775fa6e665SDamon Ding 	u8 vsd_filter_mode;
12785fa6e665SDamon Ding 	u8 hsd_pre_filter_mode;
12795fa6e665SDamon Ding 	u8 vsd_pre_filter_mode;
12805fa6e665SDamon Ding 	u8 scale_engine_num;
12811c9572c7SDamon Ding 	u8 source_win_id;
1282a552a69cSDamon Ding 	u8 possible_crtcs;
1283a552a69cSDamon Ding 	u16 pd_id;
1284b0989546SSandy Huang 	u32 reg_offset;
12854c765862SDamon Ding 	u32 max_upscale_factor;
12864c765862SDamon Ding 	u32 max_downscale_factor;
12871c9572c7SDamon Ding 	u32 feature;
1288a552a69cSDamon Ding 	u32 supported_rotations;
1289ee01dbb2SDamon Ding 	bool splice_mode_right;
129063cb669fSSandy Huang };
129163cb669fSSandy Huang 
129263cb669fSSandy Huang struct vop2_vp_data {
129363cb669fSSandy Huang 	u32 feature;
129463cb669fSSandy Huang 	u8 pre_scan_max_dly;
1295452afb13SDamon Ding 	u8 layer_mix_dly;
1296a552a69cSDamon Ding 	u8 hdrvivid_dly;
1297a552a69cSDamon Ding 	u8 sdr2hdr_dly;
1298452afb13SDamon Ding 	u8 hdr_mix_dly;
1299452afb13SDamon Ding 	u8 win_dly;
1300ee01dbb2SDamon Ding 	u8 splice_vp_id;
1301a552a69cSDamon Ding 	u8 pixel_rate;
130263cb669fSSandy Huang 	struct vop_rect max_output;
1303ecc31b6eSAndy Yan 	u32 max_dclk;
1304d0408543SAndy Yan };
1305d0408543SAndy Yan 
1306ee008497SSandy Huang struct vop2_plane_table {
1307ee008497SSandy Huang 	enum vop2_layer_phy_id plane_id;
1308ee008497SSandy Huang 	enum vop2_layer_type plane_type;
1309ee008497SSandy Huang };
1310ee008497SSandy Huang 
1311b0989546SSandy Huang struct vop2_vp_plane_mask {
1312b0989546SSandy Huang 	u8 primary_plane_id; /* use this win to show logo */
1313b0989546SSandy Huang 	u8 attached_layers_nr; /* number layers attach to this vp */
1314b0989546SSandy Huang 	u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
1315b0989546SSandy Huang 	u32 plane_mask;
1316ee008497SSandy Huang 	int cursor_plane_id;
1317b0989546SSandy Huang };
1318b0989546SSandy Huang 
131912ee5af0SDamon Ding struct vop2_dsc_data {
132012ee5af0SDamon Ding 	u8 id;
132112ee5af0SDamon Ding 	u8 max_slice_num;
132212ee5af0SDamon Ding 	u8 max_linebuf_depth;	/* used to generate the bitstream */
132312ee5af0SDamon Ding 	u8 min_bits_per_pixel;	/* bit num after encoder compress */
1324a552a69cSDamon Ding 	u16 pd_id;
132512ee5af0SDamon Ding 	const char *dsc_txp_clk_src_name;
132612ee5af0SDamon Ding 	const char *dsc_txp_clk_name;
132712ee5af0SDamon Ding 	const char *dsc_pxl_clk_name;
132812ee5af0SDamon Ding 	const char *dsc_cds_clk_name;
132912ee5af0SDamon Ding };
133012ee5af0SDamon Ding 
133112ee5af0SDamon Ding struct dsc_error_info {
133212ee5af0SDamon Ding 	u32 dsc_error_val;
133312ee5af0SDamon Ding 	char dsc_error_info[50];
133412ee5af0SDamon Ding };
133512ee5af0SDamon Ding 
133672388c26SDamon Ding struct vop2_dump_regs {
133772388c26SDamon Ding 	u32 offset;
133872388c26SDamon Ding 	const char *name;
133972388c26SDamon Ding 	u32 state_base;
134072388c26SDamon Ding 	u32 state_mask;
134172388c26SDamon Ding 	u32 state_shift;
134272388c26SDamon Ding 	bool enable_state;
1343a552a69cSDamon Ding 	u32 size;
1344a552a69cSDamon Ding };
1345a552a69cSDamon Ding 
1346a552a69cSDamon Ding struct vop2_esmart_lb_map {
1347a552a69cSDamon Ding 	u8 lb_mode;
1348a552a69cSDamon Ding 	u8 lb_map_value;
134972388c26SDamon Ding };
135072388c26SDamon Ding 
1351d0408543SAndy Yan struct vop2_data {
135252ee18acSSandy Huang 	u32 version;
13535fa6e665SDamon Ding 	u32 esmart_lb_mode;
135463cb669fSSandy Huang 	struct vop2_vp_data *vp_data;
1355b0989546SSandy Huang 	struct vop2_win_data *win_data;
1356b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
1357ee008497SSandy Huang 	struct vop2_plane_table *plane_table;
1358b6ba80b4SDamon Ding 	struct vop2_power_domain_data *pd;
135912ee5af0SDamon Ding 	struct vop2_dsc_data *dsc;
136012ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_ecw;
136112ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_buffer_flow;
136272388c26SDamon Ding 	struct vop2_dump_regs *dump_regs;
1363a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map;
1364337d1c13SDamon Ding 	u8 *vp_primary_plane_order;
1365a552a69cSDamon Ding 	u8 *vp_default_primary_plane;
136663cb669fSSandy Huang 	u8 nr_vps;
136763cb669fSSandy Huang 	u8 nr_layers;
136863cb669fSSandy Huang 	u8 nr_mixers;
13691147facaSSandy Huang 	u8 nr_gammas;
1370b6ba80b4SDamon Ding 	u8 nr_pd;
137112ee5af0SDamon Ding 	u8 nr_dscs;
137212ee5af0SDamon Ding 	u8 nr_dsc_ecw;
137312ee5af0SDamon Ding 	u8 nr_dsc_buffer_flow;
1374a552a69cSDamon Ding 	u8 esmart_lb_mode_num;
1375ecc31b6eSAndy Yan 	u32 reg_len;
137672388c26SDamon Ding 	u32 dump_regs_size;
1377d0408543SAndy Yan };
1378d0408543SAndy Yan 
1379d0408543SAndy Yan struct vop2 {
1380d0408543SAndy Yan 	u32 *regsbak;
1381d0408543SAndy Yan 	void *regs;
1382d0408543SAndy Yan 	void *grf;
1383ecc31b6eSAndy Yan 	void *vop_grf;
1384ecc31b6eSAndy Yan 	void *vo1_grf;
138560e469f5SDamon Ding 	void *sys_pmu;
1386a552a69cSDamon Ding 	void *ioc_grf;
138752ee18acSSandy Huang 	u32 reg_len;
138852ee18acSSandy Huang 	u32 version;
13895fa6e665SDamon Ding 	u32 esmart_lb_mode;
139063cb669fSSandy Huang 	bool global_init;
1391a552a69cSDamon Ding 	bool merge_irq;
1392d0408543SAndy Yan 	const struct vop2_data *data;
1393b0989546SSandy Huang 	struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
1394d0408543SAndy Yan };
1395d0408543SAndy Yan 
1396d0408543SAndy Yan static struct vop2 *rockchip_vop2;
13975fa6e665SDamon Ding 
13985fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2)
13995fa6e665SDamon Ding {
14005fa6e665SDamon Ding 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588)
14015fa6e665SDamon Ding 		return false;
14025fa6e665SDamon Ding 	else
14035fa6e665SDamon Ding 		return true;
14045fa6e665SDamon Ding }
14055fa6e665SDamon Ding 
14063e39a5a1SSandy Huang /*
14073e39a5a1SSandy Huang  * bli_sd_factor = (src - 1) / (dst - 1) << 12;
14083e39a5a1SSandy Huang  * avg_sd_factor:
14093e39a5a1SSandy Huang  * bli_su_factor:
14103e39a5a1SSandy Huang  * bic_su_factor:
14113e39a5a1SSandy Huang  * = (src - 1) / (dst - 1) << 16;
14123e39a5a1SSandy Huang  *
14135fa6e665SDamon Ding  * ygt2 enable: dst get one line from two line of the src
14145fa6e665SDamon Ding  * ygt4 enable: dst get one line from four line of the src.
14153e39a5a1SSandy Huang  *
14163e39a5a1SSandy Huang  */
14173e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst)	(((src - 1) << 12) / (dst - 1))
14183e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst)	(((src - 1) << 16) / (dst - 1))
14193e39a5a1SSandy Huang 
14203e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)	 \
14213e39a5a1SSandy Huang 				(fac * (dst - 1) >> 12 < (src - 1))
14223e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
14233e39a5a1SSandy Huang 				(fac * (dst - 1) >> 16 < (src - 1))
14245fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
14255fa6e665SDamon Ding 				(fac * (dst - 1) >> 16 < (src - 1))
14263e39a5a1SSandy Huang 
14273e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode,
14283e39a5a1SSandy Huang 				  int32_t filter_mode,
14293e39a5a1SSandy Huang 				  uint32_t src, uint32_t dst)
14303e39a5a1SSandy Huang {
14313e39a5a1SSandy Huang 	uint32_t fac = 0;
14323e39a5a1SSandy Huang 	int i = 0;
14333e39a5a1SSandy Huang 
14343e39a5a1SSandy Huang 	if (mode == SCALE_NONE)
14353e39a5a1SSandy Huang 		return 0;
14363e39a5a1SSandy Huang 
14373e39a5a1SSandy Huang 	/*
14383e39a5a1SSandy Huang 	 * A workaround to avoid zero div.
14393e39a5a1SSandy Huang 	 */
14403e39a5a1SSandy Huang 	if ((dst == 1) || (src == 1)) {
14413e39a5a1SSandy Huang 		dst = dst + 1;
14423e39a5a1SSandy Huang 		src = src + 1;
14433e39a5a1SSandy Huang 	}
14443e39a5a1SSandy Huang 
14453e39a5a1SSandy Huang 	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
14463e39a5a1SSandy Huang 		fac = VOP2_BILI_SCL_DN(src, dst);
14473e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
14483e39a5a1SSandy Huang 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
14493e39a5a1SSandy Huang 				break;
14503e39a5a1SSandy Huang 			fac -= 1;
14513e39a5a1SSandy Huang 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
14523e39a5a1SSandy Huang 		}
14533e39a5a1SSandy Huang 	} else {
14543e39a5a1SSandy Huang 		fac = VOP2_COMMON_SCL(src, dst);
14553e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
14563e39a5a1SSandy Huang 			if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
14573e39a5a1SSandy Huang 				break;
14583e39a5a1SSandy Huang 			fac -= 1;
14593e39a5a1SSandy Huang 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
14603e39a5a1SSandy Huang 		}
14613e39a5a1SSandy Huang 	}
14623e39a5a1SSandy Huang 
14633e39a5a1SSandy Huang 	return fac;
14643e39a5a1SSandy Huang }
14653e39a5a1SSandy Huang 
14665fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor)
14675fa6e665SDamon Ding {
14685fa6e665SDamon Ding 	if (is_hor)
14695fa6e665SDamon Ding 		return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac);
14705fa6e665SDamon Ding 	return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac);
14715fa6e665SDamon Ding }
14725fa6e665SDamon Ding 
14735fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode,
14745fa6e665SDamon Ding 				  uint32_t src, uint32_t dst, bool is_hor)
14755fa6e665SDamon Ding {
14765fa6e665SDamon Ding 	uint32_t fac = 0;
14775fa6e665SDamon Ding 	int i = 0;
14785fa6e665SDamon Ding 
14795fa6e665SDamon Ding 	if (mode == SCALE_NONE)
14805fa6e665SDamon Ding 		return 0;
14815fa6e665SDamon Ding 
14825fa6e665SDamon Ding 	/*
14835fa6e665SDamon Ding 	 * A workaround to avoid zero div.
14845fa6e665SDamon Ding 	 */
14855fa6e665SDamon Ding 	if ((dst == 1) || (src == 1)) {
14865fa6e665SDamon Ding 		dst = dst + 1;
14875fa6e665SDamon Ding 		src = src + 1;
14885fa6e665SDamon Ding 	}
14895fa6e665SDamon Ding 
14905fa6e665SDamon Ding 	if (mode == SCALE_DOWN) {
14915fa6e665SDamon Ding 		fac = VOP2_BILI_SCL_DN(src, dst);
14925fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
14935fa6e665SDamon Ding 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
14945fa6e665SDamon Ding 				break;
14955fa6e665SDamon Ding 			fac -= 1;
14965fa6e665SDamon Ding 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
14975fa6e665SDamon Ding 		}
14985fa6e665SDamon Ding 	} else {
14995fa6e665SDamon Ding 		fac = VOP2_COMMON_SCL(src, dst);
15005fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
15015fa6e665SDamon Ding 			if (vop3_scale_up_fac_check(src, dst, fac, is_hor))
15025fa6e665SDamon Ding 				break;
15035fa6e665SDamon Ding 			fac -= 1;
15045fa6e665SDamon Ding 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15055fa6e665SDamon Ding 		}
15065fa6e665SDamon Ding 	}
15075fa6e665SDamon Ding 
15085fa6e665SDamon Ding 	return fac;
15095fa6e665SDamon Ding }
15105fa6e665SDamon Ding 
15113e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst)
15123e39a5a1SSandy Huang {
15133e39a5a1SSandy Huang 	if (src < dst)
15143e39a5a1SSandy Huang 		return SCALE_UP;
15153e39a5a1SSandy Huang 	else if (src > dst)
15163e39a5a1SSandy Huang 		return SCALE_DOWN;
15173e39a5a1SSandy Huang 
15183e39a5a1SSandy Huang 	return SCALE_NONE;
15193e39a5a1SSandy Huang }
1520d0408543SAndy Yan 
1521ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x)
1522ac500a1fSSandy Huang {
1523ac500a1fSSandy Huang 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
1524ac500a1fSSandy Huang }
1525ac500a1fSSandy Huang 
1526b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask)
1527b0989546SSandy Huang {
1528b0989546SSandy Huang 	int i = 0;
1529ecc31b6eSAndy Yan 
1530337d1c13SDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
1531337d1c13SDamon Ding 		if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i]))
1532337d1c13SDamon Ding 			return vop2->data->vp_primary_plane_order[i];
1533ecc31b6eSAndy Yan 	}
1534b0989546SSandy Huang 
1535337d1c13SDamon Ding 	return vop2->data->vp_primary_plane_order[0];
1536b0989546SSandy Huang }
1537b0989546SSandy Huang 
153863cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift)
1539d0408543SAndy Yan {
1540d0408543SAndy Yan 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
1541d0408543SAndy Yan }
1542d0408543SAndy Yan 
154363cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst)
1544d0408543SAndy Yan {
1545d0408543SAndy Yan 	return ((src - 1) << 12) / (dst - 1);
1546d0408543SAndy Yan }
1547d0408543SAndy Yan 
154852ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
1549d0408543SAndy Yan {
1550d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1551d0408543SAndy Yan 	vop2->regsbak[offset >> 2] = v;
1552d0408543SAndy Yan }
1553d0408543SAndy Yan 
155452ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
1555d0408543SAndy Yan {
1556d0408543SAndy Yan 	return readl(vop2->regs + offset);
1557d0408543SAndy Yan }
1558d0408543SAndy Yan 
155952ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
156052ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v,
1561d0408543SAndy Yan 				   bool write_mask)
1562d0408543SAndy Yan {
1563d0408543SAndy Yan 	if (!mask)
1564d0408543SAndy Yan 		return;
1565d0408543SAndy Yan 
1566d0408543SAndy Yan 	if (write_mask) {
1567d0408543SAndy Yan 		v = ((v & mask) << shift) | (mask << (shift + 16));
1568d0408543SAndy Yan 	} else {
156952ee18acSSandy Huang 		u32 cached_val = vop2->regsbak[offset >> 2];
1570d0408543SAndy Yan 
1571d0408543SAndy Yan 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
1572d0408543SAndy Yan 		vop2->regsbak[offset >> 2] = v;
1573d0408543SAndy Yan 	}
1574d0408543SAndy Yan 
1575d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1576d0408543SAndy Yan }
1577d0408543SAndy Yan 
1578ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
157952ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v)
158052ee18acSSandy Huang {
158152ee18acSSandy Huang 	u32 val = 0;
158252ee18acSSandy Huang 
158352ee18acSSandy Huang 	val = (v << shift) | (mask << (shift + 16));
1584ecc31b6eSAndy Yan 	writel(val, grf_base + offset);
158552ee18acSSandy Huang }
158652ee18acSSandy Huang 
158760e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
158860e469f5SDamon Ding 				  u32 mask, u32 shift)
158960e469f5SDamon Ding {
159060e469f5SDamon Ding 	return (readl(grf_base + offset) >> shift) & mask;
159160e469f5SDamon Ding }
159260e469f5SDamon Ding 
15938895aec1SSandy Huang static char *get_plane_name(int plane_id, char *name)
15948895aec1SSandy Huang {
15958895aec1SSandy Huang 	switch (plane_id) {
15968895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER0:
15978895aec1SSandy Huang 		strcat(name, "Cluster0");
15988895aec1SSandy Huang 		break;
15998895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER1:
16008895aec1SSandy Huang 		strcat(name, "Cluster1");
16018895aec1SSandy Huang 		break;
16028895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART0:
16038895aec1SSandy Huang 		strcat(name, "Esmart0");
16048895aec1SSandy Huang 		break;
16058895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART1:
16068895aec1SSandy Huang 		strcat(name, "Esmart1");
16078895aec1SSandy Huang 		break;
16088895aec1SSandy Huang 	case ROCKCHIP_VOP2_SMART0:
16098895aec1SSandy Huang 		strcat(name, "Smart0");
16108895aec1SSandy Huang 		break;
16118895aec1SSandy Huang 	case ROCKCHIP_VOP2_SMART1:
16128895aec1SSandy Huang 		strcat(name, "Smart1");
16138895aec1SSandy Huang 		break;
16148895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER2:
16158895aec1SSandy Huang 		strcat(name, "Cluster2");
16168895aec1SSandy Huang 		break;
16178895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER3:
16188895aec1SSandy Huang 		strcat(name, "Cluster3");
16198895aec1SSandy Huang 		break;
16208895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART2:
16218895aec1SSandy Huang 		strcat(name, "Esmart2");
16228895aec1SSandy Huang 		break;
16238895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART3:
16248895aec1SSandy Huang 		strcat(name, "Esmart3");
16258895aec1SSandy Huang 		break;
16268895aec1SSandy Huang 	}
16278895aec1SSandy Huang 
16288895aec1SSandy Huang 	return name;
16298895aec1SSandy Huang }
16308895aec1SSandy Huang 
163152ee18acSSandy Huang static bool is_yuv_output(u32 bus_format)
1632d0408543SAndy Yan {
1633d0408543SAndy Yan 	switch (bus_format) {
1634d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
1635d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
1636034a46b5SAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
1637d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1638d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1639a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
1640a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
1641a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_2X8:
1642a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_2X8:
1643a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
1644a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
1645a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_1X16:
1646a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_1X16:
1647d0408543SAndy Yan 		return true;
1648d0408543SAndy Yan 	default:
1649d0408543SAndy Yan 		return false;
1650d0408543SAndy Yan 	}
1651d0408543SAndy Yan }
1652d0408543SAndy Yan 
1653df0a5c43SDamon Ding static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding,
1654df0a5c43SDamon Ding 						 enum drm_color_range color_range,
1655df0a5c43SDamon Ding 						 int bit_depth)
165610ee9f5bSAlgea Cao {
1657df0a5c43SDamon Ding 	bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
1658df0a5c43SDamon Ding 	enum vop_csc_format csc_mode = CSC_BT709L;
1659df0a5c43SDamon Ding 
1660df0a5c43SDamon Ding 
1661df0a5c43SDamon Ding 	switch (color_encoding) {
1662df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT601:
1663df0a5c43SDamon Ding 		if (full_range)
1664df0a5c43SDamon Ding 			csc_mode = CSC_BT601F;
16655fa6e665SDamon Ding 		else
1666df0a5c43SDamon Ding 			csc_mode = CSC_BT601L;
1667df0a5c43SDamon Ding 		break;
1668df0a5c43SDamon Ding 
1669df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT709:
1670df0a5c43SDamon Ding 		if (full_range) {
1671df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F;
1672df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1673df0a5c43SDamon Ding 				printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n");
16745fa6e665SDamon Ding 		} else {
1675df0a5c43SDamon Ding 			csc_mode = CSC_BT709L;
16765fa6e665SDamon Ding 		}
1677df0a5c43SDamon Ding 		break;
1678df0a5c43SDamon Ding 
1679df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT2020:
1680df0a5c43SDamon Ding 		if (full_range) {
1681df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F;
1682df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1683df0a5c43SDamon Ding 				printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n");
16845fa6e665SDamon Ding 		} else {
1685df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L;
16865fa6e665SDamon Ding 		}
1687df0a5c43SDamon Ding 		break;
1688df0a5c43SDamon Ding 
168910ee9f5bSAlgea Cao 	default:
1690df0a5c43SDamon Ding 		printf("Unsuport color_encoding:%d\n", color_encoding);
169110ee9f5bSAlgea Cao 	}
1692df0a5c43SDamon Ding 
1693df0a5c43SDamon Ding 	return csc_mode;
169410ee9f5bSAlgea Cao }
169510ee9f5bSAlgea Cao 
1696b0989546SSandy Huang static bool is_uv_swap(u32 bus_format, u32 output_mode)
1697d0408543SAndy Yan {
1698d0408543SAndy Yan 	/*
1699d0408543SAndy Yan 	 * FIXME:
1700d0408543SAndy Yan 	 *
1701d0408543SAndy Yan 	 * There is no media type for YUV444 output,
1702d0408543SAndy Yan 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
1703d0408543SAndy Yan 	 * yuv format.
1704d0408543SAndy Yan 	 *
1705d0408543SAndy Yan 	 * From H/W testing, YUV444 mode need a rb swap.
1706d0408543SAndy Yan 	 */
17073e59c137SSandy Huang 	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
17083e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
17093e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
17103e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
17113e59c137SSandy Huang 	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1712d0408543SAndy Yan 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1713d0408543SAndy Yan 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
17143e59c137SSandy Huang 	     output_mode == ROCKCHIP_OUT_MODE_P888)))
1715d0408543SAndy Yan 		return true;
1716d0408543SAndy Yan 	else
1717d0408543SAndy Yan 		return false;
1718d0408543SAndy Yan }
1719d0408543SAndy Yan 
17200675a2a4SDamon Ding static bool is_rb_swap(u32 bus_format, u32 output_mode)
17210675a2a4SDamon Ding {
17220675a2a4SDamon Ding 	/*
17230675a2a4SDamon Ding 	 * The default component order of serial rgb3x8 formats
17240675a2a4SDamon Ding 	 * is BGR. So it is needed to enable RB swap.
17250675a2a4SDamon Ding 	 */
1726b7b383ebSDamon Ding 	if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
1727b7b383ebSDamon Ding 	    bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8)
17280675a2a4SDamon Ding 		return true;
17290675a2a4SDamon Ding 	else
17300675a2a4SDamon Ding 		return false;
17310675a2a4SDamon Ding }
17320675a2a4SDamon Ding 
17335d2768f7SDamon Ding static bool is_yc_swap(u32 bus_format)
17345d2768f7SDamon Ding {
17355d2768f7SDamon Ding 	switch (bus_format) {
17365d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
17375d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
17385d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
17395d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
17405d2768f7SDamon Ding 		return true;
17415d2768f7SDamon Ding 	default:
17425d2768f7SDamon Ding 		return false;
17435d2768f7SDamon Ding 	}
17445d2768f7SDamon Ding }
17455d2768f7SDamon Ding 
1746b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type)
174763cb669fSSandy Huang {
1748b0989546SSandy Huang 	switch (output_type) {
1749b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIA:
1750b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIB:
1751b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_TV:
1752b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_DisplayPort:
1753b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_VGA:
1754b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_Unknown:
1755b0989546SSandy Huang 		return true;
1756b0989546SSandy Huang 	default:
1757b0989546SSandy Huang 		return false;
175863cb669fSSandy Huang 	}
175963cb669fSSandy Huang }
176063cb669fSSandy Huang 
1761ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1762ecc31b6eSAndy Yan {
1763ecc31b6eSAndy Yan 	int i = 0;
1764ecc31b6eSAndy Yan 
1765ecc31b6eSAndy Yan 	for (i = 0; i < vop2->data->nr_layers; i++) {
1766ecc31b6eSAndy Yan 		if (vop2->data->win_data[i].phys_id == phys_id)
1767ecc31b6eSAndy Yan 			return &vop2->data->win_data[i];
1768ecc31b6eSAndy Yan 	}
1769ecc31b6eSAndy Yan 
1770ecc31b6eSAndy Yan 	return NULL;
1771ecc31b6eSAndy Yan }
1772ecc31b6eSAndy Yan 
1773b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id)
1774b6ba80b4SDamon Ding {
1775b6ba80b4SDamon Ding 	int i = 0;
1776b6ba80b4SDamon Ding 
1777b6ba80b4SDamon Ding 	for (i = 0; i < vop2->data->nr_pd; i++) {
1778b6ba80b4SDamon Ding 		if (vop2->data->pd[i].id == pd_id)
1779b6ba80b4SDamon Ding 			return &vop2->data->pd[i];
1780b6ba80b4SDamon Ding 	}
1781b6ba80b4SDamon Ding 
1782b6ba80b4SDamon Ding 	return NULL;
1783b6ba80b4SDamon Ding }
1784b6ba80b4SDamon Ding 
1785db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1786db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1787db328a0dSDamon Ding {
1788db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1789db328a0dSDamon Ding 	int i;
1790db328a0dSDamon Ding 
1791db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1792db328a0dSDamon Ding 			GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1793db328a0dSDamon Ding 			crtc_id, false);
1794db328a0dSDamon Ding 
1795db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1796db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1797db328a0dSDamon Ding 
1798db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1799db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1800db328a0dSDamon Ding }
1801db328a0dSDamon Ding 
1802db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1803db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1804db328a0dSDamon Ding {
1805db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1806db328a0dSDamon Ding 	int i;
1807db328a0dSDamon Ding 
1808db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1809db328a0dSDamon Ding 			GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1810db328a0dSDamon Ding 			crtc_id, false);
1811db328a0dSDamon Ding 
1812db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1813db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1814db328a0dSDamon Ding 
1815db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1816db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1817db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1818db328a0dSDamon Ding 			EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false);
1819db328a0dSDamon Ding }
1820db328a0dSDamon Ding 
18211147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1822d0408543SAndy Yan 					struct display_state *state)
1823d0408543SAndy Yan {
18241147facaSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
18251147facaSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
18261147facaSSandy Huang 	struct resource gamma_res;
18271147facaSSandy Huang 	fdt_size_t lut_size;
18281147facaSSandy Huang 	int i, lut_len, ret = 0;
18291147facaSSandy Huang 	u32 *lut_regs;
18301147facaSSandy Huang 	u32 *lut_val;
18311147facaSSandy Huang 	u32 r, g, b;
18321147facaSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
18331147facaSSandy Huang 	static int gamma_lut_en_num = 1;
18341147facaSSandy Huang 
18351147facaSSandy Huang 	if (gamma_lut_en_num > vop2->data->nr_gammas) {
18361147facaSSandy Huang 		printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
18371147facaSSandy Huang 		return 0;
18381147facaSSandy Huang 	}
18391147facaSSandy Huang 
18401147facaSSandy Huang 	if (!disp_info)
18411147facaSSandy Huang 		return 0;
18421147facaSSandy Huang 
18431147facaSSandy Huang 	if (!disp_info->gamma_lut_data.size)
18441147facaSSandy Huang 		return 0;
18451147facaSSandy Huang 
18461147facaSSandy Huang 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
18471147facaSSandy Huang 	if (ret)
18481147facaSSandy Huang 		printf("failed to get gamma lut res\n");
18491147facaSSandy Huang 	lut_regs = (u32 *)gamma_res.start;
18501147facaSSandy Huang 	lut_size = gamma_res.end - gamma_res.start + 1;
18511147facaSSandy Huang 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
18521147facaSSandy Huang 		printf("failed to get gamma lut register\n");
18531147facaSSandy Huang 		return 0;
18541147facaSSandy Huang 	}
18551147facaSSandy Huang 	lut_len = lut_size / 4;
18561147facaSSandy Huang 	if (lut_len != 256 && lut_len != 1024) {
18571147facaSSandy Huang 		printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
18581147facaSSandy Huang 		return 0;
18591147facaSSandy Huang 	}
18601147facaSSandy Huang 	lut_val = (u32 *)calloc(1, lut_size);
18611147facaSSandy Huang 	for (i = 0; i < lut_len; i++) {
18621147facaSSandy Huang 		r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
18631147facaSSandy Huang 		g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
18641147facaSSandy Huang 		b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
18651147facaSSandy Huang 
18661147facaSSandy Huang 		lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
18671147facaSSandy Huang 	}
18681147facaSSandy Huang 
1869db328a0dSDamon Ding 	if (vop2->version == VOP_VERSION_RK3568) {
1870db328a0dSDamon Ding 		rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len);
18711147facaSSandy Huang 		gamma_lut_en_num++;
1872db328a0dSDamon Ding 	} else if (vop2->version == VOP_VERSION_RK3588) {
1873db328a0dSDamon Ding 		rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len);
1874db328a0dSDamon Ding 		if (cstate->splice_mode) {
1875db328a0dSDamon Ding 			rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, lut_val, lut_len);
1876db328a0dSDamon Ding 			gamma_lut_en_num++;
1877db328a0dSDamon Ding 		}
1878db328a0dSDamon Ding 		gamma_lut_en_num++;
1879db328a0dSDamon Ding 	}
18801147facaSSandy Huang 
1881d0408543SAndy Yan 	return 0;
1882d0408543SAndy Yan }
1883d0408543SAndy Yan 
18846414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
18856414e3bcSSandy Huang 					struct display_state *state)
18866414e3bcSSandy Huang {
18876414e3bcSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
18886414e3bcSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
18896414e3bcSSandy Huang 	int i, cubic_lut_len;
18906414e3bcSSandy Huang 	u32 vp_offset = cstate->crtc_id * 0x100;
18916414e3bcSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
18926414e3bcSSandy Huang 	struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
18936414e3bcSSandy Huang 	u32 *cubic_lut_addr;
18946414e3bcSSandy Huang 
18956414e3bcSSandy Huang 	if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
18966414e3bcSSandy Huang 		return 0;
18976414e3bcSSandy Huang 
18986414e3bcSSandy Huang 	if (!disp_info->cubic_lut_data.size)
18996414e3bcSSandy Huang 		return 0;
19006414e3bcSSandy Huang 
19016414e3bcSSandy Huang 	cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
19026414e3bcSSandy Huang 	cubic_lut_len = disp_info->cubic_lut_data.size;
19036414e3bcSSandy Huang 
19046414e3bcSSandy Huang 	for (i = 0; i < cubic_lut_len / 2; i++) {
19056414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
19066414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
19076414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
19086414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
19096414e3bcSSandy Huang 					((lut->lred[2 * i + 1] & 0xfff) << 4) +
19106414e3bcSSandy Huang 					((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
19116414e3bcSSandy Huang 					((lut->lblue[2 * i + 1] & 0xf) << 28);
19126414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
19136414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
19146414e3bcSSandy Huang 	}
19156414e3bcSSandy Huang 
19166414e3bcSSandy Huang 	if (cubic_lut_len % 2) {
19176414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
19186414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
19196414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
19206414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
19216414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
19226414e3bcSSandy Huang 		*cubic_lut_addr = 0;
19236414e3bcSSandy Huang 	}
19246414e3bcSSandy Huang 
19256414e3bcSSandy Huang 	vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
19266414e3bcSSandy Huang 		    get_cubic_lut_buffer(cstate->crtc_id));
19276414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
19286414e3bcSSandy Huang 			EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
19296414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
19306414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
19316414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
19326414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
19336414e3bcSSandy Huang 
19346414e3bcSSandy Huang 	return 0;
19356414e3bcSSandy Huang }
19366414e3bcSSandy Huang 
1937ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2,
1938ee01dbb2SDamon Ding 				 struct bcsh_state *bcsh_state, int crtc_id)
1939ee01dbb2SDamon Ding {
1940ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
1941ee01dbb2SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1942ee01dbb2SDamon Ding 
1943ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
1944ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false);
1945ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
1946ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false);
1947ee01dbb2SDamon Ding 
1948ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
1949ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
1950ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
1951ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
1952ee01dbb2SDamon Ding 
1953ee01dbb2SDamon Ding 	if (!cstate->bcsh_en) {
1954ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1955ee01dbb2SDamon Ding 				BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
1956ee01dbb2SDamon Ding 		return;
1957ee01dbb2SDamon Ding 	}
1958ee01dbb2SDamon Ding 
1959ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1960ee01dbb2SDamon Ding 			BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
1961ee01dbb2SDamon Ding 			bcsh_state->brightness, false);
1962ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1963ee01dbb2SDamon Ding 			BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false);
1964ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1965ee01dbb2SDamon Ding 			BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
1966ee01dbb2SDamon Ding 			bcsh_state->saturation * bcsh_state->contrast / 0x100, false);
1967ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1968ee01dbb2SDamon Ding 			BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false);
1969ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1970ee01dbb2SDamon Ding 			BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false);
1971ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1972ee01dbb2SDamon Ding 			BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
1973ee01dbb2SDamon Ding 			BCSH_OUT_MODE_NORMAL_VIDEO, false);
1974ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1975ee01dbb2SDamon Ding 			BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
1976ee01dbb2SDamon Ding }
1977ee01dbb2SDamon Ding 
1978ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
1979ac500a1fSSandy Huang {
1980ac500a1fSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
1981ac500a1fSSandy Huang 	struct base_bcsh_info *bcsh_info;
1982ac500a1fSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
1983ee01dbb2SDamon Ding 	struct bcsh_state bcsh_state;
1984ac500a1fSSandy Huang 	int brightness, contrast, saturation, hue, sin_hue, cos_hue;
1985ac500a1fSSandy Huang 
1986ac500a1fSSandy Huang 	if (!conn_state->disp_info)
1987ac500a1fSSandy Huang 		return;
1988ac500a1fSSandy Huang 	bcsh_info = &conn_state->disp_info->bcsh_info;
1989ac500a1fSSandy Huang 	if (!bcsh_info)
1990ac500a1fSSandy Huang 		return;
1991ac500a1fSSandy Huang 
1992ac500a1fSSandy Huang 	if (bcsh_info->brightness != 50 ||
1993ac500a1fSSandy Huang 	    bcsh_info->contrast != 50 ||
1994ac500a1fSSandy Huang 	    bcsh_info->saturation != 50 || bcsh_info->hue != 50)
1995ee01dbb2SDamon Ding 		cstate->bcsh_en = true;
1996ac500a1fSSandy Huang 
1997ee01dbb2SDamon Ding 	if (cstate->bcsh_en) {
1998ac500a1fSSandy Huang 		if (!cstate->yuv_overlay)
1999ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2000ac500a1fSSandy Huang 		if (!is_yuv_output(conn_state->bus_format))
2001ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2002ac500a1fSSandy Huang 	} else {
2003ac500a1fSSandy Huang 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2004ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2005ac500a1fSSandy Huang 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2006ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2007ac500a1fSSandy Huang 	}
2008ac500a1fSSandy Huang 
2009df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2010df0a5c43SDamon Ding 						      conn_state->color_range,
2011df0a5c43SDamon Ding 						      CSC_10BIT_DEPTH);
2012ac500a1fSSandy Huang 
2013ac500a1fSSandy Huang 	if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
2014ac500a1fSSandy Huang 		brightness = interpolate(0, -128, 100, 127,
2015ac500a1fSSandy Huang 					 bcsh_info->brightness);
2016ac500a1fSSandy Huang 	else
2017ac500a1fSSandy Huang 		brightness = interpolate(0, -32, 100, 31,
2018ac500a1fSSandy Huang 					 bcsh_info->brightness);
2019ac500a1fSSandy Huang 	contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
2020ac500a1fSSandy Huang 	saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
2021ac500a1fSSandy Huang 	hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
2022ac500a1fSSandy Huang 
2023ac500a1fSSandy Huang 
2024ac500a1fSSandy Huang 	/*
2025ac500a1fSSandy Huang 	 *  a:[-30~0):
2026ac500a1fSSandy Huang 	 *    sin_hue = 0x100 - sin(a)*256;
2027ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2028ac500a1fSSandy Huang 	 *  a:[0~30]
2029ac500a1fSSandy Huang 	 *    sin_hue = sin(a)*256;
2030ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2031ac500a1fSSandy Huang 	 */
2032ac500a1fSSandy Huang 	sin_hue = fixp_sin32(hue) >> 23;
2033ac500a1fSSandy Huang 	cos_hue = fixp_cos32(hue) >> 23;
2034ac500a1fSSandy Huang 
2035ee01dbb2SDamon Ding 	bcsh_state.brightness = brightness;
2036ee01dbb2SDamon Ding 	bcsh_state.contrast = contrast;
2037ee01dbb2SDamon Ding 	bcsh_state.saturation = saturation;
2038ee01dbb2SDamon Ding 	bcsh_state.sin_hue = sin_hue;
2039ee01dbb2SDamon Ding 	bcsh_state.cos_hue = cos_hue;
2040ee01dbb2SDamon Ding 
2041ee01dbb2SDamon Ding 	vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id);
2042ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2043ee01dbb2SDamon Ding 		vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id);
2044ee01dbb2SDamon Ding }
2045ee01dbb2SDamon Ding 
2046ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id)
2047ee01dbb2SDamon Ding {
2048ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2049ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2050ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2051ee01dbb2SDamon Ding 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
2052ee01dbb2SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2053ee01dbb2SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2054ee01dbb2SDamon Ding 
2055ee01dbb2SDamon Ding 	bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly;
2056ee01dbb2SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly;
2057ee01dbb2SDamon Ding 	bg_dly -= bg_ovl_dly;
2058ee01dbb2SDamon Ding 
2059a552a69cSDamon Ding 	/*
2060a552a69cSDamon Ding 	 * splice mode: hdisplay must roundup as 4 pixel,
2061a552a69cSDamon Ding 	 * no splice mode: hdisplay must roundup as 2 pixel.
2062a552a69cSDamon Ding 	 */
2063ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2064a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1;
2065ee01dbb2SDamon Ding 	else
2066a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2067ee01dbb2SDamon Ding 
2068ee01dbb2SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
2069ee01dbb2SDamon Ding 		hsync_len = 8;
2070ee01dbb2SDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
2071ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4,
2072ee01dbb2SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2073ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2074ac500a1fSSandy Huang }
2075ac500a1fSSandy Huang 
2076452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id)
2077452afb13SDamon Ding {
2078452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2079452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2080452afb13SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2081452afb13SDamon Ding 	struct vop2_win_data *win_data;
2082452afb13SDamon Ding 	u32 bg_dly, pre_scan_dly;
2083452afb13SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2084452afb13SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2085452afb13SDamon Ding 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
2086452afb13SDamon Ding 	u8 win_id;
2087452afb13SDamon Ding 
2088452afb13SDamon Ding 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
2089452afb13SDamon Ding 	win_id = atoi(&win_data->name[strlen(win_data->name) - 1]);
2090452afb13SDamon Ding 	vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL + win_id * 4,
2091452afb13SDamon Ding 			ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 0, false);
2092452afb13SDamon Ding 
2093452afb13SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].win_dly +
2094452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].layer_mix_dly +
2095452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].hdr_mix_dly;
2096a552a69cSDamon Ding 	/* hdisplay must roundup as 2 pixel */
2097a552a69cSDamon Ding 	pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2098a552a69cSDamon Ding 	/**
2099a552a69cSDamon Ding 	 * pre_scan_hblank minimum value is 8, otherwise the win reset signal will
2100a552a69cSDamon Ding 	 * lead to first line data be zero.
2101a552a69cSDamon Ding 	 */
2102a552a69cSDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len);
2103452afb13SDamon Ding 	vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100,
2104452afb13SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2105452afb13SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2106452afb13SDamon Ding }
2107452afb13SDamon Ding 
2108d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
2109d0408543SAndy Yan {
2110d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
2111d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
211252ee18acSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
211352ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
2114d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
2115d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
2116d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
2117d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
2118d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
2119d0408543SAndy Yan 	u16 hsize =
2120d0408543SAndy Yan 	    hdisplay * (conn_state->overscan.left_margin +
2121d0408543SAndy Yan 			conn_state->overscan.right_margin) / 200;
2122d0408543SAndy Yan 	u16 vsize =
2123d0408543SAndy Yan 	    vdisplay * (conn_state->overscan.top_margin +
2124d0408543SAndy Yan 			conn_state->overscan.bottom_margin) / 200;
2125d0408543SAndy Yan 	u16 hact_end, vact_end;
2126d0408543SAndy Yan 	u32 val;
2127d0408543SAndy Yan 
212874bd8269SSandy Huang 	hsize = round_down(hsize, 2);
2129d0408543SAndy Yan 	vsize = round_down(vsize, 2);
2130d0408543SAndy Yan 
2131d0408543SAndy Yan 	hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
2132d0408543SAndy Yan 	hact_end = hact_st + hsize;
2133d0408543SAndy Yan 	val = hact_st << 16;
2134d0408543SAndy Yan 	val |= hact_end;
2135d0408543SAndy Yan 
213652ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
2137d0408543SAndy Yan 	vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
2138d0408543SAndy Yan 	vact_end = vact_st + vsize;
2139d0408543SAndy Yan 	val = vact_st << 16;
2140d0408543SAndy Yan 	val |= vact_end;
214152ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
2142d0408543SAndy Yan 	val = scl_cal_scale2(vdisplay, vsize) << 16;
2143d0408543SAndy Yan 	val |= scl_cal_scale2(hdisplay, hsize);
214452ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
2145d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
2146d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
214752ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
2148d0408543SAndy Yan 		    POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
2149d0408543SAndy Yan 		    POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
2150d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
2151d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
2152d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vsize;
2153d0408543SAndy Yan 
2154d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
215552ee18acSSandy Huang 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
2156d0408543SAndy Yan 	}
2157d0408543SAndy Yan 
2158452afb13SDamon Ding 	if (is_vop3(vop2)) {
2159452afb13SDamon Ding 		vop3_setup_pipe_dly(state, vop2, cstate->crtc_id);
2160452afb13SDamon Ding 	} else {
2161ee01dbb2SDamon Ding 		vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id);
2162ee01dbb2SDamon Ding 		if (cstate->splice_mode)
2163ee01dbb2SDamon Ding 			vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id);
2164d0408543SAndy Yan 	}
2165452afb13SDamon Ding }
2166d0408543SAndy Yan 
21676027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2)
21686027c871SZhang Yubing {
21696027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
21706027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
21716027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
21726027c871SZhang Yubing 	struct drm_display_mode *mode = &conn_state->mode;
21736027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
21746027c871SZhang Yubing 	s16 *lut_y;
21756027c871SZhang Yubing 	s16 *lut_h;
21766027c871SZhang Yubing 	s16 *lut_s;
21776027c871SZhang Yubing 	u32 value;
21786027c871SZhang Yubing 	int i;
21796027c871SZhang Yubing 
21806027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2181b8db91d0SZhang Yubing 		POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2182b8db91d0SZhang Yubing 	if (!acm->acm_enable) {
2183b8db91d0SZhang Yubing 		writel(0, vop2->regs + RK3528_ACM_CTRL);
21846027c871SZhang Yubing 		return;
21856027c871SZhang Yubing 	}
21866027c871SZhang Yubing 
21876027c871SZhang Yubing 	printf("post acm enable\n");
21886027c871SZhang Yubing 
21896027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_START);
21906027c871SZhang Yubing 
21916027c871SZhang Yubing 	value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) +
21926027c871SZhang Yubing 		((mode->vdisplay & 0xfff) << 20);
21936027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_CTRL);
21946027c871SZhang Yubing 
21956027c871SZhang Yubing 	value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
21966027c871SZhang Yubing 		((acm->s_gain << 20) & 0x3ff00000);
21976027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE);
21986027c871SZhang Yubing 
21996027c871SZhang Yubing 	lut_y = &acm->gain_lut_hy[0];
22006027c871SZhang Yubing 	lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
22016027c871SZhang Yubing 	lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
22026027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
22036027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
22046027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
22056027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
22066027c871SZhang Yubing 	}
22076027c871SZhang Yubing 
22086027c871SZhang Yubing 	lut_y = &acm->gain_lut_hs[0];
22096027c871SZhang Yubing 	lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
22106027c871SZhang Yubing 	lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
22116027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
22126027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
22136027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
22146027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
22156027c871SZhang Yubing 	}
22166027c871SZhang Yubing 
22176027c871SZhang Yubing 	lut_y = &acm->delta_lut_h[0];
22186027c871SZhang Yubing 	lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
22196027c871SZhang Yubing 	lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
22206027c871SZhang Yubing 	for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
22216027c871SZhang Yubing 		value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
22226027c871SZhang Yubing 			((lut_s[i] << 20) & 0x3ff00000);
22236027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
22246027c871SZhang Yubing 	}
22256027c871SZhang Yubing 
22266027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_DONE);
22276027c871SZhang Yubing }
22286027c871SZhang Yubing 
22296027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2)
22306027c871SZhang Yubing {
22316027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
22326027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
22336027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
22346027c871SZhang Yubing 	struct csc_info *csc = &conn_state->disp_info->csc_info;
22356027c871SZhang Yubing 	struct post_csc_coef csc_coef;
22366027c871SZhang Yubing 	bool is_input_yuv = false;
22376027c871SZhang Yubing 	bool is_output_yuv = false;
22386027c871SZhang Yubing 	bool post_r2y_en = false;
22396027c871SZhang Yubing 	bool post_csc_en = false;
22406027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
22416027c871SZhang Yubing 	u32 value;
22426027c871SZhang Yubing 	int range_type;
22436027c871SZhang Yubing 
22446027c871SZhang Yubing 	printf("post csc enable\n");
22456027c871SZhang Yubing 
22466027c871SZhang Yubing 	if (acm->acm_enable) {
22476027c871SZhang Yubing 		if (!cstate->yuv_overlay)
22486027c871SZhang Yubing 			post_r2y_en = true;
22496027c871SZhang Yubing 
22506027c871SZhang Yubing 		/* do y2r in csc module */
22516027c871SZhang Yubing 		if (!is_yuv_output(conn_state->bus_format))
22526027c871SZhang Yubing 			post_csc_en = true;
22536027c871SZhang Yubing 	} else {
22546027c871SZhang Yubing 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
22556027c871SZhang Yubing 			post_r2y_en = true;
22566027c871SZhang Yubing 
22576027c871SZhang Yubing 		/* do y2r in csc module */
22586027c871SZhang Yubing 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
22596027c871SZhang Yubing 			post_csc_en = true;
22606027c871SZhang Yubing 	}
22616027c871SZhang Yubing 
22626027c871SZhang Yubing 	if (csc->csc_enable)
22636027c871SZhang Yubing 		post_csc_en = true;
22646027c871SZhang Yubing 
22656027c871SZhang Yubing 	if (cstate->yuv_overlay || post_r2y_en)
22666027c871SZhang Yubing 		is_input_yuv = true;
22676027c871SZhang Yubing 
22686027c871SZhang Yubing 	if (is_yuv_output(conn_state->bus_format))
22696027c871SZhang Yubing 		is_output_yuv = true;
22706027c871SZhang Yubing 
2271df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2272df0a5c43SDamon Ding 						      conn_state->color_range,
2273df0a5c43SDamon Ding 						      CSC_13BIT_DEPTH);
22746027c871SZhang Yubing 
22756027c871SZhang Yubing 	if (post_csc_en) {
22766027c871SZhang Yubing 		rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv,
22776027c871SZhang Yubing 				       is_output_yuv);
22786027c871SZhang Yubing 
22796027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
22806027c871SZhang Yubing 				POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT,
22816027c871SZhang Yubing 				csc_coef.csc_coef00, false);
22825743c73eSZhang Yubing 		value = csc_coef.csc_coef01 & 0xffff;
22835743c73eSZhang Yubing 		value |= (csc_coef.csc_coef02 << 16) & 0xffff0000;
22846027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02);
22855743c73eSZhang Yubing 		value = csc_coef.csc_coef10 & 0xffff;
22865743c73eSZhang Yubing 		value |= (csc_coef.csc_coef11 << 16) & 0xffff0000;
22876027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11);
22885743c73eSZhang Yubing 		value = csc_coef.csc_coef12 & 0xffff;
22895743c73eSZhang Yubing 		value |= (csc_coef.csc_coef20 << 16) & 0xffff0000;
22906027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20);
22915743c73eSZhang Yubing 		value = csc_coef.csc_coef21 & 0xffff;
22925743c73eSZhang Yubing 		value |= (csc_coef.csc_coef22 << 16) & 0xffff0000;
22936027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22);
22946027c871SZhang Yubing 		writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0);
22956027c871SZhang Yubing 		writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1);
22966027c871SZhang Yubing 		writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2);
22976027c871SZhang Yubing 
22986027c871SZhang Yubing 		range_type = csc_coef.range_type ? 0 : 1;
22996027c871SZhang Yubing 		range_type <<= is_input_yuv ? 0 : 1;
23006027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23016027c871SZhang Yubing 				POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false);
23026027c871SZhang Yubing 	}
23036027c871SZhang Yubing 
23046027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23055743c73eSZhang Yubing 			POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false);
23066027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23076027c871SZhang Yubing 			POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false);
23086027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23096027c871SZhang Yubing 			POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false);
23106027c871SZhang Yubing }
23116027c871SZhang Yubing 
23126027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2)
23136027c871SZhang Yubing {
23146027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
23156027c871SZhang Yubing 	struct base2_disp_info *disp_info = conn_state->disp_info;
23166027c871SZhang Yubing 	const char *enable_flag;
23176027c871SZhang Yubing 	if (!disp_info) {
23186027c871SZhang Yubing 		printf("disp_info is empty\n");
23196027c871SZhang Yubing 		return;
23206027c871SZhang Yubing 	}
23216027c871SZhang Yubing 
23226027c871SZhang Yubing 	enable_flag = (const char *)&disp_info->cacm_header;
23236027c871SZhang Yubing 	if (strncasecmp(enable_flag, "CACM", 4)) {
23246027c871SZhang Yubing 		printf("acm and csc is not support\n");
23256027c871SZhang Yubing 		return;
23266027c871SZhang Yubing 	}
23276027c871SZhang Yubing 
23286027c871SZhang Yubing 	vop3_post_acm_config(state, vop2);
23296027c871SZhang Yubing 	vop3_post_csc_config(state, vop2);
23306027c871SZhang Yubing }
23316027c871SZhang Yubing 
2332a552a69cSDamon Ding static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2,
2333a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
2334a552a69cSDamon Ding {
2335a552a69cSDamon Ding 	int val = 0;
2336a552a69cSDamon Ding 	bool is_bisr_en, is_otp_bisr_en;
2337a552a69cSDamon Ding 
2338a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER) {
2339a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2340a552a69cSDamon Ding 					    EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2341a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2342a552a69cSDamon Ding 						EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2343a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2344a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2345a552a69cSDamon Ding 						  val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1),
2346a552a69cSDamon Ding 						  50 * 1000);
2347a552a69cSDamon Ding 		else
2348a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2349a552a69cSDamon Ding 						  val, ((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1),
2350a552a69cSDamon Ding 						  50 * 1000);
2351a552a69cSDamon Ding 	} else {
2352a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2353a552a69cSDamon Ding 					    EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2354a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2355a552a69cSDamon Ding 						EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2356a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2357a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2358a552a69cSDamon Ding 						  val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1),
2359a552a69cSDamon Ding 						  50 * 1000);
2360a552a69cSDamon Ding 		else
2361a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2362a552a69cSDamon Ding 						  val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1),
2363a552a69cSDamon Ding 						  50 * 1000);
2364a552a69cSDamon Ding 	}
2365a552a69cSDamon Ding }
2366a552a69cSDamon Ding 
2367a552a69cSDamon Ding static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2368a552a69cSDamon Ding {
2369a552a69cSDamon Ding 	int ret = 0;
2370a552a69cSDamon Ding 
2371a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER)
2372a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK,
2373a552a69cSDamon Ding 				RK3576_CLUSTER_PD_EN_SHIFT, 0, true);
2374a552a69cSDamon Ding 	else
2375a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK,
2376a552a69cSDamon Ding 				RK3576_ESMART_PD_EN_SHIFT, 0, true);
2377a552a69cSDamon Ding 	ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data);
2378a552a69cSDamon Ding 	if (ret) {
2379a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2380a552a69cSDamon Ding 		return ret;
2381a552a69cSDamon Ding 	}
2382a552a69cSDamon Ding 
2383a552a69cSDamon Ding 	return 0;
2384a552a69cSDamon Ding }
2385a552a69cSDamon Ding 
2386a552a69cSDamon Ding static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2,
2387a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
238860e469f5SDamon Ding {
238960e469f5SDamon Ding 	int val = 0;
239060e469f5SDamon Ding 	int shift = 0;
2391b6ba80b4SDamon Ding 	int shift_factor = 0;
239260e469f5SDamon Ding 	bool is_bisr_en = false;
239360e469f5SDamon Ding 
2394b6ba80b4SDamon Ding 	/*
2395b6ba80b4SDamon Ding 	 * The order of pd status bits in BISR_STS register
2396b6ba80b4SDamon Ding 	 * is different from that in VOP SYS_STS register.
2397b6ba80b4SDamon Ding 	 */
2398b6ba80b4SDamon Ding 	if (pd_data->id == VOP2_PD_DSC_8K ||
2399b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_DSC_4K ||
2400b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_ESMART)
2401b6ba80b4SDamon Ding 		shift_factor = 1;
2402b6ba80b4SDamon Ding 
2403b6ba80b4SDamon Ding 	shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor;
2404b6ba80b4SDamon Ding 	is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift);
240560e469f5SDamon Ding 	if (is_bisr_en) {
2406b6ba80b4SDamon Ding 		shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor;
2407b6ba80b4SDamon Ding 
240860e469f5SDamon Ding 		return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
2409d2e91fdcSDamon Ding 					  ((val >> shift) & 0x1), 50 * 1000);
241060e469f5SDamon Ding 	} else {
2411b6ba80b4SDamon Ding 		shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1;
2412b6ba80b4SDamon Ding 
241360e469f5SDamon Ding 		return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
241460e469f5SDamon Ding 					  !((val >> shift) & 0x1), 50 * 1000);
241560e469f5SDamon Ding 	}
241660e469f5SDamon Ding }
241760e469f5SDamon Ding 
2418a552a69cSDamon Ding static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2419a552a69cSDamon Ding {
2420a552a69cSDamon Ding 	int ret = 0;
2421a552a69cSDamon Ding 
2422a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK,
2423a552a69cSDamon Ding 			RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false);
2424a552a69cSDamon Ding 	ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data);
2425a552a69cSDamon Ding 	if (ret) {
2426a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2427a552a69cSDamon Ding 		return ret;
2428a552a69cSDamon Ding 	}
2429a552a69cSDamon Ding 
2430a552a69cSDamon Ding 	return 0;
2431a552a69cSDamon Ding }
2432a552a69cSDamon Ding 
2433b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id)
243460e469f5SDamon Ding {
243560e469f5SDamon Ding 	struct vop2_power_domain_data *pd_data;
243660e469f5SDamon Ding 	int ret = 0;
243760e469f5SDamon Ding 
2438b6ba80b4SDamon Ding 	if (!pd_id)
2439b6ba80b4SDamon Ding 		return 0;
2440b6ba80b4SDamon Ding 
2441b6ba80b4SDamon Ding 	pd_data = vop2_find_pd_data_by_id(vop2, pd_id);
2442b6ba80b4SDamon Ding 	if (!pd_data) {
2443b6ba80b4SDamon Ding 		printf("can't find pd_data by id\n");
244460e469f5SDamon Ding 		return -EINVAL;
244560e469f5SDamon Ding 	}
24462c66af11SDamon Ding 
2447b6ba80b4SDamon Ding 	if (pd_data->parent_id) {
2448b6ba80b4SDamon Ding 		ret = vop2_power_domain_on(vop2, pd_data->parent_id);
244960e469f5SDamon Ding 		if (ret) {
245060e469f5SDamon Ding 			printf("can't open parent power domain\n");
245160e469f5SDamon Ding 			return -EINVAL;
245260e469f5SDamon Ding 		}
245360e469f5SDamon Ding 	}
245460e469f5SDamon Ding 
2455a552a69cSDamon Ding 	/*
2456a552a69cSDamon Ding 	 * Read VOP internal power domain on/off status.
2457a552a69cSDamon Ding 	 * We should query BISR_STS register in PMU for
2458a552a69cSDamon Ding 	 * power up/down status when memory repair is enabled.
2459a552a69cSDamon Ding 	 * Return value: 1 for power on, 0 for power off;
2460a552a69cSDamon Ding 	 */
2461a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
2462a552a69cSDamon Ding 		ret = rk3576_vop2_power_domain_on(vop2, pd_data);
2463a552a69cSDamon Ding 	else
2464a552a69cSDamon Ding 		ret = rk3588_vop2_power_domain_on(vop2, pd_data);
246560e469f5SDamon Ding 
2466a552a69cSDamon Ding 	return ret;
246760e469f5SDamon Ding }
246860e469f5SDamon Ding 
2469ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2)
2470ecc31b6eSAndy Yan {
2471ecc31b6eSAndy Yan 	u32 *base = vop2->regs;
2472ecc31b6eSAndy Yan 	int i = 0;
2473ecc31b6eSAndy Yan 
2474ecc31b6eSAndy Yan 	/*
2475ecc31b6eSAndy Yan 	 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
2476ecc31b6eSAndy Yan 	 */
2477ecc31b6eSAndy Yan 	for (i = 0; i < (vop2->reg_len >> 2); i++)
2478ecc31b6eSAndy Yan 		vop2->regsbak[i] = base[i];
2479ecc31b6eSAndy Yan }
2480ecc31b6eSAndy Yan 
24815fa6e665SDamon Ding static void vop3_overlay_init(struct vop2 *vop2, struct display_state *state)
24825fa6e665SDamon Ding {
24835fa6e665SDamon Ding 	struct vop2_win_data *win_data;
24845fa6e665SDamon Ding 	int layer_phy_id = 0;
24855fa6e665SDamon Ding 	int i, j;
24865fa6e665SDamon Ding 	u32 ovl_port_offset = 0;
24875fa6e665SDamon Ding 	u32 layer_nr = 0;
24885fa6e665SDamon Ding 	u8 shift = 0;
24895fa6e665SDamon Ding 
24905fa6e665SDamon Ding 	/* layer sel win id */
24915fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
24925fa6e665SDamon Ding 		shift = 0;
24935fa6e665SDamon Ding 		ovl_port_offset = 0x100 * i;
24945fa6e665SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
24955fa6e665SDamon Ding 		for (j = 0; j < layer_nr; j++) {
24965fa6e665SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
24975fa6e665SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
24985fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + ovl_port_offset, LAYER_SEL_MASK,
24995fa6e665SDamon Ding 					shift, win_data->layer_sel_win_id[i], false);
25005fa6e665SDamon Ding 			shift += 4;
25015fa6e665SDamon Ding 		}
25025fa6e665SDamon Ding 	}
25035fa6e665SDamon Ding 
2504a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3576) {
25055fa6e665SDamon Ding 		/* win sel port */
25065fa6e665SDamon Ding 		for (i = 0; i < vop2->data->nr_vps; i++) {
25075fa6e665SDamon Ding 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
25085fa6e665SDamon Ding 			for (j = 0; j < layer_nr; j++) {
25095fa6e665SDamon Ding 				if (!vop2->vp_plane_mask[i].attached_layers[j])
25105fa6e665SDamon Ding 					continue;
25115fa6e665SDamon Ding 				layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
25125fa6e665SDamon Ding 				win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
25135fa6e665SDamon Ding 				shift = win_data->win_sel_port_offset * 2;
2514a552a69cSDamon Ding 				vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL,
2515a552a69cSDamon Ding 						LAYER_SEL_PORT_MASK, shift, i, false);
2516a552a69cSDamon Ding 			}
25175fa6e665SDamon Ding 		}
25185fa6e665SDamon Ding 	}
25195fa6e665SDamon Ding }
25205fa6e665SDamon Ding 
25215fa6e665SDamon Ding static void vop2_overlay_init(struct vop2 *vop2, struct display_state *state)
25225fa6e665SDamon Ding {
25235fa6e665SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
25245fa6e665SDamon Ding 	struct vop2_win_data *win_data;
25255fa6e665SDamon Ding 	int layer_phy_id = 0;
25265fa6e665SDamon Ding 	int total_used_layer = 0;
25275fa6e665SDamon Ding 	int port_mux = 0;
25285fa6e665SDamon Ding 	int i, j;
25295fa6e665SDamon Ding 	u32 layer_nr = 0;
25305fa6e665SDamon Ding 	u8 shift = 0;
25315fa6e665SDamon Ding 
25325fa6e665SDamon Ding 	/* layer sel win id */
25335fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
25345fa6e665SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
25355fa6e665SDamon Ding 		for (j = 0; j < layer_nr; j++) {
25365fa6e665SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
25375fa6e665SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
25385fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
25395fa6e665SDamon Ding 					shift, win_data->layer_sel_win_id[i], false);
25405fa6e665SDamon Ding 			shift += 4;
25415fa6e665SDamon Ding 		}
25425fa6e665SDamon Ding 	}
25435fa6e665SDamon Ding 
25445fa6e665SDamon Ding 	/* win sel port */
25455fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
25465fa6e665SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
25475fa6e665SDamon Ding 		for (j = 0; j < layer_nr; j++) {
25485fa6e665SDamon Ding 			if (!vop2->vp_plane_mask[i].attached_layers[j])
25495fa6e665SDamon Ding 				continue;
25505fa6e665SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
25515fa6e665SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
25525fa6e665SDamon Ding 			shift = win_data->win_sel_port_offset * 2;
25535fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
25545fa6e665SDamon Ding 					LAYER_SEL_PORT_SHIFT + shift, i, false);
25555fa6e665SDamon Ding 		}
25565fa6e665SDamon Ding 	}
25575fa6e665SDamon Ding 
25585fa6e665SDamon Ding 	/**
25595fa6e665SDamon Ding 	 * port mux config
25605fa6e665SDamon Ding 	 */
25615fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
25625fa6e665SDamon Ding 		shift = i * 4;
25635fa6e665SDamon Ding 		if (vop2->vp_plane_mask[i].attached_layers_nr) {
25645fa6e665SDamon Ding 			total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
25655fa6e665SDamon Ding 			port_mux = total_used_layer - 1;
25665fa6e665SDamon Ding 		} else {
25675fa6e665SDamon Ding 			port_mux = 8;
25685fa6e665SDamon Ding 		}
25695fa6e665SDamon Ding 
25705fa6e665SDamon Ding 		if (i == vop2->data->nr_vps - 1)
25715fa6e665SDamon Ding 			port_mux = vop2->data->nr_mixers;
25725fa6e665SDamon Ding 
25735fa6e665SDamon Ding 		cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
25745fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
25755fa6e665SDamon Ding 				PORT_MUX_SHIFT + shift, port_mux, false);
25765fa6e665SDamon Ding 	}
25775fa6e665SDamon Ding }
25785fa6e665SDamon Ding 
25795fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win)
25805fa6e665SDamon Ding {
25815fa6e665SDamon Ding 	if (!is_vop3(vop2))
25825fa6e665SDamon Ding 		return false;
25835fa6e665SDamon Ding 
25845fa6e665SDamon Ding 	if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
25855fa6e665SDamon Ding 	    win->phys_id != ROCKCHIP_VOP2_ESMART0)
25865fa6e665SDamon Ding 		return true;
25875fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
25885fa6e665SDamon Ding 		 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
25895fa6e665SDamon Ding 		return true;
25905fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
25915fa6e665SDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART1)
25925fa6e665SDamon Ding 		return true;
2593a552a69cSDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE &&
2594a552a69cSDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART3)
2595a552a69cSDamon Ding 		return true;
25965fa6e665SDamon Ding 	else
25975fa6e665SDamon Ding 		return false;
25985fa6e665SDamon Ding }
25995fa6e665SDamon Ding 
26005fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
26015fa6e665SDamon Ding {
26025fa6e665SDamon Ding 	struct vop2_win_data *win_data;
2603fa4ecc32SDamon Ding 	int i;
26045fa6e665SDamon Ding 	u8 scale_engine_num = 0;
26055fa6e665SDamon Ding 
26065fa6e665SDamon Ding 	/* store plane mask for vop2_fixup_dts */
2607fa4ecc32SDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
2608fa4ecc32SDamon Ding 		win_data = &vop2->data->win_data[i];
26095fa6e665SDamon Ding 		if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data))
26105fa6e665SDamon Ding 			continue;
26115fa6e665SDamon Ding 
26125fa6e665SDamon Ding 		win_data->scale_engine_num = scale_engine_num++;
26135fa6e665SDamon Ding 	}
26145fa6e665SDamon Ding }
26155fa6e665SDamon Ding 
2616a552a69cSDamon Ding static int vop3_get_esmart_lb_mode(struct vop2 *vop2)
2617a552a69cSDamon Ding {
2618a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map;
2619a552a69cSDamon Ding 	int i;
2620a552a69cSDamon Ding 
2621a552a69cSDamon Ding 	if (!esmart_lb_mode_map)
2622a552a69cSDamon Ding 		return vop2->esmart_lb_mode;
2623a552a69cSDamon Ding 
2624a552a69cSDamon Ding 	for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) {
2625a552a69cSDamon Ding 		if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode)
2626a552a69cSDamon Ding 			return esmart_lb_mode_map->lb_map_value;
2627a552a69cSDamon Ding 		esmart_lb_mode_map++;
2628a552a69cSDamon Ding 	}
2629a552a69cSDamon Ding 
2630a552a69cSDamon Ding 	if (i == vop2->data->esmart_lb_mode_num)
2631a552a69cSDamon Ding 		printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode);
2632a552a69cSDamon Ding 
2633a552a69cSDamon Ding 	return vop2->data->esmart_lb_mode_map[0].lb_map_value;
2634a552a69cSDamon Ding }
2635a552a69cSDamon Ding 
2636b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
2637d0408543SAndy Yan {
2638b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
2639b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
2640a552a69cSDamon Ding 	int active_vp_num = 0;
26415fa6e665SDamon Ding 	int layer_phy_id = 0;
26425fa6e665SDamon Ding 	int i, j;
2643fa4ecc32SDamon Ding 	int ret;
26445fa6e665SDamon Ding 	u32 layer_nr = 0;
2645d0408543SAndy Yan 
264663cb669fSSandy Huang 	if (vop2->global_init)
2647d0408543SAndy Yan 		return;
264863cb669fSSandy Huang 
2649b0989546SSandy Huang 	/* OTP must enable at the first time, otherwise mirror layer register is error */
265063cb669fSSandy Huang 	if (soc_is_rk3566())
265163cb669fSSandy Huang 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
265263cb669fSSandy Huang 				OTP_WIN_EN_SHIFT, 1, false);
2653b0989546SSandy Huang 
2654b0989546SSandy Huang 	if (cstate->crtc->assign_plane) {/* dts assign plane */
2655b0989546SSandy Huang 		u32 plane_mask;
2656b0989546SSandy Huang 		int primary_plane_id;
2657b0989546SSandy Huang 
2658b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
2659b0989546SSandy Huang 			plane_mask = cstate->crtc->vps[i].plane_mask;
2660b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2661b0989546SSandy Huang 			layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */
2662b0989546SSandy Huang 			vop2->vp_plane_mask[i].attached_layers_nr = layer_nr;
26635fc2b656SDamon Ding 			primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
2664337d1c13SDamon Ding 			if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX)
2665b0989546SSandy Huang 				primary_plane_id = vop2_get_primary_plane(vop2, plane_mask);
2666b0989546SSandy Huang 			vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id;
2667b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2668b0989546SSandy Huang 
2669b0989546SSandy Huang 			/* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/
2670b0989546SSandy Huang 			for (j = 0; j < layer_nr; j++) {
2671b0989546SSandy Huang 				vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
2672b0989546SSandy Huang 				plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
267363cb669fSSandy Huang 			}
2674b0989546SSandy Huang 		}
2675b0989546SSandy Huang 	} else {/* need soft assign plane mask */
2676a552a69cSDamon Ding 		printf("Assign plane mask automatically\n");
2677a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
2678a552a69cSDamon Ding 			for (i = 0; i < vop2->data->nr_vps; i++) {
2679a552a69cSDamon Ding 				if (cstate->crtc->vps[i].enable) {
2680a552a69cSDamon Ding 					vop2->vp_plane_mask[i].attached_layers_nr = 1;
2681a552a69cSDamon Ding 					vop2->vp_plane_mask[i].primary_plane_id =
2682a552a69cSDamon Ding 						vop2->data->vp_default_primary_plane[i];
2683a552a69cSDamon Ding 					vop2->vp_plane_mask[i].attached_layers[0] =
2684a552a69cSDamon Ding 						vop2->data->vp_default_primary_plane[i];
2685a552a69cSDamon Ding 					vop2->vp_plane_mask[i].plane_mask |=
2686a552a69cSDamon Ding 						BIT(vop2->data->vp_default_primary_plane[i]);
2687a552a69cSDamon Ding 					active_vp_num++;
2688a552a69cSDamon Ding 				}
2689a552a69cSDamon Ding 			}
2690a552a69cSDamon Ding 			printf("VOP have %d active VP\n", active_vp_num);
2691a552a69cSDamon Ding 		} else {
2692b0989546SSandy Huang 			/* find the first unplug devices and set it as main display */
2693b0989546SSandy Huang 			int main_vp_index = -1;
2694b0989546SSandy Huang 
2695b0989546SSandy Huang 			for (i = 0; i < vop2->data->nr_vps; i++) {
2696b0989546SSandy Huang 				if (cstate->crtc->vps[i].enable)
2697b0989546SSandy Huang 					active_vp_num++;
2698b0989546SSandy Huang 			}
2699b0989546SSandy Huang 			printf("VOP have %d active VP\n", active_vp_num);
2700b0989546SSandy Huang 
2701b0989546SSandy Huang 			if (soc_is_rk3566() && active_vp_num > 2)
2702b0989546SSandy Huang 				printf("ERROR: rk3566 only support 2 display output!!\n");
2703b0989546SSandy Huang 			plane_mask = vop2->data->plane_mask;
2704b0989546SSandy Huang 			plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
27055fa6e665SDamon Ding 			/*
2706a552a69cSDamon Ding 			 * For rk3528, one display policy for hdmi store in plane_mask[0], and
2707a552a69cSDamon Ding 			 * the other for cvbs store in plane_mask[2].
27085fa6e665SDamon Ding 			 */
27095fa6e665SDamon Ding 			if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 &&
27105fa6e665SDamon Ding 			    cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV)
27115fa6e665SDamon Ding 				plane_mask += 2 * VOP2_VP_MAX;
2712b0989546SSandy Huang 
27135fa6e665SDamon Ding 			if (vop2->version == VOP_VERSION_RK3528) {
27145fa6e665SDamon Ding 				/*
2715a552a69cSDamon Ding 				 * For rk3528, the plane mask of vp is limited, only esmart2 can
2716a552a69cSDamon Ding 				 * be selected by both vp0 and vp1.
27175fa6e665SDamon Ding 				 */
27185fa6e665SDamon Ding 				j = 0;
27195fa6e665SDamon Ding 			} else {
2720b0989546SSandy Huang 				for (i = 0; i < vop2->data->nr_vps; i++) {
2721b0989546SSandy Huang 					if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
2722a552a69cSDamon Ding 						/* the first store main display plane mask */
2723a552a69cSDamon Ding 						vop2->vp_plane_mask[i] = plane_mask[0];
2724b0989546SSandy Huang 						main_vp_index = i;
2725e007876dSSandy Huang 						break;
2726b0989546SSandy Huang 					}
2727b0989546SSandy Huang 				}
2728b0989546SSandy Huang 
2729b0989546SSandy Huang 				/* if no find unplug devices, use vp0 as main display */
2730b0989546SSandy Huang 				if (main_vp_index < 0) {
2731b0989546SSandy Huang 					main_vp_index = 0;
2732b0989546SSandy Huang 					vop2->vp_plane_mask[0] = plane_mask[0];
2733b0989546SSandy Huang 				}
2734b0989546SSandy Huang 
2735a552a69cSDamon Ding 				/* plane_mask[0] store main display, so we from plane_mask[1] */
2736a552a69cSDamon Ding 				j = 1;
27375fa6e665SDamon Ding 			}
2738b0989546SSandy Huang 
2739b0989546SSandy Huang 			/* init other display except main display */
2740b0989546SSandy Huang 			for (i = 0; i < vop2->data->nr_vps; i++) {
2741a552a69cSDamon Ding 				/* main display or no connect devices */
2742a552a69cSDamon Ding 				if (i == main_vp_index || !cstate->crtc->vps[i].enable)
2743b0989546SSandy Huang 					continue;
2744b0989546SSandy Huang 				vop2->vp_plane_mask[i] = plane_mask[j++];
2745b0989546SSandy Huang 			}
2746a552a69cSDamon Ding 		}
2747b0989546SSandy Huang 		/* store plane mask for vop2_fixup_dts */
2748b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
2749b0989546SSandy Huang 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2750b0989546SSandy Huang 			for (j = 0; j < layer_nr; j++) {
2751b0989546SSandy Huang 				layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2752b0989546SSandy Huang 				vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
2753b0989546SSandy Huang 			}
2754b0989546SSandy Huang 		}
2755b0989546SSandy Huang 	}
2756b0989546SSandy Huang 
275760e469f5SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588)
275860e469f5SDamon Ding 		rk3588_vop2_regsbak(vop2);
275960e469f5SDamon Ding 	else
276060e469f5SDamon Ding 		memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
276160e469f5SDamon Ding 
276260e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
276360e469f5SDamon Ding 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
276460e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
276560e469f5SDamon Ding 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
276660e469f5SDamon Ding 
2767b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
2768b0989546SSandy Huang 		printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
2769b0989546SSandy Huang 		for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
2770b0989546SSandy Huang 			printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]);
2771b0989546SSandy Huang 		printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id);
2772b0989546SSandy Huang 	}
2773b0989546SSandy Huang 
27745fa6e665SDamon Ding 	if (is_vop3(vop2))
27755fa6e665SDamon Ding 		vop3_overlay_init(vop2, state);
27765fa6e665SDamon Ding 	else
27775fa6e665SDamon Ding 		vop2_overlay_init(vop2, state);
2778b0989546SSandy Huang 
27795fa6e665SDamon Ding 	if (is_vop3(vop2)) {
27805fa6e665SDamon Ding 		/*
27815fa6e665SDamon Ding 		 * you can rewrite at dts vop node:
27825fa6e665SDamon Ding 		 *
27835fa6e665SDamon Ding 		 * VOP3_ESMART_8K_MODE = 0,
27845fa6e665SDamon Ding 		 * VOP3_ESMART_4K_4K_MODE = 1,
27855fa6e665SDamon Ding 		 * VOP3_ESMART_4K_2K_2K_MODE = 2,
27865fa6e665SDamon Ding 		 * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
27875fa6e665SDamon Ding 		 *
27885fa6e665SDamon Ding 		 * &vop {
27895fa6e665SDamon Ding 		 * 	esmart_lb_mode = /bits/ 8 <2>;
27905fa6e665SDamon Ding 		 * };
279163cb669fSSandy Huang 		 */
2792fa4ecc32SDamon Ding 		ret = ofnode_read_u32(cstate->node, "esmart_lb_mode", &vop2->esmart_lb_mode);
2793fa4ecc32SDamon Ding 		if (ret < 0)
27945fa6e665SDamon Ding 			vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
2795a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
2796a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL,
2797a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_MASK,
2798a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_SHIFT,
2799a552a69cSDamon Ding 					vop3_get_esmart_lb_mode(vop2), true);
2800a552a69cSDamon Ding 		else
2801a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
2802a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_MASK,
2803a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_SHIFT,
2804a552a69cSDamon Ding 					vop3_get_esmart_lb_mode(vop2), true);
2805d0408543SAndy Yan 
28065fa6e665SDamon Ding 		vop3_init_esmart_scale_engine(vop2);
2807aa670293SDamon Ding 
2808aa670293SDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK,
2809aa670293SDamon Ding 				DSP_VS_T_SEL_SHIFT, 0, false);
281063cb669fSSandy Huang 	}
281163cb669fSSandy Huang 
2812ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3568)
281363cb669fSSandy Huang 		vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
281463cb669fSSandy Huang 
2815a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576) {
2816a552a69cSDamon Ding 		vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq");
2817a552a69cSDamon Ding 
2818f67105fbSSandy Huang 		/* Default use rkiommu 1.0 for axi0 */
2819f67105fbSSandy Huang 		vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 0, true);
2820a552a69cSDamon Ding 
2821a552a69cSDamon Ding 		/* Init frc2.0 config */
2822a552a69cSDamon Ding 		vop2_writel(vop2, 0xca0, 0xc8);
2823a552a69cSDamon Ding 		vop2_writel(vop2, 0xca4, 0x01000100);
2824a552a69cSDamon Ding 		vop2_writel(vop2, 0xca8, 0x03ff0100);
2825a552a69cSDamon Ding 		vop2_writel(vop2, 0xda0, 0xc8);
2826a552a69cSDamon Ding 		vop2_writel(vop2, 0xda4, 0x01000100);
2827a552a69cSDamon Ding 		vop2_writel(vop2, 0xda8, 0x03ff0100);
2828a552a69cSDamon Ding 
2829a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true)
2830a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
2831a552a69cSDamon Ding 					VP_INTR_MERGE_EN_SHIFT, 1, true);
2832a552a69cSDamon Ding 
2833a552a69cSDamon Ding 		/* Set reg done every field for interlace */
2834a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK,
2835a552a69cSDamon Ding 				INTERLACE_FRM_REG_DONE_SHIFT, 0, false);
2836a552a69cSDamon Ding 	}
2837a552a69cSDamon Ding 
283863cb669fSSandy Huang 	vop2->global_init = true;
2839d0408543SAndy Yan }
2840d0408543SAndy Yan 
2841344e932aSDamon Ding static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state)
2842344e932aSDamon Ding {
2843344e932aSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2844344e932aSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
2845344e932aSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
2846344e932aSDamon Ding 	struct resource sharp_regs;
2847344e932aSDamon Ding 	u32 *sharp_reg_base;
2848344e932aSDamon Ding 	int ret;
2849344e932aSDamon Ding 
2850344e932aSDamon Ding 	if (!(vp_data->feature & VOP_FEATURE_POST_SHARP))
2851344e932aSDamon Ding 		return;
2852344e932aSDamon Ding 
2853344e932aSDamon Ding 	ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs);
2854344e932aSDamon Ding 	if (ret) {
2855344e932aSDamon Ding 		printf("failed to get sharp regs\n");
2856344e932aSDamon Ding 		return;
2857344e932aSDamon Ding 	}
2858344e932aSDamon Ding 	sharp_reg_base = (u32 *)sharp_regs.start;
2859344e932aSDamon Ding 
2860344e932aSDamon Ding 	/*
2861344e932aSDamon Ding 	 * After vop initialization, keep sw_sharp_enable always on.
2862344e932aSDamon Ding 	 * Only enable/disable sharp submodule to avoid black screen.
2863344e932aSDamon Ding 	 */
2864344e932aSDamon Ding 	writel(0x1, sharp_reg_base);
2865344e932aSDamon Ding }
2866344e932aSDamon Ding 
2867d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state)
2868d0408543SAndy Yan {
28691147facaSSandy Huang 	rockchip_vop2_gamma_lut_init(vop2, state);
28706414e3bcSSandy Huang 	rockchip_vop2_cubic_lut_init(vop2, state);
2871344e932aSDamon Ding 	rockchip_vop2_sharp_init(vop2, state);
2872d0408543SAndy Yan 
2873d0408543SAndy Yan 	return 0;
2874d0408543SAndy Yan }
2875d0408543SAndy Yan 
2876d0408543SAndy Yan /*
2877d0408543SAndy Yan  * VOP2 have multi video ports.
2878d0408543SAndy Yan  * video port ------- crtc
2879d0408543SAndy Yan  */
2880d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state)
2881d0408543SAndy Yan {
2882d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
2883d0408543SAndy Yan 	const struct vop2_data *vop2_data = cstate->crtc->data;
2884734a0ce6SDamon Ding 	struct regmap *map;
2885d0408543SAndy Yan 
2886d0408543SAndy Yan 	if (!rockchip_vop2) {
28870d2d6a97SSandy Huang 		rockchip_vop2 = calloc(1, sizeof(struct vop2));
2888d0408543SAndy Yan 		if (!rockchip_vop2)
2889d0408543SAndy Yan 			return -ENOMEM;
2890d8e7f4a5SSandy Huang 		memset(rockchip_vop2, 0, sizeof(struct vop2));
2891d0408543SAndy Yan 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
2892d0408543SAndy Yan 		rockchip_vop2->reg_len = RK3568_MAX_REG;
2893d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD
2894d8e7f4a5SSandy Huang 		rockchip_vop2->regs = (void *)RK3528_VOP_BASE;
2895d8e7f4a5SSandy Huang #else
2896d8e7f4a5SSandy Huang 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
2897734a0ce6SDamon Ding 		map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf");
2898734a0ce6SDamon Ding 		rockchip_vop2->grf = regmap_get_range(map, 0);
2899d0408543SAndy Yan 		if (rockchip_vop2->grf <= 0)
290063cb669fSSandy Huang 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
2901d8e7f4a5SSandy Huang #endif
2902d0408543SAndy Yan 		rockchip_vop2->version = vop2_data->version;
2903d0408543SAndy Yan 		rockchip_vop2->data = vop2_data;
2904ecc31b6eSAndy Yan 		if (rockchip_vop2->version == VOP_VERSION_RK3588) {
2905734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf");
2906734a0ce6SDamon Ding 			rockchip_vop2->vop_grf = regmap_get_range(map, 0);
2907ecc31b6eSAndy Yan 			if (rockchip_vop2->vop_grf <= 0)
2908a552a69cSDamon Ding 				printf("%s: Get syscon vop_grf failed (ret=%p)\n",
2909a552a69cSDamon Ding 				       __func__, rockchip_vop2->vop_grf);
2910b890760eSAlgea Cao 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf");
2911b890760eSAlgea Cao 			rockchip_vop2->vo1_grf = regmap_get_range(map, 0);
2912ecc31b6eSAndy Yan 			if (rockchip_vop2->vo1_grf <= 0)
2913a552a69cSDamon Ding 				printf("%s: Get syscon vo1_grf failed (ret=%p)\n",
2914a552a69cSDamon Ding 				       __func__, rockchip_vop2->vo1_grf);
2915734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
2916734a0ce6SDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
2917b890760eSAlgea Cao 			if (rockchip_vop2->sys_pmu <= 0)
2918a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
2919a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
2920a552a69cSDamon Ding 		} else if (rockchip_vop2->version == VOP_VERSION_RK3576) {
2921a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf");
2922a552a69cSDamon Ding 			rockchip_vop2->ioc_grf = regmap_get_range(map, 0);
2923a552a69cSDamon Ding 			if (rockchip_vop2->ioc_grf <= 0)
2924a552a69cSDamon Ding 				printf("%s: Get syscon ioc_grf failed (ret=%p)\n",
2925a552a69cSDamon Ding 				       __func__, rockchip_vop2->ioc_grf);
2926a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
2927a552a69cSDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
2928a552a69cSDamon Ding 			if (rockchip_vop2->sys_pmu <= 0)
2929a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
2930a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
2931ecc31b6eSAndy Yan 		}
2932d0408543SAndy Yan 	}
2933d0408543SAndy Yan 
2934d0408543SAndy Yan 	cstate->private = rockchip_vop2;
293563cb669fSSandy Huang 	cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
293663cb669fSSandy Huang 	cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
2937d0408543SAndy Yan 
293889912f2dSSandy Huang 	vop2_global_initial(rockchip_vop2, state);
293989912f2dSSandy Huang 
2940d0408543SAndy Yan 	return 0;
2941d0408543SAndy Yan }
2942d0408543SAndy Yan 
2943ecc31b6eSAndy Yan /*
2944ecc31b6eSAndy Yan  * calc the dclk on rk3588
2945ecc31b6eSAndy Yan  * the available div of dclk is 1, 2, 4
2946ecc31b6eSAndy Yan  *
2947ecc31b6eSAndy Yan  */
2948ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
2949ecc31b6eSAndy Yan {
2950ecc31b6eSAndy Yan 	if (child_clk * 4 <= max_dclk)
2951ecc31b6eSAndy Yan 		return child_clk * 4;
2952ecc31b6eSAndy Yan 	else if (child_clk * 2 <= max_dclk)
2953ecc31b6eSAndy Yan 		return child_clk * 2;
2954ecc31b6eSAndy Yan 	else if (child_clk <= max_dclk)
2955ecc31b6eSAndy Yan 		return child_clk;
2956ecc31b6eSAndy Yan 	else
2957ecc31b6eSAndy Yan 		return 0;
2958ecc31b6eSAndy Yan }
2959ecc31b6eSAndy Yan 
2960ecc31b6eSAndy Yan /*
2961ecc31b6eSAndy Yan  * 4 pixclk/cycle on rk3588
2962ecc31b6eSAndy Yan  * RGB/eDP/HDMI: if_pixclk >= dclk_core
2963ecc31b6eSAndy Yan  * DP: dp_pixclk = dclk_out <= dclk_core
2964ecc31b6eSAndy Yan  * DSI: mipi_pixclk <= dclk_out <= dclk_core
2965ecc31b6eSAndy Yan  */
2966ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state,
2967ecc31b6eSAndy Yan 				       int *dclk_core_div, int *dclk_out_div,
2968ecc31b6eSAndy Yan 				       int *if_pixclk_div, int *if_dclk_div)
2969d0408543SAndy Yan {
2970d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
2971d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
2972d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
2973d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
29740a1fb152SZhang Yubing 	unsigned long v_pixclk = mode->crtc_clock;
2975ecc31b6eSAndy Yan 	unsigned long dclk_core_rate = v_pixclk >> 2;
2976ecc31b6eSAndy Yan 	unsigned long dclk_rate = v_pixclk;
2977ecc31b6eSAndy Yan 	unsigned long dclk_out_rate;
2978ecc31b6eSAndy Yan 	u64 if_dclk_rate;
2979ecc31b6eSAndy Yan 	u64 if_pixclk_rate;
2980ecc31b6eSAndy Yan 	int output_type = conn_state->type;
2981ecc31b6eSAndy Yan 	int output_mode = conn_state->output_mode;
2982ecc31b6eSAndy Yan 	int K = 1;
2983ecc31b6eSAndy Yan 
29840a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE &&
29850a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
29860a1fb152SZhang Yubing 		printf("Dual channel and YUV420 can't work together\n");
29870a1fb152SZhang Yubing 		return -EINVAL;
29880a1fb152SZhang Yubing 	}
29890a1fb152SZhang Yubing 
29900a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
29910a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420)
29920a1fb152SZhang Yubing 		K = 2;
29930a1fb152SZhang Yubing 
2994ecc31b6eSAndy Yan 	if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
2995ecc31b6eSAndy Yan 		/*
2996ecc31b6eSAndy Yan 		 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
2997ecc31b6eSAndy Yan 		 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
2998ecc31b6eSAndy Yan 		 */
29990a1fb152SZhang Yubing 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
30000a1fb152SZhang Yubing 		    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3001b890760eSAlgea Cao 			dclk_rate = dclk_rate >> 1;
3002ecc31b6eSAndy Yan 			K = 2;
3003b890760eSAlgea Cao 		}
300412ee5af0SDamon Ding 		if (cstate->dsc_enable) {
300512ee5af0SDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate << 1;
300612ee5af0SDamon Ding 			if_dclk_rate = cstate->dsc_cds_clk_rate;
3007ecc31b6eSAndy Yan 		} else {
3008ecc31b6eSAndy Yan 			if_pixclk_rate = (dclk_core_rate << 1) / K;
3009ecc31b6eSAndy Yan 			if_dclk_rate = dclk_core_rate / K;
3010ecc31b6eSAndy Yan 		}
3011ecc31b6eSAndy Yan 
3012631ee99aSZhang Yubing 		if (v_pixclk > VOP2_MAX_DCLK_RATE)
30134b726cc6SDamon Ding 			dclk_rate = vop2_calc_dclk(dclk_core_rate,
30144b726cc6SDamon Ding 						   vop2->data->vp_data[cstate->crtc_id].max_dclk);
3015631ee99aSZhang Yubing 
3016ecc31b6eSAndy Yan 		if (!dclk_rate) {
3017ecc31b6eSAndy Yan 			printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n",
30184b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate);
3019ecc31b6eSAndy Yan 			return -EINVAL;
3020ecc31b6eSAndy Yan 		}
3021ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3022ecc31b6eSAndy Yan 		*if_dclk_div = dclk_rate / if_dclk_rate;
3023b890760eSAlgea Cao 		*dclk_core_div = dclk_rate / dclk_core_rate;
3024b890760eSAlgea Cao 		printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n",
3025b890760eSAlgea Cao 		       dclk_rate, *if_pixclk_div, *if_dclk_div);
3026ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_eDP) {
3027ecc31b6eSAndy Yan 		/* edp_pixclk = edp_dclk > dclk_core */
3028ecc31b6eSAndy Yan 		if_pixclk_rate = v_pixclk / K;
3029ecc31b6eSAndy Yan 		if_dclk_rate = v_pixclk / K;
3030ecc31b6eSAndy Yan 		dclk_rate = if_pixclk_rate * K;
3031ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3032ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3033ecc31b6eSAndy Yan 		*if_dclk_div = *if_pixclk_div;
3034ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
3035ecc31b6eSAndy Yan 		dclk_out_rate = v_pixclk >> 2;
30360a1fb152SZhang Yubing 		dclk_out_rate = dclk_out_rate / K;
3037ecc31b6eSAndy Yan 
30384b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
30394b726cc6SDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
3040ecc31b6eSAndy Yan 		if (!dclk_rate) {
3041ecc31b6eSAndy Yan 			printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n",
30424b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate);
3043ecc31b6eSAndy Yan 			return -EINVAL;
3044ecc31b6eSAndy Yan 		}
3045ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3046ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3047ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DSI) {
3048ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3049ecc31b6eSAndy Yan 			K = 2;
305012ee5af0SDamon Ding 		if (cstate->dsc_enable)
305112ee5af0SDamon Ding 			/* dsc output is 96bit, dsi input is 192 bit */
305212ee5af0SDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1;
3053ecc31b6eSAndy Yan 		else
3054ecc31b6eSAndy Yan 			if_pixclk_rate = dclk_core_rate / K;
3055ecc31b6eSAndy Yan 		/* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
305612ee5af0SDamon Ding 		dclk_out_rate = dclk_core_rate / K;
3057ecc31b6eSAndy Yan 		/* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
30584b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
30594b726cc6SDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
30609f076eccSZhang Yubing 		if (!dclk_rate) {
30619f076eccSZhang Yubing 			printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n",
30624b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate);
30639f076eccSZhang Yubing 			return -EINVAL;
30649f076eccSZhang Yubing 		}
306512ee5af0SDamon Ding 
306612ee5af0SDamon Ding 		if (cstate->dsc_enable)
3067d57af898SDamon Ding 			dclk_rate /= cstate->dsc_slice_num;
306812ee5af0SDamon Ding 
3069ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3070ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3071ecc31b6eSAndy Yan 		*if_pixclk_div = 1;       /*mipi pixclk == dclk_out*/
307212ee5af0SDamon Ding 		if (cstate->dsc_enable)
30731ace1b6dSDamon Ding 			*if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate;
3074ecc31b6eSAndy Yan 
3075ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DPI) {
3076ecc31b6eSAndy Yan 		dclk_rate = v_pixclk;
3077ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3078ecc31b6eSAndy Yan 	}
3079ecc31b6eSAndy Yan 
3080ecc31b6eSAndy Yan 	*if_pixclk_div = ilog2(*if_pixclk_div);
3081ecc31b6eSAndy Yan 	*if_dclk_div = ilog2(*if_dclk_div);
3082ecc31b6eSAndy Yan 	*dclk_core_div = ilog2(*dclk_core_div);
3083ecc31b6eSAndy Yan 	*dclk_out_div = ilog2(*dclk_out_div);
3084ecc31b6eSAndy Yan 
3085ecc31b6eSAndy Yan 	return dclk_rate;
3086ecc31b6eSAndy Yan }
3087ecc31b6eSAndy Yan 
308812ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state)
3089ecc31b6eSAndy Yan {
309012ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3091ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
309212ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
30931ace1b6dSDamon Ding 	u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */
3094ecc31b6eSAndy Yan 	u8 k = 1;
3095ecc31b6eSAndy Yan 
3096ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3097ecc31b6eSAndy Yan 		k = 2;
3098ecc31b6eSAndy Yan 
309912ee5af0SDamon Ding 	cstate->dsc_txp_clk_rate = v_pixclk;
310012ee5af0SDamon Ding 	do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k));
3101ecc31b6eSAndy Yan 
310212ee5af0SDamon Ding 	cstate->dsc_pxl_clk_rate = v_pixclk;
310312ee5af0SDamon Ding 	do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k));
3104ecc31b6eSAndy Yan 
3105ecc31b6eSAndy Yan 	/* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
3106ecc31b6eSAndy Yan 	 * cds_dat_width = 96;
3107ecc31b6eSAndy Yan 	 * bits_per_pixel = [8-12];
3108b61227a3SDamon Ding 	 * As cds clk is div from txp clk and only support 1/2/4 div,
3109b61227a3SDamon Ding 	 * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
3110b61227a3SDamon Ding 	 * otherwise dsc_cds = crtc_clock / 8;
3111ecc31b6eSAndy Yan 	 */
3112b61227a3SDamon Ding 	cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
3113ecc31b6eSAndy Yan 
3114ecc31b6eSAndy Yan 	return 0;
3115ecc31b6eSAndy Yan }
3116ecc31b6eSAndy Yan 
3117ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
3118ecc31b6eSAndy Yan {
3119ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3120ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3121ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
312212ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
3123ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
312452ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
3125ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
3126ecc31b6eSAndy Yan 	int output_if = conn_state->output_if;
3127ecc31b6eSAndy Yan 	int if_pixclk_div = 0;
3128ecc31b6eSAndy Yan 	int if_dclk_div = 0;
3129ecc31b6eSAndy Yan 	unsigned long dclk_rate;
31305d2768f7SDamon Ding 	bool dclk_inv, yc_swap = false;
3131d0408543SAndy Yan 	u32 val;
3132ecc31b6eSAndy Yan 
31335d2768f7SDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3134b890760eSAlgea Cao 	if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
3135b890760eSAlgea Cao 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
3136b890760eSAlgea Cao 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
3137b890760eSAlgea Cao 	} else {
3138ecc31b6eSAndy Yan 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3139ecc31b6eSAndy Yan 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3140b890760eSAlgea Cao 	}
3141ecc31b6eSAndy Yan 
314212ee5af0SDamon Ding 	if (cstate->dsc_enable) {
314312ee5af0SDamon Ding 		int k = 1;
314412ee5af0SDamon Ding 
3145ecc31b6eSAndy Yan 		if (!vop2->data->nr_dscs) {
314612ee5af0SDamon Ding 			printf("Unsupported DSC\n");
3147ecc31b6eSAndy Yan 			return 0;
3148ecc31b6eSAndy Yan 		}
314912ee5af0SDamon Ding 
315012ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
315112ee5af0SDamon Ding 			k = 2;
315212ee5af0SDamon Ding 
315312ee5af0SDamon Ding 		cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
315412ee5af0SDamon Ding 		cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
315512ee5af0SDamon Ding 		cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num;
315612ee5af0SDamon Ding 
315712ee5af0SDamon Ding 		vop2_calc_dsc_clk(state);
315812ee5af0SDamon Ding 		printf("Enable DSC%d slice:%dx%d, slice num:%d\n",
315912ee5af0SDamon Ding 		       cstate->dsc_id, dsc_sink_cap->slice_width,
316012ee5af0SDamon Ding 		       dsc_sink_cap->slice_height, cstate->dsc_slice_num);
3161ecc31b6eSAndy Yan 	}
3162ecc31b6eSAndy Yan 
3163b61227a3SDamon Ding 	dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div);
3164ecc31b6eSAndy Yan 
3165ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_RGB) {
3166ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3167ecc31b6eSAndy Yan 				4, false);
31685d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
31695d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3170ecc31b6eSAndy Yan 	}
3171ecc31b6eSAndy Yan 
3172ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3173ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3174ecc31b6eSAndy Yan 				3, false);
31755d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
31765d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
31775d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
31785d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT,
31795d2768f7SDamon Ding 				yc_swap, false);
3180ecc31b6eSAndy Yan 	}
3181ecc31b6eSAndy Yan 
3182ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT656) {
3183ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3184ecc31b6eSAndy Yan 				2, false);
31855d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
31865d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
31875d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
31885d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT,
31895d2768f7SDamon Ding 				yc_swap, false);
3190ecc31b6eSAndy Yan 	}
3191ecc31b6eSAndy Yan 
3192ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3193ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3194ecc31b6eSAndy Yan 			val = 0;
3195ecc31b6eSAndy Yan 		else
3196ecc31b6eSAndy Yan 			val = 1;
319741874944SGuochun Huang 
31983df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
319941874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
320041874944SGuochun Huang 					RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
320141874944SGuochun Huang 
3202ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
3203ecc31b6eSAndy Yan 				1, false);
3204ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
3205ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
3206ecc31b6eSAndy Yan 				if_pixclk_div, false);
320741874944SGuochun Huang 
320841874944SGuochun Huang 		if (conn_state->hold_mode) {
320941874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
32108e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
321141874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
321241874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
321341874944SGuochun Huang 		}
3214ecc31b6eSAndy Yan 	}
3215ecc31b6eSAndy Yan 
3216ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI1) {
3217ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3218ecc31b6eSAndy Yan 			val = 0;
3219ecc31b6eSAndy Yan 		else if (cstate->crtc_id == 3)
3220ecc31b6eSAndy Yan 			val = 1;
3221ecc31b6eSAndy Yan 		else
3222ecc31b6eSAndy Yan 			val = 3; /*VP1*/
32233df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
322441874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
322541874944SGuochun Huang 					RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
322641874944SGuochun Huang 
3227ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
3228ecc31b6eSAndy Yan 				1, false);
3229ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
3230ecc31b6eSAndy Yan 				val, false);
3231ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
3232ecc31b6eSAndy Yan 				if_pixclk_div, false);
323341874944SGuochun Huang 
323441874944SGuochun Huang 		if (conn_state->hold_mode) {
323541874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
32368e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
323741874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
323841874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
323941874944SGuochun Huang 		}
3240ecc31b6eSAndy Yan 	}
3241ecc31b6eSAndy Yan 
3242ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
32433df6e59eSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
32443df6e59eSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
3245ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3246ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3247ecc31b6eSAndy Yan 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
3248ecc31b6eSAndy Yan 					false);
32490a1fb152SZhang Yubing 		switch (conn_state->type) {
32500a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DisplayPort:
32510a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
32520a1fb152SZhang Yubing 					RK3588_DP_DUAL_EN_SHIFT, 1, false);
32530a1fb152SZhang Yubing 			break;
32540a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_eDP:
32550a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
32560a1fb152SZhang Yubing 					RK3588_EDP_DUAL_EN_SHIFT, 1, false);
32570a1fb152SZhang Yubing 			break;
32580a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_HDMIA:
32590a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
32600a1fb152SZhang Yubing 					RK3588_HDMI_DUAL_EN_SHIFT, 1, false);
32610a1fb152SZhang Yubing 			break;
32620a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DSI:
32630a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
32640a1fb152SZhang Yubing 					RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
32650a1fb152SZhang Yubing 			break;
32660a1fb152SZhang Yubing 		default:
32670a1fb152SZhang Yubing 			break;
32680a1fb152SZhang Yubing 		}
3269ecc31b6eSAndy Yan 	}
3270ecc31b6eSAndy Yan 
3271ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP0) {
3272ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
3273ecc31b6eSAndy Yan 				1, false);
3274ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3275ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3276ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3277ecc31b6eSAndy Yan 				if_dclk_div, false);
3278ecc31b6eSAndy Yan 
3279ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3280ecc31b6eSAndy Yan 				if_pixclk_div, false);
3281ecc31b6eSAndy Yan 
3282ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3283ecc31b6eSAndy Yan 				RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
3284ecc31b6eSAndy Yan 	}
3285ecc31b6eSAndy Yan 
3286ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP1) {
3287ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
3288ecc31b6eSAndy Yan 				1, false);
3289ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3290ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3291ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3292ecc31b6eSAndy Yan 				if_dclk_div, false);
3293ecc31b6eSAndy Yan 
3294ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3295ecc31b6eSAndy Yan 				if_pixclk_div, false);
32961848455fSDamon Ding 
32971848455fSDamon Ding 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
32981848455fSDamon Ding 				RK3588_GRF_EDP1_ENABLE_SHIFT, 1);
3299ecc31b6eSAndy Yan 	}
3300ecc31b6eSAndy Yan 
3301ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
3302ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
3303ecc31b6eSAndy Yan 				1, false);
3304ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3305ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3306ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3307ecc31b6eSAndy Yan 				if_dclk_div, false);
3308ecc31b6eSAndy Yan 
3309ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3310ecc31b6eSAndy Yan 				if_pixclk_div, false);
3311b890760eSAlgea Cao 
3312b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3313b890760eSAlgea Cao 				RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1);
3314b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3315b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3316b890760eSAlgea Cao 				HDMI0_SYNC_POL_SHIFT, val);
3317ecc31b6eSAndy Yan 	}
3318ecc31b6eSAndy Yan 
3319ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI1) {
3320ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
3321ecc31b6eSAndy Yan 				1, false);
3322ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3323ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3324ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3325ecc31b6eSAndy Yan 				if_dclk_div, false);
3326ecc31b6eSAndy Yan 
3327ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3328ecc31b6eSAndy Yan 				if_pixclk_div, false);
3329b890760eSAlgea Cao 
3330b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3331b890760eSAlgea Cao 				RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1);
3332b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3333b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3334b890760eSAlgea Cao 				HDMI1_SYNC_POL_SHIFT, val);
3335ecc31b6eSAndy Yan 	}
3336ecc31b6eSAndy Yan 
3337ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP0) {
3338ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
3339ecc31b6eSAndy Yan 				1, false);
3340ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
3341ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3342ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3343ecc31b6eSAndy Yan 				RK3588_DP0_PIN_POL_SHIFT, val, false);
3344ecc31b6eSAndy Yan 	}
3345ecc31b6eSAndy Yan 
3346ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP1) {
3347108c5f8bSZhang Yubing 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT,
3348ecc31b6eSAndy Yan 				1, false);
3349ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
3350ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3351ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3352ecc31b6eSAndy Yan 				RK3588_DP1_PIN_POL_SHIFT, val, false);
3353ecc31b6eSAndy Yan 	}
3354ecc31b6eSAndy Yan 
3355ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3356b61227a3SDamon Ding 			DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false);
3357ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3358b61227a3SDamon Ding 			DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false);
3359ecc31b6eSAndy Yan 
3360ecc31b6eSAndy Yan 	return dclk_rate;
3361ecc31b6eSAndy Yan }
3362ecc31b6eSAndy Yan 
3363a552a69cSDamon Ding static unsigned long rk3576_vop2_if_cfg(struct display_state *state)
3364a552a69cSDamon Ding {
3365a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3366a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3367a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3368a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
3369a552a69cSDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
3370a552a69cSDamon Ding 	u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate;
3371a552a69cSDamon Ding 	int output_if = conn_state->output_if;
3372a552a69cSDamon Ding 	bool dclk_inv, yc_swap = false;
3373a552a69cSDamon Ding 	bool split_mode = !!(conn_state->output_flags &
3374a552a69cSDamon Ding 			     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE);
3375a552a69cSDamon Ding 	bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false;
3376a552a69cSDamon Ding 	bool interface_dclk_sel, interface_pix_clk_sel = false;
3377a552a69cSDamon Ding 	bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK ||
3378a552a69cSDamon Ding 			    conn_state->output_if & VOP_OUTPUT_IF_BT656;
3379a552a69cSDamon Ding 	u32 val;
3380a552a69cSDamon Ding 
3381a552a69cSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3382a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3383a552a69cSDamon Ding 		/*
3384a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3385a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
3386a552a69cSDamon Ding 		 */
3387a552a69cSDamon Ding 		val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3388a552a69cSDamon Ding 	} else {
3389a552a69cSDamon Ding 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3390a552a69cSDamon Ding 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3391a552a69cSDamon Ding 	}
3392a552a69cSDamon Ding 
3393a552a69cSDamon Ding 	if (cstate->crtc_id == 1 || cstate->crtc_id == 2 ||
3394a552a69cSDamon Ding 	    (cstate->crtc_id == 0 && conn_state->output_if & VOP_OUTPUT_IF_eDP0) ||
3395a552a69cSDamon Ding 	    (conn_state->output_if & VOP_OUTPUT_IF_HDMI0 && mode->crtc_clock <= VOP2_MAX_DCLK_RATE))
3396a552a69cSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */
3397a552a69cSDamon Ding 	else
3398a552a69cSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */
3399a552a69cSDamon Ding 
3400a552a69cSDamon Ding 	if (double_pixel ||
3401a552a69cSDamon Ding 	    (cstate->crtc_id == 0 && conn_state->output_if & VOP_OUTPUT_IF_eDP0) ||
3402a552a69cSDamon Ding 	    (conn_state->output_if & VOP_OUTPUT_IF_HDMI0 && mode->crtc_clock <= VOP2_MAX_DCLK_RATE))
3403a552a69cSDamon Ding 		post_dclk_core_sel = true; /* div2 */
3404a552a69cSDamon Ding 	else
3405a552a69cSDamon Ding 		post_dclk_core_sel = false; /* no div */
3406a552a69cSDamon Ding 
3407a552a69cSDamon Ding 	if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3408a552a69cSDamon Ding 		pix_half_rate = true;
3409a552a69cSDamon Ding 		post_dclk_out_sel = true;
3410a552a69cSDamon Ding 	}
3411a552a69cSDamon Ding 
3412a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3413a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3414a552a69cSDamon Ding 		/*
3415a552a69cSDamon Ding 		 * RGB interface_pix_clk_sel will auto config according
3416a552a69cSDamon Ding 		 * to rgb_en/bt1120_en/bt656_en.
3417a552a69cSDamon Ding 		 */
3418a552a69cSDamon Ding 	} else if (output_if & VOP_OUTPUT_IF_eDP0) {
3419a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3420a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0;
3421a552a69cSDamon Ding 	} else {
3422a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3423a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0;
3424a552a69cSDamon Ding 	}
3425a552a69cSDamon Ding 
3426a552a69cSDamon Ding 	/* dclk_core */
3427a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3428a552a69cSDamon Ding 			RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false);
3429a552a69cSDamon Ding 	/* dclk_out */
3430a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3431a552a69cSDamon Ding 			RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false);
3432a552a69cSDamon Ding 
3433a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3434a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3435a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3436a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3437a552a69cSDamon Ding 
3438a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3439a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3440a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3441a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3442a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3443a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3444a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3445a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3446a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3447a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3448a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3449a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv);
3450a552a69cSDamon Ding 	}
3451a552a69cSDamon Ding 
3452a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3453a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3454a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3455a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3456a552a69cSDamon Ding 
3457a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3458a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3459a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3460a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3461a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3462a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3463a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3464a552a69cSDamon Ding 				RK3576_BT1120_OUT_EN_SHIFT, 1, false);
3465a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3466a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3467a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3468a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3469a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
3470a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3471a552a69cSDamon Ding 				RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false);
3472a552a69cSDamon Ding 	}
3473a552a69cSDamon Ding 
3474a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT656) {
3475a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3476a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3477a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3478a552a69cSDamon Ding 
3479a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3480a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3481a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3482a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3483a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3484a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3485a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3486a552a69cSDamon Ding 				RK3576_BT656_OUT_EN_SHIFT, 1, false);
3487a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3488a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3489a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3490a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3491a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
3492a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3493a552a69cSDamon Ding 				RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false);
3494a552a69cSDamon Ding 	}
3495a552a69cSDamon Ding 
3496a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3497a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3498a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3499a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
3500a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3501a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3502a552a69cSDamon Ding 
3503a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3504a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3505a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3506a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3507a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3508a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3509a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3510a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3511a552a69cSDamon Ding 		/*
3512a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3513a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
3514a552a69cSDamon Ding 		 */
3515a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
3516a552a69cSDamon Ding 			val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3517a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3518a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3519a552a69cSDamon Ding 
3520a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
3521a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3522a552a69cSDamon Ding 					RK3576_MIPI_CMD_MODE_SHIFT, 1, false);
3523a552a69cSDamon Ding 
3524a552a69cSDamon Ding 		if (conn_state->hold_mode) {
3525a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3526a552a69cSDamon Ding 					EDPI_TE_EN, !cstate->soft_te, false);
3527a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3528a552a69cSDamon Ding 					EDPI_WMS_HOLD_EN, 1, false);
3529a552a69cSDamon Ding 		}
3530a552a69cSDamon Ding 	}
3531a552a69cSDamon Ding 
3532a552a69cSDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
3533a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3534a552a69cSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
3535a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3536a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3537a552a69cSDamon Ding 					MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
3538a552a69cSDamon Ding 		switch (conn_state->type) {
3539a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DisplayPort:
3540a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3541a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3542a552a69cSDamon Ding 			break;
3543a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_eDP:
3544a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3545a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3546a552a69cSDamon Ding 			break;
3547a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_HDMIA:
3548a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3549a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3550a552a69cSDamon Ding 			break;
3551a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DSI:
3552a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3553a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3554a552a69cSDamon Ding 			break;
3555a552a69cSDamon Ding 		default:
3556a552a69cSDamon Ding 			break;
3557a552a69cSDamon Ding 		}
3558a552a69cSDamon Ding 	}
3559a552a69cSDamon Ding 
3560a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_eDP0) {
3561a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3562a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3563a552a69cSDamon Ding 		/* 0: dclk, 1: port0_dclk */
3564a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3565a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3566a552a69cSDamon Ding 
3567a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3568a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3569a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3570a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3571a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3572a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3573a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3574a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3575a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3576a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3577a552a69cSDamon Ding 	}
3578a552a69cSDamon Ding 
3579a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
3580a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3581a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3582a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
3583a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3584a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3585a552a69cSDamon Ding 
3586a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3587a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3588a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3589a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3590a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3591a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3592a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3593a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3594a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3595a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3596a552a69cSDamon Ding 	}
3597a552a69cSDamon Ding 
3598a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP0) {
3599a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3600a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3601a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3602a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3603a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3604a552a69cSDamon Ding 
3605a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3606a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3607a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3608a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3609a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3610a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3611a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3612a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3613a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3614a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3615a552a69cSDamon Ding 	}
3616a552a69cSDamon Ding 
3617a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP1) {
3618a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3619a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3620a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3621a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3622a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3623a552a69cSDamon Ding 
3624a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
3625a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3626a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
3627a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3628a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
3629a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3630a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3631a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3632a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3633a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3634a552a69cSDamon Ding 	}
3635a552a69cSDamon Ding 
3636a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP2) {
3637a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3638a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3639a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3640a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3641a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3642a552a69cSDamon Ding 
3643a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
3644a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3645a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
3646a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3647a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
3648a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3649a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3650a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3651a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3652a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3653a552a69cSDamon Ding 	}
3654a552a69cSDamon Ding 
3655a552a69cSDamon Ding 	return mode->crtc_clock;
3656a552a69cSDamon Ding }
3657a552a69cSDamon Ding 
3658a2a16809SChaoyi Chen static void rk3568_vop2_setup_dual_channel_if(struct display_state *state)
3659a2a16809SChaoyi Chen {
3660a2a16809SChaoyi Chen 	struct crtc_state *cstate = &state->crtc_state;
3661a2a16809SChaoyi Chen 	struct connector_state *conn_state = &state->conn_state;
3662a2a16809SChaoyi Chen 	struct vop2 *vop2 = cstate->private;
3663a2a16809SChaoyi Chen 	u32 vp_offset = (cstate->crtc_id * 0x100);
3664a2a16809SChaoyi Chen 
3665a2a16809SChaoyi Chen 	if (conn_state->output_flags &
3666a2a16809SChaoyi Chen 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) {
3667a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3668a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
3669a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3670a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false);
3671a2a16809SChaoyi Chen 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3672a2a16809SChaoyi Chen 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3673a2a16809SChaoyi Chen 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
3674a2a16809SChaoyi Chen 
3675a2a16809SChaoyi Chen 		return;
3676a2a16809SChaoyi Chen 	}
3677a2a16809SChaoyi Chen 
3678a2a16809SChaoyi Chen 	vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3679a2a16809SChaoyi Chen 			MIPI_DUAL_EN_SHIFT, 1, false);
3680a2a16809SChaoyi Chen 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) {
3681a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3682a2a16809SChaoyi Chen 				MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
3683a2a16809SChaoyi Chen 	}
3684a2a16809SChaoyi Chen 
3685a2a16809SChaoyi Chen 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
3686a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3687a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
3688a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3689a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false);
3690a2a16809SChaoyi Chen 	}
3691a2a16809SChaoyi Chen }
3692a2a16809SChaoyi Chen 
3693ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
3694ecc31b6eSAndy Yan {
3695ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3696ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3697ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
3698ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
3699d0408543SAndy Yan 	bool dclk_inv;
3700ecc31b6eSAndy Yan 	u32 val;
37018895aec1SSandy Huang 
370213f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
370310ee9f5bSAlgea Cao 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
370410ee9f5bSAlgea Cao 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3705d0408543SAndy Yan 
3706d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3707d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3708d0408543SAndy Yan 				1, false);
3709d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3710d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
371115f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
371215f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3713ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
3714c55d261eSSandy Huang 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
3715d0408543SAndy Yan 	}
3716d0408543SAndy Yan 
3717d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
371852ee18acSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
371952ee18acSSandy Huang 				1, false);
3720d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
3721d0408543SAndy Yan 				BT1120_EN_SHIFT, 1, false);
3722d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3723d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3724ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
372552ee18acSSandy Huang 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
3726d0408543SAndy Yan 	}
3727d0408543SAndy Yan 
3728d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
3729d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
3730d0408543SAndy Yan 				1, false);
3731d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3732d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3733ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
373452ee18acSSandy Huang 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
3735d0408543SAndy Yan 	}
3736d0408543SAndy Yan 
3737d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
3738d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
3739d0408543SAndy Yan 				1, false);
3740d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3741d0408543SAndy Yan 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
374215f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
374315f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
374411f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
374515f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3746d0408543SAndy Yan 	}
3747d0408543SAndy Yan 
3748d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
3749d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
3750d0408543SAndy Yan 				1, false);
3751d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3752d0408543SAndy Yan 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
375315f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
375415f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
375511f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
375615f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3757d0408543SAndy Yan 	}
3758d0408543SAndy Yan 
3759d0408543SAndy Yan 
3760d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
3761d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
3762d0408543SAndy Yan 				1, false);
3763d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3764d0408543SAndy Yan 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
3765d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3766c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3767d0408543SAndy Yan 	}
3768d0408543SAndy Yan 
3769d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
3770d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
3771d0408543SAndy Yan 				1, false);
3772d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3773d0408543SAndy Yan 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
3774d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3775c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3776d0408543SAndy Yan 	}
3777d0408543SAndy Yan 
3778d0408543SAndy Yan 	if (conn_state->output_flags &
3779a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
3780a2a16809SChaoyi Chen 	    conn_state->output_flags &
3781a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)
3782a2a16809SChaoyi Chen 		rk3568_vop2_setup_dual_channel_if(state);
3783d0408543SAndy Yan 
3784d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
3785d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
3786d0408543SAndy Yan 				1, false);
3787d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3788d0408543SAndy Yan 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
3789c55d261eSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3790c55d261eSSandy Huang 				IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
37917bcdc6eeSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK,
37927bcdc6eeSDamon Ding 				IF_CTRL_EDP_PIN_POL_SHIFT, val, false);
3793d0408543SAndy Yan 	}
3794d0408543SAndy Yan 
3795d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
3796d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
3797d0408543SAndy Yan 				1, false);
3798d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3799d0408543SAndy Yan 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
380010ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
380110ee9f5bSAlgea Cao 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
380210ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
380310ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_MASK,
380410ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
3805d0408543SAndy Yan 	}
380610ee9f5bSAlgea Cao 
3807823146b6SDamon Ding 	return mode->crtc_clock;
3808ecc31b6eSAndy Yan }
3809ecc31b6eSAndy Yan 
3810452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state)
3811452afb13SDamon Ding {
3812452afb13SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3813452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3814452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3815452afb13SDamon Ding 	struct vop2 *vop2 = cstate->private;
3816452afb13SDamon Ding 	bool dclk_inv;
3817452afb13SDamon Ding 	u32 val;
3818452afb13SDamon Ding 
381913f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3820452afb13SDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3821452afb13SDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3822452afb13SDamon Ding 
3823452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3824452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3825452afb13SDamon Ding 				1, false);
3826452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3827452afb13SDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3828452afb13SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK,
3829452afb13SDamon Ding 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
3830452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
383115f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3832452afb13SDamon Ding 	}
3833452afb13SDamon Ding 
3834452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
3835452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
3836452afb13SDamon Ding 				1, false);
3837452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3838452afb13SDamon Ding 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
3839452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
384015f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3841452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
384215f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3843452afb13SDamon Ding 	}
3844452afb13SDamon Ding 
3845452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
3846452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
3847452afb13SDamon Ding 				1, false);
3848452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3849452afb13SDamon Ding 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
3850452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3851452afb13SDamon Ding 				RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false);
3852452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
3853452afb13SDamon Ding 				RK3562_MIPI_PIN_POL_SHIFT, val, false);
3854452afb13SDamon Ding 	}
3855452afb13SDamon Ding 
3856452afb13SDamon Ding 	return mode->crtc_clock;
3857452afb13SDamon Ding }
3858452afb13SDamon Ding 
3859a552a69cSDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state)
3860a552a69cSDamon Ding {
3861a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3862a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3863a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3864a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
3865a552a69cSDamon Ding 	u32 val;
3866a552a69cSDamon Ding 
3867a552a69cSDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3868a552a69cSDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3869a552a69cSDamon Ding 
3870a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
3871a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
3872a552a69cSDamon Ding 				1, false);
3873a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3874a552a69cSDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3875a552a69cSDamon Ding 	}
3876a552a69cSDamon Ding 
3877a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
3878a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
3879a552a69cSDamon Ding 				1, false);
3880a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3881a552a69cSDamon Ding 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
3882a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3883a552a69cSDamon Ding 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
3884a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
3885a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_MASK,
3886a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
3887a552a69cSDamon Ding 	}
3888a552a69cSDamon Ding 
3889a552a69cSDamon Ding 	return mode->crtc_clock;
3890a552a69cSDamon Ding }
3891a552a69cSDamon Ding 
389265747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state)
389365747de7SDamon Ding {
389465747de7SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
389565747de7SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
389665747de7SDamon Ding 	struct vop2 *vop2 = cstate->private;
389765747de7SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
389865747de7SDamon Ding 	u32 output_type = conn_state->type;
389965747de7SDamon Ding 	u32 data_swap = 0;
390065747de7SDamon Ding 
39010675a2a4SDamon Ding 	if (is_uv_swap(conn_state->bus_format, conn_state->output_mode) ||
39020675a2a4SDamon Ding 	    is_rb_swap(conn_state->bus_format, conn_state->output_mode))
390365747de7SDamon Ding 		data_swap = DSP_RB_SWAP;
390465747de7SDamon Ding 
3905a552a69cSDamon Ding 	if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) {
3906a552a69cSDamon Ding 		if ((output_type == DRM_MODE_CONNECTOR_HDMIA ||
390765747de7SDamon Ding 		     output_type == DRM_MODE_CONNECTOR_eDP) &&
390865747de7SDamon Ding 		    (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
390965747de7SDamon Ding 		     conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
391065747de7SDamon Ding 		data_swap |= DSP_RG_SWAP;
3911a552a69cSDamon Ding 	}
391265747de7SDamon Ding 
391365747de7SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
391465747de7SDamon Ding 			DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false);
391565747de7SDamon Ding }
391665747de7SDamon Ding 
3917b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
3918b890760eSAlgea Cao {
3919b890760eSAlgea Cao 	int ret = 0;
3920b890760eSAlgea Cao 
3921b890760eSAlgea Cao 	if (parent->dev)
3922b890760eSAlgea Cao 		ret = clk_set_parent(clk, parent);
3923b890760eSAlgea Cao 	if (ret < 0)
3924b890760eSAlgea Cao 		debug("failed to set %s as parent for %s\n",
3925b890760eSAlgea Cao 		      parent->dev->name, clk->dev->name);
3926b890760eSAlgea Cao }
3927b890760eSAlgea Cao 
3928b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate)
3929b890760eSAlgea Cao {
3930b890760eSAlgea Cao 	int ret = 0;
3931b890760eSAlgea Cao 
3932b890760eSAlgea Cao 	if (clk->dev)
3933b890760eSAlgea Cao 		ret = clk_set_rate(clk, rate);
3934b890760eSAlgea Cao 	if (ret < 0)
3935b890760eSAlgea Cao 		debug("failed to set %s rate %lu \n", clk->dev->name, rate);
3936b890760eSAlgea Cao 
3937b890760eSAlgea Cao 	return ret;
3938b890760eSAlgea Cao }
3939b890760eSAlgea Cao 
394012ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state,
394112ee5af0SDamon Ding 				  int *dsc_txp_clk_div, int *dsc_pxl_clk_div,
394212ee5af0SDamon Ding 				  int *dsc_cds_clk_div, u64 dclk_rate)
394312ee5af0SDamon Ding {
394412ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
394512ee5af0SDamon Ding 
394612ee5af0SDamon Ding 	*dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate;
394712ee5af0SDamon Ding 	*dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate;
394812ee5af0SDamon Ding 	*dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate;
394912ee5af0SDamon Ding 
395012ee5af0SDamon Ding 	*dsc_txp_clk_div = ilog2(*dsc_txp_clk_div);
395112ee5af0SDamon Ding 	*dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div);
395212ee5af0SDamon Ding 	*dsc_cds_clk_div = ilog2(*dsc_cds_clk_div);
395312ee5af0SDamon Ding }
395412ee5af0SDamon Ding 
395512ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id)
395612ee5af0SDamon Ding {
395712ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
395812ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set *pps = &cstate->pps;
395912ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set config_pps;
396012ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
396112ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
396212ee5af0SDamon Ding 	u32 *pps_val = (u32 *)&config_pps;
396312ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
396412ee5af0SDamon Ding 	int i = 0;
396512ee5af0SDamon Ding 
396612ee5af0SDamon Ding 	memcpy(&config_pps, pps, sizeof(config_pps));
396712ee5af0SDamon Ding 
396812ee5af0SDamon Ding 	if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) {
396912ee5af0SDamon Ding 		config_pps.pps_3 &= 0xf0;
397012ee5af0SDamon Ding 		config_pps.pps_3 |= dsc_data->max_linebuf_depth;
397112ee5af0SDamon Ding 		printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
397212ee5af0SDamon Ding 		       dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf);
397312ee5af0SDamon Ding 	}
397412ee5af0SDamon Ding 
397512ee5af0SDamon Ding 	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
397612ee5af0SDamon Ding 		config_pps.rc_range_parameters[i] =
397712ee5af0SDamon Ding 			(pps->rc_range_parameters[i] >> 3 & 0x1f) |
397812ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
397912ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
398012ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
398112ee5af0SDamon Ding 	}
398212ee5af0SDamon Ding 
398312ee5af0SDamon Ding 	for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
398412ee5af0SDamon Ding 		vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++);
398512ee5af0SDamon Ding }
398612ee5af0SDamon Ding 
398712ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate)
398812ee5af0SDamon Ding {
398912ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
399012ee5af0SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
399112ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
399212ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
399312ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
399412ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
399512ee5af0SDamon Ding 	bool mipi_ds_mode = false;
399612ee5af0SDamon Ding 	u8 dsc_interface_mode = 0;
399712ee5af0SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
399812ee5af0SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
399912ee5af0SDamon Ding 	u16 htotal = mode->crtc_htotal;
400012ee5af0SDamon Ding 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
400112ee5af0SDamon Ding 	u16 vdisplay = mode->crtc_vdisplay;
400212ee5af0SDamon Ding 	u16 vtotal = mode->crtc_vtotal;
400312ee5af0SDamon Ding 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
400412ee5af0SDamon Ding 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
400512ee5af0SDamon Ding 	u16 vact_end = vact_st + vdisplay;
400612ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
400712ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
400812ee5af0SDamon Ding 	int dsc_txp_clk_div = 0;
400912ee5af0SDamon Ding 	int dsc_pxl_clk_div = 0;
401012ee5af0SDamon Ding 	int dsc_cds_clk_div = 0;
4011baf2c414SDamon Ding 	int val = 0;
401212ee5af0SDamon Ding 
401312ee5af0SDamon Ding 	if (!vop2->data->nr_dscs) {
401412ee5af0SDamon Ding 		printf("Unsupported DSC\n");
401512ee5af0SDamon Ding 		return;
401612ee5af0SDamon Ding 	}
401712ee5af0SDamon Ding 
401812ee5af0SDamon Ding 	if (cstate->dsc_slice_num > dsc_data->max_slice_num)
401912ee5af0SDamon Ding 		printf("DSC%d supported max slice is: %d, current is: %d\n",
402012ee5af0SDamon Ding 		       dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num);
402112ee5af0SDamon Ding 
402212ee5af0SDamon Ding 	if (dsc_data->pd_id) {
402312ee5af0SDamon Ding 		if (vop2_power_domain_on(vop2, dsc_data->pd_id))
402412ee5af0SDamon Ding 			printf("open dsc%d pd fail\n", dsc_id);
402512ee5af0SDamon Ding 	}
402612ee5af0SDamon Ding 
402712ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK,
402812ee5af0SDamon Ding 			SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false);
402912ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK,
403012ee5af0SDamon Ding 			DSC_PORT_SEL_SHIFT, cstate->crtc_id, false);
403112ee5af0SDamon Ding 	if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
403212ee5af0SDamon Ding 		dsc_interface_mode = VOP_DSC_IF_HDMI;
403312ee5af0SDamon Ding 	} else {
403412ee5af0SDamon Ding 		mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
403512ee5af0SDamon Ding 		if (mipi_ds_mode)
403612ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
403712ee5af0SDamon Ding 		else
403812ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
403912ee5af0SDamon Ding 	}
404012ee5af0SDamon Ding 
404112ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
404212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
404312ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 0, false);
404412ee5af0SDamon Ding 	else
404512ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
404612ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 1, false);
404712ee5af0SDamon Ding 
404812ee5af0SDamon Ding 	vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate);
404912ee5af0SDamon Ding 
405012ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK,
405112ee5af0SDamon Ding 			DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false);
405212ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK,
405312ee5af0SDamon Ding 			DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false);
405412ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK,
405512ee5af0SDamon Ding 			DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false);
405612ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK,
405712ee5af0SDamon Ding 			DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false);
405812ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
405912ee5af0SDamon Ding 			DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false);
406012ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK,
406112ee5af0SDamon Ding 			DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false);
406212ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
406312ee5af0SDamon Ding 			DSC_HALT_EN_SHIFT, mipi_ds_mode, false);
406412ee5af0SDamon Ding 
406512ee5af0SDamon Ding 	if (!mipi_ds_mode) {
406612ee5af0SDamon Ding 		u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
406712ee5af0SDamon Ding 		u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
406812ee5af0SDamon Ding 		u64 dsc_cds_rate = cstate->dsc_cds_clk_rate;
406912ee5af0SDamon Ding 		u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */
407012ee5af0SDamon Ding 		u32 dly_num, dsc_cds_rate_mhz, val = 0;
4071b61227a3SDamon Ding 		int k = 1;
4072b61227a3SDamon Ding 
4073b61227a3SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
4074b61227a3SDamon Ding 			k = 2;
407512ee5af0SDamon Ding 
407612ee5af0SDamon Ding 		if (target_bpp >> 4 < dsc_data->min_bits_per_pixel)
407712ee5af0SDamon Ding 			printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel);
407812ee5af0SDamon Ding 
407912ee5af0SDamon Ding 		/*
408012ee5af0SDamon Ding 		 * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
408112ee5af0SDamon Ding 		 * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
408212ee5af0SDamon Ding 		 * T (dsc_cds) = 1 / dsc_cds_rate_mhz
40831ace1b6dSDamon Ding 		 *
40841ace1b6dSDamon Ding 		 * HDMI:
408512ee5af0SDamon Ding 		 * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
408612ee5af0SDamon Ding 		 *                 delay_line_num = 4 - BPP / 8
408712ee5af0SDamon Ding 		 *                                = (64 - target_bpp / 8) / 16
408812ee5af0SDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
40891ace1b6dSDamon Ding 		 *
40901ace1b6dSDamon Ding 		 * MIPI DSI[4320 and 9216 is buffer size for DSC]:
40911ace1b6dSDamon Ding 		 * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
40921ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
40931ace1b6dSDamon Ding 		 * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
40941ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
40951ace1b6dSDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
409612ee5af0SDamon Ding 		 */
409712ee5af0SDamon Ding 		do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
409812ee5af0SDamon Ding 		dsc_cds_rate_mhz = dsc_cds_rate;
40991ace1b6dSDamon Ding 		dsc_hsync = hsync_len / 2;
41001ace1b6dSDamon Ding 		if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
410112ee5af0SDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
41021ace1b6dSDamon Ding 		} else {
41031ace1b6dSDamon Ding 			int dsc_buf_size  = dsc_id == 0 ? 4320 * 8 : 9216 * 2;
41041ace1b6dSDamon Ding 			int delay_line_num = dsc_buf_size / cstate->dsc_slice_num /
41051ace1b6dSDamon Ding 					     be16_to_cpu(cstate->pps.chunk_size);
41061ace1b6dSDamon Ding 
41071ace1b6dSDamon Ding 			delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
41081ace1b6dSDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
41091ace1b6dSDamon Ding 
41101ace1b6dSDamon Ding 			/* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
41111ace1b6dSDamon Ding 			if (dsc_hsync < 8)
41121ace1b6dSDamon Ding 				dsc_hsync = 8;
41131ace1b6dSDamon Ding 		}
411412ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK,
411512ee5af0SDamon Ding 				DSC_INIT_DLY_MODE_SHIFT, 0, false);
411612ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK,
411712ee5af0SDamon Ding 				DSC_INIT_DLY_NUM_SHIFT, dly_num, false);
411812ee5af0SDamon Ding 
4119b61227a3SDamon Ding 		/*
4120b61227a3SDamon Ding 		 * htotal / dclk_core = dsc_htotal /cds_clk
4121b61227a3SDamon Ding 		 *
4122b61227a3SDamon Ding 		 * dclk_core = DCLK / (1 << dclk_core->div_val)
4123b61227a3SDamon Ding 		 * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
4124b61227a3SDamon Ding 		 * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
4125b61227a3SDamon Ding 		 *
4126b61227a3SDamon Ding 		 * dsc_htotal = htotal * (1 << dclk_core->div_val) /
4127b61227a3SDamon Ding 		 *              ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
4128b61227a3SDamon Ding 		 */
4129b61227a3SDamon Ding 		dsc_htotal = htotal * (1 << cstate->dclk_core_div) /
4130b61227a3SDamon Ding 			     ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div));
413112ee5af0SDamon Ding 		val = dsc_htotal << 16 | dsc_hsync;
413212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK,
413312ee5af0SDamon Ding 				DSC_HTOTAL_PW_SHIFT, val, false);
413412ee5af0SDamon Ding 
413512ee5af0SDamon Ding 		dsc_hact_st = hact_st / 2;
4136b61227a3SDamon Ding 		dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
413712ee5af0SDamon Ding 		val = dsc_hact_end << 16 | dsc_hact_st;
413812ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK,
413912ee5af0SDamon Ding 				DSC_HACT_ST_END_SHIFT, val, false);
414012ee5af0SDamon Ding 
414112ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK,
414212ee5af0SDamon Ding 				DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false);
414312ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK,
414412ee5af0SDamon Ding 				DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false);
414512ee5af0SDamon Ding 	}
414612ee5af0SDamon Ding 
414712ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK,
414812ee5af0SDamon Ding 			RST_DEASSERT_SHIFT, 1, false);
414912ee5af0SDamon Ding 	udelay(10);
415012ee5af0SDamon Ding 
4151baf2c414SDamon Ding 	val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) |
4152baf2c414SDamon Ding 	       ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT);
4153baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
4154baf2c414SDamon Ding 
415512ee5af0SDamon Ding 	vop2_load_pps(state, vop2, dsc_id);
415612ee5af0SDamon Ding 
4157baf2c414SDamon Ding 	val |= (1 << DSC_PPS_UPD_SHIFT);
4158baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
415912ee5af0SDamon Ding 
416012ee5af0SDamon Ding 	printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
416112ee5af0SDamon Ding 	       dsc_id,
416212ee5af0SDamon Ding 	       cstate->dsc_txp_clk_rate, dsc_txp_clk_div,
416312ee5af0SDamon Ding 	       cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div,
416412ee5af0SDamon Ding 	       cstate->dsc_cds_clk_rate, dsc_cds_clk_div);
416512ee5af0SDamon Ding }
416612ee5af0SDamon Ding 
41675f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev)
41685f1357a2SZhang Yubing {
41695f1357a2SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
41705f1357a2SZhang Yubing 	struct vop2 *vop2 = cstate->private;
41715f1357a2SZhang Yubing 	struct udevice *vp_dev, *dev;
41725f1357a2SZhang Yubing 	struct ofnode_phandle_args args;
41735f1357a2SZhang Yubing 	char vp_name[10];
41745f1357a2SZhang Yubing 	int ret;
41755f1357a2SZhang Yubing 
4176a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576)
41775f1357a2SZhang Yubing 		return false;
41785f1357a2SZhang Yubing 
41795f1357a2SZhang Yubing 	sprintf(vp_name, "port@%d", cstate->crtc_id);
41805f1357a2SZhang Yubing 	if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) {
41815e85f4a7SZhang Yubing 		debug("warn: can't get vp device\n");
41825f1357a2SZhang Yubing 		return false;
41835f1357a2SZhang Yubing 	}
41845f1357a2SZhang Yubing 
41855f1357a2SZhang Yubing 	ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0,
41865f1357a2SZhang Yubing 					 0, &args);
41875f1357a2SZhang Yubing 	if (ret) {
41885e85f4a7SZhang Yubing 		debug("assigned-clock-parents's node not define\n");
41895f1357a2SZhang Yubing 		return false;
41905f1357a2SZhang Yubing 	}
41915f1357a2SZhang Yubing 
41925f1357a2SZhang Yubing 	if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) {
41935e85f4a7SZhang Yubing 		debug("warn: can't get clk device\n");
41945f1357a2SZhang Yubing 		return false;
41955f1357a2SZhang Yubing 	}
41965f1357a2SZhang Yubing 
41975f1357a2SZhang Yubing 	if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) {
41985f1357a2SZhang Yubing 		printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name);
41995f1357a2SZhang Yubing 		if (clk_dev)
42005f1357a2SZhang Yubing 			*clk_dev = dev;
42015f1357a2SZhang Yubing 		return true;
42025f1357a2SZhang Yubing 	}
42035f1357a2SZhang Yubing 
42045f1357a2SZhang Yubing 	return false;
42055f1357a2SZhang Yubing }
42065f1357a2SZhang Yubing 
42070675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state)
42080675a2a4SDamon Ding {
42090675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
42100675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
42110675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
42120675a2a4SDamon Ding 
42130675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42140675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
42150675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42160675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
42170675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
42180675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false);
42190675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
42200675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false);
42210675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
42220675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false);
42230675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
42240675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false);
42250675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
42260675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false);
42270675a2a4SDamon Ding }
42280675a2a4SDamon Ding 
42290675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state)
42300675a2a4SDamon Ding {
42310675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
42320675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
42330675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
42340675a2a4SDamon Ding 
42350675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42360675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
42370675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42380675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
42390675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
42400675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, 53, false);
42410675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
42420675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, 6, false);
42430675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
42440675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, 48, false);
42450675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
42460675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, 12, false);
42470675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
42480675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, 30, false);
42490675a2a4SDamon Ding }
42500675a2a4SDamon Ding 
42510675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value)
42520675a2a4SDamon Ding {
42530675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
42540675a2a4SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
42550675a2a4SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
42560675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
42570675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
42580675a2a4SDamon Ding 
42590675a2a4SDamon Ding 	/*
426058cf1fa3SDamon Ding 	 * 1.set mcu bypass mode timing.
426158cf1fa3SDamon Ding 	 * 2.set dclk rate to 150M.
42620675a2a4SDamon Ding 	 */
42630675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && value) {
42640675a2a4SDamon Ding 		vop3_mcu_bypass_mode_setup(state);
42650675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, 150000000);
42660675a2a4SDamon Ding 	}
42670675a2a4SDamon Ding 
42680675a2a4SDamon Ding 	switch (type) {
42690675a2a4SDamon Ding 	case MCU_WRCMD:
42700675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42710675a2a4SDamon Ding 				MCU_RS_SHIFT, 0, false);
42720675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
42730675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
42740675a2a4SDamon Ding 				value, false);
42750675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42760675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
42770675a2a4SDamon Ding 		break;
42780675a2a4SDamon Ding 	case MCU_WRDATA:
42790675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42800675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
42810675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
42820675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
42830675a2a4SDamon Ding 				value, false);
42840675a2a4SDamon Ding 		break;
42850675a2a4SDamon Ding 	case MCU_SETBYPASS:
42860675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
42870675a2a4SDamon Ding 				MCU_BYPASS_SHIFT, value ? 1 : 0, false);
42880675a2a4SDamon Ding 		break;
42890675a2a4SDamon Ding 	default:
42900675a2a4SDamon Ding 		break;
42910675a2a4SDamon Ding 	}
42920675a2a4SDamon Ding 
42930675a2a4SDamon Ding 	/*
429458cf1fa3SDamon Ding 	 * 1.restore mcu data mode timing.
429558cf1fa3SDamon Ding 	 * 2.restore dclk rate to crtc_clock.
42960675a2a4SDamon Ding 	 */
42970675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && !value) {
42980675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
42990675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000);
43000675a2a4SDamon Ding 	}
43010675a2a4SDamon Ding 
43020675a2a4SDamon Ding 	return 0;
43030675a2a4SDamon Ding }
43040675a2a4SDamon Ding 
430534d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id)
430634d37ef0SDamon Ding {
4307a552a69cSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
4308a552a69cSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id];
430934d37ef0SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
431034d37ef0SDamon Ding 	bool pre_dither_down_en = false;
431134d37ef0SDamon Ding 
431234d37ef0SDamon Ding 	switch (bus_format) {
431334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB565_1X16:
431440608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
4315*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4316*e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4317*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4318*e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false);
431934d37ef0SDamon Ding 		pre_dither_down_en = true;
432034d37ef0SDamon Ding 		break;
432134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X18:
432234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
432334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
432440608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB666_3X6:
4325*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4326*e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4327*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4328*e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false);
432934d37ef0SDamon Ding 		pre_dither_down_en = true;
433034d37ef0SDamon Ding 		break;
433134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
433234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV8_1X24:
433334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
4334*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4335*e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
433634d37ef0SDamon Ding 		pre_dither_down_en = true;
433734d37ef0SDamon Ding 		break;
433834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV10_1X20:
433934d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV10_1X30:
434034d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
434134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB101010_1X30:
4342*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4343*e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
434434d37ef0SDamon Ding 		pre_dither_down_en = false;
434534d37ef0SDamon Ding 		break;
434634d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_3X8:
434734d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
434834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X24:
434934d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
435034d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
435134d37ef0SDamon Ding 	default:
4352*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4353*e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
435434d37ef0SDamon Ding 		pre_dither_down_en = true;
435534d37ef0SDamon Ding 		break;
435634d37ef0SDamon Ding 	}
435734d37ef0SDamon Ding 
4358*e2bdb3b3SDamon Ding 	if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0)
435934d37ef0SDamon Ding 		pre_dither_down_en = false;
436034d37ef0SDamon Ding 
4361a552a69cSDamon Ding 	if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) {
4362481ef52dSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
4363481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000);
4364481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100);
4365481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100);
4366481ef52dSDamon Ding 		}
4367481ef52dSDamon Ding 
4368a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4369a552a69cSDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, 0, false);
4370*e2bdb3b3SDamon Ding 		/* enable frc2.0 do 10->8 */
4371a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4372a552a69cSDamon Ding 				DITHER_DOWN_EN_SHIFT, 1, false);
4373*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4374*e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false);
4375a552a69cSDamon Ding 	} else {
437634d37ef0SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
437734d37ef0SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
4378*e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4379*e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false);
438034d37ef0SDamon Ding 	}
4381a552a69cSDamon Ding }
438234d37ef0SDamon Ding 
4383ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state)
4384ecc31b6eSAndy Yan {
4385ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
4386c2b1fe35SDamon Ding 	struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
4387ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
4388ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
4389ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
4390ecc31b6eSAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
4391ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
4392ecc31b6eSAndy Yan 	u16 htotal = mode->crtc_htotal;
4393ecc31b6eSAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
4394ecc31b6eSAndy Yan 	u16 hact_end = hact_st + hdisplay;
4395ecc31b6eSAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
4396ecc31b6eSAndy Yan 	u16 vtotal = mode->crtc_vtotal;
4397ecc31b6eSAndy Yan 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
4398ecc31b6eSAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
4399ecc31b6eSAndy Yan 	u16 vact_end = vact_st + vdisplay;
4400ecc31b6eSAndy Yan 	bool yuv_overlay = false;
4401ecc31b6eSAndy Yan 	u32 vp_offset = (cstate->crtc_id * 0x100);
440266724b9cSDamon Ding 	u32 line_flag_offset = (cstate->crtc_id * 4);
440366724b9cSDamon Ding 	u32 val, act_end;
440458cf1fa3SDamon Ding 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4405edfef528SDamon Ding 	u8 dclk_div_factor = 0;
4406a552a69cSDamon Ding 	u8 vp_dclk_div = 1;
4407ecc31b6eSAndy Yan 	char output_type_name[30] = {0};
4408d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4409ecc31b6eSAndy Yan 	char dclk_name[9];
4410d8e7f4a5SSandy Huang #endif
4411b890760eSAlgea Cao 	struct clk hdmi0_phy_pll;
4412b890760eSAlgea Cao 	struct clk hdmi1_phy_pll;
44135f1357a2SZhang Yubing 	struct clk hdmi_phy_pll;
44143e05a7b8SZhang Yubing 	struct udevice *disp_dev;
44155fa6e665SDamon Ding 	unsigned long dclk_rate = 0;
4416ecc31b6eSAndy Yan 	int ret;
4417ecc31b6eSAndy Yan 
4418ecc31b6eSAndy Yan 	printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
441971ac76f7SDamon Ding 	       mode->crtc_hdisplay, mode->vdisplay,
4420ecc31b6eSAndy Yan 	       mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
44214d64cedbSDamon Ding 	       mode->vrefresh,
44222264c88bSDamon Ding 	       rockchip_get_output_if_name(conn_state->output_if, output_type_name),
4423ecc31b6eSAndy Yan 	       cstate->crtc_id);
4424ecc31b6eSAndy Yan 
4425ee01dbb2SDamon Ding 	if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
4426ee01dbb2SDamon Ding 		cstate->splice_mode = true;
4427ee01dbb2SDamon Ding 		cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id;
4428ee01dbb2SDamon Ding 		if (!cstate->splice_crtc_id) {
4429ee01dbb2SDamon Ding 			printf("%s: Splice mode is unsupported by vp%d\n",
4430ee01dbb2SDamon Ding 			       __func__, cstate->crtc_id);
4431ee01dbb2SDamon Ding 			return -EINVAL;
4432ee01dbb2SDamon Ding 		}
4433b70b2d79SDamon Ding 
4434b70b2d79SDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK,
4435b70b2d79SDamon Ding 				PORT_MERGE_EN_SHIFT, 1, false);
4436ee01dbb2SDamon Ding 	}
4437ee01dbb2SDamon Ding 
4438cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4439cd6c85a9SDamon Ding 			RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4440cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4441cd6c85a9SDamon Ding 			RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4442cd6c85a9SDamon Ding 
4443ecc31b6eSAndy Yan 	vop2_initial(vop2, state);
4444ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3588)
4445ecc31b6eSAndy Yan 		dclk_rate = rk3588_vop2_if_cfg(state);
4446a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3576)
4447a552a69cSDamon Ding 		dclk_rate = rk3576_vop2_if_cfg(state);
44485fa6e665SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3568)
4449ecc31b6eSAndy Yan 		dclk_rate = rk3568_vop2_if_cfg(state);
4450452afb13SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3562)
4451452afb13SDamon Ding 		dclk_rate = rk3562_vop2_if_cfg(state);
4452a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3528)
4453a552a69cSDamon Ding 		dclk_rate = rk3528_vop2_if_cfg(state);
4454ecc31b6eSAndy Yan 
44555d2768f7SDamon Ding 	if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
44565d2768f7SDamon Ding 	     !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
44575d2768f7SDamon Ding 	    conn_state->output_if & VOP_OUTPUT_IF_BT656)
44587bdd0eb6SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
44597bdd0eb6SSandy Huang 
446065747de7SDamon Ding 	vop2_post_color_swap(state);
446110ee9f5bSAlgea Cao 
4462d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
4463d0408543SAndy Yan 			OUT_MODE_SHIFT, conn_state->output_mode, false);
4464d0408543SAndy Yan 
446534d37ef0SDamon Ding 	vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id);
446634d37ef0SDamon Ding 	if (cstate->splice_mode)
446734d37ef0SDamon Ding 		vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id);
4468d0408543SAndy Yan 
4469d0408543SAndy Yan 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
4470d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
4471d0408543SAndy Yan 			yuv_overlay, false);
4472d0408543SAndy Yan 
4473d0408543SAndy Yan 	cstate->yuv_overlay = yuv_overlay;
4474d0408543SAndy Yan 
4475d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
4476d0408543SAndy Yan 		    (htotal << 16) | hsync_len);
4477d0408543SAndy Yan 	val = hact_st << 16;
4478d0408543SAndy Yan 	val |= hact_end;
4479d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
4480d0408543SAndy Yan 	val = vact_st << 16;
4481d0408543SAndy Yan 	val |= vact_end;
4482d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
4483d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
4484d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
4485d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
4486d0408543SAndy Yan 
4487d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
4488d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
4489d0408543SAndy Yan 			    val);
4490d0408543SAndy Yan 
4491d0408543SAndy Yan 		val = vtotal << 16 | (vtotal + vsync_len);
4492d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
4493d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4494d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 1, false);
4495d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
44967a20be36SSandy Huang 				DSP_FILED_POL, 1, false);
44977a20be36SSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4498d0408543SAndy Yan 				P2I_EN_SHIFT, 1, false);
4499d0408543SAndy Yan 		vtotal += vtotal + 1;
450066724b9cSDamon Ding 		act_end = vact_end_f1;
4501d0408543SAndy Yan 	} else {
4502d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4503d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 0, false);
4504d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4505d0408543SAndy Yan 				P2I_EN_SHIFT, 0, false);
450666724b9cSDamon Ding 		act_end = vact_end;
4507d0408543SAndy Yan 	}
4508d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
4509d0408543SAndy Yan 		    (vtotal << 16) | vsync_len);
451067be2ffcSDamon Ding 
4511a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 ||
4512a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3562 ||
4513a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3568) {
451467be2ffcSDamon Ding 		if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
451567be2ffcSDamon Ding 		conn_state->output_if & VOP_OUTPUT_IF_BT656)
4516d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
451767be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 1, false);
451867be2ffcSDamon Ding 		else
451967be2ffcSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
452067be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 0, false);
452110ee9f5bSAlgea Cao 
452210ee9f5bSAlgea Cao 		if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
452363cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
452463cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
452510ee9f5bSAlgea Cao 		else
452663cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
452763cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
4528a552a69cSDamon Ding 	}
452910ee9f5bSAlgea Cao 
4530ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
4531ee01dbb2SDamon Ding 			OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false);
4532ee01dbb2SDamon Ding 
453310ee9f5bSAlgea Cao 	if (yuv_overlay)
453410ee9f5bSAlgea Cao 		val = 0x20010200;
453510ee9f5bSAlgea Cao 	else
453610ee9f5bSAlgea Cao 		val = 0;
453710ee9f5bSAlgea Cao 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
4538b70b2d79SDamon Ding 	if (cstate->splice_mode) {
4539ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
4540ee01dbb2SDamon Ding 				OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id,
4541ee01dbb2SDamon Ding 				yuv_overlay, false);
4542ee01dbb2SDamon Ding 		vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val);
4543ee01dbb2SDamon Ding 	}
454410ee9f5bSAlgea Cao 
454510ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
454610ee9f5bSAlgea Cao 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
4547d0408543SAndy Yan 
4548c2b1fe35SDamon Ding 	if (vp->xmirror_en)
4549c2b1fe35SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4550c2b1fe35SDamon Ding 				DSP_X_MIR_EN_SHIFT, 1, false);
4551c2b1fe35SDamon Ding 
4552ac500a1fSSandy Huang 	vop2_tv_config_update(state, vop2);
4553d0408543SAndy Yan 	vop2_post_config(state, vop2);
45546027c871SZhang Yubing 	if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
45556027c871SZhang Yubing 		vop3_post_config(state, vop2);
4556d0408543SAndy Yan 
455712ee5af0SDamon Ding 	if (cstate->dsc_enable) {
455812ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
45591ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL);
45601ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL);
456112ee5af0SDamon Ding 		} else {
45621ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL);
456312ee5af0SDamon Ding 		}
456412ee5af0SDamon Ding 	}
456512ee5af0SDamon Ding 
4566d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4567ecc31b6eSAndy Yan 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
45680675a2a4SDamon Ding 	ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk);
4569b890760eSAlgea Cao 	if (ret) {
4570b890760eSAlgea Cao 		printf("%s: Failed to get dclk ret=%d\n", __func__, ret);
4571b890760eSAlgea Cao 		return ret;
4572b890760eSAlgea Cao 	}
4573d8e7f4a5SSandy Huang #endif
4574b890760eSAlgea Cao 
45753e05a7b8SZhang Yubing 	ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev);
45763e05a7b8SZhang Yubing 	if (!ret) {
45773e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll);
45783e05a7b8SZhang Yubing 		if (ret)
45795e85f4a7SZhang Yubing 			debug("%s: hdmi0_phy_pll may not define\n", __func__);
45803e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll);
45813e05a7b8SZhang Yubing 		if (ret)
45825e85f4a7SZhang Yubing 			debug("%s: hdmi1_phy_pll may not define\n", __func__);
45833e05a7b8SZhang Yubing 	} else {
4584b890760eSAlgea Cao 		hdmi0_phy_pll.dev = NULL;
4585545a0218SAlgea Cao 		hdmi1_phy_pll.dev = NULL;
45865e85f4a7SZhang Yubing 		debug("%s: Faile to find display-subsystem node\n", __func__);
4587b890760eSAlgea Cao 	}
4588b890760eSAlgea Cao 
4589ebbd144cSAlgea Cao 	if (vop2->version == VOP_VERSION_RK3528) {
4590ebbd144cSAlgea Cao 		struct ofnode_phandle_args args;
4591ebbd144cSAlgea Cao 
4592ebbd144cSAlgea Cao 		ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents",
4593ebbd144cSAlgea Cao 						 "#clock-cells", 0, 0, &args);
4594ebbd144cSAlgea Cao 		if (!ret) {
4595ebbd144cSAlgea Cao 			ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev);
4596ebbd144cSAlgea Cao 			if (ret) {
4597ebbd144cSAlgea Cao 				debug("warn: can't get clk device\n");
4598ebbd144cSAlgea Cao 				return ret;
4599ebbd144cSAlgea Cao 			}
4600ebbd144cSAlgea Cao 		} else {
4601ebbd144cSAlgea Cao 			debug("assigned-clock-parents's node not define\n");
4602ebbd144cSAlgea Cao 		}
4603ebbd144cSAlgea Cao 	}
4604ebbd144cSAlgea Cao 
46050a1fb152SZhang Yubing 	if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) {
4606b890760eSAlgea Cao 		if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0)
46070675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll);
4608b890760eSAlgea Cao 		else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1)
46090675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll);
4610b890760eSAlgea Cao 
4611b890760eSAlgea Cao 		/*
4612b890760eSAlgea Cao 		 * uboot clk driver won't set dclk parent's rate when use
4613b890760eSAlgea Cao 		 * hdmi phypll as dclk source.
4614b890760eSAlgea Cao 		 * So set dclk rate is meaningless. Set hdmi phypll rate
4615b890760eSAlgea Cao 		 * directly.
4616b890760eSAlgea Cao 		 */
46175f1357a2SZhang Yubing 		if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) {
4618b890760eSAlgea Cao 			ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate * 1000);
46195f1357a2SZhang Yubing 		} else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) {
4620b890760eSAlgea Cao 			ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate * 1000);
46215f1357a2SZhang Yubing 		} else {
4622a552a69cSDamon Ding 			if (vop2->version == VOP_VERSION_RK3576)
4623a552a69cSDamon Ding 				vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div;
46247efea85dSDamon Ding 			if (is_extend_pll(state, &hdmi_phy_pll.dev)) {
46255f1357a2SZhang Yubing 				ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000);
46267efea85dSDamon Ding 			} else {
4627d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4628a552a69cSDamon Ding 				ret = vop2_clk_set_rate(&cstate->dclk,
4629a552a69cSDamon Ding 							dclk_rate / vp_dclk_div * 1000);
4630d8e7f4a5SSandy Huang #else
4631d8e7f4a5SSandy Huang 				if (vop2->version == VOP_VERSION_RK3528) {
4632d8e7f4a5SSandy Huang 					void *cru_base = (void *)RK3528_CRU_BASE;
4633d8e7f4a5SSandy Huang 
4634d8e7f4a5SSandy Huang 					/* dclk src switch to hdmiphy pll */
4635d8e7f4a5SSandy Huang 					writel((BIT(0) << 16) | BIT(0), cru_base + 0x450);
4636d8e7f4a5SSandy Huang 					rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000);
4637d8e7f4a5SSandy Huang 					ret = dclk_rate * 1000;
4638d8e7f4a5SSandy Huang 				}
4639d8e7f4a5SSandy Huang #endif
46405f1357a2SZhang Yubing 			}
46417efea85dSDamon Ding 		}
4642631ee99aSZhang Yubing 	} else {
46435f1357a2SZhang Yubing 		if (is_extend_pll(state, &hdmi_phy_pll.dev))
46445f1357a2SZhang Yubing 			ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000);
46455f1357a2SZhang Yubing 		else
46460675a2a4SDamon Ding 			ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate * 1000);
4647edfef528SDamon Ding 	}
464863638f32SDamon Ding 
464963638f32SDamon Ding 	if (IS_ERR_VALUE(ret)) {
465063638f32SDamon Ding 		printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
465163638f32SDamon Ding 		       __func__, cstate->crtc_id, dclk_rate, ret);
465263638f32SDamon Ding 		return ret;
465363638f32SDamon Ding 	} else {
46544d64cedbSDamon Ding 		if (cstate->mcu_timing.mcu_pix_total) {
46554d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) / 1000;
46564d64cedbSDamon Ding 		} else {
46579655ad2fSDamon Ding 			dclk_div_factor = mode->crtc_clock / dclk_rate;
46584d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000;
46594d64cedbSDamon Ding 		}
4660edfef528SDamon Ding 		printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock);
4661631ee99aSZhang Yubing 	}
4662ecc31b6eSAndy Yan 
466366724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
4664e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false);
466566724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
4666e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false);
466766724b9cSDamon Ding 
466858cf1fa3SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total) {
466958cf1fa3SDamon Ding 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
467058cf1fa3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
467158cf1fa3SDamon Ding 				STANDBY_EN_SHIFT, 0, false);
46720675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
467358cf1fa3SDamon Ding 	}
46740675a2a4SDamon Ding 
4675d0408543SAndy Yan 	return 0;
4676d0408543SAndy Yan }
4677d0408543SAndy Yan 
4678ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
46793e39a5a1SSandy Huang 			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
46803e39a5a1SSandy Huang 			     uint32_t dst_h)
46813e39a5a1SSandy Huang {
46823e39a5a1SSandy Huang 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
46833e39a5a1SSandy Huang 	uint16_t hscl_filter_mode, vscl_filter_mode;
46845fa6e665SDamon Ding 	uint8_t xgt2 = 0, xgt4 = 0;
46855fa6e665SDamon Ding 	uint8_t ygt2 = 0, ygt4 = 0;
46863e39a5a1SSandy Huang 	uint32_t xfac = 0, yfac = 0;
4687ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
46885fa6e665SDamon Ding 	bool xgt_en = false;
46895fa6e665SDamon Ding 	bool xavg_en = false;
46903e39a5a1SSandy Huang 
46915fa6e665SDamon Ding 	if (is_vop3(vop2)) {
4692a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) {
4693a552a69cSDamon Ding 			if (src_w >= (8 * dst_w)) {
4694a552a69cSDamon Ding 				xgt4 = 1;
4695a552a69cSDamon Ding 				src_w >>= 2;
4696a552a69cSDamon Ding 			} else if (src_w >= (4 * dst_w)) {
4697a552a69cSDamon Ding 				xgt2 = 1;
4698a552a69cSDamon Ding 				src_w >>= 1;
4699a552a69cSDamon Ding 			}
4700a552a69cSDamon Ding 		} else {
47015fa6e665SDamon Ding 			if (src_w >= (4 * dst_w)) {
47025fa6e665SDamon Ding 				xgt4 = 1;
47035fa6e665SDamon Ding 				src_w >>= 2;
47045fa6e665SDamon Ding 			} else if (src_w >= (2 * dst_w)) {
47055fa6e665SDamon Ding 				xgt2 = 1;
47065fa6e665SDamon Ding 				src_w >>= 1;
47075fa6e665SDamon Ding 			}
47085fa6e665SDamon Ding 		}
4709a552a69cSDamon Ding 	}
47103e39a5a1SSandy Huang 
4711183eb252SDamon Ding 	/**
4712183eb252SDamon Ding 	 * The rk3528 is processed as 2 pixel/cycle,
4713183eb252SDamon Ding 	 * so ygt2/ygt4 needs to be triggered in advance to improve performance
4714183eb252SDamon Ding 	 * when src_w is bigger than 1920.
4715183eb252SDamon Ding 	 * dst_h / src_h is at [1, 0.65)     ygt2=0; ygt4=0;
4716183eb252SDamon Ding 	 * dst_h / src_h is at [0.65, 0.35)  ygt2=1; ygt4=0;
4717183eb252SDamon Ding 	 * dst_h / src_h is at [0.35, 0)     ygt2=0; ygt4=1;
4718183eb252SDamon Ding 	 */
4719183eb252SDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
4720183eb252SDamon Ding 		if (src_h >= (100 * dst_h / 35)) {
4721183eb252SDamon Ding 			ygt4 = 1;
4722183eb252SDamon Ding 			src_h >>= 2;
4723183eb252SDamon Ding 		} else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) {
4724183eb252SDamon Ding 			ygt2 = 1;
4725183eb252SDamon Ding 			src_h >>= 1;
4726183eb252SDamon Ding 		}
4727183eb252SDamon Ding 	} else {
4728a552a69cSDamon Ding 		if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) {
4729a552a69cSDamon Ding 			if (src_h >= (8 * dst_h)) {
4730a552a69cSDamon Ding 				ygt4 = 1;
4731a552a69cSDamon Ding 				src_h >>= 2;
4732a552a69cSDamon Ding 			} else if (src_h >= (4 * dst_h)) {
4733a552a69cSDamon Ding 				ygt2 = 1;
4734a552a69cSDamon Ding 				src_h >>= 1;
4735a552a69cSDamon Ding 			}
4736a552a69cSDamon Ding 		} else {
47375fa6e665SDamon Ding 			if (src_h >= (4 * dst_h)) {
47385fa6e665SDamon Ding 				ygt4 = 1;
47393e39a5a1SSandy Huang 				src_h >>= 2;
47405fa6e665SDamon Ding 			} else if (src_h >= (2 * dst_h)) {
47415fa6e665SDamon Ding 				ygt2 = 1;
47423e39a5a1SSandy Huang 				src_h >>= 1;
47435fa6e665SDamon Ding 			}
4744183eb252SDamon Ding 		}
4745a552a69cSDamon Ding 	}
47463e39a5a1SSandy Huang 
47473e39a5a1SSandy Huang 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
47483e39a5a1SSandy Huang 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
47493e39a5a1SSandy Huang 
47503e39a5a1SSandy Huang 	if (yrgb_hor_scl_mode == SCALE_UP)
47515fa6e665SDamon Ding 		hscl_filter_mode = win->hsu_filter_mode;
47523e39a5a1SSandy Huang 	else
47535fa6e665SDamon Ding 		hscl_filter_mode = win->hsd_filter_mode;
47543e39a5a1SSandy Huang 
47553e39a5a1SSandy Huang 	if (yrgb_ver_scl_mode == SCALE_UP)
47565fa6e665SDamon Ding 		vscl_filter_mode = win->vsu_filter_mode;
47573e39a5a1SSandy Huang 	else
47585fa6e665SDamon Ding 		vscl_filter_mode = win->vsd_filter_mode;
47593e39a5a1SSandy Huang 
47603e39a5a1SSandy Huang 	/*
47613e39a5a1SSandy Huang 	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
47623e39a5a1SSandy Huang 	 * at scale down mode
47633e39a5a1SSandy Huang 	 */
47645fa6e665SDamon Ding 	if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) {
47653e39a5a1SSandy Huang 		printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
47663e39a5a1SSandy Huang 		dst_w += 1;
47673e39a5a1SSandy Huang 	}
47683e39a5a1SSandy Huang 
47695fa6e665SDamon Ding 	if (is_vop3(vop2)) {
47705fa6e665SDamon Ding 		xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true);
47715fa6e665SDamon Ding 		yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false);
47725fa6e665SDamon Ding 
47735fa6e665SDamon Ding 		if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG)
47745fa6e665SDamon Ding 			xavg_en = xgt2 || xgt4;
47755fa6e665SDamon Ding 		else
47765fa6e665SDamon Ding 			xgt_en = xgt2 || xgt4;
4777a552a69cSDamon Ding 
4778a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
4779a552a69cSDamon Ding 			bool zme_dering_en = false;
4780a552a69cSDamon Ding 
4781a552a69cSDamon Ding 			if ((yrgb_hor_scl_mode == SCALE_UP &&
4782a552a69cSDamon Ding 			     hscl_filter_mode == VOP2_SCALE_UP_ZME) ||
4783a552a69cSDamon Ding 			    (yrgb_ver_scl_mode == SCALE_UP &&
4784a552a69cSDamon Ding 			     vscl_filter_mode == VOP2_SCALE_UP_ZME))
4785a552a69cSDamon Ding 				zme_dering_en = true;
4786a552a69cSDamon Ding 
4787a552a69cSDamon Ding 			/* Recommended configuration from the algorithm */
4788a552a69cSDamon Ding 			vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset,
4789a552a69cSDamon Ding 				    0x04100d10);
4790a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset,
4791a552a69cSDamon Ding 					EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false);
4792a552a69cSDamon Ding 		}
47935fa6e665SDamon Ding 	} else {
47943e39a5a1SSandy Huang 		xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
47953e39a5a1SSandy Huang 		yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
47965fa6e665SDamon Ding 	}
4797ecc31b6eSAndy Yan 
4798ecc31b6eSAndy Yan 	if (win->type == CLUSTER_LAYER) {
4799ecc31b6eSAndy Yan 		vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
4800ecc31b6eSAndy Yan 			    yfac << 16 | xfac);
4801ecc31b6eSAndy Yan 
48025fa6e665SDamon Ding 		if (is_vop3(vop2)) {
4803ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48045fa6e665SDamon Ding 					EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false);
4805ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48065fa6e665SDamon Ding 					EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false);
48075fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48085fa6e665SDamon Ding 					XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
4809ecc31b6eSAndy Yan 
4810ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48115fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT,
48125fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
4813ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48145fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT,
48155fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
48165fa6e665SDamon Ding 		} else {
48175fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48185fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT,
48195fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
48205fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48215fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT,
48225fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
48235fa6e665SDamon Ding 		}
4824ecc31b6eSAndy Yan 
48255fa6e665SDamon Ding 		if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
48265fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48275fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false);
48285fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48295fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false);
48305fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48315fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false);
48325fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48335fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false);
48345fa6e665SDamon Ding 		} else {
48355fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48365fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false);
48375fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48385fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false);
48395fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48405fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false);
48415fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
48425fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false);
48435fa6e665SDamon Ding 		}
4844ecc31b6eSAndy Yan 	} else {
48453e39a5a1SSandy Huang 		vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
48463e39a5a1SSandy Huang 			    yfac << 16 | xfac);
48473e39a5a1SSandy Huang 
48485fa6e665SDamon Ding 		if (is_vop3(vop2)) {
484934a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
48505fa6e665SDamon Ding 					EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false);
485134a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
48525fa6e665SDamon Ding 					EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false);
48535fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
48545fa6e665SDamon Ding 					XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
48555fa6e665SDamon Ding 		}
48565fa6e665SDamon Ding 
48575fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
48585fa6e665SDamon Ding 				YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false);
48595fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
48605fa6e665SDamon Ding 				YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false);
48613e39a5a1SSandy Huang 
48623e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
48633e39a5a1SSandy Huang 				YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
48643e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
48653e39a5a1SSandy Huang 				YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
48663e39a5a1SSandy Huang 
48673e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
48683e39a5a1SSandy Huang 				YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
48693e39a5a1SSandy Huang 				hscl_filter_mode, false);
48703e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
48713e39a5a1SSandy Huang 				YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
48723e39a5a1SSandy Huang 				vscl_filter_mode, false);
48733e39a5a1SSandy Huang 	}
4874ecc31b6eSAndy Yan }
48753e39a5a1SSandy Huang 
4876a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win)
4877a33b790fSDamon Ding {
4878a33b790fSDamon Ding 	u32 win_offset = win->reg_offset;
4879a33b790fSDamon Ding 
4880a33b790fSDamon Ding 	if (win->type == CLUSTER_LAYER) {
4881a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK,
4882a33b790fSDamon Ding 				CLUSTER_AXI_ID_SHIFT, win->axi_id, false);
4883a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK,
4884a33b790fSDamon Ding 				CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
4885a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK,
4886a33b790fSDamon Ding 				CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
4887a33b790fSDamon Ding 	} else {
4888a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK,
4889a33b790fSDamon Ding 				ESMART_AXI_ID_SHIFT, win->axi_id, false);
4890a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK,
4891a33b790fSDamon Ding 				ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
4892a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK,
4893a33b790fSDamon Ding 				ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
4894a33b790fSDamon Ding 	}
4895a33b790fSDamon Ding }
4896a33b790fSDamon Ding 
4897840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format)
4898840bf541SDamon Ding {
4899840bf541SDamon Ding 	switch (format) {
4900840bf541SDamon Ding 	case ROCKCHIP_FMT_RGB565:
4901840bf541SDamon Ding 		return true;
4902840bf541SDamon Ding 	default:
4903840bf541SDamon Ding 		return false;
4904840bf541SDamon Ding 	}
4905840bf541SDamon Ding }
4906840bf541SDamon Ding 
49071c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win)
49081c9572c7SDamon Ding {
49091c9572c7SDamon Ding 	return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR);
49101c9572c7SDamon Ding }
49111c9572c7SDamon Ding 
49121c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
4913d0408543SAndy Yan {
4914d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
4915d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
4916d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
4917d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
4918ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
4919ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
4920ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
4921ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
4922ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
4923ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
4924d0408543SAndy Yan 	int xvir = cstate->xvir;
4925d0408543SAndy Yan 	int y_mirror = 0;
492610ee9f5bSAlgea Cao 	int csc_mode;
4927ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
4928ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
4929ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
4930ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
4931ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
4932ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4933840bf541SDamon Ding 	bool dither_up;
4934d0408543SAndy Yan 
4935ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
4936ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
4937ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
4938ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
4939ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
4940ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
4941ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
4942ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
4943ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
4944ee01dbb2SDamon Ding 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
4945ee01dbb2SDamon Ding 	}
4946ee01dbb2SDamon Ding 
4947ecc31b6eSAndy Yan 	act_info = (src_h - 1) << 16;
4948ecc31b6eSAndy Yan 	act_info |= (src_w - 1) & 0xffff;
4949ecc31b6eSAndy Yan 
4950ecc31b6eSAndy Yan 	dsp_info = (crtc_h - 1) << 16;
4951ecc31b6eSAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
4952ecc31b6eSAndy Yan 
4953ecc31b6eSAndy Yan 	dsp_stx = crtc_x;
4954ecc31b6eSAndy Yan 	dsp_sty = crtc_y;
4955ecc31b6eSAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
4956ecc31b6eSAndy Yan 
4957ecc31b6eSAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
4958ecc31b6eSAndy Yan 		y_mirror = 1;
4959ecc31b6eSAndy Yan 	else
4960ecc31b6eSAndy Yan 		y_mirror = 0;
4961ecc31b6eSAndy Yan 
4962ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
4963ecc31b6eSAndy Yan 
4964a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
4965a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
4966a33b790fSDamon Ding 
4967ecc31b6eSAndy Yan 	if (y_mirror)
4968ecc31b6eSAndy Yan 		printf("WARN: y mirror is unsupported by cluster window\n");
4969ecc31b6eSAndy Yan 
4970a552a69cSDamon Ding 	if (is_vop3(vop2))
4971a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset,
4972a552a69cSDamon Ding 				CLUSTER_PORT_SEL_SHIFT, CLUSTER_PORT_SEL_SHIFT,
4973a552a69cSDamon Ding 				cstate->crtc_id, false);
4974a552a69cSDamon Ding 
4975a59754e1SDamon Ding 	/* rk3588 should set half_blocK_en to 1 in line and tile mode */
4976a59754e1SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588)
4977a59754e1SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset,
4978a59754e1SDamon Ding 				EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false);
4979a59754e1SDamon Ding 
4980ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
4981ecc31b6eSAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
4982ecc31b6eSAndy Yan 			false);
4983ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
4984ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset,
4985ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
4986ecc31b6eSAndy Yan 
4987ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
4988ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
4989ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
4990ecc31b6eSAndy Yan 
4991ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
4992ecc31b6eSAndy Yan 
4993df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
4994df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
4995ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
4996ecc31b6eSAndy Yan 			CLUSTER_RGB2YUV_EN_SHIFT,
4997ecc31b6eSAndy Yan 			is_yuv_output(conn_state->bus_format), false);
4998ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
4999ecc31b6eSAndy Yan 			CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
5000840bf541SDamon Ding 
5001840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5002840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5003840bf541SDamon Ding 			CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false);
5004840bf541SDamon Ding 
5005ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
5006ecc31b6eSAndy Yan 
5007ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
50081c9572c7SDamon Ding 
50091c9572c7SDamon Ding 	return 0;
5010d0408543SAndy Yan }
5011d0408543SAndy Yan 
50121c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
5013ecc31b6eSAndy Yan {
5014ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5015ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
5016ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
5017ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
5018ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
5019ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
5020ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
5021ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
5022ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
5023ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
5024ecc31b6eSAndy Yan 	int xvir = cstate->xvir;
5025ecc31b6eSAndy Yan 	int y_mirror = 0;
5026ecc31b6eSAndy Yan 	int csc_mode;
5027ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5028ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
5029ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
5030ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
5031ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
5032ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
50331c9572c7SDamon Ding 	u32 val;
5034840bf541SDamon Ding 	bool dither_up;
5035ecc31b6eSAndy Yan 
50361c9572c7SDamon Ding 	if (vop2_is_mirror_win(win)) {
50371c9572c7SDamon Ding 		struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id);
50381c9572c7SDamon Ding 
50391c9572c7SDamon Ding 		if (!source_win) {
50401c9572c7SDamon Ding 			printf("invalid source win id %d\n", win->source_win_id);
50411c9572c7SDamon Ding 			return -ENODEV;
50421c9572c7SDamon Ding 		}
50431c9572c7SDamon Ding 
50441c9572c7SDamon Ding 		val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset);
50451c9572c7SDamon Ding 		if (!(val & BIT(WIN_EN_SHIFT))) {
50461c9572c7SDamon Ding 			printf("WARN: the source win should be enabled before mirror win\n");
50471c9572c7SDamon Ding 			return -EAGAIN;
50481c9572c7SDamon Ding 		}
50491c9572c7SDamon Ding 	}
50501c9572c7SDamon Ding 
5051ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
5052ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
5053ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
5054ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
5055ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
5056ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
5057ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
5058ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5059ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5060ee01dbb2SDamon Ding 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5061ee01dbb2SDamon Ding 	}
5062ee01dbb2SDamon Ding 
506374bd8269SSandy Huang 	/*
506474bd8269SSandy Huang 	 * This is workaround solution for IC design:
506574bd8269SSandy Huang 	 * esmart can't support scale down when actual_w % 16 == 1.
506674bd8269SSandy Huang 	 */
506774bd8269SSandy Huang 	if (src_w > crtc_w && (src_w & 0xf) == 1) {
506874bd8269SSandy Huang 		printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
506974bd8269SSandy Huang 		src_w -= 1;
507074bd8269SSandy Huang 	}
507174bd8269SSandy Huang 
5072d0408543SAndy Yan 	act_info = (src_h - 1) << 16;
5073d0408543SAndy Yan 	act_info |= (src_w - 1) & 0xffff;
5074d0408543SAndy Yan 
5075d0408543SAndy Yan 	dsp_info = (crtc_h - 1) << 16;
5076d0408543SAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
5077d0408543SAndy Yan 
5078d0408543SAndy Yan 	dsp_stx = crtc_x;
5079d0408543SAndy Yan 	dsp_sty = crtc_y;
5080d0408543SAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5081d0408543SAndy Yan 
5082d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5083d0408543SAndy Yan 		y_mirror = 1;
5084d0408543SAndy Yan 	else
5085d0408543SAndy Yan 		y_mirror = 0;
5086d0408543SAndy Yan 
5087a552a69cSDamon Ding 	if (is_vop3(vop2)) {
5088a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset,
5089a552a69cSDamon Ding 				ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT,
5090a552a69cSDamon Ding 				win->scale_engine_num, false);
5091a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5092a552a69cSDamon Ding 				ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5093a552a69cSDamon Ding 				cstate->crtc_id, false);
5094a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM + win_offset,
5095a552a69cSDamon Ding 				ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT,
5096a552a69cSDamon Ding 				0, false);
5097a552a69cSDamon Ding 
5098a552a69cSDamon Ding 		/* Merge esmart1/3 from vp1 post to vp0 */
5099a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 &&
5100a552a69cSDamon Ding 		    (win->phys_id == ROCKCHIP_VOP2_ESMART1 ||
5101a552a69cSDamon Ding 		     win->phys_id == ROCKCHIP_VOP2_ESMART3))
5102a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5103a552a69cSDamon Ding 					ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5104a552a69cSDamon Ding 					1, false);
5105a552a69cSDamon Ding 	}
51065fa6e665SDamon Ding 
5107ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
51083e39a5a1SSandy Huang 
5109a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
5110a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
5111a33b790fSDamon Ding 
5112d0408543SAndy Yan 	if (y_mirror)
5113d0408543SAndy Yan 		cstate->dma_addr += (src_h - 1) * xvir * 4;
5114d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
5115d0408543SAndy Yan 			YMIRROR_EN_SHIFT, y_mirror, false);
5116d0408543SAndy Yan 
5117d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5118d0408543SAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5119d0408543SAndy Yan 			false);
5120a552a69cSDamon Ding 
5121a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
5122a552a69cSDamon Ding 		vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00);
5123a552a69cSDamon Ding 
5124d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
5125d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
5126ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
5127d0408543SAndy Yan 
5128d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
5129d0408543SAndy Yan 		    act_info);
5130d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
5131d0408543SAndy Yan 		    dsp_info);
5132d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
5133d0408543SAndy Yan 
5134d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5135d0408543SAndy Yan 			WIN_EN_SHIFT, 1, false);
5136d0408543SAndy Yan 
5137df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5138df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
513910ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
514010ee9f5bSAlgea Cao 			RGB2YUV_EN_SHIFT,
514110ee9f5bSAlgea Cao 			is_yuv_output(conn_state->bus_format), false);
514210ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
514310ee9f5bSAlgea Cao 			CSC_MODE_SHIFT, csc_mode, false);
514410ee9f5bSAlgea Cao 
5145840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5146840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5147840bf541SDamon Ding 			REGION0_DITHER_UP_EN_SHIFT, dither_up, false);
5148840bf541SDamon Ding 
5149d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
51501c9572c7SDamon Ding 
51511c9572c7SDamon Ding 	return 0;
5152ecc31b6eSAndy Yan }
5153ecc31b6eSAndy Yan 
5154ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state)
5155ee01dbb2SDamon Ding {
5156ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5157ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
5158ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
5159ee01dbb2SDamon Ding 	struct display_rect *src_rect = &cstate->src_rect;
5160ee01dbb2SDamon Ding 	struct display_rect *dst_rect = &cstate->crtc_rect;
5161ee01dbb2SDamon Ding 	struct display_rect left_src, left_dst, right_src, right_dst;
5162ee01dbb2SDamon Ding 	u16 half_hdisplay = mode->crtc_hdisplay >> 1;
5163ee01dbb2SDamon Ding 	int left_src_w, left_dst_w, right_dst_w;
5164ee01dbb2SDamon Ding 
5165ee01dbb2SDamon Ding 	left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x;
5166ee01dbb2SDamon Ding 	if (left_dst_w < 0)
5167ee01dbb2SDamon Ding 		left_dst_w = 0;
5168ee01dbb2SDamon Ding 	right_dst_w = dst_rect->w - left_dst_w;
5169ee01dbb2SDamon Ding 
5170ee01dbb2SDamon Ding 	if (!right_dst_w)
5171ee01dbb2SDamon Ding 		left_src_w = src_rect->w;
5172ee01dbb2SDamon Ding 	else
51730df0fd39SSandy Huang 		left_src_w = src_rect->x + src_rect->w - src_rect->w / 2;
5174ee01dbb2SDamon Ding 
5175ee01dbb2SDamon Ding 	left_src.x = src_rect->x;
5176ee01dbb2SDamon Ding 	left_src.w = left_src_w;
5177ee01dbb2SDamon Ding 	left_dst.x = dst_rect->x;
5178ee01dbb2SDamon Ding 	left_dst.w = left_dst_w;
5179ee01dbb2SDamon Ding 	right_src.x = left_src.x + left_src.w;
5180ee01dbb2SDamon Ding 	right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w;
5181ee01dbb2SDamon Ding 	right_dst.x = dst_rect->x + left_dst_w - half_hdisplay;
5182ee01dbb2SDamon Ding 	right_dst.w = right_dst_w;
5183ee01dbb2SDamon Ding 
5184ee01dbb2SDamon Ding 	left_src.y = src_rect->y;
5185ee01dbb2SDamon Ding 	left_src.h = src_rect->h;
5186ee01dbb2SDamon Ding 	left_dst.y = dst_rect->y;
5187ee01dbb2SDamon Ding 	left_dst.h = dst_rect->h;
5188ee01dbb2SDamon Ding 	right_src.y = src_rect->y;
5189ee01dbb2SDamon Ding 	right_src.h = src_rect->h;
5190ee01dbb2SDamon Ding 	right_dst.y = dst_rect->y;
5191ee01dbb2SDamon Ding 	right_dst.h = dst_rect->h;
5192ee01dbb2SDamon Ding 
5193ee01dbb2SDamon Ding 	memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect));
5194ee01dbb2SDamon Ding 	memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect));
5195ee01dbb2SDamon Ding 	memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect));
5196ee01dbb2SDamon Ding 	memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect));
5197ee01dbb2SDamon Ding }
5198ee01dbb2SDamon Ding 
5199ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state)
5200ecc31b6eSAndy Yan {
5201ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5202ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
5203ecc31b6eSAndy Yan 	struct vop2_win_data *win_data;
5204ee01dbb2SDamon Ding 	struct vop2_win_data *splice_win_data;
5205ecc31b6eSAndy Yan 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
5206ecc31b6eSAndy Yan 	char plane_name[10] = {0};
52071c9572c7SDamon Ding 	int ret;
5208ecc31b6eSAndy Yan 
5209ee01dbb2SDamon Ding 	if (cstate->crtc_rect.w > cstate->max_output.width) {
5210ecc31b6eSAndy Yan 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
5211ee01dbb2SDamon Ding 		       cstate->crtc_rect.w, cstate->max_output.width);
5212ecc31b6eSAndy Yan 		return -EINVAL;
5213ecc31b6eSAndy Yan 	}
5214ecc31b6eSAndy Yan 
5215ecc31b6eSAndy Yan 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
5216ecc31b6eSAndy Yan 	if (!win_data) {
5217ecc31b6eSAndy Yan 		printf("invalid win id %d\n", primary_plane_id);
5218ecc31b6eSAndy Yan 		return -ENODEV;
5219ecc31b6eSAndy Yan 	}
5220ecc31b6eSAndy Yan 
52215fa6e665SDamon Ding 	/* ignore some plane register according vop3 esmart lb mode */
52225fa6e665SDamon Ding 	if (vop3_ignore_plane(vop2, win_data))
52235fa6e665SDamon Ding 		return -EACCES;
52245fa6e665SDamon Ding 
5225a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) {
5226b6ba80b4SDamon Ding 		if (vop2_power_domain_on(vop2, win_data->pd_id))
5227b6ba80b4SDamon Ding 			printf("open vp%d plane pd fail\n", cstate->crtc_id);
5228b6ba80b4SDamon Ding 	}
5229b6ba80b4SDamon Ding 
5230ee01dbb2SDamon Ding 	if (cstate->splice_mode) {
5231ee01dbb2SDamon Ding 		if (win_data->splice_win_id) {
5232ee01dbb2SDamon Ding 			splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id);
5233ee01dbb2SDamon Ding 			splice_win_data->splice_mode_right = true;
5234b6ba80b4SDamon Ding 
5235b6ba80b4SDamon Ding 			if (vop2_power_domain_on(vop2, splice_win_data->pd_id))
5236b6ba80b4SDamon Ding 				printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id);
5237b6ba80b4SDamon Ding 
5238ee01dbb2SDamon Ding 			vop2_calc_display_rect_for_splice(state);
5239ee01dbb2SDamon Ding 			if (win_data->type == CLUSTER_LAYER)
5240ee01dbb2SDamon Ding 				vop2_set_cluster_win(state, splice_win_data);
5241ee01dbb2SDamon Ding 			else
5242ee01dbb2SDamon Ding 				vop2_set_smart_win(state, splice_win_data);
5243ee01dbb2SDamon Ding 		} else {
5244ee01dbb2SDamon Ding 			printf("ERROR: splice mode is unsupported by plane %s\n",
5245ee01dbb2SDamon Ding 			       get_plane_name(primary_plane_id, plane_name));
5246ee01dbb2SDamon Ding 			return -EINVAL;
5247ee01dbb2SDamon Ding 		}
5248ee01dbb2SDamon Ding 	}
5249ee01dbb2SDamon Ding 
5250ecc31b6eSAndy Yan 	if (win_data->type == CLUSTER_LAYER)
52511c9572c7SDamon Ding 		ret = vop2_set_cluster_win(state, win_data);
5252ecc31b6eSAndy Yan 	else
52531c9572c7SDamon Ding 		ret = vop2_set_smart_win(state, win_data);
52541c9572c7SDamon Ding 	if (ret)
52551c9572c7SDamon Ding 		return ret;
52568895aec1SSandy Huang 
52578895aec1SSandy Huang 	printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
52588895aec1SSandy Huang 		cstate->crtc_id, get_plane_name(primary_plane_id, plane_name),
5259ee01dbb2SDamon Ding 		cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h,
5260ee01dbb2SDamon Ding 		cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format,
52618895aec1SSandy Huang 		cstate->dma_addr);
52628895aec1SSandy Huang 
5263d0408543SAndy Yan 	return 0;
5264d0408543SAndy Yan }
5265d0408543SAndy Yan 
5266d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state)
5267d0408543SAndy Yan {
5268d0408543SAndy Yan 	return 0;
5269d0408543SAndy Yan }
5270d0408543SAndy Yan 
527112ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state)
527212ee5af0SDamon Ding {
527312ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
527412ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
527512ee5af0SDamon Ding 	struct vop2 *vop2 = cstate->private;
527612ee5af0SDamon Ding 	u8 dsc_id = cstate->dsc_id;
527712ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
527812ee5af0SDamon Ding 
527912ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
528012ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK,
528112ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
528212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK,
528312ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
528412ee5af0SDamon Ding 	} else {
528512ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK,
528612ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
528712ee5af0SDamon Ding 	}
528812ee5af0SDamon Ding }
528912ee5af0SDamon Ding 
5290d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state)
5291d0408543SAndy Yan {
5292d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5293d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
529452ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5295ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5296d0408543SAndy Yan 
5297d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5298d0408543SAndy Yan 			STANDBY_EN_SHIFT, 0, false);
5299ee01dbb2SDamon Ding 
5300ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5301ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5302ee01dbb2SDamon Ding 
5303d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5304d0408543SAndy Yan 
530512ee5af0SDamon Ding 	if (cstate->dsc_enable)
530612ee5af0SDamon Ding 		vop2_dsc_cfg_done(state);
530712ee5af0SDamon Ding 
53080675a2a4SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
53090675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
53100675a2a4SDamon Ding 				MCU_HOLD_MODE_SHIFT, 0, false);
53110675a2a4SDamon Ding 
5312d0408543SAndy Yan 	return 0;
5313d0408543SAndy Yan }
5314d0408543SAndy Yan 
5315d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state)
5316d0408543SAndy Yan {
5317d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5318d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
531952ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5320ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5321d0408543SAndy Yan 
5322d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5323d0408543SAndy Yan 			STANDBY_EN_SHIFT, 1, false);
5324ee01dbb2SDamon Ding 
5325ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5326ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5327ee01dbb2SDamon Ding 
5328d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5329d0408543SAndy Yan 
5330d0408543SAndy Yan 	return 0;
5331d0408543SAndy Yan }
5332d0408543SAndy Yan 
5333ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane)
5334ee008497SSandy Huang {
5335ee008497SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
5336ee008497SSandy Huang 	struct vop2 *vop2 = cstate->private;
5337ee008497SSandy Huang 	int i = 0;
5338ee008497SSandy Huang 	int correct_cursor_plane = -1;
5339ee008497SSandy Huang 	int plane_type = -1;
5340ee008497SSandy Huang 
5341ee008497SSandy Huang 	if (cursor_plane < 0)
5342ee008497SSandy Huang 		return -1;
5343ee008497SSandy Huang 
5344ee008497SSandy Huang 	if (plane_mask & (1 << cursor_plane))
5345ee008497SSandy Huang 		return cursor_plane;
5346ee008497SSandy Huang 
5347ee008497SSandy Huang 	/* Get current cursor plane type */
5348ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
5349ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_id == cursor_plane) {
5350ee008497SSandy Huang 			plane_type = vop2->data->plane_table[i].plane_type;
5351ee008497SSandy Huang 			break;
5352ee008497SSandy Huang 		}
5353ee008497SSandy Huang 	}
5354ee008497SSandy Huang 
5355ee008497SSandy Huang 	/* Get the other same plane type plane id */
5356ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
5357ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_type == plane_type &&
5358ee008497SSandy Huang 		    vop2->data->plane_table[i].plane_id != cursor_plane) {
5359ee008497SSandy Huang 			correct_cursor_plane = vop2->data->plane_table[i].plane_id;
5360ee008497SSandy Huang 			break;
5361ee008497SSandy Huang 		}
5362ee008497SSandy Huang 	}
5363ee008497SSandy Huang 
5364ee008497SSandy Huang 	/* To check whether the new correct_cursor_plane is attach to current vp */
5365ee008497SSandy Huang 	if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) {
5366ee008497SSandy Huang 		printf("error: faild to find correct plane as cursor plane\n");
5367ee008497SSandy Huang 		return -1;
5368ee008497SSandy Huang 	}
5369ee008497SSandy Huang 
5370ee008497SSandy Huang 	printf("vp%d adjust cursor plane from %d to %d\n",
5371ee008497SSandy Huang 	       cstate->crtc_id, cursor_plane, correct_cursor_plane);
5372ee008497SSandy Huang 
5373ee008497SSandy Huang 	return correct_cursor_plane;
5374ee008497SSandy Huang }
5375ee008497SSandy Huang 
5376b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
5377b0989546SSandy Huang {
5378b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
5379b0989546SSandy Huang 	struct vop2 *vop2 = cstate->private;
5380b0989546SSandy Huang 	ofnode vp_node;
5381b0989546SSandy Huang 	struct device_node *port_parent_node = cstate->ports_node;
5382b0989546SSandy Huang 	static bool vop_fix_dts;
5383b0989546SSandy Huang 	const char *path;
5384b0989546SSandy Huang 	u32 plane_mask = 0;
5385b0989546SSandy Huang 	int vp_id = 0;
5386ee008497SSandy Huang 	int cursor_plane_id = -1;
5387b0989546SSandy Huang 
53885fa6e665SDamon Ding 	if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528)
5389b0989546SSandy Huang 		return 0;
5390b0989546SSandy Huang 
5391b0989546SSandy Huang 	ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
5392b0989546SSandy Huang 		path = vp_node.np->full_name;
5393b0989546SSandy Huang 		plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
5394b0989546SSandy Huang 
53958b1fe597SSandy Huang 		if (cstate->crtc->assign_plane)
53968b1fe597SSandy Huang 			continue;
5397ee008497SSandy Huang 		cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask,
5398ee008497SSandy Huang 								 cstate->crtc->vps[vp_id].cursor_plane);
5399ee008497SSandy Huang 		printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
5400b0989546SSandy Huang 		       vp_id, plane_mask,
5401ee008497SSandy Huang 		       vop2->vp_plane_mask[vp_id].primary_plane_id,
5402ee008497SSandy Huang 		       cursor_plane_id);
5403b0989546SSandy Huang 
5404b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
5405b0989546SSandy Huang 				     plane_mask, 1);
5406b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
5407b0989546SSandy Huang 				     vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
5408ee008497SSandy Huang 		if (cursor_plane_id >= 0)
5409ee008497SSandy Huang 			do_fixup_by_path_u32(blob, path, "cursor-win-id",
5410ee008497SSandy Huang 					     cursor_plane_id, 1);
5411b0989546SSandy Huang 		vp_id++;
5412b0989546SSandy Huang 	}
5413b0989546SSandy Huang 
5414b0989546SSandy Huang 	vop_fix_dts = true;
5415b0989546SSandy Huang 
5416b0989546SSandy Huang 	return 0;
5417b0989546SSandy Huang }
5418b0989546SSandy Huang 
5419820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state)
5420820a5c17SDamon Ding {
5421820a5c17SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5422820a5c17SDamon Ding 	struct rockchip_crtc *crtc = cstate->crtc;
5423820a5c17SDamon Ding 
5424820a5c17SDamon Ding 	if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) {
5425820a5c17SDamon Ding 		printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id);
5426820a5c17SDamon Ding 		return -ENOTSUPP;
5427820a5c17SDamon Ding 	}
5428820a5c17SDamon Ding 
5429820a5c17SDamon Ding 	if (cstate->splice_mode) {
5430820a5c17SDamon Ding 		crtc->splice_mode = true;
5431820a5c17SDamon Ding 		crtc->splice_crtc_id = cstate->splice_crtc_id;
5432820a5c17SDamon Ding 	}
5433820a5c17SDamon Ding 
5434820a5c17SDamon Ding 	return 0;
5435820a5c17SDamon Ding }
5436820a5c17SDamon Ding 
543722007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state)
543822007755SDamon Ding {
543922007755SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
544022007755SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
544122007755SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
544222007755SDamon Ding 	struct videomode vm;
544322007755SDamon Ding 
544422007755SDamon Ding 	drm_display_mode_to_videomode(mode, &vm);
544522007755SDamon Ding 
544622007755SDamon Ding 	if (vm.hactive < 32 || vm.vactive < 32 ||
544722007755SDamon Ding 	    (vm.hfront_porch * vm.hsync_len * vm.hback_porch *
544822007755SDamon Ding 	     vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) {
544922007755SDamon Ding 		printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id);
545022007755SDamon Ding 		return -EINVAL;
545122007755SDamon Ding 	}
545222007755SDamon Ding 
545322007755SDamon Ding 	return 0;
545422007755SDamon Ding }
545522007755SDamon Ding 
5456b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state)
5457b02eb70bSDamon Ding {
5458b02eb70bSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
5459b02eb70bSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
5460b02eb70bSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5461b02eb70bSDamon Ding 	struct vop2 *vop2 = cstate->private;
5462b02eb70bSDamon Ding 
54631b5811e7SDamon Ding 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
5464b02eb70bSDamon Ding 
5465b02eb70bSDamon Ding 	if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656)
5466b02eb70bSDamon Ding 		mode->crtc_clock *= 2;
5467b02eb70bSDamon Ding 
5468b02eb70bSDamon Ding 	/*
5469b02eb70bSDamon Ding 	 * For RK3528, the path of CVBS output is like:
5470b02eb70bSDamon Ding 	 * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
5471b02eb70bSDamon Ding 	 * The vop2 dclk should be four times crtc_clock for CVBS sampling
5472b02eb70bSDamon Ding 	 * clock needs.
5473b02eb70bSDamon Ding 	 */
5474b02eb70bSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656)
5475b02eb70bSDamon Ding 		mode->crtc_clock *= 4;
5476b02eb70bSDamon Ding 
54774d64cedbSDamon Ding 	mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format);
54784d64cedbSDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
54794d64cedbSDamon Ding 		mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1;
54800675a2a4SDamon Ding 
548117e6e1a5SChaoyi Chen 	if (conn_state->secondary &&
548217e6e1a5SChaoyi Chen 	    conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS) {
5483b02eb70bSDamon Ding 		mode->crtc_clock *= 2;
5484b02eb70bSDamon Ding 		mode->crtc_hdisplay *= 2;
5485b02eb70bSDamon Ding 		mode->crtc_hsync_start *= 2;
5486b02eb70bSDamon Ding 		mode->crtc_hsync_end *= 2;
5487b02eb70bSDamon Ding 		mode->crtc_htotal *= 2;
5488b02eb70bSDamon Ding 	}
5489b02eb70bSDamon Ding 
5490b02eb70bSDamon Ding 	return 0;
5491b02eb70bSDamon Ding }
5492b02eb70bSDamon Ding 
54934c765862SDamon Ding #define FRAC_16_16(mult, div)	(((mult) << 16) / (div))
54944c765862SDamon Ding 
54954c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state)
54964c765862SDamon Ding {
54974c765862SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
54984c765862SDamon Ding 	struct vop2 *vop2 = cstate->private;
54994c765862SDamon Ding 	struct display_rect *src = &cstate->src_rect;
55004c765862SDamon Ding 	struct display_rect *dst = &cstate->crtc_rect;
55014c765862SDamon Ding 	struct vop2_win_data *win_data;
55024c765862SDamon Ding 	int min_scale, max_scale;
55034c765862SDamon Ding 	int hscale, vscale;
55044c765862SDamon Ding 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
55054c765862SDamon Ding 
55064c765862SDamon Ding 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
55074c765862SDamon Ding 	if (!win_data) {
55084c765862SDamon Ding 		printf("ERROR: invalid win id %d\n", primary_plane_id);
55094c765862SDamon Ding 		return -ENODEV;
55104c765862SDamon Ding 	}
55114c765862SDamon Ding 
55124c765862SDamon Ding 	min_scale = FRAC_16_16(1, win_data->max_downscale_factor);
55134c765862SDamon Ding 	max_scale = FRAC_16_16(win_data->max_upscale_factor, 1);
55144c765862SDamon Ding 
55154c765862SDamon Ding 	hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale);
55164c765862SDamon Ding 	vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale);
55174c765862SDamon Ding 	if (hscale < 0 || vscale < 0) {
55184c765862SDamon Ding 		printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name);
55194c765862SDamon Ding 		return -ERANGE;
55204c765862SDamon Ding 		}
55214c765862SDamon Ding 
55224c765862SDamon Ding 	return 0;
55234c765862SDamon Ding }
5524337d1c13SDamon Ding 
55258e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state)
55268e7ef808SDamon Ding {
5527d8e7f4a5SSandy Huang 	__maybe_unused struct connector_state *conn_state = &state->conn_state;
55288e7ef808SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
55298e7ef808SDamon Ding 	struct vop2 *vop2 = cstate->private;
55308e7ef808SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
55318e7ef808SDamon Ding 	int val = 0;
55328e7ef808SDamon Ding 	int ret = 0;
55338e7ef808SDamon Ding 
55348e7ef808SDamon Ding 	ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val,
55358e7ef808SDamon Ding 				 (val >> EDPI_WMS_FS) & 0x1, 50 * 1000);
55368e7ef808SDamon Ding 	if (!ret) {
5537d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
55388e7ef808SDamon Ding 		ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
55398e7ef808SDamon Ding 					 !val, 50 * 1000);
55408e7ef808SDamon Ding 		if (!ret) {
55418e7ef808SDamon Ding 			ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
55428e7ef808SDamon Ding 						 val, 50 * 1000);
55438e7ef808SDamon Ding 			if (!ret) {
55448e7ef808SDamon Ding 				vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
55458e7ef808SDamon Ding 						EN_MASK, EDPI_WMS_FS, 1, false);
55468e7ef808SDamon Ding 			} else {
55478e7ef808SDamon Ding 				printf("ERROR: vp%d wait for active TE signal timeout\n",
55488e7ef808SDamon Ding 				       cstate->crtc_id);
55498e7ef808SDamon Ding 				return ret;
55508e7ef808SDamon Ding 			}
55518e7ef808SDamon Ding 		} else {
55528e7ef808SDamon Ding 			printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id);
55538e7ef808SDamon Ding 			return ret;
55548e7ef808SDamon Ding 		}
5555d8e7f4a5SSandy Huang #endif
55568e7ef808SDamon Ding 	} else {
55578e7ef808SDamon Ding 		printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id);
55588e7ef808SDamon Ding 		return ret;
55598e7ef808SDamon Ding 	}
55608e7ef808SDamon Ding 
55618e7ef808SDamon Ding 	return 0;
55628e7ef808SDamon Ding }
55638e7ef808SDamon Ding 
556472388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state)
556572388c26SDamon Ding {
556672388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
556772388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
556872388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
556972388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
5570a552a69cSDamon Ding 	u32 len = 128;
557172388c26SDamon Ding 	u32 n, i, j;
557272388c26SDamon Ding 	u32 base;
557372388c26SDamon Ding 
557472388c26SDamon Ding 	if (!cstate->crtc->active)
557572388c26SDamon Ding 		return -EINVAL;
557672388c26SDamon Ding 
557772388c26SDamon Ding 	n = vop2_data->dump_regs_size;
557872388c26SDamon Ding 	for (i = 0; i < n; i++) {
557972388c26SDamon Ding 		base = regs[i].offset;
5580a552a69cSDamon Ding 		len = 128;
5581a552a69cSDamon Ding 		if (regs[i].size)
5582a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
558372388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
5584a552a69cSDamon Ding 		for (j = 0; j < len;) {
558572388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
558672388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
558772388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
558872388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
558972388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
559072388c26SDamon Ding 			j += 4;
559172388c26SDamon Ding 		}
559272388c26SDamon Ding 	}
559372388c26SDamon Ding 
559472388c26SDamon Ding 	return 0;
559572388c26SDamon Ding }
559672388c26SDamon Ding 
559772388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state)
559872388c26SDamon Ding {
559972388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
560072388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
560172388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
560272388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
5603a552a69cSDamon Ding 	u32 len = 128;
560472388c26SDamon Ding 	u32 n, i, j;
560572388c26SDamon Ding 	u32 base;
560672388c26SDamon Ding 	bool enable_state;
560772388c26SDamon Ding 
560872388c26SDamon Ding 	if (!cstate->crtc->active)
560972388c26SDamon Ding 		return -EINVAL;
561072388c26SDamon Ding 
561172388c26SDamon Ding 	n = vop2_data->dump_regs_size;
561272388c26SDamon Ding 	for (i = 0; i < n; i++) {
561372388c26SDamon Ding 		if (regs[i].state_mask) {
561472388c26SDamon Ding 			enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) &
561572388c26SDamon Ding 				       regs[i].state_mask;
561672388c26SDamon Ding 			if (enable_state != regs[i].enable_state)
561772388c26SDamon Ding 				continue;
561872388c26SDamon Ding 		}
561972388c26SDamon Ding 
562072388c26SDamon Ding 		base = regs[i].offset;
5621a552a69cSDamon Ding 		len = 128;
5622a552a69cSDamon Ding 		if (regs[i].size)
5623a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
562472388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
5625a552a69cSDamon Ding 		for (j = 0; j < len;) {
562672388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
562772388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
562872388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
562972388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
563072388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
563172388c26SDamon Ding 			j += 4;
563272388c26SDamon Ding 		}
563372388c26SDamon Ding 	}
563472388c26SDamon Ding 
563572388c26SDamon Ding 	return 0;
563672388c26SDamon Ding }
563772388c26SDamon Ding 
563872388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = {
563972388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
564072388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
564172388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
564272388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
564372388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
564472388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
564572388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
564672388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
564772388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
564872388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
564972388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
565072388c26SDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
565172388c26SDamon Ding 	{ RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1},
565272388c26SDamon Ding };
565372388c26SDamon Ding 
56545fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
56555fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
56565fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
56575fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
56585fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
56595fa6e665SDamon Ding };
56605fa6e665SDamon Ding 
56615fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
56625fa6e665SDamon Ding 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
56635fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
56645fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
56655fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
56665fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
56675fa6e665SDamon Ding };
56685fa6e665SDamon Ding 
56695fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
56705fa6e665SDamon Ding 	{ /* one display policy for hdmi */
56715fa6e665SDamon Ding 		{/* main display */
5672ebbd144cSAlgea Cao 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
56735fa6e665SDamon Ding 			.attached_layers_nr = 4,
56745fa6e665SDamon Ding 			.attached_layers = {
56755fa6e665SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0,
56765fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2
56775fa6e665SDamon Ding 				},
56785fa6e665SDamon Ding 		},
56795fa6e665SDamon Ding 		{/* second display */},
56805fa6e665SDamon Ding 		{/* third  display */},
56815fa6e665SDamon Ding 		{/* fourth display */},
56825fa6e665SDamon Ding 	},
56835fa6e665SDamon Ding 
56845fa6e665SDamon Ding 	{ /* two display policy */
56855fa6e665SDamon Ding 		{/* main display */
5686ebbd144cSAlgea Cao 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
56875fa6e665SDamon Ding 			.attached_layers_nr = 3,
56885fa6e665SDamon Ding 			.attached_layers = {
56895fa6e665SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
56905fa6e665SDamon Ding 				},
56915fa6e665SDamon Ding 		},
56925fa6e665SDamon Ding 
56935fa6e665SDamon Ding 		{/* second display */
56945fa6e665SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
56955fa6e665SDamon Ding 			.attached_layers_nr = 2,
56965fa6e665SDamon Ding 			.attached_layers = {
56975fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
56985fa6e665SDamon Ding 				},
56995fa6e665SDamon Ding 		},
57005fa6e665SDamon Ding 		{/* third  display */},
57015fa6e665SDamon Ding 		{/* fourth display */},
57025fa6e665SDamon Ding 	},
57035fa6e665SDamon Ding 
57045fa6e665SDamon Ding 	{ /* one display policy for cvbs */
57055fa6e665SDamon Ding 		{/* main display */
57065fa6e665SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
57075fa6e665SDamon Ding 			.attached_layers_nr = 2,
57085fa6e665SDamon Ding 			.attached_layers = {
57095fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
57105fa6e665SDamon Ding 				},
57115fa6e665SDamon Ding 		},
57125fa6e665SDamon Ding 		{/* second display */},
57135fa6e665SDamon Ding 		{/* third  display */},
57145fa6e665SDamon Ding 		{/* fourth display */},
57155fa6e665SDamon Ding 	},
57165fa6e665SDamon Ding 
57175fa6e665SDamon Ding 	{/* reserved */},
57185fa6e665SDamon Ding };
57195fa6e665SDamon Ding 
57205fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = {
57215fa6e665SDamon Ding 	{
57225fa6e665SDamon Ding 		.name = "Esmart0",
57235fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
57245fa6e665SDamon Ding 		.type = ESMART_LAYER,
57255fa6e665SDamon Ding 		.win_sel_port_offset = 8,
57265fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 0xff, 0xff, 0xff },
57275fa6e665SDamon Ding 		.reg_offset = 0,
57285fa6e665SDamon Ding 		.axi_id = 0,
57295fa6e665SDamon Ding 		.axi_yrgb_id = 0x06,
57305fa6e665SDamon Ding 		.axi_uv_id = 0x07,
57315fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
57325fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57335fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
57345fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57355fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
57365fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
57375fa6e665SDamon Ding 		.max_upscale_factor = 8,
57385fa6e665SDamon Ding 		.max_downscale_factor = 8,
57395fa6e665SDamon Ding 	},
57405fa6e665SDamon Ding 
57415fa6e665SDamon Ding 	{
57425fa6e665SDamon Ding 		.name = "Esmart1",
57435fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
57445fa6e665SDamon Ding 		.type = ESMART_LAYER,
57455fa6e665SDamon Ding 		.win_sel_port_offset = 10,
57465fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0xff, 0xff },
57475fa6e665SDamon Ding 		.reg_offset = 0x200,
57485fa6e665SDamon Ding 		.axi_id = 0,
57495fa6e665SDamon Ding 		.axi_yrgb_id = 0x08,
57505fa6e665SDamon Ding 		.axi_uv_id = 0x09,
57515fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
57525fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57535fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
57545fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57555fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
57565fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
57575fa6e665SDamon Ding 		.max_upscale_factor = 8,
57585fa6e665SDamon Ding 		.max_downscale_factor = 8,
57595fa6e665SDamon Ding 	},
57605fa6e665SDamon Ding 
57615fa6e665SDamon Ding 	{
57625fa6e665SDamon Ding 		.name = "Esmart2",
57635fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
57645fa6e665SDamon Ding 		.type = ESMART_LAYER,
57655fa6e665SDamon Ding 		.win_sel_port_offset = 12,
57665fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 0, 0xff, 0xff },
57675fa6e665SDamon Ding 		.reg_offset = 0x400,
57685fa6e665SDamon Ding 		.axi_id = 0,
57695fa6e665SDamon Ding 		.axi_yrgb_id = 0x0a,
57705fa6e665SDamon Ding 		.axi_uv_id = 0x0b,
57715fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
57725fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57735fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
57745fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57755fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
57765fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
57775fa6e665SDamon Ding 		.max_upscale_factor = 8,
57785fa6e665SDamon Ding 		.max_downscale_factor = 8,
57795fa6e665SDamon Ding 	},
57805fa6e665SDamon Ding 
57815fa6e665SDamon Ding 	{
57825fa6e665SDamon Ding 		.name = "Esmart3",
57835fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
57845fa6e665SDamon Ding 		.type = ESMART_LAYER,
57855fa6e665SDamon Ding 		.win_sel_port_offset = 14,
57865fa6e665SDamon Ding 		.layer_sel_win_id = { 0xff, 1, 0xff, 0xff },
57875fa6e665SDamon Ding 		.reg_offset = 0x600,
57885fa6e665SDamon Ding 		.axi_id = 0,
57895fa6e665SDamon Ding 		.axi_yrgb_id = 0x0c,
57905fa6e665SDamon Ding 		.axi_uv_id = 0x0d,
57915fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
57925fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57935fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
57945fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
57955fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
57965fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
57975fa6e665SDamon Ding 		.max_upscale_factor = 8,
57985fa6e665SDamon Ding 		.max_downscale_factor = 8,
57995fa6e665SDamon Ding 	},
58005fa6e665SDamon Ding 
58015fa6e665SDamon Ding 	{
58025fa6e665SDamon Ding 		.name = "Cluster0",
58035fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
58045fa6e665SDamon Ding 		.type = CLUSTER_LAYER,
58055fa6e665SDamon Ding 		.win_sel_port_offset = 0,
58065fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0xff, 0xff, 0xff },
58075fa6e665SDamon Ding 		.reg_offset = 0,
58085fa6e665SDamon Ding 		.axi_id = 0,
58095fa6e665SDamon Ding 		.axi_yrgb_id = 0x02,
58105fa6e665SDamon Ding 		.axi_uv_id = 0x03,
58115fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
58125fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
58135fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
58145fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
58155fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
58165fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
58175fa6e665SDamon Ding 		.max_upscale_factor = 8,
58185fa6e665SDamon Ding 		.max_downscale_factor = 8,
58195fa6e665SDamon Ding 	},
58205fa6e665SDamon Ding };
58215fa6e665SDamon Ding 
58225fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = {
58235fa6e665SDamon Ding 	{
58246027c871SZhang Yubing 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM |
58256027c871SZhang Yubing 			   VOP_FEATURE_POST_CSC,
58265fa6e665SDamon Ding 		.max_output = {4096, 4096},
5827b05105abSDamon Ding 		.layer_mix_dly = 6,
5828b05105abSDamon Ding 		.hdr_mix_dly = 2,
5829b05105abSDamon Ding 		.win_dly = 8,
58305fa6e665SDamon Ding 	},
58315fa6e665SDamon Ding 	{
58325fa6e665SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
58335fa6e665SDamon Ding 		.max_output = {1920, 1080},
5834b05105abSDamon Ding 		.layer_mix_dly = 2,
5835b05105abSDamon Ding 		.hdr_mix_dly = 0,
5836b05105abSDamon Ding 		.win_dly = 8,
58375fa6e665SDamon Ding 	},
58385fa6e665SDamon Ding };
58395fa6e665SDamon Ding 
58405fa6e665SDamon Ding const struct vop2_data rk3528_vop = {
58415fa6e665SDamon Ding 	.version = VOP_VERSION_RK3528,
58425fa6e665SDamon Ding 	.nr_vps = 2,
58435fa6e665SDamon Ding 	.vp_data = rk3528_vp_data,
58445fa6e665SDamon Ding 	.win_data = rk3528_win_data,
58455fa6e665SDamon Ding 	.plane_mask = rk3528_vp_plane_mask[0],
58465fa6e665SDamon Ding 	.plane_table = rk3528_plane_table,
58475fa6e665SDamon Ding 	.vp_primary_plane_order = rk3528_vp_primary_plane_order,
58485fa6e665SDamon Ding 	.nr_layers = 5,
58495fa6e665SDamon Ding 	.nr_mixers = 3,
58505fa6e665SDamon Ding 	.nr_gammas = 2,
58515fa6e665SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE,
585272388c26SDamon Ding 	.dump_regs = rk3528_dump_regs,
585372388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
585472388c26SDamon Ding };
585572388c26SDamon Ding 
585672388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = {
585772388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
585872388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
585972388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
586072388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
586172388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
586272388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
586372388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
586472388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
586572388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
586672388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
58675fa6e665SDamon Ding };
58685fa6e665SDamon Ding 
5869452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
5870452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
5871452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
5872452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
5873452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
5874452afb13SDamon Ding };
5875452afb13SDamon Ding 
5876452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
5877452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
5878452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
5879452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
5880452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
5881452afb13SDamon Ding };
5882452afb13SDamon Ding 
5883452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
5884452afb13SDamon Ding 	{ /* one display policy for hdmi */
5885452afb13SDamon Ding 		{/* main display */
5886452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5887452afb13SDamon Ding 			.attached_layers_nr = 4,
5888452afb13SDamon Ding 			.attached_layers = {
5889452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1,
5890452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART2,  ROCKCHIP_VOP2_ESMART3
5891452afb13SDamon Ding 				},
5892452afb13SDamon Ding 		},
5893452afb13SDamon Ding 		{/* second display */},
5894452afb13SDamon Ding 		{/* third  display */},
5895452afb13SDamon Ding 		{/* fourth display */},
5896452afb13SDamon Ding 	},
5897452afb13SDamon Ding 
5898452afb13SDamon Ding 	{ /* two display policy */
5899452afb13SDamon Ding 		{/* main display */
5900452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5901452afb13SDamon Ding 			.attached_layers_nr = 2,
5902452afb13SDamon Ding 			.attached_layers = {
5903452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
5904452afb13SDamon Ding 				},
5905452afb13SDamon Ding 		},
5906452afb13SDamon Ding 
5907452afb13SDamon Ding 		{/* second display */
5908452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
5909452afb13SDamon Ding 			.attached_layers_nr = 2,
5910452afb13SDamon Ding 			.attached_layers = {
5911452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
5912452afb13SDamon Ding 				},
5913452afb13SDamon Ding 		},
5914452afb13SDamon Ding 		{/* third  display */},
5915452afb13SDamon Ding 		{/* fourth display */},
5916452afb13SDamon Ding 	},
5917452afb13SDamon Ding 
5918452afb13SDamon Ding 	{/* reserved */},
5919452afb13SDamon Ding };
5920452afb13SDamon Ding 
5921452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = {
5922452afb13SDamon Ding 	{
5923452afb13SDamon Ding 		.name = "Esmart0",
5924452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
5925452afb13SDamon Ding 		.type = ESMART_LAYER,
5926452afb13SDamon Ding 		.win_sel_port_offset = 8,
5927452afb13SDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
5928452afb13SDamon Ding 		.reg_offset = 0,
5929452afb13SDamon Ding 		.axi_id = 0,
5930452afb13SDamon Ding 		.axi_yrgb_id = 0x02,
5931452afb13SDamon Ding 		.axi_uv_id = 0x03,
5932452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5933452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5934452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5935452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5936452afb13SDamon Ding 		.max_upscale_factor = 8,
5937452afb13SDamon Ding 		.max_downscale_factor = 8,
5938452afb13SDamon Ding 	},
5939452afb13SDamon Ding 
5940452afb13SDamon Ding 	{
5941452afb13SDamon Ding 		.name = "Esmart1",
5942452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
5943452afb13SDamon Ding 		.type = ESMART_LAYER,
5944452afb13SDamon Ding 		.win_sel_port_offset = 10,
5945452afb13SDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
5946452afb13SDamon Ding 		.reg_offset = 0x200,
5947452afb13SDamon Ding 		.axi_id = 0,
5948452afb13SDamon Ding 		.axi_yrgb_id = 0x04,
5949452afb13SDamon Ding 		.axi_uv_id = 0x05,
5950452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5951452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5952452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5953452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5954452afb13SDamon Ding 		.max_upscale_factor = 8,
5955452afb13SDamon Ding 		.max_downscale_factor = 8,
5956452afb13SDamon Ding 	},
5957452afb13SDamon Ding 
5958452afb13SDamon Ding 	{
5959452afb13SDamon Ding 		.name = "Esmart2",
5960452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
5961452afb13SDamon Ding 		.type = ESMART_LAYER,
5962452afb13SDamon Ding 		.win_sel_port_offset = 12,
5963452afb13SDamon Ding 		.layer_sel_win_id = { 2, 2, 0xff, 0xff },
5964452afb13SDamon Ding 		.reg_offset = 0x400,
5965452afb13SDamon Ding 		.axi_id = 0,
5966452afb13SDamon Ding 		.axi_yrgb_id = 0x06,
5967452afb13SDamon Ding 		.axi_uv_id = 0x07,
5968452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5969452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5970452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5971452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5972452afb13SDamon Ding 		.max_upscale_factor = 8,
5973452afb13SDamon Ding 		.max_downscale_factor = 8,
5974452afb13SDamon Ding 	},
5975452afb13SDamon Ding 
5976452afb13SDamon Ding 	{
5977452afb13SDamon Ding 		.name = "Esmart3",
5978452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
5979452afb13SDamon Ding 		.type = ESMART_LAYER,
5980452afb13SDamon Ding 		.win_sel_port_offset = 14,
5981452afb13SDamon Ding 		.layer_sel_win_id = { 3, 3, 0xff, 0xff },
5982452afb13SDamon Ding 		.reg_offset = 0x600,
5983452afb13SDamon Ding 		.axi_id = 0,
5984452afb13SDamon Ding 		.axi_yrgb_id = 0x08,
5985452afb13SDamon Ding 		.axi_uv_id = 0x0d,
5986452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5987452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5988452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5989452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5990452afb13SDamon Ding 		.max_upscale_factor = 8,
5991452afb13SDamon Ding 		.max_downscale_factor = 8,
5992452afb13SDamon Ding 	},
5993452afb13SDamon Ding };
5994452afb13SDamon Ding 
5995452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = {
5996452afb13SDamon Ding 	{
5997452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
5998452afb13SDamon Ding 		.max_output = {2048, 4096},
5999452afb13SDamon Ding 		.win_dly = 8,
6000452afb13SDamon Ding 		.layer_mix_dly = 8,
6001452afb13SDamon Ding 	},
6002452afb13SDamon Ding 	{
6003452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6004452afb13SDamon Ding 		.max_output = {2048, 1080},
6005452afb13SDamon Ding 		.win_dly = 8,
6006452afb13SDamon Ding 		.layer_mix_dly = 8,
6007452afb13SDamon Ding 	},
6008452afb13SDamon Ding };
6009452afb13SDamon Ding 
6010452afb13SDamon Ding const struct vop2_data rk3562_vop = {
6011452afb13SDamon Ding 	.version = VOP_VERSION_RK3562,
6012452afb13SDamon Ding 	.nr_vps = 2,
6013452afb13SDamon Ding 	.vp_data = rk3562_vp_data,
6014452afb13SDamon Ding 	.win_data = rk3562_win_data,
6015452afb13SDamon Ding 	.plane_mask = rk3562_vp_plane_mask[0],
6016452afb13SDamon Ding 	.plane_table = rk3562_plane_table,
6017452afb13SDamon Ding 	.vp_primary_plane_order = rk3562_vp_primary_plane_order,
6018452afb13SDamon Ding 	.nr_layers = 4,
6019452afb13SDamon Ding 	.nr_mixers = 3,
6020452afb13SDamon Ding 	.nr_gammas = 2,
6021452afb13SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE,
602272388c26SDamon Ding 	.dump_regs = rk3562_dump_regs,
602372388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
602472388c26SDamon Ding };
602572388c26SDamon Ding 
602672388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = {
602772388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
602872388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
602972388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
603072388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
603172388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
603272388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
603372388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
603472388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
603572388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
603672388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
603772388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
603872388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
6039452afb13SDamon Ding };
6040452afb13SDamon Ding 
6041337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
6042337d1c13SDamon Ding 	ROCKCHIP_VOP2_SMART0,
6043337d1c13SDamon Ding 	ROCKCHIP_VOP2_SMART1,
6044337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6045337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6046337d1c13SDamon Ding };
6047337d1c13SDamon Ding 
6048ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6049ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6050ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6051ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6052ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6053ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
6054ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
6055ee008497SSandy Huang };
6056ee008497SSandy Huang 
6057b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
6058b0989546SSandy Huang 	{ /* one display policy */
6059b0989546SSandy Huang 		{/* main display */
6060b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6061b0989546SSandy Huang 			.attached_layers_nr = 6,
6062b0989546SSandy Huang 			.attached_layers = {
6063b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
6064b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
6065b0989546SSandy Huang 				},
6066b0989546SSandy Huang 		},
6067b0989546SSandy Huang 		{/* second display */},
6068b0989546SSandy Huang 		{/* third  display */},
6069b0989546SSandy Huang 		{/* fourth display */},
6070b0989546SSandy Huang 	},
6071b0989546SSandy Huang 
6072b0989546SSandy Huang 	{ /* two display policy */
6073b0989546SSandy Huang 		{/* main display */
6074b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6075b0989546SSandy Huang 			.attached_layers_nr = 3,
6076b0989546SSandy Huang 			.attached_layers = {
6077b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
6078b0989546SSandy Huang 				},
6079b0989546SSandy Huang 		},
6080b0989546SSandy Huang 
6081b0989546SSandy Huang 		{/* second display */
6082b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
6083b0989546SSandy Huang 			.attached_layers_nr = 3,
6084b0989546SSandy Huang 			.attached_layers = {
6085b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
6086b0989546SSandy Huang 				},
6087b0989546SSandy Huang 		},
6088b0989546SSandy Huang 		{/* third  display */},
6089b0989546SSandy Huang 		{/* fourth display */},
6090b0989546SSandy Huang 	},
6091b0989546SSandy Huang 
6092b0989546SSandy Huang 	{ /* three display policy */
6093b0989546SSandy Huang 		{/* main display */
6094b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6095b0989546SSandy Huang 			.attached_layers_nr = 3,
6096b0989546SSandy Huang 			.attached_layers = {
6097b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
6098b0989546SSandy Huang 				},
6099b0989546SSandy Huang 		},
6100b0989546SSandy Huang 
6101b0989546SSandy Huang 		{/* second display */
6102b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
6103b0989546SSandy Huang 			.attached_layers_nr = 2,
6104b0989546SSandy Huang 			.attached_layers = {
6105b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
6106b0989546SSandy Huang 				},
6107b0989546SSandy Huang 		},
6108b0989546SSandy Huang 
6109b0989546SSandy Huang 		{/* third  display */
6110b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
6111b0989546SSandy Huang 			.attached_layers_nr = 1,
6112b0989546SSandy Huang 			.attached_layers = { ROCKCHIP_VOP2_ESMART1 },
6113b0989546SSandy Huang 		},
6114b0989546SSandy Huang 
6115b0989546SSandy Huang 		{/* fourth display */},
6116b0989546SSandy Huang 	},
6117b0989546SSandy Huang 
6118b0989546SSandy Huang 	{/* reserved for four display policy */},
6119b0989546SSandy Huang };
6120b0989546SSandy Huang 
6121b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = {
6122b0989546SSandy Huang 	{
6123b0989546SSandy Huang 		.name = "Cluster0",
6124b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
6125ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6126b0989546SSandy Huang 		.win_sel_port_offset = 0,
61275fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0xff },
6128b0989546SSandy Huang 		.reg_offset = 0,
61295fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61305fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61315fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61325fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61334c765862SDamon Ding 		.max_upscale_factor = 4,
61344c765862SDamon Ding 		.max_downscale_factor = 4,
6135b0989546SSandy Huang 	},
6136b0989546SSandy Huang 
6137b0989546SSandy Huang 	{
6138b0989546SSandy Huang 		.name = "Cluster1",
6139b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
6140ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6141b0989546SSandy Huang 		.win_sel_port_offset = 1,
61425fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 0xff },
6143b0989546SSandy Huang 		.reg_offset = 0x200,
61445fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61455fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61465fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61475fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61484c765862SDamon Ding 		.max_upscale_factor = 4,
61494c765862SDamon Ding 		.max_downscale_factor = 4,
61501c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_CLUSTER0,
61511c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6152b0989546SSandy Huang 	},
6153b0989546SSandy Huang 
6154b0989546SSandy Huang 	{
6155b0989546SSandy Huang 		.name = "Esmart0",
6156b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6157ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6158b0989546SSandy Huang 		.win_sel_port_offset = 4,
61595fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 0xff },
6160b0989546SSandy Huang 		.reg_offset = 0,
61615fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61625fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61635fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61645fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61654c765862SDamon Ding 		.max_upscale_factor = 8,
61664c765862SDamon Ding 		.max_downscale_factor = 8,
6167b0989546SSandy Huang 	},
6168b0989546SSandy Huang 
6169b0989546SSandy Huang 	{
6170b0989546SSandy Huang 		.name = "Esmart1",
6171b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6172ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6173b0989546SSandy Huang 		.win_sel_port_offset = 5,
61745fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 0xff },
6175b0989546SSandy Huang 		.reg_offset = 0x200,
61765fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61775fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61785fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61795fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61804c765862SDamon Ding 		.max_upscale_factor = 8,
61814c765862SDamon Ding 		.max_downscale_factor = 8,
61821c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_ESMART0,
61831c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6184b0989546SSandy Huang 	},
6185b0989546SSandy Huang 
6186b0989546SSandy Huang 	{
6187b0989546SSandy Huang 		.name = "Smart0",
6188b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART0,
6189ecc31b6eSAndy Yan 		.type = SMART_LAYER,
6190b0989546SSandy Huang 		.win_sel_port_offset = 6,
61915fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 0xff },
6192b0989546SSandy Huang 		.reg_offset = 0x400,
61935fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61945fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61955fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61965fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61974c765862SDamon Ding 		.max_upscale_factor = 8,
61984c765862SDamon Ding 		.max_downscale_factor = 8,
6199b0989546SSandy Huang 	},
6200b0989546SSandy Huang 
6201b0989546SSandy Huang 	{
6202b0989546SSandy Huang 		.name = "Smart1",
6203b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART1,
6204ecc31b6eSAndy Yan 		.type = SMART_LAYER,
6205b0989546SSandy Huang 		.win_sel_port_offset = 7,
62065fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 0xff },
6207b0989546SSandy Huang 		.reg_offset = 0x600,
62085fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
62095fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62105fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
62115fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62124c765862SDamon Ding 		.max_upscale_factor = 8,
62134c765862SDamon Ding 		.max_downscale_factor = 8,
62141c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_SMART0,
62151c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6216b0989546SSandy Huang 	},
6217b0989546SSandy Huang };
6218b0989546SSandy Huang 
621963cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = {
622063cb669fSSandy Huang 	{
622163cb669fSSandy Huang 		.feature = VOP_FEATURE_OUTPUT_10BIT,
622263cb669fSSandy Huang 		.pre_scan_max_dly = 42,
622363cb669fSSandy Huang 		.max_output = {4096, 2304},
6224d0408543SAndy Yan 	},
622563cb669fSSandy Huang 	{
622663cb669fSSandy Huang 		.feature = 0,
622763cb669fSSandy Huang 		.pre_scan_max_dly = 40,
622863cb669fSSandy Huang 		.max_output = {2048, 1536},
622963cb669fSSandy Huang 	},
623063cb669fSSandy Huang 	{
623163cb669fSSandy Huang 		.feature = 0,
623263cb669fSSandy Huang 		.pre_scan_max_dly = 40,
623363cb669fSSandy Huang 		.max_output = {1920, 1080},
623463cb669fSSandy Huang 	},
623563cb669fSSandy Huang };
6236d0408543SAndy Yan 
623763cb669fSSandy Huang const struct vop2_data rk3568_vop = {
6238ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3568,
623963cb669fSSandy Huang 	.nr_vps = 3,
624063cb669fSSandy Huang 	.vp_data = rk3568_vp_data,
6241b0989546SSandy Huang 	.win_data = rk3568_win_data,
6242b0989546SSandy Huang 	.plane_mask = rk356x_vp_plane_mask[0],
6243ee008497SSandy Huang 	.plane_table = rk356x_plane_table,
6244337d1c13SDamon Ding 	.vp_primary_plane_order = rk3568_vp_primary_plane_order,
6245d0408543SAndy Yan 	.nr_layers = 6,
624663cb669fSSandy Huang 	.nr_mixers = 5,
62471147facaSSandy Huang 	.nr_gammas = 1,
624872388c26SDamon Ding 	.dump_regs = rk3568_dump_regs,
624972388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3568_dump_regs),
6250d0408543SAndy Yan };
6251d0408543SAndy Yan 
6252a552a69cSDamon Ding static u8 rk3576_vp_default_primary_plane[VOP2_VP_MAX] = {
6253a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6254a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6255a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART2,
6256a552a69cSDamon Ding };
6257a552a69cSDamon Ding 
6258a552a69cSDamon Ding static struct vop2_plane_table rk3576_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6259a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6260a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6261a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
6262a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
6263a552a69cSDamon Ding 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6264a552a69cSDamon Ding 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6265a552a69cSDamon Ding };
6266a552a69cSDamon Ding 
6267a552a69cSDamon Ding static struct vop2_dump_regs rk3576_dump_regs[] = {
6268a552a69cSDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 },
6269a552a69cSDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 },
6270a552a69cSDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 },
6271a552a69cSDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 },
6272a552a69cSDamon Ding 	{ RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 },
6273a552a69cSDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6274a552a69cSDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6275a552a69cSDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6276a552a69cSDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
6277a552a69cSDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
6278a552a69cSDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 },
6279a552a69cSDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 },
6280a552a69cSDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 },
6281a552a69cSDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 },
6282a552a69cSDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 },
6283a552a69cSDamon Ding };
6284a552a69cSDamon Ding 
6285a552a69cSDamon Ding /*
6286a552a69cSDamon Ding  * RK3576 VOP with 2 Cluster win and 4 Esmart win.
6287a552a69cSDamon Ding  * Every Esmart win support 4 multi-region.
6288a552a69cSDamon Ding  * VP0 can use Cluster0/1 and Esmart0/2
6289a552a69cSDamon Ding  * VP1 can use Cluster0/1 and Esmart1/3
6290a552a69cSDamon Ding  * VP2 can use Esmart0/1/2/3
6291a552a69cSDamon Ding  *
6292a552a69cSDamon Ding  * Scale filter mode:
6293a552a69cSDamon Ding  *
6294a552a69cSDamon Ding  * * Cluster:
6295a552a69cSDamon Ding  * * Support prescale down:
6296a552a69cSDamon Ding  * * H/V: gt2/avg2 or gt4/avg4
6297a552a69cSDamon Ding  * * After prescale down:
6298a552a69cSDamon Ding  *      * nearest-neighbor/bilinear/multi-phase filter for scale up
6299a552a69cSDamon Ding  *      * nearest-neighbor/bilinear/multi-phase filter for scale down
6300a552a69cSDamon Ding  *
6301a552a69cSDamon Ding  * * Esmart:
6302a552a69cSDamon Ding  * * Support prescale down:
6303a552a69cSDamon Ding  * * H: gt2/avg2 or gt4/avg4
6304a552a69cSDamon Ding  * * V: gt2 or gt4
6305a552a69cSDamon Ding  * * After prescale down:
6306a552a69cSDamon Ding  *      * nearest-neighbor/bilinear/bicubic for scale up
6307a552a69cSDamon Ding  *      * nearest-neighbor/bilinear for scale down
6308a552a69cSDamon Ding  */
6309a552a69cSDamon Ding static struct vop2_win_data rk3576_win_data[6] = {
6310a552a69cSDamon Ding 	{
6311a552a69cSDamon Ding 		.name = "Esmart0",
6312a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6313a552a69cSDamon Ding 		.type = ESMART_LAYER,
6314a552a69cSDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0, 0xff },
6315a552a69cSDamon Ding 		.reg_offset = 0x0,
6316a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6317a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6318a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6319a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6320a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6321a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6322a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6323a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6324a552a69cSDamon Ding 		.axi_id = 0,
6325a552a69cSDamon Ding 		.axi_yrgb_id = 0x0a,
6326a552a69cSDamon Ding 		.axi_uv_id = 0x0b,
6327a552a69cSDamon Ding 		.possible_crtcs = 0x5,/* vp0 or vp2 */
6328a552a69cSDamon Ding 		.max_upscale_factor = 8,
6329a552a69cSDamon Ding 		.max_downscale_factor = 8,
6330a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH,
6331a552a69cSDamon Ding 	},
6332a552a69cSDamon Ding 	{
6333a552a69cSDamon Ding 		.name = "Esmart1",
6334a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6335a552a69cSDamon Ding 		.type = ESMART_LAYER,
6336a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 2, 1, 0xff },
6337a552a69cSDamon Ding 		.reg_offset = 0x200,
6338a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6339a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6340a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6341a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6342a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6343a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6344a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6345a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6346a552a69cSDamon Ding 		.axi_id = 0,
6347a552a69cSDamon Ding 		.axi_yrgb_id = 0x0c,
6348a552a69cSDamon Ding 		.axi_uv_id = 0x0d,
6349a552a69cSDamon Ding 		.possible_crtcs = 0x6,/* vp1 or vp2 */
6350a552a69cSDamon Ding 		.max_upscale_factor = 8,
6351a552a69cSDamon Ding 		.max_downscale_factor = 8,
6352a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6353a552a69cSDamon Ding 	},
6354a552a69cSDamon Ding 
6355a552a69cSDamon Ding 	{
6356a552a69cSDamon Ding 		.name = "Esmart2",
6357a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
6358a552a69cSDamon Ding 		.type = ESMART_LAYER,
6359a552a69cSDamon Ding 		.layer_sel_win_id = { 3, 0xff, 2, 0xff },
6360a552a69cSDamon Ding 		.reg_offset = 0x400,
6361a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6362a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6363a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6364a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6365a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6366a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6367a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6368a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6369a552a69cSDamon Ding 		.axi_id = 1,
6370a552a69cSDamon Ding 		.axi_yrgb_id = 0x0a,
6371a552a69cSDamon Ding 		.axi_uv_id = 0x0b,
6372a552a69cSDamon Ding 		.possible_crtcs = 0x5,/* vp0 or vp2 */
6373a552a69cSDamon Ding 		.max_upscale_factor = 8,
6374a552a69cSDamon Ding 		.max_downscale_factor = 8,
6375a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6376a552a69cSDamon Ding 	},
6377a552a69cSDamon Ding 
6378a552a69cSDamon Ding 	{
6379a552a69cSDamon Ding 		.name = "Esmart3",
6380a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
6381a552a69cSDamon Ding 		.type = ESMART_LAYER,
6382a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 3, 3, 0xff },
6383a552a69cSDamon Ding 		.reg_offset = 0x600,
6384a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6385a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6386a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6387a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6388a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6389a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6390a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6391a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6392a552a69cSDamon Ding 		.axi_id = 1,
6393a552a69cSDamon Ding 		.axi_yrgb_id = 0x0c,
6394a552a69cSDamon Ding 		.axi_uv_id = 0x0d,
6395a552a69cSDamon Ding 		.possible_crtcs = 0x6,/* vp1 or vp2 */
6396a552a69cSDamon Ding 		.max_upscale_factor = 8,
6397a552a69cSDamon Ding 		.max_downscale_factor = 8,
6398a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6399a552a69cSDamon Ding 	},
6400a552a69cSDamon Ding 
6401a552a69cSDamon Ding 	{
6402a552a69cSDamon Ding 		.name = "Cluster0",
6403a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
6404a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
6405a552a69cSDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
6406a552a69cSDamon Ding 		.reg_offset = 0x0,
6407a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
6408a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
6409a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6410a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6411a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6412a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6413a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6414a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
6415a552a69cSDamon Ding 		.axi_yrgb_id = 0x02,
6416a552a69cSDamon Ding 		.axi_uv_id = 0x03,
6417a552a69cSDamon Ding 		.possible_crtcs = 0x3,/* vp0 or vp1 */
6418a552a69cSDamon Ding 		.max_upscale_factor = 8,
6419a552a69cSDamon Ding 		.max_downscale_factor = 8,
6420a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
6421a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI,
6422a552a69cSDamon Ding 	},
6423a552a69cSDamon Ding 
6424a552a69cSDamon Ding 	{
6425a552a69cSDamon Ding 		.name = "Cluster1",
6426a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
6427a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
6428a552a69cSDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
6429a552a69cSDamon Ding 		.reg_offset = 0x200,
6430a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
6431a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
6432a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6433a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6434a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6435a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6436a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6437a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
6438a552a69cSDamon Ding 		.axi_yrgb_id = 0x06,
6439a552a69cSDamon Ding 		.axi_uv_id = 0x07,
6440a552a69cSDamon Ding 		.possible_crtcs = 0x3,/* vp0 or vp1 */
6441a552a69cSDamon Ding 		.max_upscale_factor = 8,
6442a552a69cSDamon Ding 		.max_downscale_factor = 8,
6443a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
6444a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH,
6445a552a69cSDamon Ding 	},
6446a552a69cSDamon Ding };
6447a552a69cSDamon Ding 
6448a552a69cSDamon Ding static struct vop2_vp_data rk3576_vp_data[3] = {
6449a552a69cSDamon Ding 	{
6450a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR |
6451a552a69cSDamon Ding 			   VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT |
6452a552a69cSDamon Ding 			   VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP,
6453a552a69cSDamon Ding 		.max_output = { 4096, 4096 },
6454a552a69cSDamon Ding 		.hdrvivid_dly = 21,
6455a552a69cSDamon Ding 		.sdr2hdr_dly = 21,
6456a552a69cSDamon Ding 		.layer_mix_dly = 8,
6457a552a69cSDamon Ding 		.hdr_mix_dly = 2,
6458a552a69cSDamon Ding 		.win_dly = 10,
6459a552a69cSDamon Ding 		.pixel_rate = 2,
6460a552a69cSDamon Ding 	},
6461a552a69cSDamon Ding 	{
6462a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN |
6463a552a69cSDamon Ding 			   VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2,
6464a552a69cSDamon Ding 		.max_output = { 2560, 2560 },
6465a552a69cSDamon Ding 		.hdrvivid_dly = 0,
6466a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
6467a552a69cSDamon Ding 		.layer_mix_dly = 6,
6468a552a69cSDamon Ding 		.hdr_mix_dly = 0,
6469a552a69cSDamon Ding 		.win_dly = 10,
6470a552a69cSDamon Ding 		.pixel_rate = 1,
6471a552a69cSDamon Ding 	},
6472a552a69cSDamon Ding 	{
6473a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6474a552a69cSDamon Ding 		.max_output = { 1920, 1920 },
6475a552a69cSDamon Ding 		.hdrvivid_dly = 0,
6476a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
6477a552a69cSDamon Ding 		.layer_mix_dly = 6,
6478a552a69cSDamon Ding 		.hdr_mix_dly = 0,
6479a552a69cSDamon Ding 		.win_dly = 10,
6480a552a69cSDamon Ding 		.pixel_rate = 1,
6481a552a69cSDamon Ding 	},
6482a552a69cSDamon Ding };
6483a552a69cSDamon Ding 
6484a552a69cSDamon Ding static struct vop2_power_domain_data rk3576_vop_pd_data[] = {
6485a552a69cSDamon Ding 	{
6486a552a69cSDamon Ding 		.id = VOP2_PD_CLUSTER,
6487a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1),
6488a552a69cSDamon Ding 	},
6489a552a69cSDamon Ding 	{
6490a552a69cSDamon Ding 		.id = VOP2_PD_ESMART,
6491a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) |
6492a552a69cSDamon Ding 				  BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3),
6493a552a69cSDamon Ding 	},
6494a552a69cSDamon Ding };
6495a552a69cSDamon Ding 
6496a552a69cSDamon Ding static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = {
6497a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_4K_MODE, 2},
6498a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_2K_2K_MODE, 3}
6499a552a69cSDamon Ding };
6500a552a69cSDamon Ding 
6501a552a69cSDamon Ding const struct vop2_data rk3576_vop = {
6502a552a69cSDamon Ding 	.version = VOP_VERSION_RK3576,
6503a552a69cSDamon Ding 	.nr_vps = 3,
6504a552a69cSDamon Ding 	.nr_mixers = 4,
6505a552a69cSDamon Ding 	.nr_layers = 6,
6506a552a69cSDamon Ding 	.nr_gammas = 3,
6507a552a69cSDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE,
6508a552a69cSDamon Ding 	.esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map),
6509a552a69cSDamon Ding 	.esmart_lb_mode_map = rk3576_esmart_lb_mode_map,
6510a552a69cSDamon Ding 	.vp_data = rk3576_vp_data,
6511a552a69cSDamon Ding 	.win_data = rk3576_win_data,
6512a552a69cSDamon Ding 	.plane_table = rk3576_plane_table,
6513a552a69cSDamon Ding 	.pd = rk3576_vop_pd_data,
6514a552a69cSDamon Ding 	.vp_default_primary_plane = rk3576_vp_default_primary_plane,
6515a552a69cSDamon Ding 	.nr_pd = ARRAY_SIZE(rk3576_vop_pd_data),
6516a552a69cSDamon Ding 	.dump_regs = rk3576_dump_regs,
6517a552a69cSDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3576_dump_regs),
6518a552a69cSDamon Ding };
6519a552a69cSDamon Ding 
6520337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
6521337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6522337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6523337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
6524337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
6525337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER0,
6526337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER1,
6527337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER2,
6528337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER3,
6529337d1c13SDamon Ding };
6530337d1c13SDamon Ding 
6531ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6532ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6533ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6534ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER},
6535ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER},
6536ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6537ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6538ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
6539ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
6540ecc31b6eSAndy Yan };
6541ecc31b6eSAndy Yan 
654272388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = {
654372388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
654472388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
654572388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
654672388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
654772388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
654872388c26SDamon Ding 	{ RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 },
654972388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
655072388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
655172388c26SDamon Ding 	{ RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 },
655272388c26SDamon Ding 	{ RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 },
655372388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
655472388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
655572388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
655672388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
655772388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
655872388c26SDamon Ding };
655972388c26SDamon Ding 
6560ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
6561ecc31b6eSAndy Yan 	{ /* one display policy */
6562ecc31b6eSAndy Yan 		{/* main display */
6563608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6564ecc31b6eSAndy Yan 			.attached_layers_nr = 8,
6565ecc31b6eSAndy Yan 			.attached_layers = {
6566ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2,
6567ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3,
6568ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3
6569ecc31b6eSAndy Yan 			},
6570ecc31b6eSAndy Yan 		},
6571ecc31b6eSAndy Yan 		{/* second display */},
6572ecc31b6eSAndy Yan 		{/* third  display */},
6573ecc31b6eSAndy Yan 		{/* fourth display */},
6574ecc31b6eSAndy Yan 	},
6575ecc31b6eSAndy Yan 
6576ecc31b6eSAndy Yan 	{ /* two display policy */
6577ecc31b6eSAndy Yan 		{/* main display */
6578608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6579ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
6580ecc31b6eSAndy Yan 			.attached_layers = {
6581ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
6582ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1
6583ecc31b6eSAndy Yan 			},
6584ecc31b6eSAndy Yan 		},
6585ecc31b6eSAndy Yan 
6586ecc31b6eSAndy Yan 		{/* second display */
6587608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6588ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
6589ecc31b6eSAndy Yan 			.attached_layers = {
6590ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2,
6591ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
6592ecc31b6eSAndy Yan 			},
6593ecc31b6eSAndy Yan 		},
6594ecc31b6eSAndy Yan 		{/* third  display */},
6595ecc31b6eSAndy Yan 		{/* fourth display */},
6596ecc31b6eSAndy Yan 	},
6597ecc31b6eSAndy Yan 
6598ecc31b6eSAndy Yan 	{ /* three display policy */
6599ecc31b6eSAndy Yan 		{/* main display */
6600608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6601ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
6602ecc31b6eSAndy Yan 			.attached_layers = {
6603ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0
6604ecc31b6eSAndy Yan 			},
6605ecc31b6eSAndy Yan 		},
6606ecc31b6eSAndy Yan 
6607ecc31b6eSAndy Yan 		{/* second display */
6608608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
6609ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
6610ecc31b6eSAndy Yan 			.attached_layers = {
6611ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1
6612ecc31b6eSAndy Yan 			},
6613ecc31b6eSAndy Yan 		},
6614ecc31b6eSAndy Yan 
6615ecc31b6eSAndy Yan 		{/* third  display */
6616ecc31b6eSAndy Yan 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6617ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6618ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
6619ecc31b6eSAndy Yan 		},
6620ecc31b6eSAndy Yan 
6621ecc31b6eSAndy Yan 		{/* fourth display */},
6622ecc31b6eSAndy Yan 	},
6623ecc31b6eSAndy Yan 
6624ecc31b6eSAndy Yan 	{ /* four display policy */
6625ecc31b6eSAndy Yan 		{/* main display */
6626608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6627ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6628ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
6629ecc31b6eSAndy Yan 		},
6630ecc31b6eSAndy Yan 
6631ecc31b6eSAndy Yan 		{/* second display */
6632608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
6633ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6634ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
6635ecc31b6eSAndy Yan 		},
6636ecc31b6eSAndy Yan 
6637ecc31b6eSAndy Yan 		{/* third  display */
6638608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6639ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6640ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
6641ecc31b6eSAndy Yan 		},
6642ecc31b6eSAndy Yan 
6643ecc31b6eSAndy Yan 		{/* fourth display */
6644608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
6645ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6646ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
6647ecc31b6eSAndy Yan 		},
6648ecc31b6eSAndy Yan 	},
6649ecc31b6eSAndy Yan 
6650ecc31b6eSAndy Yan };
6651ecc31b6eSAndy Yan 
6652ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = {
6653ecc31b6eSAndy Yan 	{
6654ecc31b6eSAndy Yan 		.name = "Cluster0",
6655ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
6656ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER1,
6657ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6658ecc31b6eSAndy Yan 		.win_sel_port_offset = 0,
66595fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0 },
6660ecc31b6eSAndy Yan 		.reg_offset = 0,
6661a33b790fSDamon Ding 		.axi_id = 0,
6662a33b790fSDamon Ding 		.axi_yrgb_id = 2,
6663a33b790fSDamon Ding 		.axi_uv_id = 3,
6664b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER0,
66655fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
66665fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
66675fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
66685fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
66694c765862SDamon Ding 		.max_upscale_factor = 4,
66704c765862SDamon Ding 		.max_downscale_factor = 4,
6671ecc31b6eSAndy Yan 	},
6672ecc31b6eSAndy Yan 
6673ecc31b6eSAndy Yan 	{
6674ecc31b6eSAndy Yan 		.name = "Cluster1",
6675ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
6676ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6677ecc31b6eSAndy Yan 		.win_sel_port_offset = 1,
66785fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 1 },
6679ecc31b6eSAndy Yan 		.reg_offset = 0x200,
6680a33b790fSDamon Ding 		.axi_id = 0,
6681a33b790fSDamon Ding 		.axi_yrgb_id = 6,
6682a33b790fSDamon Ding 		.axi_uv_id = 7,
6683b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER1,
66845fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
66855fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
66865fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
66875fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
66884c765862SDamon Ding 		.max_upscale_factor = 4,
66894c765862SDamon Ding 		.max_downscale_factor = 4,
6690ecc31b6eSAndy Yan 	},
6691ecc31b6eSAndy Yan 
6692ecc31b6eSAndy Yan 	{
6693ecc31b6eSAndy Yan 		.name = "Cluster2",
6694ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
6695ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
6696ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6697ecc31b6eSAndy Yan 		.win_sel_port_offset = 2,
66985fa6e665SDamon Ding 		.layer_sel_win_id = { 4, 4, 4, 4 },
6699ecc31b6eSAndy Yan 		.reg_offset = 0x400,
6700a33b790fSDamon Ding 		.axi_id = 1,
6701a33b790fSDamon Ding 		.axi_yrgb_id = 2,
6702a33b790fSDamon Ding 		.axi_uv_id = 3,
6703b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER2,
67045fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67055fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67065fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67075fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67084c765862SDamon Ding 		.max_upscale_factor = 4,
67094c765862SDamon Ding 		.max_downscale_factor = 4,
6710ecc31b6eSAndy Yan 	},
6711ecc31b6eSAndy Yan 
6712ecc31b6eSAndy Yan 	{
6713ecc31b6eSAndy Yan 		.name = "Cluster3",
6714ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
6715ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6716ecc31b6eSAndy Yan 		.win_sel_port_offset = 3,
67175fa6e665SDamon Ding 		.layer_sel_win_id = { 5, 5, 5, 5 },
6718ecc31b6eSAndy Yan 		.reg_offset = 0x600,
6719a33b790fSDamon Ding 		.axi_id = 1,
6720a33b790fSDamon Ding 		.axi_yrgb_id = 6,
6721a33b790fSDamon Ding 		.axi_uv_id = 7,
6722b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER3,
67235fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67245fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67255fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67265fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67274c765862SDamon Ding 		.max_upscale_factor = 4,
67284c765862SDamon Ding 		.max_downscale_factor = 4,
6729ecc31b6eSAndy Yan 	},
6730ecc31b6eSAndy Yan 
6731ecc31b6eSAndy Yan 	{
6732ecc31b6eSAndy Yan 		.name = "Esmart0",
6733ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6734ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART1,
6735ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6736ecc31b6eSAndy Yan 		.win_sel_port_offset = 4,
67375fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 2 },
6738ecc31b6eSAndy Yan 		.reg_offset = 0,
6739a33b790fSDamon Ding 		.axi_id = 0,
6740a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
6741a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
67425fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67435fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67445fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67455fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67464c765862SDamon Ding 		.max_upscale_factor = 8,
67474c765862SDamon Ding 		.max_downscale_factor = 8,
6748ecc31b6eSAndy Yan 	},
6749ecc31b6eSAndy Yan 
6750ecc31b6eSAndy Yan 	{
6751ecc31b6eSAndy Yan 		.name = "Esmart1",
6752ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6753ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6754ecc31b6eSAndy Yan 		.win_sel_port_offset = 5,
67555fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 3 },
6756ecc31b6eSAndy Yan 		.reg_offset = 0x200,
6757a33b790fSDamon Ding 		.axi_id = 0,
6758a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
6759a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
6760b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
67615fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67625fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67635fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67645fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67654c765862SDamon Ding 		.max_upscale_factor = 8,
67664c765862SDamon Ding 		.max_downscale_factor = 8,
6767ecc31b6eSAndy Yan 	},
6768ecc31b6eSAndy Yan 
6769ecc31b6eSAndy Yan 	{
6770ecc31b6eSAndy Yan 		.name = "Esmart2",
6771ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART2,
6772ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART3,
6773ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6774ecc31b6eSAndy Yan 		.win_sel_port_offset = 6,
67755fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 6 },
6776ecc31b6eSAndy Yan 		.reg_offset = 0x400,
6777a33b790fSDamon Ding 		.axi_id = 1,
6778a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
6779a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
6780b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
67815fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67825fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67835fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67845fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67854c765862SDamon Ding 		.max_upscale_factor = 8,
67864c765862SDamon Ding 		.max_downscale_factor = 8,
6787ecc31b6eSAndy Yan 	},
6788ecc31b6eSAndy Yan 
6789ecc31b6eSAndy Yan 	{
6790ecc31b6eSAndy Yan 		.name = "Esmart3",
6791ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART3,
6792ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6793ecc31b6eSAndy Yan 		.win_sel_port_offset = 7,
67945fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 7 },
6795ecc31b6eSAndy Yan 		.reg_offset = 0x600,
6796a33b790fSDamon Ding 		.axi_id = 1,
6797a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
6798a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
6799b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
68005fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
68015fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
68025fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
68035fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
68044c765862SDamon Ding 		.max_upscale_factor = 8,
68054c765862SDamon Ding 		.max_downscale_factor = 8,
6806ecc31b6eSAndy Yan 	},
6807ecc31b6eSAndy Yan };
6808ecc31b6eSAndy Yan 
680912ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = {
681012ee5af0SDamon Ding 	{0x00000000, "no error detected by DSC encoder"},
681112ee5af0SDamon Ding 	{0x0030ffff, "bits per component error"},
681212ee5af0SDamon Ding 	{0x0040ffff, "multiple mode error"},
681312ee5af0SDamon Ding 	{0x0050ffff, "line buffer depth error"},
681412ee5af0SDamon Ding 	{0x0060ffff, "minor version error"},
681512ee5af0SDamon Ding 	{0x0070ffff, "picture height error"},
681612ee5af0SDamon Ding 	{0x0080ffff, "picture width error"},
681712ee5af0SDamon Ding 	{0x0090ffff, "number of slices error"},
681812ee5af0SDamon Ding 	{0x00c0ffff, "slice height Error "},
681912ee5af0SDamon Ding 	{0x00d0ffff, "slice width error"},
682012ee5af0SDamon Ding 	{0x00e0ffff, "second line BPG offset error"},
682112ee5af0SDamon Ding 	{0x00f0ffff, "non second line BPG offset error"},
682212ee5af0SDamon Ding 	{0x0100ffff, "PPS ID error"},
682312ee5af0SDamon Ding 	{0x0110ffff, "bits per pixel (BPP) Error"},
682412ee5af0SDamon Ding 	{0x0120ffff, "buffer flow error"},  /* dsc_buffer_flow */
682512ee5af0SDamon Ding 
682612ee5af0SDamon Ding 	{0x01510001, "slice 0 RC buffer model overflow error"},
682712ee5af0SDamon Ding 	{0x01510002, "slice 1 RC buffer model overflow error"},
682812ee5af0SDamon Ding 	{0x01510004, "slice 2 RC buffer model overflow error"},
682912ee5af0SDamon Ding 	{0x01510008, "slice 3 RC buffer model overflow error"},
683012ee5af0SDamon Ding 	{0x01510010, "slice 4 RC buffer model overflow error"},
683112ee5af0SDamon Ding 	{0x01510020, "slice 5 RC buffer model overflow error"},
683212ee5af0SDamon Ding 	{0x01510040, "slice 6 RC buffer model overflow error"},
683312ee5af0SDamon Ding 	{0x01510080, "slice 7 RC buffer model overflow error"},
683412ee5af0SDamon Ding 
683512ee5af0SDamon Ding 	{0x01610001, "slice 0 RC buffer model underflow error"},
683612ee5af0SDamon Ding 	{0x01610002, "slice 1 RC buffer model underflow error"},
683712ee5af0SDamon Ding 	{0x01610004, "slice 2 RC buffer model underflow error"},
683812ee5af0SDamon Ding 	{0x01610008, "slice 3 RC buffer model underflow error"},
683912ee5af0SDamon Ding 	{0x01610010, "slice 4 RC buffer model underflow error"},
684012ee5af0SDamon Ding 	{0x01610020, "slice 5 RC buffer model underflow error"},
684112ee5af0SDamon Ding 	{0x01610040, "slice 6 RC buffer model underflow error"},
684212ee5af0SDamon Ding 	{0x01610080, "slice 7 RC buffer model underflow error"},
684312ee5af0SDamon Ding 
684412ee5af0SDamon Ding 	{0xffffffff, "unsuccessful RESET cycle status"},
684512ee5af0SDamon Ding 	{0x00a0ffff, "ICH full error precision settings error"},
684612ee5af0SDamon Ding 	{0x0020ffff, "native mode"},
684712ee5af0SDamon Ding };
684812ee5af0SDamon Ding 
684912ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = {
685012ee5af0SDamon Ding 	{0x00000000, "rate buffer status"},
685112ee5af0SDamon Ding 	{0x00000001, "line buffer status"},
685212ee5af0SDamon Ding 	{0x00000002, "decoder model status"},
685312ee5af0SDamon Ding 	{0x00000003, "pixel buffer status"},
685412ee5af0SDamon Ding 	{0x00000004, "balance fifo buffer status"},
685512ee5af0SDamon Ding 	{0x00000005, "syntax element fifo status"},
685612ee5af0SDamon Ding };
685712ee5af0SDamon Ding 
685812ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = {
685912ee5af0SDamon Ding 	{
686012ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_8K,
686112ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_8K,
686212ee5af0SDamon Ding 		.max_slice_num = 8,
686312ee5af0SDamon Ding 		.max_linebuf_depth = 11,
6864b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
686512ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
686612ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_8k_txp_clk",
686712ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_8k_pxl_clk",
686812ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_8k_cds_clk",
686912ee5af0SDamon Ding 	},
687012ee5af0SDamon Ding 
687112ee5af0SDamon Ding 	{
687212ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_4K,
687312ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_4K,
687412ee5af0SDamon Ding 		.max_slice_num = 2,
687512ee5af0SDamon Ding 		.max_linebuf_depth = 11,
6876b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
687712ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
687812ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_4k_txp_clk",
687912ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_4k_pxl_clk",
688012ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_4k_cds_clk",
688112ee5af0SDamon Ding 	},
688212ee5af0SDamon Ding };
688312ee5af0SDamon Ding 
6884ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = {
6885ecc31b6eSAndy Yan 	{
6886ee01dbb2SDamon Ding 		.splice_vp_id = 1,
6887ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
6888b890760eSAlgea Cao 		.pre_scan_max_dly = 54,
6889ecc31b6eSAndy Yan 		.max_dclk = 600000,
6890ecc31b6eSAndy Yan 		.max_output = {7680, 4320},
6891ecc31b6eSAndy Yan 	},
6892ecc31b6eSAndy Yan 	{
6893ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
6894ee01dbb2SDamon Ding 		.pre_scan_max_dly = 54,
6895ecc31b6eSAndy Yan 		.max_dclk = 600000,
6896ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
6897ecc31b6eSAndy Yan 	},
6898ecc31b6eSAndy Yan 	{
6899ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
6900ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
6901ecc31b6eSAndy Yan 		.max_dclk = 600000,
6902ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
6903ecc31b6eSAndy Yan 	},
6904ecc31b6eSAndy Yan 	{
6905ecc31b6eSAndy Yan 		.feature = 0,
6906ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
6907ecc31b6eSAndy Yan 		.max_dclk = 200000,
6908ecc31b6eSAndy Yan 		.max_output = {1920, 1080},
6909ecc31b6eSAndy Yan 	},
6910ecc31b6eSAndy Yan };
6911ecc31b6eSAndy Yan 
6912b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = {
6913b6ba80b4SDamon Ding 	{
6914b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER0,
6915b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0),
6916b6ba80b4SDamon Ding 	},
6917b6ba80b4SDamon Ding 	{
6918b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER1,
6919b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1),
6920b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
6921b6ba80b4SDamon Ding 	},
6922b6ba80b4SDamon Ding 	{
6923b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER2,
6924b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2),
6925b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
6926b6ba80b4SDamon Ding 	},
6927b6ba80b4SDamon Ding 	{
6928b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER3,
6929b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3),
6930b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
6931b6ba80b4SDamon Ding 	},
6932b6ba80b4SDamon Ding 	{
6933b6ba80b4SDamon Ding 	  .id = VOP2_PD_ESMART,
6934b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) |
6935b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART2) |
6936b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART3),
6937b6ba80b4SDamon Ding 	},
6938b6ba80b4SDamon Ding 	{
6939b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_8K,
6940b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K),
6941b6ba80b4SDamon Ding 	},
6942b6ba80b4SDamon Ding 	{
6943b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_4K,
6944b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K),
6945b6ba80b4SDamon Ding 	},
6946b6ba80b4SDamon Ding };
6947b6ba80b4SDamon Ding 
6948ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = {
6949ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3588,
6950ecc31b6eSAndy Yan 	.nr_vps = 4,
6951ecc31b6eSAndy Yan 	.vp_data = rk3588_vp_data,
6952ecc31b6eSAndy Yan 	.win_data = rk3588_win_data,
6953ecc31b6eSAndy Yan 	.plane_mask = rk3588_vp_plane_mask[0],
6954ecc31b6eSAndy Yan 	.plane_table = rk3588_plane_table,
6955b6ba80b4SDamon Ding 	.pd = rk3588_vop_pd_data,
695612ee5af0SDamon Ding 	.dsc = rk3588_dsc_data,
695712ee5af0SDamon Ding 	.dsc_error_ecw = dsc_ecw,
695812ee5af0SDamon Ding 	.dsc_error_buffer_flow = dsc_buffer_flow,
6959337d1c13SDamon Ding 	.vp_primary_plane_order = rk3588_vp_primary_plane_order,
6960ecc31b6eSAndy Yan 	.nr_layers = 8,
6961ecc31b6eSAndy Yan 	.nr_mixers = 7,
6962ecc31b6eSAndy Yan 	.nr_gammas = 4,
6963b6ba80b4SDamon Ding 	.nr_pd = ARRAY_SIZE(rk3588_vop_pd_data),
696412ee5af0SDamon Ding 	.nr_dscs = 2,
696512ee5af0SDamon Ding 	.nr_dsc_ecw = ARRAY_SIZE(dsc_ecw),
696612ee5af0SDamon Ding 	.nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow),
696772388c26SDamon Ding 	.dump_regs = rk3588_dump_regs,
696872388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3588_dump_regs),
6969ecc31b6eSAndy Yan };
6970ecc31b6eSAndy Yan 
6971d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
6972d0408543SAndy Yan 	.preinit = rockchip_vop2_preinit,
6973d0408543SAndy Yan 	.prepare = rockchip_vop2_prepare,
6974d0408543SAndy Yan 	.init = rockchip_vop2_init,
6975d0408543SAndy Yan 	.set_plane = rockchip_vop2_set_plane,
6976d0408543SAndy Yan 	.enable = rockchip_vop2_enable,
6977d0408543SAndy Yan 	.disable = rockchip_vop2_disable,
6978b0989546SSandy Huang 	.fixup_dts = rockchip_vop2_fixup_dts,
69790675a2a4SDamon Ding 	.send_mcu_cmd = rockchip_vop2_send_mcu_cmd,
6980820a5c17SDamon Ding 	.check = rockchip_vop2_check,
698122007755SDamon Ding 	.mode_valid = rockchip_vop2_mode_valid,
6982b02eb70bSDamon Ding 	.mode_fixup = rockchip_vop2_mode_fixup,
69834c765862SDamon Ding 	.plane_check = rockchip_vop2_plane_check,
698472388c26SDamon Ding 	.regs_dump = rockchip_vop2_regs_dump,
698572388c26SDamon Ding 	.active_regs_dump = rockchip_vop2_active_regs_dump,
69868e7ef808SDamon Ding 	.apply_soft_te = rockchip_vop2_apply_soft_te,
6987d0408543SAndy Yan };
6988