xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_vop2.c (revision 13bc92e8e3d80098c8ceb8e939088a774109de8d)
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>
320669ab1fSDamon Ding #include <dm/of_access.h>
33d0408543SAndy Yan 
34d0408543SAndy Yan #include "rockchip_display.h"
35d0408543SAndy Yan #include "rockchip_crtc.h"
36d0408543SAndy Yan #include "rockchip_connector.h"
37d8e7f4a5SSandy Huang #include "rockchip_phy.h"
386027c871SZhang Yubing #include "rockchip_post_csc.h"
39d0408543SAndy Yan 
40d0408543SAndy Yan /* System registers definition */
41d0408543SAndy Yan #define RK3568_REG_CFG_DONE			0x000
42d0408543SAndy Yan #define	CFG_DONE_EN				BIT(15)
43d0408543SAndy Yan 
44d0408543SAndy Yan #define RK3568_VERSION_INFO			0x004
45d0408543SAndy Yan #define EN_MASK					1
46d0408543SAndy Yan 
4763cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL			0x008
480675a2a4SDamon Ding #define AUTO_GATING_EN_SHIFT			31
490675a2a4SDamon Ding #define PORT_DCLK_AUTO_GATING_EN_SHIFT		14
50bb7ec356SDamon Ding #define ACLK_PRE_AUTO_GATING_EN_SHIFT		7
5163cb669fSSandy Huang 
5244b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL0_IMD		0x014
5344b1b62cSDamon Ding #define AXI0_PORT_URGENCY_EN_SHIFT		24
5444b1b62cSDamon Ding 
5544b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL1_IMD		0x018
5644b1b62cSDamon Ding #define AXI1_PORT_URGENCY_EN_SHIFT		24
5744b1b62cSDamon Ding 
58a552a69cSDamon Ding #define RK3576_SYS_MMU_CTRL			0x020
59a552a69cSDamon Ding #define RKMMU_V2_EN_SHIFT			0
60a552a69cSDamon Ding #define RKMMU_V2_SEL_AXI_SHIFT			1
61a552a69cSDamon Ding 
626414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL			0x024
636414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT			0
64aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT			16
656414e3bcSSandy Huang 
66d0408543SAndy Yan #define RK3568_DSP_IF_EN			0x028
67d0408543SAndy Yan #define RGB_EN_SHIFT				0
68ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT			0
69ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT			1
70ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT			8
71d0408543SAndy Yan #define HDMI0_EN_SHIFT				1
72d0408543SAndy Yan #define EDP0_EN_SHIFT				3
73ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT			2
74ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT			3
75d0408543SAndy Yan #define MIPI0_EN_SHIFT				4
76ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT			4
77ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT			5
78ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT			6
79d0408543SAndy Yan #define MIPI1_EN_SHIFT				20
80ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT			7
81d0408543SAndy Yan #define LVDS0_EN_SHIFT				5
82d0408543SAndy Yan #define LVDS1_EN_SHIFT				24
83d0408543SAndy Yan #define BT1120_EN_SHIFT				6
84d0408543SAndy Yan #define BT656_EN_SHIFT				7
85d0408543SAndy Yan #define IF_MUX_MASK				3
86d0408543SAndy Yan #define RGB_MUX_SHIFT				8
87d0408543SAndy Yan #define HDMI0_MUX_SHIFT				10
88ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT			12
89ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT			14
90d0408543SAndy Yan #define EDP0_MUX_SHIFT				14
91ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT		16
92ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT		18
93d0408543SAndy Yan #define MIPI0_MUX_SHIFT				16
94ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT			20
95d0408543SAndy Yan #define MIPI1_MUX_SHIFT				21
9611f53190SSandy Huang #define LVDS0_MUX_SHIFT				18
97d0408543SAndy Yan #define LVDS1_MUX_SHIFT				25
98d0408543SAndy Yan 
99a552a69cSDamon Ding #define RK3576_SYS_PORT_CTRL			0x028
100a552a69cSDamon Ding #define VP_INTR_MERGE_EN_SHIFT			14
10112ee4de7SDamon Ding #define RK3576_DSP_VS_T_SEL_SHIFT		4
102a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_MASK		0x7
103a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_SHIFT		0
104a552a69cSDamon Ding 
105d0408543SAndy Yan #define RK3568_DSP_IF_CTRL			0x02c
106d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT			0
1075d2768f7SDamon Ding #define RK3588_BT656_UV_SWAP_SHIFT		0
108d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT		1
1095d2768f7SDamon Ding #define RK3588_BT656_YC_SWAP_SHIFT		1
110d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT			2
1115fa6e665SDamon Ding #define BT656_UV_SWAP				4
1125d2768f7SDamon Ding #define RK3588_BT1120_UV_SWAP_SHIFT		4
1135fa6e665SDamon Ding #define BT656_YC_SWAP				5
1145d2768f7SDamon Ding #define RK3588_BT1120_YC_SWAP_SHIFT		5
1155fa6e665SDamon Ding #define BT656_DCLK_POL				6
1160a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT		8
1170a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT		8
1180a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT			9
11941874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT		10
12041874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT		11
12141874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT		12
12241874944SGuochun Huang 
123d0408543SAndy Yan #define RK3568_DSP_IF_POL			0x030
124d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT		28
125d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT		19
126de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_MASK		0x7
127de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_SHIFT		16
128d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT		15
1297bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_MASK		0x7
1307bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_SHIFT		12
131d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT		7
13210ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK		0x7
13310ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT		4
13415f69071SDamon Ding #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT		3
13515f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_MASK		0x7
13615f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT		0
137ecc31b6eSAndy Yan 
138452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT		15
139452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT		12
140452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK			0x7
141452afb13SDamon Ding 
142ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT		8
143ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT		12
144ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK			0x7
145ecc31b6eSAndy Yan 
146ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT		16
147ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT		18
148ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT		20
149ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT		22
150ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT			24
151ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT			26
152ecc31b6eSAndy Yan 
153a552a69cSDamon Ding #define RK3576_SYS_CLUSTER_PD_CTRL		0x030
154a552a69cSDamon Ding #define RK3576_CLUSTER_PD_EN_SHIFT		0
155a552a69cSDamon Ding 
156a552a69cSDamon Ding #define RK3588_SYS_PD_CTRL			0x034
157a552a69cSDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT		0
158a552a69cSDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT		1
159a552a69cSDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT		2
160a552a69cSDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT		3
161a552a69cSDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT		5
162a552a69cSDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT		6
163a552a69cSDamon Ding #define RK3588_ESMART_PD_EN_SHIFT		7
164a552a69cSDamon Ding 
165a552a69cSDamon Ding #define RK3576_SYS_ESMART_PD_CTRL		0x034
166a552a69cSDamon Ding #define RK3576_ESMART_PD_EN_SHIFT		0
167a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_SHIFT		6
168a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_MASK		0x3
169a552a69cSDamon Ding 
170feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN			0x50
171feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT			0
1721147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL			0x58
1731147facaSSandy Huang #define GAMMA_PORT_SEL_MASK			0x3
1741147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT			0
175db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK		0x3
176db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT		12
177ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT			16
1785fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK			0x3
1795fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT		26
1801147facaSSandy Huang 
181d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG			0x70
182d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG			0x74
183d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG			0x78
184d0408543SAndy Yan #define RK3568_SYS0_INT_EN			0x80
185d0408543SAndy Yan #define RK3568_SYS0_INT_CLR			0x84
186d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS			0x88
187d0408543SAndy Yan #define RK3568_SYS1_INT_EN			0x90
188d0408543SAndy Yan #define RK3568_SYS1_INT_CLR			0x94
189d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS			0x98
190d0408543SAndy Yan #define RK3568_VP0_INT_EN			0xA0
191d0408543SAndy Yan #define RK3568_VP0_INT_CLR			0xA4
192d0408543SAndy Yan #define RK3568_VP0_INT_STATUS			0xA8
193d0408543SAndy Yan #define RK3568_VP1_INT_EN			0xB0
194d0408543SAndy Yan #define RK3568_VP1_INT_CLR			0xB4
195d0408543SAndy Yan #define RK3568_VP1_INT_STATUS			0xB8
196d0408543SAndy Yan #define RK3568_VP2_INT_EN			0xC0
197d0408543SAndy Yan #define RK3568_VP2_INT_CLR			0xC4
198d0408543SAndy Yan #define RK3568_VP2_INT_STATUS			0xC8
199a552a69cSDamon Ding #define RK3568_VP2_INT_RAW_STATUS		0xCC
200a552a69cSDamon Ding #define RK3588_VP3_INT_EN			0xD0
201a552a69cSDamon Ding #define RK3588_VP3_INT_CLR			0xD4
202a552a69cSDamon Ding #define RK3588_VP3_INT_STATUS			0xD8
203a552a69cSDamon Ding #define RK3576_WB_CTRL				0x100
204a552a69cSDamon Ding #define RK3576_WB_XSCAL_FACTOR			0x104
205a552a69cSDamon Ding #define RK3576_WB_YRGB_MST			0x108
206a552a69cSDamon Ding #define RK3576_WB_CBR_MST			0x10C
207a552a69cSDamon Ding #define RK3576_WB_VIR_STRIDE			0x110
208a552a69cSDamon Ding #define RK3576_WB_TIMEOUT_CTRL			0x114
209a552a69cSDamon Ding #define RK3576_MIPI0_IF_CTRL			0x180
210a552a69cSDamon Ding #define RK3576_IF_OUT_EN_SHIFT			0
211a552a69cSDamon Ding #define RK3576_IF_CLK_OUT_EN_SHIFT		1
212a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_SHIFT		2
213a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_MASK			0x3
214a552a69cSDamon Ding #define RK3576_IF_PIN_POL_SHIFT			4
215a552a69cSDamon Ding #define RK3576_IF_PIN_POL_MASK			0x7
216a552a69cSDamon Ding #define RK3576_IF_SPLIT_EN_SHIFT		8
217a552a69cSDamon Ding #define RK3576_IF_DATA1_SEL_SHIFT		9
218a552a69cSDamon Ding #define RK3576_MIPI_CMD_MODE_SHIFT		11
219a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_SHIFT		21
220a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_MASK			0x1
221a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_SHIFT		20
222a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_MASK		0x1
223a552a69cSDamon Ding #define RK3576_IF_REGDONE_IMD_EN_SHIFT		31
224a552a69cSDamon Ding #define RK3576_HDMI0_IF_CTRL			0x184
225a552a69cSDamon Ding #define RK3576_EDP0_IF_CTRL			0x188
226a552a69cSDamon Ding #define RK3576_DP0_IF_CTRL			0x18C
227a552a69cSDamon Ding #define RK3576_RGB_IF_CTRL			0x194
228a552a69cSDamon Ding #define RK3576_BT656_OUT_EN_SHIFT		12
229a552a69cSDamon Ding #define RK3576_BT656_UV_SWAP_SHIFT		13
230a552a69cSDamon Ding #define RK3576_BT656_YC_SWAP_SHIFT		14
231a552a69cSDamon Ding #define RK3576_BT1120_OUT_EN_SHIFT		16
232a552a69cSDamon Ding #define RK3576_BT1120_UV_SWAP_SHIFT		17
233a552a69cSDamon Ding #define RK3576_BT1120_YC_SWAP_SHIFT		18
234a552a69cSDamon Ding #define RK3576_DP1_IF_CTRL			0x1A4
235a552a69cSDamon Ding #define RK3576_DP2_IF_CTRL			0x1B0
23660e469f5SDamon Ding 
237cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL		0x038
238cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT	20
239cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT		24
240cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT	28
241cd6c85a9SDamon Ding 
24260e469f5SDamon Ding #define RK3568_SYS_STATUS0			0x60
24360e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT		8
24460e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT		9
24560e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT		10
24660e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT		11
247b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT		13
248b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT		14
24960e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT		15
250d0408543SAndy Yan 
25166724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0		0x70
25266724b9cSDamon Ding #define LINE_FLAG_NUM_MASK			0x1fff
25366724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT		0
25466724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT		16
25566724b9cSDamon Ding 
25612ee5af0SDamon Ding /* DSC CTRL registers definition */
25712ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL			0x200
25812ee5af0SDamon Ding #define DSC_PORT_SEL_MASK			0x3
25912ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT			0
26012ee5af0SDamon Ding #define DSC_MAN_MODE_MASK			0x1
26112ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT			2
26212ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK			0x3
26312ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT		4
26412ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK			0x3
26512ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT			6
26612ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK			0x1
26712ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT			8
26812ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK			0x3
26912ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT			12
27012ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK			0x3
27112ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT			14
27212ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK			0x1
27312ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT			16
27412ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT			17
27512ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT			18
27612ee5af0SDamon Ding 
27712ee5af0SDamon Ding #define RK3588_DSC_8K_RST			0x204
27812ee5af0SDamon Ding #define RST_DEASSERT_MASK			0x1
27912ee5af0SDamon Ding #define RST_DEASSERT_SHIFT			0
28012ee5af0SDamon Ding 
28112ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE			0x208
28212ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT			0
28312ee5af0SDamon Ding 
28412ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY			0x20C
28512ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK			0xffff
28612ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT			0
28712ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT		16
28812ee5af0SDamon Ding 
28912ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END		0x210
29012ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK			0xffffffff
29112ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT			0
29212ee5af0SDamon Ding 
29312ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END		0x214
29412ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK			0xffffffff
29512ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT			0
29612ee5af0SDamon Ding 
29712ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END		0x218
29812ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK			0xffffffff
29912ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT			0
30012ee5af0SDamon Ding 
30112ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END		0x21C
30212ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK			0xffffffff
30312ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT			0
30412ee5af0SDamon Ding 
30512ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS			0x220
30612ee5af0SDamon Ding 
30763cb669fSSandy Huang /* Overlay registers definition    */
3085fa6e665SDamon Ding #define RK3528_OVL_SYS				0x500
309a552a69cSDamon Ding #define RK3528_OVL_SYS_PORT_SEL			0x504
310a552a69cSDamon Ding #define RK3528_OVL_SYS_GATING_EN		0x508
3115fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL		0x510
3129c7848c3SDamon Ding #define CLUSTER_DLY_NUM_SHIFT			0
3135fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL		0x520
314452afb13SDamon Ding #define ESMART_DLY_NUM_MASK			0xff
315452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT			0
3165fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL		0x524
3175fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL		0x528
3185fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL		0x52C
3195fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL	0x530
3205fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL	0x534
3215fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x538
3225fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL	0x53c
323a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL	0x540
324a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL	0x544
325a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL	0x548
326a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL	0x54c
3275fa6e665SDamon Ding 
3285fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL			0x600
32963cb669fSSandy Huang #define RK3568_OVL_CTRL				0x600
330ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK			0x1
331ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT			0
33263cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
3335fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL		0x604
33463cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL			0x604
33563cb669fSSandy Huang #define LAYER_SEL_MASK				0xf
33663cb669fSSandy Huang 
33763cb669fSSandy Huang #define RK3568_OVL_PORT_SEL			0x608
33863cb669fSSandy Huang #define PORT_MUX_MASK				0xf
33963cb669fSSandy Huang #define PORT_MUX_SHIFT				0
34063cb669fSSandy Huang #define LAYER_SEL_PORT_MASK			0x3
34163cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT			16
34263cb669fSSandy Huang 
34363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
34463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
34563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
34663cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
3475fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL	0x620
3485fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL	0x624
3495fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL	0x628
3505fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL	0x62C
3515fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL	0x630
3525fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL	0x634
3535fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL	0x638
3545fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL	0x63C
3555fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL	0x640
3565fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL	0x644
3575fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL	0x648
3585fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL	0x64C
35963cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
36063cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL		0x654
36163cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
36263cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
363a552a69cSDamon Ding #define RK3576_EXTRA_SRC_COLOR_CTRL		0x650
364a552a69cSDamon Ding #define RK3576_EXTRA_DST_COLOR_CTRL		0x654
365a552a69cSDamon Ding #define RK3576_EXTRA_SRC_ALPHA_CTRL		0x658
366a552a69cSDamon Ding #define RK3576_EXTRA_DST_ALPHA_CTRL		0x65C
3675fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL		0x660
3685fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL		0x664
3695fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL		0x668
3705fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL		0x66C
3715fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL		0x670
37263cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
37363cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
37463cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
37563cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
37663cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL			0x6E0
37763cb669fSSandy Huang #define BG_MIX_CTRL_MASK			0xff
37863cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT			24
37963cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL			0x6E4
38063cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL			0x6E8
38163cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM			0x6F0
3829c7848c3SDamon Ding #define RK3568_CLUSTER_DLY_NUM1			0x6F4
3839c7848c3SDamon Ding #define CLUSTER_DLY_NUM_MASK			0xffff
3849c7848c3SDamon Ding #define CLUSTER0_DLY_NUM_SHIFT			0
3859c7848c3SDamon Ding #define CLUSTER1_DLY_NUM_SHIFT			16
38663cb669fSSandy Huang #define RK3568_SMART_DLY_NUM			0x6F8
3879c7848c3SDamon Ding #define SMART_DLY_NUM_MASK			0xff
3889c7848c3SDamon Ding #define ESMART0_DLY_NUM_SHIFT			0
3899c7848c3SDamon Ding #define ESMART1_DLY_NUM_SHIFT			8
3909c7848c3SDamon Ding #define SMART0_DLY_NUM_SHIFT			16
3919c7848c3SDamon Ding #define SMART1_DLY_NUM_SHIFT			24
39263cb669fSSandy Huang 
3935fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL			0x700
3945fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL		0x704
3955fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL	0x720
3965fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL	0x724
3975fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL	0x728
3985fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL	0x72C
3995fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL	0x730
4005fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL	0x734
4015fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL	0x738
4025fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL	0x73C
4035fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL	0x740
4045fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL	0x744
4055fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL	0x748
4065fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL	0x74C
4075fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL		0x770
408a552a69cSDamon Ding #define RK3576_OVL_PORT2_CTRL			0x800
409a552a69cSDamon Ding #define RK3576_OVL_PORT2_LAYER_SEL		0x804
410a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL	0x820
411a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL	0x824
412a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL	0x828
413a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL	0x82C
414a552a69cSDamon Ding #define RK3576_OVL_PORT2_BG_MIX_CTRL		0x870
4155fa6e665SDamon Ding 
416d0408543SAndy Yan /* Video Port registers definition */
417d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL			0xC00
418d0408543SAndy Yan #define OUT_MODE_MASK				0xf
419d0408543SAndy Yan #define OUT_MODE_SHIFT				0
42010ee9f5bSAlgea Cao #define DATA_SWAP_MASK				0x1f
42110ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT				8
42265747de7SDamon Ding #define DSP_BG_SWAP				0x1
42365747de7SDamon Ding #define DSP_RB_SWAP				0x2
42465747de7SDamon Ding #define DSP_RG_SWAP				0x4
42565747de7SDamon Ding #define DSP_DELTA_SWAP				0x8
42610ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT			4
427d0408543SAndy Yan #define P2I_EN_SHIFT				5
4287a20be36SSandy Huang #define DSP_FILED_POL				6
429d0408543SAndy Yan #define INTERLACE_EN_SHIFT			7
430c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT			13
43110ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT			15
432d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT		16
433d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT			17
434e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_SHIFT			18
435e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_MASK			0x3
436452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT			20
437db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT			22
4381147facaSSandy Huang #define DSP_LUT_EN_SHIFT			28
4391147facaSSandy Huang 
440d0408543SAndy Yan #define STANDBY_EN_SHIFT			31
441d0408543SAndy Yan 
442d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL			0xC04
44310ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT				4
44410ee9f5bSAlgea Cao #define DCLK_DIV2_MASK				0x3
445d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT			20
446d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT			21
44741874944SGuochun Huang #define EDPI_TE_EN				28
44841874944SGuochun Huang #define EDPI_WMS_HOLD_EN			30
44941874944SGuochun Huang #define EDPI_WMS_FS				31
45041874944SGuochun Huang 
451d0408543SAndy Yan 
452d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL		0xC08
45344b1b62cSDamon Ding #define POST_URGENCY_EN_SHIFT			8
45444b1b62cSDamon Ding #define POST_URGENCY_THL_SHIFT			16
45544b1b62cSDamon Ding #define POST_URGENCY_THL_MASK			0xf
45644b1b62cSDamon Ding #define POST_URGENCY_THH_SHIFT			20
45744b1b62cSDamon Ding #define POST_URGENCY_THH_MASK			0xf
4585fa6e665SDamon Ding 
4595fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL			0xC0C
460a552a69cSDamon Ding #define RK3576_DCLK_CORE_SEL_SHIFT		0
461a552a69cSDamon Ding #define RK3576_DCLK_OUT_SEL_SHIFT		2
4625fa6e665SDamon Ding 
4636414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL			0xC10
4646414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT				0
4656414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT			2
4666414e3bcSSandy Huang 
467ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL			0xC0C
468ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT			0
469ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT			2
470ecc31b6eSAndy Yan 
4716414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST			0xC20
4726414e3bcSSandy Huang 
473d0408543SAndy Yan #define RK3568_VP0_DSP_BG			0xC2C
474d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
475d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
476d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
477d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
478d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL		0xC40
4797504507fSSandy Huang #define RK3568_VP0_POST_SCALE_MASK		0x3
4807504507fSSandy Huang #define RK3568_VP0_POST_SCALE_SHIFT		0
481d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
482d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
483d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END		0xC4C
484d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
485d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END		0xC54
486d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
487d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
488d0408543SAndy Yan 
489ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL			0xC60
490ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT			0
491ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK			0x1
492ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT		2
493ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK		0x3
494ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT			4
495ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK			0x1
496ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT		6
497ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK		0x3
498ac500a1fSSandy Huang 
499ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS			0xC64
500ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT			0
501ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK			0xFF
502ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT			8
503ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK			0x1FF
504ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT			20
505ac500a1fSSandy Huang #define BCSH_SATURATION_MASK			0x3FF
506ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT			30
507ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK			0x3
508ac500a1fSSandy Huang 
509ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H			0xC68
510ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT			0
511ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK			0x1FF
512ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT			16
513ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK			0x1FF
514ac500a1fSSandy Huang 
515ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR			0xC6C
516ac500a1fSSandy Huang #define BCSH_EN_SHIFT				31
517ac500a1fSSandy Huang #define BCSH_EN_MASK				1
518ac500a1fSSandy Huang 
519a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_0		0xCA0
520a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_1		0xCA4
521a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_2		0xCA8
522a552a69cSDamon Ding 
5236027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL			0xCD0
5246027c871SZhang Yubing #define POST_CSC_COE00_MASK			0xFFFF
5256027c871SZhang Yubing #define POST_CSC_COE00_SHIFT			16
5266027c871SZhang Yubing #define POST_R2Y_MODE_MASK			0x7
5276027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT			8
5286027c871SZhang Yubing #define POST_CSC_MODE_MASK			0x7
5296027c871SZhang Yubing #define POST_CSC_MODE_SHIFT			3
5306027c871SZhang Yubing #define POST_R2Y_EN_MASK			0x1
5316027c871SZhang Yubing #define POST_R2Y_EN_SHIFT			2
5326027c871SZhang Yubing #define POST_CSC_EN_MASK			0x1
5336027c871SZhang Yubing #define POST_CSC_EN_SHIFT			1
5346027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK			0x1
5356027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT		0
5366027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02			0xCD4
5376027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11			0xCD8
5386027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20			0xCDC
5396027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22			0xCE0
5406027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0			0xCE4
5416027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1			0xCE8
5426027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2			0xCEC
5436027c871SZhang Yubing 
5440675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL			0xCF8
5450675a2a4SDamon Ding #define MCU_TYPE_SHIFT				31
5460675a2a4SDamon Ding #define MCU_BYPASS_SHIFT			30
5470675a2a4SDamon Ding #define MCU_RS_SHIFT				29
5480675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT			28
5490675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT			27
5500675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT			26
5510675a2a4SDamon Ding #define MCU_CLK_SEL_MASK			0x1
5520675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT			20
5530675a2a4SDamon Ding #define MCU_RW_PEND_MASK			0x3F
5540675a2a4SDamon Ding #define MCU_RW_PST_SHIFT			16
5550675a2a4SDamon Ding #define MCU_RW_PST_MASK				0xF
5560675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT			10
5570675a2a4SDamon Ding #define MCU_CS_PEND_MASK			0x3F
5580675a2a4SDamon Ding #define MCU_CS_PST_SHIFT			6
5590675a2a4SDamon Ding #define MCU_CS_PST_MASK				0xF
5600675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT			0
5610675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK			0x3F
5620675a2a4SDamon Ding 
5630675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT		0xCFC
5640675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT		0
5650675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK		0xFFFFFFFF
5660675a2a4SDamon Ding 
567d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL			0xD00
568d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL			0xD04
569d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL		0xD08
570d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
571d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
572d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
573d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
574d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL		0xD40
575d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO		0xD34
576d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO		0xD38
577d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
578d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
579d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END		0xD4C
580d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
581d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END		0xD54
582d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
583d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
584d0408543SAndy Yan 
585d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL			0xE00
586d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL			0xE04
587d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL		0xE08
588d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
589d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
590d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
591d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
592d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL		0xE40
593d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO		0xE34
594d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO		0xE38
595d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
596d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
597d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END		0xE4C
598d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
599d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END		0xE54
600d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
601d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
602a552a69cSDamon Ding #define RK3568_VP2_BCSH_CTRL			0xE60
603a552a69cSDamon Ding #define RK3568_VP2_BCSH_BCS			0xE64
604a552a69cSDamon Ding #define RK3568_VP2_BCSH_H			0xE68
605a552a69cSDamon Ding #define RK3568_VP2_BCSH_COLOR_BAR		0xE6C
606a552a69cSDamon Ding #define RK3576_VP2_MCU_CTRL			0xEF8
607a552a69cSDamon Ding #define RK3576_VP2_MCU_RW_BYPASS_PORT		0xEFC
608d0408543SAndy Yan 
609d0408543SAndy Yan /* Cluster0 register definition */
610d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
611ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT		8
612ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT		9
613ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT			10
614840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT		18
615d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
6165fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT	12
6175fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
6185fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
6195fa6e665SDamon Ding #define AVG2_MASK				0x1
6205fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT			18
6215fa6e665SDamon Ding #define AVG4_MASK				0x1
6225fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT			19
6235fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT	22
6245fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT			24
6255fa6e665SDamon Ding #define XGT_MODE_MASK				0x3
6265fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT			25
6275fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT			27
628ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT			28
629ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT			29
630a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2		0x1008
631a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK		0x1f
632a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT		0
633a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK			0x1f
634a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT			5
635a33b790fSDamon Ding 
636d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
637d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
638d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR		0x1018
639d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
640d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
641d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
642d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
643a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_CTRL		0x1040
644a552a69cSDamon Ding #define WIN0_ZME_DERING_EN_SHIFT		3
645a552a69cSDamon Ding #define WIN0_ZME_GATING_EN_SHIFT		31
646a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA	0x1044
647d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
648d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
649d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
650d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
651d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
652d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
653d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
654a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT		7
655a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET	0x1078
656a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE	0x107C
657d0408543SAndy Yan 
658d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
659d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
660d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
661d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
662d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR		0x1098
663d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
664d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
665d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
666d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
667d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
668d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
669d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
670d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
671d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
672d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
673d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
674a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET	0x10F8
675a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE	0x10FC
676d0408543SAndy Yan 
677d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL			0x1100
678ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT			0
679a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK			0x1
680a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT			13
681a552a69cSDamon Ding #define RK3576_CLUSTER0_PORT_SEL		0x11F4
682a552a69cSDamon Ding #define CLUSTER_PORT_SEL_SHIFT			0
683a552a69cSDamon Ding #define CLUSTER_PORT_SEL_MASK			0x3
684a552a69cSDamon Ding #define RK3576_CLUSTER0_DLY_NUM			0x11F8
685a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_SHIFT		0
686a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_MASK		0xff
687a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_SHIFT		0
688a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_MASK		0xff
689d0408543SAndy Yan 
690d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
691d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
692d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
693d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
694d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR		0x1218
695d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
696d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
697d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
698d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
699a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_CTRL		0x1240
700a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA	0x1244
701d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
702d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
703d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
704d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
705d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
706d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
707d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
708a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET	0x1278
709a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE	0x127C
710d0408543SAndy Yan 
711d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
712d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
713d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
714d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
715d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR		0x1298
716d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
717d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
718d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
719d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
720d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
721d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
722d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
723d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
724d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
725d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
726d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
727a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET	0x12F8
728a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE	0x12FC
729d0408543SAndy Yan 
730d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL			0x1300
731a552a69cSDamon Ding #define RK3576_CLUSTER1_PORT_SEL		0x13F4
732a552a69cSDamon Ding #define RK3576_CLUSTER1_DLY_NUM			0x13F8
733d0408543SAndy Yan 
734d0408543SAndy Yan /* Esmart register definition */
735d0408543SAndy Yan #define RK3568_ESMART0_CTRL0			0x1800
73610ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT			1
73710ee9f5bSAlgea Cao #define CSC_MODE_SHIFT				2
73810ee9f5bSAlgea Cao #define CSC_MODE_MASK				0x3
7395fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT			12
7405fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK			0x3
741d0408543SAndy Yan 
742d0408543SAndy Yan #define RK3568_ESMART0_CTRL1			0x1804
743a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK			0x1f
744a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT		4
745a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK			0x1f
746a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT			12
747d0408543SAndy Yan #define YMIRROR_EN_SHIFT			31
748a33b790fSDamon Ding 
749a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL			0x1808
750a33b790fSDamon Ding #define ESMART_AXI_ID_MASK			0x1
751a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT			1
752a33b790fSDamon Ding 
753d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL		0x1810
754d0408543SAndy Yan #define WIN_EN_SHIFT				0
755d0408543SAndy Yan #define WIN_FORMAT_MASK				0x1f
756d0408543SAndy Yan #define WIN_FORMAT_SHIFT			1
757840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT		12
7585fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT			14
7595fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT			20
7605fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT			21
7615fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT			22
762d0408543SAndy Yan 
763d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
764d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
765d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR		0x181C
766d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
767d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
768d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
769d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
7703e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK			0x3
7713e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT			0
7723e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK		0x3
7733e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT		2
7743e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK			0x3
7753e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT			4
7763e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK		0x3
7773e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT		6
7783e39a5a1SSandy Huang 
779d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
780d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
781d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
782d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL		0x1840
7833e39a5a1SSandy Huang #define YRGB_GT2_MASK				0x1
7843e39a5a1SSandy Huang #define YRGB_GT2_SHIFT				8
7853e39a5a1SSandy Huang #define YRGB_GT4_MASK				0x1
7863e39a5a1SSandy Huang #define YRGB_GT4_SHIFT				9
7873e39a5a1SSandy Huang 
788d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
789d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
790d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR		0x184C
791d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
792d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
793d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
794d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
795d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
796d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
797d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
798d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL		0x1870
799d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
800d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
801d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR		0x187C
802d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
803d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
804d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
805d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
806d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
807d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
808d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
809d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL		0x18A0
810d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
811d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
812d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR		0x18AC
813d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
814d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
815d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
816d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
817d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
818d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
819d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
820a552a69cSDamon Ding #define RK3568_ESMART0_COLOR_KEY_CTRL		0x18D0
821a552a69cSDamon Ding #define RK3576_ESMART0_ALPHA_MAP		0x18D8
822a552a69cSDamon Ding #define RK3576_ESMART0_PORT_SEL			0x18F4
823a552a69cSDamon Ding #define ESMART_PORT_SEL_SHIFT			0
824a552a69cSDamon Ding #define ESMART_PORT_SEL_MASK			0x3
825a552a69cSDamon Ding #define RK3576_ESMART0_DLY_NUM			0x18F8
826d0408543SAndy Yan 
827d0408543SAndy Yan #define RK3568_ESMART1_CTRL0			0x1A00
828d0408543SAndy Yan #define RK3568_ESMART1_CTRL1			0x1A04
829d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL		0x1A10
830d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
831d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
832d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR		0x1A1C
833d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
834d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
835d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
836d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
837d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
838d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
839d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
840d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL		0x1A40
841d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
842d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
843d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR		0x1A4C
844d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
845d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
846d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
847d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
848d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
849d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
850d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
851d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL		0x1A70
852d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
853d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
854d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR		0x1A7C
855d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
856d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
857d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
858d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
859d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
860d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
861d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
862d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
863d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
864d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
865d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR		0x1AAC
866d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
867d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
868d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
869d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
870d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
871d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
872d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
873a552a69cSDamon Ding #define RK3576_ESMART1_ALPHA_MAP		0x1AD8
874a552a69cSDamon Ding #define RK3576_ESMART1_PORT_SEL			0x1AF4
875a552a69cSDamon Ding #define RK3576_ESMART1_DLY_NUM			0x1AF8
876d0408543SAndy Yan 
877d0408543SAndy Yan #define RK3568_SMART0_CTRL0			0x1C00
878d0408543SAndy Yan #define RK3568_SMART0_CTRL1			0x1C04
879d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL		0x1C10
880d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
881d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
882d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR		0x1C1C
883d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
884d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
885d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
886d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
887d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
888d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
889d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
890d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL		0x1C40
891d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
892d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
893d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR		0x1C4C
894d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
895d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
896d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
897d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
898d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
899d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
900d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
901d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL		0x1C70
902d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
903d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
904d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR		0x1C7C
905d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
906d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
907d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
908d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
909d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
910d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
911d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
912d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL		0x1CA0
913d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
914d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
915d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR		0x1CAC
916d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
917d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
918d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
919d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
920d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
921d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
922d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
923a552a69cSDamon Ding #define RK3576_ESMART2_ALPHA_MAP		0x1CD8
924a552a69cSDamon Ding #define RK3576_ESMART2_PORT_SEL			0x1CF4
925a552a69cSDamon Ding #define RK3576_ESMART2_DLY_NUM			0x1CF8
926d0408543SAndy Yan 
927d0408543SAndy Yan #define RK3568_SMART1_CTRL0			0x1E00
928d0408543SAndy Yan #define RK3568_SMART1_CTRL1			0x1E04
929d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL		0x1E10
930d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
931d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
932d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR		0x1E1C
933d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
934d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
935d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
936d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
937d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
938d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
939d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
940d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL		0x1E40
941d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
942d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
943d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR		0x1E4C
944d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
945d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
946d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
947d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
948d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
949d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
950d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
951d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL		0x1E70
952d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
953d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
954d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR		0x1E7C
955d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
956d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
957d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
958d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
959d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
960d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
961d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
962d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL		0x1EA0
963d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
964d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
965d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR		0x1EAC
966d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
967d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
968d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
969d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
970d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
971d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
972d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
973a552a69cSDamon Ding #define RK3576_ESMART3_ALPHA_MAP		0x1ED8
974a552a69cSDamon Ding #define RK3576_ESMART3_PORT_SEL			0x1EF4
975a552a69cSDamon Ding #define RK3576_ESMART3_DLY_NUM			0x1EF8
976d0408543SAndy Yan 
97772388c26SDamon Ding /* HDR register definition */
97872388c26SDamon Ding #define RK3568_HDR_LUT_CTRL			0x2000
97972388c26SDamon Ding 
98072388c26SDamon Ding #define RK3588_VP3_DSP_CTRL			0xF00
98172388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0		0x1400
98272388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0		0x1600
98372388c26SDamon Ding 
98412ee5af0SDamon Ding /* DSC 8K/4K register definition */
98512ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3			0x4000
98612ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0			0x40A0
98712ee5af0SDamon Ding #define DSC_EN_SHIFT				0
98812ee5af0SDamon Ding #define DSC_RBIT_SHIFT				2
98912ee5af0SDamon Ding #define DSC_RBYT_SHIFT				3
99012ee5af0SDamon Ding #define DSC_FLAL_SHIFT				4
99112ee5af0SDamon Ding #define DSC_MER_SHIFT				5
99212ee5af0SDamon Ding #define DSC_EPB_SHIFT				6
99312ee5af0SDamon Ding #define DSC_EPL_SHIFT				7
9941ace1b6dSDamon Ding #define DSC_NSLC_MASK				0x7
99512ee5af0SDamon Ding #define DSC_NSLC_SHIFT				16
99612ee5af0SDamon Ding #define DSC_SBO_SHIFT				28
99712ee5af0SDamon Ding #define DSC_IFEP_SHIFT				29
99812ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT			31
999baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT)   | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \
1000baf2c414SDamon Ding 			   (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT)  | (0 << DSC_EPB_SHIFT)  | \
1001baf2c414SDamon Ding 			   (1 << DSC_EPL_SHIFT)  | (1 << DSC_SBO_SHIFT))
100212ee5af0SDamon Ding 
100312ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1			0x40A4
100412ee5af0SDamon Ding #define RK3588_DSC_8K_STS0			0x40A8
100512ee5af0SDamon Ding #define RK3588_DSC_8K_ERS			0x40C4
100612ee5af0SDamon Ding 
100712ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3			0x4100
100812ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0			0x41A0
100912ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1			0x41A4
101012ee5af0SDamon Ding #define RK3588_DSC_4K_STS0			0x41A8
101112ee5af0SDamon Ding #define RK3588_DSC_4K_ERS			0x41C4
101212ee5af0SDamon Ding 
101372388c26SDamon Ding /* RK3528 HDR register definition */
101472388c26SDamon Ding #define RK3528_HDR_LUT_CTRL			0x2000
101572388c26SDamon Ding 
10166027c871SZhang Yubing /* RK3528 ACM register definition */
10176027c871SZhang Yubing #define RK3528_ACM_CTRL				0x6400
10186027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE			0x6404
10196027c871SZhang Yubing #define RK3528_ACM_FETCH_START			0x6408
10206027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE			0x6420
10216027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0		0x6500
10226027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152		0x6760
10236027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0		0x6764
10246027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220		0x6ad4
10256027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0		0x6ad8
10266027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64		0x6bd8
10276027c871SZhang Yubing 
1028d0408543SAndy Yan #define RK3568_MAX_REG				0x1ED0
1029d0408543SAndy Yan 
1030452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON		0x10500
103152ee18acSSandy Huang #define RK3568_GRF_VO_CON1			0x0364
103252ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT			1
103352ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT		2
103452ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT			3
103552ee18acSSandy Huang 
1036a552a69cSDamon Ding /* Base SYS_GRF: 0x2600a000*/
1037a552a69cSDamon Ding #define RK3576_SYS_GRF_MEMFAULT_STATUS0		0x0148
1038a552a69cSDamon Ding 
1039a552a69cSDamon Ding /* Base IOC_GRF: 0x26040000 */
1040a552a69cSDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8		0x6420
1041a552a69cSDamon Ding #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT	9
1042a552a69cSDamon Ding #define RK3576_IOC_VOPLITE_SEL_SHIFT		11
1043a552a69cSDamon Ding 
1044a552a69cSDamon Ding /* Base PMU2: 0x27380000 */
1045a552a69cSDamon Ding #define RK3576_PMU_PWR_GATE_STS			0x0230
1046a552a69cSDamon Ding #define PD_VOP_ESMART_DWN_STAT			12
1047a552a69cSDamon Ding #define PD_VOP_CLUSTER_DWN_STAT			13
1048a552a69cSDamon Ding #define RK3576_PMU_BISR_PDGEN_CON0		0x0510
1049a552a69cSDamon Ding #define PD_VOP_ESMART_REPAIR_ENA_SHIFT		12
1050a552a69cSDamon Ding #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT		13
1051a552a69cSDamon Ding #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0	0x0570
1052a552a69cSDamon Ding #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT	12
1053a552a69cSDamon Ding #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT	13
1054a552a69cSDamon Ding 
10555d2768f7SDamon Ding #define RK3588_GRF_SOC_CON1			0x0304
10565d2768f7SDamon Ding #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT	14
10575d2768f7SDamon Ding 
1058ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2			0x0008
1059ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT		0
1060ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT		1
1061ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT		3
1062ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT		4
1063ecc31b6eSAndy Yan 
1064b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0			0x0000
1065b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK			0x3
1066b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT			5
1067b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT			7
1068b890760eSAlgea Cao 
106960e469f5SDamon Ding #define RK3588_PMU_BISR_CON3			0x20C
107060e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT	9
107160e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT	10
107260e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT	11
107360e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT	12
1074b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT	13
1075b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT	14
107660e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT	15
107760e469f5SDamon Ding 
107860e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5			0x294
107960e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI	9
108060e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI	10
108160e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI	11
108260e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI	12
1083b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI		13
1084b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI		14
108560e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI		15
108660e469f5SDamon Ding 
1087d0408543SAndy Yan #define VOP2_LAYER_MAX				8
108863cb669fSSandy Huang 
1089ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH		4096
1090ee01dbb2SDamon Ding 
1091631ee99aSZhang Yubing /* KHz */
1092631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE			600000
1093631ee99aSZhang Yubing 
1094b6ba80b4SDamon Ding /*
1095b6ba80b4SDamon Ding  * vop2 dsc id
1096b6ba80b4SDamon Ding  */
1097b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K	0
1098b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K	1
1099b6ba80b4SDamon Ding 
1100b6ba80b4SDamon Ding /*
1101b6ba80b4SDamon Ding  * vop2 internal power domain id,
1102b6ba80b4SDamon Ding  * should be all none zero, 0 will be
1103b6ba80b4SDamon Ding  * treat as invalid;
1104b6ba80b4SDamon Ding  */
1105b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0			BIT(0)
1106b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1			BIT(1)
1107b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2			BIT(2)
1108b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3			BIT(3)
1109b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K				BIT(5)
1110b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K				BIT(6)
1111b6ba80b4SDamon Ding #define VOP2_PD_ESMART				BIT(7)
1112a552a69cSDamon Ding #define VOP2_PD_CLUSTER				BIT(8)
1113b6ba80b4SDamon Ding 
11144c765862SDamon Ding #define VOP2_PLANE_NO_SCALING			BIT(16)
11154c765862SDamon Ding 
11165fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT	BIT(0)
11175fa6e665SDamon Ding #define VOP_FEATURE_AFBDC		BIT(1)
11185fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE		BIT(2)
11195fa6e665SDamon Ding #define VOP_FEATURE_HDR10		BIT(3)
11205fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR		BIT(4)
11215fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */
11225fa6e665SDamon Ding #define VOP_FEATURE_SPLICE		BIT(5)
11235fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN		BIT(6)
11246027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR		BIT(7)
11256027c871SZhang Yubing #define VOP_FEATURE_POST_ACM		BIT(8)
11266027c871SZhang Yubing #define VOP_FEATURE_POST_CSC		BIT(9)
1127a552a69cSDamon Ding #define VOP_FEATURE_POST_FRC_V2		BIT(10)
1128a552a69cSDamon Ding #define VOP_FEATURE_POST_SHARP		BIT(11)
11295fa6e665SDamon Ding 
11305fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR		BIT(0)
11315fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR		BIT(1)
11325fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY		BIT(2)
11335fa6e665SDamon Ding #define WIN_FEATURE_AFBDC		BIT(3)
11345fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
11355fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB		BIT(5)
11365fa6e665SDamon Ding /* a mirror win can only get fb address
11375fa6e665SDamon Ding  * from source win:
11385fa6e665SDamon Ding  * Cluster1---->Cluster0
11395fa6e665SDamon Ding  * Esmart1 ---->Esmart0
11405fa6e665SDamon Ding  * Smart1  ---->Smart0
11415fa6e665SDamon Ding  * This is a feather on rk3566
11425fa6e665SDamon Ding  */
11435fa6e665SDamon Ding #define WIN_FEATURE_MIRROR		BIT(6)
11445fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA		BIT(7)
11455fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH	BIT(8)
1146a552a69cSDamon Ding #define WIN_FEATURE_DCI			BIT(9)
11475fa6e665SDamon Ding 
11485fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F		0xfe
11495fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F		0xff
11505fa6e665SDamon Ding 
11515fa6e665SDamon Ding enum vop_csc_format {
115210ee9f5bSAlgea Cao 	CSC_BT601L,
115310ee9f5bSAlgea Cao 	CSC_BT709L,
115410ee9f5bSAlgea Cao 	CSC_BT601F,
1155df0a5c43SDamon Ding 	CSC_BT2020L,
11565fa6e665SDamon Ding 	CSC_BT709L_13BIT,
11575fa6e665SDamon Ding 	CSC_BT709F_13BIT,
11585fa6e665SDamon Ding 	CSC_BT2020L_13BIT,
11595fa6e665SDamon Ding 	CSC_BT2020F_13BIT,
11605fa6e665SDamon Ding };
11615fa6e665SDamon Ding 
11625fa6e665SDamon Ding enum vop_csc_bit_depth {
11635fa6e665SDamon Ding 	CSC_10BIT_DEPTH,
11645fa6e665SDamon Ding 	CSC_13BIT_DEPTH,
116510ee9f5bSAlgea Cao };
116610ee9f5bSAlgea Cao 
116710ee9f5bSAlgea Cao enum vop2_pol {
116810ee9f5bSAlgea Cao 	HSYNC_POSITIVE = 0,
116910ee9f5bSAlgea Cao 	VSYNC_POSITIVE = 1,
117010ee9f5bSAlgea Cao 	DEN_NEGATIVE   = 2,
117110ee9f5bSAlgea Cao 	DCLK_INVERT    = 3
117210ee9f5bSAlgea Cao };
117310ee9f5bSAlgea Cao 
1174ac500a1fSSandy Huang enum vop2_bcsh_out_mode {
1175ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLACK,
1176ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLUE,
1177ac500a1fSSandy Huang 	BCSH_OUT_MODE_COLOR_BAR,
1178ac500a1fSSandy Huang 	BCSH_OUT_MODE_NORMAL_VIDEO,
1179ac500a1fSSandy Huang };
1180ac500a1fSSandy Huang 
1181d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \
1182d0408543SAndy Yan 		{ \
1183d0408543SAndy Yan 		 .offset = off, \
1184d0408543SAndy Yan 		 .mask = _mask, \
1185d0408543SAndy Yan 		 .shift = _shift, \
1186d0408543SAndy Yan 		 .write_mask = _write_mask, \
1187d0408543SAndy Yan 		}
1188d0408543SAndy Yan 
1189d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \
1190d0408543SAndy Yan 		_VOP_REG(off, _mask, _shift, false)
1191d0408543SAndy Yan enum dither_down_mode {
1192d0408543SAndy Yan 	RGB888_TO_RGB565 = 0x0,
1193d0408543SAndy Yan 	RGB888_TO_RGB666 = 0x1
1194d0408543SAndy Yan };
1195d0408543SAndy Yan 
1196a552a69cSDamon Ding enum dither_down_mode_sel {
1197a552a69cSDamon Ding 	DITHER_DOWN_ALLEGRO = 0x0,
1198a552a69cSDamon Ding 	DITHER_DOWN_FRC = 0x1
1199a552a69cSDamon Ding };
1200a552a69cSDamon Ding 
1201d0408543SAndy Yan enum vop2_video_ports_id {
1202d0408543SAndy Yan 	VOP2_VP0,
1203d0408543SAndy Yan 	VOP2_VP1,
1204d0408543SAndy Yan 	VOP2_VP2,
1205d0408543SAndy Yan 	VOP2_VP3,
1206d0408543SAndy Yan 	VOP2_VP_MAX,
1207d0408543SAndy Yan };
1208d0408543SAndy Yan 
1209ee008497SSandy Huang enum vop2_layer_type {
1210ee008497SSandy Huang 	CLUSTER_LAYER = 0,
1211ee008497SSandy Huang 	ESMART_LAYER = 1,
1212ee008497SSandy Huang 	SMART_LAYER = 2,
1213ee008497SSandy Huang };
1214ee008497SSandy Huang 
1215b0989546SSandy Huang /* This define must same with kernel win phy id */
1216b0989546SSandy Huang enum vop2_layer_phy_id {
1217b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER0 = 0,
1218b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER1,
1219b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART0,
1220b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART1,
1221b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART0,
1222b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART1,
1223b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER2,
1224b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER3,
1225b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART2,
1226b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART3,
1227ee008497SSandy Huang 	ROCKCHIP_VOP2_LAYER_MAX,
122827cec8e2SDamon Ding 	ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
1229d0408543SAndy Yan };
1230d0408543SAndy Yan 
12313e39a5a1SSandy Huang enum vop2_scale_up_mode {
12323e39a5a1SSandy Huang 	VOP2_SCALE_UP_NRST_NBOR,
12333e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIL,
12343e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIC,
1235a552a69cSDamon Ding 	VOP2_SCALE_UP_ZME,
12363e39a5a1SSandy Huang };
12373e39a5a1SSandy Huang 
12383e39a5a1SSandy Huang enum vop2_scale_down_mode {
12393e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_NRST_NBOR,
12403e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_BIL,
12413e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_AVG,
1242a552a69cSDamon Ding 	VOP2_SCALE_DOWN_ZME,
12433e39a5a1SSandy Huang };
12443e39a5a1SSandy Huang 
12453e39a5a1SSandy Huang enum scale_mode {
12463e39a5a1SSandy Huang 	SCALE_NONE = 0x0,
12473e39a5a1SSandy Huang 	SCALE_UP   = 0x1,
12483e39a5a1SSandy Huang 	SCALE_DOWN = 0x2
12493e39a5a1SSandy Huang };
12503e39a5a1SSandy Huang 
125112ee5af0SDamon Ding enum vop_dsc_interface_mode {
125212ee5af0SDamon Ding 	VOP_DSC_IF_DISABLE = 0,
125312ee5af0SDamon Ding 	VOP_DSC_IF_HDMI = 1,
125412ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_DS_MODE = 2,
125512ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_VIDEO_MODE = 3,
125612ee5af0SDamon Ding };
125712ee5af0SDamon Ding 
12585fa6e665SDamon Ding enum vop3_pre_scale_down_mode {
12595fa6e665SDamon Ding 	VOP3_PRE_SCALE_UNSPPORT,
12605fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_GT,
12615fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_AVG,
12625fa6e665SDamon Ding };
12635fa6e665SDamon Ding 
12649c7848c3SDamon Ding /*
12659c7848c3SDamon Ding  *  the delay number of a window in different mode.
12669c7848c3SDamon Ding  */
12679c7848c3SDamon Ding enum vop2_win_dly_mode {
12689c7848c3SDamon Ding 	VOP2_DLY_MODE_DEFAULT,		/* default mode */
12699c7848c3SDamon Ding 	VOP2_DLY_MODE_HISO_S,		/* HDR in SDR out mode, as a SDR window */
12709c7848c3SDamon Ding 	VOP2_DLY_MODE_HIHO_H,		/* HDR in HDR out mode, as a HDR window */
12719c7848c3SDamon Ding 	VOP2_DLY_MODE_DOVI_IN_CORE1,	/* dovi video input, as dovi core1 */
12729c7848c3SDamon Ding 	VOP2_DLY_MODE_DOVI_IN_CORE2,	/* dovi video input, as dovi core2 */
12739c7848c3SDamon Ding 	VOP2_DLY_MODE_NONDOVI_IN_CORE1,	/* ndovi video input, as dovi core1 */
12749c7848c3SDamon Ding 	VOP2_DLY_MODE_NONDOVI_IN_CORE2,	/* ndovi video input, as dovi core2 */
12759c7848c3SDamon Ding 	VOP2_DLY_MODE_MAX,
12769c7848c3SDamon Ding };
12779c7848c3SDamon Ding 
12785fa6e665SDamon Ding enum vop3_esmart_lb_mode {
12795fa6e665SDamon Ding 	VOP3_ESMART_8K_MODE,
12805fa6e665SDamon Ding 	VOP3_ESMART_4K_4K_MODE,
12815fa6e665SDamon Ding 	VOP3_ESMART_4K_2K_2K_MODE,
12825fa6e665SDamon Ding 	VOP3_ESMART_2K_2K_2K_2K_MODE,
1283a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_4K_MODE,
1284a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_2K_2K_MODE,
12855fa6e665SDamon Ding };
12865fa6e665SDamon Ding 
12873e39a5a1SSandy Huang struct vop2_layer {
12883e39a5a1SSandy Huang 	u8 id;
12893e39a5a1SSandy Huang 	/**
12903e39a5a1SSandy Huang 	 * @win_phys_id: window id of the layer selected.
12913e39a5a1SSandy Huang 	 * Every layer must make sure to select different
12923e39a5a1SSandy Huang 	 * windows of others.
12933e39a5a1SSandy Huang 	 */
12943e39a5a1SSandy Huang 	u8 win_phys_id;
12953e39a5a1SSandy Huang };
12963e39a5a1SSandy Huang 
129760e469f5SDamon Ding struct vop2_power_domain_data {
1298a552a69cSDamon Ding 	u16 id;
1299a552a69cSDamon Ding 	u16 parent_id;
1300b6ba80b4SDamon Ding 	/*
1301b6ba80b4SDamon Ding 	 * @module_id_mask: module id of which module this power domain is belongs to.
1302b6ba80b4SDamon Ding 	 * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3
1303b6ba80b4SDamon Ding 	 */
1304b6ba80b4SDamon Ding 	u32 module_id_mask;
130560e469f5SDamon Ding };
130660e469f5SDamon Ding 
1307b0989546SSandy Huang struct vop2_win_data {
1308b0989546SSandy Huang 	char *name;
130963cb669fSSandy Huang 	u8 phys_id;
1310ecc31b6eSAndy Yan 	enum vop2_layer_type type;
1311b0989546SSandy Huang 	u8 win_sel_port_offset;
13125fa6e665SDamon Ding 	u8 layer_sel_win_id[VOP2_VP_MAX];
1313a33b790fSDamon Ding 	u8 axi_id;
1314a33b790fSDamon Ding 	u8 axi_uv_id;
1315a33b790fSDamon Ding 	u8 axi_yrgb_id;
1316ee01dbb2SDamon Ding 	u8 splice_win_id;
13175fa6e665SDamon Ding 	u8 hsu_filter_mode;
13185fa6e665SDamon Ding 	u8 hsd_filter_mode;
13195fa6e665SDamon Ding 	u8 vsu_filter_mode;
13205fa6e665SDamon Ding 	u8 vsd_filter_mode;
13215fa6e665SDamon Ding 	u8 hsd_pre_filter_mode;
13225fa6e665SDamon Ding 	u8 vsd_pre_filter_mode;
13235fa6e665SDamon Ding 	u8 scale_engine_num;
13241c9572c7SDamon Ding 	u8 source_win_id;
1325*13bc92e8SDamon Ding 	u8 possible_vp_mask;
13269c7848c3SDamon Ding 	u8 dly[VOP2_DLY_MODE_MAX];
1327a552a69cSDamon Ding 	u16 pd_id;
1328b0989546SSandy Huang 	u32 reg_offset;
13294c765862SDamon Ding 	u32 max_upscale_factor;
13304c765862SDamon Ding 	u32 max_downscale_factor;
13311c9572c7SDamon Ding 	u32 feature;
1332a552a69cSDamon Ding 	u32 supported_rotations;
1333ee01dbb2SDamon Ding 	bool splice_mode_right;
133463cb669fSSandy Huang };
133563cb669fSSandy Huang 
133663cb669fSSandy Huang struct vop2_vp_data {
133763cb669fSSandy Huang 	u32 feature;
133844b1b62cSDamon Ding 	u32 max_dclk;
133963cb669fSSandy Huang 	u8 pre_scan_max_dly;
1340452afb13SDamon Ding 	u8 layer_mix_dly;
1341a552a69cSDamon Ding 	u8 hdrvivid_dly;
1342a552a69cSDamon Ding 	u8 sdr2hdr_dly;
1343452afb13SDamon Ding 	u8 hdr_mix_dly;
1344452afb13SDamon Ding 	u8 win_dly;
1345ee01dbb2SDamon Ding 	u8 splice_vp_id;
1346a552a69cSDamon Ding 	u8 pixel_rate;
134763cb669fSSandy Huang 	struct vop_rect max_output;
134844b1b62cSDamon Ding 	struct vop_urgency *urgency;
1349d0408543SAndy Yan };
1350d0408543SAndy Yan 
1351ee008497SSandy Huang struct vop2_plane_table {
1352ee008497SSandy Huang 	enum vop2_layer_phy_id plane_id;
1353ee008497SSandy Huang 	enum vop2_layer_type plane_type;
1354ee008497SSandy Huang };
1355ee008497SSandy Huang 
1356b0989546SSandy Huang struct vop2_vp_plane_mask {
1357b0989546SSandy Huang 	u8 primary_plane_id; /* use this win to show logo */
1358b0989546SSandy Huang 	u8 attached_layers_nr; /* number layers attach to this vp */
1359b0989546SSandy Huang 	u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
1360b0989546SSandy Huang 	u32 plane_mask;
1361ee008497SSandy Huang 	int cursor_plane_id;
1362b0989546SSandy Huang };
1363b0989546SSandy Huang 
136412ee5af0SDamon Ding struct vop2_dsc_data {
136512ee5af0SDamon Ding 	u8 id;
136612ee5af0SDamon Ding 	u8 max_slice_num;
136712ee5af0SDamon Ding 	u8 max_linebuf_depth;	/* used to generate the bitstream */
136812ee5af0SDamon Ding 	u8 min_bits_per_pixel;	/* bit num after encoder compress */
1369a552a69cSDamon Ding 	u16 pd_id;
137012ee5af0SDamon Ding 	const char *dsc_txp_clk_src_name;
137112ee5af0SDamon Ding 	const char *dsc_txp_clk_name;
137212ee5af0SDamon Ding 	const char *dsc_pxl_clk_name;
137312ee5af0SDamon Ding 	const char *dsc_cds_clk_name;
137412ee5af0SDamon Ding };
137512ee5af0SDamon Ding 
137612ee5af0SDamon Ding struct dsc_error_info {
137712ee5af0SDamon Ding 	u32 dsc_error_val;
137812ee5af0SDamon Ding 	char dsc_error_info[50];
137912ee5af0SDamon Ding };
138012ee5af0SDamon Ding 
138172388c26SDamon Ding struct vop2_dump_regs {
138272388c26SDamon Ding 	u32 offset;
138372388c26SDamon Ding 	const char *name;
138472388c26SDamon Ding 	u32 state_base;
138572388c26SDamon Ding 	u32 state_mask;
138672388c26SDamon Ding 	u32 state_shift;
138772388c26SDamon Ding 	bool enable_state;
1388a552a69cSDamon Ding 	u32 size;
1389a552a69cSDamon Ding };
1390a552a69cSDamon Ding 
1391a552a69cSDamon Ding struct vop2_esmart_lb_map {
1392a552a69cSDamon Ding 	u8 lb_mode;
1393a552a69cSDamon Ding 	u8 lb_map_value;
139472388c26SDamon Ding };
139572388c26SDamon Ding 
13969c7848c3SDamon Ding /**
13979c7848c3SDamon Ding * struct vop2_ops - helper operations for vop2 hardware
13989c7848c3SDamon Ding *
13999c7848c3SDamon Ding * These hooks are used by the common part of the vop2 driver to
14009c7848c3SDamon Ding * implement the proper behaviour of different variants.
14019c7848c3SDamon Ding */
14029c7848c3SDamon Ding struct vop2_ops {
14039c7848c3SDamon Ding 	void (*setup_win_dly)(struct display_state *state, int crtc_id);
1404b7195f56SDamon Ding 	void (*setup_overlay)(struct display_state *state);
14059c7848c3SDamon Ding };
14069c7848c3SDamon Ding 
1407d0408543SAndy Yan struct vop2_data {
140852ee18acSSandy Huang 	u32 version;
14095fa6e665SDamon Ding 	u32 esmart_lb_mode;
141063cb669fSSandy Huang 	struct vop2_vp_data *vp_data;
1411b0989546SSandy Huang 	struct vop2_win_data *win_data;
1412b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
1413ee008497SSandy Huang 	struct vop2_plane_table *plane_table;
1414b6ba80b4SDamon Ding 	struct vop2_power_domain_data *pd;
141512ee5af0SDamon Ding 	struct vop2_dsc_data *dsc;
141612ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_ecw;
141712ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_buffer_flow;
141872388c26SDamon Ding 	struct vop2_dump_regs *dump_regs;
1419a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map;
14209c7848c3SDamon Ding 	const struct vop2_ops *ops;
1421337d1c13SDamon Ding 	u8 *vp_primary_plane_order;
1422a552a69cSDamon Ding 	u8 *vp_default_primary_plane;
142363cb669fSSandy Huang 	u8 nr_vps;
142463cb669fSSandy Huang 	u8 nr_layers;
142563cb669fSSandy Huang 	u8 nr_mixers;
14261147facaSSandy Huang 	u8 nr_gammas;
1427b6ba80b4SDamon Ding 	u8 nr_pd;
142812ee5af0SDamon Ding 	u8 nr_dscs;
142912ee5af0SDamon Ding 	u8 nr_dsc_ecw;
143012ee5af0SDamon Ding 	u8 nr_dsc_buffer_flow;
1431a552a69cSDamon Ding 	u8 esmart_lb_mode_num;
1432ecc31b6eSAndy Yan 	u32 reg_len;
143372388c26SDamon Ding 	u32 dump_regs_size;
1434d0408543SAndy Yan };
1435d0408543SAndy Yan 
1436d0408543SAndy Yan struct vop2 {
1437d0408543SAndy Yan 	u32 *regsbak;
1438d0408543SAndy Yan 	void *regs;
1439d0408543SAndy Yan 	void *grf;
1440ecc31b6eSAndy Yan 	void *vop_grf;
1441ecc31b6eSAndy Yan 	void *vo1_grf;
144260e469f5SDamon Ding 	void *sys_pmu;
1443a552a69cSDamon Ding 	void *ioc_grf;
144452ee18acSSandy Huang 	u32 reg_len;
144552ee18acSSandy Huang 	u32 version;
14465fa6e665SDamon Ding 	u32 esmart_lb_mode;
144763cb669fSSandy Huang 	bool global_init;
1448a552a69cSDamon Ding 	bool merge_irq;
1449d0408543SAndy Yan 	const struct vop2_data *data;
1450b0989546SSandy Huang 	struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
1451d0408543SAndy Yan };
1452d0408543SAndy Yan 
1453d0408543SAndy Yan static struct vop2 *rockchip_vop2;
14545fa6e665SDamon Ding 
145527cec8e2SDamon Ding /* vop2_layer_phy_id */
145627cec8e2SDamon Ding static const char *const vop2_layer_name_list[] = {
145727cec8e2SDamon Ding 	"Cluster0",
145827cec8e2SDamon Ding 	"Cluster1",
145927cec8e2SDamon Ding 	"Esmart0",
146027cec8e2SDamon Ding 	"Esmart1",
146127cec8e2SDamon Ding 	"Smart0",
146227cec8e2SDamon Ding 	"Smart1",
146327cec8e2SDamon Ding 	"Cluster2",
146427cec8e2SDamon Ding 	"Cluster3",
146527cec8e2SDamon Ding 	"Esmart2",
146627cec8e2SDamon Ding 	"Esmart3",
146727cec8e2SDamon Ding };
146827cec8e2SDamon Ding 
146927cec8e2SDamon Ding static inline const char *vop2_plane_id_to_string(unsigned long phy)
147027cec8e2SDamon Ding {
147127cec8e2SDamon Ding 	if (phy == ROCKCHIP_VOP2_PHY_ID_INVALID)
147227cec8e2SDamon Ding 		return "INVALID";
147327cec8e2SDamon Ding 
147427cec8e2SDamon Ding 	if (WARN_ON(phy >= ARRAY_SIZE(vop2_layer_name_list)))
147527cec8e2SDamon Ding 		return NULL;
147627cec8e2SDamon Ding 
147727cec8e2SDamon Ding 	return vop2_layer_name_list[phy];
147827cec8e2SDamon Ding }
147927cec8e2SDamon Ding 
14805fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2)
14815fa6e665SDamon Ding {
14825fa6e665SDamon Ding 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588)
14835fa6e665SDamon Ding 		return false;
14845fa6e665SDamon Ding 	else
14855fa6e665SDamon Ding 		return true;
14865fa6e665SDamon Ding }
14875fa6e665SDamon Ding 
14883e39a5a1SSandy Huang /*
14893e39a5a1SSandy Huang  * bli_sd_factor = (src - 1) / (dst - 1) << 12;
14903e39a5a1SSandy Huang  * avg_sd_factor:
14913e39a5a1SSandy Huang  * bli_su_factor:
14923e39a5a1SSandy Huang  * bic_su_factor:
14933e39a5a1SSandy Huang  * = (src - 1) / (dst - 1) << 16;
14943e39a5a1SSandy Huang  *
14955fa6e665SDamon Ding  * ygt2 enable: dst get one line from two line of the src
14965fa6e665SDamon Ding  * ygt4 enable: dst get one line from four line of the src.
14973e39a5a1SSandy Huang  *
14983e39a5a1SSandy Huang  */
14993e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst)	(((src - 1) << 12) / (dst - 1))
15003e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst)	(((src - 1) << 16) / (dst - 1))
15013e39a5a1SSandy Huang 
15023e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)	 \
15033e39a5a1SSandy Huang 				(fac * (dst - 1) >> 12 < (src - 1))
15043e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
15053e39a5a1SSandy Huang 				(fac * (dst - 1) >> 16 < (src - 1))
15065fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
15075fa6e665SDamon Ding 				(fac * (dst - 1) >> 16 < (src - 1))
15083e39a5a1SSandy Huang 
15093e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode,
15103e39a5a1SSandy Huang 				  int32_t filter_mode,
15113e39a5a1SSandy Huang 				  uint32_t src, uint32_t dst)
15123e39a5a1SSandy Huang {
15133e39a5a1SSandy Huang 	uint32_t fac = 0;
15143e39a5a1SSandy Huang 	int i = 0;
15153e39a5a1SSandy Huang 
15163e39a5a1SSandy Huang 	if (mode == SCALE_NONE)
15173e39a5a1SSandy Huang 		return 0;
15183e39a5a1SSandy Huang 
15193e39a5a1SSandy Huang 	/*
15203e39a5a1SSandy Huang 	 * A workaround to avoid zero div.
15213e39a5a1SSandy Huang 	 */
15223e39a5a1SSandy Huang 	if ((dst == 1) || (src == 1)) {
15233e39a5a1SSandy Huang 		dst = dst + 1;
15243e39a5a1SSandy Huang 		src = src + 1;
15253e39a5a1SSandy Huang 	}
15263e39a5a1SSandy Huang 
15273e39a5a1SSandy Huang 	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
15283e39a5a1SSandy Huang 		fac = VOP2_BILI_SCL_DN(src, dst);
15293e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
15303e39a5a1SSandy Huang 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
15313e39a5a1SSandy Huang 				break;
15323e39a5a1SSandy Huang 			fac -= 1;
15333e39a5a1SSandy Huang 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15343e39a5a1SSandy Huang 		}
15353e39a5a1SSandy Huang 	} else {
15363e39a5a1SSandy Huang 		fac = VOP2_COMMON_SCL(src, dst);
15373e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
15383e39a5a1SSandy Huang 			if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
15393e39a5a1SSandy Huang 				break;
15403e39a5a1SSandy Huang 			fac -= 1;
15413e39a5a1SSandy Huang 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15423e39a5a1SSandy Huang 		}
15433e39a5a1SSandy Huang 	}
15443e39a5a1SSandy Huang 
15453e39a5a1SSandy Huang 	return fac;
15463e39a5a1SSandy Huang }
15473e39a5a1SSandy Huang 
15485fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor)
15495fa6e665SDamon Ding {
15505fa6e665SDamon Ding 	if (is_hor)
15515fa6e665SDamon Ding 		return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac);
15525fa6e665SDamon Ding 	return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac);
15535fa6e665SDamon Ding }
15545fa6e665SDamon Ding 
15555fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode,
15565fa6e665SDamon Ding 				  uint32_t src, uint32_t dst, bool is_hor)
15575fa6e665SDamon Ding {
15585fa6e665SDamon Ding 	uint32_t fac = 0;
15595fa6e665SDamon Ding 	int i = 0;
15605fa6e665SDamon Ding 
15615fa6e665SDamon Ding 	if (mode == SCALE_NONE)
15625fa6e665SDamon Ding 		return 0;
15635fa6e665SDamon Ding 
15645fa6e665SDamon Ding 	/*
15655fa6e665SDamon Ding 	 * A workaround to avoid zero div.
15665fa6e665SDamon Ding 	 */
15675fa6e665SDamon Ding 	if ((dst == 1) || (src == 1)) {
15685fa6e665SDamon Ding 		dst = dst + 1;
15695fa6e665SDamon Ding 		src = src + 1;
15705fa6e665SDamon Ding 	}
15715fa6e665SDamon Ding 
15725fa6e665SDamon Ding 	if (mode == SCALE_DOWN) {
15735fa6e665SDamon Ding 		fac = VOP2_BILI_SCL_DN(src, dst);
15745fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
15755fa6e665SDamon Ding 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
15765fa6e665SDamon Ding 				break;
15775fa6e665SDamon Ding 			fac -= 1;
15785fa6e665SDamon Ding 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15795fa6e665SDamon Ding 		}
15805fa6e665SDamon Ding 	} else {
15815fa6e665SDamon Ding 		fac = VOP2_COMMON_SCL(src, dst);
15825fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
15835fa6e665SDamon Ding 			if (vop3_scale_up_fac_check(src, dst, fac, is_hor))
15845fa6e665SDamon Ding 				break;
15855fa6e665SDamon Ding 			fac -= 1;
15865fa6e665SDamon Ding 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15875fa6e665SDamon Ding 		}
15885fa6e665SDamon Ding 	}
15895fa6e665SDamon Ding 
15905fa6e665SDamon Ding 	return fac;
15915fa6e665SDamon Ding }
15925fa6e665SDamon Ding 
15933e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst)
15943e39a5a1SSandy Huang {
15953e39a5a1SSandy Huang 	if (src < dst)
15963e39a5a1SSandy Huang 		return SCALE_UP;
15973e39a5a1SSandy Huang 	else if (src > dst)
15983e39a5a1SSandy Huang 		return SCALE_DOWN;
15993e39a5a1SSandy Huang 
16003e39a5a1SSandy Huang 	return SCALE_NONE;
16013e39a5a1SSandy Huang }
1602d0408543SAndy Yan 
1603ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x)
1604ac500a1fSSandy Huang {
1605ac500a1fSSandy Huang 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
1606ac500a1fSSandy Huang }
1607ac500a1fSSandy Huang 
1608b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask)
1609b0989546SSandy Huang {
1610b0989546SSandy Huang 	int i = 0;
1611ecc31b6eSAndy Yan 
1612337d1c13SDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
1613337d1c13SDamon Ding 		if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i]))
1614337d1c13SDamon Ding 			return vop2->data->vp_primary_plane_order[i];
1615ecc31b6eSAndy Yan 	}
1616b0989546SSandy Huang 
1617337d1c13SDamon Ding 	return vop2->data->vp_primary_plane_order[0];
1618b0989546SSandy Huang }
1619b0989546SSandy Huang 
162063cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift)
1621d0408543SAndy Yan {
1622d0408543SAndy Yan 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
1623d0408543SAndy Yan }
1624d0408543SAndy Yan 
162563cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst)
1626d0408543SAndy Yan {
1627d0408543SAndy Yan 	return ((src - 1) << 12) / (dst - 1);
1628d0408543SAndy Yan }
1629d0408543SAndy Yan 
163052ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
1631d0408543SAndy Yan {
1632d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1633d0408543SAndy Yan 	vop2->regsbak[offset >> 2] = v;
1634d0408543SAndy Yan }
1635d0408543SAndy Yan 
163652ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
1637d0408543SAndy Yan {
1638d0408543SAndy Yan 	return readl(vop2->regs + offset);
1639d0408543SAndy Yan }
1640d0408543SAndy Yan 
164152ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
164252ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v,
1643d0408543SAndy Yan 				   bool write_mask)
1644d0408543SAndy Yan {
1645d0408543SAndy Yan 	if (!mask)
1646d0408543SAndy Yan 		return;
1647d0408543SAndy Yan 
1648d0408543SAndy Yan 	if (write_mask) {
1649d0408543SAndy Yan 		v = ((v & mask) << shift) | (mask << (shift + 16));
1650d0408543SAndy Yan 	} else {
165152ee18acSSandy Huang 		u32 cached_val = vop2->regsbak[offset >> 2];
1652d0408543SAndy Yan 
1653d0408543SAndy Yan 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
1654d0408543SAndy Yan 		vop2->regsbak[offset >> 2] = v;
1655d0408543SAndy Yan 	}
1656d0408543SAndy Yan 
1657d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1658d0408543SAndy Yan }
1659d0408543SAndy Yan 
1660ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
166152ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v)
166252ee18acSSandy Huang {
166352ee18acSSandy Huang 	u32 val = 0;
166452ee18acSSandy Huang 
166552ee18acSSandy Huang 	val = (v << shift) | (mask << (shift + 16));
1666ecc31b6eSAndy Yan 	writel(val, grf_base + offset);
166752ee18acSSandy Huang }
166852ee18acSSandy Huang 
166960e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
167060e469f5SDamon Ding 				  u32 mask, u32 shift)
167160e469f5SDamon Ding {
167260e469f5SDamon Ding 	return (readl(grf_base + offset) >> shift) & mask;
167360e469f5SDamon Ding }
167460e469f5SDamon Ding 
167552ee18acSSandy Huang static bool is_yuv_output(u32 bus_format)
1676d0408543SAndy Yan {
1677d0408543SAndy Yan 	switch (bus_format) {
1678d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
1679d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
1680034a46b5SAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
1681d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1682d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1683a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
1684a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
1685a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_2X8:
1686a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_2X8:
1687a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
1688a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
1689a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_1X16:
1690a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_1X16:
1691d0408543SAndy Yan 		return true;
1692d0408543SAndy Yan 	default:
1693d0408543SAndy Yan 		return false;
1694d0408543SAndy Yan 	}
1695d0408543SAndy Yan }
1696d0408543SAndy Yan 
1697df0a5c43SDamon Ding static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding,
1698df0a5c43SDamon Ding 						 enum drm_color_range color_range,
1699df0a5c43SDamon Ding 						 int bit_depth)
170010ee9f5bSAlgea Cao {
1701df0a5c43SDamon Ding 	bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
1702df0a5c43SDamon Ding 	enum vop_csc_format csc_mode = CSC_BT709L;
1703df0a5c43SDamon Ding 
1704df0a5c43SDamon Ding 
1705df0a5c43SDamon Ding 	switch (color_encoding) {
1706df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT601:
1707df0a5c43SDamon Ding 		if (full_range)
1708df0a5c43SDamon Ding 			csc_mode = CSC_BT601F;
17095fa6e665SDamon Ding 		else
1710df0a5c43SDamon Ding 			csc_mode = CSC_BT601L;
1711df0a5c43SDamon Ding 		break;
1712df0a5c43SDamon Ding 
1713df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT709:
1714df0a5c43SDamon Ding 		if (full_range) {
1715df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F;
1716df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1717df0a5c43SDamon Ding 				printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n");
17185fa6e665SDamon Ding 		} else {
1719df0a5c43SDamon Ding 			csc_mode = CSC_BT709L;
17205fa6e665SDamon Ding 		}
1721df0a5c43SDamon Ding 		break;
1722df0a5c43SDamon Ding 
1723df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT2020:
1724df0a5c43SDamon Ding 		if (full_range) {
1725df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F;
1726df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1727df0a5c43SDamon Ding 				printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n");
17285fa6e665SDamon Ding 		} else {
1729df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L;
17305fa6e665SDamon Ding 		}
1731df0a5c43SDamon Ding 		break;
1732df0a5c43SDamon Ding 
173310ee9f5bSAlgea Cao 	default:
1734df0a5c43SDamon Ding 		printf("Unsuport color_encoding:%d\n", color_encoding);
173510ee9f5bSAlgea Cao 	}
1736df0a5c43SDamon Ding 
1737df0a5c43SDamon Ding 	return csc_mode;
173810ee9f5bSAlgea Cao }
173910ee9f5bSAlgea Cao 
1740c8820b76SDamon Ding static bool is_uv_swap(struct display_state *state)
1741d0408543SAndy Yan {
1742c8820b76SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
1743c8820b76SDamon Ding 	u32 bus_format = conn_state->bus_format;
1744c8820b76SDamon Ding 	u32 output_mode = conn_state->output_mode;
1745c8820b76SDamon Ding 	u32 output_type = conn_state->type;
1746c8820b76SDamon Ding 
1747d0408543SAndy Yan 	/*
1748d0408543SAndy Yan 	 * FIXME:
1749d0408543SAndy Yan 	 *
1750d0408543SAndy Yan 	 * There is no media type for YUV444 output,
1751d0408543SAndy Yan 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
1752d0408543SAndy Yan 	 * yuv format.
1753d0408543SAndy Yan 	 *
1754c8820b76SDamon Ding 	 * From H/W testing, YUV444 mode need a rb swap except eDP.
1755d0408543SAndy Yan 	 */
17563e59c137SSandy Huang 	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
17573e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
17583e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
17593e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
17603e59c137SSandy Huang 	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1761d0408543SAndy Yan 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1762d0408543SAndy Yan 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
1763c8820b76SDamon Ding 	     output_mode == ROCKCHIP_OUT_MODE_P888) &&
1764c8820b76SDamon Ding 	     !(output_type == DRM_MODE_CONNECTOR_eDP)))
1765d0408543SAndy Yan 		return true;
1766d0408543SAndy Yan 	else
1767d0408543SAndy Yan 		return false;
1768d0408543SAndy Yan }
1769d0408543SAndy Yan 
1770c8820b76SDamon Ding static bool is_rb_swap(struct display_state *state)
17710675a2a4SDamon Ding {
1772c8820b76SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
1773c8820b76SDamon Ding 	u32 bus_format = conn_state->bus_format;
1774c8820b76SDamon Ding 
17750675a2a4SDamon Ding 	/*
17760675a2a4SDamon Ding 	 * The default component order of serial rgb3x8 formats
17770675a2a4SDamon Ding 	 * is BGR. So it is needed to enable RB swap.
17780675a2a4SDamon Ding 	 */
1779b7b383ebSDamon Ding 	if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
1780b7b383ebSDamon Ding 	    bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8)
17810675a2a4SDamon Ding 		return true;
17820675a2a4SDamon Ding 	else
17830675a2a4SDamon Ding 		return false;
17840675a2a4SDamon Ding }
17850675a2a4SDamon Ding 
17865d2768f7SDamon Ding static bool is_yc_swap(u32 bus_format)
17875d2768f7SDamon Ding {
17885d2768f7SDamon Ding 	switch (bus_format) {
17895d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
17905d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
17915d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
17925d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
17935d2768f7SDamon Ding 		return true;
17945d2768f7SDamon Ding 	default:
17955d2768f7SDamon Ding 		return false;
17965d2768f7SDamon Ding 	}
17975d2768f7SDamon Ding }
17985d2768f7SDamon Ding 
1799b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type)
180063cb669fSSandy Huang {
1801b0989546SSandy Huang 	switch (output_type) {
1802b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIA:
1803b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIB:
1804b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_TV:
1805b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_DisplayPort:
1806b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_VGA:
1807b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_Unknown:
1808b0989546SSandy Huang 		return true;
1809b0989546SSandy Huang 	default:
1810b0989546SSandy Huang 		return false;
181163cb669fSSandy Huang 	}
181263cb669fSSandy Huang }
181363cb669fSSandy Huang 
1814ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1815ecc31b6eSAndy Yan {
1816ecc31b6eSAndy Yan 	int i = 0;
1817ecc31b6eSAndy Yan 
1818ecc31b6eSAndy Yan 	for (i = 0; i < vop2->data->nr_layers; i++) {
1819ecc31b6eSAndy Yan 		if (vop2->data->win_data[i].phys_id == phys_id)
1820ecc31b6eSAndy Yan 			return &vop2->data->win_data[i];
1821ecc31b6eSAndy Yan 	}
1822ecc31b6eSAndy Yan 
1823ecc31b6eSAndy Yan 	return NULL;
1824ecc31b6eSAndy Yan }
1825ecc31b6eSAndy Yan 
1826b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id)
1827b6ba80b4SDamon Ding {
1828b6ba80b4SDamon Ding 	int i = 0;
1829b6ba80b4SDamon Ding 
1830b6ba80b4SDamon Ding 	for (i = 0; i < vop2->data->nr_pd; i++) {
1831b6ba80b4SDamon Ding 		if (vop2->data->pd[i].id == pd_id)
1832b6ba80b4SDamon Ding 			return &vop2->data->pd[i];
1833b6ba80b4SDamon Ding 	}
1834b6ba80b4SDamon Ding 
1835b6ba80b4SDamon Ding 	return NULL;
1836b6ba80b4SDamon Ding }
1837b6ba80b4SDamon Ding 
1838db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1839db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1840db328a0dSDamon Ding {
1841db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1842db328a0dSDamon Ding 	int i;
1843db328a0dSDamon Ding 
1844db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1845db328a0dSDamon Ding 			GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1846db328a0dSDamon Ding 			crtc_id, false);
1847db328a0dSDamon Ding 
1848db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1849db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1850db328a0dSDamon Ding 
1851db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1852db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1853db328a0dSDamon Ding }
1854db328a0dSDamon Ding 
1855db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1856db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1857db328a0dSDamon Ding {
1858db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1859db328a0dSDamon Ding 	int i;
1860db328a0dSDamon Ding 
1861db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1862db328a0dSDamon Ding 			GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1863db328a0dSDamon Ding 			crtc_id, false);
1864db328a0dSDamon Ding 
1865db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1866db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1867db328a0dSDamon Ding 
1868db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1869db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1870db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1871db328a0dSDamon Ding 			EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false);
1872db328a0dSDamon Ding }
1873db328a0dSDamon Ding 
18741147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1875d0408543SAndy Yan 					struct display_state *state)
1876d0408543SAndy Yan {
18771147facaSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
18781147facaSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
18791147facaSSandy Huang 	struct resource gamma_res;
18801147facaSSandy Huang 	fdt_size_t lut_size;
18811147facaSSandy Huang 	int i, lut_len, ret = 0;
18821147facaSSandy Huang 	u32 *lut_regs;
18831147facaSSandy Huang 	u32 r, g, b;
18841147facaSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
18851147facaSSandy Huang 	static int gamma_lut_en_num = 1;
18861147facaSSandy Huang 
18871147facaSSandy Huang 	if (gamma_lut_en_num > vop2->data->nr_gammas) {
18881147facaSSandy Huang 		printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
18891147facaSSandy Huang 		return 0;
18901147facaSSandy Huang 	}
18911147facaSSandy Huang 
18921147facaSSandy Huang 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
18931147facaSSandy Huang 	if (ret)
18941147facaSSandy Huang 		printf("failed to get gamma lut res\n");
18951147facaSSandy Huang 	lut_regs = (u32 *)gamma_res.start;
18961147facaSSandy Huang 	lut_size = gamma_res.end - gamma_res.start + 1;
18971147facaSSandy Huang 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
18981147facaSSandy Huang 		printf("failed to get gamma lut register\n");
18991147facaSSandy Huang 		return 0;
19001147facaSSandy Huang 	}
19011147facaSSandy Huang 	lut_len = lut_size / 4;
19021147facaSSandy Huang 	if (lut_len != 256 && lut_len != 1024) {
19031147facaSSandy Huang 		printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
19041147facaSSandy Huang 		return 0;
19051147facaSSandy Huang 	}
19060669ab1fSDamon Ding 
19070669ab1fSDamon Ding 	if (!cstate->lut_val) {
19080669ab1fSDamon Ding 		if (!disp_info)
19090669ab1fSDamon Ding 			return 0;
19100669ab1fSDamon Ding 
19110669ab1fSDamon Ding 		if (!disp_info->gamma_lut_data.size)
19120669ab1fSDamon Ding 			return 0;
19130669ab1fSDamon Ding 
19140669ab1fSDamon Ding 		cstate->lut_val = (u32 *)calloc(1, lut_size);
19151147facaSSandy Huang 		for (i = 0; i < lut_len; i++) {
19161147facaSSandy Huang 			r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
19171147facaSSandy Huang 			g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
19181147facaSSandy Huang 			b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
19191147facaSSandy Huang 
19200669ab1fSDamon Ding 			cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
19210669ab1fSDamon Ding 		}
19221147facaSSandy Huang 	}
19231147facaSSandy Huang 
1924db328a0dSDamon Ding 	if (vop2->version == VOP_VERSION_RK3568) {
19250669ab1fSDamon Ding 		rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
19260669ab1fSDamon Ding 				     cstate->lut_val, lut_len);
19271147facaSSandy Huang 		gamma_lut_en_num++;
192818d9b8adSDamon Ding 	} else {
19290669ab1fSDamon Ding 		rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
19300669ab1fSDamon Ding 				     cstate->lut_val, lut_len);
1931db328a0dSDamon Ding 		if (cstate->splice_mode) {
19320669ab1fSDamon Ding 			rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs,
19330669ab1fSDamon Ding 					     cstate->lut_val, lut_len);
1934db328a0dSDamon Ding 			gamma_lut_en_num++;
1935db328a0dSDamon Ding 		}
1936db328a0dSDamon Ding 		gamma_lut_en_num++;
1937db328a0dSDamon Ding 	}
19381147facaSSandy Huang 
19390669ab1fSDamon Ding 	free(cstate->lut_val);
19400669ab1fSDamon Ding 
1941d0408543SAndy Yan 	return 0;
1942d0408543SAndy Yan }
1943d0408543SAndy Yan 
19446414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
19456414e3bcSSandy Huang 					struct display_state *state)
19466414e3bcSSandy Huang {
19476414e3bcSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
19486414e3bcSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
19496414e3bcSSandy Huang 	int i, cubic_lut_len;
19506414e3bcSSandy Huang 	u32 vp_offset = cstate->crtc_id * 0x100;
19516414e3bcSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
19526414e3bcSSandy Huang 	struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
19536414e3bcSSandy Huang 	u32 *cubic_lut_addr;
19546414e3bcSSandy Huang 
19556414e3bcSSandy Huang 	if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
19566414e3bcSSandy Huang 		return 0;
19576414e3bcSSandy Huang 
19586414e3bcSSandy Huang 	if (!disp_info->cubic_lut_data.size)
19596414e3bcSSandy Huang 		return 0;
19606414e3bcSSandy Huang 
19616414e3bcSSandy Huang 	cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
19626414e3bcSSandy Huang 	cubic_lut_len = disp_info->cubic_lut_data.size;
19636414e3bcSSandy Huang 
19646414e3bcSSandy Huang 	for (i = 0; i < cubic_lut_len / 2; i++) {
19656414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
19666414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
19676414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
19686414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
19696414e3bcSSandy Huang 					((lut->lred[2 * i + 1] & 0xfff) << 4) +
19706414e3bcSSandy Huang 					((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
19716414e3bcSSandy Huang 					((lut->lblue[2 * i + 1] & 0xf) << 28);
19726414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
19736414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
19746414e3bcSSandy Huang 	}
19756414e3bcSSandy Huang 
19766414e3bcSSandy Huang 	if (cubic_lut_len % 2) {
19776414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
19786414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
19796414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
19806414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
19816414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
19826414e3bcSSandy Huang 		*cubic_lut_addr = 0;
19836414e3bcSSandy Huang 	}
19846414e3bcSSandy Huang 
19856414e3bcSSandy Huang 	vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
19866414e3bcSSandy Huang 		    get_cubic_lut_buffer(cstate->crtc_id));
19876414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
19886414e3bcSSandy Huang 			EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
19896414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
19906414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
19916414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
19926414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
19936414e3bcSSandy Huang 
19946414e3bcSSandy Huang 	return 0;
19956414e3bcSSandy Huang }
19966414e3bcSSandy Huang 
1997ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2,
1998ee01dbb2SDamon Ding 				 struct bcsh_state *bcsh_state, int crtc_id)
1999ee01dbb2SDamon Ding {
2000ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2001ee01dbb2SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
2002ee01dbb2SDamon Ding 
2003ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
2004ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false);
2005ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
2006ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false);
2007ee01dbb2SDamon Ding 
2008ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
2009ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2010ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
2011ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2012ee01dbb2SDamon Ding 
2013ee01dbb2SDamon Ding 	if (!cstate->bcsh_en) {
2014ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2015ee01dbb2SDamon Ding 				BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
2016ee01dbb2SDamon Ding 		return;
2017ee01dbb2SDamon Ding 	}
2018ee01dbb2SDamon Ding 
2019ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2020ee01dbb2SDamon Ding 			BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
2021ee01dbb2SDamon Ding 			bcsh_state->brightness, false);
2022ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2023ee01dbb2SDamon Ding 			BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false);
2024ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2025ee01dbb2SDamon Ding 			BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
2026ee01dbb2SDamon Ding 			bcsh_state->saturation * bcsh_state->contrast / 0x100, false);
2027ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2028ee01dbb2SDamon Ding 			BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false);
2029ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2030ee01dbb2SDamon Ding 			BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false);
2031ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2032ee01dbb2SDamon Ding 			BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
2033ee01dbb2SDamon Ding 			BCSH_OUT_MODE_NORMAL_VIDEO, false);
2034ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2035ee01dbb2SDamon Ding 			BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
2036ee01dbb2SDamon Ding }
2037ee01dbb2SDamon Ding 
2038ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
2039ac500a1fSSandy Huang {
2040ac500a1fSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
2041ac500a1fSSandy Huang 	struct base_bcsh_info *bcsh_info;
2042ac500a1fSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
2043ee01dbb2SDamon Ding 	struct bcsh_state bcsh_state;
2044ac500a1fSSandy Huang 	int brightness, contrast, saturation, hue, sin_hue, cos_hue;
2045ac500a1fSSandy Huang 
2046ac500a1fSSandy Huang 	if (!conn_state->disp_info)
2047ac500a1fSSandy Huang 		return;
2048ac500a1fSSandy Huang 	bcsh_info = &conn_state->disp_info->bcsh_info;
2049ac500a1fSSandy Huang 	if (!bcsh_info)
2050ac500a1fSSandy Huang 		return;
2051ac500a1fSSandy Huang 
2052ac500a1fSSandy Huang 	if (bcsh_info->brightness != 50 ||
2053ac500a1fSSandy Huang 	    bcsh_info->contrast != 50 ||
2054ac500a1fSSandy Huang 	    bcsh_info->saturation != 50 || bcsh_info->hue != 50)
2055ee01dbb2SDamon Ding 		cstate->bcsh_en = true;
2056ac500a1fSSandy Huang 
2057ee01dbb2SDamon Ding 	if (cstate->bcsh_en) {
2058ac500a1fSSandy Huang 		if (!cstate->yuv_overlay)
2059ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2060ac500a1fSSandy Huang 		if (!is_yuv_output(conn_state->bus_format))
2061ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2062ac500a1fSSandy Huang 	} else {
2063ac500a1fSSandy Huang 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2064ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2065ac500a1fSSandy Huang 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2066ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2067ac500a1fSSandy Huang 	}
2068ac500a1fSSandy Huang 
2069df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2070df0a5c43SDamon Ding 						      conn_state->color_range,
2071df0a5c43SDamon Ding 						      CSC_10BIT_DEPTH);
2072ac500a1fSSandy Huang 
2073ac500a1fSSandy Huang 	if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
2074ac500a1fSSandy Huang 		brightness = interpolate(0, -128, 100, 127,
2075ac500a1fSSandy Huang 					 bcsh_info->brightness);
2076ac500a1fSSandy Huang 	else
2077ac500a1fSSandy Huang 		brightness = interpolate(0, -32, 100, 31,
2078ac500a1fSSandy Huang 					 bcsh_info->brightness);
2079ac500a1fSSandy Huang 	contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
2080ac500a1fSSandy Huang 	saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
2081ac500a1fSSandy Huang 	hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
2082ac500a1fSSandy Huang 
2083ac500a1fSSandy Huang 
2084ac500a1fSSandy Huang 	/*
2085ac500a1fSSandy Huang 	 *  a:[-30~0):
2086ac500a1fSSandy Huang 	 *    sin_hue = 0x100 - sin(a)*256;
2087ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2088ac500a1fSSandy Huang 	 *  a:[0~30]
2089ac500a1fSSandy Huang 	 *    sin_hue = sin(a)*256;
2090ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2091ac500a1fSSandy Huang 	 */
2092ac500a1fSSandy Huang 	sin_hue = fixp_sin32(hue) >> 23;
2093ac500a1fSSandy Huang 	cos_hue = fixp_cos32(hue) >> 23;
2094ac500a1fSSandy Huang 
2095ee01dbb2SDamon Ding 	bcsh_state.brightness = brightness;
2096ee01dbb2SDamon Ding 	bcsh_state.contrast = contrast;
2097ee01dbb2SDamon Ding 	bcsh_state.saturation = saturation;
2098ee01dbb2SDamon Ding 	bcsh_state.sin_hue = sin_hue;
2099ee01dbb2SDamon Ding 	bcsh_state.cos_hue = cos_hue;
2100ee01dbb2SDamon Ding 
2101ee01dbb2SDamon Ding 	vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id);
2102ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2103ee01dbb2SDamon Ding 		vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id);
2104ee01dbb2SDamon Ding }
2105ee01dbb2SDamon Ding 
2106ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id)
2107ee01dbb2SDamon Ding {
2108ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2109ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2110ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2111ee01dbb2SDamon Ding 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
2112ee01dbb2SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2113ee01dbb2SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2114ee01dbb2SDamon Ding 
2115ee01dbb2SDamon Ding 	bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly;
2116ee01dbb2SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly;
2117ee01dbb2SDamon Ding 	bg_dly -= bg_ovl_dly;
2118ee01dbb2SDamon Ding 
2119a552a69cSDamon Ding 	/*
2120a552a69cSDamon Ding 	 * splice mode: hdisplay must roundup as 4 pixel,
2121a552a69cSDamon Ding 	 * no splice mode: hdisplay must roundup as 2 pixel.
2122a552a69cSDamon Ding 	 */
2123ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2124a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1;
2125ee01dbb2SDamon Ding 	else
2126a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2127ee01dbb2SDamon Ding 
2128ee01dbb2SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
2129ee01dbb2SDamon Ding 		hsync_len = 8;
2130ee01dbb2SDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
2131ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4,
2132ee01dbb2SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2133ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2134ac500a1fSSandy Huang }
2135ac500a1fSSandy Huang 
2136452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id)
2137452afb13SDamon Ding {
2138452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2139452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2140452afb13SDamon Ding 	u32 bg_dly, pre_scan_dly;
2141452afb13SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2142452afb13SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2143452afb13SDamon Ding 
2144452afb13SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].win_dly +
2145452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].layer_mix_dly +
2146452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].hdr_mix_dly;
2147a552a69cSDamon Ding 	/* hdisplay must roundup as 2 pixel */
2148a552a69cSDamon Ding 	pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2149a552a69cSDamon Ding 	/**
2150a552a69cSDamon Ding 	 * pre_scan_hblank minimum value is 8, otherwise the win reset signal will
2151a552a69cSDamon Ding 	 * lead to first line data be zero.
2152a552a69cSDamon Ding 	 */
2153a552a69cSDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len);
2154452afb13SDamon Ding 	vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100,
2155452afb13SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2156452afb13SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2157452afb13SDamon Ding }
2158452afb13SDamon Ding 
2159d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
2160d0408543SAndy Yan {
2161d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
2162d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
216352ee18acSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
21649c7848c3SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
21659c7848c3SDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
216652ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
2167d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
2168d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
2169d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
2170d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
2171d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
2172d0408543SAndy Yan 	u16 hsize =
2173d0408543SAndy Yan 	    hdisplay * (conn_state->overscan.left_margin +
2174d0408543SAndy Yan 			conn_state->overscan.right_margin) / 200;
2175d0408543SAndy Yan 	u16 vsize =
2176d0408543SAndy Yan 	    vdisplay * (conn_state->overscan.top_margin +
2177d0408543SAndy Yan 			conn_state->overscan.bottom_margin) / 200;
2178d0408543SAndy Yan 	u16 hact_end, vact_end;
2179d0408543SAndy Yan 	u32 val;
2180d0408543SAndy Yan 
218174bd8269SSandy Huang 	hsize = round_down(hsize, 2);
2182d0408543SAndy Yan 	vsize = round_down(vsize, 2);
2183d0408543SAndy Yan 
2184d0408543SAndy Yan 	hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
2185d0408543SAndy Yan 	hact_end = hact_st + hsize;
2186d0408543SAndy Yan 	val = hact_st << 16;
2187d0408543SAndy Yan 	val |= hact_end;
2188d0408543SAndy Yan 
218952ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
2190d0408543SAndy Yan 	vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
2191d0408543SAndy Yan 	vact_end = vact_st + vsize;
2192d0408543SAndy Yan 	val = vact_st << 16;
2193d0408543SAndy Yan 	val |= vact_end;
219452ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
2195d0408543SAndy Yan 	val = scl_cal_scale2(vdisplay, vsize) << 16;
2196d0408543SAndy Yan 	val |= scl_cal_scale2(hdisplay, hsize);
219752ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
2198d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
2199d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
22007504507fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
22017504507fSSandy Huang 			RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT,
2202d0408543SAndy Yan 			POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
22037504507fSSandy Huang 			POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false);
2204d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
2205d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
2206d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vsize;
2207d0408543SAndy Yan 
2208d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
220952ee18acSSandy Huang 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
2210d0408543SAndy Yan 	}
2211d0408543SAndy Yan 
2212452afb13SDamon Ding 	if (is_vop3(vop2)) {
2213452afb13SDamon Ding 		vop3_setup_pipe_dly(state, vop2, cstate->crtc_id);
2214452afb13SDamon Ding 	} else {
2215ee01dbb2SDamon Ding 		vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id);
22169c7848c3SDamon Ding 		vop2_ops->setup_win_dly(state, cstate->crtc_id);
22179c7848c3SDamon Ding 		if (cstate->splice_mode) {
2218ee01dbb2SDamon Ding 			vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id);
22199c7848c3SDamon Ding 			vop2_ops->setup_win_dly(state, cstate->splice_crtc_id);
22209c7848c3SDamon Ding 		}
2221d0408543SAndy Yan 	}
2222452afb13SDamon Ding }
2223d0408543SAndy Yan 
22246027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2)
22256027c871SZhang Yubing {
22266027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
22276027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
22286027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
22296027c871SZhang Yubing 	struct drm_display_mode *mode = &conn_state->mode;
22306027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
22316027c871SZhang Yubing 	s16 *lut_y;
22326027c871SZhang Yubing 	s16 *lut_h;
22336027c871SZhang Yubing 	s16 *lut_s;
22346027c871SZhang Yubing 	u32 value;
22356027c871SZhang Yubing 	int i;
22366027c871SZhang Yubing 
22376027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2238b8db91d0SZhang Yubing 		POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2239b8db91d0SZhang Yubing 	if (!acm->acm_enable) {
2240b8db91d0SZhang Yubing 		writel(0, vop2->regs + RK3528_ACM_CTRL);
22416027c871SZhang Yubing 		return;
22426027c871SZhang Yubing 	}
22436027c871SZhang Yubing 
22446027c871SZhang Yubing 	printf("post acm enable\n");
22456027c871SZhang Yubing 
22466027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_START);
22476027c871SZhang Yubing 
22486027c871SZhang Yubing 	value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) +
22496027c871SZhang Yubing 		((mode->vdisplay & 0xfff) << 20);
22506027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_CTRL);
22516027c871SZhang Yubing 
22526027c871SZhang Yubing 	value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
22536027c871SZhang Yubing 		((acm->s_gain << 20) & 0x3ff00000);
22546027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE);
22556027c871SZhang Yubing 
22566027c871SZhang Yubing 	lut_y = &acm->gain_lut_hy[0];
22576027c871SZhang Yubing 	lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
22586027c871SZhang Yubing 	lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
22596027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
22606027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
22616027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
22626027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
22636027c871SZhang Yubing 	}
22646027c871SZhang Yubing 
22656027c871SZhang Yubing 	lut_y = &acm->gain_lut_hs[0];
22666027c871SZhang Yubing 	lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
22676027c871SZhang Yubing 	lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
22686027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
22696027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
22706027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
22716027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
22726027c871SZhang Yubing 	}
22736027c871SZhang Yubing 
22746027c871SZhang Yubing 	lut_y = &acm->delta_lut_h[0];
22756027c871SZhang Yubing 	lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
22766027c871SZhang Yubing 	lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
22776027c871SZhang Yubing 	for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
22786027c871SZhang Yubing 		value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
22796027c871SZhang Yubing 			((lut_s[i] << 20) & 0x3ff00000);
22806027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
22816027c871SZhang Yubing 	}
22826027c871SZhang Yubing 
22836027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_DONE);
22846027c871SZhang Yubing }
22856027c871SZhang Yubing 
22866027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2)
22876027c871SZhang Yubing {
22886027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
22896027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
22906027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
22916027c871SZhang Yubing 	struct csc_info *csc = &conn_state->disp_info->csc_info;
22926027c871SZhang Yubing 	struct post_csc_coef csc_coef;
22936027c871SZhang Yubing 	bool is_input_yuv = false;
22946027c871SZhang Yubing 	bool is_output_yuv = false;
22956027c871SZhang Yubing 	bool post_r2y_en = false;
22966027c871SZhang Yubing 	bool post_csc_en = false;
22976027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
22986027c871SZhang Yubing 	u32 value;
22996027c871SZhang Yubing 	int range_type;
23006027c871SZhang Yubing 
23016027c871SZhang Yubing 	printf("post csc enable\n");
23026027c871SZhang Yubing 
23036027c871SZhang Yubing 	if (acm->acm_enable) {
23046027c871SZhang Yubing 		if (!cstate->yuv_overlay)
23056027c871SZhang Yubing 			post_r2y_en = true;
23066027c871SZhang Yubing 
23076027c871SZhang Yubing 		/* do y2r in csc module */
23086027c871SZhang Yubing 		if (!is_yuv_output(conn_state->bus_format))
23096027c871SZhang Yubing 			post_csc_en = true;
23106027c871SZhang Yubing 	} else {
23116027c871SZhang Yubing 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
23126027c871SZhang Yubing 			post_r2y_en = true;
23136027c871SZhang Yubing 
23146027c871SZhang Yubing 		/* do y2r in csc module */
23156027c871SZhang Yubing 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
23166027c871SZhang Yubing 			post_csc_en = true;
23176027c871SZhang Yubing 	}
23186027c871SZhang Yubing 
23196027c871SZhang Yubing 	if (csc->csc_enable)
23206027c871SZhang Yubing 		post_csc_en = true;
23216027c871SZhang Yubing 
23226027c871SZhang Yubing 	if (cstate->yuv_overlay || post_r2y_en)
23236027c871SZhang Yubing 		is_input_yuv = true;
23246027c871SZhang Yubing 
23256027c871SZhang Yubing 	if (is_yuv_output(conn_state->bus_format))
23266027c871SZhang Yubing 		is_output_yuv = true;
23276027c871SZhang Yubing 
2328df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2329df0a5c43SDamon Ding 						      conn_state->color_range,
2330df0a5c43SDamon Ding 						      CSC_13BIT_DEPTH);
23316027c871SZhang Yubing 
23326027c871SZhang Yubing 	if (post_csc_en) {
23336027c871SZhang Yubing 		rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv,
23346027c871SZhang Yubing 				       is_output_yuv);
23356027c871SZhang Yubing 
23366027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23376027c871SZhang Yubing 				POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT,
23386027c871SZhang Yubing 				csc_coef.csc_coef00, false);
23395743c73eSZhang Yubing 		value = csc_coef.csc_coef01 & 0xffff;
23405743c73eSZhang Yubing 		value |= (csc_coef.csc_coef02 << 16) & 0xffff0000;
23416027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02);
23425743c73eSZhang Yubing 		value = csc_coef.csc_coef10 & 0xffff;
23435743c73eSZhang Yubing 		value |= (csc_coef.csc_coef11 << 16) & 0xffff0000;
23446027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11);
23455743c73eSZhang Yubing 		value = csc_coef.csc_coef12 & 0xffff;
23465743c73eSZhang Yubing 		value |= (csc_coef.csc_coef20 << 16) & 0xffff0000;
23476027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20);
23485743c73eSZhang Yubing 		value = csc_coef.csc_coef21 & 0xffff;
23495743c73eSZhang Yubing 		value |= (csc_coef.csc_coef22 << 16) & 0xffff0000;
23506027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22);
23516027c871SZhang Yubing 		writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0);
23526027c871SZhang Yubing 		writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1);
23536027c871SZhang Yubing 		writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2);
23546027c871SZhang Yubing 
23556027c871SZhang Yubing 		range_type = csc_coef.range_type ? 0 : 1;
23566027c871SZhang Yubing 		range_type <<= is_input_yuv ? 0 : 1;
23576027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23586027c871SZhang Yubing 				POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false);
23596027c871SZhang Yubing 	}
23606027c871SZhang Yubing 
23616027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23625743c73eSZhang Yubing 			POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false);
23636027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23646027c871SZhang Yubing 			POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false);
23656027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23666027c871SZhang Yubing 			POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false);
23676027c871SZhang Yubing }
23686027c871SZhang Yubing 
23696027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2)
23706027c871SZhang Yubing {
23716027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
23726027c871SZhang Yubing 	struct base2_disp_info *disp_info = conn_state->disp_info;
23736027c871SZhang Yubing 	const char *enable_flag;
23746027c871SZhang Yubing 	if (!disp_info) {
23756027c871SZhang Yubing 		printf("disp_info is empty\n");
23766027c871SZhang Yubing 		return;
23776027c871SZhang Yubing 	}
23786027c871SZhang Yubing 
23796027c871SZhang Yubing 	enable_flag = (const char *)&disp_info->cacm_header;
23806027c871SZhang Yubing 	if (strncasecmp(enable_flag, "CACM", 4)) {
23816027c871SZhang Yubing 		printf("acm and csc is not support\n");
23826027c871SZhang Yubing 		return;
23836027c871SZhang Yubing 	}
23846027c871SZhang Yubing 
23856027c871SZhang Yubing 	vop3_post_acm_config(state, vop2);
23866027c871SZhang Yubing 	vop3_post_csc_config(state, vop2);
23876027c871SZhang Yubing }
23886027c871SZhang Yubing 
2389a552a69cSDamon Ding static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2,
2390a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
2391a552a69cSDamon Ding {
2392a552a69cSDamon Ding 	int val = 0;
2393a552a69cSDamon Ding 	bool is_bisr_en, is_otp_bisr_en;
2394a552a69cSDamon Ding 
2395a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER) {
2396a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2397a552a69cSDamon Ding 					    EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2398a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2399a552a69cSDamon Ding 						EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2400a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2401a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2402a552a69cSDamon Ding 						  val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1),
2403a552a69cSDamon Ding 						  50 * 1000);
2404a552a69cSDamon Ding 		else
2405a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
24060e0a0ff9SDamon Ding 						  val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1),
2407a552a69cSDamon Ding 						  50 * 1000);
2408a552a69cSDamon Ding 	} else {
2409a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2410a552a69cSDamon Ding 					    EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2411a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2412a552a69cSDamon Ding 						EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2413a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2414a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2415a552a69cSDamon Ding 						  val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1),
2416a552a69cSDamon Ding 						  50 * 1000);
2417a552a69cSDamon Ding 		else
2418a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2419a552a69cSDamon Ding 						  val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1),
2420a552a69cSDamon Ding 						  50 * 1000);
2421a552a69cSDamon Ding 	}
2422a552a69cSDamon Ding }
2423a552a69cSDamon Ding 
2424a552a69cSDamon Ding static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2425a552a69cSDamon Ding {
2426a552a69cSDamon Ding 	int ret = 0;
2427a552a69cSDamon Ding 
2428a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER)
2429a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK,
2430a552a69cSDamon Ding 				RK3576_CLUSTER_PD_EN_SHIFT, 0, true);
2431a552a69cSDamon Ding 	else
2432a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK,
2433a552a69cSDamon Ding 				RK3576_ESMART_PD_EN_SHIFT, 0, true);
2434a552a69cSDamon Ding 	ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data);
2435a552a69cSDamon Ding 	if (ret) {
2436a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2437a552a69cSDamon Ding 		return ret;
2438a552a69cSDamon Ding 	}
2439a552a69cSDamon Ding 
2440a552a69cSDamon Ding 	return 0;
2441a552a69cSDamon Ding }
2442a552a69cSDamon Ding 
2443a552a69cSDamon Ding static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2,
2444a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
244560e469f5SDamon Ding {
244660e469f5SDamon Ding 	int val = 0;
244760e469f5SDamon Ding 	int shift = 0;
2448b6ba80b4SDamon Ding 	int shift_factor = 0;
244960e469f5SDamon Ding 	bool is_bisr_en = false;
245060e469f5SDamon Ding 
2451b6ba80b4SDamon Ding 	/*
2452b6ba80b4SDamon Ding 	 * The order of pd status bits in BISR_STS register
2453b6ba80b4SDamon Ding 	 * is different from that in VOP SYS_STS register.
2454b6ba80b4SDamon Ding 	 */
2455b6ba80b4SDamon Ding 	if (pd_data->id == VOP2_PD_DSC_8K ||
2456b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_DSC_4K ||
2457b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_ESMART)
2458b6ba80b4SDamon Ding 		shift_factor = 1;
2459b6ba80b4SDamon Ding 
2460b6ba80b4SDamon Ding 	shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor;
2461b6ba80b4SDamon Ding 	is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift);
246260e469f5SDamon Ding 	if (is_bisr_en) {
2463b6ba80b4SDamon Ding 		shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor;
2464b6ba80b4SDamon Ding 
246560e469f5SDamon Ding 		return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
2466d2e91fdcSDamon Ding 					  ((val >> shift) & 0x1), 50 * 1000);
246760e469f5SDamon Ding 	} else {
2468b6ba80b4SDamon Ding 		shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1;
2469b6ba80b4SDamon Ding 
247060e469f5SDamon Ding 		return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
247160e469f5SDamon Ding 					  !((val >> shift) & 0x1), 50 * 1000);
247260e469f5SDamon Ding 	}
247360e469f5SDamon Ding }
247460e469f5SDamon Ding 
2475a552a69cSDamon Ding static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2476a552a69cSDamon Ding {
2477a552a69cSDamon Ding 	int ret = 0;
2478a552a69cSDamon Ding 
2479a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK,
2480a552a69cSDamon Ding 			RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false);
2481a552a69cSDamon Ding 	ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data);
2482a552a69cSDamon Ding 	if (ret) {
2483a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2484a552a69cSDamon Ding 		return ret;
2485a552a69cSDamon Ding 	}
2486a552a69cSDamon Ding 
2487a552a69cSDamon Ding 	return 0;
2488a552a69cSDamon Ding }
2489a552a69cSDamon Ding 
2490b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id)
249160e469f5SDamon Ding {
249260e469f5SDamon Ding 	struct vop2_power_domain_data *pd_data;
249360e469f5SDamon Ding 	int ret = 0;
249460e469f5SDamon Ding 
2495b6ba80b4SDamon Ding 	if (!pd_id)
2496b6ba80b4SDamon Ding 		return 0;
2497b6ba80b4SDamon Ding 
2498b6ba80b4SDamon Ding 	pd_data = vop2_find_pd_data_by_id(vop2, pd_id);
2499b6ba80b4SDamon Ding 	if (!pd_data) {
2500b6ba80b4SDamon Ding 		printf("can't find pd_data by id\n");
250160e469f5SDamon Ding 		return -EINVAL;
250260e469f5SDamon Ding 	}
25032c66af11SDamon Ding 
2504b6ba80b4SDamon Ding 	if (pd_data->parent_id) {
2505b6ba80b4SDamon Ding 		ret = vop2_power_domain_on(vop2, pd_data->parent_id);
250660e469f5SDamon Ding 		if (ret) {
250760e469f5SDamon Ding 			printf("can't open parent power domain\n");
250860e469f5SDamon Ding 			return -EINVAL;
250960e469f5SDamon Ding 		}
251060e469f5SDamon Ding 	}
251160e469f5SDamon Ding 
2512a552a69cSDamon Ding 	/*
2513a552a69cSDamon Ding 	 * Read VOP internal power domain on/off status.
2514a552a69cSDamon Ding 	 * We should query BISR_STS register in PMU for
2515a552a69cSDamon Ding 	 * power up/down status when memory repair is enabled.
2516a552a69cSDamon Ding 	 * Return value: 1 for power on, 0 for power off;
2517a552a69cSDamon Ding 	 */
2518a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
2519a552a69cSDamon Ding 		ret = rk3576_vop2_power_domain_on(vop2, pd_data);
2520a552a69cSDamon Ding 	else
2521a552a69cSDamon Ding 		ret = rk3588_vop2_power_domain_on(vop2, pd_data);
252260e469f5SDamon Ding 
2523a552a69cSDamon Ding 	return ret;
252460e469f5SDamon Ding }
252560e469f5SDamon Ding 
2526ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2)
2527ecc31b6eSAndy Yan {
2528ecc31b6eSAndy Yan 	u32 *base = vop2->regs;
2529ecc31b6eSAndy Yan 	int i = 0;
2530ecc31b6eSAndy Yan 
2531ecc31b6eSAndy Yan 	/*
2532ecc31b6eSAndy Yan 	 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
2533ecc31b6eSAndy Yan 	 */
2534ecc31b6eSAndy Yan 	for (i = 0; i < (vop2->reg_len >> 2); i++)
2535ecc31b6eSAndy Yan 		vop2->regsbak[i] = base[i];
2536ecc31b6eSAndy Yan }
2537ecc31b6eSAndy Yan 
25385fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win)
25395fa6e665SDamon Ding {
25405fa6e665SDamon Ding 	if (!is_vop3(vop2))
25415fa6e665SDamon Ding 		return false;
25425fa6e665SDamon Ding 
25435fa6e665SDamon Ding 	if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
25445fa6e665SDamon Ding 	    win->phys_id != ROCKCHIP_VOP2_ESMART0)
25455fa6e665SDamon Ding 		return true;
25465fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
25475fa6e665SDamon Ding 		 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
25485fa6e665SDamon Ding 		return true;
25495fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
25505fa6e665SDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART1)
25515fa6e665SDamon Ding 		return true;
2552a552a69cSDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE &&
2553a552a69cSDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART3)
2554a552a69cSDamon Ding 		return true;
25555fa6e665SDamon Ding 	else
25565fa6e665SDamon Ding 		return false;
25575fa6e665SDamon Ding }
25585fa6e665SDamon Ding 
25595fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
25605fa6e665SDamon Ding {
25615fa6e665SDamon Ding 	struct vop2_win_data *win_data;
2562fa4ecc32SDamon Ding 	int i;
25635fa6e665SDamon Ding 	u8 scale_engine_num = 0;
25645fa6e665SDamon Ding 
25655fa6e665SDamon Ding 	/* store plane mask for vop2_fixup_dts */
2566fa4ecc32SDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
2567fa4ecc32SDamon Ding 		win_data = &vop2->data->win_data[i];
25685fa6e665SDamon Ding 		if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data))
25695fa6e665SDamon Ding 			continue;
25705fa6e665SDamon Ding 
25715fa6e665SDamon Ding 		win_data->scale_engine_num = scale_engine_num++;
25725fa6e665SDamon Ding 	}
25735fa6e665SDamon Ding }
25745fa6e665SDamon Ding 
2575a552a69cSDamon Ding static int vop3_get_esmart_lb_mode(struct vop2 *vop2)
2576a552a69cSDamon Ding {
2577a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map;
2578a552a69cSDamon Ding 	int i;
2579a552a69cSDamon Ding 
2580a552a69cSDamon Ding 	if (!esmart_lb_mode_map)
2581a552a69cSDamon Ding 		return vop2->esmart_lb_mode;
2582a552a69cSDamon Ding 
2583a552a69cSDamon Ding 	for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) {
2584a552a69cSDamon Ding 		if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode)
2585a552a69cSDamon Ding 			return esmart_lb_mode_map->lb_map_value;
2586a552a69cSDamon Ding 		esmart_lb_mode_map++;
2587a552a69cSDamon Ding 	}
2588a552a69cSDamon Ding 
2589a552a69cSDamon Ding 	if (i == vop2->data->esmart_lb_mode_num)
2590a552a69cSDamon Ding 		printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode);
2591a552a69cSDamon Ding 
2592a552a69cSDamon Ding 	return vop2->data->esmart_lb_mode_map[0].lb_map_value;
2593a552a69cSDamon Ding }
2594a552a69cSDamon Ding 
2595b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
2596d0408543SAndy Yan {
2597b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
2598b7195f56SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
2599b7195f56SDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
2600b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
2601a552a69cSDamon Ding 	int active_vp_num = 0;
26025fa6e665SDamon Ding 	int layer_phy_id = 0;
26035fa6e665SDamon Ding 	int i, j;
26045fa6e665SDamon Ding 	u32 layer_nr = 0;
260551e1509eSDamon Ding 	const u8 *tmp;
2606d0408543SAndy Yan 
260763cb669fSSandy Huang 	if (vop2->global_init)
2608d0408543SAndy Yan 		return;
260963cb669fSSandy Huang 
2610b0989546SSandy Huang 	/* OTP must enable at the first time, otherwise mirror layer register is error */
261163cb669fSSandy Huang 	if (soc_is_rk3566())
261263cb669fSSandy Huang 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
261363cb669fSSandy Huang 				OTP_WIN_EN_SHIFT, 1, false);
2614b0989546SSandy Huang 
2615b0989546SSandy Huang 	if (cstate->crtc->assign_plane) {/* dts assign plane */
2616b0989546SSandy Huang 		u32 plane_mask;
2617b0989546SSandy Huang 		int primary_plane_id;
2618b0989546SSandy Huang 
2619b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
2620b0989546SSandy Huang 			plane_mask = cstate->crtc->vps[i].plane_mask;
2621b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2622b0989546SSandy Huang 			layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */
2623b0989546SSandy Huang 			vop2->vp_plane_mask[i].attached_layers_nr = layer_nr;
26245fc2b656SDamon Ding 			primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
2625337d1c13SDamon Ding 			if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX)
2626b0989546SSandy Huang 				primary_plane_id = vop2_get_primary_plane(vop2, plane_mask);
2627b0989546SSandy Huang 			vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id;
2628b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2629b0989546SSandy Huang 
2630b0989546SSandy Huang 			/* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/
2631b0989546SSandy Huang 			for (j = 0; j < layer_nr; j++) {
2632b0989546SSandy Huang 				vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
2633b0989546SSandy Huang 				plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
263463cb669fSSandy Huang 			}
2635b0989546SSandy Huang 		}
2636b0989546SSandy Huang 	} else {/* need soft assign plane mask */
2637a552a69cSDamon Ding 		printf("Assign plane mask automatically\n");
2638a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
2639a552a69cSDamon Ding 			for (i = 0; i < vop2->data->nr_vps; i++) {
2640a552a69cSDamon Ding 				if (cstate->crtc->vps[i].enable) {
2641a552a69cSDamon Ding 					vop2->vp_plane_mask[i].attached_layers_nr = 1;
2642a552a69cSDamon Ding 					vop2->vp_plane_mask[i].primary_plane_id =
2643a552a69cSDamon Ding 						vop2->data->vp_default_primary_plane[i];
2644a552a69cSDamon Ding 					vop2->vp_plane_mask[i].attached_layers[0] =
2645a552a69cSDamon Ding 						vop2->data->vp_default_primary_plane[i];
2646a552a69cSDamon Ding 					vop2->vp_plane_mask[i].plane_mask |=
2647a552a69cSDamon Ding 						BIT(vop2->data->vp_default_primary_plane[i]);
2648a552a69cSDamon Ding 					active_vp_num++;
2649a552a69cSDamon Ding 				}
2650a552a69cSDamon Ding 			}
2651a552a69cSDamon Ding 			printf("VOP have %d active VP\n", active_vp_num);
2652a552a69cSDamon Ding 		} else {
2653b0989546SSandy Huang 			/* find the first unplug devices and set it as main display */
2654b0989546SSandy Huang 			int main_vp_index = -1;
2655b0989546SSandy Huang 
2656b0989546SSandy Huang 			for (i = 0; i < vop2->data->nr_vps; i++) {
2657b0989546SSandy Huang 				if (cstate->crtc->vps[i].enable)
2658b0989546SSandy Huang 					active_vp_num++;
2659b0989546SSandy Huang 			}
2660b0989546SSandy Huang 			printf("VOP have %d active VP\n", active_vp_num);
2661b0989546SSandy Huang 
2662b0989546SSandy Huang 			if (soc_is_rk3566() && active_vp_num > 2)
2663b0989546SSandy Huang 				printf("ERROR: rk3566 only support 2 display output!!\n");
2664b0989546SSandy Huang 			plane_mask = vop2->data->plane_mask;
2665b0989546SSandy Huang 			plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
26665fa6e665SDamon Ding 			/*
2667a552a69cSDamon Ding 			 * For rk3528, one display policy for hdmi store in plane_mask[0], and
2668a552a69cSDamon Ding 			 * the other for cvbs store in plane_mask[2].
26695fa6e665SDamon Ding 			 */
26705fa6e665SDamon Ding 			if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 &&
26715fa6e665SDamon Ding 			    cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV)
26725fa6e665SDamon Ding 				plane_mask += 2 * VOP2_VP_MAX;
2673b0989546SSandy Huang 
26745fa6e665SDamon Ding 			if (vop2->version == VOP_VERSION_RK3528) {
26755fa6e665SDamon Ding 				/*
2676a552a69cSDamon Ding 				 * For rk3528, the plane mask of vp is limited, only esmart2 can
2677a552a69cSDamon Ding 				 * be selected by both vp0 and vp1.
26785fa6e665SDamon Ding 				 */
26795fa6e665SDamon Ding 				j = 0;
26805fa6e665SDamon Ding 			} else {
2681b0989546SSandy Huang 				for (i = 0; i < vop2->data->nr_vps; i++) {
2682b0989546SSandy Huang 					if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
2683a552a69cSDamon Ding 						/* the first store main display plane mask */
2684a552a69cSDamon Ding 						vop2->vp_plane_mask[i] = plane_mask[0];
2685b0989546SSandy Huang 						main_vp_index = i;
2686e007876dSSandy Huang 						break;
2687b0989546SSandy Huang 					}
2688b0989546SSandy Huang 				}
2689b0989546SSandy Huang 
2690b0989546SSandy Huang 				/* if no find unplug devices, use vp0 as main display */
2691b0989546SSandy Huang 				if (main_vp_index < 0) {
2692b0989546SSandy Huang 					main_vp_index = 0;
2693b0989546SSandy Huang 					vop2->vp_plane_mask[0] = plane_mask[0];
2694b0989546SSandy Huang 				}
2695b0989546SSandy Huang 
2696a552a69cSDamon Ding 				/* plane_mask[0] store main display, so we from plane_mask[1] */
2697a552a69cSDamon Ding 				j = 1;
26985fa6e665SDamon Ding 			}
2699b0989546SSandy Huang 
2700b0989546SSandy Huang 			/* init other display except main display */
2701b0989546SSandy Huang 			for (i = 0; i < vop2->data->nr_vps; i++) {
2702a552a69cSDamon Ding 				/* main display or no connect devices */
2703a552a69cSDamon Ding 				if (i == main_vp_index || !cstate->crtc->vps[i].enable)
2704b0989546SSandy Huang 					continue;
2705b0989546SSandy Huang 				vop2->vp_plane_mask[i] = plane_mask[j++];
270683d6b087SDamon Ding 				/*
270783d6b087SDamon Ding 				 * For rk3588, the main window should attach to the VP0 while
270883d6b087SDamon Ding 				 * the splice window should attach to the VP1 when the display
270983d6b087SDamon Ding 				 * mode is over 4k.
271083d6b087SDamon Ding 				 * If only one VP is enabled and the plane mask is not assigned
271183d6b087SDamon Ding 				 * in DTS, all main windows will be assigned to the enabled VPx,
271283d6b087SDamon Ding 				 * and all splice windows will be assigned to the VPx+1, in order
271383d6b087SDamon Ding 				 * to ensure that the splice mode work well.
271483d6b087SDamon Ding 				 */
271583d6b087SDamon Ding 				if (vop2->version == VOP_VERSION_RK3588 && active_vp_num == 1)
271683d6b087SDamon Ding 					vop2->vp_plane_mask[(i + 1) % vop2->data->nr_vps] = plane_mask[j++];
2717b0989546SSandy Huang 			}
2718a552a69cSDamon Ding 		}
2719b0989546SSandy Huang 		/* store plane mask for vop2_fixup_dts */
2720b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
2721b0989546SSandy Huang 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2722b0989546SSandy Huang 			for (j = 0; j < layer_nr; j++) {
2723b0989546SSandy Huang 				layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2724b0989546SSandy Huang 				vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
2725b0989546SSandy Huang 			}
2726b0989546SSandy Huang 		}
2727b0989546SSandy Huang 	}
2728b0989546SSandy Huang 
272960e469f5SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588)
273060e469f5SDamon Ding 		rk3588_vop2_regsbak(vop2);
273160e469f5SDamon Ding 	else
273260e469f5SDamon Ding 		memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
273360e469f5SDamon Ding 
273460e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
273560e469f5SDamon Ding 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
273660e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
273760e469f5SDamon Ding 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
273860e469f5SDamon Ding 
2739b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
2740b0989546SSandy Huang 		printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
2741b0989546SSandy Huang 		for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
274227cec8e2SDamon Ding 			printf("%s ",
274327cec8e2SDamon Ding 			       vop2_plane_id_to_string(vop2->vp_plane_mask[i].attached_layers[j]));
274427cec8e2SDamon Ding 		printf("], primary plane: %s\n",
274527cec8e2SDamon Ding 		       vop2_plane_id_to_string(vop2->vp_plane_mask[i].primary_plane_id));
2746b0989546SSandy Huang 	}
2747b0989546SSandy Huang 
2748b7195f56SDamon Ding 	vop2_ops->setup_overlay(state);
2749b0989546SSandy Huang 
27505fa6e665SDamon Ding 	if (is_vop3(vop2)) {
27515fa6e665SDamon Ding 		/*
27525fa6e665SDamon Ding 		 * you can rewrite at dts vop node:
27535fa6e665SDamon Ding 		 *
27545fa6e665SDamon Ding 		 * VOP3_ESMART_8K_MODE = 0,
27555fa6e665SDamon Ding 		 * VOP3_ESMART_4K_4K_MODE = 1,
27565fa6e665SDamon Ding 		 * VOP3_ESMART_4K_2K_2K_MODE = 2,
27575fa6e665SDamon Ding 		 * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
27585fa6e665SDamon Ding 		 *
27595fa6e665SDamon Ding 		 * &vop {
27605fa6e665SDamon Ding 		 * 	esmart_lb_mode = /bits/ 8 <2>;
27615fa6e665SDamon Ding 		 * };
276263cb669fSSandy Huang 		 */
276351e1509eSDamon Ding 		tmp = dev_read_u8_array_ptr(cstate->dev, "esmart_lb_mode", 1);
276451e1509eSDamon Ding 		if (tmp)
276551e1509eSDamon Ding 			vop2->esmart_lb_mode = *tmp;
276651e1509eSDamon Ding 		else
27675fa6e665SDamon Ding 			vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
2768a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
2769a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL,
2770a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_MASK,
2771a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_SHIFT,
2772a552a69cSDamon Ding 					vop3_get_esmart_lb_mode(vop2), true);
2773a552a69cSDamon Ding 		else
2774a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
2775a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_MASK,
2776a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_SHIFT,
2777f6e9a2a3SDamon Ding 					vop3_get_esmart_lb_mode(vop2), false);
2778d0408543SAndy Yan 
27795fa6e665SDamon Ding 		vop3_init_esmart_scale_engine(vop2);
2780aa670293SDamon Ding 
278112ee4de7SDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
278212ee4de7SDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
278312ee4de7SDamon Ding 					RK3576_DSP_VS_T_SEL_SHIFT, 0, true);
278412ee4de7SDamon Ding 		else
2785aa670293SDamon Ding 			vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK,
2786aa670293SDamon Ding 					DSP_VS_T_SEL_SHIFT, 0, false);
2787bb7ec356SDamon Ding 
2788bb7ec356SDamon Ding 		/*
2789bb7ec356SDamon Ding 		 * This is a workaround for RK3528/RK3562/RK3576:
2790bb7ec356SDamon Ding 		 *
2791bb7ec356SDamon Ding 		 * The aclk pre auto gating function may disable the aclk
2792bb7ec356SDamon Ding 		 * in some unexpected cases, which detected by hardware
2793bb7ec356SDamon Ding 		 * automatically.
2794bb7ec356SDamon Ding 		 *
2795bb7ec356SDamon Ding 		 * For example, if the above function is enabled, the post
2796bb7ec356SDamon Ding 		 * scale function will be affected, resulting in abnormal
2797bb7ec356SDamon Ding 		 * display.
2798bb7ec356SDamon Ding 		 */
2799bb7ec356SDamon Ding 		if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 ||
2800bb7ec356SDamon Ding 		    vop2->version == VOP_VERSION_RK3576)
2801bb7ec356SDamon Ding 			vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
2802bb7ec356SDamon Ding 					ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false);
280363cb669fSSandy Huang 	}
280463cb669fSSandy Huang 
2805ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3568)
280663cb669fSSandy Huang 		vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
280763cb669fSSandy Huang 
2808a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576) {
2809a552a69cSDamon Ding 		vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq");
2810a552a69cSDamon Ding 
2811f67105fbSSandy Huang 		/* Default use rkiommu 1.0 for axi0 */
2812f67105fbSSandy Huang 		vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 0, true);
2813a552a69cSDamon Ding 
2814a552a69cSDamon Ding 		/* Init frc2.0 config */
2815a552a69cSDamon Ding 		vop2_writel(vop2, 0xca0, 0xc8);
2816a552a69cSDamon Ding 		vop2_writel(vop2, 0xca4, 0x01000100);
2817a552a69cSDamon Ding 		vop2_writel(vop2, 0xca8, 0x03ff0100);
2818a552a69cSDamon Ding 		vop2_writel(vop2, 0xda0, 0xc8);
2819a552a69cSDamon Ding 		vop2_writel(vop2, 0xda4, 0x01000100);
2820a552a69cSDamon Ding 		vop2_writel(vop2, 0xda8, 0x03ff0100);
2821a552a69cSDamon Ding 
2822a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true)
2823a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
2824a552a69cSDamon Ding 					VP_INTR_MERGE_EN_SHIFT, 1, true);
2825a552a69cSDamon Ding 
2826a552a69cSDamon Ding 		/* Set reg done every field for interlace */
2827a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK,
2828a552a69cSDamon Ding 				INTERLACE_FRM_REG_DONE_SHIFT, 0, false);
2829a552a69cSDamon Ding 	}
2830a552a69cSDamon Ding 
283163cb669fSSandy Huang 	vop2->global_init = true;
2832d0408543SAndy Yan }
2833d0408543SAndy Yan 
2834344e932aSDamon Ding static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state)
2835344e932aSDamon Ding {
2836344e932aSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2837344e932aSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
2838344e932aSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
2839344e932aSDamon Ding 	struct resource sharp_regs;
2840344e932aSDamon Ding 	u32 *sharp_reg_base;
2841344e932aSDamon Ding 	int ret;
2842344e932aSDamon Ding 
2843344e932aSDamon Ding 	if (!(vp_data->feature & VOP_FEATURE_POST_SHARP))
2844344e932aSDamon Ding 		return;
2845344e932aSDamon Ding 
2846344e932aSDamon Ding 	ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs);
2847344e932aSDamon Ding 	if (ret) {
2848344e932aSDamon Ding 		printf("failed to get sharp regs\n");
2849344e932aSDamon Ding 		return;
2850344e932aSDamon Ding 	}
2851344e932aSDamon Ding 	sharp_reg_base = (u32 *)sharp_regs.start;
2852344e932aSDamon Ding 
2853344e932aSDamon Ding 	/*
2854344e932aSDamon Ding 	 * After vop initialization, keep sw_sharp_enable always on.
2855344e932aSDamon Ding 	 * Only enable/disable sharp submodule to avoid black screen.
2856344e932aSDamon Ding 	 */
2857344e932aSDamon Ding 	writel(0x1, sharp_reg_base);
2858344e932aSDamon Ding }
2859344e932aSDamon Ding 
2860c54cc5d2SAlgea Cao static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state)
2861c54cc5d2SAlgea Cao {
2862c54cc5d2SAlgea Cao 	struct crtc_state *cstate = &state->crtc_state;
2863c54cc5d2SAlgea Cao 	const struct vop2_data *vop2_data = vop2->data;
2864c54cc5d2SAlgea Cao 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
2865c54cc5d2SAlgea Cao 	struct resource acm_regs;
2866c54cc5d2SAlgea Cao 	u32 *acm_reg_base;
2867c54cc5d2SAlgea Cao 	u32 vp_offset = (cstate->crtc_id * 0x100);
2868c54cc5d2SAlgea Cao 	int ret;
2869c54cc5d2SAlgea Cao 
2870c54cc5d2SAlgea Cao 	if (!(vp_data->feature & VOP_FEATURE_POST_ACM))
2871c54cc5d2SAlgea Cao 		return;
2872c54cc5d2SAlgea Cao 
2873c54cc5d2SAlgea Cao 	ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs);
2874c54cc5d2SAlgea Cao 	if (ret) {
2875c54cc5d2SAlgea Cao 		printf("failed to get acm regs\n");
2876c54cc5d2SAlgea Cao 		return;
2877c54cc5d2SAlgea Cao 	}
2878c54cc5d2SAlgea Cao 	acm_reg_base = (u32 *)acm_regs.start;
2879c54cc5d2SAlgea Cao 
2880c54cc5d2SAlgea Cao 	/*
2881c54cc5d2SAlgea Cao 	 * Black screen is displayed when acm bypass switched
2882c54cc5d2SAlgea Cao 	 * between enable and disable. Therefore, disable acm
2883c54cc5d2SAlgea Cao 	 * bypass by default after system boot.
2884c54cc5d2SAlgea Cao 	 */
2885c54cc5d2SAlgea Cao 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2886c54cc5d2SAlgea Cao 			POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2887c54cc5d2SAlgea Cao 
2888e1946cbdSAlgea Cao 	writel(0, acm_reg_base + 0);
2889c54cc5d2SAlgea Cao }
2890c54cc5d2SAlgea Cao 
28910669ab1fSDamon Ding static int rockchip_vop2_of_get_gamma_lut(struct display_state *state,
28920669ab1fSDamon Ding 					  struct device_node *dsp_lut_node)
28930669ab1fSDamon Ding {
28940669ab1fSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
28950669ab1fSDamon Ding 	struct resource gamma_res;
28960669ab1fSDamon Ding 	fdt_size_t lut_size;
28970669ab1fSDamon Ding 	u32 *lut_regs;
28980669ab1fSDamon Ding 	u32 *lut;
28990669ab1fSDamon Ding 	u32 r, g, b;
29000669ab1fSDamon Ding 	int lut_len;
29010669ab1fSDamon Ding 	int length;
29020669ab1fSDamon Ding 	int i, j;
29030669ab1fSDamon Ding 	int ret = 0;
29040669ab1fSDamon Ding 
29050669ab1fSDamon Ding 	of_get_property(dsp_lut_node, "gamma-lut", &length);
29060669ab1fSDamon Ding 	if (!length)
29070669ab1fSDamon Ding 		return -EINVAL;
29080669ab1fSDamon Ding 
29090669ab1fSDamon Ding 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
29100669ab1fSDamon Ding 	if (ret)
29110669ab1fSDamon Ding 		printf("failed to get gamma lut res\n");
29120669ab1fSDamon Ding 	lut_regs = (u32 *)gamma_res.start;
29130669ab1fSDamon Ding 	lut_size = gamma_res.end - gamma_res.start + 1;
29140669ab1fSDamon Ding 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
29150669ab1fSDamon Ding 		printf("failed to get gamma lut register\n");
29160669ab1fSDamon Ding 		return -EINVAL;
29170669ab1fSDamon Ding 	}
29180669ab1fSDamon Ding 	lut_len = lut_size / 4;
29190669ab1fSDamon Ding 
29200669ab1fSDamon Ding 	cstate->lut_val = (u32 *)calloc(1, lut_size);
29210669ab1fSDamon Ding 	if (!cstate->lut_val)
29220669ab1fSDamon Ding 		return -ENOMEM;
29230669ab1fSDamon Ding 
29240669ab1fSDamon Ding 	length >>= 2;
29250669ab1fSDamon Ding 	if (length != lut_len) {
29260669ab1fSDamon Ding 		lut = (u32 *)calloc(1, lut_len);
29270669ab1fSDamon Ding 		if (!lut) {
29280669ab1fSDamon Ding 			free(cstate->lut_val);
29290669ab1fSDamon Ding 			return -ENOMEM;
29300669ab1fSDamon Ding 		}
29310669ab1fSDamon Ding 
29320669ab1fSDamon Ding 		ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length);
29330669ab1fSDamon Ding 		if (ret) {
29340669ab1fSDamon Ding 			printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id);
29350669ab1fSDamon Ding 			free(cstate->lut_val);
29360669ab1fSDamon Ding 			free(lut);
29370669ab1fSDamon Ding 			return -EINVAL;
29380669ab1fSDamon Ding 		}
29390669ab1fSDamon Ding 
29400669ab1fSDamon Ding 		/*
29410669ab1fSDamon Ding 		 * In order to achieve the same gamma correction effect in different
29420669ab1fSDamon Ding 		 * platforms, the following conversion helps to translate from 8bit
29430669ab1fSDamon Ding 		 * gamma table with 256 parameters to 10bit gamma with 1024 parameters.
29440669ab1fSDamon Ding 		 */
29450669ab1fSDamon Ding 		for (i = 0; i < lut_len; i++) {
29460669ab1fSDamon Ding 			j = i * length / lut_len;
29470669ab1fSDamon Ding 			r = lut[j] / length / length * lut_len / length;
29480669ab1fSDamon Ding 			g = lut[j] / length % length * lut_len / length;
29490669ab1fSDamon Ding 			b = lut[j] % length * lut_len / length;
29500669ab1fSDamon Ding 
29510669ab1fSDamon Ding 			cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b;
29520669ab1fSDamon Ding 		}
29530669ab1fSDamon Ding 		free(lut);
29540669ab1fSDamon Ding 	} else {
29550669ab1fSDamon Ding 		of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len);
29560669ab1fSDamon Ding 	}
29570669ab1fSDamon Ding 
29580669ab1fSDamon Ding 	return 0;
29590669ab1fSDamon Ding }
29600669ab1fSDamon Ding 
29610669ab1fSDamon Ding static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state)
29620669ab1fSDamon Ding {
29630669ab1fSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
29640669ab1fSDamon Ding 	struct device_node *dsp_lut_node;
29650669ab1fSDamon Ding 	int phandle;
29660669ab1fSDamon Ding 	int ret = 0;
29670669ab1fSDamon Ding 
29680669ab1fSDamon Ding 	phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1);
29690669ab1fSDamon Ding 	if (phandle < 0)
29700669ab1fSDamon Ding 		return;
29710669ab1fSDamon Ding 
29720669ab1fSDamon Ding 	dsp_lut_node = of_find_node_by_phandle(phandle);
29730669ab1fSDamon Ding 	if (!dsp_lut_node)
29740669ab1fSDamon Ding 		return;
29750669ab1fSDamon Ding 
29760669ab1fSDamon Ding 	ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node);
29770669ab1fSDamon Ding 	if (ret)
29780669ab1fSDamon Ding 		printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id);
29790669ab1fSDamon Ding }
29800669ab1fSDamon Ding 
2981d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state)
2982d0408543SAndy Yan {
29830669ab1fSDamon Ding 	rockchip_vop2_of_get_dsp_lut(vop2, state);
29840669ab1fSDamon Ding 
29851147facaSSandy Huang 	rockchip_vop2_gamma_lut_init(vop2, state);
29866414e3bcSSandy Huang 	rockchip_vop2_cubic_lut_init(vop2, state);
2987344e932aSDamon Ding 	rockchip_vop2_sharp_init(vop2, state);
2988c54cc5d2SAlgea Cao 	rockchip_vop2_acm_init(vop2, state);
2989d0408543SAndy Yan 
2990d0408543SAndy Yan 	return 0;
2991d0408543SAndy Yan }
2992d0408543SAndy Yan 
2993d0408543SAndy Yan /*
2994d0408543SAndy Yan  * VOP2 have multi video ports.
2995d0408543SAndy Yan  * video port ------- crtc
2996d0408543SAndy Yan  */
2997d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state)
2998d0408543SAndy Yan {
2999d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3000d0408543SAndy Yan 	const struct vop2_data *vop2_data = cstate->crtc->data;
3001734a0ce6SDamon Ding 	struct regmap *map;
30020686a6a6SZhang Yubing 	char dclk_name[16];
30030686a6a6SZhang Yubing 	int ret;
3004d0408543SAndy Yan 
3005d0408543SAndy Yan 	if (!rockchip_vop2) {
30060d2d6a97SSandy Huang 		rockchip_vop2 = calloc(1, sizeof(struct vop2));
3007d0408543SAndy Yan 		if (!rockchip_vop2)
3008d0408543SAndy Yan 			return -ENOMEM;
3009d8e7f4a5SSandy Huang 		memset(rockchip_vop2, 0, sizeof(struct vop2));
3010d0408543SAndy Yan 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
3011d0408543SAndy Yan 		rockchip_vop2->reg_len = RK3568_MAX_REG;
3012d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD
3013d8e7f4a5SSandy Huang 		rockchip_vop2->regs = (void *)RK3528_VOP_BASE;
3014d8e7f4a5SSandy Huang #else
3015d8e7f4a5SSandy Huang 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
3016734a0ce6SDamon Ding 		map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf");
3017734a0ce6SDamon Ding 		rockchip_vop2->grf = regmap_get_range(map, 0);
3018d0408543SAndy Yan 		if (rockchip_vop2->grf <= 0)
301963cb669fSSandy Huang 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
3020d8e7f4a5SSandy Huang #endif
3021d0408543SAndy Yan 		rockchip_vop2->version = vop2_data->version;
3022d0408543SAndy Yan 		rockchip_vop2->data = vop2_data;
3023ecc31b6eSAndy Yan 		if (rockchip_vop2->version == VOP_VERSION_RK3588) {
3024734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf");
3025734a0ce6SDamon Ding 			rockchip_vop2->vop_grf = regmap_get_range(map, 0);
3026ecc31b6eSAndy Yan 			if (rockchip_vop2->vop_grf <= 0)
3027a552a69cSDamon Ding 				printf("%s: Get syscon vop_grf failed (ret=%p)\n",
3028a552a69cSDamon Ding 				       __func__, rockchip_vop2->vop_grf);
3029b890760eSAlgea Cao 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf");
3030b890760eSAlgea Cao 			rockchip_vop2->vo1_grf = regmap_get_range(map, 0);
3031ecc31b6eSAndy Yan 			if (rockchip_vop2->vo1_grf <= 0)
3032a552a69cSDamon Ding 				printf("%s: Get syscon vo1_grf failed (ret=%p)\n",
3033a552a69cSDamon Ding 				       __func__, rockchip_vop2->vo1_grf);
3034734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3035734a0ce6SDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3036b890760eSAlgea Cao 			if (rockchip_vop2->sys_pmu <= 0)
3037a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3038a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
3039a552a69cSDamon Ding 		} else if (rockchip_vop2->version == VOP_VERSION_RK3576) {
3040a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf");
3041a552a69cSDamon Ding 			rockchip_vop2->ioc_grf = regmap_get_range(map, 0);
3042a552a69cSDamon Ding 			if (rockchip_vop2->ioc_grf <= 0)
3043a552a69cSDamon Ding 				printf("%s: Get syscon ioc_grf failed (ret=%p)\n",
3044a552a69cSDamon Ding 				       __func__, rockchip_vop2->ioc_grf);
3045a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3046a552a69cSDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3047a552a69cSDamon Ding 			if (rockchip_vop2->sys_pmu <= 0)
3048a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3049a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
3050ecc31b6eSAndy Yan 		}
3051d0408543SAndy Yan 	}
3052d0408543SAndy Yan 
30530686a6a6SZhang Yubing 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
3054a2ce7568SDamon Ding 	if (dev_read_stringlist_search(cstate->dev, "reset-names", dclk_name) > 0) {
30550686a6a6SZhang Yubing 		ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst);
30560686a6a6SZhang Yubing 		if (ret < 0) {
30570686a6a6SZhang Yubing 			printf("%s: failed to get dclk reset: %d\n", __func__, ret);
30580686a6a6SZhang Yubing 			cstate->dclk_rst.dev = NULL;
30590686a6a6SZhang Yubing 		}
3060a2ce7568SDamon Ding 	}
30610686a6a6SZhang Yubing 
3062d0408543SAndy Yan 	cstate->private = rockchip_vop2;
306363cb669fSSandy Huang 	cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
306463cb669fSSandy Huang 	cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
3065d0408543SAndy Yan 
306689912f2dSSandy Huang 	vop2_global_initial(rockchip_vop2, state);
306789912f2dSSandy Huang 
3068d0408543SAndy Yan 	return 0;
3069d0408543SAndy Yan }
3070d0408543SAndy Yan 
3071ecc31b6eSAndy Yan /*
3072ecc31b6eSAndy Yan  * calc the dclk on rk3588
3073ecc31b6eSAndy Yan  * the available div of dclk is 1, 2, 4
3074ecc31b6eSAndy Yan  *
3075ecc31b6eSAndy Yan  */
3076ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
3077ecc31b6eSAndy Yan {
3078ecc31b6eSAndy Yan 	if (child_clk * 4 <= max_dclk)
3079ecc31b6eSAndy Yan 		return child_clk * 4;
3080ecc31b6eSAndy Yan 	else if (child_clk * 2 <= max_dclk)
3081ecc31b6eSAndy Yan 		return child_clk * 2;
3082ecc31b6eSAndy Yan 	else if (child_clk <= max_dclk)
3083ecc31b6eSAndy Yan 		return child_clk;
3084ecc31b6eSAndy Yan 	else
3085ecc31b6eSAndy Yan 		return 0;
3086ecc31b6eSAndy Yan }
3087ecc31b6eSAndy Yan 
3088ecc31b6eSAndy Yan /*
3089ecc31b6eSAndy Yan  * 4 pixclk/cycle on rk3588
3090ecc31b6eSAndy Yan  * RGB/eDP/HDMI: if_pixclk >= dclk_core
3091ecc31b6eSAndy Yan  * DP: dp_pixclk = dclk_out <= dclk_core
3092ecc31b6eSAndy Yan  * DSI: mipi_pixclk <= dclk_out <= dclk_core
3093ecc31b6eSAndy Yan  */
3094ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state,
3095ecc31b6eSAndy Yan 				       int *dclk_core_div, int *dclk_out_div,
3096ecc31b6eSAndy Yan 				       int *if_pixclk_div, int *if_dclk_div)
3097d0408543SAndy Yan {
3098d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3099d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3100d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
3101d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
31020a1fb152SZhang Yubing 	unsigned long v_pixclk = mode->crtc_clock;
3103ecc31b6eSAndy Yan 	unsigned long dclk_core_rate = v_pixclk >> 2;
3104ecc31b6eSAndy Yan 	unsigned long dclk_rate = v_pixclk;
3105ecc31b6eSAndy Yan 	unsigned long dclk_out_rate;
3106ecc31b6eSAndy Yan 	u64 if_dclk_rate;
3107ecc31b6eSAndy Yan 	u64 if_pixclk_rate;
3108ecc31b6eSAndy Yan 	int output_type = conn_state->type;
3109ecc31b6eSAndy Yan 	int output_mode = conn_state->output_mode;
3110ecc31b6eSAndy Yan 	int K = 1;
3111ecc31b6eSAndy Yan 
31120a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE &&
31130a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
31140a1fb152SZhang Yubing 		printf("Dual channel and YUV420 can't work together\n");
31150a1fb152SZhang Yubing 		return -EINVAL;
31160a1fb152SZhang Yubing 	}
31170a1fb152SZhang Yubing 
31180a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
31190a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420)
31200a1fb152SZhang Yubing 		K = 2;
31210a1fb152SZhang Yubing 
3122ecc31b6eSAndy Yan 	if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
3123ecc31b6eSAndy Yan 		/*
3124ecc31b6eSAndy Yan 		 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
3125ecc31b6eSAndy Yan 		 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
3126ecc31b6eSAndy Yan 		 */
31270a1fb152SZhang Yubing 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
31280a1fb152SZhang Yubing 		    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3129b890760eSAlgea Cao 			dclk_rate = dclk_rate >> 1;
3130ecc31b6eSAndy Yan 			K = 2;
3131b890760eSAlgea Cao 		}
313212ee5af0SDamon Ding 		if (cstate->dsc_enable) {
313312ee5af0SDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate << 1;
313412ee5af0SDamon Ding 			if_dclk_rate = cstate->dsc_cds_clk_rate;
3135ecc31b6eSAndy Yan 		} else {
3136ecc31b6eSAndy Yan 			if_pixclk_rate = (dclk_core_rate << 1) / K;
3137ecc31b6eSAndy Yan 			if_dclk_rate = dclk_core_rate / K;
3138ecc31b6eSAndy Yan 		}
3139ecc31b6eSAndy Yan 
3140631ee99aSZhang Yubing 		if (v_pixclk > VOP2_MAX_DCLK_RATE)
31414b726cc6SDamon Ding 			dclk_rate = vop2_calc_dclk(dclk_core_rate,
31424b726cc6SDamon Ding 						   vop2->data->vp_data[cstate->crtc_id].max_dclk);
3143631ee99aSZhang Yubing 
3144ecc31b6eSAndy Yan 		if (!dclk_rate) {
3145ecc31b6eSAndy Yan 			printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n",
31464b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate);
3147ecc31b6eSAndy Yan 			return -EINVAL;
3148ecc31b6eSAndy Yan 		}
3149ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3150ecc31b6eSAndy Yan 		*if_dclk_div = dclk_rate / if_dclk_rate;
3151b890760eSAlgea Cao 		*dclk_core_div = dclk_rate / dclk_core_rate;
3152b890760eSAlgea Cao 		printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n",
3153b890760eSAlgea Cao 		       dclk_rate, *if_pixclk_div, *if_dclk_div);
3154ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_eDP) {
3155ecc31b6eSAndy Yan 		/* edp_pixclk = edp_dclk > dclk_core */
3156ecc31b6eSAndy Yan 		if_pixclk_rate = v_pixclk / K;
3157ecc31b6eSAndy Yan 		if_dclk_rate = v_pixclk / K;
3158ecc31b6eSAndy Yan 		dclk_rate = if_pixclk_rate * K;
3159ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3160ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3161ecc31b6eSAndy Yan 		*if_dclk_div = *if_pixclk_div;
3162ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
3163ecc31b6eSAndy Yan 		dclk_out_rate = v_pixclk >> 2;
31640a1fb152SZhang Yubing 		dclk_out_rate = dclk_out_rate / K;
3165ecc31b6eSAndy Yan 
31664b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
31674b726cc6SDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
3168ecc31b6eSAndy Yan 		if (!dclk_rate) {
3169ecc31b6eSAndy Yan 			printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n",
31704b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate);
3171ecc31b6eSAndy Yan 			return -EINVAL;
3172ecc31b6eSAndy Yan 		}
3173ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3174ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3175ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DSI) {
3176ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3177ecc31b6eSAndy Yan 			K = 2;
317812ee5af0SDamon Ding 		if (cstate->dsc_enable)
317912ee5af0SDamon Ding 			/* dsc output is 96bit, dsi input is 192 bit */
318012ee5af0SDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1;
3181ecc31b6eSAndy Yan 		else
3182ecc31b6eSAndy Yan 			if_pixclk_rate = dclk_core_rate / K;
3183ecc31b6eSAndy Yan 		/* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
318412ee5af0SDamon Ding 		dclk_out_rate = dclk_core_rate / K;
3185ecc31b6eSAndy Yan 		/* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
31864b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
31874b726cc6SDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
31889f076eccSZhang Yubing 		if (!dclk_rate) {
31899f076eccSZhang Yubing 			printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n",
31904b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate);
31919f076eccSZhang Yubing 			return -EINVAL;
31929f076eccSZhang Yubing 		}
319312ee5af0SDamon Ding 
319412ee5af0SDamon Ding 		if (cstate->dsc_enable)
3195d57af898SDamon Ding 			dclk_rate /= cstate->dsc_slice_num;
319612ee5af0SDamon Ding 
3197ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3198ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3199ecc31b6eSAndy Yan 		*if_pixclk_div = 1;       /*mipi pixclk == dclk_out*/
320012ee5af0SDamon Ding 		if (cstate->dsc_enable)
32011ace1b6dSDamon Ding 			*if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate;
3202ecc31b6eSAndy Yan 
3203ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DPI) {
3204ecc31b6eSAndy Yan 		dclk_rate = v_pixclk;
3205ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3206ecc31b6eSAndy Yan 	}
3207ecc31b6eSAndy Yan 
3208ecc31b6eSAndy Yan 	*if_pixclk_div = ilog2(*if_pixclk_div);
3209ecc31b6eSAndy Yan 	*if_dclk_div = ilog2(*if_dclk_div);
3210ecc31b6eSAndy Yan 	*dclk_core_div = ilog2(*dclk_core_div);
3211ecc31b6eSAndy Yan 	*dclk_out_div = ilog2(*dclk_out_div);
3212ecc31b6eSAndy Yan 
3213ecc31b6eSAndy Yan 	return dclk_rate;
3214ecc31b6eSAndy Yan }
3215ecc31b6eSAndy Yan 
321612ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state)
3217ecc31b6eSAndy Yan {
321812ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3219ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
322012ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
32211ace1b6dSDamon Ding 	u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */
3222ecc31b6eSAndy Yan 	u8 k = 1;
3223ecc31b6eSAndy Yan 
3224ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3225ecc31b6eSAndy Yan 		k = 2;
3226ecc31b6eSAndy Yan 
322712ee5af0SDamon Ding 	cstate->dsc_txp_clk_rate = v_pixclk;
322812ee5af0SDamon Ding 	do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k));
3229ecc31b6eSAndy Yan 
323012ee5af0SDamon Ding 	cstate->dsc_pxl_clk_rate = v_pixclk;
323112ee5af0SDamon Ding 	do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k));
3232ecc31b6eSAndy Yan 
3233ecc31b6eSAndy Yan 	/* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
3234ecc31b6eSAndy Yan 	 * cds_dat_width = 96;
3235ecc31b6eSAndy Yan 	 * bits_per_pixel = [8-12];
3236b61227a3SDamon Ding 	 * As cds clk is div from txp clk and only support 1/2/4 div,
3237b61227a3SDamon Ding 	 * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
3238b61227a3SDamon Ding 	 * otherwise dsc_cds = crtc_clock / 8;
3239ecc31b6eSAndy Yan 	 */
3240b61227a3SDamon Ding 	cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
3241ecc31b6eSAndy Yan 
3242ecc31b6eSAndy Yan 	return 0;
3243ecc31b6eSAndy Yan }
3244ecc31b6eSAndy Yan 
3245ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
3246ecc31b6eSAndy Yan {
3247ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3248ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3249ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
325012ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
3251ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
325252ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
3253ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
3254ecc31b6eSAndy Yan 	int output_if = conn_state->output_if;
3255ecc31b6eSAndy Yan 	int if_pixclk_div = 0;
3256ecc31b6eSAndy Yan 	int if_dclk_div = 0;
3257ecc31b6eSAndy Yan 	unsigned long dclk_rate;
32585d2768f7SDamon Ding 	bool dclk_inv, yc_swap = false;
3259d0408543SAndy Yan 	u32 val;
3260ecc31b6eSAndy Yan 
32615d2768f7SDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3262b890760eSAlgea Cao 	if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
3263b890760eSAlgea Cao 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
3264b890760eSAlgea Cao 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
3265b890760eSAlgea Cao 	} else {
3266ecc31b6eSAndy Yan 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3267ecc31b6eSAndy Yan 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3268b890760eSAlgea Cao 	}
3269ecc31b6eSAndy Yan 
327012ee5af0SDamon Ding 	if (cstate->dsc_enable) {
327112ee5af0SDamon Ding 		int k = 1;
327212ee5af0SDamon Ding 
3273ecc31b6eSAndy Yan 		if (!vop2->data->nr_dscs) {
327412ee5af0SDamon Ding 			printf("Unsupported DSC\n");
3275ecc31b6eSAndy Yan 			return 0;
3276ecc31b6eSAndy Yan 		}
327712ee5af0SDamon Ding 
327812ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
327912ee5af0SDamon Ding 			k = 2;
328012ee5af0SDamon Ding 
328112ee5af0SDamon Ding 		cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
328212ee5af0SDamon Ding 		cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
328312ee5af0SDamon Ding 		cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num;
328412ee5af0SDamon Ding 
328512ee5af0SDamon Ding 		vop2_calc_dsc_clk(state);
328612ee5af0SDamon Ding 		printf("Enable DSC%d slice:%dx%d, slice num:%d\n",
328712ee5af0SDamon Ding 		       cstate->dsc_id, dsc_sink_cap->slice_width,
328812ee5af0SDamon Ding 		       dsc_sink_cap->slice_height, cstate->dsc_slice_num);
3289ecc31b6eSAndy Yan 	}
3290ecc31b6eSAndy Yan 
3291b61227a3SDamon Ding 	dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div);
3292ecc31b6eSAndy Yan 
3293ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_RGB) {
3294ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3295ecc31b6eSAndy Yan 				4, false);
32965d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
32975d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3298ecc31b6eSAndy Yan 	}
3299ecc31b6eSAndy Yan 
3300ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3301ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3302ecc31b6eSAndy Yan 				3, false);
33035d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
33045d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
33055d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
33065d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT,
33075d2768f7SDamon Ding 				yc_swap, false);
3308ecc31b6eSAndy Yan 	}
3309ecc31b6eSAndy Yan 
3310ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT656) {
3311ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3312ecc31b6eSAndy Yan 				2, false);
33135d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
33145d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
33155d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
33165d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT,
33175d2768f7SDamon Ding 				yc_swap, false);
3318ecc31b6eSAndy Yan 	}
3319ecc31b6eSAndy Yan 
3320ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3321ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3322ecc31b6eSAndy Yan 			val = 0;
3323ecc31b6eSAndy Yan 		else
3324ecc31b6eSAndy Yan 			val = 1;
332541874944SGuochun Huang 
33263df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
332741874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
332841874944SGuochun Huang 					RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
332941874944SGuochun Huang 
3330ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
3331ecc31b6eSAndy Yan 				1, false);
3332ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
3333ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
3334ecc31b6eSAndy Yan 				if_pixclk_div, false);
333541874944SGuochun Huang 
333641874944SGuochun Huang 		if (conn_state->hold_mode) {
333741874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
33388e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
333941874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
334041874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
334141874944SGuochun Huang 		}
3342ecc31b6eSAndy Yan 	}
3343ecc31b6eSAndy Yan 
3344ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI1) {
3345ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3346ecc31b6eSAndy Yan 			val = 0;
3347ecc31b6eSAndy Yan 		else if (cstate->crtc_id == 3)
3348ecc31b6eSAndy Yan 			val = 1;
3349ecc31b6eSAndy Yan 		else
3350ecc31b6eSAndy Yan 			val = 3; /*VP1*/
33513df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
335241874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
335341874944SGuochun Huang 					RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
335441874944SGuochun Huang 
3355ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
3356ecc31b6eSAndy Yan 				1, false);
3357ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
3358ecc31b6eSAndy Yan 				val, false);
3359ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
3360ecc31b6eSAndy Yan 				if_pixclk_div, false);
336141874944SGuochun Huang 
336241874944SGuochun Huang 		if (conn_state->hold_mode) {
336341874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
33648e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
336541874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
336641874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
336741874944SGuochun Huang 		}
3368ecc31b6eSAndy Yan 	}
3369ecc31b6eSAndy Yan 
3370ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
33713df6e59eSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
33723df6e59eSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
3373ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3374ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3375ecc31b6eSAndy Yan 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
3376ecc31b6eSAndy Yan 					false);
33770a1fb152SZhang Yubing 		switch (conn_state->type) {
33780a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DisplayPort:
33790a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
33800a1fb152SZhang Yubing 					RK3588_DP_DUAL_EN_SHIFT, 1, false);
33810a1fb152SZhang Yubing 			break;
33820a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_eDP:
33830a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
33840a1fb152SZhang Yubing 					RK3588_EDP_DUAL_EN_SHIFT, 1, false);
33850a1fb152SZhang Yubing 			break;
33860a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_HDMIA:
33870a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
33880a1fb152SZhang Yubing 					RK3588_HDMI_DUAL_EN_SHIFT, 1, false);
33890a1fb152SZhang Yubing 			break;
33900a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DSI:
33910a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
33920a1fb152SZhang Yubing 					RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
33930a1fb152SZhang Yubing 			break;
33940a1fb152SZhang Yubing 		default:
33950a1fb152SZhang Yubing 			break;
33960a1fb152SZhang Yubing 		}
3397ecc31b6eSAndy Yan 	}
3398ecc31b6eSAndy Yan 
3399ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP0) {
3400ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
3401ecc31b6eSAndy Yan 				1, false);
3402ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3403ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3404ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3405ecc31b6eSAndy Yan 				if_dclk_div, false);
3406ecc31b6eSAndy Yan 
3407ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3408ecc31b6eSAndy Yan 				if_pixclk_div, false);
3409ecc31b6eSAndy Yan 
3410ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3411ecc31b6eSAndy Yan 				RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
3412ecc31b6eSAndy Yan 	}
3413ecc31b6eSAndy Yan 
3414ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP1) {
3415ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
3416ecc31b6eSAndy Yan 				1, false);
3417ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3418ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3419ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3420ecc31b6eSAndy Yan 				if_dclk_div, false);
3421ecc31b6eSAndy Yan 
3422ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3423ecc31b6eSAndy Yan 				if_pixclk_div, false);
34241848455fSDamon Ding 
34251848455fSDamon Ding 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
34261848455fSDamon Ding 				RK3588_GRF_EDP1_ENABLE_SHIFT, 1);
3427ecc31b6eSAndy Yan 	}
3428ecc31b6eSAndy Yan 
3429ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
3430ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
3431ecc31b6eSAndy Yan 				1, false);
3432ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3433ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3434ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3435ecc31b6eSAndy Yan 				if_dclk_div, false);
3436ecc31b6eSAndy Yan 
3437ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3438ecc31b6eSAndy Yan 				if_pixclk_div, false);
3439b890760eSAlgea Cao 
3440b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3441b890760eSAlgea Cao 				RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1);
3442b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3443b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3444b890760eSAlgea Cao 				HDMI0_SYNC_POL_SHIFT, val);
3445ecc31b6eSAndy Yan 	}
3446ecc31b6eSAndy Yan 
3447ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI1) {
3448ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
3449ecc31b6eSAndy Yan 				1, false);
3450ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3451ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3452ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3453ecc31b6eSAndy Yan 				if_dclk_div, false);
3454ecc31b6eSAndy Yan 
3455ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3456ecc31b6eSAndy Yan 				if_pixclk_div, false);
3457b890760eSAlgea Cao 
3458b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3459b890760eSAlgea Cao 				RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1);
3460b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3461b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3462b890760eSAlgea Cao 				HDMI1_SYNC_POL_SHIFT, val);
3463ecc31b6eSAndy Yan 	}
3464ecc31b6eSAndy Yan 
3465ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP0) {
3466ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
3467ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3468ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3469ecc31b6eSAndy Yan 				RK3588_DP0_PIN_POL_SHIFT, val, false);
3470ecc31b6eSAndy Yan 	}
3471ecc31b6eSAndy Yan 
3472ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP1) {
3473ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
3474ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3475ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3476ecc31b6eSAndy Yan 				RK3588_DP1_PIN_POL_SHIFT, val, false);
3477ecc31b6eSAndy Yan 	}
3478ecc31b6eSAndy Yan 
3479ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3480b61227a3SDamon Ding 			DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false);
3481ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3482b61227a3SDamon Ding 			DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false);
3483ecc31b6eSAndy Yan 
3484ecc31b6eSAndy Yan 	return dclk_rate;
3485ecc31b6eSAndy Yan }
3486ecc31b6eSAndy Yan 
3487a552a69cSDamon Ding static unsigned long rk3576_vop2_if_cfg(struct display_state *state)
3488a552a69cSDamon Ding {
3489a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3490a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3491a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3492a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
3493a552a69cSDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
3494a552a69cSDamon Ding 	u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate;
3495a552a69cSDamon Ding 	int output_if = conn_state->output_if;
3496a552a69cSDamon Ding 	bool dclk_inv, yc_swap = false;
3497a552a69cSDamon Ding 	bool split_mode = !!(conn_state->output_flags &
3498a552a69cSDamon Ding 			     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE);
3499a552a69cSDamon Ding 	bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false;
3500a552a69cSDamon Ding 	bool interface_dclk_sel, interface_pix_clk_sel = false;
3501a552a69cSDamon Ding 	bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK ||
3502a552a69cSDamon Ding 			    conn_state->output_if & VOP_OUTPUT_IF_BT656;
3503cce1f2abSDamon Ding 	unsigned long dclk_in_rate, dclk_core_rate;
3504a552a69cSDamon Ding 	u32 val;
3505a552a69cSDamon Ding 
3506a552a69cSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3507a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3508a552a69cSDamon Ding 		/*
3509a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3510a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
3511a552a69cSDamon Ding 		 */
3512a552a69cSDamon Ding 		val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3513a552a69cSDamon Ding 	} else {
3514a552a69cSDamon Ding 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3515a552a69cSDamon Ding 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3516a552a69cSDamon Ding 	}
3517a552a69cSDamon Ding 
3518cce1f2abSDamon Ding 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 ||
3519cce1f2abSDamon Ding 	    mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode))
3520a552a69cSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */
3521a552a69cSDamon Ding 	else
3522cce1f2abSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */
3523cce1f2abSDamon Ding 	dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div;
3524cce1f2abSDamon Ding 
3525cce1f2abSDamon Ding 	if (double_pixel)
3526cce1f2abSDamon Ding 		dclk_core_rate = mode->crtc_clock / 2;
3527cce1f2abSDamon Ding 	else
3528cce1f2abSDamon Ding 		dclk_core_rate = mode->crtc_clock / port_pix_rate;
3529cce1f2abSDamon Ding 	post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */
3530a552a69cSDamon Ding 
3531a552a69cSDamon Ding 	if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3532a552a69cSDamon Ding 		pix_half_rate = true;
3533a552a69cSDamon Ding 		post_dclk_out_sel = true;
3534a552a69cSDamon Ding 	}
3535a552a69cSDamon Ding 
3536a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3537a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3538a552a69cSDamon Ding 		/*
3539a552a69cSDamon Ding 		 * RGB interface_pix_clk_sel will auto config according
3540a552a69cSDamon Ding 		 * to rgb_en/bt1120_en/bt656_en.
3541a552a69cSDamon Ding 		 */
3542a552a69cSDamon Ding 	} else if (output_if & VOP_OUTPUT_IF_eDP0) {
3543a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3544a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0;
3545a552a69cSDamon Ding 	} else {
3546a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3547a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0;
3548a552a69cSDamon Ding 	}
3549a552a69cSDamon Ding 
3550a552a69cSDamon Ding 	/* dclk_core */
3551a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3552a552a69cSDamon Ding 			RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false);
3553a552a69cSDamon Ding 	/* dclk_out */
3554a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3555a552a69cSDamon Ding 			RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false);
3556a552a69cSDamon Ding 
3557a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3558a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3559a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3560a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3561a552a69cSDamon Ding 
3562a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3563a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3564a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3565a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3566a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3567a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3568a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3569a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3570a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3571a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3572a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3573a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv);
3574a552a69cSDamon Ding 	}
3575a552a69cSDamon Ding 
3576a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3577a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3578a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3579a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3580a552a69cSDamon Ding 
3581a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3582a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3583a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3584a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3585a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3586a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3587a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3588a552a69cSDamon Ding 				RK3576_BT1120_OUT_EN_SHIFT, 1, false);
3589a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3590a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3591a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3592a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3593a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
3594a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3595a552a69cSDamon Ding 				RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false);
3596a552a69cSDamon Ding 	}
3597a552a69cSDamon Ding 
3598a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT656) {
3599a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3600a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3601a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3602a552a69cSDamon Ding 
3603a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3604a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3605a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3606a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3607a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3608a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3609a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3610a552a69cSDamon Ding 				RK3576_BT656_OUT_EN_SHIFT, 1, false);
3611a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3612a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3613a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3614a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3615a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
3616a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3617a552a69cSDamon Ding 				RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false);
3618a552a69cSDamon Ding 	}
3619a552a69cSDamon Ding 
3620a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3621a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3622a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3623a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
3624a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3625a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3626a552a69cSDamon Ding 
3627a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3628a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3629a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3630a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3631a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3632a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3633a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3634a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3635a552a69cSDamon Ding 		/*
3636a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3637a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
3638a552a69cSDamon Ding 		 */
3639a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
3640a552a69cSDamon Ding 			val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3641a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3642a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3643a552a69cSDamon Ding 
3644a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
3645a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3646a552a69cSDamon Ding 					RK3576_MIPI_CMD_MODE_SHIFT, 1, false);
3647a552a69cSDamon Ding 
3648a552a69cSDamon Ding 		if (conn_state->hold_mode) {
3649a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3650a552a69cSDamon Ding 					EDPI_TE_EN, !cstate->soft_te, false);
3651a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3652a552a69cSDamon Ding 					EDPI_WMS_HOLD_EN, 1, false);
3653a552a69cSDamon Ding 		}
3654a552a69cSDamon Ding 	}
3655a552a69cSDamon Ding 
3656a552a69cSDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
3657a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3658a552a69cSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
3659a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3660a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3661a552a69cSDamon Ding 					MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
3662a552a69cSDamon Ding 		switch (conn_state->type) {
3663a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DisplayPort:
3664a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3665a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3666a552a69cSDamon Ding 			break;
3667a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_eDP:
3668a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3669a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3670a552a69cSDamon Ding 			break;
3671a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_HDMIA:
3672a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3673a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3674a552a69cSDamon Ding 			break;
3675a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DSI:
3676a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3677a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3678a552a69cSDamon Ding 			break;
3679a552a69cSDamon Ding 		default:
3680a552a69cSDamon Ding 			break;
3681a552a69cSDamon Ding 		}
3682a552a69cSDamon Ding 	}
3683a552a69cSDamon Ding 
3684a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_eDP0) {
3685a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3686a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3687a552a69cSDamon Ding 		/* 0: dclk, 1: port0_dclk */
3688a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3689a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3690a552a69cSDamon Ding 
3691a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3692a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3693a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3694a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3695a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3696a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3697a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3698a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3699a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3700a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3701a552a69cSDamon Ding 	}
3702a552a69cSDamon Ding 
3703a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
3704a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3705a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3706a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
3707a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3708a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3709a552a69cSDamon Ding 
3710a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3711a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3712a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3713a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3714a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3715a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3716a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3717a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3718a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3719a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3720a552a69cSDamon Ding 	}
3721a552a69cSDamon Ding 
3722a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP0) {
3723a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3724a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3725a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3726a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3727a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3728a552a69cSDamon Ding 
3729a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3730a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3731a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3732a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3733a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3734a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3735a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3736a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3737a552a69cSDamon Ding 	}
3738a552a69cSDamon Ding 
3739a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP1) {
3740a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3741a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3742a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3743a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3744a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3745a552a69cSDamon Ding 
3746a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
3747a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3748a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
3749a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3750a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3751a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3752a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3753a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3754a552a69cSDamon Ding 	}
3755a552a69cSDamon Ding 
3756a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP2) {
3757a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3758a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3759a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3760a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3761a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3762a552a69cSDamon Ding 
3763a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
3764a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3765a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
3766a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3767a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3768a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3769a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3770a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3771a552a69cSDamon Ding 	}
3772a552a69cSDamon Ding 
3773a552a69cSDamon Ding 	return mode->crtc_clock;
3774a552a69cSDamon Ding }
3775a552a69cSDamon Ding 
3776a2a16809SChaoyi Chen static void rk3568_vop2_setup_dual_channel_if(struct display_state *state)
3777a2a16809SChaoyi Chen {
3778a2a16809SChaoyi Chen 	struct crtc_state *cstate = &state->crtc_state;
3779a2a16809SChaoyi Chen 	struct connector_state *conn_state = &state->conn_state;
3780a2a16809SChaoyi Chen 	struct vop2 *vop2 = cstate->private;
3781a2a16809SChaoyi Chen 	u32 vp_offset = (cstate->crtc_id * 0x100);
3782a2a16809SChaoyi Chen 
3783a2a16809SChaoyi Chen 	if (conn_state->output_flags &
3784a2a16809SChaoyi Chen 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) {
3785a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3786a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
3787a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3788a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false);
3789a2a16809SChaoyi Chen 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3790a2a16809SChaoyi Chen 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3791a2a16809SChaoyi Chen 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
3792a2a16809SChaoyi Chen 
3793a2a16809SChaoyi Chen 		return;
3794a2a16809SChaoyi Chen 	}
3795a2a16809SChaoyi Chen 
3796a2a16809SChaoyi Chen 	vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3797a2a16809SChaoyi Chen 			MIPI_DUAL_EN_SHIFT, 1, false);
3798a2a16809SChaoyi Chen 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) {
3799a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3800a2a16809SChaoyi Chen 				MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
3801a2a16809SChaoyi Chen 	}
3802a2a16809SChaoyi Chen 
3803a2a16809SChaoyi Chen 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
3804a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3805a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
3806a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3807a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false);
3808a2a16809SChaoyi Chen 	}
3809a2a16809SChaoyi Chen }
3810a2a16809SChaoyi Chen 
3811ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
3812ecc31b6eSAndy Yan {
3813ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3814ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3815ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
3816ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
3817d0408543SAndy Yan 	bool dclk_inv;
3818ecc31b6eSAndy Yan 	u32 val;
38198895aec1SSandy Huang 
382013f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
382110ee9f5bSAlgea Cao 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
382210ee9f5bSAlgea Cao 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3823d0408543SAndy Yan 
3824d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3825d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3826d0408543SAndy Yan 				1, false);
3827d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3828d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
382915f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
383015f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3831ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
3832c55d261eSSandy Huang 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
3833d0408543SAndy Yan 	}
3834d0408543SAndy Yan 
3835d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
383652ee18acSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
383752ee18acSSandy Huang 				1, false);
3838d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
3839d0408543SAndy Yan 				BT1120_EN_SHIFT, 1, false);
3840d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3841d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3842ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
384352ee18acSSandy Huang 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
3844d0408543SAndy Yan 	}
3845d0408543SAndy Yan 
3846d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
3847d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
3848d0408543SAndy Yan 				1, false);
3849d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3850d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3851ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
385252ee18acSSandy Huang 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
3853d0408543SAndy Yan 	}
3854d0408543SAndy Yan 
3855d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
3856d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
3857d0408543SAndy Yan 				1, false);
3858d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3859d0408543SAndy Yan 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
386015f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
386115f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
386211f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
386315f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3864d0408543SAndy Yan 	}
3865d0408543SAndy Yan 
3866d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
3867d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
3868d0408543SAndy Yan 				1, false);
3869d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3870d0408543SAndy Yan 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
387115f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
387215f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
387311f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
387415f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3875d0408543SAndy Yan 	}
3876d0408543SAndy Yan 
3877d0408543SAndy Yan 
3878d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
3879d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
3880d0408543SAndy Yan 				1, false);
3881d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3882d0408543SAndy Yan 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
3883d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3884c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3885de022775SGuochun Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
3886de022775SGuochun Huang 				IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
3887d0408543SAndy Yan 	}
3888d0408543SAndy Yan 
3889d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
3890d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
3891d0408543SAndy Yan 				1, false);
3892d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3893d0408543SAndy Yan 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
3894d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3895c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3896de022775SGuochun Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
3897de022775SGuochun Huang 				IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
3898d0408543SAndy Yan 	}
3899d0408543SAndy Yan 
3900d0408543SAndy Yan 	if (conn_state->output_flags &
3901a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
3902a2a16809SChaoyi Chen 	    conn_state->output_flags &
3903a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)
3904a2a16809SChaoyi Chen 		rk3568_vop2_setup_dual_channel_if(state);
3905d0408543SAndy Yan 
3906d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
3907d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
3908d0408543SAndy Yan 				1, false);
3909d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3910d0408543SAndy Yan 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
3911c55d261eSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3912c55d261eSSandy Huang 				IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
39137bcdc6eeSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK,
39147bcdc6eeSDamon Ding 				IF_CTRL_EDP_PIN_POL_SHIFT, val, false);
3915d0408543SAndy Yan 	}
3916d0408543SAndy Yan 
3917d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
3918d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
3919d0408543SAndy Yan 				1, false);
3920d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3921d0408543SAndy Yan 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
392210ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
392310ee9f5bSAlgea Cao 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
392410ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
392510ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_MASK,
392610ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
3927d0408543SAndy Yan 	}
392810ee9f5bSAlgea Cao 
3929823146b6SDamon Ding 	return mode->crtc_clock;
3930ecc31b6eSAndy Yan }
3931ecc31b6eSAndy Yan 
3932452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state)
3933452afb13SDamon Ding {
3934452afb13SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3935452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3936452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3937452afb13SDamon Ding 	struct vop2 *vop2 = cstate->private;
3938452afb13SDamon Ding 	bool dclk_inv;
3939606f72bdSDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
3940452afb13SDamon Ding 	u32 val;
3941452afb13SDamon Ding 
394213f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3943452afb13SDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3944452afb13SDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3945452afb13SDamon Ding 
3946452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3947452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3948452afb13SDamon Ding 				1, false);
3949452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3950452afb13SDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3951452afb13SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK,
3952452afb13SDamon Ding 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
3953452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
395415f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3955452afb13SDamon Ding 	}
3956452afb13SDamon Ding 
3957452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
3958452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
3959452afb13SDamon Ding 				1, false);
3960452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3961452afb13SDamon Ding 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
3962452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
396315f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3964452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
396515f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3966452afb13SDamon Ding 	}
3967452afb13SDamon Ding 
3968452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
3969452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
3970452afb13SDamon Ding 				1, false);
3971452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3972452afb13SDamon Ding 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
3973452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3974452afb13SDamon Ding 				RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false);
3975452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
3976452afb13SDamon Ding 				RK3562_MIPI_PIN_POL_SHIFT, val, false);
3977606f72bdSDamon Ding 
3978606f72bdSDamon Ding 		if (conn_state->hold_mode) {
3979606f72bdSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3980606f72bdSDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
3981606f72bdSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3982606f72bdSDamon Ding 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
3983606f72bdSDamon Ding 		}
3984452afb13SDamon Ding 	}
3985452afb13SDamon Ding 
3986452afb13SDamon Ding 	return mode->crtc_clock;
3987452afb13SDamon Ding }
3988452afb13SDamon Ding 
3989a552a69cSDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state)
3990a552a69cSDamon Ding {
3991a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3992a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3993a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3994a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
3995a552a69cSDamon Ding 	u32 val;
3996a552a69cSDamon Ding 
3997a552a69cSDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3998a552a69cSDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3999a552a69cSDamon Ding 
4000a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4001a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4002a552a69cSDamon Ding 				1, false);
4003a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4004a552a69cSDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
4005a552a69cSDamon Ding 	}
4006a552a69cSDamon Ding 
4007a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4008a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4009a552a69cSDamon Ding 				1, false);
4010a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4011a552a69cSDamon Ding 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
4012a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4013a552a69cSDamon Ding 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
4014a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
4015a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_MASK,
4016a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4017a552a69cSDamon Ding 	}
4018a552a69cSDamon Ding 
4019a552a69cSDamon Ding 	return mode->crtc_clock;
4020a552a69cSDamon Ding }
4021a552a69cSDamon Ding 
402265747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state)
402365747de7SDamon Ding {
402465747de7SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
402565747de7SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
402665747de7SDamon Ding 	struct vop2 *vop2 = cstate->private;
402765747de7SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
402865747de7SDamon Ding 	u32 output_type = conn_state->type;
402965747de7SDamon Ding 	u32 data_swap = 0;
403065747de7SDamon Ding 
4031c8820b76SDamon Ding 	if (is_uv_swap(state) || is_rb_swap(state))
403265747de7SDamon Ding 		data_swap = DSP_RB_SWAP;
403365747de7SDamon Ding 
4034a552a69cSDamon Ding 	if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) {
4035a552a69cSDamon Ding 		if ((output_type == DRM_MODE_CONNECTOR_HDMIA ||
4036e6e4c154SDamon Ding 		     output_type == DRM_MODE_CONNECTOR_DisplayPort) &&
403765747de7SDamon Ding 		    (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
403865747de7SDamon Ding 		     conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
403965747de7SDamon Ding 		data_swap |= DSP_RG_SWAP;
4040a552a69cSDamon Ding 	}
404165747de7SDamon Ding 
404265747de7SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
404365747de7SDamon Ding 			DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false);
404465747de7SDamon Ding }
404565747de7SDamon Ding 
4046b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
4047b890760eSAlgea Cao {
4048b890760eSAlgea Cao 	int ret = 0;
4049b890760eSAlgea Cao 
4050b890760eSAlgea Cao 	if (parent->dev)
4051b890760eSAlgea Cao 		ret = clk_set_parent(clk, parent);
4052b890760eSAlgea Cao 	if (ret < 0)
4053b890760eSAlgea Cao 		debug("failed to set %s as parent for %s\n",
4054b890760eSAlgea Cao 		      parent->dev->name, clk->dev->name);
4055b890760eSAlgea Cao }
4056b890760eSAlgea Cao 
4057b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate)
4058b890760eSAlgea Cao {
4059b890760eSAlgea Cao 	int ret = 0;
4060b890760eSAlgea Cao 
4061b890760eSAlgea Cao 	if (clk->dev)
4062b890760eSAlgea Cao 		ret = clk_set_rate(clk, rate);
4063b890760eSAlgea Cao 	if (ret < 0)
4064b890760eSAlgea Cao 		debug("failed to set %s rate %lu \n", clk->dev->name, rate);
4065b890760eSAlgea Cao 
4066b890760eSAlgea Cao 	return ret;
4067b890760eSAlgea Cao }
4068b890760eSAlgea Cao 
406912ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state,
407012ee5af0SDamon Ding 				  int *dsc_txp_clk_div, int *dsc_pxl_clk_div,
407112ee5af0SDamon Ding 				  int *dsc_cds_clk_div, u64 dclk_rate)
407212ee5af0SDamon Ding {
407312ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
407412ee5af0SDamon Ding 
407512ee5af0SDamon Ding 	*dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate;
407612ee5af0SDamon Ding 	*dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate;
407712ee5af0SDamon Ding 	*dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate;
407812ee5af0SDamon Ding 
407912ee5af0SDamon Ding 	*dsc_txp_clk_div = ilog2(*dsc_txp_clk_div);
408012ee5af0SDamon Ding 	*dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div);
408112ee5af0SDamon Ding 	*dsc_cds_clk_div = ilog2(*dsc_cds_clk_div);
408212ee5af0SDamon Ding }
408312ee5af0SDamon Ding 
408412ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id)
408512ee5af0SDamon Ding {
408612ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
408712ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set *pps = &cstate->pps;
408812ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set config_pps;
408912ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
409012ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
409112ee5af0SDamon Ding 	u32 *pps_val = (u32 *)&config_pps;
409212ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
409312ee5af0SDamon Ding 	int i = 0;
409412ee5af0SDamon Ding 
409512ee5af0SDamon Ding 	memcpy(&config_pps, pps, sizeof(config_pps));
409612ee5af0SDamon Ding 
409712ee5af0SDamon Ding 	if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) {
409812ee5af0SDamon Ding 		config_pps.pps_3 &= 0xf0;
409912ee5af0SDamon Ding 		config_pps.pps_3 |= dsc_data->max_linebuf_depth;
410012ee5af0SDamon Ding 		printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
410112ee5af0SDamon Ding 		       dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf);
410212ee5af0SDamon Ding 	}
410312ee5af0SDamon Ding 
410412ee5af0SDamon Ding 	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
410512ee5af0SDamon Ding 		config_pps.rc_range_parameters[i] =
410612ee5af0SDamon Ding 			(pps->rc_range_parameters[i] >> 3 & 0x1f) |
410712ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
410812ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
410912ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
411012ee5af0SDamon Ding 	}
411112ee5af0SDamon Ding 
411212ee5af0SDamon Ding 	for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
411312ee5af0SDamon Ding 		vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++);
411412ee5af0SDamon Ding }
411512ee5af0SDamon Ding 
411612ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate)
411712ee5af0SDamon Ding {
411812ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
411912ee5af0SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
412012ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
412112ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
412212ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
412312ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
412412ee5af0SDamon Ding 	bool mipi_ds_mode = false;
412512ee5af0SDamon Ding 	u8 dsc_interface_mode = 0;
412612ee5af0SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
412712ee5af0SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
412812ee5af0SDamon Ding 	u16 htotal = mode->crtc_htotal;
412912ee5af0SDamon Ding 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
413012ee5af0SDamon Ding 	u16 vdisplay = mode->crtc_vdisplay;
413112ee5af0SDamon Ding 	u16 vtotal = mode->crtc_vtotal;
413212ee5af0SDamon Ding 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
413312ee5af0SDamon Ding 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
413412ee5af0SDamon Ding 	u16 vact_end = vact_st + vdisplay;
413512ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
413612ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
413712ee5af0SDamon Ding 	int dsc_txp_clk_div = 0;
413812ee5af0SDamon Ding 	int dsc_pxl_clk_div = 0;
413912ee5af0SDamon Ding 	int dsc_cds_clk_div = 0;
4140baf2c414SDamon Ding 	int val = 0;
414112ee5af0SDamon Ding 
414212ee5af0SDamon Ding 	if (!vop2->data->nr_dscs) {
414312ee5af0SDamon Ding 		printf("Unsupported DSC\n");
414412ee5af0SDamon Ding 		return;
414512ee5af0SDamon Ding 	}
414612ee5af0SDamon Ding 
414712ee5af0SDamon Ding 	if (cstate->dsc_slice_num > dsc_data->max_slice_num)
414812ee5af0SDamon Ding 		printf("DSC%d supported max slice is: %d, current is: %d\n",
414912ee5af0SDamon Ding 		       dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num);
415012ee5af0SDamon Ding 
415112ee5af0SDamon Ding 	if (dsc_data->pd_id) {
415212ee5af0SDamon Ding 		if (vop2_power_domain_on(vop2, dsc_data->pd_id))
415312ee5af0SDamon Ding 			printf("open dsc%d pd fail\n", dsc_id);
415412ee5af0SDamon Ding 	}
415512ee5af0SDamon Ding 
415612ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK,
415712ee5af0SDamon Ding 			SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false);
415812ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK,
415912ee5af0SDamon Ding 			DSC_PORT_SEL_SHIFT, cstate->crtc_id, false);
416012ee5af0SDamon Ding 	if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
416112ee5af0SDamon Ding 		dsc_interface_mode = VOP_DSC_IF_HDMI;
416212ee5af0SDamon Ding 	} else {
416312ee5af0SDamon Ding 		mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
416412ee5af0SDamon Ding 		if (mipi_ds_mode)
416512ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
416612ee5af0SDamon Ding 		else
416712ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
416812ee5af0SDamon Ding 	}
416912ee5af0SDamon Ding 
417012ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
417112ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
417212ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 0, false);
417312ee5af0SDamon Ding 	else
417412ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
417512ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 1, false);
417612ee5af0SDamon Ding 
417712ee5af0SDamon Ding 	vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate);
417812ee5af0SDamon Ding 
417912ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK,
418012ee5af0SDamon Ding 			DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false);
418112ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK,
418212ee5af0SDamon Ding 			DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false);
418312ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK,
418412ee5af0SDamon Ding 			DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false);
418512ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK,
418612ee5af0SDamon Ding 			DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false);
418712ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
418812ee5af0SDamon Ding 			DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false);
418912ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK,
419012ee5af0SDamon Ding 			DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false);
419112ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
419212ee5af0SDamon Ding 			DSC_HALT_EN_SHIFT, mipi_ds_mode, false);
419312ee5af0SDamon Ding 
419412ee5af0SDamon Ding 	if (!mipi_ds_mode) {
419512ee5af0SDamon Ding 		u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
419612ee5af0SDamon Ding 		u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
419712ee5af0SDamon Ding 		u64 dsc_cds_rate = cstate->dsc_cds_clk_rate;
419812ee5af0SDamon Ding 		u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */
419912ee5af0SDamon Ding 		u32 dly_num, dsc_cds_rate_mhz, val = 0;
4200b61227a3SDamon Ding 		int k = 1;
4201b61227a3SDamon Ding 
4202b61227a3SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
4203b61227a3SDamon Ding 			k = 2;
420412ee5af0SDamon Ding 
420512ee5af0SDamon Ding 		if (target_bpp >> 4 < dsc_data->min_bits_per_pixel)
420612ee5af0SDamon Ding 			printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel);
420712ee5af0SDamon Ding 
420812ee5af0SDamon Ding 		/*
420912ee5af0SDamon Ding 		 * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
421012ee5af0SDamon Ding 		 * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
421112ee5af0SDamon Ding 		 * T (dsc_cds) = 1 / dsc_cds_rate_mhz
42121ace1b6dSDamon Ding 		 *
42131ace1b6dSDamon Ding 		 * HDMI:
421412ee5af0SDamon Ding 		 * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
421512ee5af0SDamon Ding 		 *                 delay_line_num = 4 - BPP / 8
421612ee5af0SDamon Ding 		 *                                = (64 - target_bpp / 8) / 16
421712ee5af0SDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
42181ace1b6dSDamon Ding 		 *
42191ace1b6dSDamon Ding 		 * MIPI DSI[4320 and 9216 is buffer size for DSC]:
42201ace1b6dSDamon Ding 		 * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
42211ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
42221ace1b6dSDamon Ding 		 * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
42231ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
42241ace1b6dSDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
422512ee5af0SDamon Ding 		 */
422612ee5af0SDamon Ding 		do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
422712ee5af0SDamon Ding 		dsc_cds_rate_mhz = dsc_cds_rate;
42281ace1b6dSDamon Ding 		dsc_hsync = hsync_len / 2;
42291ace1b6dSDamon Ding 		if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
423012ee5af0SDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
42311ace1b6dSDamon Ding 		} else {
42321ace1b6dSDamon Ding 			int dsc_buf_size  = dsc_id == 0 ? 4320 * 8 : 9216 * 2;
42331ace1b6dSDamon Ding 			int delay_line_num = dsc_buf_size / cstate->dsc_slice_num /
42341ace1b6dSDamon Ding 					     be16_to_cpu(cstate->pps.chunk_size);
42351ace1b6dSDamon Ding 
42361ace1b6dSDamon Ding 			delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
42371ace1b6dSDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
42381ace1b6dSDamon Ding 
42391ace1b6dSDamon Ding 			/* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
42401ace1b6dSDamon Ding 			if (dsc_hsync < 8)
42411ace1b6dSDamon Ding 				dsc_hsync = 8;
42421ace1b6dSDamon Ding 		}
424312ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK,
424412ee5af0SDamon Ding 				DSC_INIT_DLY_MODE_SHIFT, 0, false);
424512ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK,
424612ee5af0SDamon Ding 				DSC_INIT_DLY_NUM_SHIFT, dly_num, false);
424712ee5af0SDamon Ding 
4248b61227a3SDamon Ding 		/*
4249b61227a3SDamon Ding 		 * htotal / dclk_core = dsc_htotal /cds_clk
4250b61227a3SDamon Ding 		 *
4251b61227a3SDamon Ding 		 * dclk_core = DCLK / (1 << dclk_core->div_val)
4252b61227a3SDamon Ding 		 * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
4253b61227a3SDamon Ding 		 * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
4254b61227a3SDamon Ding 		 *
4255b61227a3SDamon Ding 		 * dsc_htotal = htotal * (1 << dclk_core->div_val) /
4256b61227a3SDamon Ding 		 *              ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
4257b61227a3SDamon Ding 		 */
4258b61227a3SDamon Ding 		dsc_htotal = htotal * (1 << cstate->dclk_core_div) /
4259b61227a3SDamon Ding 			     ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div));
426012ee5af0SDamon Ding 		val = dsc_htotal << 16 | dsc_hsync;
426112ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK,
426212ee5af0SDamon Ding 				DSC_HTOTAL_PW_SHIFT, val, false);
426312ee5af0SDamon Ding 
426412ee5af0SDamon Ding 		dsc_hact_st = hact_st / 2;
4265b61227a3SDamon Ding 		dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
426612ee5af0SDamon Ding 		val = dsc_hact_end << 16 | dsc_hact_st;
426712ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK,
426812ee5af0SDamon Ding 				DSC_HACT_ST_END_SHIFT, val, false);
426912ee5af0SDamon Ding 
427012ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK,
427112ee5af0SDamon Ding 				DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false);
427212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK,
427312ee5af0SDamon Ding 				DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false);
427412ee5af0SDamon Ding 	}
427512ee5af0SDamon Ding 
427612ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK,
427712ee5af0SDamon Ding 			RST_DEASSERT_SHIFT, 1, false);
427812ee5af0SDamon Ding 	udelay(10);
427912ee5af0SDamon Ding 
4280baf2c414SDamon Ding 	val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) |
4281baf2c414SDamon Ding 	       ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT);
4282baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
4283baf2c414SDamon Ding 
428412ee5af0SDamon Ding 	vop2_load_pps(state, vop2, dsc_id);
428512ee5af0SDamon Ding 
4286baf2c414SDamon Ding 	val |= (1 << DSC_PPS_UPD_SHIFT);
4287baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
428812ee5af0SDamon Ding 
428912ee5af0SDamon Ding 	printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
429012ee5af0SDamon Ding 	       dsc_id,
429112ee5af0SDamon Ding 	       cstate->dsc_txp_clk_rate, dsc_txp_clk_div,
429212ee5af0SDamon Ding 	       cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div,
429312ee5af0SDamon Ding 	       cstate->dsc_cds_clk_rate, dsc_cds_clk_div);
429412ee5af0SDamon Ding }
429512ee5af0SDamon Ding 
42965f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev)
42975f1357a2SZhang Yubing {
42985f1357a2SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
42995f1357a2SZhang Yubing 	struct vop2 *vop2 = cstate->private;
43005f1357a2SZhang Yubing 	struct udevice *vp_dev, *dev;
43015f1357a2SZhang Yubing 	struct ofnode_phandle_args args;
43025f1357a2SZhang Yubing 	char vp_name[10];
43035f1357a2SZhang Yubing 	int ret;
43045f1357a2SZhang Yubing 
4305a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576)
43065f1357a2SZhang Yubing 		return false;
43075f1357a2SZhang Yubing 
43085f1357a2SZhang Yubing 	sprintf(vp_name, "port@%d", cstate->crtc_id);
43095f1357a2SZhang Yubing 	if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) {
43105e85f4a7SZhang Yubing 		debug("warn: can't get vp device\n");
43115f1357a2SZhang Yubing 		return false;
43125f1357a2SZhang Yubing 	}
43135f1357a2SZhang Yubing 
43145f1357a2SZhang Yubing 	ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0,
43155f1357a2SZhang Yubing 					 0, &args);
43165f1357a2SZhang Yubing 	if (ret) {
43175e85f4a7SZhang Yubing 		debug("assigned-clock-parents's node not define\n");
43185f1357a2SZhang Yubing 		return false;
43195f1357a2SZhang Yubing 	}
43205f1357a2SZhang Yubing 
43215f1357a2SZhang Yubing 	if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) {
43225e85f4a7SZhang Yubing 		debug("warn: can't get clk device\n");
43235f1357a2SZhang Yubing 		return false;
43245f1357a2SZhang Yubing 	}
43255f1357a2SZhang Yubing 
43265f1357a2SZhang Yubing 	if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) {
43275f1357a2SZhang Yubing 		printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name);
43285f1357a2SZhang Yubing 		if (clk_dev)
43295f1357a2SZhang Yubing 			*clk_dev = dev;
43305f1357a2SZhang Yubing 		return true;
43315f1357a2SZhang Yubing 	}
43325f1357a2SZhang Yubing 
43335f1357a2SZhang Yubing 	return false;
43345f1357a2SZhang Yubing }
43355f1357a2SZhang Yubing 
43360675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state)
43370675a2a4SDamon Ding {
43380675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
43390675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
43400675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
43410675a2a4SDamon Ding 
43420675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
43430675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
43440675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
43450675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
43460675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
43470675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false);
43480675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
43490675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false);
43500675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
43510675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false);
43520675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
43530675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false);
43540675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
43550675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false);
43560675a2a4SDamon Ding }
43570675a2a4SDamon Ding 
43580675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state)
43590675a2a4SDamon Ding {
43600675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
43610675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
43620675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
43630675a2a4SDamon Ding 
43640675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
43650675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
43660675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
43670675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
43680675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
43690675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, 53, false);
43700675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
43710675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, 6, false);
43720675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
43730675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, 48, false);
43740675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
43750675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, 12, false);
43760675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
43770675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, 30, false);
43780675a2a4SDamon Ding }
43790675a2a4SDamon Ding 
43800675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value)
43810675a2a4SDamon Ding {
43820675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
43830675a2a4SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
43840675a2a4SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
43850675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
43860675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
43870675a2a4SDamon Ding 
43880675a2a4SDamon Ding 	/*
438958cf1fa3SDamon Ding 	 * 1.set mcu bypass mode timing.
439058cf1fa3SDamon Ding 	 * 2.set dclk rate to 150M.
43910675a2a4SDamon Ding 	 */
43920675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && value) {
43930675a2a4SDamon Ding 		vop3_mcu_bypass_mode_setup(state);
43940675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, 150000000);
43950675a2a4SDamon Ding 	}
43960675a2a4SDamon Ding 
43970675a2a4SDamon Ding 	switch (type) {
43980675a2a4SDamon Ding 	case MCU_WRCMD:
43990675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44000675a2a4SDamon Ding 				MCU_RS_SHIFT, 0, false);
44010675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
44020675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
44030675a2a4SDamon Ding 				value, false);
44040675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44050675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
44060675a2a4SDamon Ding 		break;
44070675a2a4SDamon Ding 	case MCU_WRDATA:
44080675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44090675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
44100675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
44110675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
44120675a2a4SDamon Ding 				value, false);
44130675a2a4SDamon Ding 		break;
44140675a2a4SDamon Ding 	case MCU_SETBYPASS:
44150675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44160675a2a4SDamon Ding 				MCU_BYPASS_SHIFT, value ? 1 : 0, false);
44170675a2a4SDamon Ding 		break;
44180675a2a4SDamon Ding 	default:
44190675a2a4SDamon Ding 		break;
44200675a2a4SDamon Ding 	}
44210675a2a4SDamon Ding 
44220675a2a4SDamon Ding 	/*
442358cf1fa3SDamon Ding 	 * 1.restore mcu data mode timing.
442458cf1fa3SDamon Ding 	 * 2.restore dclk rate to crtc_clock.
44250675a2a4SDamon Ding 	 */
44260675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && !value) {
44270675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
44280675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000);
44290675a2a4SDamon Ding 	}
44300675a2a4SDamon Ding 
44310675a2a4SDamon Ding 	return 0;
44320675a2a4SDamon Ding }
44330675a2a4SDamon Ding 
443434d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id)
443534d37ef0SDamon Ding {
4436a552a69cSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
4437a552a69cSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id];
443834d37ef0SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
443934d37ef0SDamon Ding 	bool pre_dither_down_en = false;
444034d37ef0SDamon Ding 
444134d37ef0SDamon Ding 	switch (bus_format) {
444234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB565_1X16:
444340608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
4444e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4445e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4446e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4447e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false);
444834d37ef0SDamon Ding 		pre_dither_down_en = true;
444934d37ef0SDamon Ding 		break;
445034d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X18:
445134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
445234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
445340608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB666_3X6:
4454e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4455e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4456e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4457e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false);
445834d37ef0SDamon Ding 		pre_dither_down_en = true;
445934d37ef0SDamon Ding 		break;
446034d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
446134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV8_1X24:
446234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
4463e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4464e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
446534d37ef0SDamon Ding 		pre_dither_down_en = true;
446634d37ef0SDamon Ding 		break;
446734d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV10_1X20:
446834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV10_1X30:
446934d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
447034d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB101010_1X30:
4471e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4472e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
447334d37ef0SDamon Ding 		pre_dither_down_en = false;
447434d37ef0SDamon Ding 		break;
447534d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_3X8:
447634d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
447734d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X24:
447834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
447934d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
448034d37ef0SDamon Ding 	default:
4481e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4482e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
448334d37ef0SDamon Ding 		pre_dither_down_en = true;
448434d37ef0SDamon Ding 		break;
448534d37ef0SDamon Ding 	}
448634d37ef0SDamon Ding 
4487e2bdb3b3SDamon Ding 	if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0)
448834d37ef0SDamon Ding 		pre_dither_down_en = false;
448934d37ef0SDamon Ding 
4490a552a69cSDamon Ding 	if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) {
4491481ef52dSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
4492481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000);
4493481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100);
4494481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100);
4495481ef52dSDamon Ding 		}
4496481ef52dSDamon Ding 
4497a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4498a552a69cSDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, 0, false);
4499e2bdb3b3SDamon Ding 		/* enable frc2.0 do 10->8 */
4500a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4501a552a69cSDamon Ding 				DITHER_DOWN_EN_SHIFT, 1, false);
4502e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4503e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false);
4504a552a69cSDamon Ding 	} else {
450534d37ef0SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
450634d37ef0SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
4507e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4508e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false);
450934d37ef0SDamon Ding 	}
4510a552a69cSDamon Ding }
451134d37ef0SDamon Ding 
4512ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state)
4513ecc31b6eSAndy Yan {
4514ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
4515c2b1fe35SDamon Ding 	struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
4516ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
4517ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
4518ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
4519ecc31b6eSAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
4520ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
4521ecc31b6eSAndy Yan 	u16 htotal = mode->crtc_htotal;
4522ecc31b6eSAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
4523ecc31b6eSAndy Yan 	u16 hact_end = hact_st + hdisplay;
4524ecc31b6eSAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
4525ecc31b6eSAndy Yan 	u16 vtotal = mode->crtc_vtotal;
4526ecc31b6eSAndy Yan 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
4527ecc31b6eSAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
4528ecc31b6eSAndy Yan 	u16 vact_end = vact_st + vdisplay;
4529ecc31b6eSAndy Yan 	bool yuv_overlay = false;
4530ecc31b6eSAndy Yan 	u32 vp_offset = (cstate->crtc_id * 0x100);
453166724b9cSDamon Ding 	u32 line_flag_offset = (cstate->crtc_id * 4);
453266724b9cSDamon Ding 	u32 val, act_end;
453358cf1fa3SDamon Ding 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4534edfef528SDamon Ding 	u8 dclk_div_factor = 0;
4535a552a69cSDamon Ding 	u8 vp_dclk_div = 1;
4536ecc31b6eSAndy Yan 	char output_type_name[30] = {0};
4537d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4538ecc31b6eSAndy Yan 	char dclk_name[9];
4539d8e7f4a5SSandy Huang #endif
4540b890760eSAlgea Cao 	struct clk hdmi0_phy_pll;
4541b890760eSAlgea Cao 	struct clk hdmi1_phy_pll;
45425f1357a2SZhang Yubing 	struct clk hdmi_phy_pll;
45433e05a7b8SZhang Yubing 	struct udevice *disp_dev;
45445fa6e665SDamon Ding 	unsigned long dclk_rate = 0;
4545ecc31b6eSAndy Yan 	int ret;
4546ecc31b6eSAndy Yan 
4547ecc31b6eSAndy Yan 	printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
454871ac76f7SDamon Ding 	       mode->crtc_hdisplay, mode->vdisplay,
4549ecc31b6eSAndy Yan 	       mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
45504d64cedbSDamon Ding 	       mode->vrefresh,
45512264c88bSDamon Ding 	       rockchip_get_output_if_name(conn_state->output_if, output_type_name),
4552ecc31b6eSAndy Yan 	       cstate->crtc_id);
4553ecc31b6eSAndy Yan 
4554ee01dbb2SDamon Ding 	if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
4555ee01dbb2SDamon Ding 		cstate->splice_mode = true;
4556ee01dbb2SDamon Ding 		cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id;
4557ee01dbb2SDamon Ding 		if (!cstate->splice_crtc_id) {
4558ee01dbb2SDamon Ding 			printf("%s: Splice mode is unsupported by vp%d\n",
4559ee01dbb2SDamon Ding 			       __func__, cstate->crtc_id);
4560ee01dbb2SDamon Ding 			return -EINVAL;
4561ee01dbb2SDamon Ding 		}
4562b70b2d79SDamon Ding 
4563b70b2d79SDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK,
4564b70b2d79SDamon Ding 				PORT_MERGE_EN_SHIFT, 1, false);
4565ee01dbb2SDamon Ding 	}
4566ee01dbb2SDamon Ding 
4567cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4568cd6c85a9SDamon Ding 			RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4569cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4570cd6c85a9SDamon Ding 			RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4571cd6c85a9SDamon Ding 
457244b1b62cSDamon Ding 	if (vop2->data->vp_data[cstate->crtc_id].urgency) {
457344b1b62cSDamon Ding 		u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl;
457444b1b62cSDamon Ding 		u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh;
457544b1b62cSDamon Ding 
457644b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK,
457744b1b62cSDamon Ding 				AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
457844b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK,
457944b1b62cSDamon Ding 				AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
458044b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK,
458144b1b62cSDamon Ding 				POST_URGENCY_EN_SHIFT, 1, false);
458244b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK,
458344b1b62cSDamon Ding 				POST_URGENCY_THL_SHIFT, urgen_thl, false);
458444b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK,
458544b1b62cSDamon Ding 				POST_URGENCY_THH_SHIFT, urgen_thh, false);
458644b1b62cSDamon Ding 	}
458744b1b62cSDamon Ding 
4588ecc31b6eSAndy Yan 	vop2_initial(vop2, state);
4589ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3588)
4590ecc31b6eSAndy Yan 		dclk_rate = rk3588_vop2_if_cfg(state);
4591a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3576)
4592a552a69cSDamon Ding 		dclk_rate = rk3576_vop2_if_cfg(state);
45935fa6e665SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3568)
4594ecc31b6eSAndy Yan 		dclk_rate = rk3568_vop2_if_cfg(state);
4595452afb13SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3562)
4596452afb13SDamon Ding 		dclk_rate = rk3562_vop2_if_cfg(state);
4597a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3528)
4598a552a69cSDamon Ding 		dclk_rate = rk3528_vop2_if_cfg(state);
4599ecc31b6eSAndy Yan 
46005d2768f7SDamon Ding 	if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
46015d2768f7SDamon Ding 	     !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
46025d2768f7SDamon Ding 	    conn_state->output_if & VOP_OUTPUT_IF_BT656)
46037bdd0eb6SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
46047bdd0eb6SSandy Huang 
4605bf7c1abfSDamon Ding 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
4606bf7c1abfSDamon Ding 		if (vop2->version == VOP_VERSION_RK3588 &&
4607bf7c1abfSDamon Ding 		    conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
4608bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420;
4609bf7c1abfSDamon Ding 	} else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) {
4610bf7c1abfSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 &&
4611bf7c1abfSDamon Ding 		    conn_state->type == DRM_MODE_CONNECTOR_eDP)
4612bf7c1abfSDamon Ding 			conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422;
4613bf7c1abfSDamon Ding 		else if (vop2->version == VOP_VERSION_RK3588 &&
4614bf7c1abfSDamon Ding 			 conn_state->type == DRM_MODE_CONNECTOR_eDP)
4615bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422;
4616bf7c1abfSDamon Ding 		else if (vop2->version == VOP_VERSION_RK3576 &&
4617bf7c1abfSDamon Ding 			 conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
4618bf7c1abfSDamon Ding 			conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422;
4619bf7c1abfSDamon Ding 		else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
4620bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422;
4621bf7c1abfSDamon Ding 	}
4622bf7c1abfSDamon Ding 
462365747de7SDamon Ding 	vop2_post_color_swap(state);
462410ee9f5bSAlgea Cao 
4625d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
4626d0408543SAndy Yan 			OUT_MODE_SHIFT, conn_state->output_mode, false);
4627d0408543SAndy Yan 
462834d37ef0SDamon Ding 	vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id);
462934d37ef0SDamon Ding 	if (cstate->splice_mode)
463034d37ef0SDamon Ding 		vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id);
4631d0408543SAndy Yan 
4632d0408543SAndy Yan 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
4633d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
4634d0408543SAndy Yan 			yuv_overlay, false);
4635d0408543SAndy Yan 
4636d0408543SAndy Yan 	cstate->yuv_overlay = yuv_overlay;
4637d0408543SAndy Yan 
4638d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
4639d0408543SAndy Yan 		    (htotal << 16) | hsync_len);
4640d0408543SAndy Yan 	val = hact_st << 16;
4641d0408543SAndy Yan 	val |= hact_end;
4642d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
4643d0408543SAndy Yan 	val = vact_st << 16;
4644d0408543SAndy Yan 	val |= vact_end;
4645d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
4646d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
4647d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
4648d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
4649d0408543SAndy Yan 
4650d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
4651d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
4652d0408543SAndy Yan 			    val);
4653d0408543SAndy Yan 
4654d0408543SAndy Yan 		val = vtotal << 16 | (vtotal + vsync_len);
4655d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
4656d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4657d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 1, false);
4658d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
46597a20be36SSandy Huang 				DSP_FILED_POL, 1, false);
46607a20be36SSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4661d0408543SAndy Yan 				P2I_EN_SHIFT, 1, false);
4662d0408543SAndy Yan 		vtotal += vtotal + 1;
466366724b9cSDamon Ding 		act_end = vact_end_f1;
4664d0408543SAndy Yan 	} else {
4665d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4666d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 0, false);
4667d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4668d0408543SAndy Yan 				P2I_EN_SHIFT, 0, false);
466966724b9cSDamon Ding 		act_end = vact_end;
4670d0408543SAndy Yan 	}
4671d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
4672d0408543SAndy Yan 		    (vtotal << 16) | vsync_len);
467367be2ffcSDamon Ding 
4674a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 ||
4675a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3562 ||
4676a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3568) {
467767be2ffcSDamon Ding 		if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
467867be2ffcSDamon Ding 		conn_state->output_if & VOP_OUTPUT_IF_BT656)
4679d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
468067be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 1, false);
468167be2ffcSDamon Ding 		else
468267be2ffcSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
468367be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 0, false);
468410ee9f5bSAlgea Cao 
468510ee9f5bSAlgea Cao 		if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
468663cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
468763cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
468810ee9f5bSAlgea Cao 		else
468963cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
469063cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
4691a552a69cSDamon Ding 	}
469210ee9f5bSAlgea Cao 
4693ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
4694ee01dbb2SDamon Ding 			OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false);
4695ee01dbb2SDamon Ding 
469610ee9f5bSAlgea Cao 	if (yuv_overlay)
469710ee9f5bSAlgea Cao 		val = 0x20010200;
469810ee9f5bSAlgea Cao 	else
469910ee9f5bSAlgea Cao 		val = 0;
470010ee9f5bSAlgea Cao 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
4701b70b2d79SDamon Ding 	if (cstate->splice_mode) {
4702ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
4703ee01dbb2SDamon Ding 				OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id,
4704ee01dbb2SDamon Ding 				yuv_overlay, false);
4705ee01dbb2SDamon Ding 		vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val);
4706ee01dbb2SDamon Ding 	}
470710ee9f5bSAlgea Cao 
470810ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
470910ee9f5bSAlgea Cao 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
4710d0408543SAndy Yan 
4711c2b1fe35SDamon Ding 	if (vp->xmirror_en)
4712c2b1fe35SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4713c2b1fe35SDamon Ding 				DSP_X_MIR_EN_SHIFT, 1, false);
4714c2b1fe35SDamon Ding 
4715ac500a1fSSandy Huang 	vop2_tv_config_update(state, vop2);
4716d0408543SAndy Yan 	vop2_post_config(state, vop2);
47176027c871SZhang Yubing 	if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
47186027c871SZhang Yubing 		vop3_post_config(state, vop2);
4719d0408543SAndy Yan 
472012ee5af0SDamon Ding 	if (cstate->dsc_enable) {
472112ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
47221ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL);
47231ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL);
472412ee5af0SDamon Ding 		} else {
47251ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL);
472612ee5af0SDamon Ding 		}
472712ee5af0SDamon Ding 	}
472812ee5af0SDamon Ding 
4729d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4730ecc31b6eSAndy Yan 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
47310675a2a4SDamon Ding 	ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk);
4732b890760eSAlgea Cao 	if (ret) {
4733b890760eSAlgea Cao 		printf("%s: Failed to get dclk ret=%d\n", __func__, ret);
4734b890760eSAlgea Cao 		return ret;
4735b890760eSAlgea Cao 	}
4736d8e7f4a5SSandy Huang #endif
4737b890760eSAlgea Cao 
47383e05a7b8SZhang Yubing 	ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev);
47393e05a7b8SZhang Yubing 	if (!ret) {
47403e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll);
47413e05a7b8SZhang Yubing 		if (ret)
47425e85f4a7SZhang Yubing 			debug("%s: hdmi0_phy_pll may not define\n", __func__);
47433e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll);
47443e05a7b8SZhang Yubing 		if (ret)
47455e85f4a7SZhang Yubing 			debug("%s: hdmi1_phy_pll may not define\n", __func__);
47463e05a7b8SZhang Yubing 	} else {
4747b890760eSAlgea Cao 		hdmi0_phy_pll.dev = NULL;
4748545a0218SAlgea Cao 		hdmi1_phy_pll.dev = NULL;
47495e85f4a7SZhang Yubing 		debug("%s: Faile to find display-subsystem node\n", __func__);
4750b890760eSAlgea Cao 	}
4751b890760eSAlgea Cao 
4752ebbd144cSAlgea Cao 	if (vop2->version == VOP_VERSION_RK3528) {
4753ebbd144cSAlgea Cao 		struct ofnode_phandle_args args;
4754ebbd144cSAlgea Cao 
4755ebbd144cSAlgea Cao 		ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents",
4756ebbd144cSAlgea Cao 						 "#clock-cells", 0, 0, &args);
4757ebbd144cSAlgea Cao 		if (!ret) {
4758ebbd144cSAlgea Cao 			ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev);
4759ebbd144cSAlgea Cao 			if (ret) {
4760ebbd144cSAlgea Cao 				debug("warn: can't get clk device\n");
4761ebbd144cSAlgea Cao 				return ret;
4762ebbd144cSAlgea Cao 			}
4763ebbd144cSAlgea Cao 		} else {
4764ebbd144cSAlgea Cao 			debug("assigned-clock-parents's node not define\n");
4765ebbd144cSAlgea Cao 		}
4766ebbd144cSAlgea Cao 	}
4767ebbd144cSAlgea Cao 
4768cce1f2abSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
4769cce1f2abSDamon Ding 		vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div;
4770cce1f2abSDamon Ding 
47710a1fb152SZhang Yubing 	if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) {
4772b890760eSAlgea Cao 		if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0)
47730675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll);
4774b890760eSAlgea Cao 		else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1)
47750675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll);
4776b890760eSAlgea Cao 
4777b890760eSAlgea Cao 		/*
4778b890760eSAlgea Cao 		 * uboot clk driver won't set dclk parent's rate when use
4779b890760eSAlgea Cao 		 * hdmi phypll as dclk source.
4780b890760eSAlgea Cao 		 * So set dclk rate is meaningless. Set hdmi phypll rate
4781b890760eSAlgea Cao 		 * directly.
4782b890760eSAlgea Cao 		 */
47835f1357a2SZhang Yubing 		if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) {
4784cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000);
47855f1357a2SZhang Yubing 		} else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) {
4786cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000);
47875f1357a2SZhang Yubing 		} else {
47887efea85dSDamon Ding 			if (is_extend_pll(state, &hdmi_phy_pll.dev)) {
4789cce1f2abSDamon Ding 				ret = vop2_clk_set_rate(&hdmi_phy_pll,
4790cce1f2abSDamon Ding 							dclk_rate / vp_dclk_div * 1000);
47917efea85dSDamon Ding 			} else {
4792d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4793a552a69cSDamon Ding 				ret = vop2_clk_set_rate(&cstate->dclk,
4794a552a69cSDamon Ding 							dclk_rate / vp_dclk_div * 1000);
4795d8e7f4a5SSandy Huang #else
4796d8e7f4a5SSandy Huang 				if (vop2->version == VOP_VERSION_RK3528) {
4797d8e7f4a5SSandy Huang 					void *cru_base = (void *)RK3528_CRU_BASE;
4798d8e7f4a5SSandy Huang 
4799d8e7f4a5SSandy Huang 					/* dclk src switch to hdmiphy pll */
4800d8e7f4a5SSandy Huang 					writel((BIT(0) << 16) | BIT(0), cru_base + 0x450);
4801d8e7f4a5SSandy Huang 					rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000);
4802d8e7f4a5SSandy Huang 					ret = dclk_rate * 1000;
4803d8e7f4a5SSandy Huang 				}
4804d8e7f4a5SSandy Huang #endif
48055f1357a2SZhang Yubing 			}
48067efea85dSDamon Ding 		}
4807631ee99aSZhang Yubing 	} else {
48085f1357a2SZhang Yubing 		if (is_extend_pll(state, &hdmi_phy_pll.dev))
4809cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000);
48105f1357a2SZhang Yubing 		else
4811cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000);
4812edfef528SDamon Ding 	}
481363638f32SDamon Ding 
481463638f32SDamon Ding 	if (IS_ERR_VALUE(ret)) {
481563638f32SDamon Ding 		printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
481663638f32SDamon Ding 		       __func__, cstate->crtc_id, dclk_rate, ret);
481763638f32SDamon Ding 		return ret;
481863638f32SDamon Ding 	} else {
48194d64cedbSDamon Ding 		if (cstate->mcu_timing.mcu_pix_total) {
48204d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) / 1000;
48214d64cedbSDamon Ding 		} else {
48229655ad2fSDamon Ding 			dclk_div_factor = mode->crtc_clock / dclk_rate;
48234d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000;
48244d64cedbSDamon Ding 		}
4825edfef528SDamon Ding 		printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock);
4826631ee99aSZhang Yubing 	}
4827ecc31b6eSAndy Yan 
482866724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
4829e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false);
483066724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
4831e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false);
483266724b9cSDamon Ding 
483358cf1fa3SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total) {
483458cf1fa3SDamon Ding 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
483558cf1fa3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
483658cf1fa3SDamon Ding 				STANDBY_EN_SHIFT, 0, false);
48370675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
483858cf1fa3SDamon Ding 	}
48390675a2a4SDamon Ding 
4840d0408543SAndy Yan 	return 0;
4841d0408543SAndy Yan }
4842d0408543SAndy Yan 
4843ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
48443e39a5a1SSandy Huang 			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
48453e39a5a1SSandy Huang 			     uint32_t dst_h)
48463e39a5a1SSandy Huang {
48473e39a5a1SSandy Huang 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
48483e39a5a1SSandy Huang 	uint16_t hscl_filter_mode, vscl_filter_mode;
48495fa6e665SDamon Ding 	uint8_t xgt2 = 0, xgt4 = 0;
48505fa6e665SDamon Ding 	uint8_t ygt2 = 0, ygt4 = 0;
48513e39a5a1SSandy Huang 	uint32_t xfac = 0, yfac = 0;
4852ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
48535fa6e665SDamon Ding 	bool xgt_en = false;
48545fa6e665SDamon Ding 	bool xavg_en = false;
48553e39a5a1SSandy Huang 
48565fa6e665SDamon Ding 	if (is_vop3(vop2)) {
4857a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) {
4858a552a69cSDamon Ding 			if (src_w >= (8 * dst_w)) {
4859a552a69cSDamon Ding 				xgt4 = 1;
4860a552a69cSDamon Ding 				src_w >>= 2;
4861a552a69cSDamon Ding 			} else if (src_w >= (4 * dst_w)) {
4862a552a69cSDamon Ding 				xgt2 = 1;
4863a552a69cSDamon Ding 				src_w >>= 1;
4864a552a69cSDamon Ding 			}
4865a552a69cSDamon Ding 		} else {
48665fa6e665SDamon Ding 			if (src_w >= (4 * dst_w)) {
48675fa6e665SDamon Ding 				xgt4 = 1;
48685fa6e665SDamon Ding 				src_w >>= 2;
48695fa6e665SDamon Ding 			} else if (src_w >= (2 * dst_w)) {
48705fa6e665SDamon Ding 				xgt2 = 1;
48715fa6e665SDamon Ding 				src_w >>= 1;
48725fa6e665SDamon Ding 			}
48735fa6e665SDamon Ding 		}
4874a552a69cSDamon Ding 	}
48753e39a5a1SSandy Huang 
4876183eb252SDamon Ding 	/**
4877183eb252SDamon Ding 	 * The rk3528 is processed as 2 pixel/cycle,
4878183eb252SDamon Ding 	 * so ygt2/ygt4 needs to be triggered in advance to improve performance
4879183eb252SDamon Ding 	 * when src_w is bigger than 1920.
4880183eb252SDamon Ding 	 * dst_h / src_h is at [1, 0.65)     ygt2=0; ygt4=0;
4881183eb252SDamon Ding 	 * dst_h / src_h is at [0.65, 0.35)  ygt2=1; ygt4=0;
4882183eb252SDamon Ding 	 * dst_h / src_h is at [0.35, 0)     ygt2=0; ygt4=1;
4883183eb252SDamon Ding 	 */
4884183eb252SDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
4885183eb252SDamon Ding 		if (src_h >= (100 * dst_h / 35)) {
4886183eb252SDamon Ding 			ygt4 = 1;
4887183eb252SDamon Ding 			src_h >>= 2;
4888183eb252SDamon Ding 		} else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) {
4889183eb252SDamon Ding 			ygt2 = 1;
4890183eb252SDamon Ding 			src_h >>= 1;
4891183eb252SDamon Ding 		}
4892183eb252SDamon Ding 	} else {
4893a552a69cSDamon Ding 		if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) {
4894a552a69cSDamon Ding 			if (src_h >= (8 * dst_h)) {
4895a552a69cSDamon Ding 				ygt4 = 1;
4896a552a69cSDamon Ding 				src_h >>= 2;
4897a552a69cSDamon Ding 			} else if (src_h >= (4 * dst_h)) {
4898a552a69cSDamon Ding 				ygt2 = 1;
4899a552a69cSDamon Ding 				src_h >>= 1;
4900a552a69cSDamon Ding 			}
4901a552a69cSDamon Ding 		} else {
49025fa6e665SDamon Ding 			if (src_h >= (4 * dst_h)) {
49035fa6e665SDamon Ding 				ygt4 = 1;
49043e39a5a1SSandy Huang 				src_h >>= 2;
49055fa6e665SDamon Ding 			} else if (src_h >= (2 * dst_h)) {
49065fa6e665SDamon Ding 				ygt2 = 1;
49073e39a5a1SSandy Huang 				src_h >>= 1;
49085fa6e665SDamon Ding 			}
4909183eb252SDamon Ding 		}
4910a552a69cSDamon Ding 	}
49113e39a5a1SSandy Huang 
49123e39a5a1SSandy Huang 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
49133e39a5a1SSandy Huang 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
49143e39a5a1SSandy Huang 
49153e39a5a1SSandy Huang 	if (yrgb_hor_scl_mode == SCALE_UP)
49165fa6e665SDamon Ding 		hscl_filter_mode = win->hsu_filter_mode;
49173e39a5a1SSandy Huang 	else
49185fa6e665SDamon Ding 		hscl_filter_mode = win->hsd_filter_mode;
49193e39a5a1SSandy Huang 
49203e39a5a1SSandy Huang 	if (yrgb_ver_scl_mode == SCALE_UP)
49215fa6e665SDamon Ding 		vscl_filter_mode = win->vsu_filter_mode;
49223e39a5a1SSandy Huang 	else
49235fa6e665SDamon Ding 		vscl_filter_mode = win->vsd_filter_mode;
49243e39a5a1SSandy Huang 
49253e39a5a1SSandy Huang 	/*
49263e39a5a1SSandy Huang 	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
49273e39a5a1SSandy Huang 	 * at scale down mode
49283e39a5a1SSandy Huang 	 */
49295fa6e665SDamon Ding 	if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) {
49303e39a5a1SSandy Huang 		printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
49313e39a5a1SSandy Huang 		dst_w += 1;
49323e39a5a1SSandy Huang 	}
49333e39a5a1SSandy Huang 
49345fa6e665SDamon Ding 	if (is_vop3(vop2)) {
49355fa6e665SDamon Ding 		xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true);
49365fa6e665SDamon Ding 		yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false);
49375fa6e665SDamon Ding 
49385fa6e665SDamon Ding 		if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG)
49395fa6e665SDamon Ding 			xavg_en = xgt2 || xgt4;
49405fa6e665SDamon Ding 		else
49415fa6e665SDamon Ding 			xgt_en = xgt2 || xgt4;
4942a552a69cSDamon Ding 
4943a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
4944a552a69cSDamon Ding 			bool zme_dering_en = false;
4945a552a69cSDamon Ding 
4946a552a69cSDamon Ding 			if ((yrgb_hor_scl_mode == SCALE_UP &&
4947a552a69cSDamon Ding 			     hscl_filter_mode == VOP2_SCALE_UP_ZME) ||
4948a552a69cSDamon Ding 			    (yrgb_ver_scl_mode == SCALE_UP &&
4949a552a69cSDamon Ding 			     vscl_filter_mode == VOP2_SCALE_UP_ZME))
4950a552a69cSDamon Ding 				zme_dering_en = true;
4951a552a69cSDamon Ding 
4952a552a69cSDamon Ding 			/* Recommended configuration from the algorithm */
4953a552a69cSDamon Ding 			vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset,
4954a552a69cSDamon Ding 				    0x04100d10);
4955a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset,
4956a552a69cSDamon Ding 					EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false);
4957a552a69cSDamon Ding 		}
49585fa6e665SDamon Ding 	} else {
49593e39a5a1SSandy Huang 		xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
49603e39a5a1SSandy Huang 		yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
49615fa6e665SDamon Ding 	}
4962ecc31b6eSAndy Yan 
4963ecc31b6eSAndy Yan 	if (win->type == CLUSTER_LAYER) {
4964ecc31b6eSAndy Yan 		vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
4965ecc31b6eSAndy Yan 			    yfac << 16 | xfac);
4966ecc31b6eSAndy Yan 
49675fa6e665SDamon Ding 		if (is_vop3(vop2)) {
4968ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49695fa6e665SDamon Ding 					EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false);
4970ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49715fa6e665SDamon Ding 					EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false);
49725fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49735fa6e665SDamon Ding 					XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
4974ecc31b6eSAndy Yan 
4975ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49765fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT,
49775fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
4978ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49795fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT,
49805fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
49815fa6e665SDamon Ding 		} else {
49825fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49835fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT,
49845fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
49855fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49865fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT,
49875fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
49885fa6e665SDamon Ding 		}
4989ecc31b6eSAndy Yan 
49905fa6e665SDamon Ding 		if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
49915fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49925fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false);
49935fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49945fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false);
49955fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49965fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false);
49975fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
49985fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false);
49995fa6e665SDamon Ding 		} else {
50005fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50015fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false);
50025fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50035fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false);
50045fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50055fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false);
50065fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50075fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false);
50085fa6e665SDamon Ding 		}
5009ecc31b6eSAndy Yan 	} else {
50103e39a5a1SSandy Huang 		vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
50113e39a5a1SSandy Huang 			    yfac << 16 | xfac);
50123e39a5a1SSandy Huang 
50135fa6e665SDamon Ding 		if (is_vop3(vop2)) {
501434a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50155fa6e665SDamon Ding 					EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false);
501634a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50175fa6e665SDamon Ding 					EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false);
50185fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50195fa6e665SDamon Ding 					XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
50205fa6e665SDamon Ding 		}
50215fa6e665SDamon Ding 
50225fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50235fa6e665SDamon Ding 				YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false);
50245fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50255fa6e665SDamon Ding 				YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false);
50263e39a5a1SSandy Huang 
50273e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50283e39a5a1SSandy Huang 				YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
50293e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50303e39a5a1SSandy Huang 				YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
50313e39a5a1SSandy Huang 
50323e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50333e39a5a1SSandy Huang 				YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
50343e39a5a1SSandy Huang 				hscl_filter_mode, false);
50353e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50363e39a5a1SSandy Huang 				YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
50373e39a5a1SSandy Huang 				vscl_filter_mode, false);
50383e39a5a1SSandy Huang 	}
5039ecc31b6eSAndy Yan }
50403e39a5a1SSandy Huang 
5041a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win)
5042a33b790fSDamon Ding {
5043a33b790fSDamon Ding 	u32 win_offset = win->reg_offset;
5044a33b790fSDamon Ding 
5045a33b790fSDamon Ding 	if (win->type == CLUSTER_LAYER) {
5046a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK,
5047a33b790fSDamon Ding 				CLUSTER_AXI_ID_SHIFT, win->axi_id, false);
5048a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK,
5049a33b790fSDamon Ding 				CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5050a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK,
5051a33b790fSDamon Ding 				CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5052a33b790fSDamon Ding 	} else {
5053a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK,
5054a33b790fSDamon Ding 				ESMART_AXI_ID_SHIFT, win->axi_id, false);
5055a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK,
5056a33b790fSDamon Ding 				ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5057a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK,
5058a33b790fSDamon Ding 				ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5059a33b790fSDamon Ding 	}
5060a33b790fSDamon Ding }
5061a33b790fSDamon Ding 
5062840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format)
5063840bf541SDamon Ding {
5064840bf541SDamon Ding 	switch (format) {
5065840bf541SDamon Ding 	case ROCKCHIP_FMT_RGB565:
5066840bf541SDamon Ding 		return true;
5067840bf541SDamon Ding 	default:
5068840bf541SDamon Ding 		return false;
5069840bf541SDamon Ding 	}
5070840bf541SDamon Ding }
5071840bf541SDamon Ding 
50721c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win)
50731c9572c7SDamon Ding {
50741c9572c7SDamon Ding 	return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR);
50751c9572c7SDamon Ding }
50761c9572c7SDamon Ding 
50771c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
5078d0408543SAndy Yan {
5079d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5080d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
5081d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
5082d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
50839c7848c3SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
50849c7848c3SDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
5085ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
5086ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
5087ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
5088ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
5089ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
5090ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
5091d0408543SAndy Yan 	int xvir = cstate->xvir;
5092d0408543SAndy Yan 	int y_mirror = 0;
509310ee9f5bSAlgea Cao 	int csc_mode;
5094ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5095ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
5096ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
5097ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
5098ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
5099ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5100840bf541SDamon Ding 	bool dither_up;
5101d0408543SAndy Yan 
5102ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
5103ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
5104ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
5105ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
5106ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
5107ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
5108ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
5109ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5110ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5111ee01dbb2SDamon Ding 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5112ee01dbb2SDamon Ding 	}
5113ee01dbb2SDamon Ding 
5114ecc31b6eSAndy Yan 	act_info = (src_h - 1) << 16;
5115ecc31b6eSAndy Yan 	act_info |= (src_w - 1) & 0xffff;
5116ecc31b6eSAndy Yan 
5117ecc31b6eSAndy Yan 	dsp_info = (crtc_h - 1) << 16;
5118ecc31b6eSAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
5119ecc31b6eSAndy Yan 
5120ecc31b6eSAndy Yan 	dsp_stx = crtc_x;
5121ecc31b6eSAndy Yan 	dsp_sty = crtc_y;
5122ecc31b6eSAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5123ecc31b6eSAndy Yan 
5124ecc31b6eSAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5125ecc31b6eSAndy Yan 		y_mirror = 1;
5126ecc31b6eSAndy Yan 	else
5127ecc31b6eSAndy Yan 		y_mirror = 0;
5128ecc31b6eSAndy Yan 
5129ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
5130ecc31b6eSAndy Yan 
5131a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
5132a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
5133a33b790fSDamon Ding 
5134ecc31b6eSAndy Yan 	if (y_mirror)
5135ecc31b6eSAndy Yan 		printf("WARN: y mirror is unsupported by cluster window\n");
5136ecc31b6eSAndy Yan 
51379c7848c3SDamon Ding 	if (is_vop3(vop2)) {
5138a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset,
51394751aa64SDamon Ding 				CLUSTER_PORT_SEL_MASK, CLUSTER_PORT_SEL_SHIFT,
5140a552a69cSDamon Ding 				cstate->crtc_id, false);
51419c7848c3SDamon Ding 		vop2_ops->setup_win_dly(state, cstate->crtc_id);
51429c7848c3SDamon Ding 	}
5143a552a69cSDamon Ding 
5144e84ccd9bSDamon Ding 	/*
5145e84ccd9bSDamon Ding 	 * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode.
5146e84ccd9bSDamon Ding 	 */
5147e84ccd9bSDamon Ding 	if (vop2->version >= VOP_VERSION_RK3588)
5148a59754e1SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset,
5149a59754e1SDamon Ding 				EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false);
5150a59754e1SDamon Ding 
5151ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
5152ecc31b6eSAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5153ecc31b6eSAndy Yan 			false);
5154ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
5155ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset,
5156ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
5157ecc31b6eSAndy Yan 
5158ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
5159ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
5160ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
5161ecc31b6eSAndy Yan 
5162ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
5163ecc31b6eSAndy Yan 
5164df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5165df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
5166ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5167ecc31b6eSAndy Yan 			CLUSTER_RGB2YUV_EN_SHIFT,
5168ecc31b6eSAndy Yan 			is_yuv_output(conn_state->bus_format), false);
5169ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
5170ecc31b6eSAndy Yan 			CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
5171840bf541SDamon Ding 
5172840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5173840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5174840bf541SDamon Ding 			CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false);
5175840bf541SDamon Ding 
5176ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
5177ecc31b6eSAndy Yan 
5178ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
51791c9572c7SDamon Ding 
51801c9572c7SDamon Ding 	return 0;
5181d0408543SAndy Yan }
5182d0408543SAndy Yan 
51831c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
5184ecc31b6eSAndy Yan {
5185ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5186ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
5187ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
5188ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
51899c7848c3SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
51909c7848c3SDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
5191ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
5192ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
5193ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
5194ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
5195ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
5196ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
5197ecc31b6eSAndy Yan 	int xvir = cstate->xvir;
5198ecc31b6eSAndy Yan 	int y_mirror = 0;
5199ecc31b6eSAndy Yan 	int csc_mode;
5200ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5201ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
5202ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
5203ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
5204ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
5205ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
52061c9572c7SDamon Ding 	u32 val;
5207840bf541SDamon Ding 	bool dither_up;
5208ecc31b6eSAndy Yan 
52091c9572c7SDamon Ding 	if (vop2_is_mirror_win(win)) {
52101c9572c7SDamon Ding 		struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id);
52111c9572c7SDamon Ding 
52121c9572c7SDamon Ding 		if (!source_win) {
52131c9572c7SDamon Ding 			printf("invalid source win id %d\n", win->source_win_id);
52141c9572c7SDamon Ding 			return -ENODEV;
52151c9572c7SDamon Ding 		}
52161c9572c7SDamon Ding 
52171c9572c7SDamon Ding 		val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset);
52181c9572c7SDamon Ding 		if (!(val & BIT(WIN_EN_SHIFT))) {
52191c9572c7SDamon Ding 			printf("WARN: the source win should be enabled before mirror win\n");
52201c9572c7SDamon Ding 			return -EAGAIN;
52211c9572c7SDamon Ding 		}
52221c9572c7SDamon Ding 	}
52231c9572c7SDamon Ding 
5224ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
5225ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
5226ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
5227ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
5228ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
5229ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
5230ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
5231ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5232ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5233ee01dbb2SDamon Ding 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5234ee01dbb2SDamon Ding 	}
5235ee01dbb2SDamon Ding 
523674bd8269SSandy Huang 	/*
523774bd8269SSandy Huang 	 * This is workaround solution for IC design:
523874bd8269SSandy Huang 	 * esmart can't support scale down when actual_w % 16 == 1.
523974bd8269SSandy Huang 	 */
524074bd8269SSandy Huang 	if (src_w > crtc_w && (src_w & 0xf) == 1) {
524174bd8269SSandy Huang 		printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
524274bd8269SSandy Huang 		src_w -= 1;
524374bd8269SSandy Huang 	}
524474bd8269SSandy Huang 
5245d0408543SAndy Yan 	act_info = (src_h - 1) << 16;
5246d0408543SAndy Yan 	act_info |= (src_w - 1) & 0xffff;
5247d0408543SAndy Yan 
5248d0408543SAndy Yan 	dsp_info = (crtc_h - 1) << 16;
5249d0408543SAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
5250d0408543SAndy Yan 
5251d0408543SAndy Yan 	dsp_stx = crtc_x;
5252d0408543SAndy Yan 	dsp_sty = crtc_y;
5253d0408543SAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5254d0408543SAndy Yan 
5255d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5256d0408543SAndy Yan 		y_mirror = 1;
5257d0408543SAndy Yan 	else
5258d0408543SAndy Yan 		y_mirror = 0;
5259d0408543SAndy Yan 
5260a552a69cSDamon Ding 	if (is_vop3(vop2)) {
5261a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset,
5262a552a69cSDamon Ding 				ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT,
5263a552a69cSDamon Ding 				win->scale_engine_num, false);
5264a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5265a552a69cSDamon Ding 				ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5266a552a69cSDamon Ding 				cstate->crtc_id, false);
52679c7848c3SDamon Ding 		vop2_ops->setup_win_dly(state, cstate->crtc_id);
5268a552a69cSDamon Ding 
5269a552a69cSDamon Ding 		/* Merge esmart1/3 from vp1 post to vp0 */
5270a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 &&
5271a552a69cSDamon Ding 		    (win->phys_id == ROCKCHIP_VOP2_ESMART1 ||
5272a552a69cSDamon Ding 		     win->phys_id == ROCKCHIP_VOP2_ESMART3))
5273a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5274a552a69cSDamon Ding 					ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5275a552a69cSDamon Ding 					1, false);
5276a552a69cSDamon Ding 	}
52775fa6e665SDamon Ding 
5278ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
52793e39a5a1SSandy Huang 
5280a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
5281a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
5282a33b790fSDamon Ding 
5283d0408543SAndy Yan 	if (y_mirror)
5284d0408543SAndy Yan 		cstate->dma_addr += (src_h - 1) * xvir * 4;
5285d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
5286d0408543SAndy Yan 			YMIRROR_EN_SHIFT, y_mirror, false);
5287d0408543SAndy Yan 
5288d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5289d0408543SAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5290d0408543SAndy Yan 			false);
5291a552a69cSDamon Ding 
5292a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
5293a552a69cSDamon Ding 		vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00);
5294a552a69cSDamon Ding 
5295d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
5296d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
5297ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
5298d0408543SAndy Yan 
5299d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
5300d0408543SAndy Yan 		    act_info);
5301d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
5302d0408543SAndy Yan 		    dsp_info);
5303d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
5304d0408543SAndy Yan 
5305d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5306d0408543SAndy Yan 			WIN_EN_SHIFT, 1, false);
5307d0408543SAndy Yan 
5308df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5309df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
531010ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
531110ee9f5bSAlgea Cao 			RGB2YUV_EN_SHIFT,
531210ee9f5bSAlgea Cao 			is_yuv_output(conn_state->bus_format), false);
531310ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
531410ee9f5bSAlgea Cao 			CSC_MODE_SHIFT, csc_mode, false);
531510ee9f5bSAlgea Cao 
5316840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5317840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5318840bf541SDamon Ding 			REGION0_DITHER_UP_EN_SHIFT, dither_up, false);
5319840bf541SDamon Ding 
5320d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
53211c9572c7SDamon Ding 
53221c9572c7SDamon Ding 	return 0;
5323ecc31b6eSAndy Yan }
5324ecc31b6eSAndy Yan 
5325ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state)
5326ee01dbb2SDamon Ding {
5327ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5328ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
5329ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
5330ee01dbb2SDamon Ding 	struct display_rect *src_rect = &cstate->src_rect;
5331ee01dbb2SDamon Ding 	struct display_rect *dst_rect = &cstate->crtc_rect;
5332ee01dbb2SDamon Ding 	struct display_rect left_src, left_dst, right_src, right_dst;
5333ee01dbb2SDamon Ding 	u16 half_hdisplay = mode->crtc_hdisplay >> 1;
5334ee01dbb2SDamon Ding 	int left_src_w, left_dst_w, right_dst_w;
5335ee01dbb2SDamon Ding 
5336ee01dbb2SDamon Ding 	left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x;
5337ee01dbb2SDamon Ding 	if (left_dst_w < 0)
5338ee01dbb2SDamon Ding 		left_dst_w = 0;
5339ee01dbb2SDamon Ding 	right_dst_w = dst_rect->w - left_dst_w;
5340ee01dbb2SDamon Ding 
5341ee01dbb2SDamon Ding 	if (!right_dst_w)
5342ee01dbb2SDamon Ding 		left_src_w = src_rect->w;
5343ee01dbb2SDamon Ding 	else
53440df0fd39SSandy Huang 		left_src_w = src_rect->x + src_rect->w - src_rect->w / 2;
5345ee01dbb2SDamon Ding 
5346ee01dbb2SDamon Ding 	left_src.x = src_rect->x;
5347ee01dbb2SDamon Ding 	left_src.w = left_src_w;
5348ee01dbb2SDamon Ding 	left_dst.x = dst_rect->x;
5349ee01dbb2SDamon Ding 	left_dst.w = left_dst_w;
5350ee01dbb2SDamon Ding 	right_src.x = left_src.x + left_src.w;
5351ee01dbb2SDamon Ding 	right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w;
5352ee01dbb2SDamon Ding 	right_dst.x = dst_rect->x + left_dst_w - half_hdisplay;
5353ee01dbb2SDamon Ding 	right_dst.w = right_dst_w;
5354ee01dbb2SDamon Ding 
5355ee01dbb2SDamon Ding 	left_src.y = src_rect->y;
5356ee01dbb2SDamon Ding 	left_src.h = src_rect->h;
5357ee01dbb2SDamon Ding 	left_dst.y = dst_rect->y;
5358ee01dbb2SDamon Ding 	left_dst.h = dst_rect->h;
5359ee01dbb2SDamon Ding 	right_src.y = src_rect->y;
5360ee01dbb2SDamon Ding 	right_src.h = src_rect->h;
5361ee01dbb2SDamon Ding 	right_dst.y = dst_rect->y;
5362ee01dbb2SDamon Ding 	right_dst.h = dst_rect->h;
5363ee01dbb2SDamon Ding 
5364ee01dbb2SDamon Ding 	memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect));
5365ee01dbb2SDamon Ding 	memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect));
5366ee01dbb2SDamon Ding 	memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect));
5367ee01dbb2SDamon Ding 	memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect));
5368ee01dbb2SDamon Ding }
5369ee01dbb2SDamon Ding 
5370ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state)
5371ecc31b6eSAndy Yan {
5372ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5373ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
5374ecc31b6eSAndy Yan 	struct vop2_win_data *win_data;
5375ee01dbb2SDamon Ding 	struct vop2_win_data *splice_win_data;
5376ecc31b6eSAndy Yan 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
53771c9572c7SDamon Ding 	int ret;
5378ecc31b6eSAndy Yan 
5379ee01dbb2SDamon Ding 	if (cstate->crtc_rect.w > cstate->max_output.width) {
5380ecc31b6eSAndy Yan 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
5381ee01dbb2SDamon Ding 		       cstate->crtc_rect.w, cstate->max_output.width);
5382ecc31b6eSAndy Yan 		return -EINVAL;
5383ecc31b6eSAndy Yan 	}
5384ecc31b6eSAndy Yan 
5385ecc31b6eSAndy Yan 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
5386ecc31b6eSAndy Yan 	if (!win_data) {
5387ecc31b6eSAndy Yan 		printf("invalid win id %d\n", primary_plane_id);
5388ecc31b6eSAndy Yan 		return -ENODEV;
5389ecc31b6eSAndy Yan 	}
5390ecc31b6eSAndy Yan 
53915fa6e665SDamon Ding 	/* ignore some plane register according vop3 esmart lb mode */
53925fa6e665SDamon Ding 	if (vop3_ignore_plane(vop2, win_data))
53935fa6e665SDamon Ding 		return -EACCES;
53945fa6e665SDamon Ding 
5395a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) {
5396b6ba80b4SDamon Ding 		if (vop2_power_domain_on(vop2, win_data->pd_id))
5397b6ba80b4SDamon Ding 			printf("open vp%d plane pd fail\n", cstate->crtc_id);
5398b6ba80b4SDamon Ding 	}
5399b6ba80b4SDamon Ding 
5400ee01dbb2SDamon Ding 	if (cstate->splice_mode) {
5401ee01dbb2SDamon Ding 		if (win_data->splice_win_id) {
5402ee01dbb2SDamon Ding 			splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id);
5403ee01dbb2SDamon Ding 			splice_win_data->splice_mode_right = true;
5404b6ba80b4SDamon Ding 
5405b6ba80b4SDamon Ding 			if (vop2_power_domain_on(vop2, splice_win_data->pd_id))
5406b6ba80b4SDamon Ding 				printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id);
5407b6ba80b4SDamon Ding 
5408ee01dbb2SDamon Ding 			vop2_calc_display_rect_for_splice(state);
5409ee01dbb2SDamon Ding 			if (win_data->type == CLUSTER_LAYER)
5410ee01dbb2SDamon Ding 				vop2_set_cluster_win(state, splice_win_data);
5411ee01dbb2SDamon Ding 			else
5412ee01dbb2SDamon Ding 				vop2_set_smart_win(state, splice_win_data);
5413ee01dbb2SDamon Ding 		} else {
5414ee01dbb2SDamon Ding 			printf("ERROR: splice mode is unsupported by plane %s\n",
541527cec8e2SDamon Ding 			       vop2_plane_id_to_string(primary_plane_id));
5416ee01dbb2SDamon Ding 			return -EINVAL;
5417ee01dbb2SDamon Ding 		}
5418ee01dbb2SDamon Ding 	}
5419ee01dbb2SDamon Ding 
5420ecc31b6eSAndy Yan 	if (win_data->type == CLUSTER_LAYER)
54211c9572c7SDamon Ding 		ret = vop2_set_cluster_win(state, win_data);
5422ecc31b6eSAndy Yan 	else
54231c9572c7SDamon Ding 		ret = vop2_set_smart_win(state, win_data);
54241c9572c7SDamon Ding 	if (ret)
54251c9572c7SDamon Ding 		return ret;
54268895aec1SSandy Huang 
54278895aec1SSandy Huang 	printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
542827cec8e2SDamon Ding 		cstate->crtc_id, vop2_plane_id_to_string(primary_plane_id),
5429ee01dbb2SDamon Ding 		cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h,
5430ee01dbb2SDamon Ding 		cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format,
54318895aec1SSandy Huang 		cstate->dma_addr);
54328895aec1SSandy Huang 
5433d0408543SAndy Yan 	return 0;
5434d0408543SAndy Yan }
5435d0408543SAndy Yan 
5436d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state)
5437d0408543SAndy Yan {
5438d0408543SAndy Yan 	return 0;
5439d0408543SAndy Yan }
5440d0408543SAndy Yan 
544112ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state)
544212ee5af0SDamon Ding {
544312ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
544412ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
544512ee5af0SDamon Ding 	struct vop2 *vop2 = cstate->private;
544612ee5af0SDamon Ding 	u8 dsc_id = cstate->dsc_id;
544712ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
544812ee5af0SDamon Ding 
544912ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
545012ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK,
545112ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
545212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK,
545312ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
545412ee5af0SDamon Ding 	} else {
545512ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK,
545612ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
545712ee5af0SDamon Ding 	}
545812ee5af0SDamon Ding }
545912ee5af0SDamon Ding 
5460d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state)
5461d0408543SAndy Yan {
5462d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5463d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
546452ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5465ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5466d0408543SAndy Yan 
5467d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5468d0408543SAndy Yan 			STANDBY_EN_SHIFT, 0, false);
5469ee01dbb2SDamon Ding 
5470ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5471ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5472ee01dbb2SDamon Ding 
5473d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5474d0408543SAndy Yan 
547512ee5af0SDamon Ding 	if (cstate->dsc_enable)
547612ee5af0SDamon Ding 		vop2_dsc_cfg_done(state);
547712ee5af0SDamon Ding 
54780675a2a4SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
54790675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
54800675a2a4SDamon Ding 				MCU_HOLD_MODE_SHIFT, 0, false);
54810675a2a4SDamon Ding 
5482d0408543SAndy Yan 	return 0;
5483d0408543SAndy Yan }
5484d0408543SAndy Yan 
5485efa01fe4SZhang Yubing static int rk3588_vop2_post_enable(struct display_state *state)
5486efa01fe4SZhang Yubing {
5487efa01fe4SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
5488efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5489efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5490efa01fe4SZhang Yubing 	int output_if = conn_state->output_if;
5491efa01fe4SZhang Yubing 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5492efa01fe4SZhang Yubing 	int ret, val;
5493efa01fe4SZhang Yubing 
5494efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP0)
5495efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
5496efa01fe4SZhang Yubing 				1, false);
5497efa01fe4SZhang Yubing 
5498efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP1)
5499efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT,
5500efa01fe4SZhang Yubing 				1, false);
5501efa01fe4SZhang Yubing 
5502efa01fe4SZhang Yubing 	if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) {
5503efa01fe4SZhang Yubing 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5504efa01fe4SZhang Yubing 		ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5505efa01fe4SZhang Yubing 					 val & BIT(cstate->crtc_id), 50 * 1000);
5506efa01fe4SZhang Yubing 		if (ret)
5507efa01fe4SZhang Yubing 			printf("%s wait cfg done timeout\n", __func__);
55080686a6a6SZhang Yubing 
55090686a6a6SZhang Yubing 		if (cstate->dclk_rst.dev) {
55100686a6a6SZhang Yubing 			reset_assert(&cstate->dclk_rst);
55110686a6a6SZhang Yubing 			udelay(20);
55120686a6a6SZhang Yubing 			reset_deassert(&cstate->dclk_rst);
55130686a6a6SZhang Yubing 		}
5514efa01fe4SZhang Yubing 	}
5515efa01fe4SZhang Yubing 
5516efa01fe4SZhang Yubing 	return 0;
5517efa01fe4SZhang Yubing }
5518efa01fe4SZhang Yubing 
5519efa01fe4SZhang Yubing static int rk3576_vop2_post_enable(struct display_state *state)
5520efa01fe4SZhang Yubing {
5521efa01fe4SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
5522efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5523efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5524efa01fe4SZhang Yubing 	int output_if = conn_state->output_if;
5525efa01fe4SZhang Yubing 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5526efa01fe4SZhang Yubing 	int ret, val;
5527efa01fe4SZhang Yubing 
5528efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP0)
5529efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
5530efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5531efa01fe4SZhang Yubing 
5532efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP1)
5533efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
5534efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5535efa01fe4SZhang Yubing 
5536efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP2)
5537efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
5538efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5539efa01fe4SZhang Yubing 
5540efa01fe4SZhang Yubing 	if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
5541efa01fe4SZhang Yubing 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5542efa01fe4SZhang Yubing 		ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5543efa01fe4SZhang Yubing 					 val & BIT(cstate->crtc_id), 50 * 1000);
5544efa01fe4SZhang Yubing 		if (ret)
5545efa01fe4SZhang Yubing 			printf("%s wait cfg done timeout\n", __func__);
55460686a6a6SZhang Yubing 
55470686a6a6SZhang Yubing 		if (cstate->dclk_rst.dev) {
55480686a6a6SZhang Yubing 			reset_assert(&cstate->dclk_rst);
55490686a6a6SZhang Yubing 			udelay(20);
55500686a6a6SZhang Yubing 			reset_deassert(&cstate->dclk_rst);
55510686a6a6SZhang Yubing 		}
5552efa01fe4SZhang Yubing 	}
5553efa01fe4SZhang Yubing 
5554efa01fe4SZhang Yubing 	return 0;
5555efa01fe4SZhang Yubing }
5556efa01fe4SZhang Yubing 
5557efa01fe4SZhang Yubing static int rockchip_vop2_post_enable(struct display_state *state)
5558efa01fe4SZhang Yubing {
5559efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5560efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5561efa01fe4SZhang Yubing 
5562efa01fe4SZhang Yubing 	if (vop2->version == VOP_VERSION_RK3588)
5563efa01fe4SZhang Yubing 		rk3588_vop2_post_enable(state);
5564efa01fe4SZhang Yubing 	else if (vop2->version == VOP_VERSION_RK3576)
5565efa01fe4SZhang Yubing 		rk3576_vop2_post_enable(state);
5566efa01fe4SZhang Yubing 
5567efa01fe4SZhang Yubing 	return 0;
5568efa01fe4SZhang Yubing }
5569efa01fe4SZhang Yubing 
5570d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state)
5571d0408543SAndy Yan {
5572d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5573d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
557452ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5575ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5576d0408543SAndy Yan 
5577d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5578d0408543SAndy Yan 			STANDBY_EN_SHIFT, 1, false);
5579ee01dbb2SDamon Ding 
5580ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5581ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5582ee01dbb2SDamon Ding 
5583d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5584d0408543SAndy Yan 
5585d0408543SAndy Yan 	return 0;
5586d0408543SAndy Yan }
5587d0408543SAndy Yan 
5588ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane)
5589ee008497SSandy Huang {
5590ee008497SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
5591ee008497SSandy Huang 	struct vop2 *vop2 = cstate->private;
5592ee008497SSandy Huang 	int i = 0;
5593ee008497SSandy Huang 	int correct_cursor_plane = -1;
5594ee008497SSandy Huang 	int plane_type = -1;
5595ee008497SSandy Huang 
5596ee008497SSandy Huang 	if (cursor_plane < 0)
5597ee008497SSandy Huang 		return -1;
5598ee008497SSandy Huang 
5599ee008497SSandy Huang 	if (plane_mask & (1 << cursor_plane))
5600ee008497SSandy Huang 		return cursor_plane;
5601ee008497SSandy Huang 
5602ee008497SSandy Huang 	/* Get current cursor plane type */
5603ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
5604ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_id == cursor_plane) {
5605ee008497SSandy Huang 			plane_type = vop2->data->plane_table[i].plane_type;
5606ee008497SSandy Huang 			break;
5607ee008497SSandy Huang 		}
5608ee008497SSandy Huang 	}
5609ee008497SSandy Huang 
5610ee008497SSandy Huang 	/* Get the other same plane type plane id */
5611ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
5612ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_type == plane_type &&
5613ee008497SSandy Huang 		    vop2->data->plane_table[i].plane_id != cursor_plane) {
5614ee008497SSandy Huang 			correct_cursor_plane = vop2->data->plane_table[i].plane_id;
5615ee008497SSandy Huang 			break;
5616ee008497SSandy Huang 		}
5617ee008497SSandy Huang 	}
5618ee008497SSandy Huang 
5619ee008497SSandy Huang 	/* To check whether the new correct_cursor_plane is attach to current vp */
5620ee008497SSandy Huang 	if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) {
5621ee008497SSandy Huang 		printf("error: faild to find correct plane as cursor plane\n");
5622ee008497SSandy Huang 		return -1;
5623ee008497SSandy Huang 	}
5624ee008497SSandy Huang 
5625ee008497SSandy Huang 	printf("vp%d adjust cursor plane from %d to %d\n",
5626ee008497SSandy Huang 	       cstate->crtc_id, cursor_plane, correct_cursor_plane);
5627ee008497SSandy Huang 
5628ee008497SSandy Huang 	return correct_cursor_plane;
5629ee008497SSandy Huang }
5630ee008497SSandy Huang 
5631b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
5632b0989546SSandy Huang {
5633b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
5634b0989546SSandy Huang 	struct vop2 *vop2 = cstate->private;
5635b0989546SSandy Huang 	ofnode vp_node;
5636b0989546SSandy Huang 	struct device_node *port_parent_node = cstate->ports_node;
5637b0989546SSandy Huang 	static bool vop_fix_dts;
5638b0989546SSandy Huang 	const char *path;
5639b0989546SSandy Huang 	u32 plane_mask = 0;
5640b0989546SSandy Huang 	int vp_id = 0;
5641ee008497SSandy Huang 	int cursor_plane_id = -1;
5642b0989546SSandy Huang 
56435fa6e665SDamon Ding 	if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528)
5644b0989546SSandy Huang 		return 0;
5645b0989546SSandy Huang 
5646b0989546SSandy Huang 	ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
5647b0989546SSandy Huang 		path = vp_node.np->full_name;
5648b0989546SSandy Huang 		plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
5649b0989546SSandy Huang 
56508b1fe597SSandy Huang 		if (cstate->crtc->assign_plane)
56518b1fe597SSandy Huang 			continue;
5652ee008497SSandy Huang 		cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask,
5653ee008497SSandy Huang 								 cstate->crtc->vps[vp_id].cursor_plane);
5654ee008497SSandy Huang 		printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
5655b0989546SSandy Huang 		       vp_id, plane_mask,
5656ee008497SSandy Huang 		       vop2->vp_plane_mask[vp_id].primary_plane_id,
5657ee008497SSandy Huang 		       cursor_plane_id);
5658b0989546SSandy Huang 
5659b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
5660b0989546SSandy Huang 				     plane_mask, 1);
5661b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
5662b0989546SSandy Huang 				     vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
5663ee008497SSandy Huang 		if (cursor_plane_id >= 0)
5664ee008497SSandy Huang 			do_fixup_by_path_u32(blob, path, "cursor-win-id",
5665ee008497SSandy Huang 					     cursor_plane_id, 1);
5666b0989546SSandy Huang 		vp_id++;
5667b0989546SSandy Huang 	}
5668b0989546SSandy Huang 
5669b0989546SSandy Huang 	vop_fix_dts = true;
5670b0989546SSandy Huang 
5671b0989546SSandy Huang 	return 0;
5672b0989546SSandy Huang }
5673b0989546SSandy Huang 
5674820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state)
5675820a5c17SDamon Ding {
5676820a5c17SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5677820a5c17SDamon Ding 	struct rockchip_crtc *crtc = cstate->crtc;
5678820a5c17SDamon Ding 
5679820a5c17SDamon Ding 	if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) {
5680820a5c17SDamon Ding 		printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id);
5681820a5c17SDamon Ding 		return -ENOTSUPP;
5682820a5c17SDamon Ding 	}
5683820a5c17SDamon Ding 
5684820a5c17SDamon Ding 	if (cstate->splice_mode) {
5685820a5c17SDamon Ding 		crtc->splice_mode = true;
5686820a5c17SDamon Ding 		crtc->splice_crtc_id = cstate->splice_crtc_id;
5687820a5c17SDamon Ding 	}
5688820a5c17SDamon Ding 
5689820a5c17SDamon Ding 	return 0;
5690820a5c17SDamon Ding }
5691820a5c17SDamon Ding 
569222007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state)
569322007755SDamon Ding {
569422007755SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
569522007755SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
569622007755SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
569722007755SDamon Ding 	struct videomode vm;
569822007755SDamon Ding 
569922007755SDamon Ding 	drm_display_mode_to_videomode(mode, &vm);
570022007755SDamon Ding 
570122007755SDamon Ding 	if (vm.hactive < 32 || vm.vactive < 32 ||
570222007755SDamon Ding 	    (vm.hfront_porch * vm.hsync_len * vm.hback_porch *
570322007755SDamon Ding 	     vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) {
570422007755SDamon Ding 		printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id);
570522007755SDamon Ding 		return -EINVAL;
570622007755SDamon Ding 	}
570722007755SDamon Ding 
570822007755SDamon Ding 	return 0;
570922007755SDamon Ding }
571022007755SDamon Ding 
5711b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state)
5712b02eb70bSDamon Ding {
5713b02eb70bSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
57140e19fecdSDamon Ding 	struct rockchip_connector *conn = conn_state->connector;
5715b02eb70bSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
5716b02eb70bSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5717b02eb70bSDamon Ding 	struct vop2 *vop2 = cstate->private;
5718b02eb70bSDamon Ding 
57190e19fecdSDamon Ding 	if (conn_state->secondary) {
57200e19fecdSDamon Ding 		if (!(conn->dual_channel_mode &&
57210e19fecdSDamon Ding 		      conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) &&
57222b992d78SDamon Ding 		    conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS)
57232b992d78SDamon Ding 			drm_mode_convert_to_split_mode(mode);
57240e19fecdSDamon Ding 	}
57252b992d78SDamon Ding 
57261b5811e7SDamon Ding 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
5727b02eb70bSDamon Ding 
5728243f0077SDamon Ding 	/*
5729640211a0SDamon Ding 	 * For RK3568 and RK3588, the hactive of video timing must
5730640211a0SDamon Ding 	 * be 4-pixel aligned.
5731640211a0SDamon Ding 	 */
5732640211a0SDamon Ding 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) {
5733640211a0SDamon Ding 		if (mode->crtc_hdisplay % 4) {
5734640211a0SDamon Ding 			int old_hdisplay = mode->crtc_hdisplay;
5735640211a0SDamon Ding 			int align = 4 - (mode->crtc_hdisplay % 4);
5736640211a0SDamon Ding 
5737640211a0SDamon Ding 			mode->crtc_hdisplay += align;
5738640211a0SDamon Ding 			mode->crtc_hsync_start += align;
5739640211a0SDamon Ding 			mode->crtc_hsync_end += align;
5740640211a0SDamon Ding 			mode->crtc_htotal += align;
5741640211a0SDamon Ding 
5742640211a0SDamon Ding 			printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n",
5743640211a0SDamon Ding 			       old_hdisplay, mode->hdisplay);
5744640211a0SDamon Ding 		}
5745640211a0SDamon Ding 	}
5746640211a0SDamon Ding 
5747640211a0SDamon Ding 	/*
5748243f0077SDamon Ding 	 * For RK3576 YUV420 output, hden signal introduce one cycle delay,
5749243f0077SDamon Ding 	 * so we need to adjust hfp and hbp to compatible with this design.
5750243f0077SDamon Ding 	 */
5751243f0077SDamon Ding 	if (vop2->version == VOP_VERSION_RK3576 &&
5752243f0077SDamon Ding 	    conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
5753243f0077SDamon Ding 		mode->crtc_hsync_start += 2;
5754243f0077SDamon Ding 		mode->crtc_hsync_end += 2;
5755243f0077SDamon Ding 	}
5756243f0077SDamon Ding 
5757b02eb70bSDamon Ding 	if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656)
5758b02eb70bSDamon Ding 		mode->crtc_clock *= 2;
5759b02eb70bSDamon Ding 
5760b02eb70bSDamon Ding 	/*
5761b02eb70bSDamon Ding 	 * For RK3528, the path of CVBS output is like:
5762b02eb70bSDamon Ding 	 * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
5763b02eb70bSDamon Ding 	 * The vop2 dclk should be four times crtc_clock for CVBS sampling
5764b02eb70bSDamon Ding 	 * clock needs.
5765b02eb70bSDamon Ding 	 */
5766b02eb70bSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656)
5767b02eb70bSDamon Ding 		mode->crtc_clock *= 4;
5768b02eb70bSDamon Ding 
57694d64cedbSDamon Ding 	mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format);
57704d64cedbSDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
57714d64cedbSDamon Ding 		mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1;
57720675a2a4SDamon Ding 
5773b02eb70bSDamon Ding 	return 0;
5774b02eb70bSDamon Ding }
5775b02eb70bSDamon Ding 
57764c765862SDamon Ding #define FRAC_16_16(mult, div)	(((mult) << 16) / (div))
57774c765862SDamon Ding 
57784c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state)
57794c765862SDamon Ding {
57804c765862SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
57814c765862SDamon Ding 	struct vop2 *vop2 = cstate->private;
57824c765862SDamon Ding 	struct display_rect *src = &cstate->src_rect;
57834c765862SDamon Ding 	struct display_rect *dst = &cstate->crtc_rect;
57844c765862SDamon Ding 	struct vop2_win_data *win_data;
57854c765862SDamon Ding 	int min_scale, max_scale;
57864c765862SDamon Ding 	int hscale, vscale;
57874c765862SDamon Ding 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
57884c765862SDamon Ding 
57894c765862SDamon Ding 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
57904c765862SDamon Ding 	if (!win_data) {
57914c765862SDamon Ding 		printf("ERROR: invalid win id %d\n", primary_plane_id);
57924c765862SDamon Ding 		return -ENODEV;
57934c765862SDamon Ding 	}
57944c765862SDamon Ding 
57954c765862SDamon Ding 	min_scale = FRAC_16_16(1, win_data->max_downscale_factor);
57964c765862SDamon Ding 	max_scale = FRAC_16_16(win_data->max_upscale_factor, 1);
57974c765862SDamon Ding 
57984c765862SDamon Ding 	hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale);
57994c765862SDamon Ding 	vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale);
58004c765862SDamon Ding 	if (hscale < 0 || vscale < 0) {
58014c765862SDamon Ding 		printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name);
58024c765862SDamon Ding 		return -ERANGE;
58034c765862SDamon Ding 		}
58044c765862SDamon Ding 
58054c765862SDamon Ding 	return 0;
58064c765862SDamon Ding }
5807337d1c13SDamon Ding 
58088e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state)
58098e7ef808SDamon Ding {
5810d8e7f4a5SSandy Huang 	__maybe_unused struct connector_state *conn_state = &state->conn_state;
58118e7ef808SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
58128e7ef808SDamon Ding 	struct vop2 *vop2 = cstate->private;
58138e7ef808SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
58148e7ef808SDamon Ding 	int val = 0;
58158e7ef808SDamon Ding 	int ret = 0;
58168e7ef808SDamon Ding 
58178e7ef808SDamon Ding 	ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val,
58188e7ef808SDamon Ding 				 (val >> EDPI_WMS_FS) & 0x1, 50 * 1000);
58198e7ef808SDamon Ding 	if (!ret) {
5820d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
58218e7ef808SDamon Ding 		ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
58228e7ef808SDamon Ding 					 !val, 50 * 1000);
58238e7ef808SDamon Ding 		if (!ret) {
58248e7ef808SDamon Ding 			ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
58258e7ef808SDamon Ding 						 val, 50 * 1000);
58268e7ef808SDamon Ding 			if (!ret) {
58278e7ef808SDamon Ding 				vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
58288e7ef808SDamon Ding 						EN_MASK, EDPI_WMS_FS, 1, false);
58298e7ef808SDamon Ding 			} else {
58308e7ef808SDamon Ding 				printf("ERROR: vp%d wait for active TE signal timeout\n",
58318e7ef808SDamon Ding 				       cstate->crtc_id);
58328e7ef808SDamon Ding 				return ret;
58338e7ef808SDamon Ding 			}
58348e7ef808SDamon Ding 		} else {
58358e7ef808SDamon Ding 			printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id);
58368e7ef808SDamon Ding 			return ret;
58378e7ef808SDamon Ding 		}
5838d8e7f4a5SSandy Huang #endif
58398e7ef808SDamon Ding 	} else {
58408e7ef808SDamon Ding 		printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id);
58418e7ef808SDamon Ding 		return ret;
58428e7ef808SDamon Ding 	}
58438e7ef808SDamon Ding 
58448e7ef808SDamon Ding 	return 0;
58458e7ef808SDamon Ding }
58468e7ef808SDamon Ding 
584772388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state)
584872388c26SDamon Ding {
584972388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
585072388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
585172388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
585272388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
5853a552a69cSDamon Ding 	u32 len = 128;
585472388c26SDamon Ding 	u32 n, i, j;
585572388c26SDamon Ding 	u32 base;
585672388c26SDamon Ding 
585772388c26SDamon Ding 	if (!cstate->crtc->active)
585872388c26SDamon Ding 		return -EINVAL;
585972388c26SDamon Ding 
586072388c26SDamon Ding 	n = vop2_data->dump_regs_size;
586172388c26SDamon Ding 	for (i = 0; i < n; i++) {
586272388c26SDamon Ding 		base = regs[i].offset;
5863a552a69cSDamon Ding 		len = 128;
5864a552a69cSDamon Ding 		if (regs[i].size)
5865a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
586672388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
5867a552a69cSDamon Ding 		for (j = 0; j < len;) {
586872388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
586972388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
587072388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
587172388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
587272388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
587372388c26SDamon Ding 			j += 4;
587472388c26SDamon Ding 		}
587572388c26SDamon Ding 	}
587672388c26SDamon Ding 
587772388c26SDamon Ding 	return 0;
587872388c26SDamon Ding }
587972388c26SDamon Ding 
588072388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state)
588172388c26SDamon Ding {
588272388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
588372388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
588472388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
588572388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
5886a552a69cSDamon Ding 	u32 len = 128;
588772388c26SDamon Ding 	u32 n, i, j;
588872388c26SDamon Ding 	u32 base;
588972388c26SDamon Ding 	bool enable_state;
589072388c26SDamon Ding 
589172388c26SDamon Ding 	if (!cstate->crtc->active)
589272388c26SDamon Ding 		return -EINVAL;
589372388c26SDamon Ding 
589472388c26SDamon Ding 	n = vop2_data->dump_regs_size;
589572388c26SDamon Ding 	for (i = 0; i < n; i++) {
589672388c26SDamon Ding 		if (regs[i].state_mask) {
589772388c26SDamon Ding 			enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) &
589872388c26SDamon Ding 				       regs[i].state_mask;
589972388c26SDamon Ding 			if (enable_state != regs[i].enable_state)
590072388c26SDamon Ding 				continue;
590172388c26SDamon Ding 		}
590272388c26SDamon Ding 
590372388c26SDamon Ding 		base = regs[i].offset;
5904a552a69cSDamon Ding 		len = 128;
5905a552a69cSDamon Ding 		if (regs[i].size)
5906a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
590772388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
5908a552a69cSDamon Ding 		for (j = 0; j < len;) {
590972388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
591072388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
591172388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
591272388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
591372388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
591472388c26SDamon Ding 			j += 4;
591572388c26SDamon Ding 		}
591672388c26SDamon Ding 	}
591772388c26SDamon Ding 
591872388c26SDamon Ding 	return 0;
591972388c26SDamon Ding }
592072388c26SDamon Ding 
59219c7848c3SDamon Ding static void rk3528_setup_win_dly(struct display_state *state, int crtc_id)
59229c7848c3SDamon Ding {
59239c7848c3SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
59249c7848c3SDamon Ding 	struct vop2 *vop2 = cstate->private;
59259c7848c3SDamon Ding 	struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id];
59269c7848c3SDamon Ding 	uint32_t dly = 0; /* For vop3, the default window delay is 0 */
59279c7848c3SDamon Ding 
59289c7848c3SDamon Ding 	switch (plane_mask->primary_plane_id) {
59299c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER0:
59309c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_CLUSTER0_CTRL, CLUSTER_DLY_NUM_MASK,
59319c7848c3SDamon Ding 				CLUSTER_DLY_NUM_SHIFT, dly, false);
59329c7848c3SDamon Ding 		break;
59339c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART0:
59349c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL, ESMART_DLY_NUM_MASK,
59359c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
59369c7848c3SDamon Ding 		break;
59379c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART1:
59389c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART1_CTRL, ESMART_DLY_NUM_MASK,
59399c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
59409c7848c3SDamon Ding 		break;
59419c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART2:
59429c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART2_CTRL, ESMART_DLY_NUM_MASK,
59439c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
59449c7848c3SDamon Ding 		break;
59459c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART3:
59469c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART3_CTRL, ESMART_DLY_NUM_MASK,
59479c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
59489c7848c3SDamon Ding 		break;
59499c7848c3SDamon Ding 	}
59509c7848c3SDamon Ding }
59519c7848c3SDamon Ding 
5952b7195f56SDamon Ding static void rk3528_setup_overlay(struct display_state *state)
5953b7195f56SDamon Ding {
5954b7195f56SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5955b7195f56SDamon Ding 	struct vop2 *vop2 = cstate->private;
5956b7195f56SDamon Ding 	struct vop2_win_data *win_data;
5957b7195f56SDamon Ding 	int i;
5958b7195f56SDamon Ding 	u32 offset = 0;
5959b7195f56SDamon Ding 	u8 shift = 0;
5960b7195f56SDamon Ding 
5961b7195f56SDamon Ding 	/* init the layer sel value to 0xff(Disable layer) */
5962b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
5963b7195f56SDamon Ding 		offset = 0x100 * i;
5964b7195f56SDamon Ding 		vop2_writel(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 0xffffffff);
5965b7195f56SDamon Ding 	}
5966b7195f56SDamon Ding 
5967b7195f56SDamon Ding 	/* layer sel win id */
5968b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
5969b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
5970b7195f56SDamon Ding 			offset = 0x100 * i;
5971b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
5972b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset,
5973b7195f56SDamon Ding 					LAYER_SEL_MASK, 0, win_data->layer_sel_win_id[i], false);
5974b7195f56SDamon Ding 		}
5975b7195f56SDamon Ding 	}
5976b7195f56SDamon Ding 
5977b7195f56SDamon Ding 	/* win sel port */
5978b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
5979b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
5980b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
5981b7195f56SDamon Ding 			shift = win_data->win_sel_port_offset * 2;
5982b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL,
5983b7195f56SDamon Ding 					LAYER_SEL_PORT_MASK, shift, i, false);
5984b7195f56SDamon Ding 		}
5985b7195f56SDamon Ding 	}
5986b7195f56SDamon Ding }
5987b7195f56SDamon Ding 
59889c7848c3SDamon Ding static void rk3568_setup_win_dly(struct display_state *state, int crtc_id)
59899c7848c3SDamon Ding {
59909c7848c3SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
59919c7848c3SDamon Ding 	struct vop2 *vop2 = cstate->private;
59929c7848c3SDamon Ding 	struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id];
59939c7848c3SDamon Ding 	struct vop2_win_data *win_data;
59949c7848c3SDamon Ding 	uint32_t dly;
59959c7848c3SDamon Ding 
59969c7848c3SDamon Ding 	win_data = vop2_find_win_by_phys_id(vop2, plane_mask->primary_plane_id);
59979c7848c3SDamon Ding 	dly = win_data->dly[VOP2_DLY_MODE_DEFAULT];
59989c7848c3SDamon Ding 	if (win_data->type == CLUSTER_LAYER)
59999c7848c3SDamon Ding 		dly |= dly << 8;
60009c7848c3SDamon Ding 
60019c7848c3SDamon Ding 	switch (plane_mask->primary_plane_id) {
60029c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER0:
60039c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
60049c7848c3SDamon Ding 				CLUSTER0_DLY_NUM_SHIFT, dly, false);
60059c7848c3SDamon Ding 		break;
60069c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER1:
60079c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
60089c7848c3SDamon Ding 				CLUSTER1_DLY_NUM_SHIFT, dly, false);
60099c7848c3SDamon Ding 		break;
60109c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER2:
60119c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
60129c7848c3SDamon Ding 				CLUSTER0_DLY_NUM_SHIFT, dly, false);
60139c7848c3SDamon Ding 		break;
60149c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER3:
60159c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
60169c7848c3SDamon Ding 				CLUSTER1_DLY_NUM_SHIFT, dly, false);
60179c7848c3SDamon Ding 		break;
60189c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART0:
60199c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
60209c7848c3SDamon Ding 				ESMART0_DLY_NUM_SHIFT, dly, false);
60219c7848c3SDamon Ding 		break;
60229c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART1:
60239c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
60249c7848c3SDamon Ding 				ESMART1_DLY_NUM_SHIFT, dly, false);
60259c7848c3SDamon Ding 		break;
60269c7848c3SDamon Ding 	case ROCKCHIP_VOP2_SMART0:
60279c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART2:
60289c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
60299c7848c3SDamon Ding 				SMART0_DLY_NUM_SHIFT, dly, false);
60309c7848c3SDamon Ding 		break;
60319c7848c3SDamon Ding 	case ROCKCHIP_VOP2_SMART1:
60329c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART3:
60339c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
60349c7848c3SDamon Ding 				SMART1_DLY_NUM_SHIFT, dly, false);
60359c7848c3SDamon Ding 		break;
60369c7848c3SDamon Ding 	}
60379c7848c3SDamon Ding }
60389c7848c3SDamon Ding 
6039b7195f56SDamon Ding static void rk3568_setup_overlay(struct display_state *state)
6040b7195f56SDamon Ding {
6041b7195f56SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
6042b7195f56SDamon Ding 	struct vop2 *vop2 = cstate->private;
6043b7195f56SDamon Ding 	struct vop2_win_data *win_data;
6044b7195f56SDamon Ding 	int layer_phy_id = 0;
6045b7195f56SDamon Ding 	int total_used_layer = 0;
6046b7195f56SDamon Ding 	int port_mux = 0;
6047b7195f56SDamon Ding 	int i, j;
6048b7195f56SDamon Ding 	u32 layer_nr = 0;
6049b7195f56SDamon Ding 	u8 shift = 0;
6050b7195f56SDamon Ding 
6051b7195f56SDamon Ding 	/* layer sel win id */
6052b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6053b7195f56SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6054b7195f56SDamon Ding 		for (j = 0; j < layer_nr; j++) {
6055b7195f56SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6056b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6057b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
6058b7195f56SDamon Ding 					shift, win_data->layer_sel_win_id[i], false);
6059b7195f56SDamon Ding 			shift += 4;
6060b7195f56SDamon Ding 		}
6061b7195f56SDamon Ding 	}
6062b7195f56SDamon Ding 
6063b7195f56SDamon Ding 	/* win sel port */
6064b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6065b7195f56SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6066b7195f56SDamon Ding 		for (j = 0; j < layer_nr; j++) {
6067b7195f56SDamon Ding 			if (!vop2->vp_plane_mask[i].attached_layers[j])
6068b7195f56SDamon Ding 				continue;
6069b7195f56SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6070b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6071b7195f56SDamon Ding 			shift = win_data->win_sel_port_offset * 2;
6072b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
6073b7195f56SDamon Ding 					LAYER_SEL_PORT_SHIFT + shift, i, false);
6074b7195f56SDamon Ding 		}
6075b7195f56SDamon Ding 	}
6076b7195f56SDamon Ding 
6077b7195f56SDamon Ding 	/**
6078b7195f56SDamon Ding 	 * port mux config
6079b7195f56SDamon Ding 	 */
6080b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6081b7195f56SDamon Ding 		shift = i * 4;
6082b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].attached_layers_nr) {
6083b7195f56SDamon Ding 			total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
6084b7195f56SDamon Ding 			port_mux = total_used_layer - 1;
6085b7195f56SDamon Ding 		} else {
6086b7195f56SDamon Ding 			port_mux = 8;
6087b7195f56SDamon Ding 		}
6088b7195f56SDamon Ding 
6089b7195f56SDamon Ding 		if (i == vop2->data->nr_vps - 1)
6090b7195f56SDamon Ding 			port_mux = vop2->data->nr_mixers;
6091b7195f56SDamon Ding 
6092b7195f56SDamon Ding 		cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
6093b7195f56SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
6094b7195f56SDamon Ding 				PORT_MUX_SHIFT + shift, port_mux, false);
6095b7195f56SDamon Ding 	}
6096b7195f56SDamon Ding }
6097b7195f56SDamon Ding 
60989c7848c3SDamon Ding static void rk3576_setup_win_dly(struct display_state *state, int crtc_id)
60999c7848c3SDamon Ding {
61009c7848c3SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
61019c7848c3SDamon Ding 	struct vop2 *vop2 = cstate->private;
61029c7848c3SDamon Ding 	struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id];
61039c7848c3SDamon Ding 	uint32_t dly = 0; /* For vop3, the default window delay is 0 */
61049c7848c3SDamon Ding 
61059c7848c3SDamon Ding 	switch (plane_mask->primary_plane_id) {
61069c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER0:
61079c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER0_DLY_NUM, CLUSTER_DLY_NUM_MASK,
61089c7848c3SDamon Ding 				CLUSTER_DLY_NUM_SHIFT, dly, false);
61099c7848c3SDamon Ding 		break;
61109c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER1:
61119c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER1_DLY_NUM, CLUSTER_DLY_NUM_MASK,
61129c7848c3SDamon Ding 				CLUSTER_DLY_NUM_SHIFT, dly, false);
61139c7848c3SDamon Ding 		break;
61149c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART0:
61159c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM, ESMART_DLY_NUM_MASK,
61169c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
61179c7848c3SDamon Ding 		break;
61189c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART1:
61199c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART1_DLY_NUM, ESMART_DLY_NUM_MASK,
61209c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
61219c7848c3SDamon Ding 		break;
61229c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART2:
61239c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART2_DLY_NUM, ESMART_DLY_NUM_MASK,
61249c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
61259c7848c3SDamon Ding 		break;
61269c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART3:
61279c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART3_DLY_NUM, ESMART_DLY_NUM_MASK,
61289c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
61299c7848c3SDamon Ding 		break;
61309c7848c3SDamon Ding 	}
61319c7848c3SDamon Ding }
61329c7848c3SDamon Ding 
6133b7195f56SDamon Ding static void rk3576_setup_overlay(struct display_state *state)
6134b7195f56SDamon Ding {
6135b7195f56SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
6136b7195f56SDamon Ding 	struct vop2 *vop2 = cstate->private;
6137b7195f56SDamon Ding 	struct vop2_win_data *win_data;
6138b7195f56SDamon Ding 	int i;
6139b7195f56SDamon Ding 	u32 offset = 0;
6140b7195f56SDamon Ding 
6141b7195f56SDamon Ding 	/* layer sel win id */
6142b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6143b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6144b7195f56SDamon Ding 			offset = 0x100 * i;
6145b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6146b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, LAYER_SEL_MASK,
6147b7195f56SDamon Ding 					0, win_data->layer_sel_win_id[i], false);
6148b7195f56SDamon Ding 		}
6149b7195f56SDamon Ding 	}
6150b7195f56SDamon Ding }
6151b7195f56SDamon Ding 
615272388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = {
615372388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
615472388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
615572388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
615672388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
615772388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
615872388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
615972388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
616072388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
616172388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
616272388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
616372388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
616472388c26SDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
616572388c26SDamon Ding 	{ RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1},
616672388c26SDamon Ding };
616772388c26SDamon Ding 
61685fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
61695fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
61705fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
61715fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
61725fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
61735fa6e665SDamon Ding };
61745fa6e665SDamon Ding 
61755fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
61765fa6e665SDamon Ding 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
61775fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
61785fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
61795fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
61805fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
61815fa6e665SDamon Ding };
61825fa6e665SDamon Ding 
61835fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
61845fa6e665SDamon Ding 	{ /* one display policy for hdmi */
61855fa6e665SDamon Ding 		{/* main display */
6186ebbd144cSAlgea Cao 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
61875fa6e665SDamon Ding 			.attached_layers_nr = 4,
61885fa6e665SDamon Ding 			.attached_layers = {
61895fa6e665SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0,
61905fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2
61915fa6e665SDamon Ding 				},
61925fa6e665SDamon Ding 		},
61935fa6e665SDamon Ding 		{/* second display */},
61945fa6e665SDamon Ding 		{/* third  display */},
61955fa6e665SDamon Ding 		{/* fourth display */},
61965fa6e665SDamon Ding 	},
61975fa6e665SDamon Ding 
61985fa6e665SDamon Ding 	{ /* two display policy */
61995fa6e665SDamon Ding 		{/* main display */
6200ebbd144cSAlgea Cao 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
62015fa6e665SDamon Ding 			.attached_layers_nr = 3,
62025fa6e665SDamon Ding 			.attached_layers = {
62035fa6e665SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
62045fa6e665SDamon Ding 				},
62055fa6e665SDamon Ding 		},
62065fa6e665SDamon Ding 
62075fa6e665SDamon Ding 		{/* second display */
62085fa6e665SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
62095fa6e665SDamon Ding 			.attached_layers_nr = 2,
62105fa6e665SDamon Ding 			.attached_layers = {
62115fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
62125fa6e665SDamon Ding 				},
62135fa6e665SDamon Ding 		},
62145fa6e665SDamon Ding 		{/* third  display */},
62155fa6e665SDamon Ding 		{/* fourth display */},
62165fa6e665SDamon Ding 	},
62175fa6e665SDamon Ding 
62185fa6e665SDamon Ding 	{ /* one display policy for cvbs */
62195fa6e665SDamon Ding 		{/* main display */
62205fa6e665SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
62215fa6e665SDamon Ding 			.attached_layers_nr = 2,
62225fa6e665SDamon Ding 			.attached_layers = {
62235fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
62245fa6e665SDamon Ding 				},
62255fa6e665SDamon Ding 		},
62265fa6e665SDamon Ding 		{/* second display */},
62275fa6e665SDamon Ding 		{/* third  display */},
62285fa6e665SDamon Ding 		{/* fourth display */},
62295fa6e665SDamon Ding 	},
62305fa6e665SDamon Ding 
62315fa6e665SDamon Ding 	{/* reserved */},
62325fa6e665SDamon Ding };
62335fa6e665SDamon Ding 
62345fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = {
62355fa6e665SDamon Ding 	{
62365fa6e665SDamon Ding 		.name = "Esmart0",
62375fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
62385fa6e665SDamon Ding 		.type = ESMART_LAYER,
62395fa6e665SDamon Ding 		.win_sel_port_offset = 8,
62405fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 0xff, 0xff, 0xff },
62415fa6e665SDamon Ding 		.reg_offset = 0,
62425fa6e665SDamon Ding 		.axi_id = 0,
62435fa6e665SDamon Ding 		.axi_yrgb_id = 0x06,
62445fa6e665SDamon Ding 		.axi_uv_id = 0x07,
62455fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
62465fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62475fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
62485fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62495fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
62505fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
6251*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
62525fa6e665SDamon Ding 		.max_upscale_factor = 8,
62535fa6e665SDamon Ding 		.max_downscale_factor = 8,
62545fa6e665SDamon Ding 	},
62555fa6e665SDamon Ding 
62565fa6e665SDamon Ding 	{
62575fa6e665SDamon Ding 		.name = "Esmart1",
62585fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
62595fa6e665SDamon Ding 		.type = ESMART_LAYER,
62605fa6e665SDamon Ding 		.win_sel_port_offset = 10,
62615fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0xff, 0xff },
62625fa6e665SDamon Ding 		.reg_offset = 0x200,
62635fa6e665SDamon Ding 		.axi_id = 0,
62645fa6e665SDamon Ding 		.axi_yrgb_id = 0x08,
62655fa6e665SDamon Ding 		.axi_uv_id = 0x09,
62665fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
62675fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62685fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
62695fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62705fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
62715fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
6272*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
62735fa6e665SDamon Ding 		.max_upscale_factor = 8,
62745fa6e665SDamon Ding 		.max_downscale_factor = 8,
62755fa6e665SDamon Ding 	},
62765fa6e665SDamon Ding 
62775fa6e665SDamon Ding 	{
62785fa6e665SDamon Ding 		.name = "Esmart2",
62795fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
62805fa6e665SDamon Ding 		.type = ESMART_LAYER,
62815fa6e665SDamon Ding 		.win_sel_port_offset = 12,
62825fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 0, 0xff, 0xff },
62835fa6e665SDamon Ding 		.reg_offset = 0x400,
62845fa6e665SDamon Ding 		.axi_id = 0,
62855fa6e665SDamon Ding 		.axi_yrgb_id = 0x0a,
62865fa6e665SDamon Ding 		.axi_uv_id = 0x0b,
62875fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
62885fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62895fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
62905fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
62915fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
62925fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
6293*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
62945fa6e665SDamon Ding 		.max_upscale_factor = 8,
62955fa6e665SDamon Ding 		.max_downscale_factor = 8,
62965fa6e665SDamon Ding 	},
62975fa6e665SDamon Ding 
62985fa6e665SDamon Ding 	{
62995fa6e665SDamon Ding 		.name = "Esmart3",
63005fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
63015fa6e665SDamon Ding 		.type = ESMART_LAYER,
63025fa6e665SDamon Ding 		.win_sel_port_offset = 14,
63035fa6e665SDamon Ding 		.layer_sel_win_id = { 0xff, 1, 0xff, 0xff },
63045fa6e665SDamon Ding 		.reg_offset = 0x600,
63055fa6e665SDamon Ding 		.axi_id = 0,
63065fa6e665SDamon Ding 		.axi_yrgb_id = 0x0c,
63075fa6e665SDamon Ding 		.axi_uv_id = 0x0d,
63085fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
63095fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
63105fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
63115fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
63125fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
63135fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
6314*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP1),
63155fa6e665SDamon Ding 		.max_upscale_factor = 8,
63165fa6e665SDamon Ding 		.max_downscale_factor = 8,
63175fa6e665SDamon Ding 	},
63185fa6e665SDamon Ding 
63195fa6e665SDamon Ding 	{
63205fa6e665SDamon Ding 		.name = "Cluster0",
63215fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
63225fa6e665SDamon Ding 		.type = CLUSTER_LAYER,
63235fa6e665SDamon Ding 		.win_sel_port_offset = 0,
63245fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0xff, 0xff, 0xff },
63255fa6e665SDamon Ding 		.reg_offset = 0,
63265fa6e665SDamon Ding 		.axi_id = 0,
63275fa6e665SDamon Ding 		.axi_yrgb_id = 0x02,
63285fa6e665SDamon Ding 		.axi_uv_id = 0x03,
63295fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
63305fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
63315fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
63325fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
63335fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
63345fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
6335*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
63365fa6e665SDamon Ding 		.max_upscale_factor = 8,
63375fa6e665SDamon Ding 		.max_downscale_factor = 8,
63385fa6e665SDamon Ding 	},
63395fa6e665SDamon Ding };
63405fa6e665SDamon Ding 
63415fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = {
63425fa6e665SDamon Ding 	{
63436027c871SZhang Yubing 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM |
63446027c871SZhang Yubing 			   VOP_FEATURE_POST_CSC,
63455fa6e665SDamon Ding 		.max_output = {4096, 4096},
6346b05105abSDamon Ding 		.layer_mix_dly = 6,
6347b05105abSDamon Ding 		.hdr_mix_dly = 2,
6348b05105abSDamon Ding 		.win_dly = 8,
63495fa6e665SDamon Ding 	},
63505fa6e665SDamon Ding 	{
63515fa6e665SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
63525fa6e665SDamon Ding 		.max_output = {1920, 1080},
6353b05105abSDamon Ding 		.layer_mix_dly = 2,
6354b05105abSDamon Ding 		.hdr_mix_dly = 0,
6355b05105abSDamon Ding 		.win_dly = 8,
63565fa6e665SDamon Ding 	},
63575fa6e665SDamon Ding };
63585fa6e665SDamon Ding 
63599c7848c3SDamon Ding static const struct vop2_ops rk3528_vop_ops = {
63609c7848c3SDamon Ding 	.setup_win_dly = rk3528_setup_win_dly,
6361b7195f56SDamon Ding 	.setup_overlay = rk3528_setup_overlay,
63629c7848c3SDamon Ding };
63639c7848c3SDamon Ding 
63645fa6e665SDamon Ding const struct vop2_data rk3528_vop = {
63655fa6e665SDamon Ding 	.version = VOP_VERSION_RK3528,
63665fa6e665SDamon Ding 	.nr_vps = 2,
63675fa6e665SDamon Ding 	.vp_data = rk3528_vp_data,
63685fa6e665SDamon Ding 	.win_data = rk3528_win_data,
63695fa6e665SDamon Ding 	.plane_mask = rk3528_vp_plane_mask[0],
63705fa6e665SDamon Ding 	.plane_table = rk3528_plane_table,
63715fa6e665SDamon Ding 	.vp_primary_plane_order = rk3528_vp_primary_plane_order,
63725fa6e665SDamon Ding 	.nr_layers = 5,
63735fa6e665SDamon Ding 	.nr_mixers = 3,
63745fa6e665SDamon Ding 	.nr_gammas = 2,
63755fa6e665SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE,
637672388c26SDamon Ding 	.dump_regs = rk3528_dump_regs,
637772388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
63789c7848c3SDamon Ding 	.ops = &rk3528_vop_ops,
63799c7848c3SDamon Ding 
638072388c26SDamon Ding };
638172388c26SDamon Ding 
638272388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = {
638372388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
638472388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
638572388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
638672388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
638772388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
638872388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
638972388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
639072388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
639172388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
639272388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
63935fa6e665SDamon Ding };
63945fa6e665SDamon Ding 
6395452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
6396452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6397452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6398452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
6399452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
6400452afb13SDamon Ding };
6401452afb13SDamon Ding 
6402452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6403452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6404452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6405452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
6406452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
6407452afb13SDamon Ding };
6408452afb13SDamon Ding 
6409452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
6410452afb13SDamon Ding 	{ /* one display policy for hdmi */
6411452afb13SDamon Ding 		{/* main display */
6412452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6413452afb13SDamon Ding 			.attached_layers_nr = 4,
6414452afb13SDamon Ding 			.attached_layers = {
6415452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1,
6416452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART2,  ROCKCHIP_VOP2_ESMART3
6417452afb13SDamon Ding 				},
6418452afb13SDamon Ding 		},
6419452afb13SDamon Ding 		{/* second display */},
6420452afb13SDamon Ding 		{/* third  display */},
6421452afb13SDamon Ding 		{/* fourth display */},
6422452afb13SDamon Ding 	},
6423452afb13SDamon Ding 
6424452afb13SDamon Ding 	{ /* two display policy */
6425452afb13SDamon Ding 		{/* main display */
6426452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6427452afb13SDamon Ding 			.attached_layers_nr = 2,
6428452afb13SDamon Ding 			.attached_layers = {
6429452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
6430452afb13SDamon Ding 				},
6431452afb13SDamon Ding 		},
6432452afb13SDamon Ding 
6433452afb13SDamon Ding 		{/* second display */
6434452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6435452afb13SDamon Ding 			.attached_layers_nr = 2,
6436452afb13SDamon Ding 			.attached_layers = {
6437452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
6438452afb13SDamon Ding 				},
6439452afb13SDamon Ding 		},
6440452afb13SDamon Ding 		{/* third  display */},
6441452afb13SDamon Ding 		{/* fourth display */},
6442452afb13SDamon Ding 	},
6443452afb13SDamon Ding 
6444452afb13SDamon Ding 	{/* reserved */},
6445452afb13SDamon Ding };
6446452afb13SDamon Ding 
6447452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = {
6448452afb13SDamon Ding 	{
6449452afb13SDamon Ding 		.name = "Esmart0",
6450452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6451452afb13SDamon Ding 		.type = ESMART_LAYER,
6452452afb13SDamon Ding 		.win_sel_port_offset = 8,
6453452afb13SDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
6454452afb13SDamon Ding 		.reg_offset = 0,
6455452afb13SDamon Ding 		.axi_id = 0,
6456452afb13SDamon Ding 		.axi_yrgb_id = 0x02,
6457452afb13SDamon Ding 		.axi_uv_id = 0x03,
6458452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6459452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6460452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6461452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6462*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6463452afb13SDamon Ding 		.max_upscale_factor = 8,
6464452afb13SDamon Ding 		.max_downscale_factor = 8,
6465452afb13SDamon Ding 	},
6466452afb13SDamon Ding 
6467452afb13SDamon Ding 	{
6468452afb13SDamon Ding 		.name = "Esmart1",
6469452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6470452afb13SDamon Ding 		.type = ESMART_LAYER,
6471452afb13SDamon Ding 		.win_sel_port_offset = 10,
6472452afb13SDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
6473452afb13SDamon Ding 		.reg_offset = 0x200,
6474452afb13SDamon Ding 		.axi_id = 0,
6475452afb13SDamon Ding 		.axi_yrgb_id = 0x04,
6476452afb13SDamon Ding 		.axi_uv_id = 0x05,
6477452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6478452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6479452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6480452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6481*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6482452afb13SDamon Ding 		.max_upscale_factor = 8,
6483452afb13SDamon Ding 		.max_downscale_factor = 8,
6484452afb13SDamon Ding 	},
6485452afb13SDamon Ding 
6486452afb13SDamon Ding 	{
6487452afb13SDamon Ding 		.name = "Esmart2",
6488452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
6489452afb13SDamon Ding 		.type = ESMART_LAYER,
6490452afb13SDamon Ding 		.win_sel_port_offset = 12,
6491452afb13SDamon Ding 		.layer_sel_win_id = { 2, 2, 0xff, 0xff },
6492452afb13SDamon Ding 		.reg_offset = 0x400,
6493452afb13SDamon Ding 		.axi_id = 0,
6494452afb13SDamon Ding 		.axi_yrgb_id = 0x06,
6495452afb13SDamon Ding 		.axi_uv_id = 0x07,
6496452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6497452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6498452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6499452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6500*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6501452afb13SDamon Ding 		.max_upscale_factor = 8,
6502452afb13SDamon Ding 		.max_downscale_factor = 8,
6503452afb13SDamon Ding 	},
6504452afb13SDamon Ding 
6505452afb13SDamon Ding 	{
6506452afb13SDamon Ding 		.name = "Esmart3",
6507452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
6508452afb13SDamon Ding 		.type = ESMART_LAYER,
6509452afb13SDamon Ding 		.win_sel_port_offset = 14,
6510452afb13SDamon Ding 		.layer_sel_win_id = { 3, 3, 0xff, 0xff },
6511452afb13SDamon Ding 		.reg_offset = 0x600,
6512452afb13SDamon Ding 		.axi_id = 0,
6513452afb13SDamon Ding 		.axi_yrgb_id = 0x08,
6514452afb13SDamon Ding 		.axi_uv_id = 0x0d,
6515452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6516452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6517452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6518452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6519*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6520452afb13SDamon Ding 		.max_upscale_factor = 8,
6521452afb13SDamon Ding 		.max_downscale_factor = 8,
6522452afb13SDamon Ding 	},
6523452afb13SDamon Ding };
6524452afb13SDamon Ding 
6525452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = {
6526452afb13SDamon Ding 	{
6527452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6528452afb13SDamon Ding 		.max_output = {2048, 4096},
652953d536adSDamon Ding 		.win_dly = 6,
6530452afb13SDamon Ding 		.layer_mix_dly = 8,
6531452afb13SDamon Ding 	},
6532452afb13SDamon Ding 	{
6533452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6534452afb13SDamon Ding 		.max_output = {2048, 1080},
6535452afb13SDamon Ding 		.win_dly = 8,
6536452afb13SDamon Ding 		.layer_mix_dly = 8,
6537452afb13SDamon Ding 	},
6538452afb13SDamon Ding };
6539452afb13SDamon Ding 
65409c7848c3SDamon Ding static const struct vop2_ops rk3562_vop_ops = {
65419c7848c3SDamon Ding 	.setup_win_dly = rk3528_setup_win_dly,
6542b7195f56SDamon Ding 	.setup_overlay = rk3528_setup_overlay,
65439c7848c3SDamon Ding };
65449c7848c3SDamon Ding 
6545452afb13SDamon Ding const struct vop2_data rk3562_vop = {
6546452afb13SDamon Ding 	.version = VOP_VERSION_RK3562,
6547452afb13SDamon Ding 	.nr_vps = 2,
6548452afb13SDamon Ding 	.vp_data = rk3562_vp_data,
6549452afb13SDamon Ding 	.win_data = rk3562_win_data,
6550452afb13SDamon Ding 	.plane_mask = rk3562_vp_plane_mask[0],
6551452afb13SDamon Ding 	.plane_table = rk3562_plane_table,
6552452afb13SDamon Ding 	.vp_primary_plane_order = rk3562_vp_primary_plane_order,
6553452afb13SDamon Ding 	.nr_layers = 4,
6554452afb13SDamon Ding 	.nr_mixers = 3,
6555452afb13SDamon Ding 	.nr_gammas = 2,
6556452afb13SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE,
655772388c26SDamon Ding 	.dump_regs = rk3562_dump_regs,
655872388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
65599c7848c3SDamon Ding 	.ops = &rk3562_vop_ops,
656072388c26SDamon Ding };
656172388c26SDamon Ding 
656272388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = {
656372388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
656472388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
656572388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
656672388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
656772388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
656872388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
656972388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
657072388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
657172388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
657272388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
657372388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
657472388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
6575452afb13SDamon Ding };
6576452afb13SDamon Ding 
6577337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
6578337d1c13SDamon Ding 	ROCKCHIP_VOP2_SMART0,
6579337d1c13SDamon Ding 	ROCKCHIP_VOP2_SMART1,
6580337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6581337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6582337d1c13SDamon Ding };
6583337d1c13SDamon Ding 
6584ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6585ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6586ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6587ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6588ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6589ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
6590ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
6591ee008497SSandy Huang };
6592ee008497SSandy Huang 
6593b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
6594b0989546SSandy Huang 	{ /* one display policy */
6595b0989546SSandy Huang 		{/* main display */
6596b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6597b0989546SSandy Huang 			.attached_layers_nr = 6,
6598b0989546SSandy Huang 			.attached_layers = {
6599b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
6600b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
6601b0989546SSandy Huang 				},
6602b0989546SSandy Huang 		},
6603b0989546SSandy Huang 		{/* second display */},
6604b0989546SSandy Huang 		{/* third  display */},
6605b0989546SSandy Huang 		{/* fourth display */},
6606b0989546SSandy Huang 	},
6607b0989546SSandy Huang 
6608b0989546SSandy Huang 	{ /* two display policy */
6609b0989546SSandy Huang 		{/* main display */
6610b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6611b0989546SSandy Huang 			.attached_layers_nr = 3,
6612b0989546SSandy Huang 			.attached_layers = {
6613b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
6614b0989546SSandy Huang 				},
6615b0989546SSandy Huang 		},
6616b0989546SSandy Huang 
6617b0989546SSandy Huang 		{/* second display */
6618b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
6619b0989546SSandy Huang 			.attached_layers_nr = 3,
6620b0989546SSandy Huang 			.attached_layers = {
6621b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
6622b0989546SSandy Huang 				},
6623b0989546SSandy Huang 		},
6624b0989546SSandy Huang 		{/* third  display */},
6625b0989546SSandy Huang 		{/* fourth display */},
6626b0989546SSandy Huang 	},
6627b0989546SSandy Huang 
6628b0989546SSandy Huang 	{ /* three display policy */
6629b0989546SSandy Huang 		{/* main display */
6630b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6631b0989546SSandy Huang 			.attached_layers_nr = 3,
6632b0989546SSandy Huang 			.attached_layers = {
6633b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
6634b0989546SSandy Huang 				},
6635b0989546SSandy Huang 		},
6636b0989546SSandy Huang 
6637b0989546SSandy Huang 		{/* second display */
6638b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
6639b0989546SSandy Huang 			.attached_layers_nr = 2,
6640b0989546SSandy Huang 			.attached_layers = {
6641b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
6642b0989546SSandy Huang 				},
6643b0989546SSandy Huang 		},
6644b0989546SSandy Huang 
6645b0989546SSandy Huang 		{/* third  display */
6646b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
6647b0989546SSandy Huang 			.attached_layers_nr = 1,
6648b0989546SSandy Huang 			.attached_layers = { ROCKCHIP_VOP2_ESMART1 },
6649b0989546SSandy Huang 		},
6650b0989546SSandy Huang 
6651b0989546SSandy Huang 		{/* fourth display */},
6652b0989546SSandy Huang 	},
6653b0989546SSandy Huang 
6654b0989546SSandy Huang 	{/* reserved for four display policy */},
6655b0989546SSandy Huang };
6656b0989546SSandy Huang 
6657b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = {
6658b0989546SSandy Huang 	{
6659b0989546SSandy Huang 		.name = "Cluster0",
6660b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
6661ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6662b0989546SSandy Huang 		.win_sel_port_offset = 0,
66635fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0xff },
6664b0989546SSandy Huang 		.reg_offset = 0,
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,
6669*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
66704c765862SDamon Ding 		.max_upscale_factor = 4,
66714c765862SDamon Ding 		.max_downscale_factor = 4,
66729c7848c3SDamon Ding 		.dly = { 0, 27, 21 },
6673b0989546SSandy Huang 	},
6674b0989546SSandy Huang 
6675b0989546SSandy Huang 	{
6676b0989546SSandy Huang 		.name = "Cluster1",
6677b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
6678ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6679b0989546SSandy Huang 		.win_sel_port_offset = 1,
66805fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 0xff },
6681b0989546SSandy Huang 		.reg_offset = 0x200,
66825fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
66835fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
66845fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
66855fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6686*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
66874c765862SDamon Ding 		.max_upscale_factor = 4,
66884c765862SDamon Ding 		.max_downscale_factor = 4,
66891c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_CLUSTER0,
66901c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
66919c7848c3SDamon Ding 		.dly = { 0, 27, 21 },
6692b0989546SSandy Huang 	},
6693b0989546SSandy Huang 
6694b0989546SSandy Huang 	{
6695b0989546SSandy Huang 		.name = "Esmart0",
6696b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6697ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6698b0989546SSandy Huang 		.win_sel_port_offset = 4,
66995fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 0xff },
6700b0989546SSandy Huang 		.reg_offset = 0,
67015fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67025fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67035fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67045fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6705*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
67064c765862SDamon Ding 		.max_upscale_factor = 8,
67074c765862SDamon Ding 		.max_downscale_factor = 8,
67089c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
6709b0989546SSandy Huang 	},
6710b0989546SSandy Huang 
6711b0989546SSandy Huang 	{
6712b0989546SSandy Huang 		.name = "Esmart1",
6713b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6714ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6715b0989546SSandy Huang 		.win_sel_port_offset = 5,
67165fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 0xff },
6717b0989546SSandy Huang 		.reg_offset = 0x200,
67185fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67195fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67205fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67215fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6722*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
67234c765862SDamon Ding 		.max_upscale_factor = 8,
67244c765862SDamon Ding 		.max_downscale_factor = 8,
67259c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
67261c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_ESMART0,
67271c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6728b0989546SSandy Huang 	},
6729b0989546SSandy Huang 
6730b0989546SSandy Huang 	{
6731b0989546SSandy Huang 		.name = "Smart0",
6732b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART0,
6733ecc31b6eSAndy Yan 		.type = SMART_LAYER,
6734b0989546SSandy Huang 		.win_sel_port_offset = 6,
67355fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 0xff },
6736b0989546SSandy Huang 		.reg_offset = 0x400,
67375fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67385fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67395fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67405fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6741*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
67424c765862SDamon Ding 		.max_upscale_factor = 8,
67434c765862SDamon Ding 		.max_downscale_factor = 8,
67449c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
6745b0989546SSandy Huang 	},
6746b0989546SSandy Huang 
6747b0989546SSandy Huang 	{
6748b0989546SSandy Huang 		.name = "Smart1",
6749b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART1,
6750ecc31b6eSAndy Yan 		.type = SMART_LAYER,
6751b0989546SSandy Huang 		.win_sel_port_offset = 7,
67525fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 0xff },
6753b0989546SSandy Huang 		.reg_offset = 0x600,
67545fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67555fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67565fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67575fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6758*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
67594c765862SDamon Ding 		.max_upscale_factor = 8,
67604c765862SDamon Ding 		.max_downscale_factor = 8,
67619c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
67621c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_SMART0,
67631c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6764b0989546SSandy Huang 	},
6765b0989546SSandy Huang };
6766b0989546SSandy Huang 
676763cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = {
676863cb669fSSandy Huang 	{
676963cb669fSSandy Huang 		.feature = VOP_FEATURE_OUTPUT_10BIT,
677063cb669fSSandy Huang 		.pre_scan_max_dly = 42,
677163cb669fSSandy Huang 		.max_output = {4096, 2304},
6772d0408543SAndy Yan 	},
677363cb669fSSandy Huang 	{
677463cb669fSSandy Huang 		.feature = 0,
677563cb669fSSandy Huang 		.pre_scan_max_dly = 40,
677663cb669fSSandy Huang 		.max_output = {2048, 1536},
677763cb669fSSandy Huang 	},
677863cb669fSSandy Huang 	{
677963cb669fSSandy Huang 		.feature = 0,
678063cb669fSSandy Huang 		.pre_scan_max_dly = 40,
678163cb669fSSandy Huang 		.max_output = {1920, 1080},
678263cb669fSSandy Huang 	},
678363cb669fSSandy Huang };
6784d0408543SAndy Yan 
67859c7848c3SDamon Ding static const struct vop2_ops rk3568_vop_ops = {
67869c7848c3SDamon Ding 	.setup_win_dly = rk3568_setup_win_dly,
6787b7195f56SDamon Ding 	.setup_overlay = rk3568_setup_overlay,
67889c7848c3SDamon Ding };
67899c7848c3SDamon Ding 
679063cb669fSSandy Huang const struct vop2_data rk3568_vop = {
6791ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3568,
679263cb669fSSandy Huang 	.nr_vps = 3,
679363cb669fSSandy Huang 	.vp_data = rk3568_vp_data,
6794b0989546SSandy Huang 	.win_data = rk3568_win_data,
6795b0989546SSandy Huang 	.plane_mask = rk356x_vp_plane_mask[0],
6796ee008497SSandy Huang 	.plane_table = rk356x_plane_table,
6797337d1c13SDamon Ding 	.vp_primary_plane_order = rk3568_vp_primary_plane_order,
6798d0408543SAndy Yan 	.nr_layers = 6,
679963cb669fSSandy Huang 	.nr_mixers = 5,
68001147facaSSandy Huang 	.nr_gammas = 1,
680172388c26SDamon Ding 	.dump_regs = rk3568_dump_regs,
680272388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3568_dump_regs),
68039c7848c3SDamon Ding 	.ops = &rk3568_vop_ops,
6804d0408543SAndy Yan };
6805d0408543SAndy Yan 
6806a552a69cSDamon Ding static u8 rk3576_vp_default_primary_plane[VOP2_VP_MAX] = {
6807a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6808a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6809a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART2,
6810a552a69cSDamon Ding };
6811a552a69cSDamon Ding 
6812a552a69cSDamon Ding static struct vop2_plane_table rk3576_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6813a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6814a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6815a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
6816a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
6817a552a69cSDamon Ding 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6818a552a69cSDamon Ding 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6819a552a69cSDamon Ding };
6820a552a69cSDamon Ding 
6821a552a69cSDamon Ding static struct vop2_dump_regs rk3576_dump_regs[] = {
6822a552a69cSDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 },
6823a552a69cSDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 },
6824a552a69cSDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 },
6825a552a69cSDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 },
6826a552a69cSDamon Ding 	{ RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 },
6827a552a69cSDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6828a552a69cSDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6829a552a69cSDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6830a552a69cSDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
6831a552a69cSDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
6832a552a69cSDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 },
6833a552a69cSDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 },
6834a552a69cSDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 },
6835a552a69cSDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 },
6836a552a69cSDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 },
6837a552a69cSDamon Ding };
6838a552a69cSDamon Ding 
6839a552a69cSDamon Ding /*
6840a552a69cSDamon Ding  * RK3576 VOP with 2 Cluster win and 4 Esmart win.
6841a552a69cSDamon Ding  * Every Esmart win support 4 multi-region.
6842a552a69cSDamon Ding  * VP0 can use Cluster0/1 and Esmart0/2
6843a552a69cSDamon Ding  * VP1 can use Cluster0/1 and Esmart1/3
6844a552a69cSDamon Ding  * VP2 can use Esmart0/1/2/3
6845a552a69cSDamon Ding  *
6846a552a69cSDamon Ding  * Scale filter mode:
6847a552a69cSDamon Ding  *
6848a552a69cSDamon Ding  * * Cluster:
6849a552a69cSDamon Ding  * * Support prescale down:
6850a552a69cSDamon Ding  * * H/V: gt2/avg2 or gt4/avg4
6851a552a69cSDamon Ding  * * After prescale down:
6852a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/multi-phase filter for scale up
6853a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/multi-phase filter for scale down
6854a552a69cSDamon Ding  *
6855a552a69cSDamon Ding  * * Esmart:
6856a552a69cSDamon Ding  * * Support prescale down:
6857a552a69cSDamon Ding  * * H: gt2/avg2 or gt4/avg4
6858a552a69cSDamon Ding  * * V: gt2 or gt4
6859a552a69cSDamon Ding  * * After prescale down:
6860a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/bicubic for scale up
6861a552a69cSDamon Ding  *	* nearest-neighbor/bilinear for scale down
6862cc517d73SDamon Ding  *
6863cc517d73SDamon Ding  * AXI config::
6864cc517d73SDamon Ding  *
6865cc517d73SDamon Ding  * * Cluster0 win0: 0xa,  0xb       [AXI0]
6866cc517d73SDamon Ding  * * Cluster0 win1: 0xc,  0xd       [AXI0]
6867cc517d73SDamon Ding  * * Cluster1 win0: 0x6,  0x7       [AXI0]
6868cc517d73SDamon Ding  * * Cluster1 win1: 0x8,  0x9       [AXI0]
6869cc517d73SDamon Ding  * * Esmart0:       0x10, 0x11      [AXI0]
6870cc517d73SDamon Ding  * * Esmart1:       0x12, 0x13      [AXI0]
6871cc517d73SDamon Ding  * * Esmart2:       0xa,  0xb       [AXI1]
6872cc517d73SDamon Ding  * * Esmart3:       0xc,  0xd       [AXI1]
6873cc517d73SDamon Ding  * * Lut dma rid:   0x1,  0x2,  0x3 [AXI0]
6874cc517d73SDamon Ding  * * DCI dma rid:   0x4             [AXI0]
6875cc517d73SDamon Ding  * * Metadata rid:  0x5             [AXI0]
6876cc517d73SDamon Ding  *
6877cc517d73SDamon Ding  * * Limit:
6878cc517d73SDamon Ding  * * (1) 0x0 and 0xf can't be used;
6879cc517d73SDamon Ding  * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf,
6880cc517d73SDamon Ding  * * VOP will dead at the system bandwidth very terrible scene.
6881a552a69cSDamon Ding  */
6882a552a69cSDamon Ding static struct vop2_win_data rk3576_win_data[6] = {
6883a552a69cSDamon Ding 	{
6884a552a69cSDamon Ding 		.name = "Esmart0",
6885a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6886a552a69cSDamon Ding 		.type = ESMART_LAYER,
6887a552a69cSDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0, 0xff },
6888a552a69cSDamon Ding 		.reg_offset = 0x0,
6889a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6890a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6891a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6892a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6893a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6894a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6895a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6896a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6897a552a69cSDamon Ding 		.axi_id = 0,
6898cc517d73SDamon Ding 		.axi_yrgb_id = 0x10,
6899cc517d73SDamon Ding 		.axi_uv_id = 0x11,
6900*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
6901a552a69cSDamon Ding 		.max_upscale_factor = 8,
6902a552a69cSDamon Ding 		.max_downscale_factor = 8,
6903a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH,
6904a552a69cSDamon Ding 	},
6905a552a69cSDamon Ding 	{
6906a552a69cSDamon Ding 		.name = "Esmart1",
6907a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6908a552a69cSDamon Ding 		.type = ESMART_LAYER,
6909a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 2, 1, 0xff },
6910a552a69cSDamon Ding 		.reg_offset = 0x200,
6911a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6912a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6913a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6914a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6915a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6916a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6917a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6918a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6919a552a69cSDamon Ding 		.axi_id = 0,
6920cc517d73SDamon Ding 		.axi_yrgb_id = 0x12,
6921cc517d73SDamon Ding 		.axi_uv_id = 0x13,
6922*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
6923a552a69cSDamon Ding 		.max_upscale_factor = 8,
6924a552a69cSDamon Ding 		.max_downscale_factor = 8,
6925a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6926a552a69cSDamon Ding 	},
6927a552a69cSDamon Ding 
6928a552a69cSDamon Ding 	{
6929a552a69cSDamon Ding 		.name = "Esmart2",
6930a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
6931a552a69cSDamon Ding 		.type = ESMART_LAYER,
6932a552a69cSDamon Ding 		.layer_sel_win_id = { 3, 0xff, 2, 0xff },
6933a552a69cSDamon Ding 		.reg_offset = 0x400,
6934a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6935a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6936a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6937a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6938a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6939a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6940a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6941a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6942a552a69cSDamon Ding 		.axi_id = 1,
6943a552a69cSDamon Ding 		.axi_yrgb_id = 0x0a,
6944a552a69cSDamon Ding 		.axi_uv_id = 0x0b,
6945*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
6946a552a69cSDamon Ding 		.max_upscale_factor = 8,
6947a552a69cSDamon Ding 		.max_downscale_factor = 8,
6948a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6949a552a69cSDamon Ding 	},
6950a552a69cSDamon Ding 
6951a552a69cSDamon Ding 	{
6952a552a69cSDamon Ding 		.name = "Esmart3",
6953a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
6954a552a69cSDamon Ding 		.type = ESMART_LAYER,
6955a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 3, 3, 0xff },
6956a552a69cSDamon Ding 		.reg_offset = 0x600,
6957a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6958a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6959a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6960a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6961a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6962a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6963a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6964a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6965a552a69cSDamon Ding 		.axi_id = 1,
6966a552a69cSDamon Ding 		.axi_yrgb_id = 0x0c,
6967a552a69cSDamon Ding 		.axi_uv_id = 0x0d,
6968*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
6969a552a69cSDamon Ding 		.max_upscale_factor = 8,
6970a552a69cSDamon Ding 		.max_downscale_factor = 8,
6971a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6972a552a69cSDamon Ding 	},
6973a552a69cSDamon Ding 
6974a552a69cSDamon Ding 	{
6975a552a69cSDamon Ding 		.name = "Cluster0",
6976a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
6977a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
6978a552a69cSDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
6979a552a69cSDamon Ding 		.reg_offset = 0x0,
6980a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
6981a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
6982a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6983a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6984a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6985a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6986a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6987a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
6988cc517d73SDamon Ding 		.axi_yrgb_id = 0x0a,
6989cc517d73SDamon Ding 		.axi_uv_id = 0x0b,
6990*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
6991a552a69cSDamon Ding 		.max_upscale_factor = 8,
6992a552a69cSDamon Ding 		.max_downscale_factor = 8,
6993a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
6994a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI,
6995a552a69cSDamon Ding 	},
6996a552a69cSDamon Ding 
6997a552a69cSDamon Ding 	{
6998a552a69cSDamon Ding 		.name = "Cluster1",
6999a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
7000a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
7001a552a69cSDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
7002a552a69cSDamon Ding 		.reg_offset = 0x200,
7003a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
7004a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
7005a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7006a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
7007a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7008a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7009a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7010a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
7011a552a69cSDamon Ding 		.axi_yrgb_id = 0x06,
7012a552a69cSDamon Ding 		.axi_uv_id = 0x07,
7013*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
7014a552a69cSDamon Ding 		.max_upscale_factor = 8,
7015a552a69cSDamon Ding 		.max_downscale_factor = 8,
7016a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
7017a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH,
7018a552a69cSDamon Ding 	},
7019a552a69cSDamon Ding };
7020a552a69cSDamon Ding 
702144b1b62cSDamon Ding /*
702244b1b62cSDamon Ding  * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4,
702344b1b62cSDamon Ding  * the urgency signal will be set to 1, when full post line buffer is over 6, the
702444b1b62cSDamon Ding  * urgency signal will be set to 0.
702544b1b62cSDamon Ding  */
702644b1b62cSDamon Ding static struct vop_urgency rk3576_vp0_urgency = {
702744b1b62cSDamon Ding 	.urgen_thl = 4,
702844b1b62cSDamon Ding 	.urgen_thh = 6,
702944b1b62cSDamon Ding };
703044b1b62cSDamon Ding 
7031a552a69cSDamon Ding static struct vop2_vp_data rk3576_vp_data[3] = {
7032a552a69cSDamon Ding 	{
7033a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR |
7034a552a69cSDamon Ding 			   VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT |
7035a552a69cSDamon Ding 			   VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP,
7036a552a69cSDamon Ding 		.max_output = { 4096, 4096 },
7037a552a69cSDamon Ding 		.hdrvivid_dly = 21,
7038a552a69cSDamon Ding 		.sdr2hdr_dly = 21,
7039a552a69cSDamon Ding 		.layer_mix_dly = 8,
7040a552a69cSDamon Ding 		.hdr_mix_dly = 2,
7041a552a69cSDamon Ding 		.win_dly = 10,
7042a552a69cSDamon Ding 		.pixel_rate = 2,
704344b1b62cSDamon Ding 		.urgency = &rk3576_vp0_urgency,
7044a552a69cSDamon Ding 	},
7045a552a69cSDamon Ding 	{
7046a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN |
7047a552a69cSDamon Ding 			   VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2,
7048a552a69cSDamon Ding 		.max_output = { 2560, 2560 },
7049a552a69cSDamon Ding 		.hdrvivid_dly = 0,
7050a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
7051a552a69cSDamon Ding 		.layer_mix_dly = 6,
7052a552a69cSDamon Ding 		.hdr_mix_dly = 0,
7053a552a69cSDamon Ding 		.win_dly = 10,
7054a552a69cSDamon Ding 		.pixel_rate = 1,
7055a552a69cSDamon Ding 	},
7056a552a69cSDamon Ding 	{
7057a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
7058a552a69cSDamon Ding 		.max_output = { 1920, 1920 },
7059a552a69cSDamon Ding 		.hdrvivid_dly = 0,
7060a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
7061a552a69cSDamon Ding 		.layer_mix_dly = 6,
7062a552a69cSDamon Ding 		.hdr_mix_dly = 0,
7063a552a69cSDamon Ding 		.win_dly = 10,
7064a552a69cSDamon Ding 		.pixel_rate = 1,
7065a552a69cSDamon Ding 	},
7066a552a69cSDamon Ding };
7067a552a69cSDamon Ding 
7068a552a69cSDamon Ding static struct vop2_power_domain_data rk3576_vop_pd_data[] = {
7069a552a69cSDamon Ding 	{
7070a552a69cSDamon Ding 		.id = VOP2_PD_CLUSTER,
7071a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1),
7072a552a69cSDamon Ding 	},
7073a552a69cSDamon Ding 	{
7074a552a69cSDamon Ding 		.id = VOP2_PD_ESMART,
7075a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) |
7076a552a69cSDamon Ding 				  BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3),
7077a552a69cSDamon Ding 	},
7078a552a69cSDamon Ding };
7079a552a69cSDamon Ding 
7080a552a69cSDamon Ding static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = {
7081a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_4K_MODE, 2},
7082a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_2K_2K_MODE, 3}
7083a552a69cSDamon Ding };
7084a552a69cSDamon Ding 
70859c7848c3SDamon Ding static const struct vop2_ops rk3576_vop_ops = {
70869c7848c3SDamon Ding 	.setup_win_dly = rk3576_setup_win_dly,
7087b7195f56SDamon Ding 	.setup_overlay = rk3576_setup_overlay,
70889c7848c3SDamon Ding };
70899c7848c3SDamon Ding 
7090a552a69cSDamon Ding const struct vop2_data rk3576_vop = {
7091a552a69cSDamon Ding 	.version = VOP_VERSION_RK3576,
7092a552a69cSDamon Ding 	.nr_vps = 3,
7093a552a69cSDamon Ding 	.nr_mixers = 4,
7094a552a69cSDamon Ding 	.nr_layers = 6,
7095a552a69cSDamon Ding 	.nr_gammas = 3,
7096a552a69cSDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE,
7097a552a69cSDamon Ding 	.esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map),
7098a552a69cSDamon Ding 	.esmart_lb_mode_map = rk3576_esmart_lb_mode_map,
7099a552a69cSDamon Ding 	.vp_data = rk3576_vp_data,
7100a552a69cSDamon Ding 	.win_data = rk3576_win_data,
7101a552a69cSDamon Ding 	.plane_table = rk3576_plane_table,
7102a552a69cSDamon Ding 	.pd = rk3576_vop_pd_data,
7103a552a69cSDamon Ding 	.vp_default_primary_plane = rk3576_vp_default_primary_plane,
7104a552a69cSDamon Ding 	.nr_pd = ARRAY_SIZE(rk3576_vop_pd_data),
7105a552a69cSDamon Ding 	.dump_regs = rk3576_dump_regs,
7106a552a69cSDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3576_dump_regs),
71079c7848c3SDamon Ding 	.ops = &rk3576_vop_ops,
7108a552a69cSDamon Ding };
7109a552a69cSDamon Ding 
7110337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
7111337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
7112337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
7113337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
7114337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
7115337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER0,
7116337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER1,
7117337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER2,
7118337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER3,
7119337d1c13SDamon Ding };
7120337d1c13SDamon Ding 
7121ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
7122ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
7123ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
7124ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER},
7125ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER},
7126ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
7127ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
7128ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
7129ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
7130ecc31b6eSAndy Yan };
7131ecc31b6eSAndy Yan 
713272388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = {
713372388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
713472388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
713572388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
713672388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
713772388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
713872388c26SDamon Ding 	{ RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 },
713972388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
714072388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
714172388c26SDamon Ding 	{ RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 },
714272388c26SDamon Ding 	{ RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 },
714372388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
714472388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
714572388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
714672388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
714772388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
714872388c26SDamon Ding };
714972388c26SDamon Ding 
7150ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
7151ecc31b6eSAndy Yan 	{ /* one display policy */
7152ecc31b6eSAndy Yan 		{/* main display */
7153608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
715483d6b087SDamon Ding 			.attached_layers_nr = 4,
7155ecc31b6eSAndy Yan 			.attached_layers = {
715683d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
715783d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7158ecc31b6eSAndy Yan 			},
7159ecc31b6eSAndy Yan 		},
716083d6b087SDamon Ding 
716183d6b087SDamon Ding 		{/* planes for the splice mode */
716283d6b087SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
716383d6b087SDamon Ding 			.attached_layers_nr = 4,
716483d6b087SDamon Ding 			.attached_layers = {
716583d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
716683d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
716783d6b087SDamon Ding 			},
716883d6b087SDamon Ding 		},
7169ecc31b6eSAndy Yan 		{/* third  display */},
7170ecc31b6eSAndy Yan 		{/* fourth display */},
7171ecc31b6eSAndy Yan 	},
7172ecc31b6eSAndy Yan 
7173ecc31b6eSAndy Yan 	{ /* two display policy */
7174ecc31b6eSAndy Yan 		{/* main display */
7175608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7176ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
7177ecc31b6eSAndy Yan 			.attached_layers = {
7178ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
717983d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7180ecc31b6eSAndy Yan 			},
7181ecc31b6eSAndy Yan 		},
7182ecc31b6eSAndy Yan 
7183ecc31b6eSAndy Yan 		{/* second display */
718483d6b087SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7185ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
7186ecc31b6eSAndy Yan 			.attached_layers = {
718783d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
7188ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
7189ecc31b6eSAndy Yan 			},
7190ecc31b6eSAndy Yan 		},
7191ecc31b6eSAndy Yan 		{/* third  display */},
7192ecc31b6eSAndy Yan 		{/* fourth display */},
7193ecc31b6eSAndy Yan 	},
7194ecc31b6eSAndy Yan 
7195ecc31b6eSAndy Yan 	{ /* three display policy */
7196ecc31b6eSAndy Yan 		{/* main display */
7197608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7198ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
7199ecc31b6eSAndy Yan 			.attached_layers = {
720083d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER2,
720183d6b087SDamon Ding 				  ROCKCHIP_VOP2_ESMART0
7202ecc31b6eSAndy Yan 			},
7203ecc31b6eSAndy Yan 		},
7204ecc31b6eSAndy Yan 
7205ecc31b6eSAndy Yan 		{/* second display */
7206608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7207ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
7208ecc31b6eSAndy Yan 			.attached_layers = {
720983d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_CLUSTER3,
721083d6b087SDamon Ding 				  ROCKCHIP_VOP2_ESMART1
7211ecc31b6eSAndy Yan 			},
7212ecc31b6eSAndy Yan 		},
7213ecc31b6eSAndy Yan 
7214ecc31b6eSAndy Yan 		{/* third  display */
7215ecc31b6eSAndy Yan 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7216ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7217ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
7218ecc31b6eSAndy Yan 		},
7219ecc31b6eSAndy Yan 
7220ecc31b6eSAndy Yan 		{/* fourth display */},
7221ecc31b6eSAndy Yan 	},
7222ecc31b6eSAndy Yan 
7223ecc31b6eSAndy Yan 	{ /* four display policy */
7224ecc31b6eSAndy Yan 		{/* main display */
7225608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7226ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7227ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
7228ecc31b6eSAndy Yan 		},
7229ecc31b6eSAndy Yan 
7230ecc31b6eSAndy Yan 		{/* second display */
7231608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7232ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7233ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
7234ecc31b6eSAndy Yan 		},
7235ecc31b6eSAndy Yan 
7236ecc31b6eSAndy Yan 		{/* third  display */
7237608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7238ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7239ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
7240ecc31b6eSAndy Yan 		},
7241ecc31b6eSAndy Yan 
7242ecc31b6eSAndy Yan 		{/* fourth display */
7243608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
7244ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7245ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
7246ecc31b6eSAndy Yan 		},
7247ecc31b6eSAndy Yan 	},
7248ecc31b6eSAndy Yan 
7249ecc31b6eSAndy Yan };
7250ecc31b6eSAndy Yan 
7251ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = {
7252ecc31b6eSAndy Yan 	{
7253ecc31b6eSAndy Yan 		.name = "Cluster0",
7254ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
7255ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER1,
7256ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7257ecc31b6eSAndy Yan 		.win_sel_port_offset = 0,
72585fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0 },
7259ecc31b6eSAndy Yan 		.reg_offset = 0,
7260a33b790fSDamon Ding 		.axi_id = 0,
7261a33b790fSDamon Ding 		.axi_yrgb_id = 2,
7262a33b790fSDamon Ding 		.axi_uv_id = 3,
7263b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER0,
72645fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
72655fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
72665fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
72675fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7268*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
72694c765862SDamon Ding 		.max_upscale_factor = 4,
72704c765862SDamon Ding 		.max_downscale_factor = 4,
72719c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7272ecc31b6eSAndy Yan 	},
7273ecc31b6eSAndy Yan 
7274ecc31b6eSAndy Yan 	{
7275ecc31b6eSAndy Yan 		.name = "Cluster1",
7276ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
7277ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7278ecc31b6eSAndy Yan 		.win_sel_port_offset = 1,
72795fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 1 },
7280ecc31b6eSAndy Yan 		.reg_offset = 0x200,
7281a33b790fSDamon Ding 		.axi_id = 0,
7282a33b790fSDamon Ding 		.axi_yrgb_id = 6,
7283a33b790fSDamon Ding 		.axi_uv_id = 7,
7284b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER1,
72855fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
72865fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
72875fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
72885fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7289*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
72904c765862SDamon Ding 		.max_upscale_factor = 4,
72914c765862SDamon Ding 		.max_downscale_factor = 4,
72929c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7293ecc31b6eSAndy Yan 	},
7294ecc31b6eSAndy Yan 
7295ecc31b6eSAndy Yan 	{
7296ecc31b6eSAndy Yan 		.name = "Cluster2",
7297ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
7298ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
7299ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7300ecc31b6eSAndy Yan 		.win_sel_port_offset = 2,
73015fa6e665SDamon Ding 		.layer_sel_win_id = { 4, 4, 4, 4 },
7302ecc31b6eSAndy Yan 		.reg_offset = 0x400,
7303a33b790fSDamon Ding 		.axi_id = 1,
7304a33b790fSDamon Ding 		.axi_yrgb_id = 2,
7305a33b790fSDamon Ding 		.axi_uv_id = 3,
7306b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER2,
73075fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
73085fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
73095fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
73105fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7311*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
73124c765862SDamon Ding 		.max_upscale_factor = 4,
73134c765862SDamon Ding 		.max_downscale_factor = 4,
73149c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7315ecc31b6eSAndy Yan 	},
7316ecc31b6eSAndy Yan 
7317ecc31b6eSAndy Yan 	{
7318ecc31b6eSAndy Yan 		.name = "Cluster3",
7319ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
7320ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7321ecc31b6eSAndy Yan 		.win_sel_port_offset = 3,
73225fa6e665SDamon Ding 		.layer_sel_win_id = { 5, 5, 5, 5 },
7323ecc31b6eSAndy Yan 		.reg_offset = 0x600,
7324a33b790fSDamon Ding 		.axi_id = 1,
7325a33b790fSDamon Ding 		.axi_yrgb_id = 6,
7326a33b790fSDamon Ding 		.axi_uv_id = 7,
7327b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER3,
73285fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
73295fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
73305fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
73315fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7332*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
73334c765862SDamon Ding 		.max_upscale_factor = 4,
73344c765862SDamon Ding 		.max_downscale_factor = 4,
73359c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7336ecc31b6eSAndy Yan 	},
7337ecc31b6eSAndy Yan 
7338ecc31b6eSAndy Yan 	{
7339ecc31b6eSAndy Yan 		.name = "Esmart0",
7340ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART0,
7341ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART1,
7342ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7343ecc31b6eSAndy Yan 		.win_sel_port_offset = 4,
73445fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 2 },
7345ecc31b6eSAndy Yan 		.reg_offset = 0,
7346a33b790fSDamon Ding 		.axi_id = 0,
7347a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
7348a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
73495fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
73505fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
73515fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
73525fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7353*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
73544c765862SDamon Ding 		.max_upscale_factor = 8,
73554c765862SDamon Ding 		.max_downscale_factor = 8,
73569c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7357ecc31b6eSAndy Yan 	},
7358ecc31b6eSAndy Yan 
7359ecc31b6eSAndy Yan 	{
7360ecc31b6eSAndy Yan 		.name = "Esmart1",
7361ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART1,
7362ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7363ecc31b6eSAndy Yan 		.win_sel_port_offset = 5,
73645fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 3 },
7365ecc31b6eSAndy Yan 		.reg_offset = 0x200,
7366a33b790fSDamon Ding 		.axi_id = 0,
7367a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
7368a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
7369b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
73705fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
73715fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
73725fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
73735fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7374*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
73754c765862SDamon Ding 		.max_upscale_factor = 8,
73764c765862SDamon Ding 		.max_downscale_factor = 8,
73779c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7378ecc31b6eSAndy Yan 	},
7379ecc31b6eSAndy Yan 
7380ecc31b6eSAndy Yan 	{
7381ecc31b6eSAndy Yan 		.name = "Esmart2",
7382ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART2,
7383ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART3,
7384ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7385ecc31b6eSAndy Yan 		.win_sel_port_offset = 6,
73865fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 6 },
7387ecc31b6eSAndy Yan 		.reg_offset = 0x400,
7388a33b790fSDamon Ding 		.axi_id = 1,
7389a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
7390a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
7391b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
73925fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
73935fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
73945fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
73955fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7396*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
73974c765862SDamon Ding 		.max_upscale_factor = 8,
73984c765862SDamon Ding 		.max_downscale_factor = 8,
73999c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7400ecc31b6eSAndy Yan 	},
7401ecc31b6eSAndy Yan 
7402ecc31b6eSAndy Yan 	{
7403ecc31b6eSAndy Yan 		.name = "Esmart3",
7404ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART3,
7405ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7406ecc31b6eSAndy Yan 		.win_sel_port_offset = 7,
74075fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 7 },
7408ecc31b6eSAndy Yan 		.reg_offset = 0x600,
7409a33b790fSDamon Ding 		.axi_id = 1,
7410a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
7411a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
7412b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
74135fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
74145fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
74155fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
74165fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7417*13bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
74184c765862SDamon Ding 		.max_upscale_factor = 8,
74194c765862SDamon Ding 		.max_downscale_factor = 8,
74209c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7421ecc31b6eSAndy Yan 	},
7422ecc31b6eSAndy Yan };
7423ecc31b6eSAndy Yan 
742412ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = {
742512ee5af0SDamon Ding 	{0x00000000, "no error detected by DSC encoder"},
742612ee5af0SDamon Ding 	{0x0030ffff, "bits per component error"},
742712ee5af0SDamon Ding 	{0x0040ffff, "multiple mode error"},
742812ee5af0SDamon Ding 	{0x0050ffff, "line buffer depth error"},
742912ee5af0SDamon Ding 	{0x0060ffff, "minor version error"},
743012ee5af0SDamon Ding 	{0x0070ffff, "picture height error"},
743112ee5af0SDamon Ding 	{0x0080ffff, "picture width error"},
743212ee5af0SDamon Ding 	{0x0090ffff, "number of slices error"},
743312ee5af0SDamon Ding 	{0x00c0ffff, "slice height Error "},
743412ee5af0SDamon Ding 	{0x00d0ffff, "slice width error"},
743512ee5af0SDamon Ding 	{0x00e0ffff, "second line BPG offset error"},
743612ee5af0SDamon Ding 	{0x00f0ffff, "non second line BPG offset error"},
743712ee5af0SDamon Ding 	{0x0100ffff, "PPS ID error"},
743812ee5af0SDamon Ding 	{0x0110ffff, "bits per pixel (BPP) Error"},
743912ee5af0SDamon Ding 	{0x0120ffff, "buffer flow error"},  /* dsc_buffer_flow */
744012ee5af0SDamon Ding 
744112ee5af0SDamon Ding 	{0x01510001, "slice 0 RC buffer model overflow error"},
744212ee5af0SDamon Ding 	{0x01510002, "slice 1 RC buffer model overflow error"},
744312ee5af0SDamon Ding 	{0x01510004, "slice 2 RC buffer model overflow error"},
744412ee5af0SDamon Ding 	{0x01510008, "slice 3 RC buffer model overflow error"},
744512ee5af0SDamon Ding 	{0x01510010, "slice 4 RC buffer model overflow error"},
744612ee5af0SDamon Ding 	{0x01510020, "slice 5 RC buffer model overflow error"},
744712ee5af0SDamon Ding 	{0x01510040, "slice 6 RC buffer model overflow error"},
744812ee5af0SDamon Ding 	{0x01510080, "slice 7 RC buffer model overflow error"},
744912ee5af0SDamon Ding 
745012ee5af0SDamon Ding 	{0x01610001, "slice 0 RC buffer model underflow error"},
745112ee5af0SDamon Ding 	{0x01610002, "slice 1 RC buffer model underflow error"},
745212ee5af0SDamon Ding 	{0x01610004, "slice 2 RC buffer model underflow error"},
745312ee5af0SDamon Ding 	{0x01610008, "slice 3 RC buffer model underflow error"},
745412ee5af0SDamon Ding 	{0x01610010, "slice 4 RC buffer model underflow error"},
745512ee5af0SDamon Ding 	{0x01610020, "slice 5 RC buffer model underflow error"},
745612ee5af0SDamon Ding 	{0x01610040, "slice 6 RC buffer model underflow error"},
745712ee5af0SDamon Ding 	{0x01610080, "slice 7 RC buffer model underflow error"},
745812ee5af0SDamon Ding 
745912ee5af0SDamon Ding 	{0xffffffff, "unsuccessful RESET cycle status"},
746012ee5af0SDamon Ding 	{0x00a0ffff, "ICH full error precision settings error"},
746112ee5af0SDamon Ding 	{0x0020ffff, "native mode"},
746212ee5af0SDamon Ding };
746312ee5af0SDamon Ding 
746412ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = {
746512ee5af0SDamon Ding 	{0x00000000, "rate buffer status"},
746612ee5af0SDamon Ding 	{0x00000001, "line buffer status"},
746712ee5af0SDamon Ding 	{0x00000002, "decoder model status"},
746812ee5af0SDamon Ding 	{0x00000003, "pixel buffer status"},
746912ee5af0SDamon Ding 	{0x00000004, "balance fifo buffer status"},
747012ee5af0SDamon Ding 	{0x00000005, "syntax element fifo status"},
747112ee5af0SDamon Ding };
747212ee5af0SDamon Ding 
747312ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = {
747412ee5af0SDamon Ding 	{
747512ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_8K,
747612ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_8K,
747712ee5af0SDamon Ding 		.max_slice_num = 8,
747812ee5af0SDamon Ding 		.max_linebuf_depth = 11,
7479b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
748012ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
748112ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_8k_txp_clk",
748212ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_8k_pxl_clk",
748312ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_8k_cds_clk",
748412ee5af0SDamon Ding 	},
748512ee5af0SDamon Ding 
748612ee5af0SDamon Ding 	{
748712ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_4K,
748812ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_4K,
748912ee5af0SDamon Ding 		.max_slice_num = 2,
749012ee5af0SDamon Ding 		.max_linebuf_depth = 11,
7491b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
749212ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
749312ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_4k_txp_clk",
749412ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_4k_pxl_clk",
749512ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_4k_cds_clk",
749612ee5af0SDamon Ding 	},
749712ee5af0SDamon Ding };
749812ee5af0SDamon Ding 
7499ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = {
7500ecc31b6eSAndy Yan 	{
7501ee01dbb2SDamon Ding 		.splice_vp_id = 1,
7502ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7503b890760eSAlgea Cao 		.pre_scan_max_dly = 54,
7504ecc31b6eSAndy Yan 		.max_dclk = 600000,
7505ecc31b6eSAndy Yan 		.max_output = {7680, 4320},
7506ecc31b6eSAndy Yan 	},
7507ecc31b6eSAndy Yan 	{
7508ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7509ee01dbb2SDamon Ding 		.pre_scan_max_dly = 54,
7510ecc31b6eSAndy Yan 		.max_dclk = 600000,
7511ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
7512ecc31b6eSAndy Yan 	},
7513ecc31b6eSAndy Yan 	{
7514ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7515ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
7516ecc31b6eSAndy Yan 		.max_dclk = 600000,
7517ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
7518ecc31b6eSAndy Yan 	},
7519ecc31b6eSAndy Yan 	{
7520ecc31b6eSAndy Yan 		.feature = 0,
7521ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
7522ecc31b6eSAndy Yan 		.max_dclk = 200000,
7523ecc31b6eSAndy Yan 		.max_output = {1920, 1080},
7524ecc31b6eSAndy Yan 	},
7525ecc31b6eSAndy Yan };
7526ecc31b6eSAndy Yan 
7527b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = {
7528b6ba80b4SDamon Ding 	{
7529b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER0,
7530b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0),
7531b6ba80b4SDamon Ding 	},
7532b6ba80b4SDamon Ding 	{
7533b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER1,
7534b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1),
7535b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7536b6ba80b4SDamon Ding 	},
7537b6ba80b4SDamon Ding 	{
7538b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER2,
7539b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2),
7540b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7541b6ba80b4SDamon Ding 	},
7542b6ba80b4SDamon Ding 	{
7543b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER3,
7544b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3),
7545b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7546b6ba80b4SDamon Ding 	},
7547b6ba80b4SDamon Ding 	{
7548b6ba80b4SDamon Ding 	  .id = VOP2_PD_ESMART,
7549b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) |
7550b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART2) |
7551b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART3),
7552b6ba80b4SDamon Ding 	},
7553b6ba80b4SDamon Ding 	{
7554b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_8K,
7555b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K),
7556b6ba80b4SDamon Ding 	},
7557b6ba80b4SDamon Ding 	{
7558b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_4K,
7559b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K),
7560b6ba80b4SDamon Ding 	},
7561b6ba80b4SDamon Ding };
7562b6ba80b4SDamon Ding 
75639c7848c3SDamon Ding static const struct vop2_ops rk3588_vop_ops = {
75649c7848c3SDamon Ding 	.setup_win_dly = rk3568_setup_win_dly,
7565b7195f56SDamon Ding 	.setup_overlay = rk3568_setup_overlay,
75669c7848c3SDamon Ding };
75679c7848c3SDamon Ding 
7568ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = {
7569ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3588,
7570ecc31b6eSAndy Yan 	.nr_vps = 4,
7571ecc31b6eSAndy Yan 	.vp_data = rk3588_vp_data,
7572ecc31b6eSAndy Yan 	.win_data = rk3588_win_data,
7573ecc31b6eSAndy Yan 	.plane_mask = rk3588_vp_plane_mask[0],
7574ecc31b6eSAndy Yan 	.plane_table = rk3588_plane_table,
7575b6ba80b4SDamon Ding 	.pd = rk3588_vop_pd_data,
757612ee5af0SDamon Ding 	.dsc = rk3588_dsc_data,
757712ee5af0SDamon Ding 	.dsc_error_ecw = dsc_ecw,
757812ee5af0SDamon Ding 	.dsc_error_buffer_flow = dsc_buffer_flow,
7579337d1c13SDamon Ding 	.vp_primary_plane_order = rk3588_vp_primary_plane_order,
7580ecc31b6eSAndy Yan 	.nr_layers = 8,
7581ecc31b6eSAndy Yan 	.nr_mixers = 7,
7582ecc31b6eSAndy Yan 	.nr_gammas = 4,
7583b6ba80b4SDamon Ding 	.nr_pd = ARRAY_SIZE(rk3588_vop_pd_data),
758412ee5af0SDamon Ding 	.nr_dscs = 2,
758512ee5af0SDamon Ding 	.nr_dsc_ecw = ARRAY_SIZE(dsc_ecw),
758612ee5af0SDamon Ding 	.nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow),
758772388c26SDamon Ding 	.dump_regs = rk3588_dump_regs,
758872388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3588_dump_regs),
75899c7848c3SDamon Ding 	.ops = &rk3588_vop_ops,
7590ecc31b6eSAndy Yan };
7591ecc31b6eSAndy Yan 
7592d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
7593d0408543SAndy Yan 	.preinit = rockchip_vop2_preinit,
7594d0408543SAndy Yan 	.prepare = rockchip_vop2_prepare,
7595d0408543SAndy Yan 	.init = rockchip_vop2_init,
7596d0408543SAndy Yan 	.set_plane = rockchip_vop2_set_plane,
7597d0408543SAndy Yan 	.enable = rockchip_vop2_enable,
7598efa01fe4SZhang Yubing 	.post_enable = rockchip_vop2_post_enable,
7599d0408543SAndy Yan 	.disable = rockchip_vop2_disable,
7600b0989546SSandy Huang 	.fixup_dts = rockchip_vop2_fixup_dts,
76010675a2a4SDamon Ding 	.send_mcu_cmd = rockchip_vop2_send_mcu_cmd,
7602820a5c17SDamon Ding 	.check = rockchip_vop2_check,
760322007755SDamon Ding 	.mode_valid = rockchip_vop2_mode_valid,
7604b02eb70bSDamon Ding 	.mode_fixup = rockchip_vop2_mode_fixup,
76054c765862SDamon Ding 	.plane_check = rockchip_vop2_plane_check,
760672388c26SDamon Ding 	.regs_dump = rockchip_vop2_regs_dump,
760772388c26SDamon Ding 	.active_regs_dump = rockchip_vop2_active_regs_dump,
76088e7ef808SDamon Ding 	.apply_soft_te = rockchip_vop2_apply_soft_te,
7609d0408543SAndy Yan };
7610