xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_vop2.c (revision 0e0a0ff9aa2e2d4edfbf63a06178e4fd157ec55e)
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
3125fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL		0x520
313452afb13SDamon Ding #define ESMART_DLY_NUM_MASK			0xff
314452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT			0
3155fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL		0x524
3165fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL		0x528
3175fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL		0x52C
3185fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL	0x530
3195fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL	0x534
3205fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x538
3215fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL	0x53c
322a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL	0x540
323a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL	0x544
324a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL	0x548
325a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL	0x54c
3265fa6e665SDamon Ding 
3275fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL			0x600
32863cb669fSSandy Huang #define RK3568_OVL_CTRL				0x600
329ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK			0x1
330ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT			0
33163cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
3325fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL		0x604
33363cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL			0x604
33463cb669fSSandy Huang #define LAYER_SEL_MASK				0xf
33563cb669fSSandy Huang 
33663cb669fSSandy Huang #define RK3568_OVL_PORT_SEL			0x608
33763cb669fSSandy Huang #define PORT_MUX_MASK				0xf
33863cb669fSSandy Huang #define PORT_MUX_SHIFT				0
33963cb669fSSandy Huang #define LAYER_SEL_PORT_MASK			0x3
34063cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT			16
34163cb669fSSandy Huang 
34263cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
34363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
34463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
34563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
3465fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL	0x620
3475fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL	0x624
3485fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL	0x628
3495fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL	0x62C
3505fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL	0x630
3515fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL	0x634
3525fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL	0x638
3535fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL	0x63C
3545fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL	0x640
3555fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL	0x644
3565fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL	0x648
3575fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL	0x64C
35863cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
35963cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL		0x654
36063cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
36163cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
362a552a69cSDamon Ding #define RK3576_EXTRA_SRC_COLOR_CTRL		0x650
363a552a69cSDamon Ding #define RK3576_EXTRA_DST_COLOR_CTRL		0x654
364a552a69cSDamon Ding #define RK3576_EXTRA_SRC_ALPHA_CTRL		0x658
365a552a69cSDamon Ding #define RK3576_EXTRA_DST_ALPHA_CTRL		0x65C
3665fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL		0x660
3675fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL		0x664
3685fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL		0x668
3695fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL		0x66C
3705fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL		0x670
37163cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
37263cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
37363cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
37463cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
37563cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL			0x6E0
37663cb669fSSandy Huang #define BG_MIX_CTRL_MASK			0xff
37763cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT			24
37863cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL			0x6E4
37963cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL			0x6E8
38063cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM			0x6F0
38163cb669fSSandy Huang #define RK3568_SMART_DLY_NUM			0x6F8
38263cb669fSSandy Huang 
3835fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL			0x700
3845fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL		0x704
3855fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL	0x720
3865fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL	0x724
3875fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL	0x728
3885fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL	0x72C
3895fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL	0x730
3905fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL	0x734
3915fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL	0x738
3925fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL	0x73C
3935fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL	0x740
3945fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL	0x744
3955fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL	0x748
3965fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL	0x74C
3975fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL		0x770
398a552a69cSDamon Ding #define RK3576_OVL_PORT2_CTRL			0x800
399a552a69cSDamon Ding #define RK3576_OVL_PORT2_LAYER_SEL		0x804
400a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL	0x820
401a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL	0x824
402a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL	0x828
403a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL	0x82C
404a552a69cSDamon Ding #define RK3576_OVL_PORT2_BG_MIX_CTRL		0x870
4055fa6e665SDamon Ding 
406d0408543SAndy Yan /* Video Port registers definition */
407d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL			0xC00
408d0408543SAndy Yan #define OUT_MODE_MASK				0xf
409d0408543SAndy Yan #define OUT_MODE_SHIFT				0
41010ee9f5bSAlgea Cao #define DATA_SWAP_MASK				0x1f
41110ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT				8
41265747de7SDamon Ding #define DSP_BG_SWAP				0x1
41365747de7SDamon Ding #define DSP_RB_SWAP				0x2
41465747de7SDamon Ding #define DSP_RG_SWAP				0x4
41565747de7SDamon Ding #define DSP_DELTA_SWAP				0x8
41610ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT			4
417d0408543SAndy Yan #define P2I_EN_SHIFT				5
4187a20be36SSandy Huang #define DSP_FILED_POL				6
419d0408543SAndy Yan #define INTERLACE_EN_SHIFT			7
420c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT			13
42110ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT			15
422d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT		16
423d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT			17
424e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_SHIFT			18
425e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_MASK			0x3
426452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT			20
427db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT			22
4281147facaSSandy Huang #define DSP_LUT_EN_SHIFT			28
4291147facaSSandy Huang 
430d0408543SAndy Yan #define STANDBY_EN_SHIFT			31
431d0408543SAndy Yan 
432d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL			0xC04
43310ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT				4
43410ee9f5bSAlgea Cao #define DCLK_DIV2_MASK				0x3
435d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT			20
436d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT			21
43741874944SGuochun Huang #define EDPI_TE_EN				28
43841874944SGuochun Huang #define EDPI_WMS_HOLD_EN			30
43941874944SGuochun Huang #define EDPI_WMS_FS				31
44041874944SGuochun Huang 
441d0408543SAndy Yan 
442d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL		0xC08
44344b1b62cSDamon Ding #define POST_URGENCY_EN_SHIFT			8
44444b1b62cSDamon Ding #define POST_URGENCY_THL_SHIFT			16
44544b1b62cSDamon Ding #define POST_URGENCY_THL_MASK			0xf
44644b1b62cSDamon Ding #define POST_URGENCY_THH_SHIFT			20
44744b1b62cSDamon Ding #define POST_URGENCY_THH_MASK			0xf
4485fa6e665SDamon Ding 
4495fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL			0xC0C
450a552a69cSDamon Ding #define RK3576_DCLK_CORE_SEL_SHIFT		0
451a552a69cSDamon Ding #define RK3576_DCLK_OUT_SEL_SHIFT		2
4525fa6e665SDamon Ding 
4536414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL			0xC10
4546414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT				0
4556414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT			2
4566414e3bcSSandy Huang 
457ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL			0xC0C
458ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT			0
459ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT			2
460ecc31b6eSAndy Yan 
4616414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST			0xC20
4626414e3bcSSandy Huang 
463d0408543SAndy Yan #define RK3568_VP0_DSP_BG			0xC2C
464d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
465d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
466d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
467d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
468d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL		0xC40
4697504507fSSandy Huang #define RK3568_VP0_POST_SCALE_MASK		0x3
4707504507fSSandy Huang #define RK3568_VP0_POST_SCALE_SHIFT		0
471d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
472d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
473d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END		0xC4C
474d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
475d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END		0xC54
476d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
477d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
478d0408543SAndy Yan 
479ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL			0xC60
480ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT			0
481ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK			0x1
482ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT		2
483ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK		0x3
484ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT			4
485ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK			0x1
486ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT		6
487ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK		0x3
488ac500a1fSSandy Huang 
489ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS			0xC64
490ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT			0
491ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK			0xFF
492ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT			8
493ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK			0x1FF
494ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT			20
495ac500a1fSSandy Huang #define BCSH_SATURATION_MASK			0x3FF
496ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT			30
497ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK			0x3
498ac500a1fSSandy Huang 
499ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H			0xC68
500ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT			0
501ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK			0x1FF
502ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT			16
503ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK			0x1FF
504ac500a1fSSandy Huang 
505ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR			0xC6C
506ac500a1fSSandy Huang #define BCSH_EN_SHIFT				31
507ac500a1fSSandy Huang #define BCSH_EN_MASK				1
508ac500a1fSSandy Huang 
509a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_0		0xCA0
510a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_1		0xCA4
511a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_2		0xCA8
512a552a69cSDamon Ding 
5136027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL			0xCD0
5146027c871SZhang Yubing #define POST_CSC_COE00_MASK			0xFFFF
5156027c871SZhang Yubing #define POST_CSC_COE00_SHIFT			16
5166027c871SZhang Yubing #define POST_R2Y_MODE_MASK			0x7
5176027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT			8
5186027c871SZhang Yubing #define POST_CSC_MODE_MASK			0x7
5196027c871SZhang Yubing #define POST_CSC_MODE_SHIFT			3
5206027c871SZhang Yubing #define POST_R2Y_EN_MASK			0x1
5216027c871SZhang Yubing #define POST_R2Y_EN_SHIFT			2
5226027c871SZhang Yubing #define POST_CSC_EN_MASK			0x1
5236027c871SZhang Yubing #define POST_CSC_EN_SHIFT			1
5246027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK			0x1
5256027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT		0
5266027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02			0xCD4
5276027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11			0xCD8
5286027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20			0xCDC
5296027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22			0xCE0
5306027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0			0xCE4
5316027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1			0xCE8
5326027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2			0xCEC
5336027c871SZhang Yubing 
5340675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL			0xCF8
5350675a2a4SDamon Ding #define MCU_TYPE_SHIFT				31
5360675a2a4SDamon Ding #define MCU_BYPASS_SHIFT			30
5370675a2a4SDamon Ding #define MCU_RS_SHIFT				29
5380675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT			28
5390675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT			27
5400675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT			26
5410675a2a4SDamon Ding #define MCU_CLK_SEL_MASK			0x1
5420675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT			20
5430675a2a4SDamon Ding #define MCU_RW_PEND_MASK			0x3F
5440675a2a4SDamon Ding #define MCU_RW_PST_SHIFT			16
5450675a2a4SDamon Ding #define MCU_RW_PST_MASK				0xF
5460675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT			10
5470675a2a4SDamon Ding #define MCU_CS_PEND_MASK			0x3F
5480675a2a4SDamon Ding #define MCU_CS_PST_SHIFT			6
5490675a2a4SDamon Ding #define MCU_CS_PST_MASK				0xF
5500675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT			0
5510675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK			0x3F
5520675a2a4SDamon Ding 
5530675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT		0xCFC
5540675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT		0
5550675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK		0xFFFFFFFF
5560675a2a4SDamon Ding 
557d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL			0xD00
558d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL			0xD04
559d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL		0xD08
560d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
561d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
562d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
563d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
564d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL		0xD40
565d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO		0xD34
566d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO		0xD38
567d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
568d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
569d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END		0xD4C
570d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
571d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END		0xD54
572d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
573d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
574d0408543SAndy Yan 
575d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL			0xE00
576d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL			0xE04
577d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL		0xE08
578d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
579d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
580d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
581d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
582d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL		0xE40
583d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO		0xE34
584d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO		0xE38
585d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
586d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
587d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END		0xE4C
588d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
589d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END		0xE54
590d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
591d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
592a552a69cSDamon Ding #define RK3568_VP2_BCSH_CTRL			0xE60
593a552a69cSDamon Ding #define RK3568_VP2_BCSH_BCS			0xE64
594a552a69cSDamon Ding #define RK3568_VP2_BCSH_H			0xE68
595a552a69cSDamon Ding #define RK3568_VP2_BCSH_COLOR_BAR		0xE6C
596a552a69cSDamon Ding #define RK3576_VP2_MCU_CTRL			0xEF8
597a552a69cSDamon Ding #define RK3576_VP2_MCU_RW_BYPASS_PORT		0xEFC
598d0408543SAndy Yan 
599d0408543SAndy Yan /* Cluster0 register definition */
600d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
601ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT		8
602ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT		9
603ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT			10
604840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT		18
605d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
6065fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT	12
6075fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
6085fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
6095fa6e665SDamon Ding #define AVG2_MASK				0x1
6105fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT			18
6115fa6e665SDamon Ding #define AVG4_MASK				0x1
6125fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT			19
6135fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT	22
6145fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT			24
6155fa6e665SDamon Ding #define XGT_MODE_MASK				0x3
6165fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT			25
6175fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT			27
618ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT			28
619ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT			29
620a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2		0x1008
621a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK		0x1f
622a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT		0
623a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK			0x1f
624a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT			5
625a33b790fSDamon Ding 
626d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
627d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
628d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR		0x1018
629d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
630d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
631d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
632d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
633a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_CTRL		0x1040
634a552a69cSDamon Ding #define WIN0_ZME_DERING_EN_SHIFT		3
635a552a69cSDamon Ding #define WIN0_ZME_GATING_EN_SHIFT		31
636a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA	0x1044
637d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
638d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
639d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
640d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
641d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
642d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
643d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
644a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT		7
645a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET	0x1078
646a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE	0x107C
647d0408543SAndy Yan 
648d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
649d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
650d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
651d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
652d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR		0x1098
653d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
654d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
655d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
656d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
657d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
658d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
659d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
660d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
661d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
662d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
663d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
664a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET	0x10F8
665a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE	0x10FC
666d0408543SAndy Yan 
667d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL			0x1100
668ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT			0
669a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK			0x1
670a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT			13
671a552a69cSDamon Ding #define RK3576_CLUSTER0_PORT_SEL		0x11F4
672a552a69cSDamon Ding #define CLUSTER_PORT_SEL_SHIFT			0
673a552a69cSDamon Ding #define CLUSTER_PORT_SEL_MASK			0x3
674a552a69cSDamon Ding #define RK3576_CLUSTER0_DLY_NUM			0x11F8
675a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_SHIFT		0
676a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_MASK		0xff
677a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_SHIFT		0
678a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_MASK		0xff
679d0408543SAndy Yan 
680d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
681d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
682d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
683d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
684d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR		0x1218
685d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
686d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
687d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
688d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
689a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_CTRL		0x1240
690a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA	0x1244
691d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
692d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
693d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
694d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
695d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
696d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
697d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
698a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET	0x1278
699a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE	0x127C
700d0408543SAndy Yan 
701d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
702d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
703d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
704d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
705d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR		0x1298
706d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
707d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
708d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
709d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
710d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
711d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
712d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
713d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
714d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
715d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
716d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
717a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET	0x12F8
718a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE	0x12FC
719d0408543SAndy Yan 
720d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL			0x1300
721a552a69cSDamon Ding #define RK3576_CLUSTER1_PORT_SEL		0x13F4
722a552a69cSDamon Ding #define RK3576_CLUSTER1_DLY_NUM			0x13F8
723d0408543SAndy Yan 
724d0408543SAndy Yan /* Esmart register definition */
725d0408543SAndy Yan #define RK3568_ESMART0_CTRL0			0x1800
72610ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT			1
72710ee9f5bSAlgea Cao #define CSC_MODE_SHIFT				2
72810ee9f5bSAlgea Cao #define CSC_MODE_MASK				0x3
7295fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT			12
7305fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK			0x3
731d0408543SAndy Yan 
732d0408543SAndy Yan #define RK3568_ESMART0_CTRL1			0x1804
733a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK			0x1f
734a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT		4
735a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK			0x1f
736a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT			12
737d0408543SAndy Yan #define YMIRROR_EN_SHIFT			31
738a33b790fSDamon Ding 
739a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL			0x1808
740a33b790fSDamon Ding #define ESMART_AXI_ID_MASK			0x1
741a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT			1
742a33b790fSDamon Ding 
743d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL		0x1810
744d0408543SAndy Yan #define WIN_EN_SHIFT				0
745d0408543SAndy Yan #define WIN_FORMAT_MASK				0x1f
746d0408543SAndy Yan #define WIN_FORMAT_SHIFT			1
747840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT		12
7485fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT			14
7495fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT			20
7505fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT			21
7515fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT			22
752d0408543SAndy Yan 
753d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
754d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
755d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR		0x181C
756d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
757d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
758d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
759d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
7603e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK			0x3
7613e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT			0
7623e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK		0x3
7633e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT		2
7643e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK			0x3
7653e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT			4
7663e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK		0x3
7673e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT		6
7683e39a5a1SSandy Huang 
769d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
770d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
771d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
772d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL		0x1840
7733e39a5a1SSandy Huang #define YRGB_GT2_MASK				0x1
7743e39a5a1SSandy Huang #define YRGB_GT2_SHIFT				8
7753e39a5a1SSandy Huang #define YRGB_GT4_MASK				0x1
7763e39a5a1SSandy Huang #define YRGB_GT4_SHIFT				9
7773e39a5a1SSandy Huang 
778d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
779d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
780d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR		0x184C
781d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
782d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
783d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
784d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
785d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
786d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
787d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
788d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL		0x1870
789d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
790d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
791d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR		0x187C
792d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
793d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
794d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
795d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
796d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
797d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
798d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
799d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL		0x18A0
800d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
801d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
802d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR		0x18AC
803d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
804d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
805d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
806d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
807d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
808d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
809d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
810a552a69cSDamon Ding #define RK3568_ESMART0_COLOR_KEY_CTRL		0x18D0
811a552a69cSDamon Ding #define RK3576_ESMART0_ALPHA_MAP		0x18D8
812a552a69cSDamon Ding #define RK3576_ESMART0_PORT_SEL			0x18F4
813a552a69cSDamon Ding #define ESMART_PORT_SEL_SHIFT			0
814a552a69cSDamon Ding #define ESMART_PORT_SEL_MASK			0x3
815a552a69cSDamon Ding #define RK3576_ESMART0_DLY_NUM			0x18F8
816d0408543SAndy Yan 
817d0408543SAndy Yan #define RK3568_ESMART1_CTRL0			0x1A00
818d0408543SAndy Yan #define RK3568_ESMART1_CTRL1			0x1A04
819d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL		0x1A10
820d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
821d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
822d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR		0x1A1C
823d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
824d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
825d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
826d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
827d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
828d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
829d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
830d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL		0x1A40
831d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
832d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
833d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR		0x1A4C
834d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
835d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
836d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
837d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
838d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
839d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
840d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
841d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL		0x1A70
842d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
843d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
844d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR		0x1A7C
845d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
846d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
847d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
848d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
849d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
850d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
851d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
852d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
853d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
854d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
855d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR		0x1AAC
856d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
857d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
858d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
859d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
860d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
861d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
862d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
863a552a69cSDamon Ding #define RK3576_ESMART1_ALPHA_MAP		0x1AD8
864a552a69cSDamon Ding #define RK3576_ESMART1_PORT_SEL			0x1AF4
865a552a69cSDamon Ding #define RK3576_ESMART1_DLY_NUM			0x1AF8
866d0408543SAndy Yan 
867d0408543SAndy Yan #define RK3568_SMART0_CTRL0			0x1C00
868d0408543SAndy Yan #define RK3568_SMART0_CTRL1			0x1C04
869d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL		0x1C10
870d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
871d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
872d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR		0x1C1C
873d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
874d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
875d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
876d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
877d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
878d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
879d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
880d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL		0x1C40
881d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
882d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
883d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR		0x1C4C
884d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
885d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
886d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
887d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
888d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
889d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
890d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
891d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL		0x1C70
892d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
893d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
894d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR		0x1C7C
895d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
896d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
897d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
898d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
899d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
900d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
901d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
902d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL		0x1CA0
903d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
904d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
905d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR		0x1CAC
906d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
907d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
908d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
909d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
910d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
911d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
912d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
913a552a69cSDamon Ding #define RK3576_ESMART2_ALPHA_MAP		0x1CD8
914a552a69cSDamon Ding #define RK3576_ESMART2_PORT_SEL			0x1CF4
915a552a69cSDamon Ding #define RK3576_ESMART2_DLY_NUM			0x1CF8
916d0408543SAndy Yan 
917d0408543SAndy Yan #define RK3568_SMART1_CTRL0			0x1E00
918d0408543SAndy Yan #define RK3568_SMART1_CTRL1			0x1E04
919d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL		0x1E10
920d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
921d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
922d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR		0x1E1C
923d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
924d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
925d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
926d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
927d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
928d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
929d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
930d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL		0x1E40
931d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
932d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
933d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR		0x1E4C
934d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
935d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
936d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
937d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
938d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
939d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
940d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
941d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL		0x1E70
942d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
943d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
944d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR		0x1E7C
945d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
946d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
947d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
948d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
949d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
950d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
951d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
952d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL		0x1EA0
953d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
954d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
955d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR		0x1EAC
956d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
957d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
958d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
959d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
960d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
961d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
962d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
963a552a69cSDamon Ding #define RK3576_ESMART3_ALPHA_MAP		0x1ED8
964a552a69cSDamon Ding #define RK3576_ESMART3_PORT_SEL			0x1EF4
965a552a69cSDamon Ding #define RK3576_ESMART3_DLY_NUM			0x1EF8
966d0408543SAndy Yan 
96772388c26SDamon Ding /* HDR register definition */
96872388c26SDamon Ding #define RK3568_HDR_LUT_CTRL			0x2000
96972388c26SDamon Ding 
97072388c26SDamon Ding #define RK3588_VP3_DSP_CTRL			0xF00
97172388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0		0x1400
97272388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0		0x1600
97372388c26SDamon Ding 
97412ee5af0SDamon Ding /* DSC 8K/4K register definition */
97512ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3			0x4000
97612ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0			0x40A0
97712ee5af0SDamon Ding #define DSC_EN_SHIFT				0
97812ee5af0SDamon Ding #define DSC_RBIT_SHIFT				2
97912ee5af0SDamon Ding #define DSC_RBYT_SHIFT				3
98012ee5af0SDamon Ding #define DSC_FLAL_SHIFT				4
98112ee5af0SDamon Ding #define DSC_MER_SHIFT				5
98212ee5af0SDamon Ding #define DSC_EPB_SHIFT				6
98312ee5af0SDamon Ding #define DSC_EPL_SHIFT				7
9841ace1b6dSDamon Ding #define DSC_NSLC_MASK				0x7
98512ee5af0SDamon Ding #define DSC_NSLC_SHIFT				16
98612ee5af0SDamon Ding #define DSC_SBO_SHIFT				28
98712ee5af0SDamon Ding #define DSC_IFEP_SHIFT				29
98812ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT			31
989baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT)   | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \
990baf2c414SDamon Ding 			   (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT)  | (0 << DSC_EPB_SHIFT)  | \
991baf2c414SDamon Ding 			   (1 << DSC_EPL_SHIFT)  | (1 << DSC_SBO_SHIFT))
99212ee5af0SDamon Ding 
99312ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1			0x40A4
99412ee5af0SDamon Ding #define RK3588_DSC_8K_STS0			0x40A8
99512ee5af0SDamon Ding #define RK3588_DSC_8K_ERS			0x40C4
99612ee5af0SDamon Ding 
99712ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3			0x4100
99812ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0			0x41A0
99912ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1			0x41A4
100012ee5af0SDamon Ding #define RK3588_DSC_4K_STS0			0x41A8
100112ee5af0SDamon Ding #define RK3588_DSC_4K_ERS			0x41C4
100212ee5af0SDamon Ding 
100372388c26SDamon Ding /* RK3528 HDR register definition */
100472388c26SDamon Ding #define RK3528_HDR_LUT_CTRL			0x2000
100572388c26SDamon Ding 
10066027c871SZhang Yubing /* RK3528 ACM register definition */
10076027c871SZhang Yubing #define RK3528_ACM_CTRL				0x6400
10086027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE			0x6404
10096027c871SZhang Yubing #define RK3528_ACM_FETCH_START			0x6408
10106027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE			0x6420
10116027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0		0x6500
10126027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152		0x6760
10136027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0		0x6764
10146027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220		0x6ad4
10156027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0		0x6ad8
10166027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64		0x6bd8
10176027c871SZhang Yubing 
1018d0408543SAndy Yan #define RK3568_MAX_REG				0x1ED0
1019d0408543SAndy Yan 
1020452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON		0x10500
102152ee18acSSandy Huang #define RK3568_GRF_VO_CON1			0x0364
102252ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT			1
102352ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT		2
102452ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT			3
102552ee18acSSandy Huang 
1026a552a69cSDamon Ding /* Base SYS_GRF: 0x2600a000*/
1027a552a69cSDamon Ding #define RK3576_SYS_GRF_MEMFAULT_STATUS0		0x0148
1028a552a69cSDamon Ding 
1029a552a69cSDamon Ding /* Base IOC_GRF: 0x26040000 */
1030a552a69cSDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8		0x6420
1031a552a69cSDamon Ding #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT	9
1032a552a69cSDamon Ding #define RK3576_IOC_VOPLITE_SEL_SHIFT		11
1033a552a69cSDamon Ding 
1034a552a69cSDamon Ding /* Base PMU2: 0x27380000 */
1035a552a69cSDamon Ding #define RK3576_PMU_PWR_GATE_STS			0x0230
1036a552a69cSDamon Ding #define PD_VOP_ESMART_DWN_STAT			12
1037a552a69cSDamon Ding #define PD_VOP_CLUSTER_DWN_STAT			13
1038a552a69cSDamon Ding #define RK3576_PMU_BISR_PDGEN_CON0		0x0510
1039a552a69cSDamon Ding #define PD_VOP_ESMART_REPAIR_ENA_SHIFT		12
1040a552a69cSDamon Ding #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT		13
1041a552a69cSDamon Ding #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0	0x0570
1042a552a69cSDamon Ding #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT	12
1043a552a69cSDamon Ding #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT	13
1044a552a69cSDamon Ding 
10455d2768f7SDamon Ding #define RK3588_GRF_SOC_CON1			0x0304
10465d2768f7SDamon Ding #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT	14
10475d2768f7SDamon Ding 
1048ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2			0x0008
1049ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT		0
1050ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT		1
1051ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT		3
1052ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT		4
1053ecc31b6eSAndy Yan 
1054b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0			0x0000
1055b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK			0x3
1056b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT			5
1057b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT			7
1058b890760eSAlgea Cao 
105960e469f5SDamon Ding #define RK3588_PMU_BISR_CON3			0x20C
106060e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT	9
106160e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT	10
106260e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT	11
106360e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT	12
1064b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT	13
1065b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT	14
106660e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT	15
106760e469f5SDamon Ding 
106860e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5			0x294
106960e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI	9
107060e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI	10
107160e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI	11
107260e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI	12
1073b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI		13
1074b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI		14
107560e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI		15
107660e469f5SDamon Ding 
1077d0408543SAndy Yan #define VOP2_LAYER_MAX				8
107863cb669fSSandy Huang 
1079ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH		4096
1080ee01dbb2SDamon Ding 
1081631ee99aSZhang Yubing /* KHz */
1082631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE			600000
1083631ee99aSZhang Yubing 
1084b6ba80b4SDamon Ding /*
1085b6ba80b4SDamon Ding  * vop2 dsc id
1086b6ba80b4SDamon Ding  */
1087b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K	0
1088b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K	1
1089b6ba80b4SDamon Ding 
1090b6ba80b4SDamon Ding /*
1091b6ba80b4SDamon Ding  * vop2 internal power domain id,
1092b6ba80b4SDamon Ding  * should be all none zero, 0 will be
1093b6ba80b4SDamon Ding  * treat as invalid;
1094b6ba80b4SDamon Ding  */
1095b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0			BIT(0)
1096b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1			BIT(1)
1097b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2			BIT(2)
1098b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3			BIT(3)
1099b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K				BIT(5)
1100b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K				BIT(6)
1101b6ba80b4SDamon Ding #define VOP2_PD_ESMART				BIT(7)
1102a552a69cSDamon Ding #define VOP2_PD_CLUSTER				BIT(8)
1103b6ba80b4SDamon Ding 
11044c765862SDamon Ding #define VOP2_PLANE_NO_SCALING			BIT(16)
11054c765862SDamon Ding 
11065fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT	BIT(0)
11075fa6e665SDamon Ding #define VOP_FEATURE_AFBDC		BIT(1)
11085fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE		BIT(2)
11095fa6e665SDamon Ding #define VOP_FEATURE_HDR10		BIT(3)
11105fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR		BIT(4)
11115fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */
11125fa6e665SDamon Ding #define VOP_FEATURE_SPLICE		BIT(5)
11135fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN		BIT(6)
11146027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR		BIT(7)
11156027c871SZhang Yubing #define VOP_FEATURE_POST_ACM		BIT(8)
11166027c871SZhang Yubing #define VOP_FEATURE_POST_CSC		BIT(9)
1117a552a69cSDamon Ding #define VOP_FEATURE_POST_FRC_V2		BIT(10)
1118a552a69cSDamon Ding #define VOP_FEATURE_POST_SHARP		BIT(11)
11195fa6e665SDamon Ding 
11205fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR		BIT(0)
11215fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR		BIT(1)
11225fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY		BIT(2)
11235fa6e665SDamon Ding #define WIN_FEATURE_AFBDC		BIT(3)
11245fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
11255fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB		BIT(5)
11265fa6e665SDamon Ding /* a mirror win can only get fb address
11275fa6e665SDamon Ding  * from source win:
11285fa6e665SDamon Ding  * Cluster1---->Cluster0
11295fa6e665SDamon Ding  * Esmart1 ---->Esmart0
11305fa6e665SDamon Ding  * Smart1  ---->Smart0
11315fa6e665SDamon Ding  * This is a feather on rk3566
11325fa6e665SDamon Ding  */
11335fa6e665SDamon Ding #define WIN_FEATURE_MIRROR		BIT(6)
11345fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA		BIT(7)
11355fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH	BIT(8)
1136a552a69cSDamon Ding #define WIN_FEATURE_DCI			BIT(9)
11375fa6e665SDamon Ding 
11385fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F		0xfe
11395fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F		0xff
11405fa6e665SDamon Ding 
11415fa6e665SDamon Ding enum vop_csc_format {
114210ee9f5bSAlgea Cao 	CSC_BT601L,
114310ee9f5bSAlgea Cao 	CSC_BT709L,
114410ee9f5bSAlgea Cao 	CSC_BT601F,
1145df0a5c43SDamon Ding 	CSC_BT2020L,
11465fa6e665SDamon Ding 	CSC_BT709L_13BIT,
11475fa6e665SDamon Ding 	CSC_BT709F_13BIT,
11485fa6e665SDamon Ding 	CSC_BT2020L_13BIT,
11495fa6e665SDamon Ding 	CSC_BT2020F_13BIT,
11505fa6e665SDamon Ding };
11515fa6e665SDamon Ding 
11525fa6e665SDamon Ding enum vop_csc_bit_depth {
11535fa6e665SDamon Ding 	CSC_10BIT_DEPTH,
11545fa6e665SDamon Ding 	CSC_13BIT_DEPTH,
115510ee9f5bSAlgea Cao };
115610ee9f5bSAlgea Cao 
115710ee9f5bSAlgea Cao enum vop2_pol {
115810ee9f5bSAlgea Cao 	HSYNC_POSITIVE = 0,
115910ee9f5bSAlgea Cao 	VSYNC_POSITIVE = 1,
116010ee9f5bSAlgea Cao 	DEN_NEGATIVE   = 2,
116110ee9f5bSAlgea Cao 	DCLK_INVERT    = 3
116210ee9f5bSAlgea Cao };
116310ee9f5bSAlgea Cao 
1164ac500a1fSSandy Huang enum vop2_bcsh_out_mode {
1165ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLACK,
1166ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLUE,
1167ac500a1fSSandy Huang 	BCSH_OUT_MODE_COLOR_BAR,
1168ac500a1fSSandy Huang 	BCSH_OUT_MODE_NORMAL_VIDEO,
1169ac500a1fSSandy Huang };
1170ac500a1fSSandy Huang 
1171d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \
1172d0408543SAndy Yan 		{ \
1173d0408543SAndy Yan 		 .offset = off, \
1174d0408543SAndy Yan 		 .mask = _mask, \
1175d0408543SAndy Yan 		 .shift = _shift, \
1176d0408543SAndy Yan 		 .write_mask = _write_mask, \
1177d0408543SAndy Yan 		}
1178d0408543SAndy Yan 
1179d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \
1180d0408543SAndy Yan 		_VOP_REG(off, _mask, _shift, false)
1181d0408543SAndy Yan enum dither_down_mode {
1182d0408543SAndy Yan 	RGB888_TO_RGB565 = 0x0,
1183d0408543SAndy Yan 	RGB888_TO_RGB666 = 0x1
1184d0408543SAndy Yan };
1185d0408543SAndy Yan 
1186a552a69cSDamon Ding enum dither_down_mode_sel {
1187a552a69cSDamon Ding 	DITHER_DOWN_ALLEGRO = 0x0,
1188a552a69cSDamon Ding 	DITHER_DOWN_FRC = 0x1
1189a552a69cSDamon Ding };
1190a552a69cSDamon Ding 
1191d0408543SAndy Yan enum vop2_video_ports_id {
1192d0408543SAndy Yan 	VOP2_VP0,
1193d0408543SAndy Yan 	VOP2_VP1,
1194d0408543SAndy Yan 	VOP2_VP2,
1195d0408543SAndy Yan 	VOP2_VP3,
1196d0408543SAndy Yan 	VOP2_VP_MAX,
1197d0408543SAndy Yan };
1198d0408543SAndy Yan 
1199ee008497SSandy Huang enum vop2_layer_type {
1200ee008497SSandy Huang 	CLUSTER_LAYER = 0,
1201ee008497SSandy Huang 	ESMART_LAYER = 1,
1202ee008497SSandy Huang 	SMART_LAYER = 2,
1203ee008497SSandy Huang };
1204ee008497SSandy Huang 
1205b0989546SSandy Huang /* This define must same with kernel win phy id */
1206b0989546SSandy Huang enum vop2_layer_phy_id {
1207b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER0 = 0,
1208b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER1,
1209b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART0,
1210b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART1,
1211b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART0,
1212b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART1,
1213b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER2,
1214b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER3,
1215b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART2,
1216b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART3,
1217ee008497SSandy Huang 	ROCKCHIP_VOP2_LAYER_MAX,
121827cec8e2SDamon Ding 	ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
1219d0408543SAndy Yan };
1220d0408543SAndy Yan 
12213e39a5a1SSandy Huang enum vop2_scale_up_mode {
12223e39a5a1SSandy Huang 	VOP2_SCALE_UP_NRST_NBOR,
12233e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIL,
12243e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIC,
1225a552a69cSDamon Ding 	VOP2_SCALE_UP_ZME,
12263e39a5a1SSandy Huang };
12273e39a5a1SSandy Huang 
12283e39a5a1SSandy Huang enum vop2_scale_down_mode {
12293e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_NRST_NBOR,
12303e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_BIL,
12313e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_AVG,
1232a552a69cSDamon Ding 	VOP2_SCALE_DOWN_ZME,
12333e39a5a1SSandy Huang };
12343e39a5a1SSandy Huang 
12353e39a5a1SSandy Huang enum scale_mode {
12363e39a5a1SSandy Huang 	SCALE_NONE = 0x0,
12373e39a5a1SSandy Huang 	SCALE_UP   = 0x1,
12383e39a5a1SSandy Huang 	SCALE_DOWN = 0x2
12393e39a5a1SSandy Huang };
12403e39a5a1SSandy Huang 
124112ee5af0SDamon Ding enum vop_dsc_interface_mode {
124212ee5af0SDamon Ding 	VOP_DSC_IF_DISABLE = 0,
124312ee5af0SDamon Ding 	VOP_DSC_IF_HDMI = 1,
124412ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_DS_MODE = 2,
124512ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_VIDEO_MODE = 3,
124612ee5af0SDamon Ding };
124712ee5af0SDamon Ding 
12485fa6e665SDamon Ding enum vop3_pre_scale_down_mode {
12495fa6e665SDamon Ding 	VOP3_PRE_SCALE_UNSPPORT,
12505fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_GT,
12515fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_AVG,
12525fa6e665SDamon Ding };
12535fa6e665SDamon Ding 
12545fa6e665SDamon Ding enum vop3_esmart_lb_mode {
12555fa6e665SDamon Ding 	VOP3_ESMART_8K_MODE,
12565fa6e665SDamon Ding 	VOP3_ESMART_4K_4K_MODE,
12575fa6e665SDamon Ding 	VOP3_ESMART_4K_2K_2K_MODE,
12585fa6e665SDamon Ding 	VOP3_ESMART_2K_2K_2K_2K_MODE,
1259a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_4K_MODE,
1260a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_2K_2K_MODE,
12615fa6e665SDamon Ding };
12625fa6e665SDamon Ding 
12633e39a5a1SSandy Huang struct vop2_layer {
12643e39a5a1SSandy Huang 	u8 id;
12653e39a5a1SSandy Huang 	/**
12663e39a5a1SSandy Huang 	 * @win_phys_id: window id of the layer selected.
12673e39a5a1SSandy Huang 	 * Every layer must make sure to select different
12683e39a5a1SSandy Huang 	 * windows of others.
12693e39a5a1SSandy Huang 	 */
12703e39a5a1SSandy Huang 	u8 win_phys_id;
12713e39a5a1SSandy Huang };
12723e39a5a1SSandy Huang 
127360e469f5SDamon Ding struct vop2_power_domain_data {
1274a552a69cSDamon Ding 	u16 id;
1275a552a69cSDamon Ding 	u16 parent_id;
1276b6ba80b4SDamon Ding 	/*
1277b6ba80b4SDamon Ding 	 * @module_id_mask: module id of which module this power domain is belongs to.
1278b6ba80b4SDamon Ding 	 * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3
1279b6ba80b4SDamon Ding 	 */
1280b6ba80b4SDamon Ding 	u32 module_id_mask;
128160e469f5SDamon Ding };
128260e469f5SDamon Ding 
1283b0989546SSandy Huang struct vop2_win_data {
1284b0989546SSandy Huang 	char *name;
128563cb669fSSandy Huang 	u8 phys_id;
1286ecc31b6eSAndy Yan 	enum vop2_layer_type type;
1287b0989546SSandy Huang 	u8 win_sel_port_offset;
12885fa6e665SDamon Ding 	u8 layer_sel_win_id[VOP2_VP_MAX];
1289a33b790fSDamon Ding 	u8 axi_id;
1290a33b790fSDamon Ding 	u8 axi_uv_id;
1291a33b790fSDamon Ding 	u8 axi_yrgb_id;
1292ee01dbb2SDamon Ding 	u8 splice_win_id;
12935fa6e665SDamon Ding 	u8 hsu_filter_mode;
12945fa6e665SDamon Ding 	u8 hsd_filter_mode;
12955fa6e665SDamon Ding 	u8 vsu_filter_mode;
12965fa6e665SDamon Ding 	u8 vsd_filter_mode;
12975fa6e665SDamon Ding 	u8 hsd_pre_filter_mode;
12985fa6e665SDamon Ding 	u8 vsd_pre_filter_mode;
12995fa6e665SDamon Ding 	u8 scale_engine_num;
13001c9572c7SDamon Ding 	u8 source_win_id;
1301a552a69cSDamon Ding 	u8 possible_crtcs;
1302a552a69cSDamon Ding 	u16 pd_id;
1303b0989546SSandy Huang 	u32 reg_offset;
13044c765862SDamon Ding 	u32 max_upscale_factor;
13054c765862SDamon Ding 	u32 max_downscale_factor;
13061c9572c7SDamon Ding 	u32 feature;
1307a552a69cSDamon Ding 	u32 supported_rotations;
1308ee01dbb2SDamon Ding 	bool splice_mode_right;
130963cb669fSSandy Huang };
131063cb669fSSandy Huang 
131163cb669fSSandy Huang struct vop2_vp_data {
131263cb669fSSandy Huang 	u32 feature;
131344b1b62cSDamon Ding 	u32 max_dclk;
131463cb669fSSandy Huang 	u8 pre_scan_max_dly;
1315452afb13SDamon Ding 	u8 layer_mix_dly;
1316a552a69cSDamon Ding 	u8 hdrvivid_dly;
1317a552a69cSDamon Ding 	u8 sdr2hdr_dly;
1318452afb13SDamon Ding 	u8 hdr_mix_dly;
1319452afb13SDamon Ding 	u8 win_dly;
1320ee01dbb2SDamon Ding 	u8 splice_vp_id;
1321a552a69cSDamon Ding 	u8 pixel_rate;
132263cb669fSSandy Huang 	struct vop_rect max_output;
132344b1b62cSDamon Ding 	struct vop_urgency *urgency;
1324d0408543SAndy Yan };
1325d0408543SAndy Yan 
1326ee008497SSandy Huang struct vop2_plane_table {
1327ee008497SSandy Huang 	enum vop2_layer_phy_id plane_id;
1328ee008497SSandy Huang 	enum vop2_layer_type plane_type;
1329ee008497SSandy Huang };
1330ee008497SSandy Huang 
1331b0989546SSandy Huang struct vop2_vp_plane_mask {
1332b0989546SSandy Huang 	u8 primary_plane_id; /* use this win to show logo */
1333b0989546SSandy Huang 	u8 attached_layers_nr; /* number layers attach to this vp */
1334b0989546SSandy Huang 	u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
1335b0989546SSandy Huang 	u32 plane_mask;
1336ee008497SSandy Huang 	int cursor_plane_id;
1337b0989546SSandy Huang };
1338b0989546SSandy Huang 
133912ee5af0SDamon Ding struct vop2_dsc_data {
134012ee5af0SDamon Ding 	u8 id;
134112ee5af0SDamon Ding 	u8 max_slice_num;
134212ee5af0SDamon Ding 	u8 max_linebuf_depth;	/* used to generate the bitstream */
134312ee5af0SDamon Ding 	u8 min_bits_per_pixel;	/* bit num after encoder compress */
1344a552a69cSDamon Ding 	u16 pd_id;
134512ee5af0SDamon Ding 	const char *dsc_txp_clk_src_name;
134612ee5af0SDamon Ding 	const char *dsc_txp_clk_name;
134712ee5af0SDamon Ding 	const char *dsc_pxl_clk_name;
134812ee5af0SDamon Ding 	const char *dsc_cds_clk_name;
134912ee5af0SDamon Ding };
135012ee5af0SDamon Ding 
135112ee5af0SDamon Ding struct dsc_error_info {
135212ee5af0SDamon Ding 	u32 dsc_error_val;
135312ee5af0SDamon Ding 	char dsc_error_info[50];
135412ee5af0SDamon Ding };
135512ee5af0SDamon Ding 
135672388c26SDamon Ding struct vop2_dump_regs {
135772388c26SDamon Ding 	u32 offset;
135872388c26SDamon Ding 	const char *name;
135972388c26SDamon Ding 	u32 state_base;
136072388c26SDamon Ding 	u32 state_mask;
136172388c26SDamon Ding 	u32 state_shift;
136272388c26SDamon Ding 	bool enable_state;
1363a552a69cSDamon Ding 	u32 size;
1364a552a69cSDamon Ding };
1365a552a69cSDamon Ding 
1366a552a69cSDamon Ding struct vop2_esmart_lb_map {
1367a552a69cSDamon Ding 	u8 lb_mode;
1368a552a69cSDamon Ding 	u8 lb_map_value;
136972388c26SDamon Ding };
137072388c26SDamon Ding 
1371d0408543SAndy Yan struct vop2_data {
137252ee18acSSandy Huang 	u32 version;
13735fa6e665SDamon Ding 	u32 esmart_lb_mode;
137463cb669fSSandy Huang 	struct vop2_vp_data *vp_data;
1375b0989546SSandy Huang 	struct vop2_win_data *win_data;
1376b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
1377ee008497SSandy Huang 	struct vop2_plane_table *plane_table;
1378b6ba80b4SDamon Ding 	struct vop2_power_domain_data *pd;
137912ee5af0SDamon Ding 	struct vop2_dsc_data *dsc;
138012ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_ecw;
138112ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_buffer_flow;
138272388c26SDamon Ding 	struct vop2_dump_regs *dump_regs;
1383a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map;
1384337d1c13SDamon Ding 	u8 *vp_primary_plane_order;
1385a552a69cSDamon Ding 	u8 *vp_default_primary_plane;
138663cb669fSSandy Huang 	u8 nr_vps;
138763cb669fSSandy Huang 	u8 nr_layers;
138863cb669fSSandy Huang 	u8 nr_mixers;
13891147facaSSandy Huang 	u8 nr_gammas;
1390b6ba80b4SDamon Ding 	u8 nr_pd;
139112ee5af0SDamon Ding 	u8 nr_dscs;
139212ee5af0SDamon Ding 	u8 nr_dsc_ecw;
139312ee5af0SDamon Ding 	u8 nr_dsc_buffer_flow;
1394a552a69cSDamon Ding 	u8 esmart_lb_mode_num;
1395ecc31b6eSAndy Yan 	u32 reg_len;
139672388c26SDamon Ding 	u32 dump_regs_size;
1397d0408543SAndy Yan };
1398d0408543SAndy Yan 
1399d0408543SAndy Yan struct vop2 {
1400d0408543SAndy Yan 	u32 *regsbak;
1401d0408543SAndy Yan 	void *regs;
1402d0408543SAndy Yan 	void *grf;
1403ecc31b6eSAndy Yan 	void *vop_grf;
1404ecc31b6eSAndy Yan 	void *vo1_grf;
140560e469f5SDamon Ding 	void *sys_pmu;
1406a552a69cSDamon Ding 	void *ioc_grf;
140752ee18acSSandy Huang 	u32 reg_len;
140852ee18acSSandy Huang 	u32 version;
14095fa6e665SDamon Ding 	u32 esmart_lb_mode;
141063cb669fSSandy Huang 	bool global_init;
1411a552a69cSDamon Ding 	bool merge_irq;
1412d0408543SAndy Yan 	const struct vop2_data *data;
1413b0989546SSandy Huang 	struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
1414d0408543SAndy Yan };
1415d0408543SAndy Yan 
1416d0408543SAndy Yan static struct vop2 *rockchip_vop2;
14175fa6e665SDamon Ding 
141827cec8e2SDamon Ding /* vop2_layer_phy_id */
141927cec8e2SDamon Ding static const char *const vop2_layer_name_list[] = {
142027cec8e2SDamon Ding 	"Cluster0",
142127cec8e2SDamon Ding 	"Cluster1",
142227cec8e2SDamon Ding 	"Esmart0",
142327cec8e2SDamon Ding 	"Esmart1",
142427cec8e2SDamon Ding 	"Smart0",
142527cec8e2SDamon Ding 	"Smart1",
142627cec8e2SDamon Ding 	"Cluster2",
142727cec8e2SDamon Ding 	"Cluster3",
142827cec8e2SDamon Ding 	"Esmart2",
142927cec8e2SDamon Ding 	"Esmart3",
143027cec8e2SDamon Ding };
143127cec8e2SDamon Ding 
143227cec8e2SDamon Ding static inline const char *vop2_plane_id_to_string(unsigned long phy)
143327cec8e2SDamon Ding {
143427cec8e2SDamon Ding 	if (phy == ROCKCHIP_VOP2_PHY_ID_INVALID)
143527cec8e2SDamon Ding 		return "INVALID";
143627cec8e2SDamon Ding 
143727cec8e2SDamon Ding 	if (WARN_ON(phy >= ARRAY_SIZE(vop2_layer_name_list)))
143827cec8e2SDamon Ding 		return NULL;
143927cec8e2SDamon Ding 
144027cec8e2SDamon Ding 	return vop2_layer_name_list[phy];
144127cec8e2SDamon Ding }
144227cec8e2SDamon Ding 
14435fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2)
14445fa6e665SDamon Ding {
14455fa6e665SDamon Ding 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588)
14465fa6e665SDamon Ding 		return false;
14475fa6e665SDamon Ding 	else
14485fa6e665SDamon Ding 		return true;
14495fa6e665SDamon Ding }
14505fa6e665SDamon Ding 
14513e39a5a1SSandy Huang /*
14523e39a5a1SSandy Huang  * bli_sd_factor = (src - 1) / (dst - 1) << 12;
14533e39a5a1SSandy Huang  * avg_sd_factor:
14543e39a5a1SSandy Huang  * bli_su_factor:
14553e39a5a1SSandy Huang  * bic_su_factor:
14563e39a5a1SSandy Huang  * = (src - 1) / (dst - 1) << 16;
14573e39a5a1SSandy Huang  *
14585fa6e665SDamon Ding  * ygt2 enable: dst get one line from two line of the src
14595fa6e665SDamon Ding  * ygt4 enable: dst get one line from four line of the src.
14603e39a5a1SSandy Huang  *
14613e39a5a1SSandy Huang  */
14623e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst)	(((src - 1) << 12) / (dst - 1))
14633e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst)	(((src - 1) << 16) / (dst - 1))
14643e39a5a1SSandy Huang 
14653e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)	 \
14663e39a5a1SSandy Huang 				(fac * (dst - 1) >> 12 < (src - 1))
14673e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
14683e39a5a1SSandy Huang 				(fac * (dst - 1) >> 16 < (src - 1))
14695fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
14705fa6e665SDamon Ding 				(fac * (dst - 1) >> 16 < (src - 1))
14713e39a5a1SSandy Huang 
14723e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode,
14733e39a5a1SSandy Huang 				  int32_t filter_mode,
14743e39a5a1SSandy Huang 				  uint32_t src, uint32_t dst)
14753e39a5a1SSandy Huang {
14763e39a5a1SSandy Huang 	uint32_t fac = 0;
14773e39a5a1SSandy Huang 	int i = 0;
14783e39a5a1SSandy Huang 
14793e39a5a1SSandy Huang 	if (mode == SCALE_NONE)
14803e39a5a1SSandy Huang 		return 0;
14813e39a5a1SSandy Huang 
14823e39a5a1SSandy Huang 	/*
14833e39a5a1SSandy Huang 	 * A workaround to avoid zero div.
14843e39a5a1SSandy Huang 	 */
14853e39a5a1SSandy Huang 	if ((dst == 1) || (src == 1)) {
14863e39a5a1SSandy Huang 		dst = dst + 1;
14873e39a5a1SSandy Huang 		src = src + 1;
14883e39a5a1SSandy Huang 	}
14893e39a5a1SSandy Huang 
14903e39a5a1SSandy Huang 	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
14913e39a5a1SSandy Huang 		fac = VOP2_BILI_SCL_DN(src, dst);
14923e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
14933e39a5a1SSandy Huang 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
14943e39a5a1SSandy Huang 				break;
14953e39a5a1SSandy Huang 			fac -= 1;
14963e39a5a1SSandy Huang 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
14973e39a5a1SSandy Huang 		}
14983e39a5a1SSandy Huang 	} else {
14993e39a5a1SSandy Huang 		fac = VOP2_COMMON_SCL(src, dst);
15003e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
15013e39a5a1SSandy Huang 			if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
15023e39a5a1SSandy Huang 				break;
15033e39a5a1SSandy Huang 			fac -= 1;
15043e39a5a1SSandy Huang 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15053e39a5a1SSandy Huang 		}
15063e39a5a1SSandy Huang 	}
15073e39a5a1SSandy Huang 
15083e39a5a1SSandy Huang 	return fac;
15093e39a5a1SSandy Huang }
15103e39a5a1SSandy Huang 
15115fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor)
15125fa6e665SDamon Ding {
15135fa6e665SDamon Ding 	if (is_hor)
15145fa6e665SDamon Ding 		return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac);
15155fa6e665SDamon Ding 	return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac);
15165fa6e665SDamon Ding }
15175fa6e665SDamon Ding 
15185fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode,
15195fa6e665SDamon Ding 				  uint32_t src, uint32_t dst, bool is_hor)
15205fa6e665SDamon Ding {
15215fa6e665SDamon Ding 	uint32_t fac = 0;
15225fa6e665SDamon Ding 	int i = 0;
15235fa6e665SDamon Ding 
15245fa6e665SDamon Ding 	if (mode == SCALE_NONE)
15255fa6e665SDamon Ding 		return 0;
15265fa6e665SDamon Ding 
15275fa6e665SDamon Ding 	/*
15285fa6e665SDamon Ding 	 * A workaround to avoid zero div.
15295fa6e665SDamon Ding 	 */
15305fa6e665SDamon Ding 	if ((dst == 1) || (src == 1)) {
15315fa6e665SDamon Ding 		dst = dst + 1;
15325fa6e665SDamon Ding 		src = src + 1;
15335fa6e665SDamon Ding 	}
15345fa6e665SDamon Ding 
15355fa6e665SDamon Ding 	if (mode == SCALE_DOWN) {
15365fa6e665SDamon Ding 		fac = VOP2_BILI_SCL_DN(src, dst);
15375fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
15385fa6e665SDamon Ding 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
15395fa6e665SDamon Ding 				break;
15405fa6e665SDamon Ding 			fac -= 1;
15415fa6e665SDamon Ding 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15425fa6e665SDamon Ding 		}
15435fa6e665SDamon Ding 	} else {
15445fa6e665SDamon Ding 		fac = VOP2_COMMON_SCL(src, dst);
15455fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
15465fa6e665SDamon Ding 			if (vop3_scale_up_fac_check(src, dst, fac, is_hor))
15475fa6e665SDamon Ding 				break;
15485fa6e665SDamon Ding 			fac -= 1;
15495fa6e665SDamon Ding 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15505fa6e665SDamon Ding 		}
15515fa6e665SDamon Ding 	}
15525fa6e665SDamon Ding 
15535fa6e665SDamon Ding 	return fac;
15545fa6e665SDamon Ding }
15555fa6e665SDamon Ding 
15563e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst)
15573e39a5a1SSandy Huang {
15583e39a5a1SSandy Huang 	if (src < dst)
15593e39a5a1SSandy Huang 		return SCALE_UP;
15603e39a5a1SSandy Huang 	else if (src > dst)
15613e39a5a1SSandy Huang 		return SCALE_DOWN;
15623e39a5a1SSandy Huang 
15633e39a5a1SSandy Huang 	return SCALE_NONE;
15643e39a5a1SSandy Huang }
1565d0408543SAndy Yan 
1566ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x)
1567ac500a1fSSandy Huang {
1568ac500a1fSSandy Huang 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
1569ac500a1fSSandy Huang }
1570ac500a1fSSandy Huang 
1571b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask)
1572b0989546SSandy Huang {
1573b0989546SSandy Huang 	int i = 0;
1574ecc31b6eSAndy Yan 
1575337d1c13SDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
1576337d1c13SDamon Ding 		if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i]))
1577337d1c13SDamon Ding 			return vop2->data->vp_primary_plane_order[i];
1578ecc31b6eSAndy Yan 	}
1579b0989546SSandy Huang 
1580337d1c13SDamon Ding 	return vop2->data->vp_primary_plane_order[0];
1581b0989546SSandy Huang }
1582b0989546SSandy Huang 
158363cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift)
1584d0408543SAndy Yan {
1585d0408543SAndy Yan 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
1586d0408543SAndy Yan }
1587d0408543SAndy Yan 
158863cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst)
1589d0408543SAndy Yan {
1590d0408543SAndy Yan 	return ((src - 1) << 12) / (dst - 1);
1591d0408543SAndy Yan }
1592d0408543SAndy Yan 
159352ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
1594d0408543SAndy Yan {
1595d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1596d0408543SAndy Yan 	vop2->regsbak[offset >> 2] = v;
1597d0408543SAndy Yan }
1598d0408543SAndy Yan 
159952ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
1600d0408543SAndy Yan {
1601d0408543SAndy Yan 	return readl(vop2->regs + offset);
1602d0408543SAndy Yan }
1603d0408543SAndy Yan 
160452ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
160552ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v,
1606d0408543SAndy Yan 				   bool write_mask)
1607d0408543SAndy Yan {
1608d0408543SAndy Yan 	if (!mask)
1609d0408543SAndy Yan 		return;
1610d0408543SAndy Yan 
1611d0408543SAndy Yan 	if (write_mask) {
1612d0408543SAndy Yan 		v = ((v & mask) << shift) | (mask << (shift + 16));
1613d0408543SAndy Yan 	} else {
161452ee18acSSandy Huang 		u32 cached_val = vop2->regsbak[offset >> 2];
1615d0408543SAndy Yan 
1616d0408543SAndy Yan 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
1617d0408543SAndy Yan 		vop2->regsbak[offset >> 2] = v;
1618d0408543SAndy Yan 	}
1619d0408543SAndy Yan 
1620d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1621d0408543SAndy Yan }
1622d0408543SAndy Yan 
1623ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
162452ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v)
162552ee18acSSandy Huang {
162652ee18acSSandy Huang 	u32 val = 0;
162752ee18acSSandy Huang 
162852ee18acSSandy Huang 	val = (v << shift) | (mask << (shift + 16));
1629ecc31b6eSAndy Yan 	writel(val, grf_base + offset);
163052ee18acSSandy Huang }
163152ee18acSSandy Huang 
163260e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
163360e469f5SDamon Ding 				  u32 mask, u32 shift)
163460e469f5SDamon Ding {
163560e469f5SDamon Ding 	return (readl(grf_base + offset) >> shift) & mask;
163660e469f5SDamon Ding }
163760e469f5SDamon Ding 
163852ee18acSSandy Huang static bool is_yuv_output(u32 bus_format)
1639d0408543SAndy Yan {
1640d0408543SAndy Yan 	switch (bus_format) {
1641d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
1642d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
1643034a46b5SAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
1644d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1645d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1646a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
1647a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
1648a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_2X8:
1649a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_2X8:
1650a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
1651a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
1652a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_1X16:
1653a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_1X16:
1654d0408543SAndy Yan 		return true;
1655d0408543SAndy Yan 	default:
1656d0408543SAndy Yan 		return false;
1657d0408543SAndy Yan 	}
1658d0408543SAndy Yan }
1659d0408543SAndy Yan 
1660df0a5c43SDamon Ding static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding,
1661df0a5c43SDamon Ding 						 enum drm_color_range color_range,
1662df0a5c43SDamon Ding 						 int bit_depth)
166310ee9f5bSAlgea Cao {
1664df0a5c43SDamon Ding 	bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
1665df0a5c43SDamon Ding 	enum vop_csc_format csc_mode = CSC_BT709L;
1666df0a5c43SDamon Ding 
1667df0a5c43SDamon Ding 
1668df0a5c43SDamon Ding 	switch (color_encoding) {
1669df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT601:
1670df0a5c43SDamon Ding 		if (full_range)
1671df0a5c43SDamon Ding 			csc_mode = CSC_BT601F;
16725fa6e665SDamon Ding 		else
1673df0a5c43SDamon Ding 			csc_mode = CSC_BT601L;
1674df0a5c43SDamon Ding 		break;
1675df0a5c43SDamon Ding 
1676df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT709:
1677df0a5c43SDamon Ding 		if (full_range) {
1678df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F;
1679df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1680df0a5c43SDamon Ding 				printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n");
16815fa6e665SDamon Ding 		} else {
1682df0a5c43SDamon Ding 			csc_mode = CSC_BT709L;
16835fa6e665SDamon Ding 		}
1684df0a5c43SDamon Ding 		break;
1685df0a5c43SDamon Ding 
1686df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT2020:
1687df0a5c43SDamon Ding 		if (full_range) {
1688df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F;
1689df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1690df0a5c43SDamon Ding 				printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n");
16915fa6e665SDamon Ding 		} else {
1692df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L;
16935fa6e665SDamon Ding 		}
1694df0a5c43SDamon Ding 		break;
1695df0a5c43SDamon Ding 
169610ee9f5bSAlgea Cao 	default:
1697df0a5c43SDamon Ding 		printf("Unsuport color_encoding:%d\n", color_encoding);
169810ee9f5bSAlgea Cao 	}
1699df0a5c43SDamon Ding 
1700df0a5c43SDamon Ding 	return csc_mode;
170110ee9f5bSAlgea Cao }
170210ee9f5bSAlgea Cao 
1703c8820b76SDamon Ding static bool is_uv_swap(struct display_state *state)
1704d0408543SAndy Yan {
1705c8820b76SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
1706c8820b76SDamon Ding 	u32 bus_format = conn_state->bus_format;
1707c8820b76SDamon Ding 	u32 output_mode = conn_state->output_mode;
1708c8820b76SDamon Ding 	u32 output_type = conn_state->type;
1709c8820b76SDamon Ding 
1710d0408543SAndy Yan 	/*
1711d0408543SAndy Yan 	 * FIXME:
1712d0408543SAndy Yan 	 *
1713d0408543SAndy Yan 	 * There is no media type for YUV444 output,
1714d0408543SAndy Yan 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
1715d0408543SAndy Yan 	 * yuv format.
1716d0408543SAndy Yan 	 *
1717c8820b76SDamon Ding 	 * From H/W testing, YUV444 mode need a rb swap except eDP.
1718d0408543SAndy Yan 	 */
17193e59c137SSandy Huang 	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
17203e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
17213e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
17223e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
17233e59c137SSandy Huang 	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1724d0408543SAndy Yan 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1725d0408543SAndy Yan 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
1726c8820b76SDamon Ding 	     output_mode == ROCKCHIP_OUT_MODE_P888) &&
1727c8820b76SDamon Ding 	     !(output_type == DRM_MODE_CONNECTOR_eDP)))
1728d0408543SAndy Yan 		return true;
1729d0408543SAndy Yan 	else
1730d0408543SAndy Yan 		return false;
1731d0408543SAndy Yan }
1732d0408543SAndy Yan 
1733c8820b76SDamon Ding static bool is_rb_swap(struct display_state *state)
17340675a2a4SDamon Ding {
1735c8820b76SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
1736c8820b76SDamon Ding 	u32 bus_format = conn_state->bus_format;
1737c8820b76SDamon Ding 
17380675a2a4SDamon Ding 	/*
17390675a2a4SDamon Ding 	 * The default component order of serial rgb3x8 formats
17400675a2a4SDamon Ding 	 * is BGR. So it is needed to enable RB swap.
17410675a2a4SDamon Ding 	 */
1742b7b383ebSDamon Ding 	if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
1743b7b383ebSDamon Ding 	    bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8)
17440675a2a4SDamon Ding 		return true;
17450675a2a4SDamon Ding 	else
17460675a2a4SDamon Ding 		return false;
17470675a2a4SDamon Ding }
17480675a2a4SDamon Ding 
17495d2768f7SDamon Ding static bool is_yc_swap(u32 bus_format)
17505d2768f7SDamon Ding {
17515d2768f7SDamon Ding 	switch (bus_format) {
17525d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
17535d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
17545d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
17555d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
17565d2768f7SDamon Ding 		return true;
17575d2768f7SDamon Ding 	default:
17585d2768f7SDamon Ding 		return false;
17595d2768f7SDamon Ding 	}
17605d2768f7SDamon Ding }
17615d2768f7SDamon Ding 
1762b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type)
176363cb669fSSandy Huang {
1764b0989546SSandy Huang 	switch (output_type) {
1765b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIA:
1766b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIB:
1767b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_TV:
1768b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_DisplayPort:
1769b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_VGA:
1770b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_Unknown:
1771b0989546SSandy Huang 		return true;
1772b0989546SSandy Huang 	default:
1773b0989546SSandy Huang 		return false;
177463cb669fSSandy Huang 	}
177563cb669fSSandy Huang }
177663cb669fSSandy Huang 
1777ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1778ecc31b6eSAndy Yan {
1779ecc31b6eSAndy Yan 	int i = 0;
1780ecc31b6eSAndy Yan 
1781ecc31b6eSAndy Yan 	for (i = 0; i < vop2->data->nr_layers; i++) {
1782ecc31b6eSAndy Yan 		if (vop2->data->win_data[i].phys_id == phys_id)
1783ecc31b6eSAndy Yan 			return &vop2->data->win_data[i];
1784ecc31b6eSAndy Yan 	}
1785ecc31b6eSAndy Yan 
1786ecc31b6eSAndy Yan 	return NULL;
1787ecc31b6eSAndy Yan }
1788ecc31b6eSAndy Yan 
1789b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id)
1790b6ba80b4SDamon Ding {
1791b6ba80b4SDamon Ding 	int i = 0;
1792b6ba80b4SDamon Ding 
1793b6ba80b4SDamon Ding 	for (i = 0; i < vop2->data->nr_pd; i++) {
1794b6ba80b4SDamon Ding 		if (vop2->data->pd[i].id == pd_id)
1795b6ba80b4SDamon Ding 			return &vop2->data->pd[i];
1796b6ba80b4SDamon Ding 	}
1797b6ba80b4SDamon Ding 
1798b6ba80b4SDamon Ding 	return NULL;
1799b6ba80b4SDamon Ding }
1800b6ba80b4SDamon Ding 
1801db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1802db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1803db328a0dSDamon Ding {
1804db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1805db328a0dSDamon Ding 	int i;
1806db328a0dSDamon Ding 
1807db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1808db328a0dSDamon Ding 			GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1809db328a0dSDamon Ding 			crtc_id, false);
1810db328a0dSDamon Ding 
1811db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1812db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1813db328a0dSDamon Ding 
1814db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1815db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1816db328a0dSDamon Ding }
1817db328a0dSDamon Ding 
1818db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1819db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1820db328a0dSDamon Ding {
1821db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1822db328a0dSDamon Ding 	int i;
1823db328a0dSDamon Ding 
1824db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1825db328a0dSDamon Ding 			GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1826db328a0dSDamon Ding 			crtc_id, false);
1827db328a0dSDamon Ding 
1828db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1829db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1830db328a0dSDamon Ding 
1831db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1832db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1833db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1834db328a0dSDamon Ding 			EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false);
1835db328a0dSDamon Ding }
1836db328a0dSDamon Ding 
18371147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1838d0408543SAndy Yan 					struct display_state *state)
1839d0408543SAndy Yan {
18401147facaSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
18411147facaSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
18421147facaSSandy Huang 	struct resource gamma_res;
18431147facaSSandy Huang 	fdt_size_t lut_size;
18441147facaSSandy Huang 	int i, lut_len, ret = 0;
18451147facaSSandy Huang 	u32 *lut_regs;
18461147facaSSandy Huang 	u32 r, g, b;
18471147facaSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
18481147facaSSandy Huang 	static int gamma_lut_en_num = 1;
18491147facaSSandy Huang 
18501147facaSSandy Huang 	if (gamma_lut_en_num > vop2->data->nr_gammas) {
18511147facaSSandy Huang 		printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
18521147facaSSandy Huang 		return 0;
18531147facaSSandy Huang 	}
18541147facaSSandy Huang 
18551147facaSSandy Huang 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
18561147facaSSandy Huang 	if (ret)
18571147facaSSandy Huang 		printf("failed to get gamma lut res\n");
18581147facaSSandy Huang 	lut_regs = (u32 *)gamma_res.start;
18591147facaSSandy Huang 	lut_size = gamma_res.end - gamma_res.start + 1;
18601147facaSSandy Huang 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
18611147facaSSandy Huang 		printf("failed to get gamma lut register\n");
18621147facaSSandy Huang 		return 0;
18631147facaSSandy Huang 	}
18641147facaSSandy Huang 	lut_len = lut_size / 4;
18651147facaSSandy Huang 	if (lut_len != 256 && lut_len != 1024) {
18661147facaSSandy Huang 		printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
18671147facaSSandy Huang 		return 0;
18681147facaSSandy Huang 	}
18690669ab1fSDamon Ding 
18700669ab1fSDamon Ding 	if (!cstate->lut_val) {
18710669ab1fSDamon Ding 		if (!disp_info)
18720669ab1fSDamon Ding 			return 0;
18730669ab1fSDamon Ding 
18740669ab1fSDamon Ding 		if (!disp_info->gamma_lut_data.size)
18750669ab1fSDamon Ding 			return 0;
18760669ab1fSDamon Ding 
18770669ab1fSDamon Ding 		cstate->lut_val = (u32 *)calloc(1, lut_size);
18781147facaSSandy Huang 		for (i = 0; i < lut_len; i++) {
18791147facaSSandy Huang 			r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
18801147facaSSandy Huang 			g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
18811147facaSSandy Huang 			b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
18821147facaSSandy Huang 
18830669ab1fSDamon Ding 			cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
18840669ab1fSDamon Ding 		}
18851147facaSSandy Huang 	}
18861147facaSSandy Huang 
1887db328a0dSDamon Ding 	if (vop2->version == VOP_VERSION_RK3568) {
18880669ab1fSDamon Ding 		rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
18890669ab1fSDamon Ding 				     cstate->lut_val, lut_len);
18901147facaSSandy Huang 		gamma_lut_en_num++;
189118d9b8adSDamon Ding 	} else {
18920669ab1fSDamon Ding 		rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
18930669ab1fSDamon Ding 				     cstate->lut_val, lut_len);
1894db328a0dSDamon Ding 		if (cstate->splice_mode) {
18950669ab1fSDamon Ding 			rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs,
18960669ab1fSDamon Ding 					     cstate->lut_val, lut_len);
1897db328a0dSDamon Ding 			gamma_lut_en_num++;
1898db328a0dSDamon Ding 		}
1899db328a0dSDamon Ding 		gamma_lut_en_num++;
1900db328a0dSDamon Ding 	}
19011147facaSSandy Huang 
19020669ab1fSDamon Ding 	free(cstate->lut_val);
19030669ab1fSDamon Ding 
1904d0408543SAndy Yan 	return 0;
1905d0408543SAndy Yan }
1906d0408543SAndy Yan 
19076414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
19086414e3bcSSandy Huang 					struct display_state *state)
19096414e3bcSSandy Huang {
19106414e3bcSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
19116414e3bcSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
19126414e3bcSSandy Huang 	int i, cubic_lut_len;
19136414e3bcSSandy Huang 	u32 vp_offset = cstate->crtc_id * 0x100;
19146414e3bcSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
19156414e3bcSSandy Huang 	struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
19166414e3bcSSandy Huang 	u32 *cubic_lut_addr;
19176414e3bcSSandy Huang 
19186414e3bcSSandy Huang 	if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
19196414e3bcSSandy Huang 		return 0;
19206414e3bcSSandy Huang 
19216414e3bcSSandy Huang 	if (!disp_info->cubic_lut_data.size)
19226414e3bcSSandy Huang 		return 0;
19236414e3bcSSandy Huang 
19246414e3bcSSandy Huang 	cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
19256414e3bcSSandy Huang 	cubic_lut_len = disp_info->cubic_lut_data.size;
19266414e3bcSSandy Huang 
19276414e3bcSSandy Huang 	for (i = 0; i < cubic_lut_len / 2; i++) {
19286414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
19296414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
19306414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
19316414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
19326414e3bcSSandy Huang 					((lut->lred[2 * i + 1] & 0xfff) << 4) +
19336414e3bcSSandy Huang 					((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
19346414e3bcSSandy Huang 					((lut->lblue[2 * i + 1] & 0xf) << 28);
19356414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
19366414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
19376414e3bcSSandy Huang 	}
19386414e3bcSSandy Huang 
19396414e3bcSSandy Huang 	if (cubic_lut_len % 2) {
19406414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
19416414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
19426414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
19436414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
19446414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
19456414e3bcSSandy Huang 		*cubic_lut_addr = 0;
19466414e3bcSSandy Huang 	}
19476414e3bcSSandy Huang 
19486414e3bcSSandy Huang 	vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
19496414e3bcSSandy Huang 		    get_cubic_lut_buffer(cstate->crtc_id));
19506414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
19516414e3bcSSandy Huang 			EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
19526414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
19536414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
19546414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
19556414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
19566414e3bcSSandy Huang 
19576414e3bcSSandy Huang 	return 0;
19586414e3bcSSandy Huang }
19596414e3bcSSandy Huang 
1960ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2,
1961ee01dbb2SDamon Ding 				 struct bcsh_state *bcsh_state, int crtc_id)
1962ee01dbb2SDamon Ding {
1963ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
1964ee01dbb2SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1965ee01dbb2SDamon Ding 
1966ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
1967ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false);
1968ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
1969ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false);
1970ee01dbb2SDamon Ding 
1971ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
1972ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
1973ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
1974ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
1975ee01dbb2SDamon Ding 
1976ee01dbb2SDamon Ding 	if (!cstate->bcsh_en) {
1977ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1978ee01dbb2SDamon Ding 				BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
1979ee01dbb2SDamon Ding 		return;
1980ee01dbb2SDamon Ding 	}
1981ee01dbb2SDamon Ding 
1982ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1983ee01dbb2SDamon Ding 			BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
1984ee01dbb2SDamon Ding 			bcsh_state->brightness, false);
1985ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1986ee01dbb2SDamon Ding 			BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false);
1987ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1988ee01dbb2SDamon Ding 			BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
1989ee01dbb2SDamon Ding 			bcsh_state->saturation * bcsh_state->contrast / 0x100, false);
1990ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1991ee01dbb2SDamon Ding 			BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false);
1992ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1993ee01dbb2SDamon Ding 			BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false);
1994ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1995ee01dbb2SDamon Ding 			BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
1996ee01dbb2SDamon Ding 			BCSH_OUT_MODE_NORMAL_VIDEO, false);
1997ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1998ee01dbb2SDamon Ding 			BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
1999ee01dbb2SDamon Ding }
2000ee01dbb2SDamon Ding 
2001ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
2002ac500a1fSSandy Huang {
2003ac500a1fSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
2004ac500a1fSSandy Huang 	struct base_bcsh_info *bcsh_info;
2005ac500a1fSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
2006ee01dbb2SDamon Ding 	struct bcsh_state bcsh_state;
2007ac500a1fSSandy Huang 	int brightness, contrast, saturation, hue, sin_hue, cos_hue;
2008ac500a1fSSandy Huang 
2009ac500a1fSSandy Huang 	if (!conn_state->disp_info)
2010ac500a1fSSandy Huang 		return;
2011ac500a1fSSandy Huang 	bcsh_info = &conn_state->disp_info->bcsh_info;
2012ac500a1fSSandy Huang 	if (!bcsh_info)
2013ac500a1fSSandy Huang 		return;
2014ac500a1fSSandy Huang 
2015ac500a1fSSandy Huang 	if (bcsh_info->brightness != 50 ||
2016ac500a1fSSandy Huang 	    bcsh_info->contrast != 50 ||
2017ac500a1fSSandy Huang 	    bcsh_info->saturation != 50 || bcsh_info->hue != 50)
2018ee01dbb2SDamon Ding 		cstate->bcsh_en = true;
2019ac500a1fSSandy Huang 
2020ee01dbb2SDamon Ding 	if (cstate->bcsh_en) {
2021ac500a1fSSandy Huang 		if (!cstate->yuv_overlay)
2022ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2023ac500a1fSSandy Huang 		if (!is_yuv_output(conn_state->bus_format))
2024ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2025ac500a1fSSandy Huang 	} else {
2026ac500a1fSSandy Huang 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2027ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2028ac500a1fSSandy Huang 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2029ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2030ac500a1fSSandy Huang 	}
2031ac500a1fSSandy Huang 
2032df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2033df0a5c43SDamon Ding 						      conn_state->color_range,
2034df0a5c43SDamon Ding 						      CSC_10BIT_DEPTH);
2035ac500a1fSSandy Huang 
2036ac500a1fSSandy Huang 	if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
2037ac500a1fSSandy Huang 		brightness = interpolate(0, -128, 100, 127,
2038ac500a1fSSandy Huang 					 bcsh_info->brightness);
2039ac500a1fSSandy Huang 	else
2040ac500a1fSSandy Huang 		brightness = interpolate(0, -32, 100, 31,
2041ac500a1fSSandy Huang 					 bcsh_info->brightness);
2042ac500a1fSSandy Huang 	contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
2043ac500a1fSSandy Huang 	saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
2044ac500a1fSSandy Huang 	hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
2045ac500a1fSSandy Huang 
2046ac500a1fSSandy Huang 
2047ac500a1fSSandy Huang 	/*
2048ac500a1fSSandy Huang 	 *  a:[-30~0):
2049ac500a1fSSandy Huang 	 *    sin_hue = 0x100 - sin(a)*256;
2050ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2051ac500a1fSSandy Huang 	 *  a:[0~30]
2052ac500a1fSSandy Huang 	 *    sin_hue = sin(a)*256;
2053ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2054ac500a1fSSandy Huang 	 */
2055ac500a1fSSandy Huang 	sin_hue = fixp_sin32(hue) >> 23;
2056ac500a1fSSandy Huang 	cos_hue = fixp_cos32(hue) >> 23;
2057ac500a1fSSandy Huang 
2058ee01dbb2SDamon Ding 	bcsh_state.brightness = brightness;
2059ee01dbb2SDamon Ding 	bcsh_state.contrast = contrast;
2060ee01dbb2SDamon Ding 	bcsh_state.saturation = saturation;
2061ee01dbb2SDamon Ding 	bcsh_state.sin_hue = sin_hue;
2062ee01dbb2SDamon Ding 	bcsh_state.cos_hue = cos_hue;
2063ee01dbb2SDamon Ding 
2064ee01dbb2SDamon Ding 	vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id);
2065ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2066ee01dbb2SDamon Ding 		vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id);
2067ee01dbb2SDamon Ding }
2068ee01dbb2SDamon Ding 
2069ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id)
2070ee01dbb2SDamon Ding {
2071ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2072ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2073ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2074ee01dbb2SDamon Ding 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
2075ee01dbb2SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2076ee01dbb2SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2077ee01dbb2SDamon Ding 
2078ee01dbb2SDamon Ding 	bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly;
2079ee01dbb2SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly;
2080ee01dbb2SDamon Ding 	bg_dly -= bg_ovl_dly;
2081ee01dbb2SDamon Ding 
2082a552a69cSDamon Ding 	/*
2083a552a69cSDamon Ding 	 * splice mode: hdisplay must roundup as 4 pixel,
2084a552a69cSDamon Ding 	 * no splice mode: hdisplay must roundup as 2 pixel.
2085a552a69cSDamon Ding 	 */
2086ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2087a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1;
2088ee01dbb2SDamon Ding 	else
2089a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2090ee01dbb2SDamon Ding 
2091ee01dbb2SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
2092ee01dbb2SDamon Ding 		hsync_len = 8;
2093ee01dbb2SDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
2094ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4,
2095ee01dbb2SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2096ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2097ac500a1fSSandy Huang }
2098ac500a1fSSandy Huang 
2099452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id)
2100452afb13SDamon Ding {
2101452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2102452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2103452afb13SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2104452afb13SDamon Ding 	struct vop2_win_data *win_data;
2105452afb13SDamon Ding 	u32 bg_dly, pre_scan_dly;
2106452afb13SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2107452afb13SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2108452afb13SDamon Ding 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
2109452afb13SDamon Ding 	u8 win_id;
2110452afb13SDamon Ding 
2111452afb13SDamon Ding 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
2112452afb13SDamon Ding 	win_id = atoi(&win_data->name[strlen(win_data->name) - 1]);
2113452afb13SDamon Ding 	vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL + win_id * 4,
2114452afb13SDamon Ding 			ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 0, false);
2115452afb13SDamon Ding 
2116452afb13SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].win_dly +
2117452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].layer_mix_dly +
2118452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].hdr_mix_dly;
2119a552a69cSDamon Ding 	/* hdisplay must roundup as 2 pixel */
2120a552a69cSDamon Ding 	pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2121a552a69cSDamon Ding 	/**
2122a552a69cSDamon Ding 	 * pre_scan_hblank minimum value is 8, otherwise the win reset signal will
2123a552a69cSDamon Ding 	 * lead to first line data be zero.
2124a552a69cSDamon Ding 	 */
2125a552a69cSDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len);
2126452afb13SDamon Ding 	vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100,
2127452afb13SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2128452afb13SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2129452afb13SDamon Ding }
2130452afb13SDamon Ding 
2131d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
2132d0408543SAndy Yan {
2133d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
2134d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
213552ee18acSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
213652ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
2137d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
2138d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
2139d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
2140d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
2141d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
2142d0408543SAndy Yan 	u16 hsize =
2143d0408543SAndy Yan 	    hdisplay * (conn_state->overscan.left_margin +
2144d0408543SAndy Yan 			conn_state->overscan.right_margin) / 200;
2145d0408543SAndy Yan 	u16 vsize =
2146d0408543SAndy Yan 	    vdisplay * (conn_state->overscan.top_margin +
2147d0408543SAndy Yan 			conn_state->overscan.bottom_margin) / 200;
2148d0408543SAndy Yan 	u16 hact_end, vact_end;
2149d0408543SAndy Yan 	u32 val;
2150d0408543SAndy Yan 
215174bd8269SSandy Huang 	hsize = round_down(hsize, 2);
2152d0408543SAndy Yan 	vsize = round_down(vsize, 2);
2153d0408543SAndy Yan 
2154d0408543SAndy Yan 	hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
2155d0408543SAndy Yan 	hact_end = hact_st + hsize;
2156d0408543SAndy Yan 	val = hact_st << 16;
2157d0408543SAndy Yan 	val |= hact_end;
2158d0408543SAndy Yan 
215952ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
2160d0408543SAndy Yan 	vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
2161d0408543SAndy Yan 	vact_end = vact_st + vsize;
2162d0408543SAndy Yan 	val = vact_st << 16;
2163d0408543SAndy Yan 	val |= vact_end;
216452ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
2165d0408543SAndy Yan 	val = scl_cal_scale2(vdisplay, vsize) << 16;
2166d0408543SAndy Yan 	val |= scl_cal_scale2(hdisplay, hsize);
216752ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
2168d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
2169d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
21707504507fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
21717504507fSSandy Huang 			RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT,
2172d0408543SAndy Yan 			POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
21737504507fSSandy Huang 			POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false);
2174d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
2175d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
2176d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vsize;
2177d0408543SAndy Yan 
2178d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
217952ee18acSSandy Huang 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
2180d0408543SAndy Yan 	}
2181d0408543SAndy Yan 
2182452afb13SDamon Ding 	if (is_vop3(vop2)) {
2183452afb13SDamon Ding 		vop3_setup_pipe_dly(state, vop2, cstate->crtc_id);
2184452afb13SDamon Ding 	} else {
2185ee01dbb2SDamon Ding 		vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id);
2186ee01dbb2SDamon Ding 		if (cstate->splice_mode)
2187ee01dbb2SDamon Ding 			vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id);
2188d0408543SAndy Yan 	}
2189452afb13SDamon Ding }
2190d0408543SAndy Yan 
21916027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2)
21926027c871SZhang Yubing {
21936027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
21946027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
21956027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
21966027c871SZhang Yubing 	struct drm_display_mode *mode = &conn_state->mode;
21976027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
21986027c871SZhang Yubing 	s16 *lut_y;
21996027c871SZhang Yubing 	s16 *lut_h;
22006027c871SZhang Yubing 	s16 *lut_s;
22016027c871SZhang Yubing 	u32 value;
22026027c871SZhang Yubing 	int i;
22036027c871SZhang Yubing 
22046027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2205b8db91d0SZhang Yubing 		POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2206b8db91d0SZhang Yubing 	if (!acm->acm_enable) {
2207b8db91d0SZhang Yubing 		writel(0, vop2->regs + RK3528_ACM_CTRL);
22086027c871SZhang Yubing 		return;
22096027c871SZhang Yubing 	}
22106027c871SZhang Yubing 
22116027c871SZhang Yubing 	printf("post acm enable\n");
22126027c871SZhang Yubing 
22136027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_START);
22146027c871SZhang Yubing 
22156027c871SZhang Yubing 	value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) +
22166027c871SZhang Yubing 		((mode->vdisplay & 0xfff) << 20);
22176027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_CTRL);
22186027c871SZhang Yubing 
22196027c871SZhang Yubing 	value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
22206027c871SZhang Yubing 		((acm->s_gain << 20) & 0x3ff00000);
22216027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE);
22226027c871SZhang Yubing 
22236027c871SZhang Yubing 	lut_y = &acm->gain_lut_hy[0];
22246027c871SZhang Yubing 	lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
22256027c871SZhang Yubing 	lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
22266027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
22276027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
22286027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
22296027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
22306027c871SZhang Yubing 	}
22316027c871SZhang Yubing 
22326027c871SZhang Yubing 	lut_y = &acm->gain_lut_hs[0];
22336027c871SZhang Yubing 	lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
22346027c871SZhang Yubing 	lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
22356027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
22366027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
22376027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
22386027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
22396027c871SZhang Yubing 	}
22406027c871SZhang Yubing 
22416027c871SZhang Yubing 	lut_y = &acm->delta_lut_h[0];
22426027c871SZhang Yubing 	lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
22436027c871SZhang Yubing 	lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
22446027c871SZhang Yubing 	for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
22456027c871SZhang Yubing 		value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
22466027c871SZhang Yubing 			((lut_s[i] << 20) & 0x3ff00000);
22476027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
22486027c871SZhang Yubing 	}
22496027c871SZhang Yubing 
22506027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_DONE);
22516027c871SZhang Yubing }
22526027c871SZhang Yubing 
22536027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2)
22546027c871SZhang Yubing {
22556027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
22566027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
22576027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
22586027c871SZhang Yubing 	struct csc_info *csc = &conn_state->disp_info->csc_info;
22596027c871SZhang Yubing 	struct post_csc_coef csc_coef;
22606027c871SZhang Yubing 	bool is_input_yuv = false;
22616027c871SZhang Yubing 	bool is_output_yuv = false;
22626027c871SZhang Yubing 	bool post_r2y_en = false;
22636027c871SZhang Yubing 	bool post_csc_en = false;
22646027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
22656027c871SZhang Yubing 	u32 value;
22666027c871SZhang Yubing 	int range_type;
22676027c871SZhang Yubing 
22686027c871SZhang Yubing 	printf("post csc enable\n");
22696027c871SZhang Yubing 
22706027c871SZhang Yubing 	if (acm->acm_enable) {
22716027c871SZhang Yubing 		if (!cstate->yuv_overlay)
22726027c871SZhang Yubing 			post_r2y_en = true;
22736027c871SZhang Yubing 
22746027c871SZhang Yubing 		/* do y2r in csc module */
22756027c871SZhang Yubing 		if (!is_yuv_output(conn_state->bus_format))
22766027c871SZhang Yubing 			post_csc_en = true;
22776027c871SZhang Yubing 	} else {
22786027c871SZhang Yubing 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
22796027c871SZhang Yubing 			post_r2y_en = true;
22806027c871SZhang Yubing 
22816027c871SZhang Yubing 		/* do y2r in csc module */
22826027c871SZhang Yubing 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
22836027c871SZhang Yubing 			post_csc_en = true;
22846027c871SZhang Yubing 	}
22856027c871SZhang Yubing 
22866027c871SZhang Yubing 	if (csc->csc_enable)
22876027c871SZhang Yubing 		post_csc_en = true;
22886027c871SZhang Yubing 
22896027c871SZhang Yubing 	if (cstate->yuv_overlay || post_r2y_en)
22906027c871SZhang Yubing 		is_input_yuv = true;
22916027c871SZhang Yubing 
22926027c871SZhang Yubing 	if (is_yuv_output(conn_state->bus_format))
22936027c871SZhang Yubing 		is_output_yuv = true;
22946027c871SZhang Yubing 
2295df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2296df0a5c43SDamon Ding 						      conn_state->color_range,
2297df0a5c43SDamon Ding 						      CSC_13BIT_DEPTH);
22986027c871SZhang Yubing 
22996027c871SZhang Yubing 	if (post_csc_en) {
23006027c871SZhang Yubing 		rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv,
23016027c871SZhang Yubing 				       is_output_yuv);
23026027c871SZhang Yubing 
23036027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23046027c871SZhang Yubing 				POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT,
23056027c871SZhang Yubing 				csc_coef.csc_coef00, false);
23065743c73eSZhang Yubing 		value = csc_coef.csc_coef01 & 0xffff;
23075743c73eSZhang Yubing 		value |= (csc_coef.csc_coef02 << 16) & 0xffff0000;
23086027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02);
23095743c73eSZhang Yubing 		value = csc_coef.csc_coef10 & 0xffff;
23105743c73eSZhang Yubing 		value |= (csc_coef.csc_coef11 << 16) & 0xffff0000;
23116027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11);
23125743c73eSZhang Yubing 		value = csc_coef.csc_coef12 & 0xffff;
23135743c73eSZhang Yubing 		value |= (csc_coef.csc_coef20 << 16) & 0xffff0000;
23146027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20);
23155743c73eSZhang Yubing 		value = csc_coef.csc_coef21 & 0xffff;
23165743c73eSZhang Yubing 		value |= (csc_coef.csc_coef22 << 16) & 0xffff0000;
23176027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22);
23186027c871SZhang Yubing 		writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0);
23196027c871SZhang Yubing 		writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1);
23206027c871SZhang Yubing 		writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2);
23216027c871SZhang Yubing 
23226027c871SZhang Yubing 		range_type = csc_coef.range_type ? 0 : 1;
23236027c871SZhang Yubing 		range_type <<= is_input_yuv ? 0 : 1;
23246027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23256027c871SZhang Yubing 				POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false);
23266027c871SZhang Yubing 	}
23276027c871SZhang Yubing 
23286027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23295743c73eSZhang Yubing 			POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false);
23306027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23316027c871SZhang Yubing 			POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false);
23326027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
23336027c871SZhang Yubing 			POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false);
23346027c871SZhang Yubing }
23356027c871SZhang Yubing 
23366027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2)
23376027c871SZhang Yubing {
23386027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
23396027c871SZhang Yubing 	struct base2_disp_info *disp_info = conn_state->disp_info;
23406027c871SZhang Yubing 	const char *enable_flag;
23416027c871SZhang Yubing 	if (!disp_info) {
23426027c871SZhang Yubing 		printf("disp_info is empty\n");
23436027c871SZhang Yubing 		return;
23446027c871SZhang Yubing 	}
23456027c871SZhang Yubing 
23466027c871SZhang Yubing 	enable_flag = (const char *)&disp_info->cacm_header;
23476027c871SZhang Yubing 	if (strncasecmp(enable_flag, "CACM", 4)) {
23486027c871SZhang Yubing 		printf("acm and csc is not support\n");
23496027c871SZhang Yubing 		return;
23506027c871SZhang Yubing 	}
23516027c871SZhang Yubing 
23526027c871SZhang Yubing 	vop3_post_acm_config(state, vop2);
23536027c871SZhang Yubing 	vop3_post_csc_config(state, vop2);
23546027c871SZhang Yubing }
23556027c871SZhang Yubing 
2356a552a69cSDamon Ding static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2,
2357a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
2358a552a69cSDamon Ding {
2359a552a69cSDamon Ding 	int val = 0;
2360a552a69cSDamon Ding 	bool is_bisr_en, is_otp_bisr_en;
2361a552a69cSDamon Ding 
2362a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER) {
2363a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2364a552a69cSDamon Ding 					    EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2365a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2366a552a69cSDamon Ding 						EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2367a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2368a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2369a552a69cSDamon Ding 						  val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1),
2370a552a69cSDamon Ding 						  50 * 1000);
2371a552a69cSDamon Ding 		else
2372a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2373*0e0a0ff9SDamon Ding 						  val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1),
2374a552a69cSDamon Ding 						  50 * 1000);
2375a552a69cSDamon Ding 	} else {
2376a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2377a552a69cSDamon Ding 					    EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2378a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2379a552a69cSDamon Ding 						EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2380a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2381a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2382a552a69cSDamon Ding 						  val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1),
2383a552a69cSDamon Ding 						  50 * 1000);
2384a552a69cSDamon Ding 		else
2385a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2386a552a69cSDamon Ding 						  val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1),
2387a552a69cSDamon Ding 						  50 * 1000);
2388a552a69cSDamon Ding 	}
2389a552a69cSDamon Ding }
2390a552a69cSDamon Ding 
2391a552a69cSDamon Ding static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2392a552a69cSDamon Ding {
2393a552a69cSDamon Ding 	int ret = 0;
2394a552a69cSDamon Ding 
2395a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER)
2396a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK,
2397a552a69cSDamon Ding 				RK3576_CLUSTER_PD_EN_SHIFT, 0, true);
2398a552a69cSDamon Ding 	else
2399a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK,
2400a552a69cSDamon Ding 				RK3576_ESMART_PD_EN_SHIFT, 0, true);
2401a552a69cSDamon Ding 	ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data);
2402a552a69cSDamon Ding 	if (ret) {
2403a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2404a552a69cSDamon Ding 		return ret;
2405a552a69cSDamon Ding 	}
2406a552a69cSDamon Ding 
2407a552a69cSDamon Ding 	return 0;
2408a552a69cSDamon Ding }
2409a552a69cSDamon Ding 
2410a552a69cSDamon Ding static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2,
2411a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
241260e469f5SDamon Ding {
241360e469f5SDamon Ding 	int val = 0;
241460e469f5SDamon Ding 	int shift = 0;
2415b6ba80b4SDamon Ding 	int shift_factor = 0;
241660e469f5SDamon Ding 	bool is_bisr_en = false;
241760e469f5SDamon Ding 
2418b6ba80b4SDamon Ding 	/*
2419b6ba80b4SDamon Ding 	 * The order of pd status bits in BISR_STS register
2420b6ba80b4SDamon Ding 	 * is different from that in VOP SYS_STS register.
2421b6ba80b4SDamon Ding 	 */
2422b6ba80b4SDamon Ding 	if (pd_data->id == VOP2_PD_DSC_8K ||
2423b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_DSC_4K ||
2424b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_ESMART)
2425b6ba80b4SDamon Ding 		shift_factor = 1;
2426b6ba80b4SDamon Ding 
2427b6ba80b4SDamon Ding 	shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor;
2428b6ba80b4SDamon Ding 	is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift);
242960e469f5SDamon Ding 	if (is_bisr_en) {
2430b6ba80b4SDamon Ding 		shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor;
2431b6ba80b4SDamon Ding 
243260e469f5SDamon Ding 		return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
2433d2e91fdcSDamon Ding 					  ((val >> shift) & 0x1), 50 * 1000);
243460e469f5SDamon Ding 	} else {
2435b6ba80b4SDamon Ding 		shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1;
2436b6ba80b4SDamon Ding 
243760e469f5SDamon Ding 		return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
243860e469f5SDamon Ding 					  !((val >> shift) & 0x1), 50 * 1000);
243960e469f5SDamon Ding 	}
244060e469f5SDamon Ding }
244160e469f5SDamon Ding 
2442a552a69cSDamon Ding static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2443a552a69cSDamon Ding {
2444a552a69cSDamon Ding 	int ret = 0;
2445a552a69cSDamon Ding 
2446a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK,
2447a552a69cSDamon Ding 			RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false);
2448a552a69cSDamon Ding 	ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data);
2449a552a69cSDamon Ding 	if (ret) {
2450a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2451a552a69cSDamon Ding 		return ret;
2452a552a69cSDamon Ding 	}
2453a552a69cSDamon Ding 
2454a552a69cSDamon Ding 	return 0;
2455a552a69cSDamon Ding }
2456a552a69cSDamon Ding 
2457b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id)
245860e469f5SDamon Ding {
245960e469f5SDamon Ding 	struct vop2_power_domain_data *pd_data;
246060e469f5SDamon Ding 	int ret = 0;
246160e469f5SDamon Ding 
2462b6ba80b4SDamon Ding 	if (!pd_id)
2463b6ba80b4SDamon Ding 		return 0;
2464b6ba80b4SDamon Ding 
2465b6ba80b4SDamon Ding 	pd_data = vop2_find_pd_data_by_id(vop2, pd_id);
2466b6ba80b4SDamon Ding 	if (!pd_data) {
2467b6ba80b4SDamon Ding 		printf("can't find pd_data by id\n");
246860e469f5SDamon Ding 		return -EINVAL;
246960e469f5SDamon Ding 	}
24702c66af11SDamon Ding 
2471b6ba80b4SDamon Ding 	if (pd_data->parent_id) {
2472b6ba80b4SDamon Ding 		ret = vop2_power_domain_on(vop2, pd_data->parent_id);
247360e469f5SDamon Ding 		if (ret) {
247460e469f5SDamon Ding 			printf("can't open parent power domain\n");
247560e469f5SDamon Ding 			return -EINVAL;
247660e469f5SDamon Ding 		}
247760e469f5SDamon Ding 	}
247860e469f5SDamon Ding 
2479a552a69cSDamon Ding 	/*
2480a552a69cSDamon Ding 	 * Read VOP internal power domain on/off status.
2481a552a69cSDamon Ding 	 * We should query BISR_STS register in PMU for
2482a552a69cSDamon Ding 	 * power up/down status when memory repair is enabled.
2483a552a69cSDamon Ding 	 * Return value: 1 for power on, 0 for power off;
2484a552a69cSDamon Ding 	 */
2485a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
2486a552a69cSDamon Ding 		ret = rk3576_vop2_power_domain_on(vop2, pd_data);
2487a552a69cSDamon Ding 	else
2488a552a69cSDamon Ding 		ret = rk3588_vop2_power_domain_on(vop2, pd_data);
248960e469f5SDamon Ding 
2490a552a69cSDamon Ding 	return ret;
249160e469f5SDamon Ding }
249260e469f5SDamon Ding 
2493ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2)
2494ecc31b6eSAndy Yan {
2495ecc31b6eSAndy Yan 	u32 *base = vop2->regs;
2496ecc31b6eSAndy Yan 	int i = 0;
2497ecc31b6eSAndy Yan 
2498ecc31b6eSAndy Yan 	/*
2499ecc31b6eSAndy Yan 	 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
2500ecc31b6eSAndy Yan 	 */
2501ecc31b6eSAndy Yan 	for (i = 0; i < (vop2->reg_len >> 2); i++)
2502ecc31b6eSAndy Yan 		vop2->regsbak[i] = base[i];
2503ecc31b6eSAndy Yan }
2504ecc31b6eSAndy Yan 
25055fa6e665SDamon Ding static void vop3_overlay_init(struct vop2 *vop2, struct display_state *state)
25065fa6e665SDamon Ding {
25075fa6e665SDamon Ding 	struct vop2_win_data *win_data;
25085fa6e665SDamon Ding 	int layer_phy_id = 0;
25095fa6e665SDamon Ding 	int i, j;
25105fa6e665SDamon Ding 	u32 ovl_port_offset = 0;
25115fa6e665SDamon Ding 	u32 layer_nr = 0;
25125fa6e665SDamon Ding 	u8 shift = 0;
25135fa6e665SDamon Ding 
25145fa6e665SDamon Ding 	/* layer sel win id */
25155fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
25165fa6e665SDamon Ding 		shift = 0;
25175fa6e665SDamon Ding 		ovl_port_offset = 0x100 * i;
25185fa6e665SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
25195fa6e665SDamon Ding 		for (j = 0; j < layer_nr; j++) {
25205fa6e665SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
25215fa6e665SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
25225fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + ovl_port_offset, LAYER_SEL_MASK,
25235fa6e665SDamon Ding 					shift, win_data->layer_sel_win_id[i], false);
25245fa6e665SDamon Ding 			shift += 4;
25255fa6e665SDamon Ding 		}
25265fa6e665SDamon Ding 	}
25275fa6e665SDamon Ding 
2528a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3576) {
25295fa6e665SDamon Ding 		/* win sel port */
25305fa6e665SDamon Ding 		for (i = 0; i < vop2->data->nr_vps; i++) {
25315fa6e665SDamon Ding 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
25325fa6e665SDamon Ding 			for (j = 0; j < layer_nr; j++) {
25335fa6e665SDamon Ding 				if (!vop2->vp_plane_mask[i].attached_layers[j])
25345fa6e665SDamon Ding 					continue;
25355fa6e665SDamon Ding 				layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
25365fa6e665SDamon Ding 				win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
25375fa6e665SDamon Ding 				shift = win_data->win_sel_port_offset * 2;
2538a552a69cSDamon Ding 				vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL,
2539a552a69cSDamon Ding 						LAYER_SEL_PORT_MASK, shift, i, false);
2540a552a69cSDamon Ding 			}
25415fa6e665SDamon Ding 		}
25425fa6e665SDamon Ding 	}
25435fa6e665SDamon Ding }
25445fa6e665SDamon Ding 
25455fa6e665SDamon Ding static void vop2_overlay_init(struct vop2 *vop2, struct display_state *state)
25465fa6e665SDamon Ding {
25475fa6e665SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
25485fa6e665SDamon Ding 	struct vop2_win_data *win_data;
25495fa6e665SDamon Ding 	int layer_phy_id = 0;
25505fa6e665SDamon Ding 	int total_used_layer = 0;
25515fa6e665SDamon Ding 	int port_mux = 0;
25525fa6e665SDamon Ding 	int i, j;
25535fa6e665SDamon Ding 	u32 layer_nr = 0;
25545fa6e665SDamon Ding 	u8 shift = 0;
25555fa6e665SDamon Ding 
25565fa6e665SDamon Ding 	/* layer sel win id */
25575fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
25585fa6e665SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
25595fa6e665SDamon Ding 		for (j = 0; j < layer_nr; j++) {
25605fa6e665SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
25615fa6e665SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
25625fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
25635fa6e665SDamon Ding 					shift, win_data->layer_sel_win_id[i], false);
25645fa6e665SDamon Ding 			shift += 4;
25655fa6e665SDamon Ding 		}
25665fa6e665SDamon Ding 	}
25675fa6e665SDamon Ding 
25685fa6e665SDamon Ding 	/* win sel port */
25695fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
25705fa6e665SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
25715fa6e665SDamon Ding 		for (j = 0; j < layer_nr; j++) {
25725fa6e665SDamon Ding 			if (!vop2->vp_plane_mask[i].attached_layers[j])
25735fa6e665SDamon Ding 				continue;
25745fa6e665SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
25755fa6e665SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
25765fa6e665SDamon Ding 			shift = win_data->win_sel_port_offset * 2;
25775fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
25785fa6e665SDamon Ding 					LAYER_SEL_PORT_SHIFT + shift, i, false);
25795fa6e665SDamon Ding 		}
25805fa6e665SDamon Ding 	}
25815fa6e665SDamon Ding 
25825fa6e665SDamon Ding 	/**
25835fa6e665SDamon Ding 	 * port mux config
25845fa6e665SDamon Ding 	 */
25855fa6e665SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
25865fa6e665SDamon Ding 		shift = i * 4;
25875fa6e665SDamon Ding 		if (vop2->vp_plane_mask[i].attached_layers_nr) {
25885fa6e665SDamon Ding 			total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
25895fa6e665SDamon Ding 			port_mux = total_used_layer - 1;
25905fa6e665SDamon Ding 		} else {
25915fa6e665SDamon Ding 			port_mux = 8;
25925fa6e665SDamon Ding 		}
25935fa6e665SDamon Ding 
25945fa6e665SDamon Ding 		if (i == vop2->data->nr_vps - 1)
25955fa6e665SDamon Ding 			port_mux = vop2->data->nr_mixers;
25965fa6e665SDamon Ding 
25975fa6e665SDamon Ding 		cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
25985fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
25995fa6e665SDamon Ding 				PORT_MUX_SHIFT + shift, port_mux, false);
26005fa6e665SDamon Ding 	}
26015fa6e665SDamon Ding }
26025fa6e665SDamon Ding 
26035fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win)
26045fa6e665SDamon Ding {
26055fa6e665SDamon Ding 	if (!is_vop3(vop2))
26065fa6e665SDamon Ding 		return false;
26075fa6e665SDamon Ding 
26085fa6e665SDamon Ding 	if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
26095fa6e665SDamon Ding 	    win->phys_id != ROCKCHIP_VOP2_ESMART0)
26105fa6e665SDamon Ding 		return true;
26115fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
26125fa6e665SDamon Ding 		 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
26135fa6e665SDamon Ding 		return true;
26145fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
26155fa6e665SDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART1)
26165fa6e665SDamon Ding 		return true;
2617a552a69cSDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE &&
2618a552a69cSDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART3)
2619a552a69cSDamon Ding 		return true;
26205fa6e665SDamon Ding 	else
26215fa6e665SDamon Ding 		return false;
26225fa6e665SDamon Ding }
26235fa6e665SDamon Ding 
26245fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
26255fa6e665SDamon Ding {
26265fa6e665SDamon Ding 	struct vop2_win_data *win_data;
2627fa4ecc32SDamon Ding 	int i;
26285fa6e665SDamon Ding 	u8 scale_engine_num = 0;
26295fa6e665SDamon Ding 
26305fa6e665SDamon Ding 	/* store plane mask for vop2_fixup_dts */
2631fa4ecc32SDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
2632fa4ecc32SDamon Ding 		win_data = &vop2->data->win_data[i];
26335fa6e665SDamon Ding 		if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data))
26345fa6e665SDamon Ding 			continue;
26355fa6e665SDamon Ding 
26365fa6e665SDamon Ding 		win_data->scale_engine_num = scale_engine_num++;
26375fa6e665SDamon Ding 	}
26385fa6e665SDamon Ding }
26395fa6e665SDamon Ding 
2640a552a69cSDamon Ding static int vop3_get_esmart_lb_mode(struct vop2 *vop2)
2641a552a69cSDamon Ding {
2642a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map;
2643a552a69cSDamon Ding 	int i;
2644a552a69cSDamon Ding 
2645a552a69cSDamon Ding 	if (!esmart_lb_mode_map)
2646a552a69cSDamon Ding 		return vop2->esmart_lb_mode;
2647a552a69cSDamon Ding 
2648a552a69cSDamon Ding 	for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) {
2649a552a69cSDamon Ding 		if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode)
2650a552a69cSDamon Ding 			return esmart_lb_mode_map->lb_map_value;
2651a552a69cSDamon Ding 		esmart_lb_mode_map++;
2652a552a69cSDamon Ding 	}
2653a552a69cSDamon Ding 
2654a552a69cSDamon Ding 	if (i == vop2->data->esmart_lb_mode_num)
2655a552a69cSDamon Ding 		printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode);
2656a552a69cSDamon Ding 
2657a552a69cSDamon Ding 	return vop2->data->esmart_lb_mode_map[0].lb_map_value;
2658a552a69cSDamon Ding }
2659a552a69cSDamon Ding 
2660b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
2661d0408543SAndy Yan {
2662b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
2663b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
2664a552a69cSDamon Ding 	int active_vp_num = 0;
26655fa6e665SDamon Ding 	int layer_phy_id = 0;
26665fa6e665SDamon Ding 	int i, j;
2667fa4ecc32SDamon Ding 	int ret;
26685fa6e665SDamon Ding 	u32 layer_nr = 0;
2669d0408543SAndy Yan 
267063cb669fSSandy Huang 	if (vop2->global_init)
2671d0408543SAndy Yan 		return;
267263cb669fSSandy Huang 
2673b0989546SSandy Huang 	/* OTP must enable at the first time, otherwise mirror layer register is error */
267463cb669fSSandy Huang 	if (soc_is_rk3566())
267563cb669fSSandy Huang 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
267663cb669fSSandy Huang 				OTP_WIN_EN_SHIFT, 1, false);
2677b0989546SSandy Huang 
2678b0989546SSandy Huang 	if (cstate->crtc->assign_plane) {/* dts assign plane */
2679b0989546SSandy Huang 		u32 plane_mask;
2680b0989546SSandy Huang 		int primary_plane_id;
2681b0989546SSandy Huang 
2682b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
2683b0989546SSandy Huang 			plane_mask = cstate->crtc->vps[i].plane_mask;
2684b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2685b0989546SSandy Huang 			layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */
2686b0989546SSandy Huang 			vop2->vp_plane_mask[i].attached_layers_nr = layer_nr;
26875fc2b656SDamon Ding 			primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
2688337d1c13SDamon Ding 			if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX)
2689b0989546SSandy Huang 				primary_plane_id = vop2_get_primary_plane(vop2, plane_mask);
2690b0989546SSandy Huang 			vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id;
2691b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2692b0989546SSandy Huang 
2693b0989546SSandy Huang 			/* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/
2694b0989546SSandy Huang 			for (j = 0; j < layer_nr; j++) {
2695b0989546SSandy Huang 				vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
2696b0989546SSandy Huang 				plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
269763cb669fSSandy Huang 			}
2698b0989546SSandy Huang 		}
2699b0989546SSandy Huang 	} else {/* need soft assign plane mask */
2700a552a69cSDamon Ding 		printf("Assign plane mask automatically\n");
2701a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
2702a552a69cSDamon Ding 			for (i = 0; i < vop2->data->nr_vps; i++) {
2703a552a69cSDamon Ding 				if (cstate->crtc->vps[i].enable) {
2704a552a69cSDamon Ding 					vop2->vp_plane_mask[i].attached_layers_nr = 1;
2705a552a69cSDamon Ding 					vop2->vp_plane_mask[i].primary_plane_id =
2706a552a69cSDamon Ding 						vop2->data->vp_default_primary_plane[i];
2707a552a69cSDamon Ding 					vop2->vp_plane_mask[i].attached_layers[0] =
2708a552a69cSDamon Ding 						vop2->data->vp_default_primary_plane[i];
2709a552a69cSDamon Ding 					vop2->vp_plane_mask[i].plane_mask |=
2710a552a69cSDamon Ding 						BIT(vop2->data->vp_default_primary_plane[i]);
2711a552a69cSDamon Ding 					active_vp_num++;
2712a552a69cSDamon Ding 				}
2713a552a69cSDamon Ding 			}
2714a552a69cSDamon Ding 			printf("VOP have %d active VP\n", active_vp_num);
2715a552a69cSDamon Ding 		} else {
2716b0989546SSandy Huang 			/* find the first unplug devices and set it as main display */
2717b0989546SSandy Huang 			int main_vp_index = -1;
2718b0989546SSandy Huang 
2719b0989546SSandy Huang 			for (i = 0; i < vop2->data->nr_vps; i++) {
2720b0989546SSandy Huang 				if (cstate->crtc->vps[i].enable)
2721b0989546SSandy Huang 					active_vp_num++;
2722b0989546SSandy Huang 			}
2723b0989546SSandy Huang 			printf("VOP have %d active VP\n", active_vp_num);
2724b0989546SSandy Huang 
2725b0989546SSandy Huang 			if (soc_is_rk3566() && active_vp_num > 2)
2726b0989546SSandy Huang 				printf("ERROR: rk3566 only support 2 display output!!\n");
2727b0989546SSandy Huang 			plane_mask = vop2->data->plane_mask;
2728b0989546SSandy Huang 			plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
27295fa6e665SDamon Ding 			/*
2730a552a69cSDamon Ding 			 * For rk3528, one display policy for hdmi store in plane_mask[0], and
2731a552a69cSDamon Ding 			 * the other for cvbs store in plane_mask[2].
27325fa6e665SDamon Ding 			 */
27335fa6e665SDamon Ding 			if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 &&
27345fa6e665SDamon Ding 			    cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV)
27355fa6e665SDamon Ding 				plane_mask += 2 * VOP2_VP_MAX;
2736b0989546SSandy Huang 
27375fa6e665SDamon Ding 			if (vop2->version == VOP_VERSION_RK3528) {
27385fa6e665SDamon Ding 				/*
2739a552a69cSDamon Ding 				 * For rk3528, the plane mask of vp is limited, only esmart2 can
2740a552a69cSDamon Ding 				 * be selected by both vp0 and vp1.
27415fa6e665SDamon Ding 				 */
27425fa6e665SDamon Ding 				j = 0;
27435fa6e665SDamon Ding 			} else {
2744b0989546SSandy Huang 				for (i = 0; i < vop2->data->nr_vps; i++) {
2745b0989546SSandy Huang 					if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
2746a552a69cSDamon Ding 						/* the first store main display plane mask */
2747a552a69cSDamon Ding 						vop2->vp_plane_mask[i] = plane_mask[0];
2748b0989546SSandy Huang 						main_vp_index = i;
2749e007876dSSandy Huang 						break;
2750b0989546SSandy Huang 					}
2751b0989546SSandy Huang 				}
2752b0989546SSandy Huang 
2753b0989546SSandy Huang 				/* if no find unplug devices, use vp0 as main display */
2754b0989546SSandy Huang 				if (main_vp_index < 0) {
2755b0989546SSandy Huang 					main_vp_index = 0;
2756b0989546SSandy Huang 					vop2->vp_plane_mask[0] = plane_mask[0];
2757b0989546SSandy Huang 				}
2758b0989546SSandy Huang 
2759a552a69cSDamon Ding 				/* plane_mask[0] store main display, so we from plane_mask[1] */
2760a552a69cSDamon Ding 				j = 1;
27615fa6e665SDamon Ding 			}
2762b0989546SSandy Huang 
2763b0989546SSandy Huang 			/* init other display except main display */
2764b0989546SSandy Huang 			for (i = 0; i < vop2->data->nr_vps; i++) {
2765a552a69cSDamon Ding 				/* main display or no connect devices */
2766a552a69cSDamon Ding 				if (i == main_vp_index || !cstate->crtc->vps[i].enable)
2767b0989546SSandy Huang 					continue;
2768b0989546SSandy Huang 				vop2->vp_plane_mask[i] = plane_mask[j++];
2769b0989546SSandy Huang 			}
2770a552a69cSDamon Ding 		}
2771b0989546SSandy Huang 		/* store plane mask for vop2_fixup_dts */
2772b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
2773b0989546SSandy Huang 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2774b0989546SSandy Huang 			for (j = 0; j < layer_nr; j++) {
2775b0989546SSandy Huang 				layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2776b0989546SSandy Huang 				vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
2777b0989546SSandy Huang 			}
2778b0989546SSandy Huang 		}
2779b0989546SSandy Huang 	}
2780b0989546SSandy Huang 
278160e469f5SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588)
278260e469f5SDamon Ding 		rk3588_vop2_regsbak(vop2);
278360e469f5SDamon Ding 	else
278460e469f5SDamon Ding 		memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
278560e469f5SDamon Ding 
278660e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
278760e469f5SDamon Ding 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
278860e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
278960e469f5SDamon Ding 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
279060e469f5SDamon Ding 
2791b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
2792b0989546SSandy Huang 		printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
2793b0989546SSandy Huang 		for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
279427cec8e2SDamon Ding 			printf("%s ",
279527cec8e2SDamon Ding 			       vop2_plane_id_to_string(vop2->vp_plane_mask[i].attached_layers[j]));
279627cec8e2SDamon Ding 		printf("], primary plane: %s\n",
279727cec8e2SDamon Ding 		       vop2_plane_id_to_string(vop2->vp_plane_mask[i].primary_plane_id));
2798b0989546SSandy Huang 	}
2799b0989546SSandy Huang 
28005fa6e665SDamon Ding 	if (is_vop3(vop2))
28015fa6e665SDamon Ding 		vop3_overlay_init(vop2, state);
28025fa6e665SDamon Ding 	else
28035fa6e665SDamon Ding 		vop2_overlay_init(vop2, state);
2804b0989546SSandy Huang 
28055fa6e665SDamon Ding 	if (is_vop3(vop2)) {
28065fa6e665SDamon Ding 		/*
28075fa6e665SDamon Ding 		 * you can rewrite at dts vop node:
28085fa6e665SDamon Ding 		 *
28095fa6e665SDamon Ding 		 * VOP3_ESMART_8K_MODE = 0,
28105fa6e665SDamon Ding 		 * VOP3_ESMART_4K_4K_MODE = 1,
28115fa6e665SDamon Ding 		 * VOP3_ESMART_4K_2K_2K_MODE = 2,
28125fa6e665SDamon Ding 		 * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
28135fa6e665SDamon Ding 		 *
28145fa6e665SDamon Ding 		 * &vop {
28155fa6e665SDamon Ding 		 * 	esmart_lb_mode = /bits/ 8 <2>;
28165fa6e665SDamon Ding 		 * };
281763cb669fSSandy Huang 		 */
2818fa4ecc32SDamon Ding 		ret = ofnode_read_u32(cstate->node, "esmart_lb_mode", &vop2->esmart_lb_mode);
2819fa4ecc32SDamon Ding 		if (ret < 0)
28205fa6e665SDamon Ding 			vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
2821a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
2822a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL,
2823a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_MASK,
2824a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_SHIFT,
2825a552a69cSDamon Ding 					vop3_get_esmart_lb_mode(vop2), true);
2826a552a69cSDamon Ding 		else
2827a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
2828a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_MASK,
2829a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_SHIFT,
2830f6e9a2a3SDamon Ding 					vop3_get_esmart_lb_mode(vop2), false);
2831d0408543SAndy Yan 
28325fa6e665SDamon Ding 		vop3_init_esmart_scale_engine(vop2);
2833aa670293SDamon Ding 
283412ee4de7SDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
283512ee4de7SDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
283612ee4de7SDamon Ding 					RK3576_DSP_VS_T_SEL_SHIFT, 0, true);
283712ee4de7SDamon Ding 		else
2838aa670293SDamon Ding 			vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK,
2839aa670293SDamon Ding 					DSP_VS_T_SEL_SHIFT, 0, false);
2840bb7ec356SDamon Ding 
2841bb7ec356SDamon Ding 		/*
2842bb7ec356SDamon Ding 		 * This is a workaround for RK3528/RK3562/RK3576:
2843bb7ec356SDamon Ding 		 *
2844bb7ec356SDamon Ding 		 * The aclk pre auto gating function may disable the aclk
2845bb7ec356SDamon Ding 		 * in some unexpected cases, which detected by hardware
2846bb7ec356SDamon Ding 		 * automatically.
2847bb7ec356SDamon Ding 		 *
2848bb7ec356SDamon Ding 		 * For example, if the above function is enabled, the post
2849bb7ec356SDamon Ding 		 * scale function will be affected, resulting in abnormal
2850bb7ec356SDamon Ding 		 * display.
2851bb7ec356SDamon Ding 		 */
2852bb7ec356SDamon Ding 		if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 ||
2853bb7ec356SDamon Ding 		    vop2->version == VOP_VERSION_RK3576)
2854bb7ec356SDamon Ding 			vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
2855bb7ec356SDamon Ding 					ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false);
285663cb669fSSandy Huang 	}
285763cb669fSSandy Huang 
2858ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3568)
285963cb669fSSandy Huang 		vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
286063cb669fSSandy Huang 
2861a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576) {
2862a552a69cSDamon Ding 		vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq");
2863a552a69cSDamon Ding 
2864f67105fbSSandy Huang 		/* Default use rkiommu 1.0 for axi0 */
2865f67105fbSSandy Huang 		vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 0, true);
2866a552a69cSDamon Ding 
2867a552a69cSDamon Ding 		/* Init frc2.0 config */
2868a552a69cSDamon Ding 		vop2_writel(vop2, 0xca0, 0xc8);
2869a552a69cSDamon Ding 		vop2_writel(vop2, 0xca4, 0x01000100);
2870a552a69cSDamon Ding 		vop2_writel(vop2, 0xca8, 0x03ff0100);
2871a552a69cSDamon Ding 		vop2_writel(vop2, 0xda0, 0xc8);
2872a552a69cSDamon Ding 		vop2_writel(vop2, 0xda4, 0x01000100);
2873a552a69cSDamon Ding 		vop2_writel(vop2, 0xda8, 0x03ff0100);
2874a552a69cSDamon Ding 
2875a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true)
2876a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
2877a552a69cSDamon Ding 					VP_INTR_MERGE_EN_SHIFT, 1, true);
2878a552a69cSDamon Ding 
2879a552a69cSDamon Ding 		/* Set reg done every field for interlace */
2880a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK,
2881a552a69cSDamon Ding 				INTERLACE_FRM_REG_DONE_SHIFT, 0, false);
2882a552a69cSDamon Ding 	}
2883a552a69cSDamon Ding 
288463cb669fSSandy Huang 	vop2->global_init = true;
2885d0408543SAndy Yan }
2886d0408543SAndy Yan 
2887344e932aSDamon Ding static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state)
2888344e932aSDamon Ding {
2889344e932aSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2890344e932aSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
2891344e932aSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
2892344e932aSDamon Ding 	struct resource sharp_regs;
2893344e932aSDamon Ding 	u32 *sharp_reg_base;
2894344e932aSDamon Ding 	int ret;
2895344e932aSDamon Ding 
2896344e932aSDamon Ding 	if (!(vp_data->feature & VOP_FEATURE_POST_SHARP))
2897344e932aSDamon Ding 		return;
2898344e932aSDamon Ding 
2899344e932aSDamon Ding 	ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs);
2900344e932aSDamon Ding 	if (ret) {
2901344e932aSDamon Ding 		printf("failed to get sharp regs\n");
2902344e932aSDamon Ding 		return;
2903344e932aSDamon Ding 	}
2904344e932aSDamon Ding 	sharp_reg_base = (u32 *)sharp_regs.start;
2905344e932aSDamon Ding 
2906344e932aSDamon Ding 	/*
2907344e932aSDamon Ding 	 * After vop initialization, keep sw_sharp_enable always on.
2908344e932aSDamon Ding 	 * Only enable/disable sharp submodule to avoid black screen.
2909344e932aSDamon Ding 	 */
2910344e932aSDamon Ding 	writel(0x1, sharp_reg_base);
2911344e932aSDamon Ding }
2912344e932aSDamon Ding 
2913c54cc5d2SAlgea Cao static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state)
2914c54cc5d2SAlgea Cao {
2915c54cc5d2SAlgea Cao 	struct crtc_state *cstate = &state->crtc_state;
2916c54cc5d2SAlgea Cao 	const struct vop2_data *vop2_data = vop2->data;
2917c54cc5d2SAlgea Cao 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
2918c54cc5d2SAlgea Cao 	struct resource acm_regs;
2919c54cc5d2SAlgea Cao 	u32 *acm_reg_base;
2920c54cc5d2SAlgea Cao 	u32 vp_offset = (cstate->crtc_id * 0x100);
2921c54cc5d2SAlgea Cao 	int ret;
2922c54cc5d2SAlgea Cao 
2923c54cc5d2SAlgea Cao 	if (!(vp_data->feature & VOP_FEATURE_POST_ACM))
2924c54cc5d2SAlgea Cao 		return;
2925c54cc5d2SAlgea Cao 
2926c54cc5d2SAlgea Cao 	ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs);
2927c54cc5d2SAlgea Cao 	if (ret) {
2928c54cc5d2SAlgea Cao 		printf("failed to get acm regs\n");
2929c54cc5d2SAlgea Cao 		return;
2930c54cc5d2SAlgea Cao 	}
2931c54cc5d2SAlgea Cao 	acm_reg_base = (u32 *)acm_regs.start;
2932c54cc5d2SAlgea Cao 
2933c54cc5d2SAlgea Cao 	/*
2934c54cc5d2SAlgea Cao 	 * Black screen is displayed when acm bypass switched
2935c54cc5d2SAlgea Cao 	 * between enable and disable. Therefore, disable acm
2936c54cc5d2SAlgea Cao 	 * bypass by default after system boot.
2937c54cc5d2SAlgea Cao 	 */
2938c54cc5d2SAlgea Cao 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2939c54cc5d2SAlgea Cao 			POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2940c54cc5d2SAlgea Cao 
2941e1946cbdSAlgea Cao 	writel(0, acm_reg_base + 0);
2942c54cc5d2SAlgea Cao }
2943c54cc5d2SAlgea Cao 
29440669ab1fSDamon Ding static int rockchip_vop2_of_get_gamma_lut(struct display_state *state,
29450669ab1fSDamon Ding 					  struct device_node *dsp_lut_node)
29460669ab1fSDamon Ding {
29470669ab1fSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
29480669ab1fSDamon Ding 	struct resource gamma_res;
29490669ab1fSDamon Ding 	fdt_size_t lut_size;
29500669ab1fSDamon Ding 	u32 *lut_regs;
29510669ab1fSDamon Ding 	u32 *lut;
29520669ab1fSDamon Ding 	u32 r, g, b;
29530669ab1fSDamon Ding 	int lut_len;
29540669ab1fSDamon Ding 	int length;
29550669ab1fSDamon Ding 	int i, j;
29560669ab1fSDamon Ding 	int ret = 0;
29570669ab1fSDamon Ding 
29580669ab1fSDamon Ding 	of_get_property(dsp_lut_node, "gamma-lut", &length);
29590669ab1fSDamon Ding 	if (!length)
29600669ab1fSDamon Ding 		return -EINVAL;
29610669ab1fSDamon Ding 
29620669ab1fSDamon Ding 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
29630669ab1fSDamon Ding 	if (ret)
29640669ab1fSDamon Ding 		printf("failed to get gamma lut res\n");
29650669ab1fSDamon Ding 	lut_regs = (u32 *)gamma_res.start;
29660669ab1fSDamon Ding 	lut_size = gamma_res.end - gamma_res.start + 1;
29670669ab1fSDamon Ding 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
29680669ab1fSDamon Ding 		printf("failed to get gamma lut register\n");
29690669ab1fSDamon Ding 		return -EINVAL;
29700669ab1fSDamon Ding 	}
29710669ab1fSDamon Ding 	lut_len = lut_size / 4;
29720669ab1fSDamon Ding 
29730669ab1fSDamon Ding 	cstate->lut_val = (u32 *)calloc(1, lut_size);
29740669ab1fSDamon Ding 	if (!cstate->lut_val)
29750669ab1fSDamon Ding 		return -ENOMEM;
29760669ab1fSDamon Ding 
29770669ab1fSDamon Ding 	length >>= 2;
29780669ab1fSDamon Ding 	if (length != lut_len) {
29790669ab1fSDamon Ding 		lut = (u32 *)calloc(1, lut_len);
29800669ab1fSDamon Ding 		if (!lut) {
29810669ab1fSDamon Ding 			free(cstate->lut_val);
29820669ab1fSDamon Ding 			return -ENOMEM;
29830669ab1fSDamon Ding 		}
29840669ab1fSDamon Ding 
29850669ab1fSDamon Ding 		ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length);
29860669ab1fSDamon Ding 		if (ret) {
29870669ab1fSDamon Ding 			printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id);
29880669ab1fSDamon Ding 			free(cstate->lut_val);
29890669ab1fSDamon Ding 			free(lut);
29900669ab1fSDamon Ding 			return -EINVAL;
29910669ab1fSDamon Ding 		}
29920669ab1fSDamon Ding 
29930669ab1fSDamon Ding 		/*
29940669ab1fSDamon Ding 		 * In order to achieve the same gamma correction effect in different
29950669ab1fSDamon Ding 		 * platforms, the following conversion helps to translate from 8bit
29960669ab1fSDamon Ding 		 * gamma table with 256 parameters to 10bit gamma with 1024 parameters.
29970669ab1fSDamon Ding 		 */
29980669ab1fSDamon Ding 		for (i = 0; i < lut_len; i++) {
29990669ab1fSDamon Ding 			j = i * length / lut_len;
30000669ab1fSDamon Ding 			r = lut[j] / length / length * lut_len / length;
30010669ab1fSDamon Ding 			g = lut[j] / length % length * lut_len / length;
30020669ab1fSDamon Ding 			b = lut[j] % length * lut_len / length;
30030669ab1fSDamon Ding 
30040669ab1fSDamon Ding 			cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b;
30050669ab1fSDamon Ding 		}
30060669ab1fSDamon Ding 		free(lut);
30070669ab1fSDamon Ding 	} else {
30080669ab1fSDamon Ding 		of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len);
30090669ab1fSDamon Ding 	}
30100669ab1fSDamon Ding 
30110669ab1fSDamon Ding 	return 0;
30120669ab1fSDamon Ding }
30130669ab1fSDamon Ding 
30140669ab1fSDamon Ding static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state)
30150669ab1fSDamon Ding {
30160669ab1fSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
30170669ab1fSDamon Ding 	struct device_node *dsp_lut_node;
30180669ab1fSDamon Ding 	int phandle;
30190669ab1fSDamon Ding 	int ret = 0;
30200669ab1fSDamon Ding 
30210669ab1fSDamon Ding 	phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1);
30220669ab1fSDamon Ding 	if (phandle < 0)
30230669ab1fSDamon Ding 		return;
30240669ab1fSDamon Ding 
30250669ab1fSDamon Ding 	dsp_lut_node = of_find_node_by_phandle(phandle);
30260669ab1fSDamon Ding 	if (!dsp_lut_node)
30270669ab1fSDamon Ding 		return;
30280669ab1fSDamon Ding 
30290669ab1fSDamon Ding 	ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node);
30300669ab1fSDamon Ding 	if (ret)
30310669ab1fSDamon Ding 		printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id);
30320669ab1fSDamon Ding }
30330669ab1fSDamon Ding 
3034d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state)
3035d0408543SAndy Yan {
30360669ab1fSDamon Ding 	rockchip_vop2_of_get_dsp_lut(vop2, state);
30370669ab1fSDamon Ding 
30381147facaSSandy Huang 	rockchip_vop2_gamma_lut_init(vop2, state);
30396414e3bcSSandy Huang 	rockchip_vop2_cubic_lut_init(vop2, state);
3040344e932aSDamon Ding 	rockchip_vop2_sharp_init(vop2, state);
3041c54cc5d2SAlgea Cao 	rockchip_vop2_acm_init(vop2, state);
3042d0408543SAndy Yan 
3043d0408543SAndy Yan 	return 0;
3044d0408543SAndy Yan }
3045d0408543SAndy Yan 
3046d0408543SAndy Yan /*
3047d0408543SAndy Yan  * VOP2 have multi video ports.
3048d0408543SAndy Yan  * video port ------- crtc
3049d0408543SAndy Yan  */
3050d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state)
3051d0408543SAndy Yan {
3052d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3053d0408543SAndy Yan 	const struct vop2_data *vop2_data = cstate->crtc->data;
3054734a0ce6SDamon Ding 	struct regmap *map;
30550686a6a6SZhang Yubing 	char dclk_name[16];
30560686a6a6SZhang Yubing 	int ret;
3057d0408543SAndy Yan 
3058d0408543SAndy Yan 	if (!rockchip_vop2) {
30590d2d6a97SSandy Huang 		rockchip_vop2 = calloc(1, sizeof(struct vop2));
3060d0408543SAndy Yan 		if (!rockchip_vop2)
3061d0408543SAndy Yan 			return -ENOMEM;
3062d8e7f4a5SSandy Huang 		memset(rockchip_vop2, 0, sizeof(struct vop2));
3063d0408543SAndy Yan 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
3064d0408543SAndy Yan 		rockchip_vop2->reg_len = RK3568_MAX_REG;
3065d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD
3066d8e7f4a5SSandy Huang 		rockchip_vop2->regs = (void *)RK3528_VOP_BASE;
3067d8e7f4a5SSandy Huang #else
3068d8e7f4a5SSandy Huang 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
3069734a0ce6SDamon Ding 		map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf");
3070734a0ce6SDamon Ding 		rockchip_vop2->grf = regmap_get_range(map, 0);
3071d0408543SAndy Yan 		if (rockchip_vop2->grf <= 0)
307263cb669fSSandy Huang 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
3073d8e7f4a5SSandy Huang #endif
3074d0408543SAndy Yan 		rockchip_vop2->version = vop2_data->version;
3075d0408543SAndy Yan 		rockchip_vop2->data = vop2_data;
3076ecc31b6eSAndy Yan 		if (rockchip_vop2->version == VOP_VERSION_RK3588) {
3077734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf");
3078734a0ce6SDamon Ding 			rockchip_vop2->vop_grf = regmap_get_range(map, 0);
3079ecc31b6eSAndy Yan 			if (rockchip_vop2->vop_grf <= 0)
3080a552a69cSDamon Ding 				printf("%s: Get syscon vop_grf failed (ret=%p)\n",
3081a552a69cSDamon Ding 				       __func__, rockchip_vop2->vop_grf);
3082b890760eSAlgea Cao 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf");
3083b890760eSAlgea Cao 			rockchip_vop2->vo1_grf = regmap_get_range(map, 0);
3084ecc31b6eSAndy Yan 			if (rockchip_vop2->vo1_grf <= 0)
3085a552a69cSDamon Ding 				printf("%s: Get syscon vo1_grf failed (ret=%p)\n",
3086a552a69cSDamon Ding 				       __func__, rockchip_vop2->vo1_grf);
3087734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3088734a0ce6SDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3089b890760eSAlgea Cao 			if (rockchip_vop2->sys_pmu <= 0)
3090a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3091a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
3092a552a69cSDamon Ding 		} else if (rockchip_vop2->version == VOP_VERSION_RK3576) {
3093a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf");
3094a552a69cSDamon Ding 			rockchip_vop2->ioc_grf = regmap_get_range(map, 0);
3095a552a69cSDamon Ding 			if (rockchip_vop2->ioc_grf <= 0)
3096a552a69cSDamon Ding 				printf("%s: Get syscon ioc_grf failed (ret=%p)\n",
3097a552a69cSDamon Ding 				       __func__, rockchip_vop2->ioc_grf);
3098a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3099a552a69cSDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3100a552a69cSDamon Ding 			if (rockchip_vop2->sys_pmu <= 0)
3101a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3102a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
3103ecc31b6eSAndy Yan 		}
3104d0408543SAndy Yan 	}
3105d0408543SAndy Yan 
31060686a6a6SZhang Yubing 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
31070686a6a6SZhang Yubing 	ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst);
31080686a6a6SZhang Yubing 	if (ret < 0) {
31090686a6a6SZhang Yubing 		printf("%s: failed to get dclk reset: %d\n", __func__, ret);
31100686a6a6SZhang Yubing 		cstate->dclk_rst.dev = NULL;
31110686a6a6SZhang Yubing 	}
31120686a6a6SZhang Yubing 
3113d0408543SAndy Yan 	cstate->private = rockchip_vop2;
311463cb669fSSandy Huang 	cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
311563cb669fSSandy Huang 	cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
3116d0408543SAndy Yan 
311789912f2dSSandy Huang 	vop2_global_initial(rockchip_vop2, state);
311889912f2dSSandy Huang 
3119d0408543SAndy Yan 	return 0;
3120d0408543SAndy Yan }
3121d0408543SAndy Yan 
3122ecc31b6eSAndy Yan /*
3123ecc31b6eSAndy Yan  * calc the dclk on rk3588
3124ecc31b6eSAndy Yan  * the available div of dclk is 1, 2, 4
3125ecc31b6eSAndy Yan  *
3126ecc31b6eSAndy Yan  */
3127ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
3128ecc31b6eSAndy Yan {
3129ecc31b6eSAndy Yan 	if (child_clk * 4 <= max_dclk)
3130ecc31b6eSAndy Yan 		return child_clk * 4;
3131ecc31b6eSAndy Yan 	else if (child_clk * 2 <= max_dclk)
3132ecc31b6eSAndy Yan 		return child_clk * 2;
3133ecc31b6eSAndy Yan 	else if (child_clk <= max_dclk)
3134ecc31b6eSAndy Yan 		return child_clk;
3135ecc31b6eSAndy Yan 	else
3136ecc31b6eSAndy Yan 		return 0;
3137ecc31b6eSAndy Yan }
3138ecc31b6eSAndy Yan 
3139ecc31b6eSAndy Yan /*
3140ecc31b6eSAndy Yan  * 4 pixclk/cycle on rk3588
3141ecc31b6eSAndy Yan  * RGB/eDP/HDMI: if_pixclk >= dclk_core
3142ecc31b6eSAndy Yan  * DP: dp_pixclk = dclk_out <= dclk_core
3143ecc31b6eSAndy Yan  * DSI: mipi_pixclk <= dclk_out <= dclk_core
3144ecc31b6eSAndy Yan  */
3145ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state,
3146ecc31b6eSAndy Yan 				       int *dclk_core_div, int *dclk_out_div,
3147ecc31b6eSAndy Yan 				       int *if_pixclk_div, int *if_dclk_div)
3148d0408543SAndy Yan {
3149d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3150d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3151d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
3152d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
31530a1fb152SZhang Yubing 	unsigned long v_pixclk = mode->crtc_clock;
3154ecc31b6eSAndy Yan 	unsigned long dclk_core_rate = v_pixclk >> 2;
3155ecc31b6eSAndy Yan 	unsigned long dclk_rate = v_pixclk;
3156ecc31b6eSAndy Yan 	unsigned long dclk_out_rate;
3157ecc31b6eSAndy Yan 	u64 if_dclk_rate;
3158ecc31b6eSAndy Yan 	u64 if_pixclk_rate;
3159ecc31b6eSAndy Yan 	int output_type = conn_state->type;
3160ecc31b6eSAndy Yan 	int output_mode = conn_state->output_mode;
3161ecc31b6eSAndy Yan 	int K = 1;
3162ecc31b6eSAndy Yan 
31630a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE &&
31640a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
31650a1fb152SZhang Yubing 		printf("Dual channel and YUV420 can't work together\n");
31660a1fb152SZhang Yubing 		return -EINVAL;
31670a1fb152SZhang Yubing 	}
31680a1fb152SZhang Yubing 
31690a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
31700a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420)
31710a1fb152SZhang Yubing 		K = 2;
31720a1fb152SZhang Yubing 
3173ecc31b6eSAndy Yan 	if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
3174ecc31b6eSAndy Yan 		/*
3175ecc31b6eSAndy Yan 		 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
3176ecc31b6eSAndy Yan 		 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
3177ecc31b6eSAndy Yan 		 */
31780a1fb152SZhang Yubing 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
31790a1fb152SZhang Yubing 		    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3180b890760eSAlgea Cao 			dclk_rate = dclk_rate >> 1;
3181ecc31b6eSAndy Yan 			K = 2;
3182b890760eSAlgea Cao 		}
318312ee5af0SDamon Ding 		if (cstate->dsc_enable) {
318412ee5af0SDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate << 1;
318512ee5af0SDamon Ding 			if_dclk_rate = cstate->dsc_cds_clk_rate;
3186ecc31b6eSAndy Yan 		} else {
3187ecc31b6eSAndy Yan 			if_pixclk_rate = (dclk_core_rate << 1) / K;
3188ecc31b6eSAndy Yan 			if_dclk_rate = dclk_core_rate / K;
3189ecc31b6eSAndy Yan 		}
3190ecc31b6eSAndy Yan 
3191631ee99aSZhang Yubing 		if (v_pixclk > VOP2_MAX_DCLK_RATE)
31924b726cc6SDamon Ding 			dclk_rate = vop2_calc_dclk(dclk_core_rate,
31934b726cc6SDamon Ding 						   vop2->data->vp_data[cstate->crtc_id].max_dclk);
3194631ee99aSZhang Yubing 
3195ecc31b6eSAndy Yan 		if (!dclk_rate) {
3196ecc31b6eSAndy Yan 			printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n",
31974b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate);
3198ecc31b6eSAndy Yan 			return -EINVAL;
3199ecc31b6eSAndy Yan 		}
3200ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3201ecc31b6eSAndy Yan 		*if_dclk_div = dclk_rate / if_dclk_rate;
3202b890760eSAlgea Cao 		*dclk_core_div = dclk_rate / dclk_core_rate;
3203b890760eSAlgea Cao 		printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n",
3204b890760eSAlgea Cao 		       dclk_rate, *if_pixclk_div, *if_dclk_div);
3205ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_eDP) {
3206ecc31b6eSAndy Yan 		/* edp_pixclk = edp_dclk > dclk_core */
3207ecc31b6eSAndy Yan 		if_pixclk_rate = v_pixclk / K;
3208ecc31b6eSAndy Yan 		if_dclk_rate = v_pixclk / K;
3209ecc31b6eSAndy Yan 		dclk_rate = if_pixclk_rate * K;
3210ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3211ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3212ecc31b6eSAndy Yan 		*if_dclk_div = *if_pixclk_div;
3213ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
3214ecc31b6eSAndy Yan 		dclk_out_rate = v_pixclk >> 2;
32150a1fb152SZhang Yubing 		dclk_out_rate = dclk_out_rate / K;
3216ecc31b6eSAndy Yan 
32174b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
32184b726cc6SDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
3219ecc31b6eSAndy Yan 		if (!dclk_rate) {
3220ecc31b6eSAndy Yan 			printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n",
32214b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate);
3222ecc31b6eSAndy Yan 			return -EINVAL;
3223ecc31b6eSAndy Yan 		}
3224ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3225ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3226ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DSI) {
3227ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3228ecc31b6eSAndy Yan 			K = 2;
322912ee5af0SDamon Ding 		if (cstate->dsc_enable)
323012ee5af0SDamon Ding 			/* dsc output is 96bit, dsi input is 192 bit */
323112ee5af0SDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1;
3232ecc31b6eSAndy Yan 		else
3233ecc31b6eSAndy Yan 			if_pixclk_rate = dclk_core_rate / K;
3234ecc31b6eSAndy Yan 		/* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
323512ee5af0SDamon Ding 		dclk_out_rate = dclk_core_rate / K;
3236ecc31b6eSAndy Yan 		/* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
32374b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
32384b726cc6SDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
32399f076eccSZhang Yubing 		if (!dclk_rate) {
32409f076eccSZhang Yubing 			printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n",
32414b726cc6SDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate);
32429f076eccSZhang Yubing 			return -EINVAL;
32439f076eccSZhang Yubing 		}
324412ee5af0SDamon Ding 
324512ee5af0SDamon Ding 		if (cstate->dsc_enable)
3246d57af898SDamon Ding 			dclk_rate /= cstate->dsc_slice_num;
324712ee5af0SDamon Ding 
3248ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3249ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3250ecc31b6eSAndy Yan 		*if_pixclk_div = 1;       /*mipi pixclk == dclk_out*/
325112ee5af0SDamon Ding 		if (cstate->dsc_enable)
32521ace1b6dSDamon Ding 			*if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate;
3253ecc31b6eSAndy Yan 
3254ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DPI) {
3255ecc31b6eSAndy Yan 		dclk_rate = v_pixclk;
3256ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3257ecc31b6eSAndy Yan 	}
3258ecc31b6eSAndy Yan 
3259ecc31b6eSAndy Yan 	*if_pixclk_div = ilog2(*if_pixclk_div);
3260ecc31b6eSAndy Yan 	*if_dclk_div = ilog2(*if_dclk_div);
3261ecc31b6eSAndy Yan 	*dclk_core_div = ilog2(*dclk_core_div);
3262ecc31b6eSAndy Yan 	*dclk_out_div = ilog2(*dclk_out_div);
3263ecc31b6eSAndy Yan 
3264ecc31b6eSAndy Yan 	return dclk_rate;
3265ecc31b6eSAndy Yan }
3266ecc31b6eSAndy Yan 
326712ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state)
3268ecc31b6eSAndy Yan {
326912ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3270ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
327112ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
32721ace1b6dSDamon Ding 	u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */
3273ecc31b6eSAndy Yan 	u8 k = 1;
3274ecc31b6eSAndy Yan 
3275ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3276ecc31b6eSAndy Yan 		k = 2;
3277ecc31b6eSAndy Yan 
327812ee5af0SDamon Ding 	cstate->dsc_txp_clk_rate = v_pixclk;
327912ee5af0SDamon Ding 	do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k));
3280ecc31b6eSAndy Yan 
328112ee5af0SDamon Ding 	cstate->dsc_pxl_clk_rate = v_pixclk;
328212ee5af0SDamon Ding 	do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k));
3283ecc31b6eSAndy Yan 
3284ecc31b6eSAndy Yan 	/* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
3285ecc31b6eSAndy Yan 	 * cds_dat_width = 96;
3286ecc31b6eSAndy Yan 	 * bits_per_pixel = [8-12];
3287b61227a3SDamon Ding 	 * As cds clk is div from txp clk and only support 1/2/4 div,
3288b61227a3SDamon Ding 	 * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
3289b61227a3SDamon Ding 	 * otherwise dsc_cds = crtc_clock / 8;
3290ecc31b6eSAndy Yan 	 */
3291b61227a3SDamon Ding 	cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
3292ecc31b6eSAndy Yan 
3293ecc31b6eSAndy Yan 	return 0;
3294ecc31b6eSAndy Yan }
3295ecc31b6eSAndy Yan 
3296ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
3297ecc31b6eSAndy Yan {
3298ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3299ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3300ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
330112ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
3302ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
330352ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
3304ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
3305ecc31b6eSAndy Yan 	int output_if = conn_state->output_if;
3306ecc31b6eSAndy Yan 	int if_pixclk_div = 0;
3307ecc31b6eSAndy Yan 	int if_dclk_div = 0;
3308ecc31b6eSAndy Yan 	unsigned long dclk_rate;
33095d2768f7SDamon Ding 	bool dclk_inv, yc_swap = false;
3310d0408543SAndy Yan 	u32 val;
3311ecc31b6eSAndy Yan 
33125d2768f7SDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3313b890760eSAlgea Cao 	if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
3314b890760eSAlgea Cao 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
3315b890760eSAlgea Cao 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
3316b890760eSAlgea Cao 	} else {
3317ecc31b6eSAndy Yan 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3318ecc31b6eSAndy Yan 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3319b890760eSAlgea Cao 	}
3320ecc31b6eSAndy Yan 
332112ee5af0SDamon Ding 	if (cstate->dsc_enable) {
332212ee5af0SDamon Ding 		int k = 1;
332312ee5af0SDamon Ding 
3324ecc31b6eSAndy Yan 		if (!vop2->data->nr_dscs) {
332512ee5af0SDamon Ding 			printf("Unsupported DSC\n");
3326ecc31b6eSAndy Yan 			return 0;
3327ecc31b6eSAndy Yan 		}
332812ee5af0SDamon Ding 
332912ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
333012ee5af0SDamon Ding 			k = 2;
333112ee5af0SDamon Ding 
333212ee5af0SDamon Ding 		cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
333312ee5af0SDamon Ding 		cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
333412ee5af0SDamon Ding 		cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num;
333512ee5af0SDamon Ding 
333612ee5af0SDamon Ding 		vop2_calc_dsc_clk(state);
333712ee5af0SDamon Ding 		printf("Enable DSC%d slice:%dx%d, slice num:%d\n",
333812ee5af0SDamon Ding 		       cstate->dsc_id, dsc_sink_cap->slice_width,
333912ee5af0SDamon Ding 		       dsc_sink_cap->slice_height, cstate->dsc_slice_num);
3340ecc31b6eSAndy Yan 	}
3341ecc31b6eSAndy Yan 
3342b61227a3SDamon Ding 	dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div);
3343ecc31b6eSAndy Yan 
3344ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_RGB) {
3345ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3346ecc31b6eSAndy Yan 				4, false);
33475d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
33485d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3349ecc31b6eSAndy Yan 	}
3350ecc31b6eSAndy Yan 
3351ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3352ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3353ecc31b6eSAndy Yan 				3, false);
33545d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
33555d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
33565d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
33575d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT,
33585d2768f7SDamon Ding 				yc_swap, false);
3359ecc31b6eSAndy Yan 	}
3360ecc31b6eSAndy Yan 
3361ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT656) {
3362ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3363ecc31b6eSAndy Yan 				2, false);
33645d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
33655d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
33665d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
33675d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT,
33685d2768f7SDamon Ding 				yc_swap, false);
3369ecc31b6eSAndy Yan 	}
3370ecc31b6eSAndy Yan 
3371ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3372ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3373ecc31b6eSAndy Yan 			val = 0;
3374ecc31b6eSAndy Yan 		else
3375ecc31b6eSAndy Yan 			val = 1;
337641874944SGuochun Huang 
33773df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
337841874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
337941874944SGuochun Huang 					RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
338041874944SGuochun Huang 
3381ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
3382ecc31b6eSAndy Yan 				1, false);
3383ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
3384ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
3385ecc31b6eSAndy Yan 				if_pixclk_div, false);
338641874944SGuochun Huang 
338741874944SGuochun Huang 		if (conn_state->hold_mode) {
338841874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
33898e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
339041874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
339141874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
339241874944SGuochun Huang 		}
3393ecc31b6eSAndy Yan 	}
3394ecc31b6eSAndy Yan 
3395ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI1) {
3396ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3397ecc31b6eSAndy Yan 			val = 0;
3398ecc31b6eSAndy Yan 		else if (cstate->crtc_id == 3)
3399ecc31b6eSAndy Yan 			val = 1;
3400ecc31b6eSAndy Yan 		else
3401ecc31b6eSAndy Yan 			val = 3; /*VP1*/
34023df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
340341874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
340441874944SGuochun Huang 					RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
340541874944SGuochun Huang 
3406ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
3407ecc31b6eSAndy Yan 				1, false);
3408ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
3409ecc31b6eSAndy Yan 				val, false);
3410ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
3411ecc31b6eSAndy Yan 				if_pixclk_div, false);
341241874944SGuochun Huang 
341341874944SGuochun Huang 		if (conn_state->hold_mode) {
341441874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
34158e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
341641874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
341741874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
341841874944SGuochun Huang 		}
3419ecc31b6eSAndy Yan 	}
3420ecc31b6eSAndy Yan 
3421ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
34223df6e59eSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
34233df6e59eSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
3424ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3425ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3426ecc31b6eSAndy Yan 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
3427ecc31b6eSAndy Yan 					false);
34280a1fb152SZhang Yubing 		switch (conn_state->type) {
34290a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DisplayPort:
34300a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
34310a1fb152SZhang Yubing 					RK3588_DP_DUAL_EN_SHIFT, 1, false);
34320a1fb152SZhang Yubing 			break;
34330a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_eDP:
34340a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
34350a1fb152SZhang Yubing 					RK3588_EDP_DUAL_EN_SHIFT, 1, false);
34360a1fb152SZhang Yubing 			break;
34370a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_HDMIA:
34380a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
34390a1fb152SZhang Yubing 					RK3588_HDMI_DUAL_EN_SHIFT, 1, false);
34400a1fb152SZhang Yubing 			break;
34410a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DSI:
34420a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
34430a1fb152SZhang Yubing 					RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
34440a1fb152SZhang Yubing 			break;
34450a1fb152SZhang Yubing 		default:
34460a1fb152SZhang Yubing 			break;
34470a1fb152SZhang Yubing 		}
3448ecc31b6eSAndy Yan 	}
3449ecc31b6eSAndy Yan 
3450ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP0) {
3451ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
3452ecc31b6eSAndy Yan 				1, false);
3453ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3454ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3455ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3456ecc31b6eSAndy Yan 				if_dclk_div, false);
3457ecc31b6eSAndy Yan 
3458ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3459ecc31b6eSAndy Yan 				if_pixclk_div, false);
3460ecc31b6eSAndy Yan 
3461ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3462ecc31b6eSAndy Yan 				RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
3463ecc31b6eSAndy Yan 	}
3464ecc31b6eSAndy Yan 
3465ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP1) {
3466ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
3467ecc31b6eSAndy Yan 				1, false);
3468ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3469ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3470ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3471ecc31b6eSAndy Yan 				if_dclk_div, false);
3472ecc31b6eSAndy Yan 
3473ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3474ecc31b6eSAndy Yan 				if_pixclk_div, false);
34751848455fSDamon Ding 
34761848455fSDamon Ding 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
34771848455fSDamon Ding 				RK3588_GRF_EDP1_ENABLE_SHIFT, 1);
3478ecc31b6eSAndy Yan 	}
3479ecc31b6eSAndy Yan 
3480ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
3481ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
3482ecc31b6eSAndy Yan 				1, false);
3483ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3484ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3485ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3486ecc31b6eSAndy Yan 				if_dclk_div, false);
3487ecc31b6eSAndy Yan 
3488ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3489ecc31b6eSAndy Yan 				if_pixclk_div, false);
3490b890760eSAlgea Cao 
3491b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3492b890760eSAlgea Cao 				RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1);
3493b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3494b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3495b890760eSAlgea Cao 				HDMI0_SYNC_POL_SHIFT, val);
3496ecc31b6eSAndy Yan 	}
3497ecc31b6eSAndy Yan 
3498ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI1) {
3499ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
3500ecc31b6eSAndy Yan 				1, false);
3501ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3502ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3503ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3504ecc31b6eSAndy Yan 				if_dclk_div, false);
3505ecc31b6eSAndy Yan 
3506ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3507ecc31b6eSAndy Yan 				if_pixclk_div, false);
3508b890760eSAlgea Cao 
3509b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3510b890760eSAlgea Cao 				RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1);
3511b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3512b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3513b890760eSAlgea Cao 				HDMI1_SYNC_POL_SHIFT, val);
3514ecc31b6eSAndy Yan 	}
3515ecc31b6eSAndy Yan 
3516ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP0) {
3517ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
3518ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3519ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3520ecc31b6eSAndy Yan 				RK3588_DP0_PIN_POL_SHIFT, val, false);
3521ecc31b6eSAndy Yan 	}
3522ecc31b6eSAndy Yan 
3523ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP1) {
3524ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
3525ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3526ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3527ecc31b6eSAndy Yan 				RK3588_DP1_PIN_POL_SHIFT, val, false);
3528ecc31b6eSAndy Yan 	}
3529ecc31b6eSAndy Yan 
3530ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3531b61227a3SDamon Ding 			DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false);
3532ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3533b61227a3SDamon Ding 			DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false);
3534ecc31b6eSAndy Yan 
3535ecc31b6eSAndy Yan 	return dclk_rate;
3536ecc31b6eSAndy Yan }
3537ecc31b6eSAndy Yan 
3538a552a69cSDamon Ding static unsigned long rk3576_vop2_if_cfg(struct display_state *state)
3539a552a69cSDamon Ding {
3540a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3541a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3542a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3543a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
3544a552a69cSDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
3545a552a69cSDamon Ding 	u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate;
3546a552a69cSDamon Ding 	int output_if = conn_state->output_if;
3547a552a69cSDamon Ding 	bool dclk_inv, yc_swap = false;
3548a552a69cSDamon Ding 	bool split_mode = !!(conn_state->output_flags &
3549a552a69cSDamon Ding 			     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE);
3550a552a69cSDamon Ding 	bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false;
3551a552a69cSDamon Ding 	bool interface_dclk_sel, interface_pix_clk_sel = false;
3552a552a69cSDamon Ding 	bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK ||
3553a552a69cSDamon Ding 			    conn_state->output_if & VOP_OUTPUT_IF_BT656;
3554cce1f2abSDamon Ding 	unsigned long dclk_in_rate, dclk_core_rate;
3555a552a69cSDamon Ding 	u32 val;
3556a552a69cSDamon Ding 
3557a552a69cSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3558a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3559a552a69cSDamon Ding 		/*
3560a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3561a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
3562a552a69cSDamon Ding 		 */
3563a552a69cSDamon Ding 		val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3564a552a69cSDamon Ding 	} else {
3565a552a69cSDamon Ding 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3566a552a69cSDamon Ding 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3567a552a69cSDamon Ding 	}
3568a552a69cSDamon Ding 
3569cce1f2abSDamon Ding 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 ||
3570cce1f2abSDamon Ding 	    mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode))
3571a552a69cSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */
3572a552a69cSDamon Ding 	else
3573cce1f2abSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */
3574cce1f2abSDamon Ding 	dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div;
3575cce1f2abSDamon Ding 
3576cce1f2abSDamon Ding 	if (double_pixel)
3577cce1f2abSDamon Ding 		dclk_core_rate = mode->crtc_clock / 2;
3578cce1f2abSDamon Ding 	else
3579cce1f2abSDamon Ding 		dclk_core_rate = mode->crtc_clock / port_pix_rate;
3580cce1f2abSDamon Ding 	post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */
3581a552a69cSDamon Ding 
3582a552a69cSDamon Ding 	if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3583a552a69cSDamon Ding 		pix_half_rate = true;
3584a552a69cSDamon Ding 		post_dclk_out_sel = true;
3585a552a69cSDamon Ding 	}
3586a552a69cSDamon Ding 
3587a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3588a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3589a552a69cSDamon Ding 		/*
3590a552a69cSDamon Ding 		 * RGB interface_pix_clk_sel will auto config according
3591a552a69cSDamon Ding 		 * to rgb_en/bt1120_en/bt656_en.
3592a552a69cSDamon Ding 		 */
3593a552a69cSDamon Ding 	} else if (output_if & VOP_OUTPUT_IF_eDP0) {
3594a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3595a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0;
3596a552a69cSDamon Ding 	} else {
3597a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3598a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0;
3599a552a69cSDamon Ding 	}
3600a552a69cSDamon Ding 
3601a552a69cSDamon Ding 	/* dclk_core */
3602a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3603a552a69cSDamon Ding 			RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false);
3604a552a69cSDamon Ding 	/* dclk_out */
3605a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3606a552a69cSDamon Ding 			RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false);
3607a552a69cSDamon Ding 
3608a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3609a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3610a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3611a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3612a552a69cSDamon Ding 
3613a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3614a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3615a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3616a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3617a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3618a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3619a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3620a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3621a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3622a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3623a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3624a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv);
3625a552a69cSDamon Ding 	}
3626a552a69cSDamon Ding 
3627a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3628a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3629a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3630a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3631a552a69cSDamon Ding 
3632a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3633a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3634a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3635a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3636a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3637a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3638a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3639a552a69cSDamon Ding 				RK3576_BT1120_OUT_EN_SHIFT, 1, false);
3640a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3641a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3642a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3643a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3644a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
3645a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3646a552a69cSDamon Ding 				RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false);
3647a552a69cSDamon Ding 	}
3648a552a69cSDamon Ding 
3649a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT656) {
3650a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3651a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3652a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3653a552a69cSDamon Ding 
3654a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3655a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3656a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3657a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3658a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3659a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3660a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3661a552a69cSDamon Ding 				RK3576_BT656_OUT_EN_SHIFT, 1, false);
3662a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3663a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3664a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3665a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3666a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
3667a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3668a552a69cSDamon Ding 				RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false);
3669a552a69cSDamon Ding 	}
3670a552a69cSDamon Ding 
3671a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3672a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3673a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3674a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
3675a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3676a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3677a552a69cSDamon Ding 
3678a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3679a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3680a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3681a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3682a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3683a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3684a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3685a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3686a552a69cSDamon Ding 		/*
3687a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3688a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
3689a552a69cSDamon Ding 		 */
3690a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
3691a552a69cSDamon Ding 			val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3692a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3693a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3694a552a69cSDamon Ding 
3695a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
3696a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3697a552a69cSDamon Ding 					RK3576_MIPI_CMD_MODE_SHIFT, 1, false);
3698a552a69cSDamon Ding 
3699a552a69cSDamon Ding 		if (conn_state->hold_mode) {
3700a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3701a552a69cSDamon Ding 					EDPI_TE_EN, !cstate->soft_te, false);
3702a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3703a552a69cSDamon Ding 					EDPI_WMS_HOLD_EN, 1, false);
3704a552a69cSDamon Ding 		}
3705a552a69cSDamon Ding 	}
3706a552a69cSDamon Ding 
3707a552a69cSDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
3708a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3709a552a69cSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
3710a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3711a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3712a552a69cSDamon Ding 					MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
3713a552a69cSDamon Ding 		switch (conn_state->type) {
3714a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DisplayPort:
3715a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3716a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3717a552a69cSDamon Ding 			break;
3718a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_eDP:
3719a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3720a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3721a552a69cSDamon Ding 			break;
3722a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_HDMIA:
3723a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3724a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3725a552a69cSDamon Ding 			break;
3726a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DSI:
3727a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
3728a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
3729a552a69cSDamon Ding 			break;
3730a552a69cSDamon Ding 		default:
3731a552a69cSDamon Ding 			break;
3732a552a69cSDamon Ding 		}
3733a552a69cSDamon Ding 	}
3734a552a69cSDamon Ding 
3735a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_eDP0) {
3736a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3737a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3738a552a69cSDamon Ding 		/* 0: dclk, 1: port0_dclk */
3739a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3740a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3741a552a69cSDamon Ding 
3742a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3743a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3744a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3745a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3746a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
3747a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3748a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3749a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3750a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3751a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3752a552a69cSDamon Ding 	}
3753a552a69cSDamon Ding 
3754a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
3755a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3756a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3757a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
3758a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3759a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3760a552a69cSDamon Ding 
3761a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3762a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3763a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3764a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3765a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
3766a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3767a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_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_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3770a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3771a552a69cSDamon Ding 	}
3772a552a69cSDamon Ding 
3773a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP0) {
3774a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3775a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3776a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3777a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3778a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3779a552a69cSDamon Ding 
3780a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3781a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3782a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
3783a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3784a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3785a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3786a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3787a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3788a552a69cSDamon Ding 	}
3789a552a69cSDamon Ding 
3790a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP1) {
3791a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3792a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3793a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3794a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3795a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3796a552a69cSDamon Ding 
3797a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
3798a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3799a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
3800a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3801a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3802a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3803a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3804a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3805a552a69cSDamon Ding 	}
3806a552a69cSDamon Ding 
3807a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP2) {
3808a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3809a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3810a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
3811a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
3812a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
3813a552a69cSDamon Ding 
3814a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
3815a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3816a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
3817a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3818a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3819a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3820a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3821a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3822a552a69cSDamon Ding 	}
3823a552a69cSDamon Ding 
3824a552a69cSDamon Ding 	return mode->crtc_clock;
3825a552a69cSDamon Ding }
3826a552a69cSDamon Ding 
3827a2a16809SChaoyi Chen static void rk3568_vop2_setup_dual_channel_if(struct display_state *state)
3828a2a16809SChaoyi Chen {
3829a2a16809SChaoyi Chen 	struct crtc_state *cstate = &state->crtc_state;
3830a2a16809SChaoyi Chen 	struct connector_state *conn_state = &state->conn_state;
3831a2a16809SChaoyi Chen 	struct vop2 *vop2 = cstate->private;
3832a2a16809SChaoyi Chen 	u32 vp_offset = (cstate->crtc_id * 0x100);
3833a2a16809SChaoyi Chen 
3834a2a16809SChaoyi Chen 	if (conn_state->output_flags &
3835a2a16809SChaoyi Chen 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) {
3836a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3837a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
3838a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3839a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false);
3840a2a16809SChaoyi Chen 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3841a2a16809SChaoyi Chen 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3842a2a16809SChaoyi Chen 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
3843a2a16809SChaoyi Chen 
3844a2a16809SChaoyi Chen 		return;
3845a2a16809SChaoyi Chen 	}
3846a2a16809SChaoyi Chen 
3847a2a16809SChaoyi Chen 	vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3848a2a16809SChaoyi Chen 			MIPI_DUAL_EN_SHIFT, 1, false);
3849a2a16809SChaoyi Chen 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) {
3850a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3851a2a16809SChaoyi Chen 				MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
3852a2a16809SChaoyi Chen 	}
3853a2a16809SChaoyi Chen 
3854a2a16809SChaoyi Chen 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
3855a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3856a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
3857a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3858a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false);
3859a2a16809SChaoyi Chen 	}
3860a2a16809SChaoyi Chen }
3861a2a16809SChaoyi Chen 
3862ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
3863ecc31b6eSAndy Yan {
3864ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3865ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3866ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
3867ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
3868d0408543SAndy Yan 	bool dclk_inv;
3869ecc31b6eSAndy Yan 	u32 val;
38708895aec1SSandy Huang 
387113f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
387210ee9f5bSAlgea Cao 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
387310ee9f5bSAlgea Cao 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3874d0408543SAndy Yan 
3875d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3876d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3877d0408543SAndy Yan 				1, false);
3878d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3879d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
388015f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
388115f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3882ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
3883c55d261eSSandy Huang 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
3884d0408543SAndy Yan 	}
3885d0408543SAndy Yan 
3886d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
388752ee18acSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
388852ee18acSSandy Huang 				1, false);
3889d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
3890d0408543SAndy Yan 				BT1120_EN_SHIFT, 1, false);
3891d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3892d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3893ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
389452ee18acSSandy Huang 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
3895d0408543SAndy Yan 	}
3896d0408543SAndy Yan 
3897d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
3898d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
3899d0408543SAndy Yan 				1, false);
3900d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3901d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3902ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
390352ee18acSSandy Huang 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
3904d0408543SAndy Yan 	}
3905d0408543SAndy Yan 
3906d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
3907d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
3908d0408543SAndy Yan 				1, false);
3909d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3910d0408543SAndy Yan 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
391115f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
391215f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
391311f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
391415f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3915d0408543SAndy Yan 	}
3916d0408543SAndy Yan 
3917d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
3918d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
3919d0408543SAndy Yan 				1, false);
3920d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3921d0408543SAndy Yan 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
392215f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
392315f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
392411f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
392515f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3926d0408543SAndy Yan 	}
3927d0408543SAndy Yan 
3928d0408543SAndy Yan 
3929d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
3930d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
3931d0408543SAndy Yan 				1, false);
3932d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3933d0408543SAndy Yan 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
3934d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3935c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3936de022775SGuochun Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
3937de022775SGuochun Huang 				IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
3938d0408543SAndy Yan 	}
3939d0408543SAndy Yan 
3940d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
3941d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
3942d0408543SAndy Yan 				1, false);
3943d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3944d0408543SAndy Yan 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
3945d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3946c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3947de022775SGuochun Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
3948de022775SGuochun Huang 				IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
3949d0408543SAndy Yan 	}
3950d0408543SAndy Yan 
3951d0408543SAndy Yan 	if (conn_state->output_flags &
3952a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
3953a2a16809SChaoyi Chen 	    conn_state->output_flags &
3954a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)
3955a2a16809SChaoyi Chen 		rk3568_vop2_setup_dual_channel_if(state);
3956d0408543SAndy Yan 
3957d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
3958d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
3959d0408543SAndy Yan 				1, false);
3960d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3961d0408543SAndy Yan 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
3962c55d261eSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3963c55d261eSSandy Huang 				IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
39647bcdc6eeSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK,
39657bcdc6eeSDamon Ding 				IF_CTRL_EDP_PIN_POL_SHIFT, val, false);
3966d0408543SAndy Yan 	}
3967d0408543SAndy Yan 
3968d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
3969d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
3970d0408543SAndy Yan 				1, false);
3971d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3972d0408543SAndy Yan 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
397310ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
397410ee9f5bSAlgea Cao 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
397510ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
397610ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_MASK,
397710ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
3978d0408543SAndy Yan 	}
397910ee9f5bSAlgea Cao 
3980823146b6SDamon Ding 	return mode->crtc_clock;
3981ecc31b6eSAndy Yan }
3982ecc31b6eSAndy Yan 
3983452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state)
3984452afb13SDamon Ding {
3985452afb13SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3986452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3987452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3988452afb13SDamon Ding 	struct vop2 *vop2 = cstate->private;
3989452afb13SDamon Ding 	bool dclk_inv;
3990606f72bdSDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
3991452afb13SDamon Ding 	u32 val;
3992452afb13SDamon Ding 
399313f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3994452afb13SDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3995452afb13SDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3996452afb13SDamon Ding 
3997452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3998452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3999452afb13SDamon Ding 				1, false);
4000452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4001452afb13SDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
4002452afb13SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK,
4003452afb13SDamon Ding 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
4004452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
400515f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4006452afb13SDamon Ding 	}
4007452afb13SDamon Ding 
4008452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
4009452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
4010452afb13SDamon Ding 				1, false);
4011452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4012452afb13SDamon Ding 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
4013452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
401415f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4015452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
401615f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4017452afb13SDamon Ding 	}
4018452afb13SDamon Ding 
4019452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
4020452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
4021452afb13SDamon Ding 				1, false);
4022452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4023452afb13SDamon Ding 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
4024452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4025452afb13SDamon Ding 				RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false);
4026452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
4027452afb13SDamon Ding 				RK3562_MIPI_PIN_POL_SHIFT, val, false);
4028606f72bdSDamon Ding 
4029606f72bdSDamon Ding 		if (conn_state->hold_mode) {
4030606f72bdSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4031606f72bdSDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
4032606f72bdSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4033606f72bdSDamon Ding 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
4034606f72bdSDamon Ding 		}
4035452afb13SDamon Ding 	}
4036452afb13SDamon Ding 
4037452afb13SDamon Ding 	return mode->crtc_clock;
4038452afb13SDamon Ding }
4039452afb13SDamon Ding 
4040a552a69cSDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state)
4041a552a69cSDamon Ding {
4042a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
4043a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
4044a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
4045a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
4046a552a69cSDamon Ding 	u32 val;
4047a552a69cSDamon Ding 
4048a552a69cSDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4049a552a69cSDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4050a552a69cSDamon Ding 
4051a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4052a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4053a552a69cSDamon Ding 				1, false);
4054a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4055a552a69cSDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
4056a552a69cSDamon Ding 	}
4057a552a69cSDamon Ding 
4058a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4059a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4060a552a69cSDamon Ding 				1, false);
4061a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4062a552a69cSDamon Ding 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
4063a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4064a552a69cSDamon Ding 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
4065a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
4066a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_MASK,
4067a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4068a552a69cSDamon Ding 	}
4069a552a69cSDamon Ding 
4070a552a69cSDamon Ding 	return mode->crtc_clock;
4071a552a69cSDamon Ding }
4072a552a69cSDamon Ding 
407365747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state)
407465747de7SDamon Ding {
407565747de7SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
407665747de7SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
407765747de7SDamon Ding 	struct vop2 *vop2 = cstate->private;
407865747de7SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
407965747de7SDamon Ding 	u32 output_type = conn_state->type;
408065747de7SDamon Ding 	u32 data_swap = 0;
408165747de7SDamon Ding 
4082c8820b76SDamon Ding 	if (is_uv_swap(state) || is_rb_swap(state))
408365747de7SDamon Ding 		data_swap = DSP_RB_SWAP;
408465747de7SDamon Ding 
4085a552a69cSDamon Ding 	if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) {
4086a552a69cSDamon Ding 		if ((output_type == DRM_MODE_CONNECTOR_HDMIA ||
4087e6e4c154SDamon Ding 		     output_type == DRM_MODE_CONNECTOR_DisplayPort) &&
408865747de7SDamon Ding 		    (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
408965747de7SDamon Ding 		     conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
409065747de7SDamon Ding 		data_swap |= DSP_RG_SWAP;
4091a552a69cSDamon Ding 	}
409265747de7SDamon Ding 
409365747de7SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
409465747de7SDamon Ding 			DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false);
409565747de7SDamon Ding }
409665747de7SDamon Ding 
4097b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
4098b890760eSAlgea Cao {
4099b890760eSAlgea Cao 	int ret = 0;
4100b890760eSAlgea Cao 
4101b890760eSAlgea Cao 	if (parent->dev)
4102b890760eSAlgea Cao 		ret = clk_set_parent(clk, parent);
4103b890760eSAlgea Cao 	if (ret < 0)
4104b890760eSAlgea Cao 		debug("failed to set %s as parent for %s\n",
4105b890760eSAlgea Cao 		      parent->dev->name, clk->dev->name);
4106b890760eSAlgea Cao }
4107b890760eSAlgea Cao 
4108b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate)
4109b890760eSAlgea Cao {
4110b890760eSAlgea Cao 	int ret = 0;
4111b890760eSAlgea Cao 
4112b890760eSAlgea Cao 	if (clk->dev)
4113b890760eSAlgea Cao 		ret = clk_set_rate(clk, rate);
4114b890760eSAlgea Cao 	if (ret < 0)
4115b890760eSAlgea Cao 		debug("failed to set %s rate %lu \n", clk->dev->name, rate);
4116b890760eSAlgea Cao 
4117b890760eSAlgea Cao 	return ret;
4118b890760eSAlgea Cao }
4119b890760eSAlgea Cao 
412012ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state,
412112ee5af0SDamon Ding 				  int *dsc_txp_clk_div, int *dsc_pxl_clk_div,
412212ee5af0SDamon Ding 				  int *dsc_cds_clk_div, u64 dclk_rate)
412312ee5af0SDamon Ding {
412412ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
412512ee5af0SDamon Ding 
412612ee5af0SDamon Ding 	*dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate;
412712ee5af0SDamon Ding 	*dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate;
412812ee5af0SDamon Ding 	*dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate;
412912ee5af0SDamon Ding 
413012ee5af0SDamon Ding 	*dsc_txp_clk_div = ilog2(*dsc_txp_clk_div);
413112ee5af0SDamon Ding 	*dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div);
413212ee5af0SDamon Ding 	*dsc_cds_clk_div = ilog2(*dsc_cds_clk_div);
413312ee5af0SDamon Ding }
413412ee5af0SDamon Ding 
413512ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id)
413612ee5af0SDamon Ding {
413712ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
413812ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set *pps = &cstate->pps;
413912ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set config_pps;
414012ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
414112ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
414212ee5af0SDamon Ding 	u32 *pps_val = (u32 *)&config_pps;
414312ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
414412ee5af0SDamon Ding 	int i = 0;
414512ee5af0SDamon Ding 
414612ee5af0SDamon Ding 	memcpy(&config_pps, pps, sizeof(config_pps));
414712ee5af0SDamon Ding 
414812ee5af0SDamon Ding 	if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) {
414912ee5af0SDamon Ding 		config_pps.pps_3 &= 0xf0;
415012ee5af0SDamon Ding 		config_pps.pps_3 |= dsc_data->max_linebuf_depth;
415112ee5af0SDamon Ding 		printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
415212ee5af0SDamon Ding 		       dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf);
415312ee5af0SDamon Ding 	}
415412ee5af0SDamon Ding 
415512ee5af0SDamon Ding 	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
415612ee5af0SDamon Ding 		config_pps.rc_range_parameters[i] =
415712ee5af0SDamon Ding 			(pps->rc_range_parameters[i] >> 3 & 0x1f) |
415812ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
415912ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
416012ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
416112ee5af0SDamon Ding 	}
416212ee5af0SDamon Ding 
416312ee5af0SDamon Ding 	for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
416412ee5af0SDamon Ding 		vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++);
416512ee5af0SDamon Ding }
416612ee5af0SDamon Ding 
416712ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate)
416812ee5af0SDamon Ding {
416912ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
417012ee5af0SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
417112ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
417212ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
417312ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
417412ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
417512ee5af0SDamon Ding 	bool mipi_ds_mode = false;
417612ee5af0SDamon Ding 	u8 dsc_interface_mode = 0;
417712ee5af0SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
417812ee5af0SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
417912ee5af0SDamon Ding 	u16 htotal = mode->crtc_htotal;
418012ee5af0SDamon Ding 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
418112ee5af0SDamon Ding 	u16 vdisplay = mode->crtc_vdisplay;
418212ee5af0SDamon Ding 	u16 vtotal = mode->crtc_vtotal;
418312ee5af0SDamon Ding 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
418412ee5af0SDamon Ding 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
418512ee5af0SDamon Ding 	u16 vact_end = vact_st + vdisplay;
418612ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
418712ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
418812ee5af0SDamon Ding 	int dsc_txp_clk_div = 0;
418912ee5af0SDamon Ding 	int dsc_pxl_clk_div = 0;
419012ee5af0SDamon Ding 	int dsc_cds_clk_div = 0;
4191baf2c414SDamon Ding 	int val = 0;
419212ee5af0SDamon Ding 
419312ee5af0SDamon Ding 	if (!vop2->data->nr_dscs) {
419412ee5af0SDamon Ding 		printf("Unsupported DSC\n");
419512ee5af0SDamon Ding 		return;
419612ee5af0SDamon Ding 	}
419712ee5af0SDamon Ding 
419812ee5af0SDamon Ding 	if (cstate->dsc_slice_num > dsc_data->max_slice_num)
419912ee5af0SDamon Ding 		printf("DSC%d supported max slice is: %d, current is: %d\n",
420012ee5af0SDamon Ding 		       dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num);
420112ee5af0SDamon Ding 
420212ee5af0SDamon Ding 	if (dsc_data->pd_id) {
420312ee5af0SDamon Ding 		if (vop2_power_domain_on(vop2, dsc_data->pd_id))
420412ee5af0SDamon Ding 			printf("open dsc%d pd fail\n", dsc_id);
420512ee5af0SDamon Ding 	}
420612ee5af0SDamon Ding 
420712ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK,
420812ee5af0SDamon Ding 			SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false);
420912ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK,
421012ee5af0SDamon Ding 			DSC_PORT_SEL_SHIFT, cstate->crtc_id, false);
421112ee5af0SDamon Ding 	if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
421212ee5af0SDamon Ding 		dsc_interface_mode = VOP_DSC_IF_HDMI;
421312ee5af0SDamon Ding 	} else {
421412ee5af0SDamon Ding 		mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
421512ee5af0SDamon Ding 		if (mipi_ds_mode)
421612ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
421712ee5af0SDamon Ding 		else
421812ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
421912ee5af0SDamon Ding 	}
422012ee5af0SDamon Ding 
422112ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
422212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
422312ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 0, false);
422412ee5af0SDamon Ding 	else
422512ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
422612ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 1, false);
422712ee5af0SDamon Ding 
422812ee5af0SDamon Ding 	vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate);
422912ee5af0SDamon Ding 
423012ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK,
423112ee5af0SDamon Ding 			DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false);
423212ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK,
423312ee5af0SDamon Ding 			DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false);
423412ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK,
423512ee5af0SDamon Ding 			DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false);
423612ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK,
423712ee5af0SDamon Ding 			DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false);
423812ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
423912ee5af0SDamon Ding 			DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false);
424012ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK,
424112ee5af0SDamon Ding 			DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false);
424212ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
424312ee5af0SDamon Ding 			DSC_HALT_EN_SHIFT, mipi_ds_mode, false);
424412ee5af0SDamon Ding 
424512ee5af0SDamon Ding 	if (!mipi_ds_mode) {
424612ee5af0SDamon Ding 		u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
424712ee5af0SDamon Ding 		u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
424812ee5af0SDamon Ding 		u64 dsc_cds_rate = cstate->dsc_cds_clk_rate;
424912ee5af0SDamon Ding 		u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */
425012ee5af0SDamon Ding 		u32 dly_num, dsc_cds_rate_mhz, val = 0;
4251b61227a3SDamon Ding 		int k = 1;
4252b61227a3SDamon Ding 
4253b61227a3SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
4254b61227a3SDamon Ding 			k = 2;
425512ee5af0SDamon Ding 
425612ee5af0SDamon Ding 		if (target_bpp >> 4 < dsc_data->min_bits_per_pixel)
425712ee5af0SDamon Ding 			printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel);
425812ee5af0SDamon Ding 
425912ee5af0SDamon Ding 		/*
426012ee5af0SDamon Ding 		 * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
426112ee5af0SDamon Ding 		 * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
426212ee5af0SDamon Ding 		 * T (dsc_cds) = 1 / dsc_cds_rate_mhz
42631ace1b6dSDamon Ding 		 *
42641ace1b6dSDamon Ding 		 * HDMI:
426512ee5af0SDamon Ding 		 * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
426612ee5af0SDamon Ding 		 *                 delay_line_num = 4 - BPP / 8
426712ee5af0SDamon Ding 		 *                                = (64 - target_bpp / 8) / 16
426812ee5af0SDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
42691ace1b6dSDamon Ding 		 *
42701ace1b6dSDamon Ding 		 * MIPI DSI[4320 and 9216 is buffer size for DSC]:
42711ace1b6dSDamon Ding 		 * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
42721ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
42731ace1b6dSDamon Ding 		 * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
42741ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
42751ace1b6dSDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
427612ee5af0SDamon Ding 		 */
427712ee5af0SDamon Ding 		do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
427812ee5af0SDamon Ding 		dsc_cds_rate_mhz = dsc_cds_rate;
42791ace1b6dSDamon Ding 		dsc_hsync = hsync_len / 2;
42801ace1b6dSDamon Ding 		if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
428112ee5af0SDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
42821ace1b6dSDamon Ding 		} else {
42831ace1b6dSDamon Ding 			int dsc_buf_size  = dsc_id == 0 ? 4320 * 8 : 9216 * 2;
42841ace1b6dSDamon Ding 			int delay_line_num = dsc_buf_size / cstate->dsc_slice_num /
42851ace1b6dSDamon Ding 					     be16_to_cpu(cstate->pps.chunk_size);
42861ace1b6dSDamon Ding 
42871ace1b6dSDamon Ding 			delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
42881ace1b6dSDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
42891ace1b6dSDamon Ding 
42901ace1b6dSDamon Ding 			/* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
42911ace1b6dSDamon Ding 			if (dsc_hsync < 8)
42921ace1b6dSDamon Ding 				dsc_hsync = 8;
42931ace1b6dSDamon Ding 		}
429412ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK,
429512ee5af0SDamon Ding 				DSC_INIT_DLY_MODE_SHIFT, 0, false);
429612ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK,
429712ee5af0SDamon Ding 				DSC_INIT_DLY_NUM_SHIFT, dly_num, false);
429812ee5af0SDamon Ding 
4299b61227a3SDamon Ding 		/*
4300b61227a3SDamon Ding 		 * htotal / dclk_core = dsc_htotal /cds_clk
4301b61227a3SDamon Ding 		 *
4302b61227a3SDamon Ding 		 * dclk_core = DCLK / (1 << dclk_core->div_val)
4303b61227a3SDamon Ding 		 * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
4304b61227a3SDamon Ding 		 * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
4305b61227a3SDamon Ding 		 *
4306b61227a3SDamon Ding 		 * dsc_htotal = htotal * (1 << dclk_core->div_val) /
4307b61227a3SDamon Ding 		 *              ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
4308b61227a3SDamon Ding 		 */
4309b61227a3SDamon Ding 		dsc_htotal = htotal * (1 << cstate->dclk_core_div) /
4310b61227a3SDamon Ding 			     ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div));
431112ee5af0SDamon Ding 		val = dsc_htotal << 16 | dsc_hsync;
431212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK,
431312ee5af0SDamon Ding 				DSC_HTOTAL_PW_SHIFT, val, false);
431412ee5af0SDamon Ding 
431512ee5af0SDamon Ding 		dsc_hact_st = hact_st / 2;
4316b61227a3SDamon Ding 		dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
431712ee5af0SDamon Ding 		val = dsc_hact_end << 16 | dsc_hact_st;
431812ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK,
431912ee5af0SDamon Ding 				DSC_HACT_ST_END_SHIFT, val, false);
432012ee5af0SDamon Ding 
432112ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK,
432212ee5af0SDamon Ding 				DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false);
432312ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK,
432412ee5af0SDamon Ding 				DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false);
432512ee5af0SDamon Ding 	}
432612ee5af0SDamon Ding 
432712ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK,
432812ee5af0SDamon Ding 			RST_DEASSERT_SHIFT, 1, false);
432912ee5af0SDamon Ding 	udelay(10);
433012ee5af0SDamon Ding 
4331baf2c414SDamon Ding 	val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) |
4332baf2c414SDamon Ding 	       ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT);
4333baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
4334baf2c414SDamon Ding 
433512ee5af0SDamon Ding 	vop2_load_pps(state, vop2, dsc_id);
433612ee5af0SDamon Ding 
4337baf2c414SDamon Ding 	val |= (1 << DSC_PPS_UPD_SHIFT);
4338baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
433912ee5af0SDamon Ding 
434012ee5af0SDamon Ding 	printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
434112ee5af0SDamon Ding 	       dsc_id,
434212ee5af0SDamon Ding 	       cstate->dsc_txp_clk_rate, dsc_txp_clk_div,
434312ee5af0SDamon Ding 	       cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div,
434412ee5af0SDamon Ding 	       cstate->dsc_cds_clk_rate, dsc_cds_clk_div);
434512ee5af0SDamon Ding }
434612ee5af0SDamon Ding 
43475f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev)
43485f1357a2SZhang Yubing {
43495f1357a2SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
43505f1357a2SZhang Yubing 	struct vop2 *vop2 = cstate->private;
43515f1357a2SZhang Yubing 	struct udevice *vp_dev, *dev;
43525f1357a2SZhang Yubing 	struct ofnode_phandle_args args;
43535f1357a2SZhang Yubing 	char vp_name[10];
43545f1357a2SZhang Yubing 	int ret;
43555f1357a2SZhang Yubing 
4356a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576)
43575f1357a2SZhang Yubing 		return false;
43585f1357a2SZhang Yubing 
43595f1357a2SZhang Yubing 	sprintf(vp_name, "port@%d", cstate->crtc_id);
43605f1357a2SZhang Yubing 	if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) {
43615e85f4a7SZhang Yubing 		debug("warn: can't get vp device\n");
43625f1357a2SZhang Yubing 		return false;
43635f1357a2SZhang Yubing 	}
43645f1357a2SZhang Yubing 
43655f1357a2SZhang Yubing 	ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0,
43665f1357a2SZhang Yubing 					 0, &args);
43675f1357a2SZhang Yubing 	if (ret) {
43685e85f4a7SZhang Yubing 		debug("assigned-clock-parents's node not define\n");
43695f1357a2SZhang Yubing 		return false;
43705f1357a2SZhang Yubing 	}
43715f1357a2SZhang Yubing 
43725f1357a2SZhang Yubing 	if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) {
43735e85f4a7SZhang Yubing 		debug("warn: can't get clk device\n");
43745f1357a2SZhang Yubing 		return false;
43755f1357a2SZhang Yubing 	}
43765f1357a2SZhang Yubing 
43775f1357a2SZhang Yubing 	if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) {
43785f1357a2SZhang Yubing 		printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name);
43795f1357a2SZhang Yubing 		if (clk_dev)
43805f1357a2SZhang Yubing 			*clk_dev = dev;
43815f1357a2SZhang Yubing 		return true;
43825f1357a2SZhang Yubing 	}
43835f1357a2SZhang Yubing 
43845f1357a2SZhang Yubing 	return false;
43855f1357a2SZhang Yubing }
43865f1357a2SZhang Yubing 
43870675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state)
43880675a2a4SDamon Ding {
43890675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
43900675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
43910675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
43920675a2a4SDamon Ding 
43930675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
43940675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
43950675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
43960675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
43970675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
43980675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false);
43990675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
44000675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false);
44010675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
44020675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false);
44030675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
44040675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false);
44050675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
44060675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false);
44070675a2a4SDamon Ding }
44080675a2a4SDamon Ding 
44090675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state)
44100675a2a4SDamon Ding {
44110675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
44120675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
44130675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
44140675a2a4SDamon Ding 
44150675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44160675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
44170675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44180675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
44190675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
44200675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, 53, false);
44210675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
44220675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, 6, false);
44230675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
44240675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, 48, false);
44250675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
44260675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, 12, false);
44270675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
44280675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, 30, false);
44290675a2a4SDamon Ding }
44300675a2a4SDamon Ding 
44310675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value)
44320675a2a4SDamon Ding {
44330675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
44340675a2a4SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
44350675a2a4SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
44360675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
44370675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
44380675a2a4SDamon Ding 
44390675a2a4SDamon Ding 	/*
444058cf1fa3SDamon Ding 	 * 1.set mcu bypass mode timing.
444158cf1fa3SDamon Ding 	 * 2.set dclk rate to 150M.
44420675a2a4SDamon Ding 	 */
44430675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && value) {
44440675a2a4SDamon Ding 		vop3_mcu_bypass_mode_setup(state);
44450675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, 150000000);
44460675a2a4SDamon Ding 	}
44470675a2a4SDamon Ding 
44480675a2a4SDamon Ding 	switch (type) {
44490675a2a4SDamon Ding 	case MCU_WRCMD:
44500675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44510675a2a4SDamon Ding 				MCU_RS_SHIFT, 0, false);
44520675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
44530675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
44540675a2a4SDamon Ding 				value, false);
44550675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44560675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
44570675a2a4SDamon Ding 		break;
44580675a2a4SDamon Ding 	case MCU_WRDATA:
44590675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44600675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
44610675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
44620675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
44630675a2a4SDamon Ding 				value, false);
44640675a2a4SDamon Ding 		break;
44650675a2a4SDamon Ding 	case MCU_SETBYPASS:
44660675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
44670675a2a4SDamon Ding 				MCU_BYPASS_SHIFT, value ? 1 : 0, false);
44680675a2a4SDamon Ding 		break;
44690675a2a4SDamon Ding 	default:
44700675a2a4SDamon Ding 		break;
44710675a2a4SDamon Ding 	}
44720675a2a4SDamon Ding 
44730675a2a4SDamon Ding 	/*
447458cf1fa3SDamon Ding 	 * 1.restore mcu data mode timing.
447558cf1fa3SDamon Ding 	 * 2.restore dclk rate to crtc_clock.
44760675a2a4SDamon Ding 	 */
44770675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && !value) {
44780675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
44790675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000);
44800675a2a4SDamon Ding 	}
44810675a2a4SDamon Ding 
44820675a2a4SDamon Ding 	return 0;
44830675a2a4SDamon Ding }
44840675a2a4SDamon Ding 
448534d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id)
448634d37ef0SDamon Ding {
4487a552a69cSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
4488a552a69cSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id];
448934d37ef0SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
449034d37ef0SDamon Ding 	bool pre_dither_down_en = false;
449134d37ef0SDamon Ding 
449234d37ef0SDamon Ding 	switch (bus_format) {
449334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB565_1X16:
449440608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
4495e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4496e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4497e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4498e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false);
449934d37ef0SDamon Ding 		pre_dither_down_en = true;
450034d37ef0SDamon Ding 		break;
450134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X18:
450234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
450334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
450440608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB666_3X6:
4505e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4506e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4507e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4508e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false);
450934d37ef0SDamon Ding 		pre_dither_down_en = true;
451034d37ef0SDamon Ding 		break;
451134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
451234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV8_1X24:
451334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
4514e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4515e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
451634d37ef0SDamon Ding 		pre_dither_down_en = true;
451734d37ef0SDamon Ding 		break;
451834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV10_1X20:
451934d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV10_1X30:
452034d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
452134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB101010_1X30:
4522e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4523e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
452434d37ef0SDamon Ding 		pre_dither_down_en = false;
452534d37ef0SDamon Ding 		break;
452634d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_3X8:
452734d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
452834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X24:
452934d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
453034d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
453134d37ef0SDamon Ding 	default:
4532e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4533e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
453434d37ef0SDamon Ding 		pre_dither_down_en = true;
453534d37ef0SDamon Ding 		break;
453634d37ef0SDamon Ding 	}
453734d37ef0SDamon Ding 
4538e2bdb3b3SDamon Ding 	if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0)
453934d37ef0SDamon Ding 		pre_dither_down_en = false;
454034d37ef0SDamon Ding 
4541a552a69cSDamon Ding 	if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) {
4542481ef52dSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
4543481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000);
4544481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100);
4545481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100);
4546481ef52dSDamon Ding 		}
4547481ef52dSDamon Ding 
4548a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4549a552a69cSDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, 0, false);
4550e2bdb3b3SDamon Ding 		/* enable frc2.0 do 10->8 */
4551a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4552a552a69cSDamon Ding 				DITHER_DOWN_EN_SHIFT, 1, false);
4553e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4554e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false);
4555a552a69cSDamon Ding 	} else {
455634d37ef0SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
455734d37ef0SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
4558e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4559e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false);
456034d37ef0SDamon Ding 	}
4561a552a69cSDamon Ding }
456234d37ef0SDamon Ding 
4563ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state)
4564ecc31b6eSAndy Yan {
4565ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
4566c2b1fe35SDamon Ding 	struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
4567ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
4568ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
4569ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
4570ecc31b6eSAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
4571ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
4572ecc31b6eSAndy Yan 	u16 htotal = mode->crtc_htotal;
4573ecc31b6eSAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
4574ecc31b6eSAndy Yan 	u16 hact_end = hact_st + hdisplay;
4575ecc31b6eSAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
4576ecc31b6eSAndy Yan 	u16 vtotal = mode->crtc_vtotal;
4577ecc31b6eSAndy Yan 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
4578ecc31b6eSAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
4579ecc31b6eSAndy Yan 	u16 vact_end = vact_st + vdisplay;
4580ecc31b6eSAndy Yan 	bool yuv_overlay = false;
4581ecc31b6eSAndy Yan 	u32 vp_offset = (cstate->crtc_id * 0x100);
458266724b9cSDamon Ding 	u32 line_flag_offset = (cstate->crtc_id * 4);
458366724b9cSDamon Ding 	u32 val, act_end;
458458cf1fa3SDamon Ding 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4585edfef528SDamon Ding 	u8 dclk_div_factor = 0;
4586a552a69cSDamon Ding 	u8 vp_dclk_div = 1;
4587ecc31b6eSAndy Yan 	char output_type_name[30] = {0};
4588d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4589ecc31b6eSAndy Yan 	char dclk_name[9];
4590d8e7f4a5SSandy Huang #endif
4591b890760eSAlgea Cao 	struct clk hdmi0_phy_pll;
4592b890760eSAlgea Cao 	struct clk hdmi1_phy_pll;
45935f1357a2SZhang Yubing 	struct clk hdmi_phy_pll;
45943e05a7b8SZhang Yubing 	struct udevice *disp_dev;
45955fa6e665SDamon Ding 	unsigned long dclk_rate = 0;
4596ecc31b6eSAndy Yan 	int ret;
4597ecc31b6eSAndy Yan 
4598ecc31b6eSAndy Yan 	printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
459971ac76f7SDamon Ding 	       mode->crtc_hdisplay, mode->vdisplay,
4600ecc31b6eSAndy Yan 	       mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
46014d64cedbSDamon Ding 	       mode->vrefresh,
46022264c88bSDamon Ding 	       rockchip_get_output_if_name(conn_state->output_if, output_type_name),
4603ecc31b6eSAndy Yan 	       cstate->crtc_id);
4604ecc31b6eSAndy Yan 
4605ee01dbb2SDamon Ding 	if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
4606ee01dbb2SDamon Ding 		cstate->splice_mode = true;
4607ee01dbb2SDamon Ding 		cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id;
4608ee01dbb2SDamon Ding 		if (!cstate->splice_crtc_id) {
4609ee01dbb2SDamon Ding 			printf("%s: Splice mode is unsupported by vp%d\n",
4610ee01dbb2SDamon Ding 			       __func__, cstate->crtc_id);
4611ee01dbb2SDamon Ding 			return -EINVAL;
4612ee01dbb2SDamon Ding 		}
4613b70b2d79SDamon Ding 
4614b70b2d79SDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK,
4615b70b2d79SDamon Ding 				PORT_MERGE_EN_SHIFT, 1, false);
4616ee01dbb2SDamon Ding 	}
4617ee01dbb2SDamon Ding 
4618cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4619cd6c85a9SDamon Ding 			RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4620cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4621cd6c85a9SDamon Ding 			RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4622cd6c85a9SDamon Ding 
462344b1b62cSDamon Ding 	if (vop2->data->vp_data[cstate->crtc_id].urgency) {
462444b1b62cSDamon Ding 		u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl;
462544b1b62cSDamon Ding 		u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh;
462644b1b62cSDamon Ding 
462744b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK,
462844b1b62cSDamon Ding 				AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
462944b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK,
463044b1b62cSDamon Ding 				AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
463144b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK,
463244b1b62cSDamon Ding 				POST_URGENCY_EN_SHIFT, 1, false);
463344b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK,
463444b1b62cSDamon Ding 				POST_URGENCY_THL_SHIFT, urgen_thl, false);
463544b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK,
463644b1b62cSDamon Ding 				POST_URGENCY_THH_SHIFT, urgen_thh, false);
463744b1b62cSDamon Ding 	}
463844b1b62cSDamon Ding 
4639ecc31b6eSAndy Yan 	vop2_initial(vop2, state);
4640ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3588)
4641ecc31b6eSAndy Yan 		dclk_rate = rk3588_vop2_if_cfg(state);
4642a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3576)
4643a552a69cSDamon Ding 		dclk_rate = rk3576_vop2_if_cfg(state);
46445fa6e665SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3568)
4645ecc31b6eSAndy Yan 		dclk_rate = rk3568_vop2_if_cfg(state);
4646452afb13SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3562)
4647452afb13SDamon Ding 		dclk_rate = rk3562_vop2_if_cfg(state);
4648a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3528)
4649a552a69cSDamon Ding 		dclk_rate = rk3528_vop2_if_cfg(state);
4650ecc31b6eSAndy Yan 
46515d2768f7SDamon Ding 	if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
46525d2768f7SDamon Ding 	     !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
46535d2768f7SDamon Ding 	    conn_state->output_if & VOP_OUTPUT_IF_BT656)
46547bdd0eb6SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
46557bdd0eb6SSandy Huang 
4656bf7c1abfSDamon Ding 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
4657bf7c1abfSDamon Ding 		if (vop2->version == VOP_VERSION_RK3588 &&
4658bf7c1abfSDamon Ding 		    conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
4659bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420;
4660bf7c1abfSDamon Ding 	} else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) {
4661bf7c1abfSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 &&
4662bf7c1abfSDamon Ding 		    conn_state->type == DRM_MODE_CONNECTOR_eDP)
4663bf7c1abfSDamon Ding 			conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422;
4664bf7c1abfSDamon Ding 		else if (vop2->version == VOP_VERSION_RK3588 &&
4665bf7c1abfSDamon Ding 			 conn_state->type == DRM_MODE_CONNECTOR_eDP)
4666bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422;
4667bf7c1abfSDamon Ding 		else if (vop2->version == VOP_VERSION_RK3576 &&
4668bf7c1abfSDamon Ding 			 conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
4669bf7c1abfSDamon Ding 			conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422;
4670bf7c1abfSDamon Ding 		else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
4671bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422;
4672bf7c1abfSDamon Ding 	}
4673bf7c1abfSDamon Ding 
467465747de7SDamon Ding 	vop2_post_color_swap(state);
467510ee9f5bSAlgea Cao 
4676d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
4677d0408543SAndy Yan 			OUT_MODE_SHIFT, conn_state->output_mode, false);
4678d0408543SAndy Yan 
467934d37ef0SDamon Ding 	vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id);
468034d37ef0SDamon Ding 	if (cstate->splice_mode)
468134d37ef0SDamon Ding 		vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id);
4682d0408543SAndy Yan 
4683d0408543SAndy Yan 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
4684d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
4685d0408543SAndy Yan 			yuv_overlay, false);
4686d0408543SAndy Yan 
4687d0408543SAndy Yan 	cstate->yuv_overlay = yuv_overlay;
4688d0408543SAndy Yan 
4689d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
4690d0408543SAndy Yan 		    (htotal << 16) | hsync_len);
4691d0408543SAndy Yan 	val = hact_st << 16;
4692d0408543SAndy Yan 	val |= hact_end;
4693d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
4694d0408543SAndy Yan 	val = vact_st << 16;
4695d0408543SAndy Yan 	val |= vact_end;
4696d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
4697d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
4698d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
4699d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
4700d0408543SAndy Yan 
4701d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
4702d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
4703d0408543SAndy Yan 			    val);
4704d0408543SAndy Yan 
4705d0408543SAndy Yan 		val = vtotal << 16 | (vtotal + vsync_len);
4706d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
4707d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4708d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 1, false);
4709d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
47107a20be36SSandy Huang 				DSP_FILED_POL, 1, false);
47117a20be36SSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4712d0408543SAndy Yan 				P2I_EN_SHIFT, 1, false);
4713d0408543SAndy Yan 		vtotal += vtotal + 1;
471466724b9cSDamon Ding 		act_end = vact_end_f1;
4715d0408543SAndy Yan 	} else {
4716d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4717d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 0, false);
4718d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4719d0408543SAndy Yan 				P2I_EN_SHIFT, 0, false);
472066724b9cSDamon Ding 		act_end = vact_end;
4721d0408543SAndy Yan 	}
4722d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
4723d0408543SAndy Yan 		    (vtotal << 16) | vsync_len);
472467be2ffcSDamon Ding 
4725a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 ||
4726a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3562 ||
4727a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3568) {
472867be2ffcSDamon Ding 		if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
472967be2ffcSDamon Ding 		conn_state->output_if & VOP_OUTPUT_IF_BT656)
4730d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
473167be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 1, false);
473267be2ffcSDamon Ding 		else
473367be2ffcSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
473467be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 0, false);
473510ee9f5bSAlgea Cao 
473610ee9f5bSAlgea Cao 		if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
473763cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
473863cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
473910ee9f5bSAlgea Cao 		else
474063cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
474163cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
4742a552a69cSDamon Ding 	}
474310ee9f5bSAlgea Cao 
4744ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
4745ee01dbb2SDamon Ding 			OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false);
4746ee01dbb2SDamon Ding 
474710ee9f5bSAlgea Cao 	if (yuv_overlay)
474810ee9f5bSAlgea Cao 		val = 0x20010200;
474910ee9f5bSAlgea Cao 	else
475010ee9f5bSAlgea Cao 		val = 0;
475110ee9f5bSAlgea Cao 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
4752b70b2d79SDamon Ding 	if (cstate->splice_mode) {
4753ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
4754ee01dbb2SDamon Ding 				OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id,
4755ee01dbb2SDamon Ding 				yuv_overlay, false);
4756ee01dbb2SDamon Ding 		vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val);
4757ee01dbb2SDamon Ding 	}
475810ee9f5bSAlgea Cao 
475910ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
476010ee9f5bSAlgea Cao 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
4761d0408543SAndy Yan 
4762c2b1fe35SDamon Ding 	if (vp->xmirror_en)
4763c2b1fe35SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4764c2b1fe35SDamon Ding 				DSP_X_MIR_EN_SHIFT, 1, false);
4765c2b1fe35SDamon Ding 
4766ac500a1fSSandy Huang 	vop2_tv_config_update(state, vop2);
4767d0408543SAndy Yan 	vop2_post_config(state, vop2);
47686027c871SZhang Yubing 	if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
47696027c871SZhang Yubing 		vop3_post_config(state, vop2);
4770d0408543SAndy Yan 
477112ee5af0SDamon Ding 	if (cstate->dsc_enable) {
477212ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
47731ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL);
47741ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL);
477512ee5af0SDamon Ding 		} else {
47761ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL);
477712ee5af0SDamon Ding 		}
477812ee5af0SDamon Ding 	}
477912ee5af0SDamon Ding 
4780d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4781ecc31b6eSAndy Yan 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
47820675a2a4SDamon Ding 	ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk);
4783b890760eSAlgea Cao 	if (ret) {
4784b890760eSAlgea Cao 		printf("%s: Failed to get dclk ret=%d\n", __func__, ret);
4785b890760eSAlgea Cao 		return ret;
4786b890760eSAlgea Cao 	}
4787d8e7f4a5SSandy Huang #endif
4788b890760eSAlgea Cao 
47893e05a7b8SZhang Yubing 	ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev);
47903e05a7b8SZhang Yubing 	if (!ret) {
47913e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll);
47923e05a7b8SZhang Yubing 		if (ret)
47935e85f4a7SZhang Yubing 			debug("%s: hdmi0_phy_pll may not define\n", __func__);
47943e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll);
47953e05a7b8SZhang Yubing 		if (ret)
47965e85f4a7SZhang Yubing 			debug("%s: hdmi1_phy_pll may not define\n", __func__);
47973e05a7b8SZhang Yubing 	} else {
4798b890760eSAlgea Cao 		hdmi0_phy_pll.dev = NULL;
4799545a0218SAlgea Cao 		hdmi1_phy_pll.dev = NULL;
48005e85f4a7SZhang Yubing 		debug("%s: Faile to find display-subsystem node\n", __func__);
4801b890760eSAlgea Cao 	}
4802b890760eSAlgea Cao 
4803ebbd144cSAlgea Cao 	if (vop2->version == VOP_VERSION_RK3528) {
4804ebbd144cSAlgea Cao 		struct ofnode_phandle_args args;
4805ebbd144cSAlgea Cao 
4806ebbd144cSAlgea Cao 		ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents",
4807ebbd144cSAlgea Cao 						 "#clock-cells", 0, 0, &args);
4808ebbd144cSAlgea Cao 		if (!ret) {
4809ebbd144cSAlgea Cao 			ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev);
4810ebbd144cSAlgea Cao 			if (ret) {
4811ebbd144cSAlgea Cao 				debug("warn: can't get clk device\n");
4812ebbd144cSAlgea Cao 				return ret;
4813ebbd144cSAlgea Cao 			}
4814ebbd144cSAlgea Cao 		} else {
4815ebbd144cSAlgea Cao 			debug("assigned-clock-parents's node not define\n");
4816ebbd144cSAlgea Cao 		}
4817ebbd144cSAlgea Cao 	}
4818ebbd144cSAlgea Cao 
4819cce1f2abSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
4820cce1f2abSDamon Ding 		vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div;
4821cce1f2abSDamon Ding 
48220a1fb152SZhang Yubing 	if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) {
4823b890760eSAlgea Cao 		if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0)
48240675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll);
4825b890760eSAlgea Cao 		else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1)
48260675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll);
4827b890760eSAlgea Cao 
4828b890760eSAlgea Cao 		/*
4829b890760eSAlgea Cao 		 * uboot clk driver won't set dclk parent's rate when use
4830b890760eSAlgea Cao 		 * hdmi phypll as dclk source.
4831b890760eSAlgea Cao 		 * So set dclk rate is meaningless. Set hdmi phypll rate
4832b890760eSAlgea Cao 		 * directly.
4833b890760eSAlgea Cao 		 */
48345f1357a2SZhang Yubing 		if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) {
4835cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000);
48365f1357a2SZhang Yubing 		} else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) {
4837cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000);
48385f1357a2SZhang Yubing 		} else {
48397efea85dSDamon Ding 			if (is_extend_pll(state, &hdmi_phy_pll.dev)) {
4840cce1f2abSDamon Ding 				ret = vop2_clk_set_rate(&hdmi_phy_pll,
4841cce1f2abSDamon Ding 							dclk_rate / vp_dclk_div * 1000);
48427efea85dSDamon Ding 			} else {
4843d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4844a552a69cSDamon Ding 				ret = vop2_clk_set_rate(&cstate->dclk,
4845a552a69cSDamon Ding 							dclk_rate / vp_dclk_div * 1000);
4846d8e7f4a5SSandy Huang #else
4847d8e7f4a5SSandy Huang 				if (vop2->version == VOP_VERSION_RK3528) {
4848d8e7f4a5SSandy Huang 					void *cru_base = (void *)RK3528_CRU_BASE;
4849d8e7f4a5SSandy Huang 
4850d8e7f4a5SSandy Huang 					/* dclk src switch to hdmiphy pll */
4851d8e7f4a5SSandy Huang 					writel((BIT(0) << 16) | BIT(0), cru_base + 0x450);
4852d8e7f4a5SSandy Huang 					rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000);
4853d8e7f4a5SSandy Huang 					ret = dclk_rate * 1000;
4854d8e7f4a5SSandy Huang 				}
4855d8e7f4a5SSandy Huang #endif
48565f1357a2SZhang Yubing 			}
48577efea85dSDamon Ding 		}
4858631ee99aSZhang Yubing 	} else {
48595f1357a2SZhang Yubing 		if (is_extend_pll(state, &hdmi_phy_pll.dev))
4860cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000);
48615f1357a2SZhang Yubing 		else
4862cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000);
4863edfef528SDamon Ding 	}
486463638f32SDamon Ding 
486563638f32SDamon Ding 	if (IS_ERR_VALUE(ret)) {
486663638f32SDamon Ding 		printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
486763638f32SDamon Ding 		       __func__, cstate->crtc_id, dclk_rate, ret);
486863638f32SDamon Ding 		return ret;
486963638f32SDamon Ding 	} else {
48704d64cedbSDamon Ding 		if (cstate->mcu_timing.mcu_pix_total) {
48714d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) / 1000;
48724d64cedbSDamon Ding 		} else {
48739655ad2fSDamon Ding 			dclk_div_factor = mode->crtc_clock / dclk_rate;
48744d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000;
48754d64cedbSDamon Ding 		}
4876edfef528SDamon Ding 		printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock);
4877631ee99aSZhang Yubing 	}
4878ecc31b6eSAndy Yan 
487966724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
4880e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false);
488166724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
4882e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false);
488366724b9cSDamon Ding 
488458cf1fa3SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total) {
488558cf1fa3SDamon Ding 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
488658cf1fa3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
488758cf1fa3SDamon Ding 				STANDBY_EN_SHIFT, 0, false);
48880675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
488958cf1fa3SDamon Ding 	}
48900675a2a4SDamon Ding 
4891d0408543SAndy Yan 	return 0;
4892d0408543SAndy Yan }
4893d0408543SAndy Yan 
4894ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
48953e39a5a1SSandy Huang 			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
48963e39a5a1SSandy Huang 			     uint32_t dst_h)
48973e39a5a1SSandy Huang {
48983e39a5a1SSandy Huang 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
48993e39a5a1SSandy Huang 	uint16_t hscl_filter_mode, vscl_filter_mode;
49005fa6e665SDamon Ding 	uint8_t xgt2 = 0, xgt4 = 0;
49015fa6e665SDamon Ding 	uint8_t ygt2 = 0, ygt4 = 0;
49023e39a5a1SSandy Huang 	uint32_t xfac = 0, yfac = 0;
4903ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
49045fa6e665SDamon Ding 	bool xgt_en = false;
49055fa6e665SDamon Ding 	bool xavg_en = false;
49063e39a5a1SSandy Huang 
49075fa6e665SDamon Ding 	if (is_vop3(vop2)) {
4908a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) {
4909a552a69cSDamon Ding 			if (src_w >= (8 * dst_w)) {
4910a552a69cSDamon Ding 				xgt4 = 1;
4911a552a69cSDamon Ding 				src_w >>= 2;
4912a552a69cSDamon Ding 			} else if (src_w >= (4 * dst_w)) {
4913a552a69cSDamon Ding 				xgt2 = 1;
4914a552a69cSDamon Ding 				src_w >>= 1;
4915a552a69cSDamon Ding 			}
4916a552a69cSDamon Ding 		} else {
49175fa6e665SDamon Ding 			if (src_w >= (4 * dst_w)) {
49185fa6e665SDamon Ding 				xgt4 = 1;
49195fa6e665SDamon Ding 				src_w >>= 2;
49205fa6e665SDamon Ding 			} else if (src_w >= (2 * dst_w)) {
49215fa6e665SDamon Ding 				xgt2 = 1;
49225fa6e665SDamon Ding 				src_w >>= 1;
49235fa6e665SDamon Ding 			}
49245fa6e665SDamon Ding 		}
4925a552a69cSDamon Ding 	}
49263e39a5a1SSandy Huang 
4927183eb252SDamon Ding 	/**
4928183eb252SDamon Ding 	 * The rk3528 is processed as 2 pixel/cycle,
4929183eb252SDamon Ding 	 * so ygt2/ygt4 needs to be triggered in advance to improve performance
4930183eb252SDamon Ding 	 * when src_w is bigger than 1920.
4931183eb252SDamon Ding 	 * dst_h / src_h is at [1, 0.65)     ygt2=0; ygt4=0;
4932183eb252SDamon Ding 	 * dst_h / src_h is at [0.65, 0.35)  ygt2=1; ygt4=0;
4933183eb252SDamon Ding 	 * dst_h / src_h is at [0.35, 0)     ygt2=0; ygt4=1;
4934183eb252SDamon Ding 	 */
4935183eb252SDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
4936183eb252SDamon Ding 		if (src_h >= (100 * dst_h / 35)) {
4937183eb252SDamon Ding 			ygt4 = 1;
4938183eb252SDamon Ding 			src_h >>= 2;
4939183eb252SDamon Ding 		} else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) {
4940183eb252SDamon Ding 			ygt2 = 1;
4941183eb252SDamon Ding 			src_h >>= 1;
4942183eb252SDamon Ding 		}
4943183eb252SDamon Ding 	} else {
4944a552a69cSDamon Ding 		if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) {
4945a552a69cSDamon Ding 			if (src_h >= (8 * dst_h)) {
4946a552a69cSDamon Ding 				ygt4 = 1;
4947a552a69cSDamon Ding 				src_h >>= 2;
4948a552a69cSDamon Ding 			} else if (src_h >= (4 * dst_h)) {
4949a552a69cSDamon Ding 				ygt2 = 1;
4950a552a69cSDamon Ding 				src_h >>= 1;
4951a552a69cSDamon Ding 			}
4952a552a69cSDamon Ding 		} else {
49535fa6e665SDamon Ding 			if (src_h >= (4 * dst_h)) {
49545fa6e665SDamon Ding 				ygt4 = 1;
49553e39a5a1SSandy Huang 				src_h >>= 2;
49565fa6e665SDamon Ding 			} else if (src_h >= (2 * dst_h)) {
49575fa6e665SDamon Ding 				ygt2 = 1;
49583e39a5a1SSandy Huang 				src_h >>= 1;
49595fa6e665SDamon Ding 			}
4960183eb252SDamon Ding 		}
4961a552a69cSDamon Ding 	}
49623e39a5a1SSandy Huang 
49633e39a5a1SSandy Huang 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
49643e39a5a1SSandy Huang 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
49653e39a5a1SSandy Huang 
49663e39a5a1SSandy Huang 	if (yrgb_hor_scl_mode == SCALE_UP)
49675fa6e665SDamon Ding 		hscl_filter_mode = win->hsu_filter_mode;
49683e39a5a1SSandy Huang 	else
49695fa6e665SDamon Ding 		hscl_filter_mode = win->hsd_filter_mode;
49703e39a5a1SSandy Huang 
49713e39a5a1SSandy Huang 	if (yrgb_ver_scl_mode == SCALE_UP)
49725fa6e665SDamon Ding 		vscl_filter_mode = win->vsu_filter_mode;
49733e39a5a1SSandy Huang 	else
49745fa6e665SDamon Ding 		vscl_filter_mode = win->vsd_filter_mode;
49753e39a5a1SSandy Huang 
49763e39a5a1SSandy Huang 	/*
49773e39a5a1SSandy Huang 	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
49783e39a5a1SSandy Huang 	 * at scale down mode
49793e39a5a1SSandy Huang 	 */
49805fa6e665SDamon Ding 	if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) {
49813e39a5a1SSandy Huang 		printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
49823e39a5a1SSandy Huang 		dst_w += 1;
49833e39a5a1SSandy Huang 	}
49843e39a5a1SSandy Huang 
49855fa6e665SDamon Ding 	if (is_vop3(vop2)) {
49865fa6e665SDamon Ding 		xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true);
49875fa6e665SDamon Ding 		yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false);
49885fa6e665SDamon Ding 
49895fa6e665SDamon Ding 		if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG)
49905fa6e665SDamon Ding 			xavg_en = xgt2 || xgt4;
49915fa6e665SDamon Ding 		else
49925fa6e665SDamon Ding 			xgt_en = xgt2 || xgt4;
4993a552a69cSDamon Ding 
4994a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
4995a552a69cSDamon Ding 			bool zme_dering_en = false;
4996a552a69cSDamon Ding 
4997a552a69cSDamon Ding 			if ((yrgb_hor_scl_mode == SCALE_UP &&
4998a552a69cSDamon Ding 			     hscl_filter_mode == VOP2_SCALE_UP_ZME) ||
4999a552a69cSDamon Ding 			    (yrgb_ver_scl_mode == SCALE_UP &&
5000a552a69cSDamon Ding 			     vscl_filter_mode == VOP2_SCALE_UP_ZME))
5001a552a69cSDamon Ding 				zme_dering_en = true;
5002a552a69cSDamon Ding 
5003a552a69cSDamon Ding 			/* Recommended configuration from the algorithm */
5004a552a69cSDamon Ding 			vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset,
5005a552a69cSDamon Ding 				    0x04100d10);
5006a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset,
5007a552a69cSDamon Ding 					EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false);
5008a552a69cSDamon Ding 		}
50095fa6e665SDamon Ding 	} else {
50103e39a5a1SSandy Huang 		xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
50113e39a5a1SSandy Huang 		yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
50125fa6e665SDamon Ding 	}
5013ecc31b6eSAndy Yan 
5014ecc31b6eSAndy Yan 	if (win->type == CLUSTER_LAYER) {
5015ecc31b6eSAndy Yan 		vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
5016ecc31b6eSAndy Yan 			    yfac << 16 | xfac);
5017ecc31b6eSAndy Yan 
50185fa6e665SDamon Ding 		if (is_vop3(vop2)) {
5019ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50205fa6e665SDamon Ding 					EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false);
5021ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50225fa6e665SDamon Ding 					EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false);
50235fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50245fa6e665SDamon Ding 					XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
5025ecc31b6eSAndy Yan 
5026ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50275fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT,
50285fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
5029ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50305fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT,
50315fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
50325fa6e665SDamon Ding 		} else {
50335fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50345fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT,
50355fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
50365fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50375fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT,
50385fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
50395fa6e665SDamon Ding 		}
5040ecc31b6eSAndy Yan 
50415fa6e665SDamon Ding 		if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
50425fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50435fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false);
50445fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50455fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false);
50465fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50475fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false);
50485fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50495fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false);
50505fa6e665SDamon Ding 		} else {
50515fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50525fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false);
50535fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50545fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false);
50555fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50565fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false);
50575fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
50585fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false);
50595fa6e665SDamon Ding 		}
5060ecc31b6eSAndy Yan 	} else {
50613e39a5a1SSandy Huang 		vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
50623e39a5a1SSandy Huang 			    yfac << 16 | xfac);
50633e39a5a1SSandy Huang 
50645fa6e665SDamon Ding 		if (is_vop3(vop2)) {
506534a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50665fa6e665SDamon Ding 					EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false);
506734a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50685fa6e665SDamon Ding 					EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false);
50695fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50705fa6e665SDamon Ding 					XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
50715fa6e665SDamon Ding 		}
50725fa6e665SDamon Ding 
50735fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50745fa6e665SDamon Ding 				YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false);
50755fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
50765fa6e665SDamon Ding 				YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false);
50773e39a5a1SSandy Huang 
50783e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50793e39a5a1SSandy Huang 				YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
50803e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50813e39a5a1SSandy Huang 				YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
50823e39a5a1SSandy Huang 
50833e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50843e39a5a1SSandy Huang 				YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
50853e39a5a1SSandy Huang 				hscl_filter_mode, false);
50863e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
50873e39a5a1SSandy Huang 				YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
50883e39a5a1SSandy Huang 				vscl_filter_mode, false);
50893e39a5a1SSandy Huang 	}
5090ecc31b6eSAndy Yan }
50913e39a5a1SSandy Huang 
5092a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win)
5093a33b790fSDamon Ding {
5094a33b790fSDamon Ding 	u32 win_offset = win->reg_offset;
5095a33b790fSDamon Ding 
5096a33b790fSDamon Ding 	if (win->type == CLUSTER_LAYER) {
5097a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK,
5098a33b790fSDamon Ding 				CLUSTER_AXI_ID_SHIFT, win->axi_id, false);
5099a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK,
5100a33b790fSDamon Ding 				CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5101a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK,
5102a33b790fSDamon Ding 				CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5103a33b790fSDamon Ding 	} else {
5104a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK,
5105a33b790fSDamon Ding 				ESMART_AXI_ID_SHIFT, win->axi_id, false);
5106a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK,
5107a33b790fSDamon Ding 				ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5108a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK,
5109a33b790fSDamon Ding 				ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5110a33b790fSDamon Ding 	}
5111a33b790fSDamon Ding }
5112a33b790fSDamon Ding 
5113840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format)
5114840bf541SDamon Ding {
5115840bf541SDamon Ding 	switch (format) {
5116840bf541SDamon Ding 	case ROCKCHIP_FMT_RGB565:
5117840bf541SDamon Ding 		return true;
5118840bf541SDamon Ding 	default:
5119840bf541SDamon Ding 		return false;
5120840bf541SDamon Ding 	}
5121840bf541SDamon Ding }
5122840bf541SDamon Ding 
51231c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win)
51241c9572c7SDamon Ding {
51251c9572c7SDamon Ding 	return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR);
51261c9572c7SDamon Ding }
51271c9572c7SDamon Ding 
51281c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
5129d0408543SAndy Yan {
5130d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5131d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
5132d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
5133d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
5134ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
5135ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
5136ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
5137ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
5138ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
5139ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
5140d0408543SAndy Yan 	int xvir = cstate->xvir;
5141d0408543SAndy Yan 	int y_mirror = 0;
514210ee9f5bSAlgea Cao 	int csc_mode;
5143ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5144ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
5145ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
5146ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
5147ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
5148ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5149840bf541SDamon Ding 	bool dither_up;
5150d0408543SAndy Yan 
5151ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
5152ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
5153ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
5154ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
5155ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
5156ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
5157ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
5158ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5159ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5160ee01dbb2SDamon Ding 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5161ee01dbb2SDamon Ding 	}
5162ee01dbb2SDamon Ding 
5163ecc31b6eSAndy Yan 	act_info = (src_h - 1) << 16;
5164ecc31b6eSAndy Yan 	act_info |= (src_w - 1) & 0xffff;
5165ecc31b6eSAndy Yan 
5166ecc31b6eSAndy Yan 	dsp_info = (crtc_h - 1) << 16;
5167ecc31b6eSAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
5168ecc31b6eSAndy Yan 
5169ecc31b6eSAndy Yan 	dsp_stx = crtc_x;
5170ecc31b6eSAndy Yan 	dsp_sty = crtc_y;
5171ecc31b6eSAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5172ecc31b6eSAndy Yan 
5173ecc31b6eSAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5174ecc31b6eSAndy Yan 		y_mirror = 1;
5175ecc31b6eSAndy Yan 	else
5176ecc31b6eSAndy Yan 		y_mirror = 0;
5177ecc31b6eSAndy Yan 
5178ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
5179ecc31b6eSAndy Yan 
5180a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
5181a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
5182a33b790fSDamon Ding 
5183ecc31b6eSAndy Yan 	if (y_mirror)
5184ecc31b6eSAndy Yan 		printf("WARN: y mirror is unsupported by cluster window\n");
5185ecc31b6eSAndy Yan 
5186a552a69cSDamon Ding 	if (is_vop3(vop2))
5187a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset,
5188a552a69cSDamon Ding 				CLUSTER_PORT_SEL_SHIFT, CLUSTER_PORT_SEL_SHIFT,
5189a552a69cSDamon Ding 				cstate->crtc_id, false);
5190a552a69cSDamon Ding 
5191e84ccd9bSDamon Ding 	/*
5192e84ccd9bSDamon Ding 	 * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode.
5193e84ccd9bSDamon Ding 	 */
5194e84ccd9bSDamon Ding 	if (vop2->version >= VOP_VERSION_RK3588)
5195a59754e1SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset,
5196a59754e1SDamon Ding 				EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false);
5197a59754e1SDamon Ding 
5198ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
5199ecc31b6eSAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5200ecc31b6eSAndy Yan 			false);
5201ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
5202ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset,
5203ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
5204ecc31b6eSAndy Yan 
5205ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
5206ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
5207ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
5208ecc31b6eSAndy Yan 
5209ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
5210ecc31b6eSAndy Yan 
5211df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5212df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
5213ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5214ecc31b6eSAndy Yan 			CLUSTER_RGB2YUV_EN_SHIFT,
5215ecc31b6eSAndy Yan 			is_yuv_output(conn_state->bus_format), false);
5216ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
5217ecc31b6eSAndy Yan 			CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
5218840bf541SDamon Ding 
5219840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5220840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5221840bf541SDamon Ding 			CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false);
5222840bf541SDamon Ding 
5223ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
5224ecc31b6eSAndy Yan 
5225ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
52261c9572c7SDamon Ding 
52271c9572c7SDamon Ding 	return 0;
5228d0408543SAndy Yan }
5229d0408543SAndy Yan 
52301c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
5231ecc31b6eSAndy Yan {
5232ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5233ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
5234ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
5235ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
5236ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
5237ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
5238ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
5239ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
5240ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
5241ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
5242ecc31b6eSAndy Yan 	int xvir = cstate->xvir;
5243ecc31b6eSAndy Yan 	int y_mirror = 0;
5244ecc31b6eSAndy Yan 	int csc_mode;
5245ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5246ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
5247ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
5248ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
5249ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
5250ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
52511c9572c7SDamon Ding 	u32 val;
5252840bf541SDamon Ding 	bool dither_up;
5253ecc31b6eSAndy Yan 
52541c9572c7SDamon Ding 	if (vop2_is_mirror_win(win)) {
52551c9572c7SDamon Ding 		struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id);
52561c9572c7SDamon Ding 
52571c9572c7SDamon Ding 		if (!source_win) {
52581c9572c7SDamon Ding 			printf("invalid source win id %d\n", win->source_win_id);
52591c9572c7SDamon Ding 			return -ENODEV;
52601c9572c7SDamon Ding 		}
52611c9572c7SDamon Ding 
52621c9572c7SDamon Ding 		val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset);
52631c9572c7SDamon Ding 		if (!(val & BIT(WIN_EN_SHIFT))) {
52641c9572c7SDamon Ding 			printf("WARN: the source win should be enabled before mirror win\n");
52651c9572c7SDamon Ding 			return -EAGAIN;
52661c9572c7SDamon Ding 		}
52671c9572c7SDamon Ding 	}
52681c9572c7SDamon Ding 
5269ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
5270ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
5271ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
5272ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
5273ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
5274ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
5275ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
5276ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5277ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5278ee01dbb2SDamon Ding 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5279ee01dbb2SDamon Ding 	}
5280ee01dbb2SDamon Ding 
528174bd8269SSandy Huang 	/*
528274bd8269SSandy Huang 	 * This is workaround solution for IC design:
528374bd8269SSandy Huang 	 * esmart can't support scale down when actual_w % 16 == 1.
528474bd8269SSandy Huang 	 */
528574bd8269SSandy Huang 	if (src_w > crtc_w && (src_w & 0xf) == 1) {
528674bd8269SSandy Huang 		printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
528774bd8269SSandy Huang 		src_w -= 1;
528874bd8269SSandy Huang 	}
528974bd8269SSandy Huang 
5290d0408543SAndy Yan 	act_info = (src_h - 1) << 16;
5291d0408543SAndy Yan 	act_info |= (src_w - 1) & 0xffff;
5292d0408543SAndy Yan 
5293d0408543SAndy Yan 	dsp_info = (crtc_h - 1) << 16;
5294d0408543SAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
5295d0408543SAndy Yan 
5296d0408543SAndy Yan 	dsp_stx = crtc_x;
5297d0408543SAndy Yan 	dsp_sty = crtc_y;
5298d0408543SAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5299d0408543SAndy Yan 
5300d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5301d0408543SAndy Yan 		y_mirror = 1;
5302d0408543SAndy Yan 	else
5303d0408543SAndy Yan 		y_mirror = 0;
5304d0408543SAndy Yan 
5305a552a69cSDamon Ding 	if (is_vop3(vop2)) {
5306a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset,
5307a552a69cSDamon Ding 				ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT,
5308a552a69cSDamon Ding 				win->scale_engine_num, false);
5309a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5310a552a69cSDamon Ding 				ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5311a552a69cSDamon Ding 				cstate->crtc_id, false);
5312a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM + win_offset,
5313a552a69cSDamon Ding 				ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT,
5314a552a69cSDamon Ding 				0, false);
5315a552a69cSDamon Ding 
5316a552a69cSDamon Ding 		/* Merge esmart1/3 from vp1 post to vp0 */
5317a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 &&
5318a552a69cSDamon Ding 		    (win->phys_id == ROCKCHIP_VOP2_ESMART1 ||
5319a552a69cSDamon Ding 		     win->phys_id == ROCKCHIP_VOP2_ESMART3))
5320a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5321a552a69cSDamon Ding 					ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5322a552a69cSDamon Ding 					1, false);
5323a552a69cSDamon Ding 	}
53245fa6e665SDamon Ding 
5325ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
53263e39a5a1SSandy Huang 
5327a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
5328a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
5329a33b790fSDamon Ding 
5330d0408543SAndy Yan 	if (y_mirror)
5331d0408543SAndy Yan 		cstate->dma_addr += (src_h - 1) * xvir * 4;
5332d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
5333d0408543SAndy Yan 			YMIRROR_EN_SHIFT, y_mirror, false);
5334d0408543SAndy Yan 
5335d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5336d0408543SAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5337d0408543SAndy Yan 			false);
5338a552a69cSDamon Ding 
5339a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
5340a552a69cSDamon Ding 		vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00);
5341a552a69cSDamon Ding 
5342d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
5343d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
5344ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
5345d0408543SAndy Yan 
5346d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
5347d0408543SAndy Yan 		    act_info);
5348d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
5349d0408543SAndy Yan 		    dsp_info);
5350d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
5351d0408543SAndy Yan 
5352d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5353d0408543SAndy Yan 			WIN_EN_SHIFT, 1, false);
5354d0408543SAndy Yan 
5355df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5356df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
535710ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
535810ee9f5bSAlgea Cao 			RGB2YUV_EN_SHIFT,
535910ee9f5bSAlgea Cao 			is_yuv_output(conn_state->bus_format), false);
536010ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
536110ee9f5bSAlgea Cao 			CSC_MODE_SHIFT, csc_mode, false);
536210ee9f5bSAlgea Cao 
5363840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5364840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5365840bf541SDamon Ding 			REGION0_DITHER_UP_EN_SHIFT, dither_up, false);
5366840bf541SDamon Ding 
5367d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
53681c9572c7SDamon Ding 
53691c9572c7SDamon Ding 	return 0;
5370ecc31b6eSAndy Yan }
5371ecc31b6eSAndy Yan 
5372ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state)
5373ee01dbb2SDamon Ding {
5374ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5375ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
5376ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
5377ee01dbb2SDamon Ding 	struct display_rect *src_rect = &cstate->src_rect;
5378ee01dbb2SDamon Ding 	struct display_rect *dst_rect = &cstate->crtc_rect;
5379ee01dbb2SDamon Ding 	struct display_rect left_src, left_dst, right_src, right_dst;
5380ee01dbb2SDamon Ding 	u16 half_hdisplay = mode->crtc_hdisplay >> 1;
5381ee01dbb2SDamon Ding 	int left_src_w, left_dst_w, right_dst_w;
5382ee01dbb2SDamon Ding 
5383ee01dbb2SDamon Ding 	left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x;
5384ee01dbb2SDamon Ding 	if (left_dst_w < 0)
5385ee01dbb2SDamon Ding 		left_dst_w = 0;
5386ee01dbb2SDamon Ding 	right_dst_w = dst_rect->w - left_dst_w;
5387ee01dbb2SDamon Ding 
5388ee01dbb2SDamon Ding 	if (!right_dst_w)
5389ee01dbb2SDamon Ding 		left_src_w = src_rect->w;
5390ee01dbb2SDamon Ding 	else
53910df0fd39SSandy Huang 		left_src_w = src_rect->x + src_rect->w - src_rect->w / 2;
5392ee01dbb2SDamon Ding 
5393ee01dbb2SDamon Ding 	left_src.x = src_rect->x;
5394ee01dbb2SDamon Ding 	left_src.w = left_src_w;
5395ee01dbb2SDamon Ding 	left_dst.x = dst_rect->x;
5396ee01dbb2SDamon Ding 	left_dst.w = left_dst_w;
5397ee01dbb2SDamon Ding 	right_src.x = left_src.x + left_src.w;
5398ee01dbb2SDamon Ding 	right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w;
5399ee01dbb2SDamon Ding 	right_dst.x = dst_rect->x + left_dst_w - half_hdisplay;
5400ee01dbb2SDamon Ding 	right_dst.w = right_dst_w;
5401ee01dbb2SDamon Ding 
5402ee01dbb2SDamon Ding 	left_src.y = src_rect->y;
5403ee01dbb2SDamon Ding 	left_src.h = src_rect->h;
5404ee01dbb2SDamon Ding 	left_dst.y = dst_rect->y;
5405ee01dbb2SDamon Ding 	left_dst.h = dst_rect->h;
5406ee01dbb2SDamon Ding 	right_src.y = src_rect->y;
5407ee01dbb2SDamon Ding 	right_src.h = src_rect->h;
5408ee01dbb2SDamon Ding 	right_dst.y = dst_rect->y;
5409ee01dbb2SDamon Ding 	right_dst.h = dst_rect->h;
5410ee01dbb2SDamon Ding 
5411ee01dbb2SDamon Ding 	memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect));
5412ee01dbb2SDamon Ding 	memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect));
5413ee01dbb2SDamon Ding 	memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect));
5414ee01dbb2SDamon Ding 	memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect));
5415ee01dbb2SDamon Ding }
5416ee01dbb2SDamon Ding 
5417ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state)
5418ecc31b6eSAndy Yan {
5419ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5420ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
5421ecc31b6eSAndy Yan 	struct vop2_win_data *win_data;
5422ee01dbb2SDamon Ding 	struct vop2_win_data *splice_win_data;
5423ecc31b6eSAndy Yan 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
54241c9572c7SDamon Ding 	int ret;
5425ecc31b6eSAndy Yan 
5426ee01dbb2SDamon Ding 	if (cstate->crtc_rect.w > cstate->max_output.width) {
5427ecc31b6eSAndy Yan 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
5428ee01dbb2SDamon Ding 		       cstate->crtc_rect.w, cstate->max_output.width);
5429ecc31b6eSAndy Yan 		return -EINVAL;
5430ecc31b6eSAndy Yan 	}
5431ecc31b6eSAndy Yan 
5432ecc31b6eSAndy Yan 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
5433ecc31b6eSAndy Yan 	if (!win_data) {
5434ecc31b6eSAndy Yan 		printf("invalid win id %d\n", primary_plane_id);
5435ecc31b6eSAndy Yan 		return -ENODEV;
5436ecc31b6eSAndy Yan 	}
5437ecc31b6eSAndy Yan 
54385fa6e665SDamon Ding 	/* ignore some plane register according vop3 esmart lb mode */
54395fa6e665SDamon Ding 	if (vop3_ignore_plane(vop2, win_data))
54405fa6e665SDamon Ding 		return -EACCES;
54415fa6e665SDamon Ding 
5442a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) {
5443b6ba80b4SDamon Ding 		if (vop2_power_domain_on(vop2, win_data->pd_id))
5444b6ba80b4SDamon Ding 			printf("open vp%d plane pd fail\n", cstate->crtc_id);
5445b6ba80b4SDamon Ding 	}
5446b6ba80b4SDamon Ding 
5447ee01dbb2SDamon Ding 	if (cstate->splice_mode) {
5448ee01dbb2SDamon Ding 		if (win_data->splice_win_id) {
5449ee01dbb2SDamon Ding 			splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id);
5450ee01dbb2SDamon Ding 			splice_win_data->splice_mode_right = true;
5451b6ba80b4SDamon Ding 
5452b6ba80b4SDamon Ding 			if (vop2_power_domain_on(vop2, splice_win_data->pd_id))
5453b6ba80b4SDamon Ding 				printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id);
5454b6ba80b4SDamon Ding 
5455ee01dbb2SDamon Ding 			vop2_calc_display_rect_for_splice(state);
5456ee01dbb2SDamon Ding 			if (win_data->type == CLUSTER_LAYER)
5457ee01dbb2SDamon Ding 				vop2_set_cluster_win(state, splice_win_data);
5458ee01dbb2SDamon Ding 			else
5459ee01dbb2SDamon Ding 				vop2_set_smart_win(state, splice_win_data);
5460ee01dbb2SDamon Ding 		} else {
5461ee01dbb2SDamon Ding 			printf("ERROR: splice mode is unsupported by plane %s\n",
546227cec8e2SDamon Ding 			       vop2_plane_id_to_string(primary_plane_id));
5463ee01dbb2SDamon Ding 			return -EINVAL;
5464ee01dbb2SDamon Ding 		}
5465ee01dbb2SDamon Ding 	}
5466ee01dbb2SDamon Ding 
5467ecc31b6eSAndy Yan 	if (win_data->type == CLUSTER_LAYER)
54681c9572c7SDamon Ding 		ret = vop2_set_cluster_win(state, win_data);
5469ecc31b6eSAndy Yan 	else
54701c9572c7SDamon Ding 		ret = vop2_set_smart_win(state, win_data);
54711c9572c7SDamon Ding 	if (ret)
54721c9572c7SDamon Ding 		return ret;
54738895aec1SSandy Huang 
54748895aec1SSandy Huang 	printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
547527cec8e2SDamon Ding 		cstate->crtc_id, vop2_plane_id_to_string(primary_plane_id),
5476ee01dbb2SDamon Ding 		cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h,
5477ee01dbb2SDamon Ding 		cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format,
54788895aec1SSandy Huang 		cstate->dma_addr);
54798895aec1SSandy Huang 
5480d0408543SAndy Yan 	return 0;
5481d0408543SAndy Yan }
5482d0408543SAndy Yan 
5483d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state)
5484d0408543SAndy Yan {
5485d0408543SAndy Yan 	return 0;
5486d0408543SAndy Yan }
5487d0408543SAndy Yan 
548812ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state)
548912ee5af0SDamon Ding {
549012ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
549112ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
549212ee5af0SDamon Ding 	struct vop2 *vop2 = cstate->private;
549312ee5af0SDamon Ding 	u8 dsc_id = cstate->dsc_id;
549412ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
549512ee5af0SDamon Ding 
549612ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
549712ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK,
549812ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
549912ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK,
550012ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
550112ee5af0SDamon Ding 	} else {
550212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK,
550312ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
550412ee5af0SDamon Ding 	}
550512ee5af0SDamon Ding }
550612ee5af0SDamon Ding 
5507d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state)
5508d0408543SAndy Yan {
5509d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5510d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
551152ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5512ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5513d0408543SAndy Yan 
5514d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5515d0408543SAndy Yan 			STANDBY_EN_SHIFT, 0, false);
5516ee01dbb2SDamon Ding 
5517ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5518ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5519ee01dbb2SDamon Ding 
5520d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5521d0408543SAndy Yan 
552212ee5af0SDamon Ding 	if (cstate->dsc_enable)
552312ee5af0SDamon Ding 		vop2_dsc_cfg_done(state);
552412ee5af0SDamon Ding 
55250675a2a4SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
55260675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
55270675a2a4SDamon Ding 				MCU_HOLD_MODE_SHIFT, 0, false);
55280675a2a4SDamon Ding 
5529d0408543SAndy Yan 	return 0;
5530d0408543SAndy Yan }
5531d0408543SAndy Yan 
5532efa01fe4SZhang Yubing static int rk3588_vop2_post_enable(struct display_state *state)
5533efa01fe4SZhang Yubing {
5534efa01fe4SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
5535efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5536efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5537efa01fe4SZhang Yubing 	int output_if = conn_state->output_if;
5538efa01fe4SZhang Yubing 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5539efa01fe4SZhang Yubing 	int ret, val;
5540efa01fe4SZhang Yubing 
5541efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP0)
5542efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
5543efa01fe4SZhang Yubing 				1, false);
5544efa01fe4SZhang Yubing 
5545efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP1)
5546efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT,
5547efa01fe4SZhang Yubing 				1, false);
5548efa01fe4SZhang Yubing 
5549efa01fe4SZhang Yubing 	if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) {
5550efa01fe4SZhang Yubing 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5551efa01fe4SZhang Yubing 		ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5552efa01fe4SZhang Yubing 					 val & BIT(cstate->crtc_id), 50 * 1000);
5553efa01fe4SZhang Yubing 		if (ret)
5554efa01fe4SZhang Yubing 			printf("%s wait cfg done timeout\n", __func__);
55550686a6a6SZhang Yubing 
55560686a6a6SZhang Yubing 		if (cstate->dclk_rst.dev) {
55570686a6a6SZhang Yubing 			reset_assert(&cstate->dclk_rst);
55580686a6a6SZhang Yubing 			udelay(20);
55590686a6a6SZhang Yubing 			reset_deassert(&cstate->dclk_rst);
55600686a6a6SZhang Yubing 		}
5561efa01fe4SZhang Yubing 	}
5562efa01fe4SZhang Yubing 
5563efa01fe4SZhang Yubing 	return 0;
5564efa01fe4SZhang Yubing }
5565efa01fe4SZhang Yubing 
5566efa01fe4SZhang Yubing static int rk3576_vop2_post_enable(struct display_state *state)
5567efa01fe4SZhang Yubing {
5568efa01fe4SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
5569efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5570efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5571efa01fe4SZhang Yubing 	int output_if = conn_state->output_if;
5572efa01fe4SZhang Yubing 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5573efa01fe4SZhang Yubing 	int ret, val;
5574efa01fe4SZhang Yubing 
5575efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP0)
5576efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
5577efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5578efa01fe4SZhang Yubing 
5579efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP1)
5580efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
5581efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5582efa01fe4SZhang Yubing 
5583efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP2)
5584efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
5585efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5586efa01fe4SZhang Yubing 
5587efa01fe4SZhang Yubing 	if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
5588efa01fe4SZhang Yubing 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5589efa01fe4SZhang Yubing 		ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5590efa01fe4SZhang Yubing 					 val & BIT(cstate->crtc_id), 50 * 1000);
5591efa01fe4SZhang Yubing 		if (ret)
5592efa01fe4SZhang Yubing 			printf("%s wait cfg done timeout\n", __func__);
55930686a6a6SZhang Yubing 
55940686a6a6SZhang Yubing 		if (cstate->dclk_rst.dev) {
55950686a6a6SZhang Yubing 			reset_assert(&cstate->dclk_rst);
55960686a6a6SZhang Yubing 			udelay(20);
55970686a6a6SZhang Yubing 			reset_deassert(&cstate->dclk_rst);
55980686a6a6SZhang Yubing 		}
5599efa01fe4SZhang Yubing 	}
5600efa01fe4SZhang Yubing 
5601efa01fe4SZhang Yubing 	return 0;
5602efa01fe4SZhang Yubing }
5603efa01fe4SZhang Yubing 
5604efa01fe4SZhang Yubing static int rockchip_vop2_post_enable(struct display_state *state)
5605efa01fe4SZhang Yubing {
5606efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5607efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5608efa01fe4SZhang Yubing 
5609efa01fe4SZhang Yubing 	if (vop2->version == VOP_VERSION_RK3588)
5610efa01fe4SZhang Yubing 		rk3588_vop2_post_enable(state);
5611efa01fe4SZhang Yubing 	else if (vop2->version == VOP_VERSION_RK3576)
5612efa01fe4SZhang Yubing 		rk3576_vop2_post_enable(state);
5613efa01fe4SZhang Yubing 
5614efa01fe4SZhang Yubing 	return 0;
5615efa01fe4SZhang Yubing }
5616efa01fe4SZhang Yubing 
5617d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state)
5618d0408543SAndy Yan {
5619d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5620d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
562152ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5622ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5623d0408543SAndy Yan 
5624d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5625d0408543SAndy Yan 			STANDBY_EN_SHIFT, 1, false);
5626ee01dbb2SDamon Ding 
5627ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5628ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5629ee01dbb2SDamon Ding 
5630d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5631d0408543SAndy Yan 
5632d0408543SAndy Yan 	return 0;
5633d0408543SAndy Yan }
5634d0408543SAndy Yan 
5635ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane)
5636ee008497SSandy Huang {
5637ee008497SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
5638ee008497SSandy Huang 	struct vop2 *vop2 = cstate->private;
5639ee008497SSandy Huang 	int i = 0;
5640ee008497SSandy Huang 	int correct_cursor_plane = -1;
5641ee008497SSandy Huang 	int plane_type = -1;
5642ee008497SSandy Huang 
5643ee008497SSandy Huang 	if (cursor_plane < 0)
5644ee008497SSandy Huang 		return -1;
5645ee008497SSandy Huang 
5646ee008497SSandy Huang 	if (plane_mask & (1 << cursor_plane))
5647ee008497SSandy Huang 		return cursor_plane;
5648ee008497SSandy Huang 
5649ee008497SSandy Huang 	/* Get current cursor plane type */
5650ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
5651ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_id == cursor_plane) {
5652ee008497SSandy Huang 			plane_type = vop2->data->plane_table[i].plane_type;
5653ee008497SSandy Huang 			break;
5654ee008497SSandy Huang 		}
5655ee008497SSandy Huang 	}
5656ee008497SSandy Huang 
5657ee008497SSandy Huang 	/* Get the other same plane type plane id */
5658ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
5659ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_type == plane_type &&
5660ee008497SSandy Huang 		    vop2->data->plane_table[i].plane_id != cursor_plane) {
5661ee008497SSandy Huang 			correct_cursor_plane = vop2->data->plane_table[i].plane_id;
5662ee008497SSandy Huang 			break;
5663ee008497SSandy Huang 		}
5664ee008497SSandy Huang 	}
5665ee008497SSandy Huang 
5666ee008497SSandy Huang 	/* To check whether the new correct_cursor_plane is attach to current vp */
5667ee008497SSandy Huang 	if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) {
5668ee008497SSandy Huang 		printf("error: faild to find correct plane as cursor plane\n");
5669ee008497SSandy Huang 		return -1;
5670ee008497SSandy Huang 	}
5671ee008497SSandy Huang 
5672ee008497SSandy Huang 	printf("vp%d adjust cursor plane from %d to %d\n",
5673ee008497SSandy Huang 	       cstate->crtc_id, cursor_plane, correct_cursor_plane);
5674ee008497SSandy Huang 
5675ee008497SSandy Huang 	return correct_cursor_plane;
5676ee008497SSandy Huang }
5677ee008497SSandy Huang 
5678b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
5679b0989546SSandy Huang {
5680b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
5681b0989546SSandy Huang 	struct vop2 *vop2 = cstate->private;
5682b0989546SSandy Huang 	ofnode vp_node;
5683b0989546SSandy Huang 	struct device_node *port_parent_node = cstate->ports_node;
5684b0989546SSandy Huang 	static bool vop_fix_dts;
5685b0989546SSandy Huang 	const char *path;
5686b0989546SSandy Huang 	u32 plane_mask = 0;
5687b0989546SSandy Huang 	int vp_id = 0;
5688ee008497SSandy Huang 	int cursor_plane_id = -1;
5689b0989546SSandy Huang 
56905fa6e665SDamon Ding 	if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528)
5691b0989546SSandy Huang 		return 0;
5692b0989546SSandy Huang 
5693b0989546SSandy Huang 	ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
5694b0989546SSandy Huang 		path = vp_node.np->full_name;
5695b0989546SSandy Huang 		plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
5696b0989546SSandy Huang 
56978b1fe597SSandy Huang 		if (cstate->crtc->assign_plane)
56988b1fe597SSandy Huang 			continue;
5699ee008497SSandy Huang 		cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask,
5700ee008497SSandy Huang 								 cstate->crtc->vps[vp_id].cursor_plane);
5701ee008497SSandy Huang 		printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
5702b0989546SSandy Huang 		       vp_id, plane_mask,
5703ee008497SSandy Huang 		       vop2->vp_plane_mask[vp_id].primary_plane_id,
5704ee008497SSandy Huang 		       cursor_plane_id);
5705b0989546SSandy Huang 
5706b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
5707b0989546SSandy Huang 				     plane_mask, 1);
5708b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
5709b0989546SSandy Huang 				     vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
5710ee008497SSandy Huang 		if (cursor_plane_id >= 0)
5711ee008497SSandy Huang 			do_fixup_by_path_u32(blob, path, "cursor-win-id",
5712ee008497SSandy Huang 					     cursor_plane_id, 1);
5713b0989546SSandy Huang 		vp_id++;
5714b0989546SSandy Huang 	}
5715b0989546SSandy Huang 
5716b0989546SSandy Huang 	vop_fix_dts = true;
5717b0989546SSandy Huang 
5718b0989546SSandy Huang 	return 0;
5719b0989546SSandy Huang }
5720b0989546SSandy Huang 
5721820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state)
5722820a5c17SDamon Ding {
5723820a5c17SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5724820a5c17SDamon Ding 	struct rockchip_crtc *crtc = cstate->crtc;
5725820a5c17SDamon Ding 
5726820a5c17SDamon Ding 	if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) {
5727820a5c17SDamon Ding 		printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id);
5728820a5c17SDamon Ding 		return -ENOTSUPP;
5729820a5c17SDamon Ding 	}
5730820a5c17SDamon Ding 
5731820a5c17SDamon Ding 	if (cstate->splice_mode) {
5732820a5c17SDamon Ding 		crtc->splice_mode = true;
5733820a5c17SDamon Ding 		crtc->splice_crtc_id = cstate->splice_crtc_id;
5734820a5c17SDamon Ding 	}
5735820a5c17SDamon Ding 
5736820a5c17SDamon Ding 	return 0;
5737820a5c17SDamon Ding }
5738820a5c17SDamon Ding 
573922007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state)
574022007755SDamon Ding {
574122007755SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
574222007755SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
574322007755SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
574422007755SDamon Ding 	struct videomode vm;
574522007755SDamon Ding 
574622007755SDamon Ding 	drm_display_mode_to_videomode(mode, &vm);
574722007755SDamon Ding 
574822007755SDamon Ding 	if (vm.hactive < 32 || vm.vactive < 32 ||
574922007755SDamon Ding 	    (vm.hfront_porch * vm.hsync_len * vm.hback_porch *
575022007755SDamon Ding 	     vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) {
575122007755SDamon Ding 		printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id);
575222007755SDamon Ding 		return -EINVAL;
575322007755SDamon Ding 	}
575422007755SDamon Ding 
575522007755SDamon Ding 	return 0;
575622007755SDamon Ding }
575722007755SDamon Ding 
5758b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state)
5759b02eb70bSDamon Ding {
5760b02eb70bSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
57610e19fecdSDamon Ding 	struct rockchip_connector *conn = conn_state->connector;
5762b02eb70bSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
5763b02eb70bSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5764b02eb70bSDamon Ding 	struct vop2 *vop2 = cstate->private;
5765b02eb70bSDamon Ding 
57660e19fecdSDamon Ding 	if (conn_state->secondary) {
57670e19fecdSDamon Ding 		if (!(conn->dual_channel_mode &&
57680e19fecdSDamon Ding 		      conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) &&
57692b992d78SDamon Ding 		    conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS)
57702b992d78SDamon Ding 			drm_mode_convert_to_split_mode(mode);
57710e19fecdSDamon Ding 	}
57722b992d78SDamon Ding 
57731b5811e7SDamon Ding 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
5774b02eb70bSDamon Ding 
5775243f0077SDamon Ding 	/*
5776640211a0SDamon Ding 	 * For RK3568 and RK3588, the hactive of video timing must
5777640211a0SDamon Ding 	 * be 4-pixel aligned.
5778640211a0SDamon Ding 	 */
5779640211a0SDamon Ding 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) {
5780640211a0SDamon Ding 		if (mode->crtc_hdisplay % 4) {
5781640211a0SDamon Ding 			int old_hdisplay = mode->crtc_hdisplay;
5782640211a0SDamon Ding 			int align = 4 - (mode->crtc_hdisplay % 4);
5783640211a0SDamon Ding 
5784640211a0SDamon Ding 			mode->crtc_hdisplay += align;
5785640211a0SDamon Ding 			mode->crtc_hsync_start += align;
5786640211a0SDamon Ding 			mode->crtc_hsync_end += align;
5787640211a0SDamon Ding 			mode->crtc_htotal += align;
5788640211a0SDamon Ding 
5789640211a0SDamon Ding 			printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n",
5790640211a0SDamon Ding 			       old_hdisplay, mode->hdisplay);
5791640211a0SDamon Ding 		}
5792640211a0SDamon Ding 	}
5793640211a0SDamon Ding 
5794640211a0SDamon Ding 	/*
5795243f0077SDamon Ding 	 * For RK3576 YUV420 output, hden signal introduce one cycle delay,
5796243f0077SDamon Ding 	 * so we need to adjust hfp and hbp to compatible with this design.
5797243f0077SDamon Ding 	 */
5798243f0077SDamon Ding 	if (vop2->version == VOP_VERSION_RK3576 &&
5799243f0077SDamon Ding 	    conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
5800243f0077SDamon Ding 		mode->crtc_hsync_start += 2;
5801243f0077SDamon Ding 		mode->crtc_hsync_end += 2;
5802243f0077SDamon Ding 	}
5803243f0077SDamon Ding 
5804b02eb70bSDamon Ding 	if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656)
5805b02eb70bSDamon Ding 		mode->crtc_clock *= 2;
5806b02eb70bSDamon Ding 
5807b02eb70bSDamon Ding 	/*
5808b02eb70bSDamon Ding 	 * For RK3528, the path of CVBS output is like:
5809b02eb70bSDamon Ding 	 * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
5810b02eb70bSDamon Ding 	 * The vop2 dclk should be four times crtc_clock for CVBS sampling
5811b02eb70bSDamon Ding 	 * clock needs.
5812b02eb70bSDamon Ding 	 */
5813b02eb70bSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656)
5814b02eb70bSDamon Ding 		mode->crtc_clock *= 4;
5815b02eb70bSDamon Ding 
58164d64cedbSDamon Ding 	mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format);
58174d64cedbSDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
58184d64cedbSDamon Ding 		mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1;
58190675a2a4SDamon Ding 
5820b02eb70bSDamon Ding 	return 0;
5821b02eb70bSDamon Ding }
5822b02eb70bSDamon Ding 
58234c765862SDamon Ding #define FRAC_16_16(mult, div)	(((mult) << 16) / (div))
58244c765862SDamon Ding 
58254c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state)
58264c765862SDamon Ding {
58274c765862SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
58284c765862SDamon Ding 	struct vop2 *vop2 = cstate->private;
58294c765862SDamon Ding 	struct display_rect *src = &cstate->src_rect;
58304c765862SDamon Ding 	struct display_rect *dst = &cstate->crtc_rect;
58314c765862SDamon Ding 	struct vop2_win_data *win_data;
58324c765862SDamon Ding 	int min_scale, max_scale;
58334c765862SDamon Ding 	int hscale, vscale;
58344c765862SDamon Ding 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
58354c765862SDamon Ding 
58364c765862SDamon Ding 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
58374c765862SDamon Ding 	if (!win_data) {
58384c765862SDamon Ding 		printf("ERROR: invalid win id %d\n", primary_plane_id);
58394c765862SDamon Ding 		return -ENODEV;
58404c765862SDamon Ding 	}
58414c765862SDamon Ding 
58424c765862SDamon Ding 	min_scale = FRAC_16_16(1, win_data->max_downscale_factor);
58434c765862SDamon Ding 	max_scale = FRAC_16_16(win_data->max_upscale_factor, 1);
58444c765862SDamon Ding 
58454c765862SDamon Ding 	hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale);
58464c765862SDamon Ding 	vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale);
58474c765862SDamon Ding 	if (hscale < 0 || vscale < 0) {
58484c765862SDamon Ding 		printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name);
58494c765862SDamon Ding 		return -ERANGE;
58504c765862SDamon Ding 		}
58514c765862SDamon Ding 
58524c765862SDamon Ding 	return 0;
58534c765862SDamon Ding }
5854337d1c13SDamon Ding 
58558e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state)
58568e7ef808SDamon Ding {
5857d8e7f4a5SSandy Huang 	__maybe_unused struct connector_state *conn_state = &state->conn_state;
58588e7ef808SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
58598e7ef808SDamon Ding 	struct vop2 *vop2 = cstate->private;
58608e7ef808SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
58618e7ef808SDamon Ding 	int val = 0;
58628e7ef808SDamon Ding 	int ret = 0;
58638e7ef808SDamon Ding 
58648e7ef808SDamon Ding 	ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val,
58658e7ef808SDamon Ding 				 (val >> EDPI_WMS_FS) & 0x1, 50 * 1000);
58668e7ef808SDamon Ding 	if (!ret) {
5867d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
58688e7ef808SDamon Ding 		ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
58698e7ef808SDamon Ding 					 !val, 50 * 1000);
58708e7ef808SDamon Ding 		if (!ret) {
58718e7ef808SDamon Ding 			ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
58728e7ef808SDamon Ding 						 val, 50 * 1000);
58738e7ef808SDamon Ding 			if (!ret) {
58748e7ef808SDamon Ding 				vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
58758e7ef808SDamon Ding 						EN_MASK, EDPI_WMS_FS, 1, false);
58768e7ef808SDamon Ding 			} else {
58778e7ef808SDamon Ding 				printf("ERROR: vp%d wait for active TE signal timeout\n",
58788e7ef808SDamon Ding 				       cstate->crtc_id);
58798e7ef808SDamon Ding 				return ret;
58808e7ef808SDamon Ding 			}
58818e7ef808SDamon Ding 		} else {
58828e7ef808SDamon Ding 			printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id);
58838e7ef808SDamon Ding 			return ret;
58848e7ef808SDamon Ding 		}
5885d8e7f4a5SSandy Huang #endif
58868e7ef808SDamon Ding 	} else {
58878e7ef808SDamon Ding 		printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id);
58888e7ef808SDamon Ding 		return ret;
58898e7ef808SDamon Ding 	}
58908e7ef808SDamon Ding 
58918e7ef808SDamon Ding 	return 0;
58928e7ef808SDamon Ding }
58938e7ef808SDamon Ding 
589472388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state)
589572388c26SDamon Ding {
589672388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
589772388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
589872388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
589972388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
5900a552a69cSDamon Ding 	u32 len = 128;
590172388c26SDamon Ding 	u32 n, i, j;
590272388c26SDamon Ding 	u32 base;
590372388c26SDamon Ding 
590472388c26SDamon Ding 	if (!cstate->crtc->active)
590572388c26SDamon Ding 		return -EINVAL;
590672388c26SDamon Ding 
590772388c26SDamon Ding 	n = vop2_data->dump_regs_size;
590872388c26SDamon Ding 	for (i = 0; i < n; i++) {
590972388c26SDamon Ding 		base = regs[i].offset;
5910a552a69cSDamon Ding 		len = 128;
5911a552a69cSDamon Ding 		if (regs[i].size)
5912a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
591372388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
5914a552a69cSDamon Ding 		for (j = 0; j < len;) {
591572388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
591672388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
591772388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
591872388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
591972388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
592072388c26SDamon Ding 			j += 4;
592172388c26SDamon Ding 		}
592272388c26SDamon Ding 	}
592372388c26SDamon Ding 
592472388c26SDamon Ding 	return 0;
592572388c26SDamon Ding }
592672388c26SDamon Ding 
592772388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state)
592872388c26SDamon Ding {
592972388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
593072388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
593172388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
593272388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
5933a552a69cSDamon Ding 	u32 len = 128;
593472388c26SDamon Ding 	u32 n, i, j;
593572388c26SDamon Ding 	u32 base;
593672388c26SDamon Ding 	bool enable_state;
593772388c26SDamon Ding 
593872388c26SDamon Ding 	if (!cstate->crtc->active)
593972388c26SDamon Ding 		return -EINVAL;
594072388c26SDamon Ding 
594172388c26SDamon Ding 	n = vop2_data->dump_regs_size;
594272388c26SDamon Ding 	for (i = 0; i < n; i++) {
594372388c26SDamon Ding 		if (regs[i].state_mask) {
594472388c26SDamon Ding 			enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) &
594572388c26SDamon Ding 				       regs[i].state_mask;
594672388c26SDamon Ding 			if (enable_state != regs[i].enable_state)
594772388c26SDamon Ding 				continue;
594872388c26SDamon Ding 		}
594972388c26SDamon Ding 
595072388c26SDamon Ding 		base = regs[i].offset;
5951a552a69cSDamon Ding 		len = 128;
5952a552a69cSDamon Ding 		if (regs[i].size)
5953a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
595472388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
5955a552a69cSDamon Ding 		for (j = 0; j < len;) {
595672388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
595772388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
595872388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
595972388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
596072388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
596172388c26SDamon Ding 			j += 4;
596272388c26SDamon Ding 		}
596372388c26SDamon Ding 	}
596472388c26SDamon Ding 
596572388c26SDamon Ding 	return 0;
596672388c26SDamon Ding }
596772388c26SDamon Ding 
596872388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = {
596972388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
597072388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
597172388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
597272388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
597372388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
597472388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
597572388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
597672388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
597772388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
597872388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
597972388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
598072388c26SDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
598172388c26SDamon Ding 	{ RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1},
598272388c26SDamon Ding };
598372388c26SDamon Ding 
59845fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
59855fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
59865fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
59875fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
59885fa6e665SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
59895fa6e665SDamon Ding };
59905fa6e665SDamon Ding 
59915fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
59925fa6e665SDamon Ding 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
59935fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
59945fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
59955fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
59965fa6e665SDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
59975fa6e665SDamon Ding };
59985fa6e665SDamon Ding 
59995fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
60005fa6e665SDamon Ding 	{ /* one display policy for hdmi */
60015fa6e665SDamon Ding 		{/* main display */
6002ebbd144cSAlgea Cao 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
60035fa6e665SDamon Ding 			.attached_layers_nr = 4,
60045fa6e665SDamon Ding 			.attached_layers = {
60055fa6e665SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0,
60065fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2
60075fa6e665SDamon Ding 				},
60085fa6e665SDamon Ding 		},
60095fa6e665SDamon Ding 		{/* second display */},
60105fa6e665SDamon Ding 		{/* third  display */},
60115fa6e665SDamon Ding 		{/* fourth display */},
60125fa6e665SDamon Ding 	},
60135fa6e665SDamon Ding 
60145fa6e665SDamon Ding 	{ /* two display policy */
60155fa6e665SDamon Ding 		{/* main display */
6016ebbd144cSAlgea Cao 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
60175fa6e665SDamon Ding 			.attached_layers_nr = 3,
60185fa6e665SDamon Ding 			.attached_layers = {
60195fa6e665SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
60205fa6e665SDamon Ding 				},
60215fa6e665SDamon Ding 		},
60225fa6e665SDamon Ding 
60235fa6e665SDamon Ding 		{/* second display */
60245fa6e665SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
60255fa6e665SDamon Ding 			.attached_layers_nr = 2,
60265fa6e665SDamon Ding 			.attached_layers = {
60275fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
60285fa6e665SDamon Ding 				},
60295fa6e665SDamon Ding 		},
60305fa6e665SDamon Ding 		{/* third  display */},
60315fa6e665SDamon Ding 		{/* fourth display */},
60325fa6e665SDamon Ding 	},
60335fa6e665SDamon Ding 
60345fa6e665SDamon Ding 	{ /* one display policy for cvbs */
60355fa6e665SDamon Ding 		{/* main display */
60365fa6e665SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
60375fa6e665SDamon Ding 			.attached_layers_nr = 2,
60385fa6e665SDamon Ding 			.attached_layers = {
60395fa6e665SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
60405fa6e665SDamon Ding 				},
60415fa6e665SDamon Ding 		},
60425fa6e665SDamon Ding 		{/* second display */},
60435fa6e665SDamon Ding 		{/* third  display */},
60445fa6e665SDamon Ding 		{/* fourth display */},
60455fa6e665SDamon Ding 	},
60465fa6e665SDamon Ding 
60475fa6e665SDamon Ding 	{/* reserved */},
60485fa6e665SDamon Ding };
60495fa6e665SDamon Ding 
60505fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = {
60515fa6e665SDamon Ding 	{
60525fa6e665SDamon Ding 		.name = "Esmart0",
60535fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
60545fa6e665SDamon Ding 		.type = ESMART_LAYER,
60555fa6e665SDamon Ding 		.win_sel_port_offset = 8,
60565fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 0xff, 0xff, 0xff },
60575fa6e665SDamon Ding 		.reg_offset = 0,
60585fa6e665SDamon Ding 		.axi_id = 0,
60595fa6e665SDamon Ding 		.axi_yrgb_id = 0x06,
60605fa6e665SDamon Ding 		.axi_uv_id = 0x07,
60615fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
60625fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
60635fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
60645fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
60655fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
60665fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
60675fa6e665SDamon Ding 		.max_upscale_factor = 8,
60685fa6e665SDamon Ding 		.max_downscale_factor = 8,
60695fa6e665SDamon Ding 	},
60705fa6e665SDamon Ding 
60715fa6e665SDamon Ding 	{
60725fa6e665SDamon Ding 		.name = "Esmart1",
60735fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
60745fa6e665SDamon Ding 		.type = ESMART_LAYER,
60755fa6e665SDamon Ding 		.win_sel_port_offset = 10,
60765fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0xff, 0xff },
60775fa6e665SDamon Ding 		.reg_offset = 0x200,
60785fa6e665SDamon Ding 		.axi_id = 0,
60795fa6e665SDamon Ding 		.axi_yrgb_id = 0x08,
60805fa6e665SDamon Ding 		.axi_uv_id = 0x09,
60815fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
60825fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
60835fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
60845fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
60855fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
60865fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
60875fa6e665SDamon Ding 		.max_upscale_factor = 8,
60885fa6e665SDamon Ding 		.max_downscale_factor = 8,
60895fa6e665SDamon Ding 	},
60905fa6e665SDamon Ding 
60915fa6e665SDamon Ding 	{
60925fa6e665SDamon Ding 		.name = "Esmart2",
60935fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
60945fa6e665SDamon Ding 		.type = ESMART_LAYER,
60955fa6e665SDamon Ding 		.win_sel_port_offset = 12,
60965fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 0, 0xff, 0xff },
60975fa6e665SDamon Ding 		.reg_offset = 0x400,
60985fa6e665SDamon Ding 		.axi_id = 0,
60995fa6e665SDamon Ding 		.axi_yrgb_id = 0x0a,
61005fa6e665SDamon Ding 		.axi_uv_id = 0x0b,
61015fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61025fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61035fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61045fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61055fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
61065fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
61075fa6e665SDamon Ding 		.max_upscale_factor = 8,
61085fa6e665SDamon Ding 		.max_downscale_factor = 8,
61095fa6e665SDamon Ding 	},
61105fa6e665SDamon Ding 
61115fa6e665SDamon Ding 	{
61125fa6e665SDamon Ding 		.name = "Esmart3",
61135fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
61145fa6e665SDamon Ding 		.type = ESMART_LAYER,
61155fa6e665SDamon Ding 		.win_sel_port_offset = 14,
61165fa6e665SDamon Ding 		.layer_sel_win_id = { 0xff, 1, 0xff, 0xff },
61175fa6e665SDamon Ding 		.reg_offset = 0x600,
61185fa6e665SDamon Ding 		.axi_id = 0,
61195fa6e665SDamon Ding 		.axi_yrgb_id = 0x0c,
61205fa6e665SDamon Ding 		.axi_uv_id = 0x0d,
61215fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61225fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61235fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61245fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61255fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
61265fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
61275fa6e665SDamon Ding 		.max_upscale_factor = 8,
61285fa6e665SDamon Ding 		.max_downscale_factor = 8,
61295fa6e665SDamon Ding 	},
61305fa6e665SDamon Ding 
61315fa6e665SDamon Ding 	{
61325fa6e665SDamon Ding 		.name = "Cluster0",
61335fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
61345fa6e665SDamon Ding 		.type = CLUSTER_LAYER,
61355fa6e665SDamon Ding 		.win_sel_port_offset = 0,
61365fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0xff, 0xff, 0xff },
61375fa6e665SDamon Ding 		.reg_offset = 0,
61385fa6e665SDamon Ding 		.axi_id = 0,
61395fa6e665SDamon Ding 		.axi_yrgb_id = 0x02,
61405fa6e665SDamon Ding 		.axi_uv_id = 0x03,
61415fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
61425fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61435fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
61445fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
61455fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
61465fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
61475fa6e665SDamon Ding 		.max_upscale_factor = 8,
61485fa6e665SDamon Ding 		.max_downscale_factor = 8,
61495fa6e665SDamon Ding 	},
61505fa6e665SDamon Ding };
61515fa6e665SDamon Ding 
61525fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = {
61535fa6e665SDamon Ding 	{
61546027c871SZhang Yubing 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM |
61556027c871SZhang Yubing 			   VOP_FEATURE_POST_CSC,
61565fa6e665SDamon Ding 		.max_output = {4096, 4096},
6157b05105abSDamon Ding 		.layer_mix_dly = 6,
6158b05105abSDamon Ding 		.hdr_mix_dly = 2,
6159b05105abSDamon Ding 		.win_dly = 8,
61605fa6e665SDamon Ding 	},
61615fa6e665SDamon Ding 	{
61625fa6e665SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
61635fa6e665SDamon Ding 		.max_output = {1920, 1080},
6164b05105abSDamon Ding 		.layer_mix_dly = 2,
6165b05105abSDamon Ding 		.hdr_mix_dly = 0,
6166b05105abSDamon Ding 		.win_dly = 8,
61675fa6e665SDamon Ding 	},
61685fa6e665SDamon Ding };
61695fa6e665SDamon Ding 
61705fa6e665SDamon Ding const struct vop2_data rk3528_vop = {
61715fa6e665SDamon Ding 	.version = VOP_VERSION_RK3528,
61725fa6e665SDamon Ding 	.nr_vps = 2,
61735fa6e665SDamon Ding 	.vp_data = rk3528_vp_data,
61745fa6e665SDamon Ding 	.win_data = rk3528_win_data,
61755fa6e665SDamon Ding 	.plane_mask = rk3528_vp_plane_mask[0],
61765fa6e665SDamon Ding 	.plane_table = rk3528_plane_table,
61775fa6e665SDamon Ding 	.vp_primary_plane_order = rk3528_vp_primary_plane_order,
61785fa6e665SDamon Ding 	.nr_layers = 5,
61795fa6e665SDamon Ding 	.nr_mixers = 3,
61805fa6e665SDamon Ding 	.nr_gammas = 2,
61815fa6e665SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE,
618272388c26SDamon Ding 	.dump_regs = rk3528_dump_regs,
618372388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
618472388c26SDamon Ding };
618572388c26SDamon Ding 
618672388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = {
618772388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
618872388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
618972388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
619072388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
619172388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
619272388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
619372388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
619472388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
619572388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
619672388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
61975fa6e665SDamon Ding };
61985fa6e665SDamon Ding 
6199452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
6200452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6201452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6202452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
6203452afb13SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
6204452afb13SDamon Ding };
6205452afb13SDamon Ding 
6206452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6207452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6208452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6209452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
6210452afb13SDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
6211452afb13SDamon Ding };
6212452afb13SDamon Ding 
6213452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
6214452afb13SDamon Ding 	{ /* one display policy for hdmi */
6215452afb13SDamon Ding 		{/* main display */
6216452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6217452afb13SDamon Ding 			.attached_layers_nr = 4,
6218452afb13SDamon Ding 			.attached_layers = {
6219452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1,
6220452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART2,  ROCKCHIP_VOP2_ESMART3
6221452afb13SDamon Ding 				},
6222452afb13SDamon Ding 		},
6223452afb13SDamon Ding 		{/* second display */},
6224452afb13SDamon Ding 		{/* third  display */},
6225452afb13SDamon Ding 		{/* fourth display */},
6226452afb13SDamon Ding 	},
6227452afb13SDamon Ding 
6228452afb13SDamon Ding 	{ /* two display policy */
6229452afb13SDamon Ding 		{/* main display */
6230452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6231452afb13SDamon Ding 			.attached_layers_nr = 2,
6232452afb13SDamon Ding 			.attached_layers = {
6233452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
6234452afb13SDamon Ding 				},
6235452afb13SDamon Ding 		},
6236452afb13SDamon Ding 
6237452afb13SDamon Ding 		{/* second display */
6238452afb13SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6239452afb13SDamon Ding 			.attached_layers_nr = 2,
6240452afb13SDamon Ding 			.attached_layers = {
6241452afb13SDamon Ding 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
6242452afb13SDamon Ding 				},
6243452afb13SDamon Ding 		},
6244452afb13SDamon Ding 		{/* third  display */},
6245452afb13SDamon Ding 		{/* fourth display */},
6246452afb13SDamon Ding 	},
6247452afb13SDamon Ding 
6248452afb13SDamon Ding 	{/* reserved */},
6249452afb13SDamon Ding };
6250452afb13SDamon Ding 
6251452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = {
6252452afb13SDamon Ding 	{
6253452afb13SDamon Ding 		.name = "Esmart0",
6254452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6255452afb13SDamon Ding 		.type = ESMART_LAYER,
6256452afb13SDamon Ding 		.win_sel_port_offset = 8,
6257452afb13SDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
6258452afb13SDamon Ding 		.reg_offset = 0,
6259452afb13SDamon Ding 		.axi_id = 0,
6260452afb13SDamon Ding 		.axi_yrgb_id = 0x02,
6261452afb13SDamon Ding 		.axi_uv_id = 0x03,
6262452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6263452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6264452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6265452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6266452afb13SDamon Ding 		.max_upscale_factor = 8,
6267452afb13SDamon Ding 		.max_downscale_factor = 8,
6268452afb13SDamon Ding 	},
6269452afb13SDamon Ding 
6270452afb13SDamon Ding 	{
6271452afb13SDamon Ding 		.name = "Esmart1",
6272452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6273452afb13SDamon Ding 		.type = ESMART_LAYER,
6274452afb13SDamon Ding 		.win_sel_port_offset = 10,
6275452afb13SDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
6276452afb13SDamon Ding 		.reg_offset = 0x200,
6277452afb13SDamon Ding 		.axi_id = 0,
6278452afb13SDamon Ding 		.axi_yrgb_id = 0x04,
6279452afb13SDamon Ding 		.axi_uv_id = 0x05,
6280452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6281452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6282452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6283452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6284452afb13SDamon Ding 		.max_upscale_factor = 8,
6285452afb13SDamon Ding 		.max_downscale_factor = 8,
6286452afb13SDamon Ding 	},
6287452afb13SDamon Ding 
6288452afb13SDamon Ding 	{
6289452afb13SDamon Ding 		.name = "Esmart2",
6290452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
6291452afb13SDamon Ding 		.type = ESMART_LAYER,
6292452afb13SDamon Ding 		.win_sel_port_offset = 12,
6293452afb13SDamon Ding 		.layer_sel_win_id = { 2, 2, 0xff, 0xff },
6294452afb13SDamon Ding 		.reg_offset = 0x400,
6295452afb13SDamon Ding 		.axi_id = 0,
6296452afb13SDamon Ding 		.axi_yrgb_id = 0x06,
6297452afb13SDamon Ding 		.axi_uv_id = 0x07,
6298452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6299452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6300452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6301452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6302452afb13SDamon Ding 		.max_upscale_factor = 8,
6303452afb13SDamon Ding 		.max_downscale_factor = 8,
6304452afb13SDamon Ding 	},
6305452afb13SDamon Ding 
6306452afb13SDamon Ding 	{
6307452afb13SDamon Ding 		.name = "Esmart3",
6308452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
6309452afb13SDamon Ding 		.type = ESMART_LAYER,
6310452afb13SDamon Ding 		.win_sel_port_offset = 14,
6311452afb13SDamon Ding 		.layer_sel_win_id = { 3, 3, 0xff, 0xff },
6312452afb13SDamon Ding 		.reg_offset = 0x600,
6313452afb13SDamon Ding 		.axi_id = 0,
6314452afb13SDamon Ding 		.axi_yrgb_id = 0x08,
6315452afb13SDamon Ding 		.axi_uv_id = 0x0d,
6316452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6317452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6318452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6319452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6320452afb13SDamon Ding 		.max_upscale_factor = 8,
6321452afb13SDamon Ding 		.max_downscale_factor = 8,
6322452afb13SDamon Ding 	},
6323452afb13SDamon Ding };
6324452afb13SDamon Ding 
6325452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = {
6326452afb13SDamon Ding 	{
6327452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6328452afb13SDamon Ding 		.max_output = {2048, 4096},
6329452afb13SDamon Ding 		.win_dly = 8,
6330452afb13SDamon Ding 		.layer_mix_dly = 8,
6331452afb13SDamon Ding 	},
6332452afb13SDamon Ding 	{
6333452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6334452afb13SDamon Ding 		.max_output = {2048, 1080},
6335452afb13SDamon Ding 		.win_dly = 8,
6336452afb13SDamon Ding 		.layer_mix_dly = 8,
6337452afb13SDamon Ding 	},
6338452afb13SDamon Ding };
6339452afb13SDamon Ding 
6340452afb13SDamon Ding const struct vop2_data rk3562_vop = {
6341452afb13SDamon Ding 	.version = VOP_VERSION_RK3562,
6342452afb13SDamon Ding 	.nr_vps = 2,
6343452afb13SDamon Ding 	.vp_data = rk3562_vp_data,
6344452afb13SDamon Ding 	.win_data = rk3562_win_data,
6345452afb13SDamon Ding 	.plane_mask = rk3562_vp_plane_mask[0],
6346452afb13SDamon Ding 	.plane_table = rk3562_plane_table,
6347452afb13SDamon Ding 	.vp_primary_plane_order = rk3562_vp_primary_plane_order,
6348452afb13SDamon Ding 	.nr_layers = 4,
6349452afb13SDamon Ding 	.nr_mixers = 3,
6350452afb13SDamon Ding 	.nr_gammas = 2,
6351452afb13SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE,
635272388c26SDamon Ding 	.dump_regs = rk3562_dump_regs,
635372388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
635472388c26SDamon Ding };
635572388c26SDamon Ding 
635672388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = {
635772388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
635872388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
635972388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
636072388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
636172388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
636272388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
636372388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
636472388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
636572388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
636672388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
636772388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
636872388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
6369452afb13SDamon Ding };
6370452afb13SDamon Ding 
6371337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
6372337d1c13SDamon Ding 	ROCKCHIP_VOP2_SMART0,
6373337d1c13SDamon Ding 	ROCKCHIP_VOP2_SMART1,
6374337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6375337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6376337d1c13SDamon Ding };
6377337d1c13SDamon Ding 
6378ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6379ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6380ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6381ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6382ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6383ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
6384ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
6385ee008497SSandy Huang };
6386ee008497SSandy Huang 
6387b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
6388b0989546SSandy Huang 	{ /* one display policy */
6389b0989546SSandy Huang 		{/* main display */
6390b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6391b0989546SSandy Huang 			.attached_layers_nr = 6,
6392b0989546SSandy Huang 			.attached_layers = {
6393b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
6394b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
6395b0989546SSandy Huang 				},
6396b0989546SSandy Huang 		},
6397b0989546SSandy Huang 		{/* second display */},
6398b0989546SSandy Huang 		{/* third  display */},
6399b0989546SSandy Huang 		{/* fourth display */},
6400b0989546SSandy Huang 	},
6401b0989546SSandy Huang 
6402b0989546SSandy Huang 	{ /* two display policy */
6403b0989546SSandy Huang 		{/* main display */
6404b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6405b0989546SSandy Huang 			.attached_layers_nr = 3,
6406b0989546SSandy Huang 			.attached_layers = {
6407b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
6408b0989546SSandy Huang 				},
6409b0989546SSandy Huang 		},
6410b0989546SSandy Huang 
6411b0989546SSandy Huang 		{/* second display */
6412b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
6413b0989546SSandy Huang 			.attached_layers_nr = 3,
6414b0989546SSandy Huang 			.attached_layers = {
6415b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
6416b0989546SSandy Huang 				},
6417b0989546SSandy Huang 		},
6418b0989546SSandy Huang 		{/* third  display */},
6419b0989546SSandy Huang 		{/* fourth display */},
6420b0989546SSandy Huang 	},
6421b0989546SSandy Huang 
6422b0989546SSandy Huang 	{ /* three display policy */
6423b0989546SSandy Huang 		{/* main display */
6424b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
6425b0989546SSandy Huang 			.attached_layers_nr = 3,
6426b0989546SSandy Huang 			.attached_layers = {
6427b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
6428b0989546SSandy Huang 				},
6429b0989546SSandy Huang 		},
6430b0989546SSandy Huang 
6431b0989546SSandy Huang 		{/* second display */
6432b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
6433b0989546SSandy Huang 			.attached_layers_nr = 2,
6434b0989546SSandy Huang 			.attached_layers = {
6435b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
6436b0989546SSandy Huang 				},
6437b0989546SSandy Huang 		},
6438b0989546SSandy Huang 
6439b0989546SSandy Huang 		{/* third  display */
6440b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
6441b0989546SSandy Huang 			.attached_layers_nr = 1,
6442b0989546SSandy Huang 			.attached_layers = { ROCKCHIP_VOP2_ESMART1 },
6443b0989546SSandy Huang 		},
6444b0989546SSandy Huang 
6445b0989546SSandy Huang 		{/* fourth display */},
6446b0989546SSandy Huang 	},
6447b0989546SSandy Huang 
6448b0989546SSandy Huang 	{/* reserved for four display policy */},
6449b0989546SSandy Huang };
6450b0989546SSandy Huang 
6451b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = {
6452b0989546SSandy Huang 	{
6453b0989546SSandy Huang 		.name = "Cluster0",
6454b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
6455ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6456b0989546SSandy Huang 		.win_sel_port_offset = 0,
64575fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0xff },
6458b0989546SSandy Huang 		.reg_offset = 0,
64595fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
64605fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
64615fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
64625fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
64634c765862SDamon Ding 		.max_upscale_factor = 4,
64644c765862SDamon Ding 		.max_downscale_factor = 4,
6465b0989546SSandy Huang 	},
6466b0989546SSandy Huang 
6467b0989546SSandy Huang 	{
6468b0989546SSandy Huang 		.name = "Cluster1",
6469b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
6470ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
6471b0989546SSandy Huang 		.win_sel_port_offset = 1,
64725fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 0xff },
6473b0989546SSandy Huang 		.reg_offset = 0x200,
64745fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
64755fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
64765fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
64775fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
64784c765862SDamon Ding 		.max_upscale_factor = 4,
64794c765862SDamon Ding 		.max_downscale_factor = 4,
64801c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_CLUSTER0,
64811c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6482b0989546SSandy Huang 	},
6483b0989546SSandy Huang 
6484b0989546SSandy Huang 	{
6485b0989546SSandy Huang 		.name = "Esmart0",
6486b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6487ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6488b0989546SSandy Huang 		.win_sel_port_offset = 4,
64895fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 0xff },
6490b0989546SSandy Huang 		.reg_offset = 0,
64915fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
64925fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
64935fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
64945fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
64954c765862SDamon Ding 		.max_upscale_factor = 8,
64964c765862SDamon Ding 		.max_downscale_factor = 8,
6497b0989546SSandy Huang 	},
6498b0989546SSandy Huang 
6499b0989546SSandy Huang 	{
6500b0989546SSandy Huang 		.name = "Esmart1",
6501b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6502ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
6503b0989546SSandy Huang 		.win_sel_port_offset = 5,
65045fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 0xff },
6505b0989546SSandy Huang 		.reg_offset = 0x200,
65065fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
65075fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
65085fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
65095fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
65104c765862SDamon Ding 		.max_upscale_factor = 8,
65114c765862SDamon Ding 		.max_downscale_factor = 8,
65121c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_ESMART0,
65131c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6514b0989546SSandy Huang 	},
6515b0989546SSandy Huang 
6516b0989546SSandy Huang 	{
6517b0989546SSandy Huang 		.name = "Smart0",
6518b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART0,
6519ecc31b6eSAndy Yan 		.type = SMART_LAYER,
6520b0989546SSandy Huang 		.win_sel_port_offset = 6,
65215fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 0xff },
6522b0989546SSandy Huang 		.reg_offset = 0x400,
65235fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
65245fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
65255fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
65265fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
65274c765862SDamon Ding 		.max_upscale_factor = 8,
65284c765862SDamon Ding 		.max_downscale_factor = 8,
6529b0989546SSandy Huang 	},
6530b0989546SSandy Huang 
6531b0989546SSandy Huang 	{
6532b0989546SSandy Huang 		.name = "Smart1",
6533b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART1,
6534ecc31b6eSAndy Yan 		.type = SMART_LAYER,
6535b0989546SSandy Huang 		.win_sel_port_offset = 7,
65365fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 0xff },
6537b0989546SSandy Huang 		.reg_offset = 0x600,
65385fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
65395fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
65405fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
65415fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
65424c765862SDamon Ding 		.max_upscale_factor = 8,
65434c765862SDamon Ding 		.max_downscale_factor = 8,
65441c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_SMART0,
65451c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
6546b0989546SSandy Huang 	},
6547b0989546SSandy Huang };
6548b0989546SSandy Huang 
654963cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = {
655063cb669fSSandy Huang 	{
655163cb669fSSandy Huang 		.feature = VOP_FEATURE_OUTPUT_10BIT,
655263cb669fSSandy Huang 		.pre_scan_max_dly = 42,
655363cb669fSSandy Huang 		.max_output = {4096, 2304},
6554d0408543SAndy Yan 	},
655563cb669fSSandy Huang 	{
655663cb669fSSandy Huang 		.feature = 0,
655763cb669fSSandy Huang 		.pre_scan_max_dly = 40,
655863cb669fSSandy Huang 		.max_output = {2048, 1536},
655963cb669fSSandy Huang 	},
656063cb669fSSandy Huang 	{
656163cb669fSSandy Huang 		.feature = 0,
656263cb669fSSandy Huang 		.pre_scan_max_dly = 40,
656363cb669fSSandy Huang 		.max_output = {1920, 1080},
656463cb669fSSandy Huang 	},
656563cb669fSSandy Huang };
6566d0408543SAndy Yan 
656763cb669fSSandy Huang const struct vop2_data rk3568_vop = {
6568ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3568,
656963cb669fSSandy Huang 	.nr_vps = 3,
657063cb669fSSandy Huang 	.vp_data = rk3568_vp_data,
6571b0989546SSandy Huang 	.win_data = rk3568_win_data,
6572b0989546SSandy Huang 	.plane_mask = rk356x_vp_plane_mask[0],
6573ee008497SSandy Huang 	.plane_table = rk356x_plane_table,
6574337d1c13SDamon Ding 	.vp_primary_plane_order = rk3568_vp_primary_plane_order,
6575d0408543SAndy Yan 	.nr_layers = 6,
657663cb669fSSandy Huang 	.nr_mixers = 5,
65771147facaSSandy Huang 	.nr_gammas = 1,
657872388c26SDamon Ding 	.dump_regs = rk3568_dump_regs,
657972388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3568_dump_regs),
6580d0408543SAndy Yan };
6581d0408543SAndy Yan 
6582a552a69cSDamon Ding static u8 rk3576_vp_default_primary_plane[VOP2_VP_MAX] = {
6583a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6584a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6585a552a69cSDamon Ding 	ROCKCHIP_VOP2_ESMART2,
6586a552a69cSDamon Ding };
6587a552a69cSDamon Ding 
6588a552a69cSDamon Ding static struct vop2_plane_table rk3576_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6589a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6590a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6591a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
6592a552a69cSDamon Ding 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
6593a552a69cSDamon Ding 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6594a552a69cSDamon Ding 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6595a552a69cSDamon Ding };
6596a552a69cSDamon Ding 
6597a552a69cSDamon Ding static struct vop2_dump_regs rk3576_dump_regs[] = {
6598a552a69cSDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 },
6599a552a69cSDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 },
6600a552a69cSDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 },
6601a552a69cSDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 },
6602a552a69cSDamon Ding 	{ RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 },
6603a552a69cSDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6604a552a69cSDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6605a552a69cSDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
6606a552a69cSDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
6607a552a69cSDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
6608a552a69cSDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 },
6609a552a69cSDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 },
6610a552a69cSDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 },
6611a552a69cSDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 },
6612a552a69cSDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 },
6613a552a69cSDamon Ding };
6614a552a69cSDamon Ding 
6615a552a69cSDamon Ding /*
6616a552a69cSDamon Ding  * RK3576 VOP with 2 Cluster win and 4 Esmart win.
6617a552a69cSDamon Ding  * Every Esmart win support 4 multi-region.
6618a552a69cSDamon Ding  * VP0 can use Cluster0/1 and Esmart0/2
6619a552a69cSDamon Ding  * VP1 can use Cluster0/1 and Esmart1/3
6620a552a69cSDamon Ding  * VP2 can use Esmart0/1/2/3
6621a552a69cSDamon Ding  *
6622a552a69cSDamon Ding  * Scale filter mode:
6623a552a69cSDamon Ding  *
6624a552a69cSDamon Ding  * * Cluster:
6625a552a69cSDamon Ding  * * Support prescale down:
6626a552a69cSDamon Ding  * * H/V: gt2/avg2 or gt4/avg4
6627a552a69cSDamon Ding  * * After prescale down:
6628a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/multi-phase filter for scale up
6629a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/multi-phase filter for scale down
6630a552a69cSDamon Ding  *
6631a552a69cSDamon Ding  * * Esmart:
6632a552a69cSDamon Ding  * * Support prescale down:
6633a552a69cSDamon Ding  * * H: gt2/avg2 or gt4/avg4
6634a552a69cSDamon Ding  * * V: gt2 or gt4
6635a552a69cSDamon Ding  * * After prescale down:
6636a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/bicubic for scale up
6637a552a69cSDamon Ding  *	* nearest-neighbor/bilinear for scale down
6638cc517d73SDamon Ding  *
6639cc517d73SDamon Ding  * AXI config::
6640cc517d73SDamon Ding  *
6641cc517d73SDamon Ding  * * Cluster0 win0: 0xa,  0xb       [AXI0]
6642cc517d73SDamon Ding  * * Cluster0 win1: 0xc,  0xd       [AXI0]
6643cc517d73SDamon Ding  * * Cluster1 win0: 0x6,  0x7       [AXI0]
6644cc517d73SDamon Ding  * * Cluster1 win1: 0x8,  0x9       [AXI0]
6645cc517d73SDamon Ding  * * Esmart0:       0x10, 0x11      [AXI0]
6646cc517d73SDamon Ding  * * Esmart1:       0x12, 0x13      [AXI0]
6647cc517d73SDamon Ding  * * Esmart2:       0xa,  0xb       [AXI1]
6648cc517d73SDamon Ding  * * Esmart3:       0xc,  0xd       [AXI1]
6649cc517d73SDamon Ding  * * Lut dma rid:   0x1,  0x2,  0x3 [AXI0]
6650cc517d73SDamon Ding  * * DCI dma rid:   0x4             [AXI0]
6651cc517d73SDamon Ding  * * Metadata rid:  0x5             [AXI0]
6652cc517d73SDamon Ding  *
6653cc517d73SDamon Ding  * * Limit:
6654cc517d73SDamon Ding  * * (1) 0x0 and 0xf can't be used;
6655cc517d73SDamon Ding  * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf,
6656cc517d73SDamon Ding  * * VOP will dead at the system bandwidth very terrible scene.
6657a552a69cSDamon Ding  */
6658a552a69cSDamon Ding static struct vop2_win_data rk3576_win_data[6] = {
6659a552a69cSDamon Ding 	{
6660a552a69cSDamon Ding 		.name = "Esmart0",
6661a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6662a552a69cSDamon Ding 		.type = ESMART_LAYER,
6663a552a69cSDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0, 0xff },
6664a552a69cSDamon Ding 		.reg_offset = 0x0,
6665a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6666a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6667a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6668a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6669a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6670a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6671a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6672a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6673a552a69cSDamon Ding 		.axi_id = 0,
6674cc517d73SDamon Ding 		.axi_yrgb_id = 0x10,
6675cc517d73SDamon Ding 		.axi_uv_id = 0x11,
6676a552a69cSDamon Ding 		.possible_crtcs = 0x5,/* vp0 or vp2 */
6677a552a69cSDamon Ding 		.max_upscale_factor = 8,
6678a552a69cSDamon Ding 		.max_downscale_factor = 8,
6679a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH,
6680a552a69cSDamon Ding 	},
6681a552a69cSDamon Ding 	{
6682a552a69cSDamon Ding 		.name = "Esmart1",
6683a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6684a552a69cSDamon Ding 		.type = ESMART_LAYER,
6685a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 2, 1, 0xff },
6686a552a69cSDamon Ding 		.reg_offset = 0x200,
6687a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6688a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6689a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6690a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6691a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6692a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6693a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6694a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6695a552a69cSDamon Ding 		.axi_id = 0,
6696cc517d73SDamon Ding 		.axi_yrgb_id = 0x12,
6697cc517d73SDamon Ding 		.axi_uv_id = 0x13,
6698a552a69cSDamon Ding 		.possible_crtcs = 0x6,/* vp1 or vp2 */
6699a552a69cSDamon Ding 		.max_upscale_factor = 8,
6700a552a69cSDamon Ding 		.max_downscale_factor = 8,
6701a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6702a552a69cSDamon Ding 	},
6703a552a69cSDamon Ding 
6704a552a69cSDamon Ding 	{
6705a552a69cSDamon Ding 		.name = "Esmart2",
6706a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
6707a552a69cSDamon Ding 		.type = ESMART_LAYER,
6708a552a69cSDamon Ding 		.layer_sel_win_id = { 3, 0xff, 2, 0xff },
6709a552a69cSDamon Ding 		.reg_offset = 0x400,
6710a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6711a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6712a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6713a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6714a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6715a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6716a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6717a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6718a552a69cSDamon Ding 		.axi_id = 1,
6719a552a69cSDamon Ding 		.axi_yrgb_id = 0x0a,
6720a552a69cSDamon Ding 		.axi_uv_id = 0x0b,
6721a552a69cSDamon Ding 		.possible_crtcs = 0x5,/* vp0 or vp2 */
6722a552a69cSDamon Ding 		.max_upscale_factor = 8,
6723a552a69cSDamon Ding 		.max_downscale_factor = 8,
6724a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6725a552a69cSDamon Ding 	},
6726a552a69cSDamon Ding 
6727a552a69cSDamon Ding 	{
6728a552a69cSDamon Ding 		.name = "Esmart3",
6729a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
6730a552a69cSDamon Ding 		.type = ESMART_LAYER,
6731a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 3, 3, 0xff },
6732a552a69cSDamon Ding 		.reg_offset = 0x600,
6733a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
6734a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6735a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6736a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6737a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6738a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6739a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
6740a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
6741a552a69cSDamon Ding 		.axi_id = 1,
6742a552a69cSDamon Ding 		.axi_yrgb_id = 0x0c,
6743a552a69cSDamon Ding 		.axi_uv_id = 0x0d,
6744a552a69cSDamon Ding 		.possible_crtcs = 0x6,/* vp1 or vp2 */
6745a552a69cSDamon Ding 		.max_upscale_factor = 8,
6746a552a69cSDamon Ding 		.max_downscale_factor = 8,
6747a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
6748a552a69cSDamon Ding 	},
6749a552a69cSDamon Ding 
6750a552a69cSDamon Ding 	{
6751a552a69cSDamon Ding 		.name = "Cluster0",
6752a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
6753a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
6754a552a69cSDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
6755a552a69cSDamon Ding 		.reg_offset = 0x0,
6756a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
6757a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
6758a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6759a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6760a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6761a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6762a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6763a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
6764cc517d73SDamon Ding 		.axi_yrgb_id = 0x0a,
6765cc517d73SDamon Ding 		.axi_uv_id = 0x0b,
6766a552a69cSDamon Ding 		.possible_crtcs = 0x3,/* vp0 or vp1 */
6767a552a69cSDamon Ding 		.max_upscale_factor = 8,
6768a552a69cSDamon Ding 		.max_downscale_factor = 8,
6769a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
6770a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI,
6771a552a69cSDamon Ding 	},
6772a552a69cSDamon Ding 
6773a552a69cSDamon Ding 	{
6774a552a69cSDamon Ding 		.name = "Cluster1",
6775a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
6776a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
6777a552a69cSDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
6778a552a69cSDamon Ding 		.reg_offset = 0x200,
6779a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
6780a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
6781a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6782a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6783a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6784a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6785a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
6786a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
6787a552a69cSDamon Ding 		.axi_yrgb_id = 0x06,
6788a552a69cSDamon Ding 		.axi_uv_id = 0x07,
6789a552a69cSDamon Ding 		.possible_crtcs = 0x3,/* vp0 or vp1 */
6790a552a69cSDamon Ding 		.max_upscale_factor = 8,
6791a552a69cSDamon Ding 		.max_downscale_factor = 8,
6792a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
6793a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH,
6794a552a69cSDamon Ding 	},
6795a552a69cSDamon Ding };
6796a552a69cSDamon Ding 
679744b1b62cSDamon Ding /*
679844b1b62cSDamon Ding  * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4,
679944b1b62cSDamon Ding  * the urgency signal will be set to 1, when full post line buffer is over 6, the
680044b1b62cSDamon Ding  * urgency signal will be set to 0.
680144b1b62cSDamon Ding  */
680244b1b62cSDamon Ding static struct vop_urgency rk3576_vp0_urgency = {
680344b1b62cSDamon Ding 	.urgen_thl = 4,
680444b1b62cSDamon Ding 	.urgen_thh = 6,
680544b1b62cSDamon Ding };
680644b1b62cSDamon Ding 
6807a552a69cSDamon Ding static struct vop2_vp_data rk3576_vp_data[3] = {
6808a552a69cSDamon Ding 	{
6809a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR |
6810a552a69cSDamon Ding 			   VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT |
6811a552a69cSDamon Ding 			   VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP,
6812a552a69cSDamon Ding 		.max_output = { 4096, 4096 },
6813a552a69cSDamon Ding 		.hdrvivid_dly = 21,
6814a552a69cSDamon Ding 		.sdr2hdr_dly = 21,
6815a552a69cSDamon Ding 		.layer_mix_dly = 8,
6816a552a69cSDamon Ding 		.hdr_mix_dly = 2,
6817a552a69cSDamon Ding 		.win_dly = 10,
6818a552a69cSDamon Ding 		.pixel_rate = 2,
681944b1b62cSDamon Ding 		.urgency = &rk3576_vp0_urgency,
6820a552a69cSDamon Ding 	},
6821a552a69cSDamon Ding 	{
6822a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN |
6823a552a69cSDamon Ding 			   VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2,
6824a552a69cSDamon Ding 		.max_output = { 2560, 2560 },
6825a552a69cSDamon Ding 		.hdrvivid_dly = 0,
6826a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
6827a552a69cSDamon Ding 		.layer_mix_dly = 6,
6828a552a69cSDamon Ding 		.hdr_mix_dly = 0,
6829a552a69cSDamon Ding 		.win_dly = 10,
6830a552a69cSDamon Ding 		.pixel_rate = 1,
6831a552a69cSDamon Ding 	},
6832a552a69cSDamon Ding 	{
6833a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6834a552a69cSDamon Ding 		.max_output = { 1920, 1920 },
6835a552a69cSDamon Ding 		.hdrvivid_dly = 0,
6836a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
6837a552a69cSDamon Ding 		.layer_mix_dly = 6,
6838a552a69cSDamon Ding 		.hdr_mix_dly = 0,
6839a552a69cSDamon Ding 		.win_dly = 10,
6840a552a69cSDamon Ding 		.pixel_rate = 1,
6841a552a69cSDamon Ding 	},
6842a552a69cSDamon Ding };
6843a552a69cSDamon Ding 
6844a552a69cSDamon Ding static struct vop2_power_domain_data rk3576_vop_pd_data[] = {
6845a552a69cSDamon Ding 	{
6846a552a69cSDamon Ding 		.id = VOP2_PD_CLUSTER,
6847a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1),
6848a552a69cSDamon Ding 	},
6849a552a69cSDamon Ding 	{
6850a552a69cSDamon Ding 		.id = VOP2_PD_ESMART,
6851a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) |
6852a552a69cSDamon Ding 				  BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3),
6853a552a69cSDamon Ding 	},
6854a552a69cSDamon Ding };
6855a552a69cSDamon Ding 
6856a552a69cSDamon Ding static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = {
6857a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_4K_MODE, 2},
6858a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_2K_2K_MODE, 3}
6859a552a69cSDamon Ding };
6860a552a69cSDamon Ding 
6861a552a69cSDamon Ding const struct vop2_data rk3576_vop = {
6862a552a69cSDamon Ding 	.version = VOP_VERSION_RK3576,
6863a552a69cSDamon Ding 	.nr_vps = 3,
6864a552a69cSDamon Ding 	.nr_mixers = 4,
6865a552a69cSDamon Ding 	.nr_layers = 6,
6866a552a69cSDamon Ding 	.nr_gammas = 3,
6867a552a69cSDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE,
6868a552a69cSDamon Ding 	.esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map),
6869a552a69cSDamon Ding 	.esmart_lb_mode_map = rk3576_esmart_lb_mode_map,
6870a552a69cSDamon Ding 	.vp_data = rk3576_vp_data,
6871a552a69cSDamon Ding 	.win_data = rk3576_win_data,
6872a552a69cSDamon Ding 	.plane_table = rk3576_plane_table,
6873a552a69cSDamon Ding 	.pd = rk3576_vop_pd_data,
6874a552a69cSDamon Ding 	.vp_default_primary_plane = rk3576_vp_default_primary_plane,
6875a552a69cSDamon Ding 	.nr_pd = ARRAY_SIZE(rk3576_vop_pd_data),
6876a552a69cSDamon Ding 	.dump_regs = rk3576_dump_regs,
6877a552a69cSDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3576_dump_regs),
6878a552a69cSDamon Ding };
6879a552a69cSDamon Ding 
6880337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
6881337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART0,
6882337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART1,
6883337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART2,
6884337d1c13SDamon Ding 	ROCKCHIP_VOP2_ESMART3,
6885337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER0,
6886337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER1,
6887337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER2,
6888337d1c13SDamon Ding 	ROCKCHIP_VOP2_CLUSTER3,
6889337d1c13SDamon Ding };
6890337d1c13SDamon Ding 
6891ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
6892ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
6893ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
6894ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER},
6895ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER},
6896ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
6897ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
6898ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
6899ecc31b6eSAndy Yan 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
6900ecc31b6eSAndy Yan };
6901ecc31b6eSAndy Yan 
690272388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = {
690372388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
690472388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
690572388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
690672388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
690772388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
690872388c26SDamon Ding 	{ RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 },
690972388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
691072388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
691172388c26SDamon Ding 	{ RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 },
691272388c26SDamon Ding 	{ RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 },
691372388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
691472388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
691572388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
691672388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
691772388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
691872388c26SDamon Ding };
691972388c26SDamon Ding 
6920ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
6921ecc31b6eSAndy Yan 	{ /* one display policy */
6922ecc31b6eSAndy Yan 		{/* main display */
6923608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6924ecc31b6eSAndy Yan 			.attached_layers_nr = 8,
6925ecc31b6eSAndy Yan 			.attached_layers = {
6926ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2,
6927ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3,
6928ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3
6929ecc31b6eSAndy Yan 			},
6930ecc31b6eSAndy Yan 		},
6931ecc31b6eSAndy Yan 		{/* second display */},
6932ecc31b6eSAndy Yan 		{/* third  display */},
6933ecc31b6eSAndy Yan 		{/* fourth display */},
6934ecc31b6eSAndy Yan 	},
6935ecc31b6eSAndy Yan 
6936ecc31b6eSAndy Yan 	{ /* two display policy */
6937ecc31b6eSAndy Yan 		{/* main display */
6938608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6939ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
6940ecc31b6eSAndy Yan 			.attached_layers = {
6941ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
6942ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1
6943ecc31b6eSAndy Yan 			},
6944ecc31b6eSAndy Yan 		},
6945ecc31b6eSAndy Yan 
6946ecc31b6eSAndy Yan 		{/* second display */
6947608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6948ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
6949ecc31b6eSAndy Yan 			.attached_layers = {
6950ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2,
6951ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
6952ecc31b6eSAndy Yan 			},
6953ecc31b6eSAndy Yan 		},
6954ecc31b6eSAndy Yan 		{/* third  display */},
6955ecc31b6eSAndy Yan 		{/* fourth display */},
6956ecc31b6eSAndy Yan 	},
6957ecc31b6eSAndy Yan 
6958ecc31b6eSAndy Yan 	{ /* three display policy */
6959ecc31b6eSAndy Yan 		{/* main display */
6960608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6961ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
6962ecc31b6eSAndy Yan 			.attached_layers = {
6963ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0
6964ecc31b6eSAndy Yan 			},
6965ecc31b6eSAndy Yan 		},
6966ecc31b6eSAndy Yan 
6967ecc31b6eSAndy Yan 		{/* second display */
6968608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
6969ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
6970ecc31b6eSAndy Yan 			.attached_layers = {
6971ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1
6972ecc31b6eSAndy Yan 			},
6973ecc31b6eSAndy Yan 		},
6974ecc31b6eSAndy Yan 
6975ecc31b6eSAndy Yan 		{/* third  display */
6976ecc31b6eSAndy Yan 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6977ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6978ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
6979ecc31b6eSAndy Yan 		},
6980ecc31b6eSAndy Yan 
6981ecc31b6eSAndy Yan 		{/* fourth display */},
6982ecc31b6eSAndy Yan 	},
6983ecc31b6eSAndy Yan 
6984ecc31b6eSAndy Yan 	{ /* four display policy */
6985ecc31b6eSAndy Yan 		{/* main display */
6986608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
6987ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6988ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
6989ecc31b6eSAndy Yan 		},
6990ecc31b6eSAndy Yan 
6991ecc31b6eSAndy Yan 		{/* second display */
6992608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
6993ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
6994ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
6995ecc31b6eSAndy Yan 		},
6996ecc31b6eSAndy Yan 
6997ecc31b6eSAndy Yan 		{/* third  display */
6998608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
6999ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7000ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
7001ecc31b6eSAndy Yan 		},
7002ecc31b6eSAndy Yan 
7003ecc31b6eSAndy Yan 		{/* fourth display */
7004608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
7005ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7006ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
7007ecc31b6eSAndy Yan 		},
7008ecc31b6eSAndy Yan 	},
7009ecc31b6eSAndy Yan 
7010ecc31b6eSAndy Yan };
7011ecc31b6eSAndy Yan 
7012ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = {
7013ecc31b6eSAndy Yan 	{
7014ecc31b6eSAndy Yan 		.name = "Cluster0",
7015ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
7016ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER1,
7017ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7018ecc31b6eSAndy Yan 		.win_sel_port_offset = 0,
70195fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0 },
7020ecc31b6eSAndy Yan 		.reg_offset = 0,
7021a33b790fSDamon Ding 		.axi_id = 0,
7022a33b790fSDamon Ding 		.axi_yrgb_id = 2,
7023a33b790fSDamon Ding 		.axi_uv_id = 3,
7024b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER0,
70255fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
70265fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70275fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
70285fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70294c765862SDamon Ding 		.max_upscale_factor = 4,
70304c765862SDamon Ding 		.max_downscale_factor = 4,
7031ecc31b6eSAndy Yan 	},
7032ecc31b6eSAndy Yan 
7033ecc31b6eSAndy Yan 	{
7034ecc31b6eSAndy Yan 		.name = "Cluster1",
7035ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
7036ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7037ecc31b6eSAndy Yan 		.win_sel_port_offset = 1,
70385fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 1 },
7039ecc31b6eSAndy Yan 		.reg_offset = 0x200,
7040a33b790fSDamon Ding 		.axi_id = 0,
7041a33b790fSDamon Ding 		.axi_yrgb_id = 6,
7042a33b790fSDamon Ding 		.axi_uv_id = 7,
7043b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER1,
70445fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
70455fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70465fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
70475fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70484c765862SDamon Ding 		.max_upscale_factor = 4,
70494c765862SDamon Ding 		.max_downscale_factor = 4,
7050ecc31b6eSAndy Yan 	},
7051ecc31b6eSAndy Yan 
7052ecc31b6eSAndy Yan 	{
7053ecc31b6eSAndy Yan 		.name = "Cluster2",
7054ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
7055ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
7056ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7057ecc31b6eSAndy Yan 		.win_sel_port_offset = 2,
70585fa6e665SDamon Ding 		.layer_sel_win_id = { 4, 4, 4, 4 },
7059ecc31b6eSAndy Yan 		.reg_offset = 0x400,
7060a33b790fSDamon Ding 		.axi_id = 1,
7061a33b790fSDamon Ding 		.axi_yrgb_id = 2,
7062a33b790fSDamon Ding 		.axi_uv_id = 3,
7063b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER2,
70645fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
70655fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70665fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
70675fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70684c765862SDamon Ding 		.max_upscale_factor = 4,
70694c765862SDamon Ding 		.max_downscale_factor = 4,
7070ecc31b6eSAndy Yan 	},
7071ecc31b6eSAndy Yan 
7072ecc31b6eSAndy Yan 	{
7073ecc31b6eSAndy Yan 		.name = "Cluster3",
7074ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
7075ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
7076ecc31b6eSAndy Yan 		.win_sel_port_offset = 3,
70775fa6e665SDamon Ding 		.layer_sel_win_id = { 5, 5, 5, 5 },
7078ecc31b6eSAndy Yan 		.reg_offset = 0x600,
7079a33b790fSDamon Ding 		.axi_id = 1,
7080a33b790fSDamon Ding 		.axi_yrgb_id = 6,
7081a33b790fSDamon Ding 		.axi_uv_id = 7,
7082b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER3,
70835fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
70845fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70855fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
70865fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
70874c765862SDamon Ding 		.max_upscale_factor = 4,
70884c765862SDamon Ding 		.max_downscale_factor = 4,
7089ecc31b6eSAndy Yan 	},
7090ecc31b6eSAndy Yan 
7091ecc31b6eSAndy Yan 	{
7092ecc31b6eSAndy Yan 		.name = "Esmart0",
7093ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART0,
7094ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART1,
7095ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7096ecc31b6eSAndy Yan 		.win_sel_port_offset = 4,
70975fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 2 },
7098ecc31b6eSAndy Yan 		.reg_offset = 0,
7099a33b790fSDamon Ding 		.axi_id = 0,
7100a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
7101a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
71025fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71035fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71045fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71055fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71064c765862SDamon Ding 		.max_upscale_factor = 8,
71074c765862SDamon Ding 		.max_downscale_factor = 8,
7108ecc31b6eSAndy Yan 	},
7109ecc31b6eSAndy Yan 
7110ecc31b6eSAndy Yan 	{
7111ecc31b6eSAndy Yan 		.name = "Esmart1",
7112ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART1,
7113ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7114ecc31b6eSAndy Yan 		.win_sel_port_offset = 5,
71155fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 3 },
7116ecc31b6eSAndy Yan 		.reg_offset = 0x200,
7117a33b790fSDamon Ding 		.axi_id = 0,
7118a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
7119a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
7120b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
71215fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71225fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71235fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71245fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71254c765862SDamon Ding 		.max_upscale_factor = 8,
71264c765862SDamon Ding 		.max_downscale_factor = 8,
7127ecc31b6eSAndy Yan 	},
7128ecc31b6eSAndy Yan 
7129ecc31b6eSAndy Yan 	{
7130ecc31b6eSAndy Yan 		.name = "Esmart2",
7131ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART2,
7132ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART3,
7133ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7134ecc31b6eSAndy Yan 		.win_sel_port_offset = 6,
71355fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 6 },
7136ecc31b6eSAndy Yan 		.reg_offset = 0x400,
7137a33b790fSDamon Ding 		.axi_id = 1,
7138a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
7139a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
7140b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
71415fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71425fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71435fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71445fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71454c765862SDamon Ding 		.max_upscale_factor = 8,
71464c765862SDamon Ding 		.max_downscale_factor = 8,
7147ecc31b6eSAndy Yan 	},
7148ecc31b6eSAndy Yan 
7149ecc31b6eSAndy Yan 	{
7150ecc31b6eSAndy Yan 		.name = "Esmart3",
7151ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART3,
7152ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
7153ecc31b6eSAndy Yan 		.win_sel_port_offset = 7,
71545fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 7 },
7155ecc31b6eSAndy Yan 		.reg_offset = 0x600,
7156a33b790fSDamon Ding 		.axi_id = 1,
7157a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
7158a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
7159b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
71605fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71615fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71625fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71635fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71644c765862SDamon Ding 		.max_upscale_factor = 8,
71654c765862SDamon Ding 		.max_downscale_factor = 8,
7166ecc31b6eSAndy Yan 	},
7167ecc31b6eSAndy Yan };
7168ecc31b6eSAndy Yan 
716912ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = {
717012ee5af0SDamon Ding 	{0x00000000, "no error detected by DSC encoder"},
717112ee5af0SDamon Ding 	{0x0030ffff, "bits per component error"},
717212ee5af0SDamon Ding 	{0x0040ffff, "multiple mode error"},
717312ee5af0SDamon Ding 	{0x0050ffff, "line buffer depth error"},
717412ee5af0SDamon Ding 	{0x0060ffff, "minor version error"},
717512ee5af0SDamon Ding 	{0x0070ffff, "picture height error"},
717612ee5af0SDamon Ding 	{0x0080ffff, "picture width error"},
717712ee5af0SDamon Ding 	{0x0090ffff, "number of slices error"},
717812ee5af0SDamon Ding 	{0x00c0ffff, "slice height Error "},
717912ee5af0SDamon Ding 	{0x00d0ffff, "slice width error"},
718012ee5af0SDamon Ding 	{0x00e0ffff, "second line BPG offset error"},
718112ee5af0SDamon Ding 	{0x00f0ffff, "non second line BPG offset error"},
718212ee5af0SDamon Ding 	{0x0100ffff, "PPS ID error"},
718312ee5af0SDamon Ding 	{0x0110ffff, "bits per pixel (BPP) Error"},
718412ee5af0SDamon Ding 	{0x0120ffff, "buffer flow error"},  /* dsc_buffer_flow */
718512ee5af0SDamon Ding 
718612ee5af0SDamon Ding 	{0x01510001, "slice 0 RC buffer model overflow error"},
718712ee5af0SDamon Ding 	{0x01510002, "slice 1 RC buffer model overflow error"},
718812ee5af0SDamon Ding 	{0x01510004, "slice 2 RC buffer model overflow error"},
718912ee5af0SDamon Ding 	{0x01510008, "slice 3 RC buffer model overflow error"},
719012ee5af0SDamon Ding 	{0x01510010, "slice 4 RC buffer model overflow error"},
719112ee5af0SDamon Ding 	{0x01510020, "slice 5 RC buffer model overflow error"},
719212ee5af0SDamon Ding 	{0x01510040, "slice 6 RC buffer model overflow error"},
719312ee5af0SDamon Ding 	{0x01510080, "slice 7 RC buffer model overflow error"},
719412ee5af0SDamon Ding 
719512ee5af0SDamon Ding 	{0x01610001, "slice 0 RC buffer model underflow error"},
719612ee5af0SDamon Ding 	{0x01610002, "slice 1 RC buffer model underflow error"},
719712ee5af0SDamon Ding 	{0x01610004, "slice 2 RC buffer model underflow error"},
719812ee5af0SDamon Ding 	{0x01610008, "slice 3 RC buffer model underflow error"},
719912ee5af0SDamon Ding 	{0x01610010, "slice 4 RC buffer model underflow error"},
720012ee5af0SDamon Ding 	{0x01610020, "slice 5 RC buffer model underflow error"},
720112ee5af0SDamon Ding 	{0x01610040, "slice 6 RC buffer model underflow error"},
720212ee5af0SDamon Ding 	{0x01610080, "slice 7 RC buffer model underflow error"},
720312ee5af0SDamon Ding 
720412ee5af0SDamon Ding 	{0xffffffff, "unsuccessful RESET cycle status"},
720512ee5af0SDamon Ding 	{0x00a0ffff, "ICH full error precision settings error"},
720612ee5af0SDamon Ding 	{0x0020ffff, "native mode"},
720712ee5af0SDamon Ding };
720812ee5af0SDamon Ding 
720912ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = {
721012ee5af0SDamon Ding 	{0x00000000, "rate buffer status"},
721112ee5af0SDamon Ding 	{0x00000001, "line buffer status"},
721212ee5af0SDamon Ding 	{0x00000002, "decoder model status"},
721312ee5af0SDamon Ding 	{0x00000003, "pixel buffer status"},
721412ee5af0SDamon Ding 	{0x00000004, "balance fifo buffer status"},
721512ee5af0SDamon Ding 	{0x00000005, "syntax element fifo status"},
721612ee5af0SDamon Ding };
721712ee5af0SDamon Ding 
721812ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = {
721912ee5af0SDamon Ding 	{
722012ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_8K,
722112ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_8K,
722212ee5af0SDamon Ding 		.max_slice_num = 8,
722312ee5af0SDamon Ding 		.max_linebuf_depth = 11,
7224b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
722512ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
722612ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_8k_txp_clk",
722712ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_8k_pxl_clk",
722812ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_8k_cds_clk",
722912ee5af0SDamon Ding 	},
723012ee5af0SDamon Ding 
723112ee5af0SDamon Ding 	{
723212ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_4K,
723312ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_4K,
723412ee5af0SDamon Ding 		.max_slice_num = 2,
723512ee5af0SDamon Ding 		.max_linebuf_depth = 11,
7236b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
723712ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
723812ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_4k_txp_clk",
723912ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_4k_pxl_clk",
724012ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_4k_cds_clk",
724112ee5af0SDamon Ding 	},
724212ee5af0SDamon Ding };
724312ee5af0SDamon Ding 
7244ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = {
7245ecc31b6eSAndy Yan 	{
7246ee01dbb2SDamon Ding 		.splice_vp_id = 1,
7247ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7248b890760eSAlgea Cao 		.pre_scan_max_dly = 54,
7249ecc31b6eSAndy Yan 		.max_dclk = 600000,
7250ecc31b6eSAndy Yan 		.max_output = {7680, 4320},
7251ecc31b6eSAndy Yan 	},
7252ecc31b6eSAndy Yan 	{
7253ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7254ee01dbb2SDamon Ding 		.pre_scan_max_dly = 54,
7255ecc31b6eSAndy Yan 		.max_dclk = 600000,
7256ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
7257ecc31b6eSAndy Yan 	},
7258ecc31b6eSAndy Yan 	{
7259ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7260ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
7261ecc31b6eSAndy Yan 		.max_dclk = 600000,
7262ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
7263ecc31b6eSAndy Yan 	},
7264ecc31b6eSAndy Yan 	{
7265ecc31b6eSAndy Yan 		.feature = 0,
7266ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
7267ecc31b6eSAndy Yan 		.max_dclk = 200000,
7268ecc31b6eSAndy Yan 		.max_output = {1920, 1080},
7269ecc31b6eSAndy Yan 	},
7270ecc31b6eSAndy Yan };
7271ecc31b6eSAndy Yan 
7272b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = {
7273b6ba80b4SDamon Ding 	{
7274b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER0,
7275b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0),
7276b6ba80b4SDamon Ding 	},
7277b6ba80b4SDamon Ding 	{
7278b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER1,
7279b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1),
7280b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7281b6ba80b4SDamon Ding 	},
7282b6ba80b4SDamon Ding 	{
7283b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER2,
7284b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2),
7285b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7286b6ba80b4SDamon Ding 	},
7287b6ba80b4SDamon Ding 	{
7288b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER3,
7289b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3),
7290b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7291b6ba80b4SDamon Ding 	},
7292b6ba80b4SDamon Ding 	{
7293b6ba80b4SDamon Ding 	  .id = VOP2_PD_ESMART,
7294b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) |
7295b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART2) |
7296b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART3),
7297b6ba80b4SDamon Ding 	},
7298b6ba80b4SDamon Ding 	{
7299b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_8K,
7300b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K),
7301b6ba80b4SDamon Ding 	},
7302b6ba80b4SDamon Ding 	{
7303b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_4K,
7304b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K),
7305b6ba80b4SDamon Ding 	},
7306b6ba80b4SDamon Ding };
7307b6ba80b4SDamon Ding 
7308ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = {
7309ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3588,
7310ecc31b6eSAndy Yan 	.nr_vps = 4,
7311ecc31b6eSAndy Yan 	.vp_data = rk3588_vp_data,
7312ecc31b6eSAndy Yan 	.win_data = rk3588_win_data,
7313ecc31b6eSAndy Yan 	.plane_mask = rk3588_vp_plane_mask[0],
7314ecc31b6eSAndy Yan 	.plane_table = rk3588_plane_table,
7315b6ba80b4SDamon Ding 	.pd = rk3588_vop_pd_data,
731612ee5af0SDamon Ding 	.dsc = rk3588_dsc_data,
731712ee5af0SDamon Ding 	.dsc_error_ecw = dsc_ecw,
731812ee5af0SDamon Ding 	.dsc_error_buffer_flow = dsc_buffer_flow,
7319337d1c13SDamon Ding 	.vp_primary_plane_order = rk3588_vp_primary_plane_order,
7320ecc31b6eSAndy Yan 	.nr_layers = 8,
7321ecc31b6eSAndy Yan 	.nr_mixers = 7,
7322ecc31b6eSAndy Yan 	.nr_gammas = 4,
7323b6ba80b4SDamon Ding 	.nr_pd = ARRAY_SIZE(rk3588_vop_pd_data),
732412ee5af0SDamon Ding 	.nr_dscs = 2,
732512ee5af0SDamon Ding 	.nr_dsc_ecw = ARRAY_SIZE(dsc_ecw),
732612ee5af0SDamon Ding 	.nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow),
732772388c26SDamon Ding 	.dump_regs = rk3588_dump_regs,
732872388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3588_dump_regs),
7329ecc31b6eSAndy Yan };
7330ecc31b6eSAndy Yan 
7331d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
7332d0408543SAndy Yan 	.preinit = rockchip_vop2_preinit,
7333d0408543SAndy Yan 	.prepare = rockchip_vop2_prepare,
7334d0408543SAndy Yan 	.init = rockchip_vop2_init,
7335d0408543SAndy Yan 	.set_plane = rockchip_vop2_set_plane,
7336d0408543SAndy Yan 	.enable = rockchip_vop2_enable,
7337efa01fe4SZhang Yubing 	.post_enable = rockchip_vop2_post_enable,
7338d0408543SAndy Yan 	.disable = rockchip_vop2_disable,
7339b0989546SSandy Huang 	.fixup_dts = rockchip_vop2_fixup_dts,
73400675a2a4SDamon Ding 	.send_mcu_cmd = rockchip_vop2_send_mcu_cmd,
7341820a5c17SDamon Ding 	.check = rockchip_vop2_check,
734222007755SDamon Ding 	.mode_valid = rockchip_vop2_mode_valid,
7343b02eb70bSDamon Ding 	.mode_fixup = rockchip_vop2_mode_fixup,
73444c765862SDamon Ding 	.plane_check = rockchip_vop2_plane_check,
734572388c26SDamon Ding 	.regs_dump = rockchip_vop2_regs_dump,
734672388c26SDamon Ding 	.active_regs_dump = rockchip_vop2_active_regs_dump,
73478e7ef808SDamon Ding 	.apply_soft_te = rockchip_vop2_apply_soft_te,
7348d0408543SAndy Yan };
7349