xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_vop2.c (revision 60e6e79d7a046ddb710e589fd559751760c3b206)
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>
33789e70ecSFinley Xiao #include <power-domain.h>
34d0408543SAndy Yan 
35d0408543SAndy Yan #include "rockchip_display.h"
36d0408543SAndy Yan #include "rockchip_crtc.h"
37d0408543SAndy Yan #include "rockchip_connector.h"
38d8e7f4a5SSandy Huang #include "rockchip_phy.h"
396027c871SZhang Yubing #include "rockchip_post_csc.h"
40d0408543SAndy Yan 
41d0408543SAndy Yan /* System registers definition */
42d0408543SAndy Yan #define RK3568_REG_CFG_DONE			0x000
43d0408543SAndy Yan #define	CFG_DONE_EN				BIT(15)
44d0408543SAndy Yan 
45d0408543SAndy Yan #define RK3568_VERSION_INFO			0x004
46d0408543SAndy Yan #define EN_MASK					1
47d0408543SAndy Yan 
4863cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL			0x008
490675a2a4SDamon Ding #define AUTO_GATING_EN_SHIFT			31
500675a2a4SDamon Ding #define PORT_DCLK_AUTO_GATING_EN_SHIFT		14
51bb7ec356SDamon Ding #define ACLK_PRE_AUTO_GATING_EN_SHIFT		7
5263cb669fSSandy Huang 
5344b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL0_IMD		0x014
5444b1b62cSDamon Ding #define AXI0_PORT_URGENCY_EN_SHIFT		24
5544b1b62cSDamon Ding 
5644b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL1_IMD		0x018
5744b1b62cSDamon Ding #define AXI1_PORT_URGENCY_EN_SHIFT		24
5844b1b62cSDamon Ding 
59a552a69cSDamon Ding #define RK3576_SYS_MMU_CTRL			0x020
60a552a69cSDamon Ding #define RKMMU_V2_EN_SHIFT			0
61a552a69cSDamon Ding #define RKMMU_V2_SEL_AXI_SHIFT			1
62a552a69cSDamon Ding 
636414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL			0x024
646414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT			0
65aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT			16
666414e3bcSSandy Huang 
67d0408543SAndy Yan #define RK3568_DSP_IF_EN			0x028
68d0408543SAndy Yan #define RGB_EN_SHIFT				0
69ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT			0
70ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT			1
71ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT			8
72d0408543SAndy Yan #define HDMI0_EN_SHIFT				1
73d0408543SAndy Yan #define EDP0_EN_SHIFT				3
74ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT			2
75ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT			3
76d0408543SAndy Yan #define MIPI0_EN_SHIFT				4
77ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT			4
78ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT			5
79ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT			6
80d0408543SAndy Yan #define MIPI1_EN_SHIFT				20
81ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT			7
82d0408543SAndy Yan #define LVDS0_EN_SHIFT				5
83d0408543SAndy Yan #define LVDS1_EN_SHIFT				24
84d0408543SAndy Yan #define BT1120_EN_SHIFT				6
85d0408543SAndy Yan #define BT656_EN_SHIFT				7
86d0408543SAndy Yan #define IF_MUX_MASK				3
87d0408543SAndy Yan #define RGB_MUX_SHIFT				8
88d0408543SAndy Yan #define HDMI0_MUX_SHIFT				10
89ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT			12
90ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT			14
91d0408543SAndy Yan #define EDP0_MUX_SHIFT				14
92ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT		16
93ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT		18
94d0408543SAndy Yan #define MIPI0_MUX_SHIFT				16
95ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT			20
96d0408543SAndy Yan #define MIPI1_MUX_SHIFT				21
9711f53190SSandy Huang #define LVDS0_MUX_SHIFT				18
98d0408543SAndy Yan #define LVDS1_MUX_SHIFT				25
99d0408543SAndy Yan 
100a552a69cSDamon Ding #define RK3576_SYS_PORT_CTRL			0x028
101a552a69cSDamon Ding #define VP_INTR_MERGE_EN_SHIFT			14
10212ee4de7SDamon Ding #define RK3576_DSP_VS_T_SEL_SHIFT		4
103a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_MASK		0x7
104a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_SHIFT		0
105a552a69cSDamon Ding 
106d0408543SAndy Yan #define RK3568_DSP_IF_CTRL			0x02c
107d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT			0
1085d2768f7SDamon Ding #define RK3588_BT656_UV_SWAP_SHIFT		0
109d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT		1
1105d2768f7SDamon Ding #define RK3588_BT656_YC_SWAP_SHIFT		1
111d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT			2
1125fa6e665SDamon Ding #define BT656_UV_SWAP				4
1135d2768f7SDamon Ding #define RK3588_BT1120_UV_SWAP_SHIFT		4
1145fa6e665SDamon Ding #define BT656_YC_SWAP				5
1155d2768f7SDamon Ding #define RK3588_BT1120_YC_SWAP_SHIFT		5
1165fa6e665SDamon Ding #define BT656_DCLK_POL				6
1170a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT		8
1180a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT		8
1190a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT			9
12041874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT		10
12141874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT		11
12241874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT		12
12341874944SGuochun Huang 
124d0408543SAndy Yan #define RK3568_DSP_IF_POL			0x030
125d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT		28
126d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT		19
127de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_MASK		0x7
128de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_SHIFT		16
129d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT		15
1307bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_MASK		0x7
1317bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_SHIFT		12
132d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT		7
13310ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK		0x7
13410ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT		4
13515f69071SDamon Ding #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT		3
13615f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_MASK		0x7
13715f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT		0
138ecc31b6eSAndy Yan 
139452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT		15
140452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT		12
141452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK			0x7
142452afb13SDamon Ding 
143ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT		8
144ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT		12
145ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK			0x7
146ecc31b6eSAndy Yan 
147ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT		16
148ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT		18
149ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT		20
150ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT		22
151ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT			24
152ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT			26
153ecc31b6eSAndy Yan 
154a552a69cSDamon Ding #define RK3576_SYS_CLUSTER_PD_CTRL		0x030
155a552a69cSDamon Ding #define RK3576_CLUSTER_PD_EN_SHIFT		0
156a552a69cSDamon Ding 
157a552a69cSDamon Ding #define RK3588_SYS_PD_CTRL			0x034
158a552a69cSDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT		0
159a552a69cSDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT		1
160a552a69cSDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT		2
161a552a69cSDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT		3
162a552a69cSDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT		5
163a552a69cSDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT		6
164a552a69cSDamon Ding #define RK3588_ESMART_PD_EN_SHIFT		7
165a552a69cSDamon Ding 
166a552a69cSDamon Ding #define RK3576_SYS_ESMART_PD_CTRL		0x034
167a552a69cSDamon Ding #define RK3576_ESMART_PD_EN_SHIFT		0
168a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_SHIFT		6
169a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_MASK		0x3
170a552a69cSDamon Ding 
171feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN			0x50
172feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT			0
1731147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL			0x58
1741147facaSSandy Huang #define GAMMA_PORT_SEL_MASK			0x3
1751147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT			0
176db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK		0x3
177db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT		12
178ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT			16
1795fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK			0x3
1805fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT		26
1811147facaSSandy Huang 
182d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG			0x70
183d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG			0x74
184d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG			0x78
185d0408543SAndy Yan #define RK3568_SYS0_INT_EN			0x80
186d0408543SAndy Yan #define RK3568_SYS0_INT_CLR			0x84
187d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS			0x88
188d0408543SAndy Yan #define RK3568_SYS1_INT_EN			0x90
189d0408543SAndy Yan #define RK3568_SYS1_INT_CLR			0x94
190d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS			0x98
191d0408543SAndy Yan #define RK3568_VP0_INT_EN			0xA0
192d0408543SAndy Yan #define RK3568_VP0_INT_CLR			0xA4
193d0408543SAndy Yan #define RK3568_VP0_INT_STATUS			0xA8
194d0408543SAndy Yan #define RK3568_VP1_INT_EN			0xB0
195d0408543SAndy Yan #define RK3568_VP1_INT_CLR			0xB4
196d0408543SAndy Yan #define RK3568_VP1_INT_STATUS			0xB8
197d0408543SAndy Yan #define RK3568_VP2_INT_EN			0xC0
198d0408543SAndy Yan #define RK3568_VP2_INT_CLR			0xC4
199d0408543SAndy Yan #define RK3568_VP2_INT_STATUS			0xC8
200a552a69cSDamon Ding #define RK3568_VP2_INT_RAW_STATUS		0xCC
201a552a69cSDamon Ding #define RK3588_VP3_INT_EN			0xD0
202a552a69cSDamon Ding #define RK3588_VP3_INT_CLR			0xD4
203a552a69cSDamon Ding #define RK3588_VP3_INT_STATUS			0xD8
204a552a69cSDamon Ding #define RK3576_WB_CTRL				0x100
205a552a69cSDamon Ding #define RK3576_WB_XSCAL_FACTOR			0x104
206a552a69cSDamon Ding #define RK3576_WB_YRGB_MST			0x108
207a552a69cSDamon Ding #define RK3576_WB_CBR_MST			0x10C
208a552a69cSDamon Ding #define RK3576_WB_VIR_STRIDE			0x110
209a552a69cSDamon Ding #define RK3576_WB_TIMEOUT_CTRL			0x114
210a552a69cSDamon Ding #define RK3576_MIPI0_IF_CTRL			0x180
211a552a69cSDamon Ding #define RK3576_IF_OUT_EN_SHIFT			0
212a552a69cSDamon Ding #define RK3576_IF_CLK_OUT_EN_SHIFT		1
213a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_SHIFT		2
214a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_MASK			0x3
215a552a69cSDamon Ding #define RK3576_IF_PIN_POL_SHIFT			4
216a552a69cSDamon Ding #define RK3576_IF_PIN_POL_MASK			0x7
217a552a69cSDamon Ding #define RK3576_IF_SPLIT_EN_SHIFT		8
218a552a69cSDamon Ding #define RK3576_IF_DATA1_SEL_SHIFT		9
219a552a69cSDamon Ding #define RK3576_MIPI_CMD_MODE_SHIFT		11
220a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_SHIFT		21
221a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_MASK			0x1
222a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_SHIFT		20
223a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_MASK		0x1
224a552a69cSDamon Ding #define RK3576_IF_REGDONE_IMD_EN_SHIFT		31
225a552a69cSDamon Ding #define RK3576_HDMI0_IF_CTRL			0x184
226a552a69cSDamon Ding #define RK3576_EDP0_IF_CTRL			0x188
227a552a69cSDamon Ding #define RK3576_DP0_IF_CTRL			0x18C
228a552a69cSDamon Ding #define RK3576_RGB_IF_CTRL			0x194
229a552a69cSDamon Ding #define RK3576_BT656_OUT_EN_SHIFT		12
230a552a69cSDamon Ding #define RK3576_BT656_UV_SWAP_SHIFT		13
231a552a69cSDamon Ding #define RK3576_BT656_YC_SWAP_SHIFT		14
232a552a69cSDamon Ding #define RK3576_BT1120_OUT_EN_SHIFT		16
233a552a69cSDamon Ding #define RK3576_BT1120_UV_SWAP_SHIFT		17
234a552a69cSDamon Ding #define RK3576_BT1120_YC_SWAP_SHIFT		18
235a552a69cSDamon Ding #define RK3576_DP1_IF_CTRL			0x1A4
236a552a69cSDamon Ding #define RK3576_DP2_IF_CTRL			0x1B0
23760e469f5SDamon Ding 
238cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL		0x038
239cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT	20
240cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT		24
241cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT	28
242cd6c85a9SDamon Ding 
24360e469f5SDamon Ding #define RK3568_SYS_STATUS0			0x60
24460e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT		8
24560e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT		9
24660e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT		10
24760e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT		11
248b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT		13
249b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT		14
25060e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT		15
251d0408543SAndy Yan 
25266724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0		0x70
25366724b9cSDamon Ding #define LINE_FLAG_NUM_MASK			0x1fff
25466724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT		0
25566724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT		16
25666724b9cSDamon Ding 
25712ee5af0SDamon Ding /* DSC CTRL registers definition */
25812ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL			0x200
25912ee5af0SDamon Ding #define DSC_PORT_SEL_MASK			0x3
26012ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT			0
26112ee5af0SDamon Ding #define DSC_MAN_MODE_MASK			0x1
26212ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT			2
26312ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK			0x3
26412ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT		4
26512ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK			0x3
26612ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT			6
26712ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK			0x1
26812ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT			8
26912ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK			0x3
27012ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT			12
27112ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK			0x3
27212ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT			14
27312ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK			0x1
27412ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT			16
27512ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT			17
27612ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT			18
27712ee5af0SDamon Ding 
27812ee5af0SDamon Ding #define RK3588_DSC_8K_RST			0x204
27912ee5af0SDamon Ding #define RST_DEASSERT_MASK			0x1
28012ee5af0SDamon Ding #define RST_DEASSERT_SHIFT			0
28112ee5af0SDamon Ding 
28212ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE			0x208
28312ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT			0
28412ee5af0SDamon Ding 
28512ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY			0x20C
28612ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK			0xffff
28712ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT			0
28812ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT		16
28912ee5af0SDamon Ding 
29012ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END		0x210
29112ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK			0xffffffff
29212ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT			0
29312ee5af0SDamon Ding 
29412ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END		0x214
29512ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK			0xffffffff
29612ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT			0
29712ee5af0SDamon Ding 
29812ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END		0x218
29912ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK			0xffffffff
30012ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT			0
30112ee5af0SDamon Ding 
30212ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END		0x21C
30312ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK			0xffffffff
30412ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT			0
30512ee5af0SDamon Ding 
30612ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS			0x220
30712ee5af0SDamon Ding 
30863cb669fSSandy Huang /* Overlay registers definition    */
3095fa6e665SDamon Ding #define RK3528_OVL_SYS				0x500
310a552a69cSDamon Ding #define RK3528_OVL_SYS_PORT_SEL			0x504
311a552a69cSDamon Ding #define RK3528_OVL_SYS_GATING_EN		0x508
3125fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL		0x510
3139c7848c3SDamon Ding #define CLUSTER_DLY_NUM_SHIFT			0
3145fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL		0x520
315452afb13SDamon Ding #define ESMART_DLY_NUM_MASK			0xff
316452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT			0
3175fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL		0x524
3185fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL		0x528
3195fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL		0x52C
3205fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL	0x530
3215fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL	0x534
3225fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x538
3235fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL	0x53c
324a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL	0x540
325a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL	0x544
326a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL	0x548
327a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL	0x54c
3285fa6e665SDamon Ding 
3295fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL			0x600
33063cb669fSSandy Huang #define RK3568_OVL_CTRL				0x600
331ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK			0x1
332ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT			0
33363cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
3345fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL		0x604
33563cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL			0x604
33663cb669fSSandy Huang #define LAYER_SEL_MASK				0xf
33763cb669fSSandy Huang 
33863cb669fSSandy Huang #define RK3568_OVL_PORT_SEL			0x608
33963cb669fSSandy Huang #define PORT_MUX_MASK				0xf
34063cb669fSSandy Huang #define PORT_MUX_SHIFT				0
34163cb669fSSandy Huang #define LAYER_SEL_PORT_MASK			0x3
34263cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT			16
34363cb669fSSandy Huang 
34463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
34563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
34663cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
34763cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
3485fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL	0x620
3495fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL	0x624
3505fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL	0x628
3515fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL	0x62C
3525fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL	0x630
3535fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL	0x634
3545fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL	0x638
3555fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL	0x63C
3565fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL	0x640
3575fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL	0x644
3585fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL	0x648
3595fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL	0x64C
36063cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
36163cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL		0x654
36263cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
36363cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
364a552a69cSDamon Ding #define RK3576_EXTRA_SRC_COLOR_CTRL		0x650
365a552a69cSDamon Ding #define RK3576_EXTRA_DST_COLOR_CTRL		0x654
366a552a69cSDamon Ding #define RK3576_EXTRA_SRC_ALPHA_CTRL		0x658
367a552a69cSDamon Ding #define RK3576_EXTRA_DST_ALPHA_CTRL		0x65C
3685fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL		0x660
3695fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL		0x664
3705fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL		0x668
3715fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL		0x66C
3725fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL		0x670
37363cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
37463cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
37563cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
37663cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
37763cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL			0x6E0
37863cb669fSSandy Huang #define BG_MIX_CTRL_MASK			0xff
37963cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT			24
38063cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL			0x6E4
38163cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL			0x6E8
38263cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM			0x6F0
3839c7848c3SDamon Ding #define RK3568_CLUSTER_DLY_NUM1			0x6F4
3849c7848c3SDamon Ding #define CLUSTER_DLY_NUM_MASK			0xffff
3859c7848c3SDamon Ding #define CLUSTER0_DLY_NUM_SHIFT			0
3869c7848c3SDamon Ding #define CLUSTER1_DLY_NUM_SHIFT			16
38763cb669fSSandy Huang #define RK3568_SMART_DLY_NUM			0x6F8
3889c7848c3SDamon Ding #define SMART_DLY_NUM_MASK			0xff
3899c7848c3SDamon Ding #define ESMART0_DLY_NUM_SHIFT			0
3909c7848c3SDamon Ding #define ESMART1_DLY_NUM_SHIFT			8
3919c7848c3SDamon Ding #define SMART0_DLY_NUM_SHIFT			16
3929c7848c3SDamon Ding #define SMART1_DLY_NUM_SHIFT			24
39363cb669fSSandy Huang 
3945fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL			0x700
3955fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL		0x704
3965fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL	0x720
3975fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL	0x724
3985fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL	0x728
3995fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL	0x72C
4005fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL	0x730
4015fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL	0x734
4025fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL	0x738
4035fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL	0x73C
4045fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL	0x740
4055fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL	0x744
4065fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL	0x748
4075fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL	0x74C
4085fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL		0x770
409a552a69cSDamon Ding #define RK3576_OVL_PORT2_CTRL			0x800
410a552a69cSDamon Ding #define RK3576_OVL_PORT2_LAYER_SEL		0x804
411a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL	0x820
412a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL	0x824
413a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL	0x828
414a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL	0x82C
415a552a69cSDamon Ding #define RK3576_OVL_PORT2_BG_MIX_CTRL		0x870
4165fa6e665SDamon Ding 
417d0408543SAndy Yan /* Video Port registers definition */
418d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL			0xC00
419d0408543SAndy Yan #define OUT_MODE_MASK				0xf
420d0408543SAndy Yan #define OUT_MODE_SHIFT				0
42110ee9f5bSAlgea Cao #define DATA_SWAP_MASK				0x1f
42210ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT				8
42365747de7SDamon Ding #define DSP_BG_SWAP				0x1
42465747de7SDamon Ding #define DSP_RB_SWAP				0x2
42565747de7SDamon Ding #define DSP_RG_SWAP				0x4
42665747de7SDamon Ding #define DSP_DELTA_SWAP				0x8
42710ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT			4
428d0408543SAndy Yan #define P2I_EN_SHIFT				5
4297a20be36SSandy Huang #define DSP_FILED_POL				6
430d0408543SAndy Yan #define INTERLACE_EN_SHIFT			7
431c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT			13
43210ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT			15
433d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT		16
434d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT			17
435e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_SHIFT			18
436e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_MASK			0x3
437452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT			20
438db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT			22
4391147facaSSandy Huang #define DSP_LUT_EN_SHIFT			28
4401147facaSSandy Huang 
441d0408543SAndy Yan #define STANDBY_EN_SHIFT			31
442d0408543SAndy Yan 
443d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL			0xC04
44410ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT				4
44510ee9f5bSAlgea Cao #define DCLK_DIV2_MASK				0x3
446d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT			20
447d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT			21
44841874944SGuochun Huang #define EDPI_TE_EN				28
44941874944SGuochun Huang #define EDPI_WMS_HOLD_EN			30
45041874944SGuochun Huang #define EDPI_WMS_FS				31
45141874944SGuochun Huang 
452d0408543SAndy Yan 
453d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL		0xC08
45444b1b62cSDamon Ding #define POST_URGENCY_EN_SHIFT			8
45544b1b62cSDamon Ding #define POST_URGENCY_THL_SHIFT			16
45644b1b62cSDamon Ding #define POST_URGENCY_THL_MASK			0xf
45744b1b62cSDamon Ding #define POST_URGENCY_THH_SHIFT			20
45844b1b62cSDamon Ding #define POST_URGENCY_THH_MASK			0xf
4595fa6e665SDamon Ding 
4605fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL			0xC0C
461a552a69cSDamon Ding #define RK3576_DCLK_CORE_SEL_SHIFT		0
462a552a69cSDamon Ding #define RK3576_DCLK_OUT_SEL_SHIFT		2
4635fa6e665SDamon Ding 
4646414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL			0xC10
4656414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT				0
4666414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT			2
4676414e3bcSSandy Huang 
468ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL			0xC0C
469ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT			0
470ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT			2
471ecc31b6eSAndy Yan 
4726414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST			0xC20
4736414e3bcSSandy Huang 
474d0408543SAndy Yan #define RK3568_VP0_DSP_BG			0xC2C
475d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
476d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
477d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
478d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
479d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL		0xC40
4807504507fSSandy Huang #define RK3568_VP0_POST_SCALE_MASK		0x3
4817504507fSSandy Huang #define RK3568_VP0_POST_SCALE_SHIFT		0
482d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
483d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
484d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END		0xC4C
485d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
486d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END		0xC54
487d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
488d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
489d0408543SAndy Yan 
490ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL			0xC60
491ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT			0
492ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK			0x1
493ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT		2
494ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK		0x3
495ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT			4
496ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK			0x1
497ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT		6
498ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK		0x3
499ac500a1fSSandy Huang 
500ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS			0xC64
501ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT			0
502ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK			0xFF
503ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT			8
504ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK			0x1FF
505ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT			20
506ac500a1fSSandy Huang #define BCSH_SATURATION_MASK			0x3FF
507ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT			30
508ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK			0x3
509ac500a1fSSandy Huang 
510ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H			0xC68
511ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT			0
512ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK			0x1FF
513ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT			16
514ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK			0x1FF
515ac500a1fSSandy Huang 
516ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR			0xC6C
517ac500a1fSSandy Huang #define BCSH_EN_SHIFT				31
518ac500a1fSSandy Huang #define BCSH_EN_MASK				1
519ac500a1fSSandy Huang 
520a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_0		0xCA0
521a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_1		0xCA4
522a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_2		0xCA8
523a552a69cSDamon Ding 
5246027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL			0xCD0
5256027c871SZhang Yubing #define POST_CSC_COE00_MASK			0xFFFF
5266027c871SZhang Yubing #define POST_CSC_COE00_SHIFT			16
5276027c871SZhang Yubing #define POST_R2Y_MODE_MASK			0x7
5286027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT			8
5296027c871SZhang Yubing #define POST_CSC_MODE_MASK			0x7
5306027c871SZhang Yubing #define POST_CSC_MODE_SHIFT			3
5316027c871SZhang Yubing #define POST_R2Y_EN_MASK			0x1
5326027c871SZhang Yubing #define POST_R2Y_EN_SHIFT			2
5336027c871SZhang Yubing #define POST_CSC_EN_MASK			0x1
5346027c871SZhang Yubing #define POST_CSC_EN_SHIFT			1
5356027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK			0x1
5366027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT		0
5376027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02			0xCD4
5386027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11			0xCD8
5396027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20			0xCDC
5406027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22			0xCE0
5416027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0			0xCE4
5426027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1			0xCE8
5436027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2			0xCEC
5446027c871SZhang Yubing 
5450675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL			0xCF8
5460675a2a4SDamon Ding #define MCU_TYPE_SHIFT				31
5470675a2a4SDamon Ding #define MCU_BYPASS_SHIFT			30
5480675a2a4SDamon Ding #define MCU_RS_SHIFT				29
5490675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT			28
5500675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT			27
5510675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT			26
5520675a2a4SDamon Ding #define MCU_CLK_SEL_MASK			0x1
5530675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT			20
5540675a2a4SDamon Ding #define MCU_RW_PEND_MASK			0x3F
5550675a2a4SDamon Ding #define MCU_RW_PST_SHIFT			16
5560675a2a4SDamon Ding #define MCU_RW_PST_MASK				0xF
5570675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT			10
5580675a2a4SDamon Ding #define MCU_CS_PEND_MASK			0x3F
5590675a2a4SDamon Ding #define MCU_CS_PST_SHIFT			6
5600675a2a4SDamon Ding #define MCU_CS_PST_MASK				0xF
5610675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT			0
5620675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK			0x3F
5630675a2a4SDamon Ding 
5640675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT		0xCFC
5650675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT		0
5660675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK		0xFFFFFFFF
5670675a2a4SDamon Ding 
568d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL			0xD00
569d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL			0xD04
570d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL		0xD08
571d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
572d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
573d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
574d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
575d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL		0xD40
576d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO		0xD34
577d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO		0xD38
578d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
579d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
580d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END		0xD4C
581d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
582d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END		0xD54
583d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
584d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
585d0408543SAndy Yan 
586d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL			0xE00
587d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL			0xE04
588d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL		0xE08
589d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
590d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
591d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
592d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
593d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL		0xE40
594d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO		0xE34
595d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO		0xE38
596d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
597d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
598d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END		0xE4C
599d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
600d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END		0xE54
601d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
602d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
603a552a69cSDamon Ding #define RK3568_VP2_BCSH_CTRL			0xE60
604a552a69cSDamon Ding #define RK3568_VP2_BCSH_BCS			0xE64
605a552a69cSDamon Ding #define RK3568_VP2_BCSH_H			0xE68
606a552a69cSDamon Ding #define RK3568_VP2_BCSH_COLOR_BAR		0xE6C
607a552a69cSDamon Ding #define RK3576_VP2_MCU_CTRL			0xEF8
608a552a69cSDamon Ding #define RK3576_VP2_MCU_RW_BYPASS_PORT		0xEFC
609d0408543SAndy Yan 
610d0408543SAndy Yan /* Cluster0 register definition */
611d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
612ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT		8
613ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT		9
614ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT			10
6151615d939SSandy Huang #define CLUSTER_RB_SWAP_SHIFT			14
616840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT		18
617d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
6185fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT	12
6195fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
6205fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
6215fa6e665SDamon Ding #define AVG2_MASK				0x1
6225fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT			18
6235fa6e665SDamon Ding #define AVG4_MASK				0x1
6245fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT			19
6255fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT	22
6265fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT			24
6275fa6e665SDamon Ding #define XGT_MODE_MASK				0x3
6285fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT			25
6295fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT			27
630ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT			28
631ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT			29
632a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2		0x1008
633a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK		0x1f
634a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT		0
635a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK			0x1f
636a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT			5
637a33b790fSDamon Ding 
638d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
639d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
640d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR		0x1018
641d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
642d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
643d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
644d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
645a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_CTRL		0x1040
646a552a69cSDamon Ding #define WIN0_ZME_DERING_EN_SHIFT		3
647a552a69cSDamon Ding #define WIN0_ZME_GATING_EN_SHIFT		31
648a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA	0x1044
649d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
650d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
651d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
652d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
653d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
654d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
655d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
656a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT		7
657a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET	0x1078
658a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE	0x107C
659d0408543SAndy Yan 
660d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
661d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
662d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
663d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
664d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR		0x1098
665d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
666d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
667d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
668d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
669d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
670d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
671d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
672d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
673d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
674d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
675d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
676a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET	0x10F8
677a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE	0x10FC
678d0408543SAndy Yan 
679d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL			0x1100
680ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT			0
681a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK			0x1
682a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT			13
683a552a69cSDamon Ding #define RK3576_CLUSTER0_PORT_SEL		0x11F4
684a552a69cSDamon Ding #define CLUSTER_PORT_SEL_SHIFT			0
685a552a69cSDamon Ding #define CLUSTER_PORT_SEL_MASK			0x3
686a552a69cSDamon Ding #define RK3576_CLUSTER0_DLY_NUM			0x11F8
687a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_SHIFT		0
688a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_MASK		0xff
689a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_SHIFT		0
690a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_MASK		0xff
691d0408543SAndy Yan 
692d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
693d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
694d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
695d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
696d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR		0x1218
697d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
698d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
699d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
700d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
701a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_CTRL		0x1240
702a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA	0x1244
703d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
704d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
705d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
706d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
707d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
708d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
709d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
710a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET	0x1278
711a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE	0x127C
712d0408543SAndy Yan 
713d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
714d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
715d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
716d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
717d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR		0x1298
718d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
719d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
720d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
721d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
722d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
723d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
724d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
725d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
726d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
727d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
728d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
729a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET	0x12F8
730a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE	0x12FC
731d0408543SAndy Yan 
732d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL			0x1300
733a552a69cSDamon Ding #define RK3576_CLUSTER1_PORT_SEL		0x13F4
734a552a69cSDamon Ding #define RK3576_CLUSTER1_DLY_NUM			0x13F8
735d0408543SAndy Yan 
736d0408543SAndy Yan /* Esmart register definition */
737d0408543SAndy Yan #define RK3568_ESMART0_CTRL0			0x1800
73810ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT			1
73910ee9f5bSAlgea Cao #define CSC_MODE_SHIFT				2
74010ee9f5bSAlgea Cao #define CSC_MODE_MASK				0x3
7415fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT			12
7425fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK			0x3
743d0408543SAndy Yan 
744d0408543SAndy Yan #define RK3568_ESMART0_CTRL1			0x1804
745a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK			0x1f
746a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT		4
747a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK			0x1f
748a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT			12
749d0408543SAndy Yan #define YMIRROR_EN_SHIFT			31
750a33b790fSDamon Ding 
751a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL			0x1808
752a33b790fSDamon Ding #define ESMART_AXI_ID_MASK			0x1
753a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT			1
754a33b790fSDamon Ding 
755d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL		0x1810
756d0408543SAndy Yan #define WIN_EN_SHIFT				0
757d0408543SAndy Yan #define WIN_FORMAT_MASK				0x1f
758d0408543SAndy Yan #define WIN_FORMAT_SHIFT			1
759840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT		12
7605fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT			14
7615fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT			20
7625fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT			21
7635fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT			22
764d0408543SAndy Yan 
765d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
766d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
767d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR		0x181C
768d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
769d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
770d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
771d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
7723e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK			0x3
7733e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT			0
7743e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK		0x3
7753e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT		2
7763e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK			0x3
7773e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT			4
7783e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK		0x3
7793e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT		6
7803e39a5a1SSandy Huang 
781d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
782d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
783d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
784d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL		0x1840
7853e39a5a1SSandy Huang #define YRGB_GT2_MASK				0x1
7863e39a5a1SSandy Huang #define YRGB_GT2_SHIFT				8
7873e39a5a1SSandy Huang #define YRGB_GT4_MASK				0x1
7883e39a5a1SSandy Huang #define YRGB_GT4_SHIFT				9
7893e39a5a1SSandy Huang 
790d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
791d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
792d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR		0x184C
793d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
794d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
795d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
796d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
797d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
798d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
799d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
800d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL		0x1870
801d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
802d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
803d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR		0x187C
804d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
805d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
806d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
807d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
808d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
809d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
810d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
811d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL		0x18A0
812d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
813d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
814d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR		0x18AC
815d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
816d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
817d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
818d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
819d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
820d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
821d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
822a552a69cSDamon Ding #define RK3568_ESMART0_COLOR_KEY_CTRL		0x18D0
823a552a69cSDamon Ding #define RK3576_ESMART0_ALPHA_MAP		0x18D8
824a552a69cSDamon Ding #define RK3576_ESMART0_PORT_SEL			0x18F4
825a552a69cSDamon Ding #define ESMART_PORT_SEL_SHIFT			0
826a552a69cSDamon Ding #define ESMART_PORT_SEL_MASK			0x3
827a552a69cSDamon Ding #define RK3576_ESMART0_DLY_NUM			0x18F8
828d0408543SAndy Yan 
829d0408543SAndy Yan #define RK3568_ESMART1_CTRL0			0x1A00
830d0408543SAndy Yan #define RK3568_ESMART1_CTRL1			0x1A04
831d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL		0x1A10
832d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
833d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
834d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR		0x1A1C
835d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
836d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
837d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
838d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
839d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
840d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
841d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
842d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL		0x1A40
843d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
844d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
845d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR		0x1A4C
846d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
847d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
848d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
849d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
850d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
851d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
852d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
853d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL		0x1A70
854d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
855d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
856d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR		0x1A7C
857d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
858d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
859d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
860d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
861d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
862d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
863d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
864d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
865d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
866d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
867d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR		0x1AAC
868d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
869d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
870d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
871d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
872d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
873d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
874d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
875a552a69cSDamon Ding #define RK3576_ESMART1_ALPHA_MAP		0x1AD8
876a552a69cSDamon Ding #define RK3576_ESMART1_PORT_SEL			0x1AF4
877a552a69cSDamon Ding #define RK3576_ESMART1_DLY_NUM			0x1AF8
878d0408543SAndy Yan 
879d0408543SAndy Yan #define RK3568_SMART0_CTRL0			0x1C00
880d0408543SAndy Yan #define RK3568_SMART0_CTRL1			0x1C04
881d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL		0x1C10
882d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
883d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
884d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR		0x1C1C
885d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
886d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
887d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
888d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
889d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
890d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
891d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
892d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL		0x1C40
893d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
894d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
895d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR		0x1C4C
896d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
897d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
898d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
899d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
900d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
901d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
902d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
903d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL		0x1C70
904d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
905d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
906d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR		0x1C7C
907d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
908d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
909d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
910d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
911d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
912d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
913d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
914d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL		0x1CA0
915d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
916d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
917d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR		0x1CAC
918d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
919d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
920d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
921d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
922d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
923d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
924d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
925a552a69cSDamon Ding #define RK3576_ESMART2_ALPHA_MAP		0x1CD8
926a552a69cSDamon Ding #define RK3576_ESMART2_PORT_SEL			0x1CF4
927a552a69cSDamon Ding #define RK3576_ESMART2_DLY_NUM			0x1CF8
928d0408543SAndy Yan 
929d0408543SAndy Yan #define RK3568_SMART1_CTRL0			0x1E00
930d0408543SAndy Yan #define RK3568_SMART1_CTRL1			0x1E04
931d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL		0x1E10
932d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
933d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
934d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR		0x1E1C
935d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
936d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
937d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
938d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
939d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
940d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
941d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
942d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL		0x1E40
943d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
944d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
945d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR		0x1E4C
946d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
947d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
948d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
949d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
950d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
951d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
952d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
953d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL		0x1E70
954d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
955d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
956d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR		0x1E7C
957d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
958d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
959d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
960d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
961d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
962d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
963d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
964d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL		0x1EA0
965d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
966d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
967d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR		0x1EAC
968d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
969d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
970d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
971d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
972d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
973d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
974d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
975a552a69cSDamon Ding #define RK3576_ESMART3_ALPHA_MAP		0x1ED8
976a552a69cSDamon Ding #define RK3576_ESMART3_PORT_SEL			0x1EF4
977a552a69cSDamon Ding #define RK3576_ESMART3_DLY_NUM			0x1EF8
978d0408543SAndy Yan 
97972388c26SDamon Ding /* HDR register definition */
98072388c26SDamon Ding #define RK3568_HDR_LUT_CTRL			0x2000
98172388c26SDamon Ding 
98272388c26SDamon Ding #define RK3588_VP3_DSP_CTRL			0xF00
98372388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0		0x1400
98472388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0		0x1600
98572388c26SDamon Ding 
98612ee5af0SDamon Ding /* DSC 8K/4K register definition */
98712ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3			0x4000
98812ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0			0x40A0
98912ee5af0SDamon Ding #define DSC_EN_SHIFT				0
99012ee5af0SDamon Ding #define DSC_RBIT_SHIFT				2
99112ee5af0SDamon Ding #define DSC_RBYT_SHIFT				3
99212ee5af0SDamon Ding #define DSC_FLAL_SHIFT				4
99312ee5af0SDamon Ding #define DSC_MER_SHIFT				5
99412ee5af0SDamon Ding #define DSC_EPB_SHIFT				6
99512ee5af0SDamon Ding #define DSC_EPL_SHIFT				7
9961ace1b6dSDamon Ding #define DSC_NSLC_MASK				0x7
99712ee5af0SDamon Ding #define DSC_NSLC_SHIFT				16
99812ee5af0SDamon Ding #define DSC_SBO_SHIFT				28
99912ee5af0SDamon Ding #define DSC_IFEP_SHIFT				29
100012ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT			31
1001baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT)   | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \
1002baf2c414SDamon Ding 			   (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT)  | (0 << DSC_EPB_SHIFT)  | \
1003baf2c414SDamon Ding 			   (1 << DSC_EPL_SHIFT)  | (1 << DSC_SBO_SHIFT))
100412ee5af0SDamon Ding 
100512ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1			0x40A4
100612ee5af0SDamon Ding #define RK3588_DSC_8K_STS0			0x40A8
100712ee5af0SDamon Ding #define RK3588_DSC_8K_ERS			0x40C4
100812ee5af0SDamon Ding 
100912ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3			0x4100
101012ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0			0x41A0
101112ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1			0x41A4
101212ee5af0SDamon Ding #define RK3588_DSC_4K_STS0			0x41A8
101312ee5af0SDamon Ding #define RK3588_DSC_4K_ERS			0x41C4
101412ee5af0SDamon Ding 
101572388c26SDamon Ding /* RK3528 HDR register definition */
101672388c26SDamon Ding #define RK3528_HDR_LUT_CTRL			0x2000
101772388c26SDamon Ding 
10186027c871SZhang Yubing /* RK3528 ACM register definition */
10196027c871SZhang Yubing #define RK3528_ACM_CTRL				0x6400
10206027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE			0x6404
10216027c871SZhang Yubing #define RK3528_ACM_FETCH_START			0x6408
10226027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE			0x6420
10236027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0		0x6500
10246027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152		0x6760
10256027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0		0x6764
10266027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220		0x6ad4
10276027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0		0x6ad8
10286027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64		0x6bd8
10296027c871SZhang Yubing 
1030*60e6e79dSSandy Huang #define RK3568_IOMMU0_DTE_ADDR			0x7e00
1031*60e6e79dSSandy Huang #define RK3568_IOMMU0_STATUS			0x7e04
1032*60e6e79dSSandy Huang #define MMU_PAGING_EN				BIT(0)
1033*60e6e79dSSandy Huang #define MMU_PAGE_FAULT_ACTIVE			BIT(1)
1034*60e6e79dSSandy Huang #define RK3568_IOMMU0_COMMAND			0x7e08
1035*60e6e79dSSandy Huang #define MMU_ENABLE_PAGING			0
1036*60e6e79dSSandy Huang #define MMU_DISABLE_PAGING			1
1037*60e6e79dSSandy Huang #define MMU_FORCE_RESET				6
1038*60e6e79dSSandy Huang #define RK3568_IOMMU0_PAGEFAULT_ADDR		0x7e0c
1039*60e6e79dSSandy Huang 
104045ec9215SDamon Ding /* RK3576 SHARP register definition */
104145ec9215SDamon Ding #define RK3576_SHARP_CTRL			0x0000
104245ec9215SDamon Ding #define SW_SHARP_ENABLE_SHIFT			0
104345ec9215SDamon Ding 
1044d0408543SAndy Yan #define RK3568_MAX_REG				0x1ED0
1045d0408543SAndy Yan 
1046452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON		0x10500
104752ee18acSSandy Huang #define RK3568_GRF_VO_CON1			0x0364
104852ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT			1
104952ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT		2
105052ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT			3
105152ee18acSSandy Huang 
1052a552a69cSDamon Ding /* Base SYS_GRF: 0x2600a000*/
1053a552a69cSDamon Ding #define RK3576_SYS_GRF_MEMFAULT_STATUS0		0x0148
1054a552a69cSDamon Ding 
1055a552a69cSDamon Ding /* Base IOC_GRF: 0x26040000 */
1056a552a69cSDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8		0x6420
1057a552a69cSDamon Ding #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT	9
1058a552a69cSDamon Ding #define RK3576_IOC_VOPLITE_SEL_SHIFT		11
1059a552a69cSDamon Ding 
1060a552a69cSDamon Ding /* Base PMU2: 0x27380000 */
1061a552a69cSDamon Ding #define RK3576_PMU_PWR_GATE_STS			0x0230
1062a552a69cSDamon Ding #define PD_VOP_ESMART_DWN_STAT			12
1063a552a69cSDamon Ding #define PD_VOP_CLUSTER_DWN_STAT			13
1064a552a69cSDamon Ding #define RK3576_PMU_BISR_PDGEN_CON0		0x0510
1065a552a69cSDamon Ding #define PD_VOP_ESMART_REPAIR_ENA_SHIFT		12
1066a552a69cSDamon Ding #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT		13
1067a552a69cSDamon Ding #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0	0x0570
1068a552a69cSDamon Ding #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT	12
1069a552a69cSDamon Ding #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT	13
1070a552a69cSDamon Ding 
10715d2768f7SDamon Ding #define RK3588_GRF_SOC_CON1			0x0304
10725d2768f7SDamon Ding #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT	14
10735d2768f7SDamon Ding 
1074ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2			0x0008
1075ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT		0
1076ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT		1
10772e42aca5SDamon Ding #define RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT	2
1078ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT		3
1079ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT		4
10802e42aca5SDamon Ding #define RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT	5
1081ecc31b6eSAndy Yan 
1082b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0			0x0000
1083b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK			0x3
1084b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT			5
1085b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT			7
1086b890760eSAlgea Cao 
108760e469f5SDamon Ding #define RK3588_PMU_BISR_CON3			0x20C
108860e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT	9
108960e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT	10
109060e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT	11
109160e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT	12
1092b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT	13
1093b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT	14
109460e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT	15
109560e469f5SDamon Ding 
109660e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5			0x294
109760e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI	9
109860e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI	10
109960e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI	11
110060e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI	12
1101b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI		13
1102b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI		14
110360e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI		15
110460e469f5SDamon Ding 
1105d0408543SAndy Yan #define VOP2_LAYER_MAX				8
110663cb669fSSandy Huang 
1107ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH		4096
1108ee01dbb2SDamon Ding 
1109631ee99aSZhang Yubing /* KHz */
1110631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE			600000
1111631ee99aSZhang Yubing 
1112b6ba80b4SDamon Ding /*
1113b6ba80b4SDamon Ding  * vop2 dsc id
1114b6ba80b4SDamon Ding  */
1115b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K	0
1116b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K	1
1117b6ba80b4SDamon Ding 
1118b6ba80b4SDamon Ding /*
1119b6ba80b4SDamon Ding  * vop2 internal power domain id,
1120b6ba80b4SDamon Ding  * should be all none zero, 0 will be
1121b6ba80b4SDamon Ding  * treat as invalid;
1122b6ba80b4SDamon Ding  */
1123b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0			BIT(0)
1124b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1			BIT(1)
1125b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2			BIT(2)
1126b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3			BIT(3)
1127b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K				BIT(5)
1128b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K				BIT(6)
1129b6ba80b4SDamon Ding #define VOP2_PD_ESMART				BIT(7)
1130a552a69cSDamon Ding #define VOP2_PD_CLUSTER				BIT(8)
1131b6ba80b4SDamon Ding 
11324c765862SDamon Ding #define VOP2_PLANE_NO_SCALING			BIT(16)
11334c765862SDamon Ding 
11345fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT	BIT(0)
11355fa6e665SDamon Ding #define VOP_FEATURE_AFBDC		BIT(1)
11365fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE		BIT(2)
11375fa6e665SDamon Ding #define VOP_FEATURE_HDR10		BIT(3)
11385fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR		BIT(4)
11395fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */
11405fa6e665SDamon Ding #define VOP_FEATURE_SPLICE		BIT(5)
11415fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN		BIT(6)
11426027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR		BIT(7)
11436027c871SZhang Yubing #define VOP_FEATURE_POST_ACM		BIT(8)
11446027c871SZhang Yubing #define VOP_FEATURE_POST_CSC		BIT(9)
1145a552a69cSDamon Ding #define VOP_FEATURE_POST_FRC_V2		BIT(10)
1146a552a69cSDamon Ding #define VOP_FEATURE_POST_SHARP		BIT(11)
11475fa6e665SDamon Ding 
11485fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR		BIT(0)
11495fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR		BIT(1)
11505fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY		BIT(2)
11515fa6e665SDamon Ding #define WIN_FEATURE_AFBDC		BIT(3)
11525fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
11535fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB		BIT(5)
11545fa6e665SDamon Ding /* a mirror win can only get fb address
11555fa6e665SDamon Ding  * from source win:
11565fa6e665SDamon Ding  * Cluster1---->Cluster0
11575fa6e665SDamon Ding  * Esmart1 ---->Esmart0
11585fa6e665SDamon Ding  * Smart1  ---->Smart0
11595fa6e665SDamon Ding  * This is a feather on rk3566
11605fa6e665SDamon Ding  */
11615fa6e665SDamon Ding #define WIN_FEATURE_MIRROR		BIT(6)
11625fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA		BIT(7)
11635fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH	BIT(8)
1164a552a69cSDamon Ding #define WIN_FEATURE_DCI			BIT(9)
11655fa6e665SDamon Ding 
11665fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F		0xfe
11675fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F		0xff
11685fa6e665SDamon Ding 
11695fa6e665SDamon Ding enum vop_csc_format {
117010ee9f5bSAlgea Cao 	CSC_BT601L,
117110ee9f5bSAlgea Cao 	CSC_BT709L,
117210ee9f5bSAlgea Cao 	CSC_BT601F,
1173df0a5c43SDamon Ding 	CSC_BT2020L,
11745fa6e665SDamon Ding 	CSC_BT709L_13BIT,
11755fa6e665SDamon Ding 	CSC_BT709F_13BIT,
11765fa6e665SDamon Ding 	CSC_BT2020L_13BIT,
11775fa6e665SDamon Ding 	CSC_BT2020F_13BIT,
11785fa6e665SDamon Ding };
11795fa6e665SDamon Ding 
11805fa6e665SDamon Ding enum vop_csc_bit_depth {
11815fa6e665SDamon Ding 	CSC_10BIT_DEPTH,
11825fa6e665SDamon Ding 	CSC_13BIT_DEPTH,
118310ee9f5bSAlgea Cao };
118410ee9f5bSAlgea Cao 
118510ee9f5bSAlgea Cao enum vop2_pol {
118610ee9f5bSAlgea Cao 	HSYNC_POSITIVE = 0,
118710ee9f5bSAlgea Cao 	VSYNC_POSITIVE = 1,
118810ee9f5bSAlgea Cao 	DEN_NEGATIVE   = 2,
118910ee9f5bSAlgea Cao 	DCLK_INVERT    = 3
119010ee9f5bSAlgea Cao };
119110ee9f5bSAlgea Cao 
1192ac500a1fSSandy Huang enum vop2_bcsh_out_mode {
1193ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLACK,
1194ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLUE,
1195ac500a1fSSandy Huang 	BCSH_OUT_MODE_COLOR_BAR,
1196ac500a1fSSandy Huang 	BCSH_OUT_MODE_NORMAL_VIDEO,
1197ac500a1fSSandy Huang };
1198ac500a1fSSandy Huang 
1199d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \
1200d0408543SAndy Yan 		{ \
1201d0408543SAndy Yan 		 .offset = off, \
1202d0408543SAndy Yan 		 .mask = _mask, \
1203d0408543SAndy Yan 		 .shift = _shift, \
1204d0408543SAndy Yan 		 .write_mask = _write_mask, \
1205d0408543SAndy Yan 		}
1206d0408543SAndy Yan 
1207d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \
1208d0408543SAndy Yan 		_VOP_REG(off, _mask, _shift, false)
1209d0408543SAndy Yan enum dither_down_mode {
1210d0408543SAndy Yan 	RGB888_TO_RGB565 = 0x0,
1211d0408543SAndy Yan 	RGB888_TO_RGB666 = 0x1
1212d0408543SAndy Yan };
1213d0408543SAndy Yan 
1214a552a69cSDamon Ding enum dither_down_mode_sel {
1215a552a69cSDamon Ding 	DITHER_DOWN_ALLEGRO = 0x0,
1216a552a69cSDamon Ding 	DITHER_DOWN_FRC = 0x1
1217a552a69cSDamon Ding };
1218a552a69cSDamon Ding 
1219d0408543SAndy Yan enum vop2_video_ports_id {
1220d0408543SAndy Yan 	VOP2_VP0,
1221d0408543SAndy Yan 	VOP2_VP1,
1222d0408543SAndy Yan 	VOP2_VP2,
1223d0408543SAndy Yan 	VOP2_VP3,
1224d0408543SAndy Yan 	VOP2_VP_MAX,
1225d0408543SAndy Yan };
1226d0408543SAndy Yan 
1227ee008497SSandy Huang enum vop2_layer_type {
1228ee008497SSandy Huang 	CLUSTER_LAYER = 0,
1229ee008497SSandy Huang 	ESMART_LAYER = 1,
1230ee008497SSandy Huang 	SMART_LAYER = 2,
1231ee008497SSandy Huang };
1232ee008497SSandy Huang 
12336fea745cSDamon Ding enum vop2_plane_type {
12346fea745cSDamon Ding 	VOP2_PLANE_TYPE_OVERLAY = 0,
12356fea745cSDamon Ding 	VOP2_PLANE_TYPE_PRIMARY = 1,
12366fea745cSDamon Ding 	VOP2_PLANE_TYPE_CURSOR = 2,
12376fea745cSDamon Ding };
12386fea745cSDamon Ding 
1239b0989546SSandy Huang /* This define must same with kernel win phy id */
1240b0989546SSandy Huang enum vop2_layer_phy_id {
1241b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER0 = 0,
1242b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER1,
1243b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART0,
1244b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART1,
1245b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART0,
1246b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART1,
1247b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER2,
1248b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER3,
1249b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART2,
1250b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART3,
1251ee008497SSandy Huang 	ROCKCHIP_VOP2_LAYER_MAX,
1252a7cb29b7SDamon Ding 	ROCKCHIP_VOP2_PHY_ID_INVALID = (u8)-1,
1253d0408543SAndy Yan };
1254d0408543SAndy Yan 
12553e39a5a1SSandy Huang enum vop2_scale_up_mode {
12563e39a5a1SSandy Huang 	VOP2_SCALE_UP_NRST_NBOR,
12573e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIL,
12583e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIC,
1259a552a69cSDamon Ding 	VOP2_SCALE_UP_ZME,
12603e39a5a1SSandy Huang };
12613e39a5a1SSandy Huang 
12623e39a5a1SSandy Huang enum vop2_scale_down_mode {
12633e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_NRST_NBOR,
12643e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_BIL,
12653e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_AVG,
1266a552a69cSDamon Ding 	VOP2_SCALE_DOWN_ZME,
12673e39a5a1SSandy Huang };
12683e39a5a1SSandy Huang 
12693e39a5a1SSandy Huang enum scale_mode {
12703e39a5a1SSandy Huang 	SCALE_NONE = 0x0,
12713e39a5a1SSandy Huang 	SCALE_UP   = 0x1,
12723e39a5a1SSandy Huang 	SCALE_DOWN = 0x2
12733e39a5a1SSandy Huang };
12743e39a5a1SSandy Huang 
127512ee5af0SDamon Ding enum vop_dsc_interface_mode {
127612ee5af0SDamon Ding 	VOP_DSC_IF_DISABLE = 0,
127712ee5af0SDamon Ding 	VOP_DSC_IF_HDMI = 1,
127812ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_DS_MODE = 2,
127912ee5af0SDamon Ding 	VOP_DSC_IF_MIPI_VIDEO_MODE = 3,
128012ee5af0SDamon Ding };
128112ee5af0SDamon Ding 
12825fa6e665SDamon Ding enum vop3_pre_scale_down_mode {
12835fa6e665SDamon Ding 	VOP3_PRE_SCALE_UNSPPORT,
12845fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_GT,
12855fa6e665SDamon Ding 	VOP3_PRE_SCALE_DOWN_AVG,
12865fa6e665SDamon Ding };
12875fa6e665SDamon Ding 
12889c7848c3SDamon Ding /*
12899c7848c3SDamon Ding  *  the delay number of a window in different mode.
12909c7848c3SDamon Ding  */
12919c7848c3SDamon Ding enum vop2_win_dly_mode {
12929c7848c3SDamon Ding 	VOP2_DLY_MODE_DEFAULT,		/* default mode */
12939c7848c3SDamon Ding 	VOP2_DLY_MODE_HISO_S,		/* HDR in SDR out mode, as a SDR window */
12949c7848c3SDamon Ding 	VOP2_DLY_MODE_HIHO_H,		/* HDR in HDR out mode, as a HDR window */
12959c7848c3SDamon Ding 	VOP2_DLY_MODE_DOVI_IN_CORE1,	/* dovi video input, as dovi core1 */
12969c7848c3SDamon Ding 	VOP2_DLY_MODE_DOVI_IN_CORE2,	/* dovi video input, as dovi core2 */
12979c7848c3SDamon Ding 	VOP2_DLY_MODE_NONDOVI_IN_CORE1,	/* ndovi video input, as dovi core1 */
12989c7848c3SDamon Ding 	VOP2_DLY_MODE_NONDOVI_IN_CORE2,	/* ndovi video input, as dovi core2 */
12999c7848c3SDamon Ding 	VOP2_DLY_MODE_MAX,
13009c7848c3SDamon Ding };
13019c7848c3SDamon Ding 
13025fa6e665SDamon Ding enum vop3_esmart_lb_mode {
13035fa6e665SDamon Ding 	VOP3_ESMART_8K_MODE,
13045fa6e665SDamon Ding 	VOP3_ESMART_4K_4K_MODE,
13055fa6e665SDamon Ding 	VOP3_ESMART_4K_2K_2K_MODE,
13065fa6e665SDamon Ding 	VOP3_ESMART_2K_2K_2K_2K_MODE,
1307a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_4K_MODE,
1308a552a69cSDamon Ding 	VOP3_ESMART_4K_4K_2K_2K_MODE,
13095fa6e665SDamon Ding };
13105fa6e665SDamon Ding 
13113e39a5a1SSandy Huang struct vop2_layer {
13123e39a5a1SSandy Huang 	u8 id;
13133e39a5a1SSandy Huang 	/**
13143e39a5a1SSandy Huang 	 * @win_phys_id: window id of the layer selected.
13153e39a5a1SSandy Huang 	 * Every layer must make sure to select different
13163e39a5a1SSandy Huang 	 * windows of others.
13173e39a5a1SSandy Huang 	 */
13183e39a5a1SSandy Huang 	u8 win_phys_id;
13193e39a5a1SSandy Huang };
13203e39a5a1SSandy Huang 
132160e469f5SDamon Ding struct vop2_power_domain_data {
1322a552a69cSDamon Ding 	u16 id;
1323a552a69cSDamon Ding 	u16 parent_id;
1324b6ba80b4SDamon Ding 	/*
1325b6ba80b4SDamon Ding 	 * @module_id_mask: module id of which module this power domain is belongs to.
1326b6ba80b4SDamon Ding 	 * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3
1327b6ba80b4SDamon Ding 	 */
1328b6ba80b4SDamon Ding 	u32 module_id_mask;
132960e469f5SDamon Ding };
133060e469f5SDamon Ding 
1331b0989546SSandy Huang struct vop2_win_data {
1332b0989546SSandy Huang 	char *name;
133363cb669fSSandy Huang 	u8 phys_id;
1334ecc31b6eSAndy Yan 	enum vop2_layer_type type;
13356fea745cSDamon Ding 	enum vop2_plane_type plane_type;
1336b0989546SSandy Huang 	u8 win_sel_port_offset;
13375fa6e665SDamon Ding 	u8 layer_sel_win_id[VOP2_VP_MAX];
1338a33b790fSDamon Ding 	u8 axi_id;
1339a33b790fSDamon Ding 	u8 axi_uv_id;
1340a33b790fSDamon Ding 	u8 axi_yrgb_id;
1341ee01dbb2SDamon Ding 	u8 splice_win_id;
13425fa6e665SDamon Ding 	u8 hsu_filter_mode;
13435fa6e665SDamon Ding 	u8 hsd_filter_mode;
13445fa6e665SDamon Ding 	u8 vsu_filter_mode;
13455fa6e665SDamon Ding 	u8 vsd_filter_mode;
13465fa6e665SDamon Ding 	u8 hsd_pre_filter_mode;
13475fa6e665SDamon Ding 	u8 vsd_pre_filter_mode;
13485fa6e665SDamon Ding 	u8 scale_engine_num;
13491c9572c7SDamon Ding 	u8 source_win_id;
135013bc92e8SDamon Ding 	u8 possible_vp_mask;
13519c7848c3SDamon Ding 	u8 dly[VOP2_DLY_MODE_MAX];
1352a552a69cSDamon Ding 	u16 pd_id;
1353b0989546SSandy Huang 	u32 reg_offset;
13544c765862SDamon Ding 	u32 max_upscale_factor;
13554c765862SDamon Ding 	u32 max_downscale_factor;
13561c9572c7SDamon Ding 	u32 feature;
1357a552a69cSDamon Ding 	u32 supported_rotations;
1358ee01dbb2SDamon Ding 	bool splice_mode_right;
135963cb669fSSandy Huang };
136063cb669fSSandy Huang 
136163cb669fSSandy Huang struct vop2_vp_data {
136263cb669fSSandy Huang 	u32 feature;
136344b1b62cSDamon Ding 	u32 max_dclk;
136463cb669fSSandy Huang 	u8 pre_scan_max_dly;
1365452afb13SDamon Ding 	u8 layer_mix_dly;
1366a552a69cSDamon Ding 	u8 hdrvivid_dly;
1367a552a69cSDamon Ding 	u8 sdr2hdr_dly;
1368452afb13SDamon Ding 	u8 hdr_mix_dly;
1369452afb13SDamon Ding 	u8 win_dly;
1370ee01dbb2SDamon Ding 	u8 splice_vp_id;
1371a552a69cSDamon Ding 	u8 pixel_rate;
137263cb669fSSandy Huang 	struct vop_rect max_output;
137344b1b62cSDamon Ding 	struct vop_urgency *urgency;
1374d0408543SAndy Yan };
1375d0408543SAndy Yan 
1376b0989546SSandy Huang struct vop2_vp_plane_mask {
1377b0989546SSandy Huang 	u8 primary_plane_id; /* use this win to show logo */
1378b4fa21deSDamon Ding 	u8 cursor_plane_id;
1379b0989546SSandy Huang 	u8 attached_layers_nr; /* number layers attach to this vp */
1380b0989546SSandy Huang 	u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
1381b0989546SSandy Huang 	u32 plane_mask;
1382b0989546SSandy Huang };
1383b0989546SSandy Huang 
138412ee5af0SDamon Ding struct vop2_dsc_data {
138512ee5af0SDamon Ding 	u8 id;
138612ee5af0SDamon Ding 	u8 max_slice_num;
138712ee5af0SDamon Ding 	u8 max_linebuf_depth;	/* used to generate the bitstream */
138812ee5af0SDamon Ding 	u8 min_bits_per_pixel;	/* bit num after encoder compress */
1389a552a69cSDamon Ding 	u16 pd_id;
139012ee5af0SDamon Ding 	const char *dsc_txp_clk_src_name;
139112ee5af0SDamon Ding 	const char *dsc_txp_clk_name;
139212ee5af0SDamon Ding 	const char *dsc_pxl_clk_name;
139312ee5af0SDamon Ding 	const char *dsc_cds_clk_name;
139412ee5af0SDamon Ding };
139512ee5af0SDamon Ding 
139612ee5af0SDamon Ding struct dsc_error_info {
139712ee5af0SDamon Ding 	u32 dsc_error_val;
139812ee5af0SDamon Ding 	char dsc_error_info[50];
139912ee5af0SDamon Ding };
140012ee5af0SDamon Ding 
140172388c26SDamon Ding struct vop2_dump_regs {
140272388c26SDamon Ding 	u32 offset;
140372388c26SDamon Ding 	const char *name;
140472388c26SDamon Ding 	u32 state_base;
140572388c26SDamon Ding 	u32 state_mask;
140672388c26SDamon Ding 	u32 state_shift;
140772388c26SDamon Ding 	bool enable_state;
1408a552a69cSDamon Ding 	u32 size;
1409a552a69cSDamon Ding };
1410a552a69cSDamon Ding 
1411a552a69cSDamon Ding struct vop2_esmart_lb_map {
1412a552a69cSDamon Ding 	u8 lb_mode;
1413a552a69cSDamon Ding 	u8 lb_map_value;
141472388c26SDamon Ding };
141572388c26SDamon Ding 
14169c7848c3SDamon Ding /**
14179c7848c3SDamon Ding * struct vop2_ops - helper operations for vop2 hardware
14189c7848c3SDamon Ding *
14199c7848c3SDamon Ding * These hooks are used by the common part of the vop2 driver to
14209c7848c3SDamon Ding * implement the proper behaviour of different variants.
14219c7848c3SDamon Ding */
14229c7848c3SDamon Ding struct vop2_ops {
1423b888dbc8SSandy Huang 	void (*setup_win_dly)(struct display_state *state, int crtc_id, u8 plane_phy_id);
1424b7195f56SDamon Ding 	void (*setup_overlay)(struct display_state *state);
1425ef0607a7SDamon Ding 	void (*assign_plane_mask)(struct display_state *state);
14269c7848c3SDamon Ding };
14279c7848c3SDamon Ding 
1428d0408543SAndy Yan struct vop2_data {
142952ee18acSSandy Huang 	u32 version;
14305fa6e665SDamon Ding 	u32 esmart_lb_mode;
143163cb669fSSandy Huang 	struct vop2_vp_data *vp_data;
1432b0989546SSandy Huang 	struct vop2_win_data *win_data;
1433b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
1434b6ba80b4SDamon Ding 	struct vop2_power_domain_data *pd;
143512ee5af0SDamon Ding 	struct vop2_dsc_data *dsc;
143612ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_ecw;
143712ee5af0SDamon Ding 	struct dsc_error_info *dsc_error_buffer_flow;
143872388c26SDamon Ding 	struct vop2_dump_regs *dump_regs;
1439a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map;
14409c7848c3SDamon Ding 	const struct vop2_ops *ops;
144163cb669fSSandy Huang 	u8 nr_vps;
144263cb669fSSandy Huang 	u8 nr_layers;
144363cb669fSSandy Huang 	u8 nr_mixers;
14441147facaSSandy Huang 	u8 nr_gammas;
1445b6ba80b4SDamon Ding 	u8 nr_pd;
144612ee5af0SDamon Ding 	u8 nr_dscs;
144712ee5af0SDamon Ding 	u8 nr_dsc_ecw;
144812ee5af0SDamon Ding 	u8 nr_dsc_buffer_flow;
1449a552a69cSDamon Ding 	u8 esmart_lb_mode_num;
1450ecc31b6eSAndy Yan 	u32 reg_len;
145172388c26SDamon Ding 	u32 dump_regs_size;
14526fea745cSDamon Ding 	u32 plane_mask_base;
1453d0408543SAndy Yan };
1454d0408543SAndy Yan 
1455d0408543SAndy Yan struct vop2 {
1456d0408543SAndy Yan 	u32 *regsbak;
1457d0408543SAndy Yan 	void *regs;
1458d0408543SAndy Yan 	void *grf;
1459ecc31b6eSAndy Yan 	void *vop_grf;
1460ecc31b6eSAndy Yan 	void *vo1_grf;
146160e469f5SDamon Ding 	void *sys_pmu;
1462a552a69cSDamon Ding 	void *ioc_grf;
146345ec9215SDamon Ding 	void *sharp_res;
146452ee18acSSandy Huang 	u32 reg_len;
146552ee18acSSandy Huang 	u32 version;
14665fa6e665SDamon Ding 	u32 esmart_lb_mode;
146763cb669fSSandy Huang 	bool global_init;
1468a552a69cSDamon Ding 	bool merge_irq;
1469d0408543SAndy Yan 	const struct vop2_data *data;
1470b0989546SSandy Huang 	struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
1471d0408543SAndy Yan };
1472d0408543SAndy Yan 
1473d0408543SAndy Yan static struct vop2 *rockchip_vop2;
14745fa6e665SDamon Ding 
147527cec8e2SDamon Ding /* vop2_layer_phy_id */
147627cec8e2SDamon Ding static const char *const vop2_layer_name_list[] = {
147727cec8e2SDamon Ding 	"Cluster0",
147827cec8e2SDamon Ding 	"Cluster1",
147927cec8e2SDamon Ding 	"Esmart0",
148027cec8e2SDamon Ding 	"Esmart1",
148127cec8e2SDamon Ding 	"Smart0",
148227cec8e2SDamon Ding 	"Smart1",
148327cec8e2SDamon Ding 	"Cluster2",
148427cec8e2SDamon Ding 	"Cluster3",
148527cec8e2SDamon Ding 	"Esmart2",
148627cec8e2SDamon Ding 	"Esmart3",
148727cec8e2SDamon Ding };
148827cec8e2SDamon Ding 
vop2_plane_phys_id_to_string(u8 phys_id)1489a7cb29b7SDamon Ding static inline const char *vop2_plane_phys_id_to_string(u8 phys_id)
149027cec8e2SDamon Ding {
1491a7cb29b7SDamon Ding 	if (phys_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
149227cec8e2SDamon Ding 		return "INVALID";
149327cec8e2SDamon Ding 
1494a7cb29b7SDamon Ding 	if (phys_id >= ARRAY_SIZE(vop2_layer_name_list))
149527cec8e2SDamon Ding 		return NULL;
149627cec8e2SDamon Ding 
1497a7cb29b7SDamon Ding 	return vop2_layer_name_list[phys_id];
149827cec8e2SDamon Ding }
149927cec8e2SDamon Ding 
is_vop3(struct vop2 * vop2)15005fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2)
15015fa6e665SDamon Ding {
15025fa6e665SDamon Ding 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588)
15035fa6e665SDamon Ding 		return false;
15045fa6e665SDamon Ding 	else
15055fa6e665SDamon Ding 		return true;
15065fa6e665SDamon Ding }
15075fa6e665SDamon Ding 
15083e39a5a1SSandy Huang /*
15093e39a5a1SSandy Huang  * bli_sd_factor = (src - 1) / (dst - 1) << 12;
15103e39a5a1SSandy Huang  * avg_sd_factor:
15113e39a5a1SSandy Huang  * bli_su_factor:
15123e39a5a1SSandy Huang  * bic_su_factor:
15133e39a5a1SSandy Huang  * = (src - 1) / (dst - 1) << 16;
15143e39a5a1SSandy Huang  *
15155fa6e665SDamon Ding  * ygt2 enable: dst get one line from two line of the src
15165fa6e665SDamon Ding  * ygt4 enable: dst get one line from four line of the src.
15173e39a5a1SSandy Huang  *
15183e39a5a1SSandy Huang  */
15193e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst)	(((src - 1) << 12) / (dst - 1))
15203e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst)	(((src - 1) << 16) / (dst - 1))
15213e39a5a1SSandy Huang 
15223e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)	 \
15233e39a5a1SSandy Huang 				(fac * (dst - 1) >> 12 < (src - 1))
15243e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
15253e39a5a1SSandy Huang 				(fac * (dst - 1) >> 16 < (src - 1))
15265fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
15275fa6e665SDamon Ding 				(fac * (dst - 1) >> 16 < (src - 1))
15283e39a5a1SSandy Huang 
vop2_scale_factor(enum scale_mode mode,int32_t filter_mode,uint32_t src,uint32_t dst)15293e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode,
15303e39a5a1SSandy Huang 				  int32_t filter_mode,
15313e39a5a1SSandy Huang 				  uint32_t src, uint32_t dst)
15323e39a5a1SSandy Huang {
15333e39a5a1SSandy Huang 	uint32_t fac = 0;
15343e39a5a1SSandy Huang 	int i = 0;
15353e39a5a1SSandy Huang 
15363e39a5a1SSandy Huang 	if (mode == SCALE_NONE)
15373e39a5a1SSandy Huang 		return 0;
15383e39a5a1SSandy Huang 
15393e39a5a1SSandy Huang 	/*
15403e39a5a1SSandy Huang 	 * A workaround to avoid zero div.
15413e39a5a1SSandy Huang 	 */
15423e39a5a1SSandy Huang 	if ((dst == 1) || (src == 1)) {
15433e39a5a1SSandy Huang 		dst = dst + 1;
15443e39a5a1SSandy Huang 		src = src + 1;
15453e39a5a1SSandy Huang 	}
15463e39a5a1SSandy Huang 
15473e39a5a1SSandy Huang 	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
15483e39a5a1SSandy Huang 		fac = VOP2_BILI_SCL_DN(src, dst);
15493e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
15503e39a5a1SSandy Huang 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
15513e39a5a1SSandy Huang 				break;
15523e39a5a1SSandy Huang 			fac -= 1;
15533e39a5a1SSandy Huang 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15543e39a5a1SSandy Huang 		}
15553e39a5a1SSandy Huang 	} else {
15563e39a5a1SSandy Huang 		fac = VOP2_COMMON_SCL(src, dst);
15573e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
15583e39a5a1SSandy Huang 			if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
15593e39a5a1SSandy Huang 				break;
15603e39a5a1SSandy Huang 			fac -= 1;
15613e39a5a1SSandy Huang 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15623e39a5a1SSandy Huang 		}
15633e39a5a1SSandy Huang 	}
15643e39a5a1SSandy Huang 
15653e39a5a1SSandy Huang 	return fac;
15663e39a5a1SSandy Huang }
15673e39a5a1SSandy Huang 
vop3_scale_up_fac_check(uint32_t src,uint32_t dst,uint32_t fac,bool is_hor)15685fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor)
15695fa6e665SDamon Ding {
15705fa6e665SDamon Ding 	if (is_hor)
15715fa6e665SDamon Ding 		return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac);
15725fa6e665SDamon Ding 	return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac);
15735fa6e665SDamon Ding }
15745fa6e665SDamon Ding 
vop3_scale_factor(enum scale_mode mode,uint32_t src,uint32_t dst,bool is_hor)15755fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode,
15765fa6e665SDamon Ding 				  uint32_t src, uint32_t dst, bool is_hor)
15775fa6e665SDamon Ding {
15785fa6e665SDamon Ding 	uint32_t fac = 0;
15795fa6e665SDamon Ding 	int i = 0;
15805fa6e665SDamon Ding 
15815fa6e665SDamon Ding 	if (mode == SCALE_NONE)
15825fa6e665SDamon Ding 		return 0;
15835fa6e665SDamon Ding 
15845fa6e665SDamon Ding 	/*
15855fa6e665SDamon Ding 	 * A workaround to avoid zero div.
15865fa6e665SDamon Ding 	 */
15875fa6e665SDamon Ding 	if ((dst == 1) || (src == 1)) {
15885fa6e665SDamon Ding 		dst = dst + 1;
15895fa6e665SDamon Ding 		src = src + 1;
15905fa6e665SDamon Ding 	}
15915fa6e665SDamon Ding 
15925fa6e665SDamon Ding 	if (mode == SCALE_DOWN) {
15935fa6e665SDamon Ding 		fac = VOP2_BILI_SCL_DN(src, dst);
15945fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
15955fa6e665SDamon Ding 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
15965fa6e665SDamon Ding 				break;
15975fa6e665SDamon Ding 			fac -= 1;
15985fa6e665SDamon Ding 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15995fa6e665SDamon Ding 		}
16005fa6e665SDamon Ding 	} else {
16015fa6e665SDamon Ding 		fac = VOP2_COMMON_SCL(src, dst);
16025fa6e665SDamon Ding 		for (i = 0; i < 100; i++) {
16035fa6e665SDamon Ding 			if (vop3_scale_up_fac_check(src, dst, fac, is_hor))
16045fa6e665SDamon Ding 				break;
16055fa6e665SDamon Ding 			fac -= 1;
16065fa6e665SDamon Ding 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
16075fa6e665SDamon Ding 		}
16085fa6e665SDamon Ding 	}
16095fa6e665SDamon Ding 
16105fa6e665SDamon Ding 	return fac;
16115fa6e665SDamon Ding }
16125fa6e665SDamon Ding 
scl_get_scl_mode(int src,int dst)16133e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst)
16143e39a5a1SSandy Huang {
16153e39a5a1SSandy Huang 	if (src < dst)
16163e39a5a1SSandy Huang 		return SCALE_UP;
16173e39a5a1SSandy Huang 	else if (src > dst)
16183e39a5a1SSandy Huang 		return SCALE_DOWN;
16193e39a5a1SSandy Huang 
16203e39a5a1SSandy Huang 	return SCALE_NONE;
16213e39a5a1SSandy Huang }
1622d0408543SAndy Yan 
interpolate(int x1,int y1,int x2,int y2,int x)1623ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x)
1624ac500a1fSSandy Huang {
1625ac500a1fSSandy Huang 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
1626ac500a1fSSandy Huang }
1627ac500a1fSSandy Huang 
vop2_win_can_attach_to_vp(struct vop2_win_data * win_data,u8 vp_id)16286fea745cSDamon Ding static inline bool vop2_win_can_attach_to_vp(struct vop2_win_data *win_data, u8 vp_id)
1629b0989546SSandy Huang {
16306fea745cSDamon Ding 	return win_data->possible_vp_mask & BIT(vp_id);
1631ecc31b6eSAndy Yan }
1632b0989546SSandy Huang 
vop2_vp_find_attachable_win(struct display_state * state,u8 vp_id)16336fea745cSDamon Ding static int vop2_vp_find_attachable_win(struct display_state *state, u8 vp_id)
16346fea745cSDamon Ding {
16356fea745cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
16366fea745cSDamon Ding 	struct vop2 *vop2 = cstate->private;
16376fea745cSDamon Ding 	u32 plane_mask = cstate->crtc->vps[vp_id].plane_mask;
16386fea745cSDamon Ding 	int i = 0;
16396fea745cSDamon Ding 
16406fea745cSDamon Ding 	if (!plane_mask)
16416fea745cSDamon Ding 		return ROCKCHIP_VOP2_PHY_ID_INVALID;
16426fea745cSDamon Ding 
16436fea745cSDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
16446fea745cSDamon Ding 		if (vop2_win_can_attach_to_vp(&vop2->data->win_data[i], vp_id))
16456fea745cSDamon Ding 			break;
16466fea745cSDamon Ding 	}
16476fea745cSDamon Ding 
16486fea745cSDamon Ding 	return vop2->data->win_data[i].phys_id;
1649b0989546SSandy Huang }
1650b0989546SSandy Huang 
scl_cal_scale(int src,int dst,int shift)165163cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift)
1652d0408543SAndy Yan {
1653d0408543SAndy Yan 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
1654d0408543SAndy Yan }
1655d0408543SAndy Yan 
scl_cal_scale2(int src,int dst)165663cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst)
1657d0408543SAndy Yan {
1658d0408543SAndy Yan 	return ((src - 1) << 12) / (dst - 1);
1659d0408543SAndy Yan }
1660d0408543SAndy Yan 
vop2_writel(struct vop2 * vop2,u32 offset,u32 v)166152ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
1662d0408543SAndy Yan {
1663d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1664d0408543SAndy Yan 	vop2->regsbak[offset >> 2] = v;
1665d0408543SAndy Yan }
1666d0408543SAndy Yan 
vop2_readl(struct vop2 * vop2,u32 offset)166752ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
1668d0408543SAndy Yan {
1669d0408543SAndy Yan 	return readl(vop2->regs + offset);
1670d0408543SAndy Yan }
1671d0408543SAndy Yan 
vop2_mask_write(struct vop2 * vop2,u32 offset,u32 mask,u32 shift,u32 v,bool write_mask)167252ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
167352ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v,
1674d0408543SAndy Yan 				   bool write_mask)
1675d0408543SAndy Yan {
1676d0408543SAndy Yan 	if (!mask)
1677d0408543SAndy Yan 		return;
1678d0408543SAndy Yan 
1679d0408543SAndy Yan 	if (write_mask) {
1680d0408543SAndy Yan 		v = ((v & mask) << shift) | (mask << (shift + 16));
1681d0408543SAndy Yan 	} else {
168252ee18acSSandy Huang 		u32 cached_val = vop2->regsbak[offset >> 2];
1683d0408543SAndy Yan 
1684d0408543SAndy Yan 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
1685d0408543SAndy Yan 		vop2->regsbak[offset >> 2] = v;
1686d0408543SAndy Yan 	}
1687d0408543SAndy Yan 
1688d0408543SAndy Yan 	writel(v, vop2->regs + offset);
1689d0408543SAndy Yan }
1690d0408543SAndy Yan 
vop2_grf_writel(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift,u32 v)1691ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
169252ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v)
169352ee18acSSandy Huang {
169452ee18acSSandy Huang 	u32 val = 0;
169552ee18acSSandy Huang 
169652ee18acSSandy Huang 	val = (v << shift) | (mask << (shift + 16));
1697ecc31b6eSAndy Yan 	writel(val, grf_base + offset);
169852ee18acSSandy Huang }
169952ee18acSSandy Huang 
vop2_grf_readl(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift)170060e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
170160e469f5SDamon Ding 				  u32 mask, u32 shift)
170260e469f5SDamon Ding {
170360e469f5SDamon Ding 	return (readl(grf_base + offset) >> shift) & mask;
170460e469f5SDamon Ding }
170560e469f5SDamon Ding 
is_yuv_output(u32 bus_format)170652ee18acSSandy Huang static bool is_yuv_output(u32 bus_format)
1707d0408543SAndy Yan {
1708d0408543SAndy Yan 	switch (bus_format) {
1709d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
1710d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
1711034a46b5SAlgea Cao 	case MEDIA_BUS_FMT_YUYV10_1X20:
1712d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1713d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1714a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
1715a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
1716a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_2X8:
1717a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_2X8:
1718a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
1719a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
1720a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_1X16:
1721a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_1X16:
1722d0408543SAndy Yan 		return true;
1723d0408543SAndy Yan 	default:
1724d0408543SAndy Yan 		return false;
1725d0408543SAndy Yan 	}
1726d0408543SAndy Yan }
1727d0408543SAndy Yan 
vop2_convert_csc_mode(enum drm_color_encoding color_encoding,enum drm_color_range color_range,int bit_depth)1728df0a5c43SDamon Ding static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding,
1729df0a5c43SDamon Ding 						 enum drm_color_range color_range,
1730df0a5c43SDamon Ding 						 int bit_depth)
173110ee9f5bSAlgea Cao {
1732df0a5c43SDamon Ding 	bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
1733df0a5c43SDamon Ding 	enum vop_csc_format csc_mode = CSC_BT709L;
1734df0a5c43SDamon Ding 
1735df0a5c43SDamon Ding 
1736df0a5c43SDamon Ding 	switch (color_encoding) {
1737df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT601:
1738df0a5c43SDamon Ding 		if (full_range)
1739df0a5c43SDamon Ding 			csc_mode = CSC_BT601F;
17405fa6e665SDamon Ding 		else
1741df0a5c43SDamon Ding 			csc_mode = CSC_BT601L;
1742df0a5c43SDamon Ding 		break;
1743df0a5c43SDamon Ding 
1744df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT709:
1745df0a5c43SDamon Ding 		if (full_range) {
1746df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F;
1747df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1748df0a5c43SDamon Ding 				printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n");
17495fa6e665SDamon Ding 		} else {
1750df0a5c43SDamon Ding 			csc_mode = CSC_BT709L;
17515fa6e665SDamon Ding 		}
1752df0a5c43SDamon Ding 		break;
1753df0a5c43SDamon Ding 
1754df0a5c43SDamon Ding 	case DRM_COLOR_YCBCR_BT2020:
1755df0a5c43SDamon Ding 		if (full_range) {
1756df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F;
1757df0a5c43SDamon Ding 			if (bit_depth != CSC_13BIT_DEPTH)
1758df0a5c43SDamon Ding 				printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n");
17595fa6e665SDamon Ding 		} else {
1760df0a5c43SDamon Ding 			csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L;
17615fa6e665SDamon Ding 		}
1762df0a5c43SDamon Ding 		break;
1763df0a5c43SDamon Ding 
176410ee9f5bSAlgea Cao 	default:
1765df0a5c43SDamon Ding 		printf("Unsuport color_encoding:%d\n", color_encoding);
176610ee9f5bSAlgea Cao 	}
1767df0a5c43SDamon Ding 
1768df0a5c43SDamon Ding 	return csc_mode;
176910ee9f5bSAlgea Cao }
177010ee9f5bSAlgea Cao 
is_uv_swap(struct display_state * state)1771c8820b76SDamon Ding static bool is_uv_swap(struct display_state *state)
1772d0408543SAndy Yan {
1773c8820b76SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
1774c8820b76SDamon Ding 	u32 bus_format = conn_state->bus_format;
1775c8820b76SDamon Ding 	u32 output_mode = conn_state->output_mode;
1776c8820b76SDamon Ding 	u32 output_type = conn_state->type;
1777c8820b76SDamon Ding 
1778d0408543SAndy Yan 	/*
1779d0408543SAndy Yan 	 * FIXME:
1780d0408543SAndy Yan 	 *
1781d0408543SAndy Yan 	 * There is no media type for YUV444 output,
1782d0408543SAndy Yan 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
1783d0408543SAndy Yan 	 * yuv format.
1784d0408543SAndy Yan 	 *
1785c8820b76SDamon Ding 	 * From H/W testing, YUV444 mode need a rb swap except eDP.
1786d0408543SAndy Yan 	 */
17873e59c137SSandy Huang 	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
17883e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
17893e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
17903e59c137SSandy Huang 	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
17913e59c137SSandy Huang 	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1792d0408543SAndy Yan 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1793d0408543SAndy Yan 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
1794c8820b76SDamon Ding 	     output_mode == ROCKCHIP_OUT_MODE_P888) &&
1795c8820b76SDamon Ding 	     !(output_type == DRM_MODE_CONNECTOR_eDP)))
1796d0408543SAndy Yan 		return true;
1797d0408543SAndy Yan 	else
1798d0408543SAndy Yan 		return false;
1799d0408543SAndy Yan }
1800d0408543SAndy Yan 
is_rb_swap(struct display_state * state)1801c8820b76SDamon Ding static bool is_rb_swap(struct display_state *state)
18020675a2a4SDamon Ding {
1803c8820b76SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
1804c8820b76SDamon Ding 	u32 bus_format = conn_state->bus_format;
1805c8820b76SDamon Ding 
18060675a2a4SDamon Ding 	/*
18070675a2a4SDamon Ding 	 * The default component order of serial rgb3x8 formats
18080675a2a4SDamon Ding 	 * is BGR. So it is needed to enable RB swap.
18090675a2a4SDamon Ding 	 */
1810b7b383ebSDamon Ding 	if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
1811b7b383ebSDamon Ding 	    bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8)
18120675a2a4SDamon Ding 		return true;
18130675a2a4SDamon Ding 	else
18140675a2a4SDamon Ding 		return false;
18150675a2a4SDamon Ding }
18160675a2a4SDamon Ding 
is_yc_swap(u32 bus_format)18175d2768f7SDamon Ding static bool is_yc_swap(u32 bus_format)
18185d2768f7SDamon Ding {
18195d2768f7SDamon Ding 	switch (bus_format) {
18205d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
18215d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
18225d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
18235d2768f7SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
18245d2768f7SDamon Ding 		return true;
18255d2768f7SDamon Ding 	default:
18265d2768f7SDamon Ding 		return false;
18275d2768f7SDamon Ding 	}
18285d2768f7SDamon Ding }
18295d2768f7SDamon Ding 
is_hot_plug_devices(int output_type)1830b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type)
183163cb669fSSandy Huang {
1832b0989546SSandy Huang 	switch (output_type) {
1833b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIA:
1834b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIB:
1835b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_TV:
1836b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_DisplayPort:
1837b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_VGA:
1838b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_Unknown:
1839b0989546SSandy Huang 		return true;
1840b0989546SSandy Huang 	default:
1841b0989546SSandy Huang 		return false;
184263cb669fSSandy Huang 	}
184363cb669fSSandy Huang }
184463cb669fSSandy Huang 
vop2_find_win_by_phys_id(struct vop2 * vop2,int phys_id)1845ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1846ecc31b6eSAndy Yan {
1847ecc31b6eSAndy Yan 	int i = 0;
1848ecc31b6eSAndy Yan 
1849ecc31b6eSAndy Yan 	for (i = 0; i < vop2->data->nr_layers; i++) {
1850ecc31b6eSAndy Yan 		if (vop2->data->win_data[i].phys_id == phys_id)
1851ecc31b6eSAndy Yan 			return &vop2->data->win_data[i];
1852ecc31b6eSAndy Yan 	}
1853ecc31b6eSAndy Yan 
1854ecc31b6eSAndy Yan 	return NULL;
1855ecc31b6eSAndy Yan }
1856ecc31b6eSAndy Yan 
vop2_find_pd_data_by_id(struct vop2 * vop2,int pd_id)1857b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id)
1858b6ba80b4SDamon Ding {
1859b6ba80b4SDamon Ding 	int i = 0;
1860b6ba80b4SDamon Ding 
1861b6ba80b4SDamon Ding 	for (i = 0; i < vop2->data->nr_pd; i++) {
1862b6ba80b4SDamon Ding 		if (vop2->data->pd[i].id == pd_id)
1863b6ba80b4SDamon Ding 			return &vop2->data->pd[i];
1864b6ba80b4SDamon Ding 	}
1865b6ba80b4SDamon Ding 
1866b6ba80b4SDamon Ding 	return NULL;
1867b6ba80b4SDamon Ding }
1868b6ba80b4SDamon Ding 
rk3568_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1869db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1870db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1871db328a0dSDamon Ding {
1872db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1873db328a0dSDamon Ding 	int i;
1874db328a0dSDamon Ding 
1875db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1876db328a0dSDamon Ding 			GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1877db328a0dSDamon Ding 			crtc_id, false);
1878db328a0dSDamon Ding 
1879db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1880db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1881db328a0dSDamon Ding 
1882db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1883db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1884db328a0dSDamon Ding }
1885db328a0dSDamon Ding 
rk3588_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1886db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1887db328a0dSDamon Ding 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1888db328a0dSDamon Ding {
1889db328a0dSDamon Ding 	u32 vp_offset = crtc_id * 0x100;
1890db328a0dSDamon Ding 	int i;
1891db328a0dSDamon Ding 
18921828f293SDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
18931828f293SDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
18941828f293SDamon Ding 				GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
18951828f293SDamon Ding 				crtc_id, true);
18961828f293SDamon Ding 	else
1897db328a0dSDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1898db328a0dSDamon Ding 				GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1899db328a0dSDamon Ding 				crtc_id, false);
1900db328a0dSDamon Ding 
1901db328a0dSDamon Ding 	for (i = 0; i < lut_len; i++)
1902db328a0dSDamon Ding 		writel(lut_val[i], lut_regs + i);
1903db328a0dSDamon Ding 
1904db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1905db328a0dSDamon Ding 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1906db328a0dSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1907db328a0dSDamon Ding 			EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false);
1908db328a0dSDamon Ding }
1909db328a0dSDamon Ding 
rockchip_vop2_gamma_lut_init(struct vop2 * vop2,struct display_state * state)19101147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1911d0408543SAndy Yan 					struct display_state *state)
1912d0408543SAndy Yan {
19131147facaSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
19141147facaSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
19151147facaSSandy Huang 	struct resource gamma_res;
19161147facaSSandy Huang 	fdt_size_t lut_size;
19171147facaSSandy Huang 	int i, lut_len, ret = 0;
19181147facaSSandy Huang 	u32 *lut_regs;
19191147facaSSandy Huang 	u32 r, g, b;
19201147facaSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
19211147facaSSandy Huang 	static int gamma_lut_en_num = 1;
19221147facaSSandy Huang 
19231147facaSSandy Huang 	if (gamma_lut_en_num > vop2->data->nr_gammas) {
19241147facaSSandy Huang 		printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
19251147facaSSandy Huang 		return 0;
19261147facaSSandy Huang 	}
19271147facaSSandy Huang 
19281147facaSSandy Huang 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
19291147facaSSandy Huang 	if (ret)
19301147facaSSandy Huang 		printf("failed to get gamma lut res\n");
19311147facaSSandy Huang 	lut_regs = (u32 *)gamma_res.start;
19321147facaSSandy Huang 	lut_size = gamma_res.end - gamma_res.start + 1;
19331147facaSSandy Huang 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
19341147facaSSandy Huang 		printf("failed to get gamma lut register\n");
19351147facaSSandy Huang 		return 0;
19361147facaSSandy Huang 	}
19371147facaSSandy Huang 	lut_len = lut_size / 4;
19381147facaSSandy Huang 	if (lut_len != 256 && lut_len != 1024) {
19391147facaSSandy Huang 		printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
19401147facaSSandy Huang 		return 0;
19411147facaSSandy Huang 	}
19420669ab1fSDamon Ding 
19430669ab1fSDamon Ding 	if (!cstate->lut_val) {
19440669ab1fSDamon Ding 		if (!disp_info)
19450669ab1fSDamon Ding 			return 0;
19460669ab1fSDamon Ding 
19470669ab1fSDamon Ding 		if (!disp_info->gamma_lut_data.size)
19480669ab1fSDamon Ding 			return 0;
19490669ab1fSDamon Ding 
19500669ab1fSDamon Ding 		cstate->lut_val = (u32 *)calloc(1, lut_size);
19511147facaSSandy Huang 		for (i = 0; i < lut_len; i++) {
19521147facaSSandy Huang 			r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
19531147facaSSandy Huang 			g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
19541147facaSSandy Huang 			b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
19551147facaSSandy Huang 
19560669ab1fSDamon Ding 			cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
19570669ab1fSDamon Ding 		}
19581147facaSSandy Huang 	}
19591147facaSSandy Huang 
1960db328a0dSDamon Ding 	if (vop2->version == VOP_VERSION_RK3568) {
19610669ab1fSDamon Ding 		rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
19620669ab1fSDamon Ding 				     cstate->lut_val, lut_len);
19631147facaSSandy Huang 		gamma_lut_en_num++;
196418d9b8adSDamon Ding 	} else {
19650669ab1fSDamon Ding 		rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
19660669ab1fSDamon Ding 				     cstate->lut_val, lut_len);
1967db328a0dSDamon Ding 		if (cstate->splice_mode) {
19680669ab1fSDamon Ding 			rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs,
19690669ab1fSDamon Ding 					     cstate->lut_val, lut_len);
1970db328a0dSDamon Ding 			gamma_lut_en_num++;
1971db328a0dSDamon Ding 		}
1972db328a0dSDamon Ding 		gamma_lut_en_num++;
1973db328a0dSDamon Ding 	}
19741147facaSSandy Huang 
19750669ab1fSDamon Ding 	free(cstate->lut_val);
19760669ab1fSDamon Ding 
1977d0408543SAndy Yan 	return 0;
1978d0408543SAndy Yan }
1979d0408543SAndy Yan 
rockchip_vop2_cubic_lut_init(struct vop2 * vop2,struct display_state * state)19806414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
19816414e3bcSSandy Huang 					struct display_state *state)
19826414e3bcSSandy Huang {
19836414e3bcSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
19846414e3bcSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
19856414e3bcSSandy Huang 	int i, cubic_lut_len;
19866414e3bcSSandy Huang 	u32 vp_offset = cstate->crtc_id * 0x100;
19876414e3bcSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
19886414e3bcSSandy Huang 	struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
19896414e3bcSSandy Huang 	u32 *cubic_lut_addr;
19906414e3bcSSandy Huang 
19916414e3bcSSandy Huang 	if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
19926414e3bcSSandy Huang 		return 0;
19936414e3bcSSandy Huang 
19946414e3bcSSandy Huang 	if (!disp_info->cubic_lut_data.size)
19956414e3bcSSandy Huang 		return 0;
19966414e3bcSSandy Huang 
19976414e3bcSSandy Huang 	cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
19986414e3bcSSandy Huang 	cubic_lut_len = disp_info->cubic_lut_data.size;
19996414e3bcSSandy Huang 
20006414e3bcSSandy Huang 	for (i = 0; i < cubic_lut_len / 2; i++) {
20016414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
20026414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
20036414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
20046414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
20056414e3bcSSandy Huang 					((lut->lred[2 * i + 1] & 0xfff) << 4) +
20066414e3bcSSandy Huang 					((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
20076414e3bcSSandy Huang 					((lut->lblue[2 * i + 1] & 0xf) << 28);
20086414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
20096414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
20106414e3bcSSandy Huang 	}
20116414e3bcSSandy Huang 
20126414e3bcSSandy Huang 	if (cubic_lut_len % 2) {
20136414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
20146414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
20156414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
20166414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
20176414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
20186414e3bcSSandy Huang 		*cubic_lut_addr = 0;
20196414e3bcSSandy Huang 	}
20206414e3bcSSandy Huang 
20216414e3bcSSandy Huang 	vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
20226414e3bcSSandy Huang 		    get_cubic_lut_buffer(cstate->crtc_id));
20236414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
20246414e3bcSSandy Huang 			EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
20256414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
20266414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
20276414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
20286414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
20296414e3bcSSandy Huang 
20306414e3bcSSandy Huang 	return 0;
20316414e3bcSSandy Huang }
20326414e3bcSSandy Huang 
vop2_bcsh_reg_update(struct display_state * state,struct vop2 * vop2,struct bcsh_state * bcsh_state,int crtc_id)2033ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2,
2034ee01dbb2SDamon Ding 				 struct bcsh_state *bcsh_state, int crtc_id)
2035ee01dbb2SDamon Ding {
2036ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2037ee01dbb2SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
2038ee01dbb2SDamon Ding 
2039ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
2040ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false);
2041ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
2042ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false);
2043ee01dbb2SDamon Ding 
2044ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
2045ee01dbb2SDamon Ding 			BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2046ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
2047ee01dbb2SDamon Ding 			BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2048ee01dbb2SDamon Ding 
2049ee01dbb2SDamon Ding 	if (!cstate->bcsh_en) {
2050ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2051ee01dbb2SDamon Ding 				BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
2052ee01dbb2SDamon Ding 		return;
2053ee01dbb2SDamon Ding 	}
2054ee01dbb2SDamon Ding 
2055ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2056ee01dbb2SDamon Ding 			BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
2057ee01dbb2SDamon Ding 			bcsh_state->brightness, false);
2058ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2059ee01dbb2SDamon Ding 			BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false);
2060ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2061ee01dbb2SDamon Ding 			BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
2062ee01dbb2SDamon Ding 			bcsh_state->saturation * bcsh_state->contrast / 0x100, false);
2063ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2064ee01dbb2SDamon Ding 			BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false);
2065ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2066ee01dbb2SDamon Ding 			BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false);
2067ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2068ee01dbb2SDamon Ding 			BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
2069ee01dbb2SDamon Ding 			BCSH_OUT_MODE_NORMAL_VIDEO, false);
2070ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2071ee01dbb2SDamon Ding 			BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
2072ee01dbb2SDamon Ding }
2073ee01dbb2SDamon Ding 
vop2_tv_config_update(struct display_state * state,struct vop2 * vop2)2074ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
2075ac500a1fSSandy Huang {
2076ac500a1fSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
2077ac500a1fSSandy Huang 	struct base_bcsh_info *bcsh_info;
2078ac500a1fSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
2079ee01dbb2SDamon Ding 	struct bcsh_state bcsh_state;
2080ac500a1fSSandy Huang 	int brightness, contrast, saturation, hue, sin_hue, cos_hue;
2081ac500a1fSSandy Huang 
2082ac500a1fSSandy Huang 	if (!conn_state->disp_info)
2083ac500a1fSSandy Huang 		return;
2084ac500a1fSSandy Huang 	bcsh_info = &conn_state->disp_info->bcsh_info;
2085ac500a1fSSandy Huang 	if (!bcsh_info)
2086ac500a1fSSandy Huang 		return;
2087ac500a1fSSandy Huang 
2088ac500a1fSSandy Huang 	if (bcsh_info->brightness != 50 ||
2089ac500a1fSSandy Huang 	    bcsh_info->contrast != 50 ||
2090ac500a1fSSandy Huang 	    bcsh_info->saturation != 50 || bcsh_info->hue != 50)
2091ee01dbb2SDamon Ding 		cstate->bcsh_en = true;
2092ac500a1fSSandy Huang 
2093ee01dbb2SDamon Ding 	if (cstate->bcsh_en) {
2094ac500a1fSSandy Huang 		if (!cstate->yuv_overlay)
2095ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2096ac500a1fSSandy Huang 		if (!is_yuv_output(conn_state->bus_format))
2097ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2098ac500a1fSSandy Huang 	} else {
2099ac500a1fSSandy Huang 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2100ee01dbb2SDamon Ding 			cstate->post_r2y_en = 1;
2101ac500a1fSSandy Huang 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2102ee01dbb2SDamon Ding 			cstate->post_y2r_en = 1;
2103ac500a1fSSandy Huang 	}
2104ac500a1fSSandy Huang 
2105df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2106df0a5c43SDamon Ding 						      conn_state->color_range,
2107df0a5c43SDamon Ding 						      CSC_10BIT_DEPTH);
2108ac500a1fSSandy Huang 
2109ac500a1fSSandy Huang 	if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
2110ac500a1fSSandy Huang 		brightness = interpolate(0, -128, 100, 127,
2111ac500a1fSSandy Huang 					 bcsh_info->brightness);
2112ac500a1fSSandy Huang 	else
2113ac500a1fSSandy Huang 		brightness = interpolate(0, -32, 100, 31,
2114ac500a1fSSandy Huang 					 bcsh_info->brightness);
2115ac500a1fSSandy Huang 	contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
2116ac500a1fSSandy Huang 	saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
2117ac500a1fSSandy Huang 	hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
2118ac500a1fSSandy Huang 
2119ac500a1fSSandy Huang 
2120ac500a1fSSandy Huang 	/*
2121ac500a1fSSandy Huang 	 *  a:[-30~0):
2122ac500a1fSSandy Huang 	 *    sin_hue = 0x100 - sin(a)*256;
2123ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2124ac500a1fSSandy Huang 	 *  a:[0~30]
2125ac500a1fSSandy Huang 	 *    sin_hue = sin(a)*256;
2126ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
2127ac500a1fSSandy Huang 	 */
2128ac500a1fSSandy Huang 	sin_hue = fixp_sin32(hue) >> 23;
2129ac500a1fSSandy Huang 	cos_hue = fixp_cos32(hue) >> 23;
2130ac500a1fSSandy Huang 
2131ee01dbb2SDamon Ding 	bcsh_state.brightness = brightness;
2132ee01dbb2SDamon Ding 	bcsh_state.contrast = contrast;
2133ee01dbb2SDamon Ding 	bcsh_state.saturation = saturation;
2134ee01dbb2SDamon Ding 	bcsh_state.sin_hue = sin_hue;
2135ee01dbb2SDamon Ding 	bcsh_state.cos_hue = cos_hue;
2136ee01dbb2SDamon Ding 
2137ee01dbb2SDamon Ding 	vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id);
2138ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2139ee01dbb2SDamon Ding 		vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id);
2140ee01dbb2SDamon Ding }
2141ee01dbb2SDamon Ding 
vop2_setup_dly_for_vp(struct display_state * state,struct vop2 * vop2,int crtc_id)2142ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id)
2143ee01dbb2SDamon Ding {
2144ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2145ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2146ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2147ee01dbb2SDamon Ding 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
2148ee01dbb2SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2149ee01dbb2SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2150ee01dbb2SDamon Ding 
2151ee01dbb2SDamon Ding 	bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly;
2152ee01dbb2SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly;
2153ee01dbb2SDamon Ding 	bg_dly -= bg_ovl_dly;
2154ee01dbb2SDamon Ding 
2155a552a69cSDamon Ding 	/*
2156a552a69cSDamon Ding 	 * splice mode: hdisplay must roundup as 4 pixel,
2157a552a69cSDamon Ding 	 * no splice mode: hdisplay must roundup as 2 pixel.
2158a552a69cSDamon Ding 	 */
2159ee01dbb2SDamon Ding 	if (cstate->splice_mode)
2160a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1;
2161ee01dbb2SDamon Ding 	else
2162a552a69cSDamon Ding 		pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2163ee01dbb2SDamon Ding 
2164ee01dbb2SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
2165ee01dbb2SDamon Ding 		hsync_len = 8;
2166ee01dbb2SDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
2167ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4,
2168ee01dbb2SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2169ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2170ac500a1fSSandy Huang }
2171ac500a1fSSandy Huang 
vop3_setup_pipe_dly(struct display_state * state,struct vop2 * vop2,int crtc_id)2172452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id)
2173452afb13SDamon Ding {
2174452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2175452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2176452afb13SDamon Ding 	u32 bg_dly, pre_scan_dly;
2177452afb13SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
2178452afb13SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2179452afb13SDamon Ding 
2180452afb13SDamon Ding 	bg_dly = vop2->data->vp_data[crtc_id].win_dly +
2181452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].layer_mix_dly +
2182452afb13SDamon Ding 		 vop2->data->vp_data[crtc_id].hdr_mix_dly;
2183a552a69cSDamon Ding 	/* hdisplay must roundup as 2 pixel */
2184a552a69cSDamon Ding 	pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2185a552a69cSDamon Ding 	/**
2186a552a69cSDamon Ding 	 * pre_scan_hblank minimum value is 8, otherwise the win reset signal will
2187a552a69cSDamon Ding 	 * lead to first line data be zero.
2188a552a69cSDamon Ding 	 */
2189a552a69cSDamon Ding 	pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len);
2190452afb13SDamon Ding 	vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100,
2191452afb13SDamon Ding 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2192452afb13SDamon Ding 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2193452afb13SDamon Ding }
2194452afb13SDamon Ding 
vop2_post_config(struct display_state * state,struct vop2 * vop2)2195d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
2196d0408543SAndy Yan {
2197d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
2198d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
219952ee18acSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
22009c7848c3SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
22019c7848c3SDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
2202b888dbc8SSandy Huang 	struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[cstate->crtc_id];
220352ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
2204d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
2205d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
2206d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
2207d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
2208d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
2209668e6278SDamon Ding 	u16 hsize;
2210668e6278SDamon Ding 	u16 vsize;
2211d0408543SAndy Yan 	u16 hact_end, vact_end;
2212d0408543SAndy Yan 	u32 val;
2213d0408543SAndy Yan 
2214668e6278SDamon Ding 	/*
2215668e6278SDamon Ding 	 * For RK3576, use the win scale instead of the post scale to configure
2216668e6278SDamon Ding 	 * overscan parameters, because the sharp/post scale/split functions are
2217668e6278SDamon Ding 	 * mutually exclusice.
2218668e6278SDamon Ding 	 */
2219668e6278SDamon Ding 	if (vop2->version == VOP_VERSION_RK3576) {
2220668e6278SDamon Ding 		hsize = hdisplay;
2221668e6278SDamon Ding 		vsize = vdisplay;
2222668e6278SDamon Ding 
2223668e6278SDamon Ding 		cstate->overscan_by_win_scale = true;
2224668e6278SDamon Ding 	} else {
2225668e6278SDamon Ding 		hsize = hdisplay * (conn_state->overscan.left_margin +
2226668e6278SDamon Ding 				    conn_state->overscan.right_margin) / 200;
2227668e6278SDamon Ding 		vsize = vdisplay * (conn_state->overscan.top_margin +
2228668e6278SDamon Ding 				    conn_state->overscan.bottom_margin) / 200;
222974bd8269SSandy Huang 		hsize = round_down(hsize, 2);
2230d0408543SAndy Yan 		vsize = round_down(vsize, 2);
2231d0408543SAndy Yan 
2232d0408543SAndy Yan 		hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
2233668e6278SDamon Ding 		vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
2234668e6278SDamon Ding 	}
2235668e6278SDamon Ding 
2236d0408543SAndy Yan 	hact_end = hact_st + hsize;
2237d0408543SAndy Yan 	val = hact_st << 16;
2238d0408543SAndy Yan 	val |= hact_end;
223952ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
2240d0408543SAndy Yan 	vact_end = vact_st + vsize;
2241d0408543SAndy Yan 	val = vact_st << 16;
2242d0408543SAndy Yan 	val |= vact_end;
224352ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
2244d0408543SAndy Yan 	val = scl_cal_scale2(vdisplay, vsize) << 16;
2245d0408543SAndy Yan 	val |= scl_cal_scale2(hdisplay, hsize);
224652ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
2247d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
2248d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
22497504507fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
22507504507fSSandy Huang 			RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT,
2251d0408543SAndy Yan 			POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
22527504507fSSandy Huang 			POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false);
2253d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
2254d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
2255d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vsize;
2256d0408543SAndy Yan 
2257d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
225852ee18acSSandy Huang 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
2259d0408543SAndy Yan 	}
2260d0408543SAndy Yan 
2261452afb13SDamon Ding 	if (is_vop3(vop2)) {
2262452afb13SDamon Ding 		vop3_setup_pipe_dly(state, vop2, cstate->crtc_id);
2263452afb13SDamon Ding 	} else {
2264ee01dbb2SDamon Ding 		vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id);
2265b888dbc8SSandy Huang 		vop2_ops->setup_win_dly(state, cstate->crtc_id, plane_mask->primary_plane_id);
22669c7848c3SDamon Ding 		if (cstate->splice_mode) {
2267b888dbc8SSandy Huang 			plane_mask = &vop2->vp_plane_mask[cstate->splice_crtc_id];
2268ee01dbb2SDamon Ding 			vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id);
2269b888dbc8SSandy Huang 			vop2_ops->setup_win_dly(state, cstate->splice_crtc_id, plane_mask->primary_plane_id);
22709c7848c3SDamon Ding 		}
2271d0408543SAndy Yan 	}
2272452afb13SDamon Ding }
2273d0408543SAndy Yan 
vop3_post_acm_config(struct display_state * state,struct vop2 * vop2)22746027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2)
22756027c871SZhang Yubing {
22766027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
22776027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
22786027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
22796027c871SZhang Yubing 	struct drm_display_mode *mode = &conn_state->mode;
22806027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
22816027c871SZhang Yubing 	s16 *lut_y;
22826027c871SZhang Yubing 	s16 *lut_h;
22836027c871SZhang Yubing 	s16 *lut_s;
22846027c871SZhang Yubing 	u32 value;
22856027c871SZhang Yubing 	int i;
22866027c871SZhang Yubing 
22876027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2288b8db91d0SZhang Yubing 		POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2289b8db91d0SZhang Yubing 	if (!acm->acm_enable) {
2290b8db91d0SZhang Yubing 		writel(0, vop2->regs + RK3528_ACM_CTRL);
22916027c871SZhang Yubing 		return;
22926027c871SZhang Yubing 	}
22936027c871SZhang Yubing 
22946027c871SZhang Yubing 	printf("post acm enable\n");
22956027c871SZhang Yubing 
22966027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_START);
22976027c871SZhang Yubing 
22986027c871SZhang Yubing 	value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) +
22996027c871SZhang Yubing 		((mode->vdisplay & 0xfff) << 20);
23006027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_CTRL);
23016027c871SZhang Yubing 
23026027c871SZhang Yubing 	value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
23036027c871SZhang Yubing 		((acm->s_gain << 20) & 0x3ff00000);
23046027c871SZhang Yubing 	writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE);
23056027c871SZhang Yubing 
23066027c871SZhang Yubing 	lut_y = &acm->gain_lut_hy[0];
23076027c871SZhang Yubing 	lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
23086027c871SZhang Yubing 	lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
23096027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
23106027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
23116027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
23126027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
23136027c871SZhang Yubing 	}
23146027c871SZhang Yubing 
23156027c871SZhang Yubing 	lut_y = &acm->gain_lut_hs[0];
23166027c871SZhang Yubing 	lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
23176027c871SZhang Yubing 	lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
23186027c871SZhang Yubing 	for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
23196027c871SZhang Yubing 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
23206027c871SZhang Yubing 			((lut_s[i] << 16) & 0xff0000);
23216027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
23226027c871SZhang Yubing 	}
23236027c871SZhang Yubing 
23246027c871SZhang Yubing 	lut_y = &acm->delta_lut_h[0];
23256027c871SZhang Yubing 	lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
23266027c871SZhang Yubing 	lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
23276027c871SZhang Yubing 	for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
23286027c871SZhang Yubing 		value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
23296027c871SZhang Yubing 			((lut_s[i] << 20) & 0x3ff00000);
23306027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
23316027c871SZhang Yubing 	}
23326027c871SZhang Yubing 
23336027c871SZhang Yubing 	writel(1, vop2->regs + RK3528_ACM_FETCH_DONE);
23346027c871SZhang Yubing }
23356027c871SZhang Yubing 
vop3_get_csc_info_from_bcsh(struct display_state * state,struct csc_info * csc_info)233628dc0247SDamon Ding static void vop3_get_csc_info_from_bcsh(struct display_state *state,
233728dc0247SDamon Ding 					struct csc_info *csc_info)
233828dc0247SDamon Ding {
233928dc0247SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
234028dc0247SDamon Ding 	struct base_bcsh_info *bcsh_info;
234128dc0247SDamon Ding 
234228dc0247SDamon Ding 	if (!conn_state->disp_info)
234328dc0247SDamon Ding 		return;
234428dc0247SDamon Ding 
234528dc0247SDamon Ding 	bcsh_info = &conn_state->disp_info->bcsh_info;
234628dc0247SDamon Ding 	if (!bcsh_info)
234728dc0247SDamon Ding 		return;
234828dc0247SDamon Ding 
234928dc0247SDamon Ding 	csc_info->r_gain = 256;
235028dc0247SDamon Ding 	csc_info->g_gain = 256;
235128dc0247SDamon Ding 	csc_info->b_gain = 256;
235228dc0247SDamon Ding 	csc_info->r_offset = 256;
235328dc0247SDamon Ding 	csc_info->g_offset = 256;
235428dc0247SDamon Ding 	csc_info->b_offset = 256;
235528dc0247SDamon Ding 	if (bcsh_info->brightness == 50 && bcsh_info->contrast == 50 &&
235628dc0247SDamon Ding 	    bcsh_info->saturation == 50 && bcsh_info->hue == 50) {
235728dc0247SDamon Ding 		csc_info->csc_enable = false;
235828dc0247SDamon Ding 		csc_info->brightness = 256;
235928dc0247SDamon Ding 		csc_info->contrast = 256;
236028dc0247SDamon Ding 		csc_info->saturation = 256;
236128dc0247SDamon Ding 		csc_info->hue = 256;
236228dc0247SDamon Ding 	} else {
236328dc0247SDamon Ding 		csc_info->csc_enable = true;
236428dc0247SDamon Ding 		csc_info->brightness = bcsh_info->brightness * 511 / 100;
236528dc0247SDamon Ding 		csc_info->contrast = bcsh_info->contrast * 511 / 100;
236628dc0247SDamon Ding 		csc_info->saturation = bcsh_info->saturation * 511 / 100;
236728dc0247SDamon Ding 		csc_info->hue = bcsh_info->hue * 511 / 100;
236828dc0247SDamon Ding 	}
236928dc0247SDamon Ding }
237028dc0247SDamon Ding 
vop3_post_csc_config(struct display_state * state,struct vop2 * vop2)23716027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2)
23726027c871SZhang Yubing {
23736027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
23746027c871SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
23756027c871SZhang Yubing 	struct acm_data *acm = &conn_state->disp_info->acm_data;
23766027c871SZhang Yubing 	struct csc_info *csc = &conn_state->disp_info->csc_info;
23776027c871SZhang Yubing 	struct post_csc_coef csc_coef;
23786027c871SZhang Yubing 	bool is_input_yuv = false;
23796027c871SZhang Yubing 	bool is_output_yuv = false;
23806027c871SZhang Yubing 	bool post_r2y_en = false;
23816027c871SZhang Yubing 	bool post_csc_en = false;
23826027c871SZhang Yubing 	u32 vp_offset = (cstate->crtc_id * 0x100);
23836027c871SZhang Yubing 	u32 value;
23846027c871SZhang Yubing 	int range_type;
23856027c871SZhang Yubing 
23866027c871SZhang Yubing 	printf("post csc enable\n");
23876027c871SZhang Yubing 
238828dc0247SDamon Ding 	if (!csc->csc_enable)
238928dc0247SDamon Ding 		vop3_get_csc_info_from_bcsh(state, csc);
239028dc0247SDamon Ding 
23916027c871SZhang Yubing 	if (acm->acm_enable) {
23926027c871SZhang Yubing 		if (!cstate->yuv_overlay)
23936027c871SZhang Yubing 			post_r2y_en = true;
23946027c871SZhang Yubing 
23956027c871SZhang Yubing 		/* do y2r in csc module */
23966027c871SZhang Yubing 		if (!is_yuv_output(conn_state->bus_format))
23976027c871SZhang Yubing 			post_csc_en = true;
23986027c871SZhang Yubing 	} else {
23996027c871SZhang Yubing 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
24006027c871SZhang Yubing 			post_r2y_en = true;
24016027c871SZhang Yubing 
24026027c871SZhang Yubing 		/* do y2r in csc module */
24036027c871SZhang Yubing 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
24046027c871SZhang Yubing 			post_csc_en = true;
24056027c871SZhang Yubing 	}
24066027c871SZhang Yubing 
24076027c871SZhang Yubing 	if (csc->csc_enable)
24086027c871SZhang Yubing 		post_csc_en = true;
24096027c871SZhang Yubing 
24106027c871SZhang Yubing 	if (cstate->yuv_overlay || post_r2y_en)
24116027c871SZhang Yubing 		is_input_yuv = true;
24126027c871SZhang Yubing 
24136027c871SZhang Yubing 	if (is_yuv_output(conn_state->bus_format))
24146027c871SZhang Yubing 		is_output_yuv = true;
24156027c871SZhang Yubing 
2416df0a5c43SDamon Ding 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2417df0a5c43SDamon Ding 						      conn_state->color_range,
2418df0a5c43SDamon Ding 						      CSC_13BIT_DEPTH);
24196027c871SZhang Yubing 
24206027c871SZhang Yubing 	if (post_csc_en) {
24216027c871SZhang Yubing 		rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv,
24226027c871SZhang Yubing 				       is_output_yuv);
24236027c871SZhang Yubing 
24246027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24256027c871SZhang Yubing 				POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT,
24266027c871SZhang Yubing 				csc_coef.csc_coef00, false);
24275743c73eSZhang Yubing 		value = csc_coef.csc_coef01 & 0xffff;
24285743c73eSZhang Yubing 		value |= (csc_coef.csc_coef02 << 16) & 0xffff0000;
24296027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02);
24305743c73eSZhang Yubing 		value = csc_coef.csc_coef10 & 0xffff;
24315743c73eSZhang Yubing 		value |= (csc_coef.csc_coef11 << 16) & 0xffff0000;
24326027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11);
24335743c73eSZhang Yubing 		value = csc_coef.csc_coef12 & 0xffff;
24345743c73eSZhang Yubing 		value |= (csc_coef.csc_coef20 << 16) & 0xffff0000;
24356027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20);
24365743c73eSZhang Yubing 		value = csc_coef.csc_coef21 & 0xffff;
24375743c73eSZhang Yubing 		value |= (csc_coef.csc_coef22 << 16) & 0xffff0000;
24386027c871SZhang Yubing 		writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22);
24396027c871SZhang Yubing 		writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0);
24406027c871SZhang Yubing 		writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1);
24416027c871SZhang Yubing 		writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2);
24426027c871SZhang Yubing 
24436027c871SZhang Yubing 		range_type = csc_coef.range_type ? 0 : 1;
24446027c871SZhang Yubing 		range_type <<= is_input_yuv ? 0 : 1;
24456027c871SZhang Yubing 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24466027c871SZhang Yubing 				POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false);
24476027c871SZhang Yubing 	}
24486027c871SZhang Yubing 
24496027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24505743c73eSZhang Yubing 			POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false);
24516027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24526027c871SZhang Yubing 			POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false);
24536027c871SZhang Yubing 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24546027c871SZhang Yubing 			POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false);
24556027c871SZhang Yubing }
24566027c871SZhang Yubing 
vop3_post_config(struct display_state * state,struct vop2 * vop2)24576027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2)
24586027c871SZhang Yubing {
24596027c871SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
24606027c871SZhang Yubing 	struct base2_disp_info *disp_info = conn_state->disp_info;
24616027c871SZhang Yubing 	const char *enable_flag;
24626027c871SZhang Yubing 	if (!disp_info) {
24636027c871SZhang Yubing 		printf("disp_info is empty\n");
24646027c871SZhang Yubing 		return;
24656027c871SZhang Yubing 	}
24666027c871SZhang Yubing 
24676027c871SZhang Yubing 	enable_flag = (const char *)&disp_info->cacm_header;
24686027c871SZhang Yubing 	if (strncasecmp(enable_flag, "CACM", 4)) {
24696027c871SZhang Yubing 		printf("acm and csc is not support\n");
24706027c871SZhang Yubing 		return;
24716027c871SZhang Yubing 	}
24726027c871SZhang Yubing 
24736027c871SZhang Yubing 	vop3_post_acm_config(state, vop2);
24746027c871SZhang Yubing 	vop3_post_csc_config(state, vop2);
24756027c871SZhang Yubing }
24766027c871SZhang Yubing 
rk3576_vop2_wait_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2477a552a69cSDamon Ding static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2,
2478a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
2479a552a69cSDamon Ding {
2480a552a69cSDamon Ding 	int val = 0;
2481a552a69cSDamon Ding 	bool is_bisr_en, is_otp_bisr_en;
2482a552a69cSDamon Ding 
2483a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER) {
2484a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2485a552a69cSDamon Ding 					    EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2486a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2487a552a69cSDamon Ding 						EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2488a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2489a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2490a552a69cSDamon Ding 						  val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1),
2491a552a69cSDamon Ding 						  50 * 1000);
2492a552a69cSDamon Ding 		else
2493a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
24940e0a0ff9SDamon Ding 						  val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1),
2495a552a69cSDamon Ding 						  50 * 1000);
2496a552a69cSDamon Ding 	} else {
2497a552a69cSDamon Ding 		is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2498a552a69cSDamon Ding 					    EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2499a552a69cSDamon Ding 		is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2500a552a69cSDamon Ding 						EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2501a552a69cSDamon Ding 		if (is_bisr_en && is_otp_bisr_en)
2502a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2503a552a69cSDamon Ding 						  val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1),
2504a552a69cSDamon Ding 						  50 * 1000);
2505a552a69cSDamon Ding 		else
2506a552a69cSDamon Ding 			return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2507a552a69cSDamon Ding 						  val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1),
2508a552a69cSDamon Ding 						  50 * 1000);
2509a552a69cSDamon Ding 	}
2510a552a69cSDamon Ding }
2511a552a69cSDamon Ding 
rk3576_vop2_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2512a552a69cSDamon Ding static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2513a552a69cSDamon Ding {
2514a552a69cSDamon Ding 	int ret = 0;
2515a552a69cSDamon Ding 
2516a552a69cSDamon Ding 	if (pd_data->id == VOP2_PD_CLUSTER)
2517a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK,
2518a552a69cSDamon Ding 				RK3576_CLUSTER_PD_EN_SHIFT, 0, true);
2519a552a69cSDamon Ding 	else
2520a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK,
2521a552a69cSDamon Ding 				RK3576_ESMART_PD_EN_SHIFT, 0, true);
2522a552a69cSDamon Ding 	ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data);
2523a552a69cSDamon Ding 	if (ret) {
2524a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2525a552a69cSDamon Ding 		return ret;
2526a552a69cSDamon Ding 	}
2527a552a69cSDamon Ding 
2528a552a69cSDamon Ding 	return 0;
2529a552a69cSDamon Ding }
2530a552a69cSDamon Ding 
rk3588_vop2_wait_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2531a552a69cSDamon Ding static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2,
2532a552a69cSDamon Ding 					    struct vop2_power_domain_data *pd_data)
253360e469f5SDamon Ding {
253460e469f5SDamon Ding 	int val = 0;
253560e469f5SDamon Ding 	int shift = 0;
2536b6ba80b4SDamon Ding 	int shift_factor = 0;
253760e469f5SDamon Ding 	bool is_bisr_en = false;
253860e469f5SDamon Ding 
2539b6ba80b4SDamon Ding 	/*
2540b6ba80b4SDamon Ding 	 * The order of pd status bits in BISR_STS register
2541b6ba80b4SDamon Ding 	 * is different from that in VOP SYS_STS register.
2542b6ba80b4SDamon Ding 	 */
2543b6ba80b4SDamon Ding 	if (pd_data->id == VOP2_PD_DSC_8K ||
2544b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_DSC_4K ||
2545b6ba80b4SDamon Ding 	    pd_data->id == VOP2_PD_ESMART)
2546b6ba80b4SDamon Ding 		shift_factor = 1;
2547b6ba80b4SDamon Ding 
2548b6ba80b4SDamon Ding 	shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor;
2549b6ba80b4SDamon Ding 	is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift);
255060e469f5SDamon Ding 	if (is_bisr_en) {
2551b6ba80b4SDamon Ding 		shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor;
2552b6ba80b4SDamon Ding 
255360e469f5SDamon Ding 		return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
2554d2e91fdcSDamon Ding 					  ((val >> shift) & 0x1), 50 * 1000);
255560e469f5SDamon Ding 	} else {
2556b6ba80b4SDamon Ding 		shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1;
2557b6ba80b4SDamon Ding 
255860e469f5SDamon Ding 		return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
255960e469f5SDamon Ding 					  !((val >> shift) & 0x1), 50 * 1000);
256060e469f5SDamon Ding 	}
256160e469f5SDamon Ding }
256260e469f5SDamon Ding 
rk3588_vop2_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2563a552a69cSDamon Ding static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2564a552a69cSDamon Ding {
2565a552a69cSDamon Ding 	int ret = 0;
2566a552a69cSDamon Ding 
2567a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK,
2568a552a69cSDamon Ding 			RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false);
2569a552a69cSDamon Ding 	ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data);
2570a552a69cSDamon Ding 	if (ret) {
2571a552a69cSDamon Ding 		printf("wait vop2 power domain timeout\n");
2572a552a69cSDamon Ding 		return ret;
2573a552a69cSDamon Ding 	}
2574a552a69cSDamon Ding 
2575a552a69cSDamon Ding 	return 0;
2576a552a69cSDamon Ding }
2577a552a69cSDamon Ding 
vop2_power_domain_on(struct vop2 * vop2,int pd_id)2578b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id)
257960e469f5SDamon Ding {
258060e469f5SDamon Ding 	struct vop2_power_domain_data *pd_data;
258160e469f5SDamon Ding 	int ret = 0;
258260e469f5SDamon Ding 
2583b6ba80b4SDamon Ding 	if (!pd_id)
2584b6ba80b4SDamon Ding 		return 0;
2585b6ba80b4SDamon Ding 
2586b6ba80b4SDamon Ding 	pd_data = vop2_find_pd_data_by_id(vop2, pd_id);
2587b6ba80b4SDamon Ding 	if (!pd_data) {
2588b6ba80b4SDamon Ding 		printf("can't find pd_data by id\n");
258960e469f5SDamon Ding 		return -EINVAL;
259060e469f5SDamon Ding 	}
25912c66af11SDamon Ding 
2592b6ba80b4SDamon Ding 	if (pd_data->parent_id) {
2593b6ba80b4SDamon Ding 		ret = vop2_power_domain_on(vop2, pd_data->parent_id);
259460e469f5SDamon Ding 		if (ret) {
259560e469f5SDamon Ding 			printf("can't open parent power domain\n");
259660e469f5SDamon Ding 			return -EINVAL;
259760e469f5SDamon Ding 		}
259860e469f5SDamon Ding 	}
259960e469f5SDamon Ding 
2600a552a69cSDamon Ding 	/*
2601a552a69cSDamon Ding 	 * Read VOP internal power domain on/off status.
2602a552a69cSDamon Ding 	 * We should query BISR_STS register in PMU for
2603a552a69cSDamon Ding 	 * power up/down status when memory repair is enabled.
2604a552a69cSDamon Ding 	 * Return value: 1 for power on, 0 for power off;
2605a552a69cSDamon Ding 	 */
2606a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
2607a552a69cSDamon Ding 		ret = rk3576_vop2_power_domain_on(vop2, pd_data);
2608a552a69cSDamon Ding 	else
2609a552a69cSDamon Ding 		ret = rk3588_vop2_power_domain_on(vop2, pd_data);
261060e469f5SDamon Ding 
2611a552a69cSDamon Ding 	return ret;
261260e469f5SDamon Ding }
261360e469f5SDamon Ding 
rk3588_vop2_regsbak(struct vop2 * vop2)2614ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2)
2615ecc31b6eSAndy Yan {
2616ecc31b6eSAndy Yan 	u32 *base = vop2->regs;
2617ecc31b6eSAndy Yan 	int i = 0;
2618ecc31b6eSAndy Yan 
2619ecc31b6eSAndy Yan 	/*
2620ecc31b6eSAndy Yan 	 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
2621ecc31b6eSAndy Yan 	 */
2622ecc31b6eSAndy Yan 	for (i = 0; i < (vop2->reg_len >> 2); i++)
2623ecc31b6eSAndy Yan 		vop2->regsbak[i] = base[i];
2624ecc31b6eSAndy Yan }
2625ecc31b6eSAndy Yan 
vop3_ignore_plane(struct vop2 * vop2,struct vop2_win_data * win)26265fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win)
26275fa6e665SDamon Ding {
26285fa6e665SDamon Ding 	if (!is_vop3(vop2))
26295fa6e665SDamon Ding 		return false;
26305fa6e665SDamon Ding 
26315fa6e665SDamon Ding 	if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
26325fa6e665SDamon Ding 	    win->phys_id != ROCKCHIP_VOP2_ESMART0)
26335fa6e665SDamon Ding 		return true;
26345fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
26355fa6e665SDamon Ding 		 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
26365fa6e665SDamon Ding 		return true;
26375fa6e665SDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
26385fa6e665SDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART1)
26395fa6e665SDamon Ding 		return true;
2640a552a69cSDamon Ding 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE &&
2641a552a69cSDamon Ding 		 win->phys_id == ROCKCHIP_VOP2_ESMART3)
2642a552a69cSDamon Ding 		return true;
26435fa6e665SDamon Ding 	else
26445fa6e665SDamon Ding 		return false;
26455fa6e665SDamon Ding }
26465fa6e665SDamon Ding 
vop3_init_esmart_scale_engine(struct vop2 * vop2)26475fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
26485fa6e665SDamon Ding {
26495fa6e665SDamon Ding 	struct vop2_win_data *win_data;
2650fa4ecc32SDamon Ding 	int i;
26515fa6e665SDamon Ding 	u8 scale_engine_num = 0;
26525fa6e665SDamon Ding 
26535fa6e665SDamon Ding 	/* store plane mask for vop2_fixup_dts */
2654fa4ecc32SDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
2655fa4ecc32SDamon Ding 		win_data = &vop2->data->win_data[i];
26565fa6e665SDamon Ding 		if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data))
26575fa6e665SDamon Ding 			continue;
26585fa6e665SDamon Ding 
26595fa6e665SDamon Ding 		win_data->scale_engine_num = scale_engine_num++;
26605fa6e665SDamon Ding 	}
26615fa6e665SDamon Ding }
26625fa6e665SDamon Ding 
vop3_get_esmart_lb_mode(struct vop2 * vop2)2663a552a69cSDamon Ding static int vop3_get_esmart_lb_mode(struct vop2 *vop2)
2664a552a69cSDamon Ding {
2665a552a69cSDamon Ding 	const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map;
2666a552a69cSDamon Ding 	int i;
2667a552a69cSDamon Ding 
2668a552a69cSDamon Ding 	if (!esmart_lb_mode_map)
2669a552a69cSDamon Ding 		return vop2->esmart_lb_mode;
2670a552a69cSDamon Ding 
2671a552a69cSDamon Ding 	for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) {
2672a552a69cSDamon Ding 		if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode)
2673a552a69cSDamon Ding 			return esmart_lb_mode_map->lb_map_value;
2674a552a69cSDamon Ding 		esmart_lb_mode_map++;
2675a552a69cSDamon Ding 	}
2676a552a69cSDamon Ding 
2677a552a69cSDamon Ding 	if (i == vop2->data->esmart_lb_mode_num)
2678a552a69cSDamon Ding 		printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode);
2679a552a69cSDamon Ding 
2680a552a69cSDamon Ding 	return vop2->data->esmart_lb_mode_map[0].lb_map_value;
2681a552a69cSDamon Ding }
2682a552a69cSDamon Ding 
vop2_plane_mask_to_possible_vp_mask(struct display_state * state)26836fea745cSDamon Ding static inline void vop2_plane_mask_to_possible_vp_mask(struct display_state *state)
2684d0408543SAndy Yan {
2685b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
26866fea745cSDamon Ding 	struct vop2 *vop2 = cstate->private;
2687b7195f56SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
26886fea745cSDamon Ding 	struct vop2_win_data *win_data;
2689b0989546SSandy Huang 	u32 plane_mask;
26906fea745cSDamon Ding 	u32 nr_planes;
26916fea745cSDamon Ding 	u32 phys_id;
26926fea745cSDamon Ding 	int i, j;
2693b0989546SSandy Huang 
26946fea745cSDamon Ding 	for (i = 0; i < vop2_data->nr_layers; i++) {
26956fea745cSDamon Ding 		win_data = &vop2_data->win_data[i];
26966fea745cSDamon Ding 		win_data->possible_vp_mask = 0;
26976fea745cSDamon Ding 	}
26986fea745cSDamon Ding 
26996fea745cSDamon Ding 	for (i = 0; i < vop2_data->nr_vps; i++) {
27006fea745cSDamon Ding 		plane_mask = cstate->crtc->vps[i].plane_mask;
27016fea745cSDamon Ding 		nr_planes = hweight32(plane_mask);
27026fea745cSDamon Ding 
27036fea745cSDamon Ding 		for (j = 0; j < nr_planes; j++) {
27046fea745cSDamon Ding 			phys_id = ffs(plane_mask) - 1;
27056fea745cSDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, phys_id);
27066fea745cSDamon Ding 			win_data->possible_vp_mask |= BIT(i);
27076fea745cSDamon Ding 			plane_mask &= ~BIT(phys_id);
27086fea745cSDamon Ding 		}
27096fea745cSDamon Ding 	}
27106fea745cSDamon Ding }
27116fea745cSDamon Ding 
27126fea745cSDamon Ding /*
27136fea745cSDamon Ding  * The function checks whether the 'rockchip,plane-mask' property assigned
27146fea745cSDamon Ding  * in DTS is valid.
27156fea745cSDamon Ding  */
vop2_plane_mask_check(struct display_state * state)27166fea745cSDamon Ding static bool vop2_plane_mask_check(struct display_state *state)
27176fea745cSDamon Ding {
27186fea745cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
27196fea745cSDamon Ding 	struct vop2 *vop2 = cstate->private;
27206fea745cSDamon Ding 	struct vop2_win_data *win_data;
27216fea745cSDamon Ding 	u32 assigned_plane_mask = 0, plane_mask = 0;
27226fea745cSDamon Ding 	u32 phys_id;
27236fea745cSDamon Ding 	u32 nr_planes;
2724b4fa21deSDamon Ding 	u8 primary_plane_id, cursor_plane_id;
27256fea745cSDamon Ding 	int i, j;
27266fea745cSDamon Ding 
27276fea745cSDamon Ding 	/*
27286fea745cSDamon Ding 	 * If plane mask is assigned in DTS, then every plane need to be assigned to
27296fea745cSDamon Ding 	 * one of all the VPs, and no single plane can be assigned to more than one
27306fea745cSDamon Ding 	 * VP.
27316fea745cSDamon Ding 	 */
2732b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
2733b0989546SSandy Huang 		plane_mask = cstate->crtc->vps[i].plane_mask;
27345fc2b656SDamon Ding 		primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
2735b4fa21deSDamon Ding 		cursor_plane_id = cstate->crtc->vps[i].cursor_plane_id;
27366fea745cSDamon Ding 		nr_planes = hweight32(plane_mask);
2737b0989546SSandy Huang 
27386fea745cSDamon Ding 		/*
27396fea745cSDamon Ding 		 * If the plane mask and primary plane both are assigned in DTS, the
27406fea745cSDamon Ding 		 * primary plane should be included in the plane mask of VPx.
27416fea745cSDamon Ding 		 */
27426fea745cSDamon Ding 		if (plane_mask && primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
27436fea745cSDamon Ding 		    !(BIT(primary_plane_id) & plane_mask)) {
27446fea745cSDamon Ding 			printf("Invalid primary plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n",
27456fea745cSDamon Ding 			       vop2_plane_phys_id_to_string(primary_plane_id),
27466fea745cSDamon Ding 			       BIT(primary_plane_id), i, plane_mask);
27476fea745cSDamon Ding 			return false;
274863cb669fSSandy Huang 		}
27496fea745cSDamon Ding 
2750b4fa21deSDamon Ding 		if (cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
2751b4fa21deSDamon Ding 		    cursor_plane_id == primary_plane_id) {
2752b4fa21deSDamon Ding 			printf("Assigned cursor plane of VP%d [%s] has been assigned as its pirmary plane\n",
2753b4fa21deSDamon Ding 			       i, vop2_plane_phys_id_to_string(cursor_plane_id));
2754b4fa21deSDamon Ding 			return false;
2755b4fa21deSDamon Ding 		}
2756b4fa21deSDamon Ding 
2757b4fa21deSDamon Ding 		/*
2758b4fa21deSDamon Ding 		 * If the plane mask and cursor plane both are assigned in DTS, the
2759b4fa21deSDamon Ding 		 * cursor plane should be included in the plane mask of VPx.
2760b4fa21deSDamon Ding 		 */
2761b4fa21deSDamon Ding 		if (plane_mask && cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
2762b4fa21deSDamon Ding 		    !(BIT(cursor_plane_id) & plane_mask)) {
2763b4fa21deSDamon Ding 			printf("Invalid cursor plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n",
2764b4fa21deSDamon Ding 			       vop2_plane_phys_id_to_string(cursor_plane_id),
2765b4fa21deSDamon Ding 			       BIT(cursor_plane_id), i, plane_mask);
2766b4fa21deSDamon Ding 			return false;
2767b4fa21deSDamon Ding 		}
2768b4fa21deSDamon Ding 
27696fea745cSDamon Ding 		/*
27706fea745cSDamon Ding 		 * Every plane assigned to the specific VP should follow the constraints
27716fea745cSDamon Ding 		 * of default &vop2_win_data.possible_vp_mask.
27726fea745cSDamon Ding 		 */
27736fea745cSDamon Ding 		for (j = 0; j < nr_planes; j++) {
27746fea745cSDamon Ding 			phys_id = ffs(plane_mask) - 1;
27756fea745cSDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, phys_id);
27766fea745cSDamon Ding 			if (!win_data) {
27776fea745cSDamon Ding 				printf("Invalid plane id %d in VP%d assigned plane mask\n",
27786fea745cSDamon Ding 				       phys_id, i);
27796fea745cSDamon Ding 				return false;
2780b0989546SSandy Huang 			}
27816fea745cSDamon Ding 
27826fea745cSDamon Ding 			if (!(vop2_win_can_attach_to_vp(win_data, i))) {
27836fea745cSDamon Ding 				printf("%s can not attach to VP%d\n",
27846fea745cSDamon Ding 				       vop2_plane_phys_id_to_string(phys_id), i);
27856fea745cSDamon Ding 				return false;
27866fea745cSDamon Ding 			}
27876fea745cSDamon Ding 
27886fea745cSDamon Ding 			plane_mask &= ~BIT(phys_id);
27896fea745cSDamon Ding 		}
27906fea745cSDamon Ding 
27916fea745cSDamon Ding 		if (assigned_plane_mask & cstate->crtc->vps[i].plane_mask) {
27926fea745cSDamon Ding 			printf("the same window can't be assigned to two vp\n");
27936fea745cSDamon Ding 			return false;
27946fea745cSDamon Ding 		}
27956fea745cSDamon Ding 		assigned_plane_mask |= cstate->crtc->vps[i].plane_mask;
27966fea745cSDamon Ding 	}
27976fea745cSDamon Ding 
27986fea745cSDamon Ding 	if (assigned_plane_mask != vop2->data->plane_mask_base) {
27996fea745cSDamon Ding 		printf("all windows should be assigned, full plane mask: [0x%08x], current plane mask: [0x%08x]\n",
28006fea745cSDamon Ding 		       vop2->data->plane_mask_base, assigned_plane_mask);
28016fea745cSDamon Ding 		return false;
28026fea745cSDamon Ding 	}
28036fea745cSDamon Ding 
28046fea745cSDamon Ding 	/*
28056fea745cSDamon Ding 	 * If plane_mask assigned in DTS is valid, then convert it to &vop2_win_data.possible_vp_mask
28066fea745cSDamon Ding 	 * and replace the default one with it.
28076fea745cSDamon Ding 	 */
28086fea745cSDamon Ding 	vop2_plane_mask_to_possible_vp_mask(state);
28096fea745cSDamon Ding 
28106fea745cSDamon Ding 	return true;
28116fea745cSDamon Ding }
28126fea745cSDamon Ding 
rockchip_cursor_plane_assign(struct display_state * state,u8 vp_id)2813b4fa21deSDamon Ding static void rockchip_cursor_plane_assign(struct display_state *state, u8 vp_id)
2814b4fa21deSDamon Ding {
2815b4fa21deSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2816b4fa21deSDamon Ding 	struct vop2 *vop2 = cstate->private;
2817b4fa21deSDamon Ding 	struct vop2_win_data *win_data;
2818b4fa21deSDamon Ding 	int i, j;
2819b4fa21deSDamon Ding 
2820b4fa21deSDamon Ding 	if (cstate->crtc->vps[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
2821b4fa21deSDamon Ding 		win_data = vop2_find_win_by_phys_id(vop2, cstate->crtc->vps[vp_id].cursor_plane_id);
2822b4fa21deSDamon Ding 		if (win_data) {
2823b4fa21deSDamon Ding 			if (vop2_win_can_attach_to_vp(win_data, vp_id))
2824b4fa21deSDamon Ding 				vop2->vp_plane_mask[vp_id].cursor_plane_id =
2825b4fa21deSDamon Ding 					cstate->crtc->vps[vp_id].cursor_plane_id;
2826b4fa21deSDamon Ding 			return;
2827b4fa21deSDamon Ding 		}
2828b4fa21deSDamon Ding 	}
2829b4fa21deSDamon Ding 
2830b4fa21deSDamon Ding 	for (i = 0; i < vop2->data->nr_layers; i++) {
2831b4fa21deSDamon Ding 		win_data = &vop2->data->win_data[i];
2832b4fa21deSDamon Ding 
2833b4fa21deSDamon Ding 		if (win_data->plane_type != VOP2_PLANE_TYPE_CURSOR)
2834b4fa21deSDamon Ding 			continue;
2835b4fa21deSDamon Ding 
2836b4fa21deSDamon Ding 		if (!vop2_win_can_attach_to_vp(win_data, vp_id))
2837b4fa21deSDamon Ding 			continue;
2838b4fa21deSDamon Ding 
2839b4fa21deSDamon Ding 		for (j = 0; j < vop2->data->nr_vps; j++) {
2840b4fa21deSDamon Ding 			if (win_data->phys_id == vop2->vp_plane_mask[j].cursor_plane_id)
2841b4fa21deSDamon Ding 				break;
2842b4fa21deSDamon Ding 		}
2843b4fa21deSDamon Ding 
2844b4fa21deSDamon Ding 		/* The win has been used as the cursor plane for other VPs */
2845b4fa21deSDamon Ding 		if (j < vop2->data->nr_vps)
2846b4fa21deSDamon Ding 			continue;
2847b4fa21deSDamon Ding 
2848b4fa21deSDamon Ding 		vop2->vp_plane_mask[vp_id].cursor_plane_id = win_data->phys_id;
2849b4fa21deSDamon Ding 		return;
2850b4fa21deSDamon Ding 	}
2851b4fa21deSDamon Ding 
2852b4fa21deSDamon Ding 	vop2->vp_plane_mask[vp_id].cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
2853b4fa21deSDamon Ding }
2854b4fa21deSDamon Ding 
28556fea745cSDamon Ding /*
28566fea745cSDamon Ding  * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in
28576fea745cSDamon Ding  * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched
28586fea745cSDamon Ding  * between different CRTCs flexibly and the userspace do not need
2859ef0607a7SDamon Ding  * the plane_mask to restrict the switch between the crtc and plane.
28606fea745cSDamon Ding  * We just find a expected plane for logo display.
28616fea745cSDamon Ding  */
rk3528_assign_plane_mask(struct display_state * state)2862ef0607a7SDamon Ding static void rk3528_assign_plane_mask(struct display_state *state)
2863ef0607a7SDamon Ding {
2864ef0607a7SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2865ef0607a7SDamon Ding 	struct vop2 *vop2 = cstate->private;
2866ef0607a7SDamon Ding 	struct vop2_win_data *win_data;
2867ef0607a7SDamon Ding 	int active_vp_num = 0;
2868ef0607a7SDamon Ding 	int i, j, k;
2869ef0607a7SDamon Ding 
2870ef0607a7SDamon Ding 	printf("Assign default plane mask\n");
2871ef0607a7SDamon Ding 
2872a552a69cSDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
28736fea745cSDamon Ding 		if (!cstate->crtc->vps[i].enable)
28746fea745cSDamon Ding 			continue;
28756fea745cSDamon Ding 
28766fea745cSDamon Ding 		for (j = 0; j < vop2->data->nr_layers; j++) {
28776fea745cSDamon Ding 			win_data = &vop2->data->win_data[j];
28786fea745cSDamon Ding 
28796fea745cSDamon Ding 			if (win_data->plane_type != VOP2_PLANE_TYPE_PRIMARY)
28806fea745cSDamon Ding 				continue;
28816fea745cSDamon Ding 
28826fea745cSDamon Ding 			if (!vop2_win_can_attach_to_vp(win_data, i))
28836fea745cSDamon Ding 				continue;
28846fea745cSDamon Ding 
28856fea745cSDamon Ding 			for (k = 0; k < vop2->data->nr_vps; k++) {
28866fea745cSDamon Ding 				if (win_data->phys_id == vop2->vp_plane_mask[k].primary_plane_id)
28876fea745cSDamon Ding 					break;
2888a552a69cSDamon Ding 			}
28896fea745cSDamon Ding 
28906fea745cSDamon Ding 			/* The win has been used as the primary plane for other VPs */
28916fea745cSDamon Ding 			if (k < vop2->data->nr_vps)
28926fea745cSDamon Ding 				continue;
28936fea745cSDamon Ding 
28946fea745cSDamon Ding 			vop2->vp_plane_mask[i].attached_layers_nr = 1;
28956fea745cSDamon Ding 			vop2->vp_plane_mask[i].primary_plane_id = win_data->phys_id;
28966fea745cSDamon Ding 			vop2->vp_plane_mask[i].attached_layers[0] = win_data->phys_id;
28976fea745cSDamon Ding 			vop2->vp_plane_mask[i].plane_mask |= BIT(win_data->phys_id);
28986fea745cSDamon Ding 			active_vp_num++;
28996fea745cSDamon Ding 			break;
29006fea745cSDamon Ding 		}
29016fea745cSDamon Ding 
29026fea745cSDamon Ding 		if (vop2->vp_plane_mask[i].primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
29036fea745cSDamon Ding 			printf("ERROR: No primary plane find for video_port%d\n", i);
290465365de1SDamon Ding 
290565365de1SDamon Ding 		rockchip_cursor_plane_assign(state, i);
2906a552a69cSDamon Ding 	}
2907a552a69cSDamon Ding 	printf("VOP have %d active VP\n", active_vp_num);
2908ef0607a7SDamon Ding }
2909ef0607a7SDamon Ding 
rk3568_assign_plane_mask(struct display_state * state)2910ef0607a7SDamon Ding static void rk3568_assign_plane_mask(struct display_state *state)
2911ef0607a7SDamon Ding {
2912ef0607a7SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
2913ef0607a7SDamon Ding 	struct vop2 *vop2 = cstate->private;
2914ef0607a7SDamon Ding 	struct vop2_vp_plane_mask *plane_mask;
2915ef0607a7SDamon Ding 	u32 nr_planes = 0;
2916ef0607a7SDamon Ding 	int active_vp_num = 0;
2917ef0607a7SDamon Ding 	int main_vp_index = -1;
2918ef0607a7SDamon Ding 	int layer_phy_id = 0;
2919ef0607a7SDamon Ding 	int i, j;
2920ef0607a7SDamon Ding 
2921ef0607a7SDamon Ding 	printf("Assign default plane mask\n");
2922ef0607a7SDamon Ding 
2923b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
292465365de1SDamon Ding 		if (cstate->crtc->vps[i].enable)
2925b0989546SSandy Huang 			active_vp_num++;
2926b0989546SSandy Huang 	}
292765365de1SDamon Ding 
2928b0989546SSandy Huang 	printf("VOP have %d active VP\n", active_vp_num);
2929b0989546SSandy Huang 
2930b0989546SSandy Huang 	if (soc_is_rk3566() && active_vp_num > 2)
2931b0989546SSandy Huang 		printf("ERROR: rk3566 only support 2 display output!!\n");
2932b0989546SSandy Huang 	plane_mask = vop2->data->plane_mask;
2933b0989546SSandy Huang 	plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
2934b0989546SSandy Huang 
29357a290128SDamon Ding 	/*
29367a290128SDamon Ding 	 * For RK3566, the main planes should be enabled before the mirror planes.
29377a290128SDamon Ding 	 * The devices that support hot plug may be disconnected initially, so we
29387a290128SDamon Ding 	 * assign the main planes to the first device that does not support hot
29397a290128SDamon Ding 	 * plug, in order to ensure that the mirror planes are not enabled first.
29407a290128SDamon Ding 	 */
29417a290128SDamon Ding 	if (soc_is_rk3566()) {
2942b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
2943b0989546SSandy Huang 			if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
2944a552a69cSDamon Ding 				/* the first store main display plane mask */
2945a552a69cSDamon Ding 				vop2->vp_plane_mask[i] = plane_mask[0];
2946b0989546SSandy Huang 				main_vp_index = i;
2947e007876dSSandy Huang 				break;
2948b0989546SSandy Huang 			}
2949b0989546SSandy Huang 		}
2950b0989546SSandy Huang 
2951b0989546SSandy Huang 		/* if no find unplug devices, use vp0 as main display */
2952b0989546SSandy Huang 		if (main_vp_index < 0) {
2953b0989546SSandy Huang 			main_vp_index = 0;
2954b0989546SSandy Huang 			vop2->vp_plane_mask[0] = plane_mask[0];
2955b0989546SSandy Huang 		}
2956b0989546SSandy Huang 
2957a552a69cSDamon Ding 		/* plane_mask[0] store main display, so we from plane_mask[1] */
2958a552a69cSDamon Ding 		j = 1;
29597a290128SDamon Ding 	} else {
29607a290128SDamon Ding 		/*
29617a290128SDamon Ding 		 * For the platforms except RK3566, we assign the plane mask of
29627a290128SDamon Ding 		 * VPx according to the &vop2_data.plane_mask[active_vp_num][x].
29637a290128SDamon Ding 		 */
29647a290128SDamon Ding 		j = 0;
29657a290128SDamon Ding 	}
2966b0989546SSandy Huang 
2967b0989546SSandy Huang 	/* init other display except main display */
2968b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
2969a552a69cSDamon Ding 		/* main display or no connect devices */
2970a552a69cSDamon Ding 		if (i == main_vp_index || !cstate->crtc->vps[i].enable)
2971b0989546SSandy Huang 			continue;
2972b0989546SSandy Huang 		vop2->vp_plane_mask[i] = plane_mask[j++];
297383d6b087SDamon Ding 		/*
297483d6b087SDamon Ding 		 * For rk3588, the main window should attach to the VP0 while
297583d6b087SDamon Ding 		 * the splice window should attach to the VP1 when the display
297683d6b087SDamon Ding 		 * mode is over 4k.
297783d6b087SDamon Ding 		 * If only one VP is enabled and the plane mask is not assigned
297883d6b087SDamon Ding 		 * in DTS, all main windows will be assigned to the enabled VPx,
297983d6b087SDamon Ding 		 * and all splice windows will be assigned to the VPx+1, in order
298083d6b087SDamon Ding 		 * to ensure that the splice mode work well.
298183d6b087SDamon Ding 		 */
298283d6b087SDamon Ding 		if (vop2->version == VOP_VERSION_RK3588 && active_vp_num == 1)
298383d6b087SDamon Ding 			vop2->vp_plane_mask[(i + 1) % vop2->data->nr_vps] = plane_mask[j++];
2984b0989546SSandy Huang 	}
29856fea745cSDamon Ding 
2986b0989546SSandy Huang 	/* store plane mask for vop2_fixup_dts */
2987b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
29886fea745cSDamon Ding 		nr_planes = vop2->vp_plane_mask[i].attached_layers_nr;
29896fea745cSDamon Ding 		for (j = 0; j < nr_planes; j++) {
2990b0989546SSandy Huang 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2991b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
2992b0989546SSandy Huang 		}
2993b0989546SSandy Huang 	}
299465365de1SDamon Ding 
299565365de1SDamon Ding 	/*
299665365de1SDamon Ding 	 * For RK3568 and RK3588, to aovid &vop2.vp_plane_mask[].cursor_plane_id
299765365de1SDamon Ding 	 * being overwritten by &vop2.data->plane_mask[].cursor_plane_id, which
299865365de1SDamon Ding 	 * is always 0, the assignment of cursor plane should be placed at the
299965365de1SDamon Ding 	 * end.
300065365de1SDamon Ding 	 */
300165365de1SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
300265365de1SDamon Ding 		vop2->vp_plane_mask[i].cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
300365365de1SDamon Ding 		if (cstate->crtc->vps[i].enable)
300465365de1SDamon Ding 			rockchip_cursor_plane_assign(state, i);
300565365de1SDamon Ding 	}
3006b0989546SSandy Huang }
30076fea745cSDamon Ding 
vop2_global_initial(struct vop2 * vop2,struct display_state * state)30086fea745cSDamon Ding static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
30096fea745cSDamon Ding {
30106fea745cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
30116fea745cSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
30126fea745cSDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
30132d3a2f01SDamon Ding 	struct vop2_vp_plane_mask *vp_plane_mask;
30146fea745cSDamon Ding 	u32 nr_planes = 0;
30156fea745cSDamon Ding 	u32 plane_mask;
30166fea745cSDamon Ding 	u8 primary_plane_id;
30176fea745cSDamon Ding 	const u8 *tmp;
30186fea745cSDamon Ding 	int i, j;
30196fea745cSDamon Ding 
30206fea745cSDamon Ding 	if (vop2->global_init)
30216fea745cSDamon Ding 		return;
30226fea745cSDamon Ding 
30232d3a2f01SDamon Ding 	/*
30242d3a2f01SDamon Ding 	 * Initialize struct vop2_vp_plane_mask, whose main function is to
30252d3a2f01SDamon Ding 	 * fixup the DTS.
30262d3a2f01SDamon Ding 	 */
30272d3a2f01SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
30282d3a2f01SDamon Ding 		vp_plane_mask = &vop2->vp_plane_mask[i];
30292d3a2f01SDamon Ding 		/*
30302d3a2f01SDamon Ding 		 * Set default value of the primary plane id and cursor plane
30312d3a2f01SDamon Ding 		 * id to invalid.
30322d3a2f01SDamon Ding 		 */
30332d3a2f01SDamon Ding 		vp_plane_mask->primary_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
30342d3a2f01SDamon Ding 		vp_plane_mask->cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
30352d3a2f01SDamon Ding 	}
30362d3a2f01SDamon Ding 
30376fea745cSDamon Ding 	/* OTP must enable at the first time, otherwise mirror layer register is error */
30386fea745cSDamon Ding 	if (soc_is_rk3566())
30396fea745cSDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
30406fea745cSDamon Ding 				OTP_WIN_EN_SHIFT, 1, false);
30416fea745cSDamon Ding 
30426fea745cSDamon Ding 	/* The plane mask is assigned in DTS */
30436fea745cSDamon Ding 	if (cstate->crtc->assign_plane) {
30446fea745cSDamon Ding 		/* check whether plane mask and primary plane are valid */
30456fea745cSDamon Ding 		if (vop2_plane_mask_check(state)) {
30466fea745cSDamon Ding 			for (i = 0; i < vop2->data->nr_vps; i++) {
30476fea745cSDamon Ding 				plane_mask = cstate->crtc->vps[i].plane_mask;
30486fea745cSDamon Ding 				nr_planes = hweight32(plane_mask); /* use bitmap to store plane mask */
30496fea745cSDamon Ding 				vop2->vp_plane_mask[i].attached_layers_nr = nr_planes;
30506fea745cSDamon Ding 				primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
30516fea745cSDamon Ding 				/*
30526fea745cSDamon Ding 				 * If the primary plane of specific VP is not assigned
30536fea745cSDamon Ding 				 * in DTS, find a proper primary plane according to the
30546fea745cSDamon Ding 				 * &vop2_win_data.possible_vp_mask.
30556fea745cSDamon Ding 				 */
30566fea745cSDamon Ding 				if (primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
30576fea745cSDamon Ding 					primary_plane_id = vop2_vp_find_attachable_win(state, i);
30586fea745cSDamon Ding 				vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id;
30596fea745cSDamon Ding 				vop2->vp_plane_mask[i].plane_mask = plane_mask;
30606fea745cSDamon Ding 
30616fea745cSDamon Ding 				/* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id] */
30626fea745cSDamon Ding 				for (j = 0; j < nr_planes; j++) {
30636fea745cSDamon Ding 					vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
30646fea745cSDamon Ding 					plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
30656fea745cSDamon Ding 				}
30666fea745cSDamon Ding 			}
30676fea745cSDamon Ding 		} else {
3068ef0607a7SDamon Ding 			vop2_ops->assign_plane_mask(state);
30696fea745cSDamon Ding 		}
30706fea745cSDamon Ding 	} else {
30716fea745cSDamon Ding 		/*
30726fea745cSDamon Ding 		 * If no plane mask assignment, plane mask and primary plane will be
30736fea745cSDamon Ding 		 * assigned automatically.
30746fea745cSDamon Ding 		 */
3075ef0607a7SDamon Ding 		vop2_ops->assign_plane_mask(state);
30766fea745cSDamon Ding 	}
3077b0989546SSandy Huang 
307860e469f5SDamon Ding 	if (vop2->version == VOP_VERSION_RK3588)
307960e469f5SDamon Ding 		rk3588_vop2_regsbak(vop2);
308060e469f5SDamon Ding 	else
308160e469f5SDamon Ding 		memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
308260e469f5SDamon Ding 
308360e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
308460e469f5SDamon Ding 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
308560e469f5SDamon Ding 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
308660e469f5SDamon Ding 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
308760e469f5SDamon Ding 
3088b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
3089b0989546SSandy Huang 		printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
3090b0989546SSandy Huang 		for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
309127cec8e2SDamon Ding 			printf("%s ",
3092a7cb29b7SDamon Ding 			       vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].attached_layers[j]));
309327cec8e2SDamon Ding 		printf("], primary plane: %s\n",
3094a7cb29b7SDamon Ding 		       vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].primary_plane_id));
3095b0989546SSandy Huang 	}
3096b0989546SSandy Huang 
3097b7195f56SDamon Ding 	vop2_ops->setup_overlay(state);
3098b0989546SSandy Huang 
30995fa6e665SDamon Ding 	if (is_vop3(vop2)) {
31005fa6e665SDamon Ding 		/*
31015fa6e665SDamon Ding 		 * you can rewrite at dts vop node:
31025fa6e665SDamon Ding 		 *
31035fa6e665SDamon Ding 		 * VOP3_ESMART_8K_MODE = 0,
31045fa6e665SDamon Ding 		 * VOP3_ESMART_4K_4K_MODE = 1,
31055fa6e665SDamon Ding 		 * VOP3_ESMART_4K_2K_2K_MODE = 2,
31065fa6e665SDamon Ding 		 * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
31075fa6e665SDamon Ding 		 *
31085fa6e665SDamon Ding 		 * &vop {
31095fa6e665SDamon Ding 		 * 	esmart_lb_mode = /bits/ 8 <2>;
31105fa6e665SDamon Ding 		 * };
311163cb669fSSandy Huang 		 */
311251e1509eSDamon Ding 		tmp = dev_read_u8_array_ptr(cstate->dev, "esmart_lb_mode", 1);
311351e1509eSDamon Ding 		if (tmp)
311451e1509eSDamon Ding 			vop2->esmart_lb_mode = *tmp;
311551e1509eSDamon Ding 		else
31165fa6e665SDamon Ding 			vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
3117a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
3118a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL,
3119a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_MASK,
3120a552a69cSDamon Ding 					RK3576_ESMART_LB_MODE_SEL_SHIFT,
3121a552a69cSDamon Ding 					vop3_get_esmart_lb_mode(vop2), true);
3122a552a69cSDamon Ding 		else
3123a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
3124a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_MASK,
3125a552a69cSDamon Ding 					ESMART_LB_MODE_SEL_SHIFT,
3126f6e9a2a3SDamon Ding 					vop3_get_esmart_lb_mode(vop2), false);
3127d0408543SAndy Yan 
31285fa6e665SDamon Ding 		vop3_init_esmart_scale_engine(vop2);
3129aa670293SDamon Ding 
313012ee4de7SDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
313112ee4de7SDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
313212ee4de7SDamon Ding 					RK3576_DSP_VS_T_SEL_SHIFT, 0, true);
313312ee4de7SDamon Ding 		else
3134aa670293SDamon Ding 			vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK,
3135aa670293SDamon Ding 					DSP_VS_T_SEL_SHIFT, 0, false);
3136bb7ec356SDamon Ding 
3137bb7ec356SDamon Ding 		/*
3138bb7ec356SDamon Ding 		 * This is a workaround for RK3528/RK3562/RK3576:
3139bb7ec356SDamon Ding 		 *
3140bb7ec356SDamon Ding 		 * The aclk pre auto gating function may disable the aclk
3141bb7ec356SDamon Ding 		 * in some unexpected cases, which detected by hardware
3142bb7ec356SDamon Ding 		 * automatically.
3143bb7ec356SDamon Ding 		 *
3144bb7ec356SDamon Ding 		 * For example, if the above function is enabled, the post
3145bb7ec356SDamon Ding 		 * scale function will be affected, resulting in abnormal
3146bb7ec356SDamon Ding 		 * display.
3147bb7ec356SDamon Ding 		 */
3148bb7ec356SDamon Ding 		if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 ||
3149bb7ec356SDamon Ding 		    vop2->version == VOP_VERSION_RK3576)
3150bb7ec356SDamon Ding 			vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
3151bb7ec356SDamon Ding 					ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false);
315263cb669fSSandy Huang 	}
315363cb669fSSandy Huang 
3154ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3568)
315563cb669fSSandy Huang 		vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
315663cb669fSSandy Huang 
3157a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576) {
3158a552a69cSDamon Ding 		vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq");
3159a552a69cSDamon Ding 
3160dad2c246SSandy Huang 		/* Default use rkiommu 2.0 for axi0 */
3161dad2c246SSandy Huang 		vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 1, true);
3162a552a69cSDamon Ding 
3163a552a69cSDamon Ding 		/* Init frc2.0 config */
3164a552a69cSDamon Ding 		vop2_writel(vop2, 0xca0, 0xc8);
3165a552a69cSDamon Ding 		vop2_writel(vop2, 0xca4, 0x01000100);
3166a552a69cSDamon Ding 		vop2_writel(vop2, 0xca8, 0x03ff0100);
3167a552a69cSDamon Ding 		vop2_writel(vop2, 0xda0, 0xc8);
3168a552a69cSDamon Ding 		vop2_writel(vop2, 0xda4, 0x01000100);
3169a552a69cSDamon Ding 		vop2_writel(vop2, 0xda8, 0x03ff0100);
3170a552a69cSDamon Ding 
3171a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true)
3172a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
3173a552a69cSDamon Ding 					VP_INTR_MERGE_EN_SHIFT, 1, true);
3174a552a69cSDamon Ding 
3175a552a69cSDamon Ding 		/* Set reg done every field for interlace */
3176a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK,
3177a552a69cSDamon Ding 				INTERLACE_FRM_REG_DONE_SHIFT, 0, false);
3178a552a69cSDamon Ding 	}
3179a552a69cSDamon Ding 
318063cb669fSSandy Huang 	vop2->global_init = true;
3181d0408543SAndy Yan }
3182d0408543SAndy Yan 
rockchip_vop2_sharp_init(struct vop2 * vop2,struct display_state * state)3183344e932aSDamon Ding static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state)
3184344e932aSDamon Ding {
3185344e932aSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3186344e932aSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
3187344e932aSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
318845ec9215SDamon Ding 	struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
3189344e932aSDamon Ding 	struct resource sharp_regs;
3190344e932aSDamon Ding 	int ret;
3191344e932aSDamon Ding 
319245ec9215SDamon Ding 	if (!(vp_data->feature & VOP_FEATURE_POST_SHARP) || !vp->sharp_en)
3193344e932aSDamon Ding 		return;
3194344e932aSDamon Ding 
3195344e932aSDamon Ding 	ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs);
3196344e932aSDamon Ding 	if (ret) {
3197344e932aSDamon Ding 		printf("failed to get sharp regs\n");
3198344e932aSDamon Ding 		return;
3199344e932aSDamon Ding 	}
320045ec9215SDamon Ding 	vop2->sharp_res = (void *)sharp_regs.start;
3201344e932aSDamon Ding 
3202344e932aSDamon Ding 	/*
3203344e932aSDamon Ding 	 * After vop initialization, keep sw_sharp_enable always on.
3204344e932aSDamon Ding 	 * Only enable/disable sharp submodule to avoid black screen.
3205344e932aSDamon Ding 	 */
320645ec9215SDamon Ding 	writel(true << SW_SHARP_ENABLE_SHIFT, vop2->sharp_res + RK3576_SHARP_CTRL);
3207344e932aSDamon Ding }
3208344e932aSDamon Ding 
rockchip_vop2_acm_init(struct vop2 * vop2,struct display_state * state)3209c54cc5d2SAlgea Cao static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state)
3210c54cc5d2SAlgea Cao {
3211c54cc5d2SAlgea Cao 	struct crtc_state *cstate = &state->crtc_state;
3212c54cc5d2SAlgea Cao 	const struct vop2_data *vop2_data = vop2->data;
3213c54cc5d2SAlgea Cao 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
3214c54cc5d2SAlgea Cao 	struct resource acm_regs;
3215c54cc5d2SAlgea Cao 	u32 *acm_reg_base;
3216c54cc5d2SAlgea Cao 	u32 vp_offset = (cstate->crtc_id * 0x100);
3217c54cc5d2SAlgea Cao 	int ret;
3218c54cc5d2SAlgea Cao 
3219c54cc5d2SAlgea Cao 	if (!(vp_data->feature & VOP_FEATURE_POST_ACM))
3220c54cc5d2SAlgea Cao 		return;
3221c54cc5d2SAlgea Cao 
3222c54cc5d2SAlgea Cao 	ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs);
3223c54cc5d2SAlgea Cao 	if (ret) {
3224c54cc5d2SAlgea Cao 		printf("failed to get acm regs\n");
3225c54cc5d2SAlgea Cao 		return;
3226c54cc5d2SAlgea Cao 	}
3227c54cc5d2SAlgea Cao 	acm_reg_base = (u32 *)acm_regs.start;
3228c54cc5d2SAlgea Cao 
3229c54cc5d2SAlgea Cao 	/*
3230c54cc5d2SAlgea Cao 	 * Black screen is displayed when acm bypass switched
3231c54cc5d2SAlgea Cao 	 * between enable and disable. Therefore, disable acm
3232c54cc5d2SAlgea Cao 	 * bypass by default after system boot.
3233c54cc5d2SAlgea Cao 	 */
3234c54cc5d2SAlgea Cao 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
3235c54cc5d2SAlgea Cao 			POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
3236c54cc5d2SAlgea Cao 
3237e1946cbdSAlgea Cao 	writel(0, acm_reg_base + 0);
3238c54cc5d2SAlgea Cao }
3239c54cc5d2SAlgea Cao 
rockchip_vop2_of_get_gamma_lut(struct display_state * state,struct device_node * dsp_lut_node)32400669ab1fSDamon Ding static int rockchip_vop2_of_get_gamma_lut(struct display_state *state,
32410669ab1fSDamon Ding 					  struct device_node *dsp_lut_node)
32420669ab1fSDamon Ding {
32430669ab1fSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
32440669ab1fSDamon Ding 	struct resource gamma_res;
32450669ab1fSDamon Ding 	fdt_size_t lut_size;
32460669ab1fSDamon Ding 	u32 *lut_regs;
32470669ab1fSDamon Ding 	u32 *lut;
32480669ab1fSDamon Ding 	u32 r, g, b;
32490669ab1fSDamon Ding 	int lut_len;
32500669ab1fSDamon Ding 	int length;
32510669ab1fSDamon Ding 	int i, j;
32520669ab1fSDamon Ding 	int ret = 0;
32530669ab1fSDamon Ding 
32540669ab1fSDamon Ding 	of_get_property(dsp_lut_node, "gamma-lut", &length);
32550669ab1fSDamon Ding 	if (!length)
32560669ab1fSDamon Ding 		return -EINVAL;
32570669ab1fSDamon Ding 
32580669ab1fSDamon Ding 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
32590669ab1fSDamon Ding 	if (ret)
32600669ab1fSDamon Ding 		printf("failed to get gamma lut res\n");
32610669ab1fSDamon Ding 	lut_regs = (u32 *)gamma_res.start;
32620669ab1fSDamon Ding 	lut_size = gamma_res.end - gamma_res.start + 1;
32630669ab1fSDamon Ding 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
32640669ab1fSDamon Ding 		printf("failed to get gamma lut register\n");
32650669ab1fSDamon Ding 		return -EINVAL;
32660669ab1fSDamon Ding 	}
32670669ab1fSDamon Ding 	lut_len = lut_size / 4;
32680669ab1fSDamon Ding 
32690669ab1fSDamon Ding 	cstate->lut_val = (u32 *)calloc(1, lut_size);
32700669ab1fSDamon Ding 	if (!cstate->lut_val)
32710669ab1fSDamon Ding 		return -ENOMEM;
32720669ab1fSDamon Ding 
32730669ab1fSDamon Ding 	length >>= 2;
32740669ab1fSDamon Ding 	if (length != lut_len) {
32750669ab1fSDamon Ding 		lut = (u32 *)calloc(1, lut_len);
32760669ab1fSDamon Ding 		if (!lut) {
32770669ab1fSDamon Ding 			free(cstate->lut_val);
32780669ab1fSDamon Ding 			return -ENOMEM;
32790669ab1fSDamon Ding 		}
32800669ab1fSDamon Ding 
32810669ab1fSDamon Ding 		ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length);
32820669ab1fSDamon Ding 		if (ret) {
32830669ab1fSDamon Ding 			printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id);
32840669ab1fSDamon Ding 			free(cstate->lut_val);
32850669ab1fSDamon Ding 			free(lut);
32860669ab1fSDamon Ding 			return -EINVAL;
32870669ab1fSDamon Ding 		}
32880669ab1fSDamon Ding 
32890669ab1fSDamon Ding 		/*
32900669ab1fSDamon Ding 		 * In order to achieve the same gamma correction effect in different
32910669ab1fSDamon Ding 		 * platforms, the following conversion helps to translate from 8bit
32920669ab1fSDamon Ding 		 * gamma table with 256 parameters to 10bit gamma with 1024 parameters.
32930669ab1fSDamon Ding 		 */
32940669ab1fSDamon Ding 		for (i = 0; i < lut_len; i++) {
32950669ab1fSDamon Ding 			j = i * length / lut_len;
32960669ab1fSDamon Ding 			r = lut[j] / length / length * lut_len / length;
32970669ab1fSDamon Ding 			g = lut[j] / length % length * lut_len / length;
32980669ab1fSDamon Ding 			b = lut[j] % length * lut_len / length;
32990669ab1fSDamon Ding 
33000669ab1fSDamon Ding 			cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b;
33010669ab1fSDamon Ding 		}
33020669ab1fSDamon Ding 		free(lut);
33030669ab1fSDamon Ding 	} else {
33040669ab1fSDamon Ding 		of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len);
33050669ab1fSDamon Ding 	}
33060669ab1fSDamon Ding 
33070669ab1fSDamon Ding 	return 0;
33080669ab1fSDamon Ding }
33090669ab1fSDamon Ding 
rockchip_vop2_of_get_dsp_lut(struct vop2 * vop2,struct display_state * state)33100669ab1fSDamon Ding static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state)
33110669ab1fSDamon Ding {
33120669ab1fSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
33130669ab1fSDamon Ding 	struct device_node *dsp_lut_node;
33140669ab1fSDamon Ding 	int phandle;
33150669ab1fSDamon Ding 	int ret = 0;
33160669ab1fSDamon Ding 
33170669ab1fSDamon Ding 	phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1);
33180669ab1fSDamon Ding 	if (phandle < 0)
33190669ab1fSDamon Ding 		return;
33200669ab1fSDamon Ding 
33210669ab1fSDamon Ding 	dsp_lut_node = of_find_node_by_phandle(phandle);
33220669ab1fSDamon Ding 	if (!dsp_lut_node)
33230669ab1fSDamon Ding 		return;
33240669ab1fSDamon Ding 
33250669ab1fSDamon Ding 	ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node);
33260669ab1fSDamon Ding 	if (ret)
33270669ab1fSDamon Ding 		printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id);
33280669ab1fSDamon Ding }
33290669ab1fSDamon Ding 
vop2_initial(struct vop2 * vop2,struct display_state * state)3330d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state)
3331d0408543SAndy Yan {
33320669ab1fSDamon Ding 	rockchip_vop2_of_get_dsp_lut(vop2, state);
33330669ab1fSDamon Ding 
33341147facaSSandy Huang 	rockchip_vop2_gamma_lut_init(vop2, state);
33356414e3bcSSandy Huang 	rockchip_vop2_cubic_lut_init(vop2, state);
3336344e932aSDamon Ding 	rockchip_vop2_sharp_init(vop2, state);
3337c54cc5d2SAlgea Cao 	rockchip_vop2_acm_init(vop2, state);
3338d0408543SAndy Yan 
3339d0408543SAndy Yan 	return 0;
3340d0408543SAndy Yan }
3341d0408543SAndy Yan 
3342d0408543SAndy Yan /*
3343d0408543SAndy Yan  * VOP2 have multi video ports.
3344d0408543SAndy Yan  * video port ------- crtc
3345d0408543SAndy Yan  */
rockchip_vop2_preinit(struct display_state * state)3346d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state)
3347d0408543SAndy Yan {
3348d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3349d0408543SAndy Yan 	const struct vop2_data *vop2_data = cstate->crtc->data;
3350734a0ce6SDamon Ding 	struct regmap *map;
3351789e70ecSFinley Xiao #if defined(CONFIG_MOS_SUPPORT) && !defined(CONFIG_SPL_BUILD)
3352789e70ecSFinley Xiao 	struct power_domain pwrdom;
3353789e70ecSFinley Xiao 	struct clk_bulk clks;
3354789e70ecSFinley Xiao #endif
33550686a6a6SZhang Yubing 	char dclk_name[16];
33560686a6a6SZhang Yubing 	int ret;
3357d0408543SAndy Yan 
3358d0408543SAndy Yan 	if (!rockchip_vop2) {
33590d2d6a97SSandy Huang 		rockchip_vop2 = calloc(1, sizeof(struct vop2));
3360d0408543SAndy Yan 		if (!rockchip_vop2)
3361d0408543SAndy Yan 			return -ENOMEM;
3362d8e7f4a5SSandy Huang 		memset(rockchip_vop2, 0, sizeof(struct vop2));
3363d0408543SAndy Yan 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
3364d0408543SAndy Yan 		rockchip_vop2->reg_len = RK3568_MAX_REG;
3365d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD
3366d8e7f4a5SSandy Huang 		rockchip_vop2->regs = (void *)RK3528_VOP_BASE;
3367d8e7f4a5SSandy Huang #else
3368d8e7f4a5SSandy Huang 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
3369734a0ce6SDamon Ding 		map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf");
3370734a0ce6SDamon Ding 		rockchip_vop2->grf = regmap_get_range(map, 0);
3371d0408543SAndy Yan 		if (rockchip_vop2->grf <= 0)
337263cb669fSSandy Huang 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
3373d8e7f4a5SSandy Huang #endif
3374d0408543SAndy Yan 		rockchip_vop2->version = vop2_data->version;
3375d0408543SAndy Yan 		rockchip_vop2->data = vop2_data;
3376ecc31b6eSAndy Yan 		if (rockchip_vop2->version == VOP_VERSION_RK3588) {
3377734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf");
3378734a0ce6SDamon Ding 			rockchip_vop2->vop_grf = regmap_get_range(map, 0);
3379ecc31b6eSAndy Yan 			if (rockchip_vop2->vop_grf <= 0)
3380a552a69cSDamon Ding 				printf("%s: Get syscon vop_grf failed (ret=%p)\n",
3381a552a69cSDamon Ding 				       __func__, rockchip_vop2->vop_grf);
3382b890760eSAlgea Cao 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf");
3383b890760eSAlgea Cao 			rockchip_vop2->vo1_grf = regmap_get_range(map, 0);
3384ecc31b6eSAndy Yan 			if (rockchip_vop2->vo1_grf <= 0)
3385a552a69cSDamon Ding 				printf("%s: Get syscon vo1_grf failed (ret=%p)\n",
3386a552a69cSDamon Ding 				       __func__, rockchip_vop2->vo1_grf);
3387734a0ce6SDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3388734a0ce6SDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3389b890760eSAlgea Cao 			if (rockchip_vop2->sys_pmu <= 0)
3390a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3391a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
3392a552a69cSDamon Ding 		} else if (rockchip_vop2->version == VOP_VERSION_RK3576) {
3393a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf");
3394a552a69cSDamon Ding 			rockchip_vop2->ioc_grf = regmap_get_range(map, 0);
3395a552a69cSDamon Ding 			if (rockchip_vop2->ioc_grf <= 0)
3396a552a69cSDamon Ding 				printf("%s: Get syscon ioc_grf failed (ret=%p)\n",
3397a552a69cSDamon Ding 				       __func__, rockchip_vop2->ioc_grf);
3398a552a69cSDamon Ding 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3399a552a69cSDamon Ding 			rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3400a552a69cSDamon Ding 			if (rockchip_vop2->sys_pmu <= 0)
3401a552a69cSDamon Ding 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3402a552a69cSDamon Ding 				       __func__, rockchip_vop2->sys_pmu);
3403ecc31b6eSAndy Yan 		}
3404789e70ecSFinley Xiao #if defined(CONFIG_MOS_SUPPORT) && !defined(CONFIG_SPL_BUILD)
3405789e70ecSFinley Xiao 		ret = power_domain_get(cstate->dev, &pwrdom);
3406789e70ecSFinley Xiao 		if (ret) {
3407789e70ecSFinley Xiao 			printf("failed to get pwrdom: %d\n", ret);
3408789e70ecSFinley Xiao 			return ret;
3409789e70ecSFinley Xiao 		}
3410789e70ecSFinley Xiao 		ret = power_domain_on(&pwrdom);
3411789e70ecSFinley Xiao 		if (ret) {
3412789e70ecSFinley Xiao 			printf("failed to power on pd: %d\n", ret);
3413789e70ecSFinley Xiao 			return ret;
3414789e70ecSFinley Xiao 		}
3415789e70ecSFinley Xiao 		ret = clk_get_bulk(cstate->dev, &clks);
3416789e70ecSFinley Xiao 		if (ret) {
3417789e70ecSFinley Xiao 			if (ret != -ENOSYS && ret != -ENOENT) {
3418789e70ecSFinley Xiao 				printf("failed to get clk: %d\n", ret);
3419789e70ecSFinley Xiao 				return ret;
3420789e70ecSFinley Xiao 			}
3421789e70ecSFinley Xiao 		}
3422789e70ecSFinley Xiao 		ret = clk_enable_bulk(&clks);
3423789e70ecSFinley Xiao 		if (ret) {
3424789e70ecSFinley Xiao 			printf("failed to enable clk: %d\n", ret);
3425789e70ecSFinley Xiao 			clk_release_bulk(&clks);
3426789e70ecSFinley Xiao 			return ret;
3427789e70ecSFinley Xiao 		}
3428789e70ecSFinley Xiao #endif
3429d0408543SAndy Yan 	}
3430d0408543SAndy Yan 
34310686a6a6SZhang Yubing 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
3432a2ce7568SDamon Ding 	if (dev_read_stringlist_search(cstate->dev, "reset-names", dclk_name) > 0) {
34330686a6a6SZhang Yubing 		ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst);
34340686a6a6SZhang Yubing 		if (ret < 0) {
34350686a6a6SZhang Yubing 			printf("%s: failed to get dclk reset: %d\n", __func__, ret);
34360686a6a6SZhang Yubing 			cstate->dclk_rst.dev = NULL;
34370686a6a6SZhang Yubing 		}
3438a2ce7568SDamon Ding 	}
34390686a6a6SZhang Yubing 
3440d0408543SAndy Yan 	cstate->private = rockchip_vop2;
344163cb669fSSandy Huang 	cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
344263cb669fSSandy Huang 	cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
3443d0408543SAndy Yan 
344489912f2dSSandy Huang 	vop2_global_initial(rockchip_vop2, state);
344589912f2dSSandy Huang 
3446d0408543SAndy Yan 	return 0;
3447d0408543SAndy Yan }
3448d0408543SAndy Yan 
3449ecc31b6eSAndy Yan /*
3450ecc31b6eSAndy Yan  * calc the dclk on rk3588
3451ecc31b6eSAndy Yan  * the available div of dclk is 1, 2, 4
3452ecc31b6eSAndy Yan  *
3453ecc31b6eSAndy Yan  */
vop2_calc_dclk(unsigned long child_clk,unsigned long max_dclk)3454ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
3455ecc31b6eSAndy Yan {
3456ecc31b6eSAndy Yan 	if (child_clk * 4 <= max_dclk)
3457ecc31b6eSAndy Yan 		return child_clk * 4;
3458ecc31b6eSAndy Yan 	else if (child_clk * 2 <= max_dclk)
3459ecc31b6eSAndy Yan 		return child_clk * 2;
3460ecc31b6eSAndy Yan 	else if (child_clk <= max_dclk)
3461ecc31b6eSAndy Yan 		return child_clk;
3462ecc31b6eSAndy Yan 	else
3463ecc31b6eSAndy Yan 		return 0;
3464ecc31b6eSAndy Yan }
3465ecc31b6eSAndy Yan 
3466ecc31b6eSAndy Yan /*
3467ecc31b6eSAndy Yan  * 4 pixclk/cycle on rk3588
3468ecc31b6eSAndy Yan  * RGB/eDP/HDMI: if_pixclk >= dclk_core
3469ecc31b6eSAndy Yan  * DP: dp_pixclk = dclk_out <= dclk_core
3470ecc31b6eSAndy Yan  * DSI: mipi_pixclk <= dclk_out <= dclk_core
3471ecc31b6eSAndy Yan  */
vop2_calc_cru_cfg(struct display_state * state,int * dclk_core_div,int * dclk_out_div,int * if_pixclk_div,int * if_dclk_div)3472ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state,
3473ecc31b6eSAndy Yan 				       int *dclk_core_div, int *dclk_out_div,
3474ecc31b6eSAndy Yan 				       int *if_pixclk_div, int *if_dclk_div)
3475d0408543SAndy Yan {
3476d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3477d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3478d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
3479d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
3480dd0d7bfeSDamon Ding 	unsigned long v_pixclk = mode->crtc_clock * 1000L;
3481ecc31b6eSAndy Yan 	unsigned long dclk_core_rate = v_pixclk >> 2;
3482ecc31b6eSAndy Yan 	unsigned long dclk_rate = v_pixclk;
3483ecc31b6eSAndy Yan 	unsigned long dclk_out_rate;
3484ecc31b6eSAndy Yan 	u64 if_dclk_rate;
3485ecc31b6eSAndy Yan 	u64 if_pixclk_rate;
3486ecc31b6eSAndy Yan 	int output_type = conn_state->type;
3487ecc31b6eSAndy Yan 	int output_mode = conn_state->output_mode;
3488ecc31b6eSAndy Yan 	int K = 1;
3489ecc31b6eSAndy Yan 
34900a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE &&
34910a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
34920a1fb152SZhang Yubing 		printf("Dual channel and YUV420 can't work together\n");
34930a1fb152SZhang Yubing 		return -EINVAL;
34940a1fb152SZhang Yubing 	}
34950a1fb152SZhang Yubing 
34960a1fb152SZhang Yubing 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
34970a1fb152SZhang Yubing 	    output_mode == ROCKCHIP_OUT_MODE_YUV420)
34980a1fb152SZhang Yubing 		K = 2;
34990a1fb152SZhang Yubing 
3500ecc31b6eSAndy Yan 	if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
3501ecc31b6eSAndy Yan 		/*
3502ecc31b6eSAndy Yan 		 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
3503ecc31b6eSAndy Yan 		 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
3504ecc31b6eSAndy Yan 		 */
35050a1fb152SZhang Yubing 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
35060a1fb152SZhang Yubing 		    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3507b890760eSAlgea Cao 			dclk_rate = dclk_rate >> 1;
3508ecc31b6eSAndy Yan 			K = 2;
3509b890760eSAlgea Cao 		}
351012ee5af0SDamon Ding 		if (cstate->dsc_enable) {
3511dd0d7bfeSDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate << 1;
3512dd0d7bfeSDamon Ding 			if_dclk_rate = cstate->dsc_cds_clk_rate;
3513ecc31b6eSAndy Yan 		} else {
3514ecc31b6eSAndy Yan 			if_pixclk_rate = (dclk_core_rate << 1) / K;
3515ecc31b6eSAndy Yan 			if_dclk_rate = dclk_core_rate / K;
3516ecc31b6eSAndy Yan 		}
3517ecc31b6eSAndy Yan 
3518dd0d7bfeSDamon Ding 		if (v_pixclk > VOP2_MAX_DCLK_RATE * 1000L)
35194b726cc6SDamon Ding 			dclk_rate = vop2_calc_dclk(dclk_core_rate,
3520dd0d7bfeSDamon Ding 						   vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
3521631ee99aSZhang Yubing 
3522ecc31b6eSAndy Yan 		if (!dclk_rate) {
3523dd0d7bfeSDamon Ding 			printf("HDMI if_pixclk_rate out of range(max_dclk: %ld HZ, dclk_core: %lld HZ)\n",
3524dd0d7bfeSDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, if_pixclk_rate);
3525ecc31b6eSAndy Yan 			return -EINVAL;
3526ecc31b6eSAndy Yan 		}
3527ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3528ecc31b6eSAndy Yan 		*if_dclk_div = dclk_rate / if_dclk_rate;
3529b890760eSAlgea Cao 		*dclk_core_div = dclk_rate / dclk_core_rate;
3530d86cb420SDamon Ding 		/* For HDMI DSC mode, the dclk_out_div should be the same as dclk_core_div */
3531d86cb420SDamon Ding 		if (cstate->dsc_enable)
3532d86cb420SDamon Ding 			*dclk_out_div = *dclk_core_div;
3533b890760eSAlgea Cao 		printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n",
3534b890760eSAlgea Cao 		       dclk_rate, *if_pixclk_div, *if_dclk_div);
3535ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_eDP) {
3536ecc31b6eSAndy Yan 		/* edp_pixclk = edp_dclk > dclk_core */
3537ecc31b6eSAndy Yan 		if_pixclk_rate = v_pixclk / K;
3538ecc31b6eSAndy Yan 		if_dclk_rate = v_pixclk / K;
3539ecc31b6eSAndy Yan 		dclk_rate = if_pixclk_rate * K;
3540ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3541ecc31b6eSAndy Yan 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
3542ecc31b6eSAndy Yan 		*if_dclk_div = *if_pixclk_div;
3543ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
3544ecc31b6eSAndy Yan 		dclk_out_rate = v_pixclk >> 2;
35450a1fb152SZhang Yubing 		dclk_out_rate = dclk_out_rate / K;
3546ecc31b6eSAndy Yan 
35474b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
3548dd0d7bfeSDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
3549ecc31b6eSAndy Yan 		if (!dclk_rate) {
3550dd0d7bfeSDamon Ding 			printf("DP dclk_core out of range(max_dclk: %ld HZ, dclk_core: %ld HZ)\n",
3551dd0d7bfeSDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_core_rate);
3552ecc31b6eSAndy Yan 			return -EINVAL;
3553ecc31b6eSAndy Yan 		}
3554ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3555ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3556ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DSI) {
3557ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3558ecc31b6eSAndy Yan 			K = 2;
355912ee5af0SDamon Ding 		if (cstate->dsc_enable)
356012ee5af0SDamon Ding 			/* dsc output is 96bit, dsi input is 192 bit */
356112ee5af0SDamon Ding 			if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1;
3562ecc31b6eSAndy Yan 		else
3563ecc31b6eSAndy Yan 			if_pixclk_rate = dclk_core_rate / K;
3564ecc31b6eSAndy Yan 		/* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
356512ee5af0SDamon Ding 		dclk_out_rate = dclk_core_rate / K;
3566ecc31b6eSAndy Yan 		/* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
35674b726cc6SDamon Ding 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
3568dd0d7bfeSDamon Ding 					   vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
35699f076eccSZhang Yubing 		if (!dclk_rate) {
3570dd0d7bfeSDamon Ding 			printf("MIPI dclk out of range(max_dclk: %ld HZ, dclk_rate: %ld HZ)\n",
3571dd0d7bfeSDamon Ding 			       vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_rate);
35729f076eccSZhang Yubing 			return -EINVAL;
35739f076eccSZhang Yubing 		}
357412ee5af0SDamon Ding 
357512ee5af0SDamon Ding 		if (cstate->dsc_enable)
3576d57af898SDamon Ding 			dclk_rate /= cstate->dsc_slice_num;
357712ee5af0SDamon Ding 
3578ecc31b6eSAndy Yan 		*dclk_out_div = dclk_rate / dclk_out_rate;
3579ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3580ecc31b6eSAndy Yan 		*if_pixclk_div = 1;       /*mipi pixclk == dclk_out*/
358112ee5af0SDamon Ding 		if (cstate->dsc_enable)
3582dd0d7bfeSDamon Ding 			*if_pixclk_div = dclk_out_rate / if_pixclk_rate;
3583ecc31b6eSAndy Yan 
3584ecc31b6eSAndy Yan 	} else if (output_type == DRM_MODE_CONNECTOR_DPI) {
3585ecc31b6eSAndy Yan 		dclk_rate = v_pixclk;
3586ecc31b6eSAndy Yan 		*dclk_core_div = dclk_rate / dclk_core_rate;
3587ecc31b6eSAndy Yan 	}
3588ecc31b6eSAndy Yan 
3589ecc31b6eSAndy Yan 	*if_pixclk_div = ilog2(*if_pixclk_div);
3590ecc31b6eSAndy Yan 	*if_dclk_div = ilog2(*if_dclk_div);
3591ecc31b6eSAndy Yan 	*dclk_core_div = ilog2(*dclk_core_div);
3592d86cb420SDamon Ding 	/*
3593d86cb420SDamon Ding 	 * For RK3588, dclk_out is designed for DP, MIPI(both DSC and non-DSC mode)
3594d86cb420SDamon Ding 	 * and HDMI in DSC mode.
3595d86cb420SDamon Ding 	 */
3596d86cb420SDamon Ding 	if (output_type == DRM_MODE_CONNECTOR_DisplayPort ||
3597d86cb420SDamon Ding 	    output_type == DRM_MODE_CONNECTOR_DSI ||
3598d86cb420SDamon Ding 	    (output_type == DRM_MODE_CONNECTOR_HDMIA && cstate->dsc_enable))
3599ecc31b6eSAndy Yan 		*dclk_out_div = ilog2(*dclk_out_div);
3600d86cb420SDamon Ding 	else
3601d86cb420SDamon Ding 		*dclk_out_div = 0;
3602ecc31b6eSAndy Yan 
3603ecc31b6eSAndy Yan 	return dclk_rate;
3604ecc31b6eSAndy Yan }
3605ecc31b6eSAndy Yan 
vop2_calc_dsc_clk(struct display_state * state)360612ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state)
3607ecc31b6eSAndy Yan {
360812ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3609ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
361012ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
36111ace1b6dSDamon Ding 	u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */
3612ecc31b6eSAndy Yan 	u8 k = 1;
3613ecc31b6eSAndy Yan 
3614ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3615ecc31b6eSAndy Yan 		k = 2;
3616ecc31b6eSAndy Yan 
361712ee5af0SDamon Ding 	cstate->dsc_txp_clk_rate = v_pixclk;
361812ee5af0SDamon Ding 	do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k));
3619ecc31b6eSAndy Yan 
362012ee5af0SDamon Ding 	cstate->dsc_pxl_clk_rate = v_pixclk;
362112ee5af0SDamon Ding 	do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k));
3622ecc31b6eSAndy Yan 
3623ecc31b6eSAndy Yan 	/* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
3624ecc31b6eSAndy Yan 	 * cds_dat_width = 96;
3625ecc31b6eSAndy Yan 	 * bits_per_pixel = [8-12];
3626b61227a3SDamon Ding 	 * As cds clk is div from txp clk and only support 1/2/4 div,
3627b61227a3SDamon Ding 	 * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
3628b61227a3SDamon Ding 	 * otherwise dsc_cds = crtc_clock / 8;
3629ecc31b6eSAndy Yan 	 */
3630b61227a3SDamon Ding 	cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
3631ecc31b6eSAndy Yan 
3632ecc31b6eSAndy Yan 	return 0;
3633ecc31b6eSAndy Yan }
3634ecc31b6eSAndy Yan 
rk3588_vop2_if_cfg(struct display_state * state)3635ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
3636ecc31b6eSAndy Yan {
3637ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
3638ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
3639ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
364012ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
3641ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
364252ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
3643ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
3644ecc31b6eSAndy Yan 	int output_if = conn_state->output_if;
3645ecc31b6eSAndy Yan 	int if_pixclk_div = 0;
3646ecc31b6eSAndy Yan 	int if_dclk_div = 0;
3647ecc31b6eSAndy Yan 	unsigned long dclk_rate;
36485d2768f7SDamon Ding 	bool dclk_inv, yc_swap = false;
3649d0408543SAndy Yan 	u32 val;
3650ecc31b6eSAndy Yan 
36515d2768f7SDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3652b890760eSAlgea Cao 	if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
3653b890760eSAlgea Cao 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
3654b890760eSAlgea Cao 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
3655b890760eSAlgea Cao 	} else {
3656ecc31b6eSAndy Yan 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3657ecc31b6eSAndy Yan 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3658b890760eSAlgea Cao 	}
3659ecc31b6eSAndy Yan 
366012ee5af0SDamon Ding 	if (cstate->dsc_enable) {
366112ee5af0SDamon Ding 		int k = 1;
366212ee5af0SDamon Ding 
3663ecc31b6eSAndy Yan 		if (!vop2->data->nr_dscs) {
366412ee5af0SDamon Ding 			printf("Unsupported DSC\n");
3665ecc31b6eSAndy Yan 			return 0;
3666ecc31b6eSAndy Yan 		}
366712ee5af0SDamon Ding 
366812ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
366912ee5af0SDamon Ding 			k = 2;
367012ee5af0SDamon Ding 
367112ee5af0SDamon Ding 		cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
367212ee5af0SDamon Ding 		cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
367312ee5af0SDamon Ding 		cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num;
367412ee5af0SDamon Ding 
367512ee5af0SDamon Ding 		vop2_calc_dsc_clk(state);
367612ee5af0SDamon Ding 		printf("Enable DSC%d slice:%dx%d, slice num:%d\n",
367712ee5af0SDamon Ding 		       cstate->dsc_id, dsc_sink_cap->slice_width,
367812ee5af0SDamon Ding 		       dsc_sink_cap->slice_height, cstate->dsc_slice_num);
3679ecc31b6eSAndy Yan 	}
3680ecc31b6eSAndy Yan 
3681b61227a3SDamon Ding 	dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div);
3682ecc31b6eSAndy Yan 
3683ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_RGB) {
3684ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3685ecc31b6eSAndy Yan 				4, false);
36865d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
36875d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3688ecc31b6eSAndy Yan 	}
3689ecc31b6eSAndy Yan 
3690ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3691ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3692ecc31b6eSAndy Yan 				3, false);
36935d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
36945d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
36955d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
36965d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT,
36975d2768f7SDamon Ding 				yc_swap, false);
3698ecc31b6eSAndy Yan 	}
3699ecc31b6eSAndy Yan 
3700ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_BT656) {
3701ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3702ecc31b6eSAndy Yan 				2, false);
37035d2768f7SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
37045d2768f7SDamon Ding 				RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
37055d2768f7SDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
37065d2768f7SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT,
37075d2768f7SDamon Ding 				yc_swap, false);
3708ecc31b6eSAndy Yan 	}
3709ecc31b6eSAndy Yan 
3710ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3711ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3712ecc31b6eSAndy Yan 			val = 0;
3713ecc31b6eSAndy Yan 		else
3714ecc31b6eSAndy Yan 			val = 1;
371541874944SGuochun Huang 
37163df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
371741874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
371841874944SGuochun Huang 					RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
371941874944SGuochun Huang 
3720ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
3721ecc31b6eSAndy Yan 				1, false);
3722ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
3723ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
3724ecc31b6eSAndy Yan 				if_pixclk_div, false);
372541874944SGuochun Huang 
372641874944SGuochun Huang 		if (conn_state->hold_mode) {
372741874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
37288e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
372941874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
373041874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
373141874944SGuochun Huang 		}
3732ecc31b6eSAndy Yan 	}
3733ecc31b6eSAndy Yan 
3734ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_MIPI1) {
3735ecc31b6eSAndy Yan 		if (cstate->crtc_id == 2)
3736ecc31b6eSAndy Yan 			val = 0;
3737ecc31b6eSAndy Yan 		else if (cstate->crtc_id == 3)
3738ecc31b6eSAndy Yan 			val = 1;
3739ecc31b6eSAndy Yan 		else
3740ecc31b6eSAndy Yan 			val = 3; /*VP1*/
37413df6e59eSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
374241874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
374341874944SGuochun Huang 					RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
374441874944SGuochun Huang 
3745ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
3746ecc31b6eSAndy Yan 				1, false);
3747ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
3748ecc31b6eSAndy Yan 				val, false);
3749ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
3750ecc31b6eSAndy Yan 				if_pixclk_div, false);
375141874944SGuochun Huang 
375241874944SGuochun Huang 		if (conn_state->hold_mode) {
375341874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
37548e7ef808SDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
375541874944SGuochun Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
375641874944SGuochun Huang 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
375741874944SGuochun Huang 		}
3758ecc31b6eSAndy Yan 	}
3759ecc31b6eSAndy Yan 
3760ecc31b6eSAndy Yan 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
37613df6e59eSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
37623df6e59eSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
3763ecc31b6eSAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3764ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3765ecc31b6eSAndy Yan 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
3766ecc31b6eSAndy Yan 					false);
37670a1fb152SZhang Yubing 		switch (conn_state->type) {
37680a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DisplayPort:
37690a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37700a1fb152SZhang Yubing 					RK3588_DP_DUAL_EN_SHIFT, 1, false);
37710a1fb152SZhang Yubing 			break;
37720a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_eDP:
37730a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37740a1fb152SZhang Yubing 					RK3588_EDP_DUAL_EN_SHIFT, 1, false);
37750a1fb152SZhang Yubing 			break;
37760a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_HDMIA:
37770a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37780a1fb152SZhang Yubing 					RK3588_HDMI_DUAL_EN_SHIFT, 1, false);
37790a1fb152SZhang Yubing 			break;
37800a1fb152SZhang Yubing 		case DRM_MODE_CONNECTOR_DSI:
37810a1fb152SZhang Yubing 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37820a1fb152SZhang Yubing 					RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
37830a1fb152SZhang Yubing 			break;
37840a1fb152SZhang Yubing 		default:
37850a1fb152SZhang Yubing 			break;
37860a1fb152SZhang Yubing 		}
3787ecc31b6eSAndy Yan 	}
3788ecc31b6eSAndy Yan 
3789ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP0) {
3790ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
3791ecc31b6eSAndy Yan 				1, false);
3792ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3793ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3794ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3795ecc31b6eSAndy Yan 				if_dclk_div, false);
3796ecc31b6eSAndy Yan 
3797ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3798ecc31b6eSAndy Yan 				if_pixclk_div, false);
3799ecc31b6eSAndy Yan 
3800ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3801ecc31b6eSAndy Yan 				RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
3802ecc31b6eSAndy Yan 	}
3803ecc31b6eSAndy Yan 
3804ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_eDP1) {
3805ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
3806ecc31b6eSAndy Yan 				1, false);
3807ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3808ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3809ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3810ecc31b6eSAndy Yan 				if_dclk_div, false);
3811ecc31b6eSAndy Yan 
3812ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3813ecc31b6eSAndy Yan 				if_pixclk_div, false);
38141848455fSDamon Ding 
38151848455fSDamon Ding 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
38161848455fSDamon Ding 				RK3588_GRF_EDP1_ENABLE_SHIFT, 1);
3817ecc31b6eSAndy Yan 	}
3818ecc31b6eSAndy Yan 
3819ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
3820ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
3821ecc31b6eSAndy Yan 				1, false);
3822ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3823ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3824ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3825ecc31b6eSAndy Yan 				if_dclk_div, false);
3826ecc31b6eSAndy Yan 
3827ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3828ecc31b6eSAndy Yan 				if_pixclk_div, false);
3829b890760eSAlgea Cao 
38302e42aca5SDamon Ding 		if (cstate->dsc_enable)
38312e42aca5SDamon Ding 			vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
38322e42aca5SDamon Ding 					RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT, 1);
38332e42aca5SDamon Ding 
3834b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3835b890760eSAlgea Cao 				RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1);
3836b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3837b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3838b890760eSAlgea Cao 				HDMI0_SYNC_POL_SHIFT, val);
3839ecc31b6eSAndy Yan 	}
3840ecc31b6eSAndy Yan 
3841ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_HDMI1) {
3842ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
3843ecc31b6eSAndy Yan 				1, false);
3844ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3845ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3846ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3847ecc31b6eSAndy Yan 				if_dclk_div, false);
3848ecc31b6eSAndy Yan 
3849ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3850ecc31b6eSAndy Yan 				if_pixclk_div, false);
3851b890760eSAlgea Cao 
38522e42aca5SDamon Ding 		if (cstate->dsc_enable)
38532e42aca5SDamon Ding 			vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
38542e42aca5SDamon Ding 					RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT, 1);
38552e42aca5SDamon Ding 
3856b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3857b890760eSAlgea Cao 				RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1);
3858b890760eSAlgea Cao 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3859b890760eSAlgea Cao 				HDMI_SYNC_POL_MASK,
3860b890760eSAlgea Cao 				HDMI1_SYNC_POL_SHIFT, val);
3861ecc31b6eSAndy Yan 	}
3862ecc31b6eSAndy Yan 
3863ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP0) {
3864ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
3865ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3866ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3867ecc31b6eSAndy Yan 				RK3588_DP0_PIN_POL_SHIFT, val, false);
3868ecc31b6eSAndy Yan 	}
3869ecc31b6eSAndy Yan 
3870ecc31b6eSAndy Yan 	if (output_if & VOP_OUTPUT_IF_DP1) {
3871ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
3872ecc31b6eSAndy Yan 				cstate->crtc_id, false);
3873ecc31b6eSAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3874ecc31b6eSAndy Yan 				RK3588_DP1_PIN_POL_SHIFT, val, false);
3875ecc31b6eSAndy Yan 	}
3876ecc31b6eSAndy Yan 
3877ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3878b61227a3SDamon Ding 			DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false);
3879ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3880b61227a3SDamon Ding 			DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false);
3881ecc31b6eSAndy Yan 
3882dd0d7bfeSDamon Ding 	return dclk_rate / 1000;
3883ecc31b6eSAndy Yan }
3884ecc31b6eSAndy Yan 
rk3576_vop2_if_cfg(struct display_state * state)3885a552a69cSDamon Ding static unsigned long rk3576_vop2_if_cfg(struct display_state *state)
3886a552a69cSDamon Ding {
3887a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
3888a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
3889a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
3890a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
3891a552a69cSDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
3892a552a69cSDamon Ding 	u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate;
3893a552a69cSDamon Ding 	int output_if = conn_state->output_if;
3894a552a69cSDamon Ding 	bool dclk_inv, yc_swap = false;
3895a552a69cSDamon Ding 	bool split_mode = !!(conn_state->output_flags &
3896a552a69cSDamon Ding 			     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE);
3897a552a69cSDamon Ding 	bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false;
3898a552a69cSDamon Ding 	bool interface_dclk_sel, interface_pix_clk_sel = false;
3899a552a69cSDamon Ding 	bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK ||
3900a552a69cSDamon Ding 			    conn_state->output_if & VOP_OUTPUT_IF_BT656;
3901cce1f2abSDamon Ding 	unsigned long dclk_in_rate, dclk_core_rate;
3902a552a69cSDamon Ding 	u32 val;
3903a552a69cSDamon Ding 
390445ec9215SDamon Ding 	if (split_mode) {
390545ec9215SDamon Ding 		printf("WARN: split is enabled, post-scaler shouldn't be set\n");
390645ec9215SDamon Ding 		conn_state->overscan.left_margin = 100;
390745ec9215SDamon Ding 		conn_state->overscan.right_margin = 100;
390845ec9215SDamon Ding 		conn_state->overscan.top_margin = 100;
390945ec9215SDamon Ding 		conn_state->overscan.bottom_margin = 100;
391045ec9215SDamon Ding 
391145ec9215SDamon Ding 		/*
391245ec9215SDamon Ding 		 * VOP split and sharp use the same line buffer. If enable
391345ec9215SDamon Ding 		 * split, sharp must be disabled completely.
391445ec9215SDamon Ding 		 */
391545ec9215SDamon Ding 		if (vop2->data->vp_data[cstate->crtc_id].feature & VOP_FEATURE_POST_SHARP)
391645ec9215SDamon Ding 			writel(false << SW_SHARP_ENABLE_SHIFT,
391745ec9215SDamon Ding 			       vop2->sharp_res + RK3576_SHARP_CTRL);
391845ec9215SDamon Ding 	}
391945ec9215SDamon Ding 
3920a552a69cSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3921a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
3922a552a69cSDamon Ding 		/*
3923a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3924a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
3925a552a69cSDamon Ding 		 */
3926a552a69cSDamon Ding 		val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3927a552a69cSDamon Ding 	} else {
3928a552a69cSDamon Ding 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3929a552a69cSDamon Ding 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3930a552a69cSDamon Ding 	}
3931a552a69cSDamon Ding 
3932cce1f2abSDamon Ding 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 ||
3933cce1f2abSDamon Ding 	    mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode))
3934a552a69cSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */
3935a552a69cSDamon Ding 	else
3936cce1f2abSDamon Ding 		cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */
3937cce1f2abSDamon Ding 	dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div;
3938cce1f2abSDamon Ding 
3939cce1f2abSDamon Ding 	if (double_pixel)
3940cce1f2abSDamon Ding 		dclk_core_rate = mode->crtc_clock / 2;
3941cce1f2abSDamon Ding 	else
3942cce1f2abSDamon Ding 		dclk_core_rate = mode->crtc_clock / port_pix_rate;
3943cce1f2abSDamon Ding 	post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */
3944a552a69cSDamon Ding 
3945a552a69cSDamon Ding 	if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3946a552a69cSDamon Ding 		pix_half_rate = true;
3947a552a69cSDamon Ding 		post_dclk_out_sel = true;
3948a552a69cSDamon Ding 	}
3949a552a69cSDamon Ding 
3950a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3951a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3952a552a69cSDamon Ding 		/*
3953a552a69cSDamon Ding 		 * RGB interface_pix_clk_sel will auto config according
3954a552a69cSDamon Ding 		 * to rgb_en/bt1120_en/bt656_en.
3955a552a69cSDamon Ding 		 */
3956a552a69cSDamon Ding 	} else if (output_if & VOP_OUTPUT_IF_eDP0) {
3957a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3958a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0;
3959a552a69cSDamon Ding 	} else {
3960a552a69cSDamon Ding 		interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3961a552a69cSDamon Ding 		interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0;
3962a552a69cSDamon Ding 	}
3963a552a69cSDamon Ding 
3964a552a69cSDamon Ding 	/* dclk_core */
3965a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3966a552a69cSDamon Ding 			RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false);
3967a552a69cSDamon Ding 	/* dclk_out */
3968a552a69cSDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3969a552a69cSDamon Ding 			RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false);
3970a552a69cSDamon Ding 
3971a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_RGB) {
3972a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3973a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3974a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3975a552a69cSDamon Ding 
3976a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3977a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3978a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3979a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3980a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3981a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
3982a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3983a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3984a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3985a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
3986a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3987a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv);
3988a552a69cSDamon Ding 	}
3989a552a69cSDamon Ding 
3990a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT1120) {
3991a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
3992a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3993a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3994a552a69cSDamon Ding 
3995a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3996a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3997a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3998a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3999a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4000a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
4001a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4002a552a69cSDamon Ding 				RK3576_BT1120_OUT_EN_SHIFT, 1, false);
4003a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4004a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4005a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
4006a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
4007a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
4008a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4009a552a69cSDamon Ding 				RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false);
4010a552a69cSDamon Ding 	}
4011a552a69cSDamon Ding 
4012a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_BT656) {
4013a552a69cSDamon Ding 		/* 0: dclk_core, 1: dclk_out */
4014a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4015a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4016a552a69cSDamon Ding 
4017a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4018a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4019a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4020a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4021a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4022a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
4023a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4024a552a69cSDamon Ding 				RK3576_BT656_OUT_EN_SHIFT, 1, false);
4025a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4026a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4027a552a69cSDamon Ding 		vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
4028a552a69cSDamon Ding 				RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
4029a552a69cSDamon Ding 		yc_swap = is_yc_swap(conn_state->bus_format);
4030a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4031a552a69cSDamon Ding 				RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false);
4032a552a69cSDamon Ding 	}
4033a552a69cSDamon Ding 
4034a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
4035a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4036a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4037a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
4038a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4039a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4040a552a69cSDamon Ding 
4041a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4042a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4043a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4044a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4045a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4046a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
4047a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4048a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4049a552a69cSDamon Ding 		/*
4050a552a69cSDamon Ding 		 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
4051a552a69cSDamon Ding 		 * so set VOP hsync/vsync polarity as positive by default.
4052a552a69cSDamon Ding 		 */
4053a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576)
4054a552a69cSDamon Ding 			val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
4055a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4056a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
4057a552a69cSDamon Ding 
4058a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
4059a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4060a552a69cSDamon Ding 					RK3576_MIPI_CMD_MODE_SHIFT, 1, false);
4061a552a69cSDamon Ding 
4062a552a69cSDamon Ding 		if (conn_state->hold_mode) {
4063a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4064a552a69cSDamon Ding 					EDPI_TE_EN, !cstate->soft_te, false);
4065a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4066a552a69cSDamon Ding 					EDPI_WMS_HOLD_EN, 1, false);
4067a552a69cSDamon Ding 		}
4068a552a69cSDamon Ding 	}
4069a552a69cSDamon Ding 
4070a552a69cSDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
4071a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4072a552a69cSDamon Ding 				MIPI_DUAL_EN_SHIFT, 1, false);
4073a552a69cSDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
4074a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4075a552a69cSDamon Ding 					MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
4076a552a69cSDamon Ding 		switch (conn_state->type) {
4077a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DisplayPort:
4078a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4079a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4080a552a69cSDamon Ding 			break;
4081a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_eDP:
4082a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4083a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4084a552a69cSDamon Ding 			break;
4085a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_HDMIA:
4086a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4087a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4088a552a69cSDamon Ding 			break;
4089a552a69cSDamon Ding 		case DRM_MODE_CONNECTOR_DSI:
4090a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4091a552a69cSDamon Ding 					RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4092a552a69cSDamon Ding 			break;
4093a552a69cSDamon Ding 		default:
4094a552a69cSDamon Ding 			break;
4095a552a69cSDamon Ding 		}
4096a552a69cSDamon Ding 	}
4097a552a69cSDamon Ding 
4098a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_eDP0) {
4099a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4100a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4101a552a69cSDamon Ding 		/* 0: dclk, 1: port0_dclk */
4102a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4103a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4104a552a69cSDamon Ding 
4105a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4106a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4107a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4108a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4109a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4110a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
4111a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4112a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4113a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4114a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
4115a552a69cSDamon Ding 	}
4116a552a69cSDamon Ding 
4117a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
4118a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4119a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4120a552a69cSDamon Ding 		/* 0: div2, 1: div4 */
4121a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4122a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4123a552a69cSDamon Ding 
4124a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4125a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4126a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4127a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4128a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4129a552a69cSDamon Ding 				RK3576_IF_OUT_EN_SHIFT, 1, false);
4130a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4131a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4132a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4133a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
4134a552a69cSDamon Ding 	}
4135a552a69cSDamon Ding 
4136a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP0) {
4137a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4138a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4139a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
4140a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4141a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4142a552a69cSDamon Ding 
4143a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4144a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4145a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4146a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4147a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4148a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4149a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4150a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
4151a552a69cSDamon Ding 	}
4152a552a69cSDamon Ding 
4153a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP1) {
4154a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4155a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4156a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
4157a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4158a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4159a552a69cSDamon Ding 
4160a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
4161a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4162a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
4163a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4164a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4165a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4166a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4167a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
4168a552a69cSDamon Ding 	}
4169a552a69cSDamon Ding 
4170a552a69cSDamon Ding 	if (output_if & VOP_OUTPUT_IF_DP2) {
4171a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4172a552a69cSDamon Ding 				RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4173a552a69cSDamon Ding 		/* 0: no div, 1: div2 */
4174a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4175a552a69cSDamon Ding 				RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4176a552a69cSDamon Ding 
4177a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
4178a552a69cSDamon Ding 				RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4179a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
4180a552a69cSDamon Ding 				RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4181a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4182a552a69cSDamon Ding 				RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4183a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4184a552a69cSDamon Ding 				RK3576_IF_PIN_POL_SHIFT, val, false);
4185a552a69cSDamon Ding 	}
4186a552a69cSDamon Ding 
4187a552a69cSDamon Ding 	return mode->crtc_clock;
4188a552a69cSDamon Ding }
4189a552a69cSDamon Ding 
rk3568_vop2_setup_dual_channel_if(struct display_state * state)4190a2a16809SChaoyi Chen static void rk3568_vop2_setup_dual_channel_if(struct display_state *state)
4191a2a16809SChaoyi Chen {
4192a2a16809SChaoyi Chen 	struct crtc_state *cstate = &state->crtc_state;
4193a2a16809SChaoyi Chen 	struct connector_state *conn_state = &state->conn_state;
4194a2a16809SChaoyi Chen 	struct vop2 *vop2 = cstate->private;
4195a2a16809SChaoyi Chen 	u32 vp_offset = (cstate->crtc_id * 0x100);
4196a2a16809SChaoyi Chen 
4197a2a16809SChaoyi Chen 	if (conn_state->output_flags &
4198a2a16809SChaoyi Chen 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) {
4199a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4200a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
4201a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4202a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false);
4203a2a16809SChaoyi Chen 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
4204a2a16809SChaoyi Chen 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4205a2a16809SChaoyi Chen 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
4206a2a16809SChaoyi Chen 
4207a2a16809SChaoyi Chen 		return;
4208a2a16809SChaoyi Chen 	}
4209a2a16809SChaoyi Chen 
4210a2a16809SChaoyi Chen 	vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4211a2a16809SChaoyi Chen 			MIPI_DUAL_EN_SHIFT, 1, false);
4212a2a16809SChaoyi Chen 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) {
4213a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4214a2a16809SChaoyi Chen 				MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
4215a2a16809SChaoyi Chen 	}
4216a2a16809SChaoyi Chen 
4217a2a16809SChaoyi Chen 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
4218a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4219a2a16809SChaoyi Chen 				LVDS_DUAL_EN_SHIFT, 1, false);
4220a2a16809SChaoyi Chen 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4221a2a16809SChaoyi Chen 				LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false);
4222a2a16809SChaoyi Chen 	}
4223a2a16809SChaoyi Chen }
4224a2a16809SChaoyi Chen 
rk3568_vop2_if_cfg(struct display_state * state)4225ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
4226ecc31b6eSAndy Yan {
4227ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
4228ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
4229ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
4230ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
4231d0408543SAndy Yan 	bool dclk_inv;
4232ecc31b6eSAndy Yan 	u32 val;
42338895aec1SSandy Huang 
423413f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
423510ee9f5bSAlgea Cao 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
423610ee9f5bSAlgea Cao 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4237d0408543SAndy Yan 
4238d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
4239d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
4240d0408543SAndy Yan 				1, false);
4241d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4242d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
424315f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
424415f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4245ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
4246c55d261eSSandy Huang 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
4247d0408543SAndy Yan 	}
4248d0408543SAndy Yan 
4249d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
425052ee18acSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
425152ee18acSSandy Huang 				1, false);
4252d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
4253d0408543SAndy Yan 				BT1120_EN_SHIFT, 1, false);
4254d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4255d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
4256ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
425752ee18acSSandy Huang 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
4258d0408543SAndy Yan 	}
4259d0408543SAndy Yan 
4260d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4261d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4262d0408543SAndy Yan 				1, false);
4263d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4264d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
4265ecc31b6eSAndy Yan 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
426652ee18acSSandy Huang 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
4267d0408543SAndy Yan 	}
4268d0408543SAndy Yan 
4269d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
4270d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
4271d0408543SAndy Yan 				1, false);
4272d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4273d0408543SAndy Yan 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
427415f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
427515f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
427611f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
427715f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4278d0408543SAndy Yan 	}
4279d0408543SAndy Yan 
4280d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
4281d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
4282d0408543SAndy Yan 				1, false);
4283d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4284d0408543SAndy Yan 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
428515f69071SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
428615f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
428711f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
428815f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4289d0408543SAndy Yan 	}
4290d0408543SAndy Yan 
4291d0408543SAndy Yan 
4292d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
4293d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
4294d0408543SAndy Yan 				1, false);
4295d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4296d0408543SAndy Yan 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
4297d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4298c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
4299de022775SGuochun Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
4300de022775SGuochun Huang 				IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
4301d0408543SAndy Yan 	}
4302d0408543SAndy Yan 
4303d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
4304d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
4305d0408543SAndy Yan 				1, false);
4306d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4307d0408543SAndy Yan 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
4308d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4309c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
4310de022775SGuochun Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
4311de022775SGuochun Huang 				IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
4312d0408543SAndy Yan 	}
4313d0408543SAndy Yan 
4314d0408543SAndy Yan 	if (conn_state->output_flags &
4315a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
4316a2a16809SChaoyi Chen 	    conn_state->output_flags &
4317a2a16809SChaoyi Chen 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)
4318a2a16809SChaoyi Chen 		rk3568_vop2_setup_dual_channel_if(state);
4319d0408543SAndy Yan 
4320d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
4321d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
4322d0408543SAndy Yan 				1, false);
4323d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4324d0408543SAndy Yan 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
4325c55d261eSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4326c55d261eSSandy Huang 				IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
43277bcdc6eeSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK,
43287bcdc6eeSDamon Ding 				IF_CTRL_EDP_PIN_POL_SHIFT, val, false);
4329d0408543SAndy Yan 	}
4330d0408543SAndy Yan 
4331d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4332d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4333d0408543SAndy Yan 				1, false);
4334d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4335d0408543SAndy Yan 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
433610ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
433710ee9f5bSAlgea Cao 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
433810ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
433910ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_MASK,
434010ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4341d0408543SAndy Yan 	}
434210ee9f5bSAlgea Cao 
4343823146b6SDamon Ding 	return mode->crtc_clock;
4344ecc31b6eSAndy Yan }
4345ecc31b6eSAndy Yan 
rk3562_vop2_if_cfg(struct display_state * state)4346452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state)
4347452afb13SDamon Ding {
4348452afb13SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
4349452afb13SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
4350452afb13SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
4351452afb13SDamon Ding 	struct vop2 *vop2 = cstate->private;
4352452afb13SDamon Ding 	bool dclk_inv;
4353606f72bdSDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
4354452afb13SDamon Ding 	u32 val;
4355452afb13SDamon Ding 
435613f658dcSDamon Ding 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
4357452afb13SDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4358452afb13SDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4359452afb13SDamon Ding 
4360452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
4361452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
4362452afb13SDamon Ding 				1, false);
4363452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4364452afb13SDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
4365452afb13SDamon Ding 		vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK,
4366452afb13SDamon Ding 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
4367452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
436815f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4369452afb13SDamon Ding 	}
4370452afb13SDamon Ding 
4371452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
4372452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
4373452afb13SDamon Ding 				1, false);
4374452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4375452afb13SDamon Ding 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
4376452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
437715f69071SDamon Ding 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4378452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
437915f69071SDamon Ding 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4380452afb13SDamon Ding 	}
4381452afb13SDamon Ding 
4382452afb13SDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
4383452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
4384452afb13SDamon Ding 				1, false);
4385452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4386452afb13SDamon Ding 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
4387452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4388452afb13SDamon Ding 				RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false);
4389452afb13SDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
4390452afb13SDamon Ding 				RK3562_MIPI_PIN_POL_SHIFT, val, false);
4391606f72bdSDamon Ding 
4392606f72bdSDamon Ding 		if (conn_state->hold_mode) {
4393606f72bdSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4394606f72bdSDamon Ding 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
4395606f72bdSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4396606f72bdSDamon Ding 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
4397606f72bdSDamon Ding 		}
4398452afb13SDamon Ding 	}
4399452afb13SDamon Ding 
4400452afb13SDamon Ding 	return mode->crtc_clock;
4401452afb13SDamon Ding }
4402452afb13SDamon Ding 
rk3528_vop2_if_cfg(struct display_state * state)4403a552a69cSDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state)
4404a552a69cSDamon Ding {
4405a552a69cSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
4406a552a69cSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
4407a552a69cSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
4408a552a69cSDamon Ding 	struct vop2 *vop2 = cstate->private;
4409a552a69cSDamon Ding 	u32 val;
4410a552a69cSDamon Ding 
4411a552a69cSDamon Ding 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4412a552a69cSDamon Ding 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4413a552a69cSDamon Ding 
4414a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4415a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4416a552a69cSDamon Ding 				1, false);
4417a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4418a552a69cSDamon Ding 				RGB_MUX_SHIFT, cstate->crtc_id, false);
4419a552a69cSDamon Ding 	}
4420a552a69cSDamon Ding 
4421a552a69cSDamon Ding 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4422a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4423a552a69cSDamon Ding 				1, false);
4424a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4425a552a69cSDamon Ding 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
4426a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4427a552a69cSDamon Ding 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
4428a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
4429a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_MASK,
4430a552a69cSDamon Ding 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4431a552a69cSDamon Ding 	}
4432a552a69cSDamon Ding 
4433a552a69cSDamon Ding 	return mode->crtc_clock;
4434a552a69cSDamon Ding }
4435a552a69cSDamon Ding 
vop2_post_color_swap(struct display_state * state)443665747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state)
443765747de7SDamon Ding {
443865747de7SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
443965747de7SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
444065747de7SDamon Ding 	struct vop2 *vop2 = cstate->private;
444165747de7SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
444265747de7SDamon Ding 	u32 output_type = conn_state->type;
444365747de7SDamon Ding 	u32 data_swap = 0;
444465747de7SDamon Ding 
4445c8820b76SDamon Ding 	if (is_uv_swap(state) || is_rb_swap(state))
444665747de7SDamon Ding 		data_swap = DSP_RB_SWAP;
444765747de7SDamon Ding 
4448a552a69cSDamon Ding 	if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) {
4449a552a69cSDamon Ding 		if ((output_type == DRM_MODE_CONNECTOR_HDMIA ||
4450e6e4c154SDamon Ding 		     output_type == DRM_MODE_CONNECTOR_DisplayPort) &&
445165747de7SDamon Ding 		    (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
445265747de7SDamon Ding 		     conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
445365747de7SDamon Ding 		data_swap |= DSP_RG_SWAP;
4454a552a69cSDamon Ding 	}
445565747de7SDamon Ding 
445665747de7SDamon Ding 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
445765747de7SDamon Ding 			DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false);
445865747de7SDamon Ding }
445965747de7SDamon Ding 
vop2_clk_set_parent(struct clk * clk,struct clk * parent)4460b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
4461b890760eSAlgea Cao {
4462e1a1aa04SFinley Xiao #ifndef CONFIG_MOS_SUPPORT
4463b890760eSAlgea Cao 	int ret = 0;
4464b890760eSAlgea Cao 
4465b890760eSAlgea Cao 	if (parent->dev)
4466b890760eSAlgea Cao 		ret = clk_set_parent(clk, parent);
4467b890760eSAlgea Cao 	if (ret < 0)
4468b890760eSAlgea Cao 		debug("failed to set %s as parent for %s\n",
4469b890760eSAlgea Cao 		      parent->dev->name, clk->dev->name);
4470e1a1aa04SFinley Xiao #endif
4471b890760eSAlgea Cao }
4472b890760eSAlgea Cao 
vop2_clk_set_rate(struct clk * clk,ulong rate)4473b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate)
4474b890760eSAlgea Cao {
4475b890760eSAlgea Cao 	int ret = 0;
4476b890760eSAlgea Cao 
4477b890760eSAlgea Cao 	if (clk->dev)
4478b890760eSAlgea Cao 		ret = clk_set_rate(clk, rate);
4479b890760eSAlgea Cao 	if (ret < 0)
4480b890760eSAlgea Cao 		debug("failed to set %s rate %lu \n", clk->dev->name, rate);
4481b890760eSAlgea Cao 
4482b890760eSAlgea Cao 	return ret;
4483b890760eSAlgea Cao }
4484b890760eSAlgea Cao 
vop2_calc_dsc_cru_cfg(struct display_state * state,int * dsc_txp_clk_div,int * dsc_pxl_clk_div,int * dsc_cds_clk_div,u64 dclk_rate)448512ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state,
448612ee5af0SDamon Ding 				  int *dsc_txp_clk_div, int *dsc_pxl_clk_div,
448712ee5af0SDamon Ding 				  int *dsc_cds_clk_div, u64 dclk_rate)
448812ee5af0SDamon Ding {
448912ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
449012ee5af0SDamon Ding 
449112ee5af0SDamon Ding 	*dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate;
449212ee5af0SDamon Ding 	*dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate;
449312ee5af0SDamon Ding 	*dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate;
449412ee5af0SDamon Ding 
449512ee5af0SDamon Ding 	*dsc_txp_clk_div = ilog2(*dsc_txp_clk_div);
449612ee5af0SDamon Ding 	*dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div);
449712ee5af0SDamon Ding 	*dsc_cds_clk_div = ilog2(*dsc_cds_clk_div);
449812ee5af0SDamon Ding }
449912ee5af0SDamon Ding 
vop2_load_pps(struct display_state * state,struct vop2 * vop2,u8 dsc_id)450012ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id)
450112ee5af0SDamon Ding {
450212ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
450312ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set *pps = &cstate->pps;
450412ee5af0SDamon Ding 	struct drm_dsc_picture_parameter_set config_pps;
450512ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
450612ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
450712ee5af0SDamon Ding 	u32 *pps_val = (u32 *)&config_pps;
450812ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
450912ee5af0SDamon Ding 	int i = 0;
451012ee5af0SDamon Ding 
451112ee5af0SDamon Ding 	memcpy(&config_pps, pps, sizeof(config_pps));
451212ee5af0SDamon Ding 
451312ee5af0SDamon Ding 	if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) {
451412ee5af0SDamon Ding 		config_pps.pps_3 &= 0xf0;
451512ee5af0SDamon Ding 		config_pps.pps_3 |= dsc_data->max_linebuf_depth;
451612ee5af0SDamon Ding 		printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
451712ee5af0SDamon Ding 		       dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf);
451812ee5af0SDamon Ding 	}
451912ee5af0SDamon Ding 
452012ee5af0SDamon Ding 	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
452112ee5af0SDamon Ding 		config_pps.rc_range_parameters[i] =
452212ee5af0SDamon Ding 			(pps->rc_range_parameters[i] >> 3 & 0x1f) |
452312ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
452412ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
452512ee5af0SDamon Ding 			((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
452612ee5af0SDamon Ding 	}
452712ee5af0SDamon Ding 
452812ee5af0SDamon Ding 	for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
452912ee5af0SDamon Ding 		vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++);
453012ee5af0SDamon Ding }
453112ee5af0SDamon Ding 
vop2_dsc_enable(struct display_state * state,struct vop2 * vop2,u8 dsc_id,u64 dclk_rate)453212ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate)
453312ee5af0SDamon Ding {
453412ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
453512ee5af0SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
453612ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
453712ee5af0SDamon Ding 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
453812ee5af0SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
453912ee5af0SDamon Ding 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
454012ee5af0SDamon Ding 	bool mipi_ds_mode = false;
454112ee5af0SDamon Ding 	u8 dsc_interface_mode = 0;
454212ee5af0SDamon Ding 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
454312ee5af0SDamon Ding 	u16 hdisplay = mode->crtc_hdisplay;
454412ee5af0SDamon Ding 	u16 htotal = mode->crtc_htotal;
454512ee5af0SDamon Ding 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
454612ee5af0SDamon Ding 	u16 vdisplay = mode->crtc_vdisplay;
454712ee5af0SDamon Ding 	u16 vtotal = mode->crtc_vtotal;
454812ee5af0SDamon Ding 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
454912ee5af0SDamon Ding 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
455012ee5af0SDamon Ding 	u16 vact_end = vact_st + vdisplay;
455112ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
455212ee5af0SDamon Ding 	u32 decoder_regs_offset = (dsc_id * 0x100);
455312ee5af0SDamon Ding 	int dsc_txp_clk_div = 0;
455412ee5af0SDamon Ding 	int dsc_pxl_clk_div = 0;
455512ee5af0SDamon Ding 	int dsc_cds_clk_div = 0;
4556baf2c414SDamon Ding 	int val = 0;
455712ee5af0SDamon Ding 
455812ee5af0SDamon Ding 	if (!vop2->data->nr_dscs) {
455912ee5af0SDamon Ding 		printf("Unsupported DSC\n");
456012ee5af0SDamon Ding 		return;
456112ee5af0SDamon Ding 	}
456212ee5af0SDamon Ding 
456312ee5af0SDamon Ding 	if (cstate->dsc_slice_num > dsc_data->max_slice_num)
456412ee5af0SDamon Ding 		printf("DSC%d supported max slice is: %d, current is: %d\n",
456512ee5af0SDamon Ding 		       dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num);
456612ee5af0SDamon Ding 
456712ee5af0SDamon Ding 	if (dsc_data->pd_id) {
456812ee5af0SDamon Ding 		if (vop2_power_domain_on(vop2, dsc_data->pd_id))
456912ee5af0SDamon Ding 			printf("open dsc%d pd fail\n", dsc_id);
457012ee5af0SDamon Ding 	}
457112ee5af0SDamon Ding 
457212ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK,
457312ee5af0SDamon Ding 			SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false);
457412ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK,
457512ee5af0SDamon Ding 			DSC_PORT_SEL_SHIFT, cstate->crtc_id, false);
457612ee5af0SDamon Ding 	if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
457712ee5af0SDamon Ding 		dsc_interface_mode = VOP_DSC_IF_HDMI;
457812ee5af0SDamon Ding 	} else {
457912ee5af0SDamon Ding 		mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
458012ee5af0SDamon Ding 		if (mipi_ds_mode)
458112ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
458212ee5af0SDamon Ding 		else
458312ee5af0SDamon Ding 			dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
458412ee5af0SDamon Ding 	}
458512ee5af0SDamon Ding 
458612ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
458712ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
458812ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 0, false);
458912ee5af0SDamon Ding 	else
459012ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
459112ee5af0SDamon Ding 				DSC_MAN_MODE_SHIFT, 1, false);
459212ee5af0SDamon Ding 
459312ee5af0SDamon Ding 	vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate);
459412ee5af0SDamon Ding 
459512ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK,
459612ee5af0SDamon Ding 			DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false);
459712ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK,
459812ee5af0SDamon Ding 			DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false);
459912ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK,
460012ee5af0SDamon Ding 			DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false);
460112ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK,
460212ee5af0SDamon Ding 			DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false);
460312ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
460412ee5af0SDamon Ding 			DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false);
460512ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK,
460612ee5af0SDamon Ding 			DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false);
460712ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
460812ee5af0SDamon Ding 			DSC_HALT_EN_SHIFT, mipi_ds_mode, false);
460912ee5af0SDamon Ding 
461012ee5af0SDamon Ding 	if (!mipi_ds_mode) {
461112ee5af0SDamon Ding 		u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
461212ee5af0SDamon Ding 		u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
461312ee5af0SDamon Ding 		u64 dsc_cds_rate = cstate->dsc_cds_clk_rate;
461412ee5af0SDamon Ding 		u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */
461512ee5af0SDamon Ding 		u32 dly_num, dsc_cds_rate_mhz, val = 0;
4616b61227a3SDamon Ding 		int k = 1;
4617b61227a3SDamon Ding 
4618b61227a3SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
4619b61227a3SDamon Ding 			k = 2;
462012ee5af0SDamon Ding 
462112ee5af0SDamon Ding 		if (target_bpp >> 4 < dsc_data->min_bits_per_pixel)
462212ee5af0SDamon Ding 			printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel);
462312ee5af0SDamon Ding 
462412ee5af0SDamon Ding 		/*
462512ee5af0SDamon Ding 		 * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
462612ee5af0SDamon Ding 		 * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
462712ee5af0SDamon Ding 		 * T (dsc_cds) = 1 / dsc_cds_rate_mhz
46281ace1b6dSDamon Ding 		 *
46291ace1b6dSDamon Ding 		 * HDMI:
463012ee5af0SDamon Ding 		 * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
463112ee5af0SDamon Ding 		 *                 delay_line_num = 4 - BPP / 8
463212ee5af0SDamon Ding 		 *                                = (64 - target_bpp / 8) / 16
463312ee5af0SDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
46341ace1b6dSDamon Ding 		 *
46351ace1b6dSDamon Ding 		 * MIPI DSI[4320 and 9216 is buffer size for DSC]:
46361ace1b6dSDamon Ding 		 * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
46371ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
46381ace1b6dSDamon Ding 		 * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
46391ace1b6dSDamon Ding 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
46401ace1b6dSDamon Ding 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
464112ee5af0SDamon Ding 		 */
464212ee5af0SDamon Ding 		do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
464312ee5af0SDamon Ding 		dsc_cds_rate_mhz = dsc_cds_rate;
46441ace1b6dSDamon Ding 		dsc_hsync = hsync_len / 2;
46451ace1b6dSDamon Ding 		if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
464612ee5af0SDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
46471ace1b6dSDamon Ding 		} else {
46481ace1b6dSDamon Ding 			int dsc_buf_size  = dsc_id == 0 ? 4320 * 8 : 9216 * 2;
46491ace1b6dSDamon Ding 			int delay_line_num = dsc_buf_size / cstate->dsc_slice_num /
46501ace1b6dSDamon Ding 					     be16_to_cpu(cstate->pps.chunk_size);
46511ace1b6dSDamon Ding 
46521ace1b6dSDamon Ding 			delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
46531ace1b6dSDamon Ding 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
46541ace1b6dSDamon Ding 
46551ace1b6dSDamon Ding 			/* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
46561ace1b6dSDamon Ding 			if (dsc_hsync < 8)
46571ace1b6dSDamon Ding 				dsc_hsync = 8;
46581ace1b6dSDamon Ding 		}
465912ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK,
466012ee5af0SDamon Ding 				DSC_INIT_DLY_MODE_SHIFT, 0, false);
466112ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK,
466212ee5af0SDamon Ding 				DSC_INIT_DLY_NUM_SHIFT, dly_num, false);
466312ee5af0SDamon Ding 
4664b61227a3SDamon Ding 		/*
4665b61227a3SDamon Ding 		 * htotal / dclk_core = dsc_htotal /cds_clk
4666b61227a3SDamon Ding 		 *
4667b61227a3SDamon Ding 		 * dclk_core = DCLK / (1 << dclk_core->div_val)
4668b61227a3SDamon Ding 		 * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
4669b61227a3SDamon Ding 		 * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
4670b61227a3SDamon Ding 		 *
4671b61227a3SDamon Ding 		 * dsc_htotal = htotal * (1 << dclk_core->div_val) /
4672b61227a3SDamon Ding 		 *              ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
4673b61227a3SDamon Ding 		 */
4674b61227a3SDamon Ding 		dsc_htotal = htotal * (1 << cstate->dclk_core_div) /
4675b61227a3SDamon Ding 			     ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div));
467612ee5af0SDamon Ding 		val = dsc_htotal << 16 | dsc_hsync;
467712ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK,
467812ee5af0SDamon Ding 				DSC_HTOTAL_PW_SHIFT, val, false);
467912ee5af0SDamon Ding 
468012ee5af0SDamon Ding 		dsc_hact_st = hact_st / 2;
4681b61227a3SDamon Ding 		dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
468212ee5af0SDamon Ding 		val = dsc_hact_end << 16 | dsc_hact_st;
468312ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK,
468412ee5af0SDamon Ding 				DSC_HACT_ST_END_SHIFT, val, false);
468512ee5af0SDamon Ding 
468612ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK,
468712ee5af0SDamon Ding 				DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false);
468812ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK,
468912ee5af0SDamon Ding 				DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false);
469012ee5af0SDamon Ding 	}
469112ee5af0SDamon Ding 
469212ee5af0SDamon Ding 	vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK,
469312ee5af0SDamon Ding 			RST_DEASSERT_SHIFT, 1, false);
469412ee5af0SDamon Ding 	udelay(10);
469512ee5af0SDamon Ding 
4696baf2c414SDamon Ding 	val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) |
4697baf2c414SDamon Ding 	       ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT);
4698baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
4699baf2c414SDamon Ding 
470012ee5af0SDamon Ding 	vop2_load_pps(state, vop2, dsc_id);
470112ee5af0SDamon Ding 
4702baf2c414SDamon Ding 	val |= (1 << DSC_PPS_UPD_SHIFT);
4703baf2c414SDamon Ding 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
470412ee5af0SDamon Ding 
470512ee5af0SDamon Ding 	printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
470612ee5af0SDamon Ding 	       dsc_id,
470712ee5af0SDamon Ding 	       cstate->dsc_txp_clk_rate, dsc_txp_clk_div,
470812ee5af0SDamon Ding 	       cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div,
470912ee5af0SDamon Ding 	       cstate->dsc_cds_clk_rate, dsc_cds_clk_div);
471012ee5af0SDamon Ding }
471112ee5af0SDamon Ding 
is_extend_pll(struct display_state * state,struct udevice ** clk_dev)47125f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev)
47135f1357a2SZhang Yubing {
47145f1357a2SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
47155f1357a2SZhang Yubing 	struct vop2 *vop2 = cstate->private;
47165f1357a2SZhang Yubing 	struct udevice *vp_dev, *dev;
47175f1357a2SZhang Yubing 	struct ofnode_phandle_args args;
47185f1357a2SZhang Yubing 	char vp_name[10];
47195f1357a2SZhang Yubing 	int ret;
47205f1357a2SZhang Yubing 
4721a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576)
47225f1357a2SZhang Yubing 		return false;
47235f1357a2SZhang Yubing 
47245f1357a2SZhang Yubing 	sprintf(vp_name, "port@%d", cstate->crtc_id);
47255f1357a2SZhang Yubing 	if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) {
47265e85f4a7SZhang Yubing 		debug("warn: can't get vp device\n");
47275f1357a2SZhang Yubing 		return false;
47285f1357a2SZhang Yubing 	}
47295f1357a2SZhang Yubing 
47305f1357a2SZhang Yubing 	ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0,
47315f1357a2SZhang Yubing 					 0, &args);
47325f1357a2SZhang Yubing 	if (ret) {
47335e85f4a7SZhang Yubing 		debug("assigned-clock-parents's node not define\n");
47345f1357a2SZhang Yubing 		return false;
47355f1357a2SZhang Yubing 	}
47365f1357a2SZhang Yubing 
47375f1357a2SZhang Yubing 	if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) {
47385e85f4a7SZhang Yubing 		debug("warn: can't get clk device\n");
47395f1357a2SZhang Yubing 		return false;
47405f1357a2SZhang Yubing 	}
47415f1357a2SZhang Yubing 
47425f1357a2SZhang Yubing 	if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) {
47435f1357a2SZhang Yubing 		printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name);
47445f1357a2SZhang Yubing 		if (clk_dev)
47455f1357a2SZhang Yubing 			*clk_dev = dev;
47465f1357a2SZhang Yubing 		return true;
47475f1357a2SZhang Yubing 	}
47485f1357a2SZhang Yubing 
47495f1357a2SZhang Yubing 	return false;
47505f1357a2SZhang Yubing }
47515f1357a2SZhang Yubing 
vop3_mcu_mode_setup(struct display_state * state)47520675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state)
47530675a2a4SDamon Ding {
47540675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
47550675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
47560675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
47570675a2a4SDamon Ding 
47580675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47590675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
47600675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47610675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
47620675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
47630675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false);
47640675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
47650675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false);
47660675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
47670675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false);
47680675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
47690675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false);
47700675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
47710675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false);
47720675a2a4SDamon Ding }
47730675a2a4SDamon Ding 
vop3_mcu_bypass_mode_setup(struct display_state * state)47740675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state)
47750675a2a4SDamon Ding {
47760675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
47770675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
47780675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
47790675a2a4SDamon Ding 
47800675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47810675a2a4SDamon Ding 			MCU_TYPE_SHIFT, 1, false);
47820675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47830675a2a4SDamon Ding 			MCU_HOLD_MODE_SHIFT, 1, false);
47840675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
47850675a2a4SDamon Ding 			MCU_PIX_TOTAL_SHIFT, 53, false);
47860675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
47870675a2a4SDamon Ding 			MCU_CS_PST_SHIFT, 6, false);
47880675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
47890675a2a4SDamon Ding 			MCU_CS_PEND_SHIFT, 48, false);
47900675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
47910675a2a4SDamon Ding 			MCU_RW_PST_SHIFT, 12, false);
47920675a2a4SDamon Ding 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
47930675a2a4SDamon Ding 			MCU_RW_PEND_SHIFT, 30, false);
47940675a2a4SDamon Ding }
47950675a2a4SDamon Ding 
rockchip_vop2_send_mcu_cmd(struct display_state * state,u32 type,u32 value)47960675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value)
47970675a2a4SDamon Ding {
47980675a2a4SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
47990675a2a4SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
48000675a2a4SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
48010675a2a4SDamon Ding 	struct vop2 *vop2 = cstate->private;
48020675a2a4SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
48030675a2a4SDamon Ding 
48040675a2a4SDamon Ding 	/*
480558cf1fa3SDamon Ding 	 * 1.set mcu bypass mode timing.
480658cf1fa3SDamon Ding 	 * 2.set dclk rate to 150M.
48070675a2a4SDamon Ding 	 */
48080675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && value) {
48090675a2a4SDamon Ding 		vop3_mcu_bypass_mode_setup(state);
48100675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, 150000000);
48110675a2a4SDamon Ding 	}
48120675a2a4SDamon Ding 
48130675a2a4SDamon Ding 	switch (type) {
48140675a2a4SDamon Ding 	case MCU_WRCMD:
48150675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48160675a2a4SDamon Ding 				MCU_RS_SHIFT, 0, false);
48170675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
48180675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
48190675a2a4SDamon Ding 				value, false);
48200675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48210675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
48220675a2a4SDamon Ding 		break;
48230675a2a4SDamon Ding 	case MCU_WRDATA:
48240675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48250675a2a4SDamon Ding 				MCU_RS_SHIFT, 1, false);
48260675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
48270675a2a4SDamon Ding 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
48280675a2a4SDamon Ding 				value, false);
48290675a2a4SDamon Ding 		break;
48300675a2a4SDamon Ding 	case MCU_SETBYPASS:
48310675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48320675a2a4SDamon Ding 				MCU_BYPASS_SHIFT, value ? 1 : 0, false);
48330675a2a4SDamon Ding 		break;
48340675a2a4SDamon Ding 	default:
48350675a2a4SDamon Ding 		break;
48360675a2a4SDamon Ding 	}
48370675a2a4SDamon Ding 
48380675a2a4SDamon Ding 	/*
483958cf1fa3SDamon Ding 	 * 1.restore mcu data mode timing.
484058cf1fa3SDamon Ding 	 * 2.restore dclk rate to crtc_clock.
48410675a2a4SDamon Ding 	 */
48420675a2a4SDamon Ding 	if (type == MCU_SETBYPASS && !value) {
48430675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
48440675a2a4SDamon Ding 		vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000);
48450675a2a4SDamon Ding 	}
48460675a2a4SDamon Ding 
48470675a2a4SDamon Ding 	return 0;
48480675a2a4SDamon Ding }
48490675a2a4SDamon Ding 
vop2_dither_setup(struct vop2 * vop2,int bus_format,int crtc_id)485034d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id)
485134d37ef0SDamon Ding {
4852a552a69cSDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
4853a552a69cSDamon Ding 	const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id];
485434d37ef0SDamon Ding 	u32 vp_offset = crtc_id * 0x100;
485534d37ef0SDamon Ding 	bool pre_dither_down_en = false;
485634d37ef0SDamon Ding 
485734d37ef0SDamon Ding 	switch (bus_format) {
485834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB565_1X16:
485940608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
4860e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4861e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4862e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4863e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false);
486434d37ef0SDamon Ding 		pre_dither_down_en = true;
486534d37ef0SDamon Ding 		break;
486634d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X18:
486734d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
486834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
486940608a7cSDamon Ding 	case MEDIA_BUS_FMT_RGB666_3X6:
4870e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4871e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, true, false);
4872e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4873e2bdb3b3SDamon Ding 				DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false);
487434d37ef0SDamon Ding 		pre_dither_down_en = true;
487534d37ef0SDamon Ding 		break;
487634d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
487734d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV8_1X24:
487834d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
4879e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4880e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
488134d37ef0SDamon Ding 		pre_dither_down_en = true;
488234d37ef0SDamon Ding 		break;
488334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUYV10_1X20:
488434d37ef0SDamon Ding 	case MEDIA_BUS_FMT_YUV10_1X30:
488534d37ef0SDamon Ding 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
488634d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB101010_1X30:
4887e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4888e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
488934d37ef0SDamon Ding 		pre_dither_down_en = false;
489034d37ef0SDamon Ding 		break;
489134d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_3X8:
489234d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
489334d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X24:
489434d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
489534d37ef0SDamon Ding 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
489634d37ef0SDamon Ding 	default:
4897e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4898e2bdb3b3SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, false, false);
489934d37ef0SDamon Ding 		pre_dither_down_en = true;
490034d37ef0SDamon Ding 		break;
490134d37ef0SDamon Ding 	}
490234d37ef0SDamon Ding 
4903e2bdb3b3SDamon Ding 	if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0)
490434d37ef0SDamon Ding 		pre_dither_down_en = false;
490534d37ef0SDamon Ding 
4906a552a69cSDamon Ding 	if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) {
4907481ef52dSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
4908481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000);
4909481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100);
4910481ef52dSDamon Ding 			vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100);
4911481ef52dSDamon Ding 		}
4912481ef52dSDamon Ding 
4913a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4914a552a69cSDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, 0, false);
4915e2bdb3b3SDamon Ding 		/* enable frc2.0 do 10->8 */
4916a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4917a552a69cSDamon Ding 				DITHER_DOWN_EN_SHIFT, 1, false);
4918e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4919e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false);
4920a552a69cSDamon Ding 	} else {
492134d37ef0SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
492234d37ef0SDamon Ding 				PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
4923e2bdb3b3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4924e2bdb3b3SDamon Ding 				DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false);
492534d37ef0SDamon Ding 	}
4926a552a69cSDamon Ding }
492734d37ef0SDamon Ding 
rockchip_vop2_init(struct display_state * state)4928ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state)
4929ecc31b6eSAndy Yan {
4930ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
4931c2b1fe35SDamon Ding 	struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
4932ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
4933ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
4934ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
4935ecc31b6eSAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
4936ecc31b6eSAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
4937ecc31b6eSAndy Yan 	u16 htotal = mode->crtc_htotal;
4938ecc31b6eSAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
4939ecc31b6eSAndy Yan 	u16 hact_end = hact_st + hdisplay;
4940ecc31b6eSAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
4941ecc31b6eSAndy Yan 	u16 vtotal = mode->crtc_vtotal;
4942ecc31b6eSAndy Yan 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
4943ecc31b6eSAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
4944ecc31b6eSAndy Yan 	u16 vact_end = vact_st + vdisplay;
4945ecc31b6eSAndy Yan 	bool yuv_overlay = false;
4946ecc31b6eSAndy Yan 	u32 vp_offset = (cstate->crtc_id * 0x100);
494766724b9cSDamon Ding 	u32 line_flag_offset = (cstate->crtc_id * 4);
494866724b9cSDamon Ding 	u32 val, act_end;
494958cf1fa3SDamon Ding 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4950edfef528SDamon Ding 	u8 dclk_div_factor = 0;
4951a552a69cSDamon Ding 	u8 vp_dclk_div = 1;
4952ecc31b6eSAndy Yan 	char output_type_name[30] = {0};
4953d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4954ecc31b6eSAndy Yan 	char dclk_name[9];
4955d8e7f4a5SSandy Huang #endif
4956b890760eSAlgea Cao 	struct clk hdmi0_phy_pll;
4957b890760eSAlgea Cao 	struct clk hdmi1_phy_pll;
49585f1357a2SZhang Yubing 	struct clk hdmi_phy_pll;
49593e05a7b8SZhang Yubing 	struct udevice *disp_dev;
49605fa6e665SDamon Ding 	unsigned long dclk_rate = 0;
4961ecc31b6eSAndy Yan 	int ret;
4962ecc31b6eSAndy Yan 
4963ecc31b6eSAndy Yan 	printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
496471ac76f7SDamon Ding 	       mode->crtc_hdisplay, mode->vdisplay,
4965ecc31b6eSAndy Yan 	       mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
49664d64cedbSDamon Ding 	       mode->vrefresh,
49672264c88bSDamon Ding 	       rockchip_get_output_if_name(conn_state->output_if, output_type_name),
4968ecc31b6eSAndy Yan 	       cstate->crtc_id);
4969ecc31b6eSAndy Yan 
4970ee01dbb2SDamon Ding 	if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
4971ee01dbb2SDamon Ding 		cstate->splice_mode = true;
4972ee01dbb2SDamon Ding 		cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id;
4973ee01dbb2SDamon Ding 		if (!cstate->splice_crtc_id) {
4974ee01dbb2SDamon Ding 			printf("%s: Splice mode is unsupported by vp%d\n",
4975ee01dbb2SDamon Ding 			       __func__, cstate->crtc_id);
4976ee01dbb2SDamon Ding 			return -EINVAL;
4977ee01dbb2SDamon Ding 		}
4978b70b2d79SDamon Ding 
4979b70b2d79SDamon Ding 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK,
4980b70b2d79SDamon Ding 				PORT_MERGE_EN_SHIFT, 1, false);
4981ee01dbb2SDamon Ding 	}
4982ee01dbb2SDamon Ding 
4983cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4984cd6c85a9SDamon Ding 			RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4985cd6c85a9SDamon Ding 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4986cd6c85a9SDamon Ding 			RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4987cd6c85a9SDamon Ding 
498844b1b62cSDamon Ding 	if (vop2->data->vp_data[cstate->crtc_id].urgency) {
498944b1b62cSDamon Ding 		u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl;
499044b1b62cSDamon Ding 		u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh;
499144b1b62cSDamon Ding 
499244b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK,
499344b1b62cSDamon Ding 				AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
499444b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK,
499544b1b62cSDamon Ding 				AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
499644b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK,
499744b1b62cSDamon Ding 				POST_URGENCY_EN_SHIFT, 1, false);
499844b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK,
499944b1b62cSDamon Ding 				POST_URGENCY_THL_SHIFT, urgen_thl, false);
500044b1b62cSDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK,
500144b1b62cSDamon Ding 				POST_URGENCY_THH_SHIFT, urgen_thh, false);
500244b1b62cSDamon Ding 	}
500344b1b62cSDamon Ding 
5004ecc31b6eSAndy Yan 	vop2_initial(vop2, state);
5005ecc31b6eSAndy Yan 	if (vop2->version == VOP_VERSION_RK3588)
5006ecc31b6eSAndy Yan 		dclk_rate = rk3588_vop2_if_cfg(state);
5007a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3576)
5008a552a69cSDamon Ding 		dclk_rate = rk3576_vop2_if_cfg(state);
50095fa6e665SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3568)
5010ecc31b6eSAndy Yan 		dclk_rate = rk3568_vop2_if_cfg(state);
5011452afb13SDamon Ding 	else if (vop2->version == VOP_VERSION_RK3562)
5012452afb13SDamon Ding 		dclk_rate = rk3562_vop2_if_cfg(state);
5013a552a69cSDamon Ding 	else if (vop2->version == VOP_VERSION_RK3528)
5014a552a69cSDamon Ding 		dclk_rate = rk3528_vop2_if_cfg(state);
5015ecc31b6eSAndy Yan 
50165d2768f7SDamon Ding 	if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
50175d2768f7SDamon Ding 	     !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
50185d2768f7SDamon Ding 	    conn_state->output_if & VOP_OUTPUT_IF_BT656)
50197bdd0eb6SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
50207bdd0eb6SSandy Huang 
5021bf7c1abfSDamon Ding 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
5022bf7c1abfSDamon Ding 		if (vop2->version == VOP_VERSION_RK3588 &&
5023bf7c1abfSDamon Ding 		    conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
5024bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420;
5025bf7c1abfSDamon Ding 	} else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) {
5026bf7c1abfSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 &&
5027bf7c1abfSDamon Ding 		    conn_state->type == DRM_MODE_CONNECTOR_eDP)
5028bf7c1abfSDamon Ding 			conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422;
5029bf7c1abfSDamon Ding 		else if (vop2->version == VOP_VERSION_RK3588 &&
5030bf7c1abfSDamon Ding 			 conn_state->type == DRM_MODE_CONNECTOR_eDP)
5031bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422;
5032bf7c1abfSDamon Ding 		else if (vop2->version == VOP_VERSION_RK3576 &&
5033bf7c1abfSDamon Ding 			 conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
5034bf7c1abfSDamon Ding 			conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422;
5035bf7c1abfSDamon Ding 		else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
5036bf7c1abfSDamon Ding 			conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422;
5037bf7c1abfSDamon Ding 	}
5038bf7c1abfSDamon Ding 
503965747de7SDamon Ding 	vop2_post_color_swap(state);
504010ee9f5bSAlgea Cao 
5041d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
5042d0408543SAndy Yan 			OUT_MODE_SHIFT, conn_state->output_mode, false);
5043d0408543SAndy Yan 
504434d37ef0SDamon Ding 	vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id);
504534d37ef0SDamon Ding 	if (cstate->splice_mode)
504634d37ef0SDamon Ding 		vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id);
5047d0408543SAndy Yan 
5048d0408543SAndy Yan 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
5049d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
5050d0408543SAndy Yan 			yuv_overlay, false);
5051d0408543SAndy Yan 
5052d0408543SAndy Yan 	cstate->yuv_overlay = yuv_overlay;
5053d0408543SAndy Yan 
5054d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
5055d0408543SAndy Yan 		    (htotal << 16) | hsync_len);
5056d0408543SAndy Yan 	val = hact_st << 16;
5057d0408543SAndy Yan 	val |= hact_end;
5058d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
5059d0408543SAndy Yan 	val = vact_st << 16;
5060d0408543SAndy Yan 	val |= vact_end;
5061d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
5062d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
5063d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
5064d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
5065d0408543SAndy Yan 
5066d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
5067d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
5068d0408543SAndy Yan 			    val);
5069d0408543SAndy Yan 
5070d0408543SAndy Yan 		val = vtotal << 16 | (vtotal + vsync_len);
5071d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
5072d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5073d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 1, false);
5074d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
50757a20be36SSandy Huang 				DSP_FILED_POL, 1, false);
50767a20be36SSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5077d0408543SAndy Yan 				P2I_EN_SHIFT, 1, false);
5078d0408543SAndy Yan 		vtotal += vtotal + 1;
507966724b9cSDamon Ding 		act_end = vact_end_f1;
5080d0408543SAndy Yan 	} else {
5081d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5082d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 0, false);
5083d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5084d0408543SAndy Yan 				P2I_EN_SHIFT, 0, false);
508566724b9cSDamon Ding 		act_end = vact_end;
5086d0408543SAndy Yan 	}
5087d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
5088d0408543SAndy Yan 		    (vtotal << 16) | vsync_len);
508967be2ffcSDamon Ding 
5090a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 ||
5091a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3562 ||
5092a552a69cSDamon Ding 	    vop2->version == VOP_VERSION_RK3568) {
509367be2ffcSDamon Ding 		if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
509467be2ffcSDamon Ding 		conn_state->output_if & VOP_OUTPUT_IF_BT656)
5095d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
509667be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 1, false);
509767be2ffcSDamon Ding 		else
509867be2ffcSDamon Ding 			vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
509967be2ffcSDamon Ding 					CORE_DCLK_DIV_EN_SHIFT, 0, false);
510010ee9f5bSAlgea Cao 
510110ee9f5bSAlgea Cao 		if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
510263cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
510363cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
510410ee9f5bSAlgea Cao 		else
510563cb669fSSandy Huang 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
510663cb669fSSandy Huang 					DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
5107a552a69cSDamon Ding 	}
510810ee9f5bSAlgea Cao 
5109ee01dbb2SDamon Ding 	vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
5110ee01dbb2SDamon Ding 			OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false);
5111ee01dbb2SDamon Ding 
511210ee9f5bSAlgea Cao 	if (yuv_overlay)
511310ee9f5bSAlgea Cao 		val = 0x20010200;
511410ee9f5bSAlgea Cao 	else
511510ee9f5bSAlgea Cao 		val = 0;
511610ee9f5bSAlgea Cao 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
5117b70b2d79SDamon Ding 	if (cstate->splice_mode) {
5118ee01dbb2SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
5119ee01dbb2SDamon Ding 				OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id,
5120ee01dbb2SDamon Ding 				yuv_overlay, false);
5121ee01dbb2SDamon Ding 		vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val);
5122ee01dbb2SDamon Ding 	}
512310ee9f5bSAlgea Cao 
512410ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
512510ee9f5bSAlgea Cao 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
5126d0408543SAndy Yan 
5127c2b1fe35SDamon Ding 	if (vp->xmirror_en)
5128c2b1fe35SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5129c2b1fe35SDamon Ding 				DSP_X_MIR_EN_SHIFT, 1, false);
5130c2b1fe35SDamon Ding 
5131ac500a1fSSandy Huang 	vop2_tv_config_update(state, vop2);
5132d0408543SAndy Yan 	vop2_post_config(state, vop2);
51336027c871SZhang Yubing 	if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
51346027c871SZhang Yubing 		vop3_post_config(state, vop2);
5135d0408543SAndy Yan 
513612ee5af0SDamon Ding 	if (cstate->dsc_enable) {
513712ee5af0SDamon Ding 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
51381ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL);
51391ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL);
514012ee5af0SDamon Ding 		} else {
51411ace1b6dSDamon Ding 			vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL);
514212ee5af0SDamon Ding 		}
514312ee5af0SDamon Ding 	}
514412ee5af0SDamon Ding 
5145d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
5146ecc31b6eSAndy Yan 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
51470675a2a4SDamon Ding 	ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk);
5148b890760eSAlgea Cao 	if (ret) {
5149b890760eSAlgea Cao 		printf("%s: Failed to get dclk ret=%d\n", __func__, ret);
5150b890760eSAlgea Cao 		return ret;
5151b890760eSAlgea Cao 	}
5152d8e7f4a5SSandy Huang #endif
5153b890760eSAlgea Cao 
51543e05a7b8SZhang Yubing 	ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev);
51553e05a7b8SZhang Yubing 	if (!ret) {
51563e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll);
51573e05a7b8SZhang Yubing 		if (ret)
51585e85f4a7SZhang Yubing 			debug("%s: hdmi0_phy_pll may not define\n", __func__);
51593e05a7b8SZhang Yubing 		ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll);
51603e05a7b8SZhang Yubing 		if (ret)
51615e85f4a7SZhang Yubing 			debug("%s: hdmi1_phy_pll may not define\n", __func__);
51623e05a7b8SZhang Yubing 	} else {
5163b890760eSAlgea Cao 		hdmi0_phy_pll.dev = NULL;
5164545a0218SAlgea Cao 		hdmi1_phy_pll.dev = NULL;
51655e85f4a7SZhang Yubing 		debug("%s: Faile to find display-subsystem node\n", __func__);
5166b890760eSAlgea Cao 	}
5167b890760eSAlgea Cao 
5168ebbd144cSAlgea Cao 	if (vop2->version == VOP_VERSION_RK3528) {
5169ebbd144cSAlgea Cao 		struct ofnode_phandle_args args;
5170ebbd144cSAlgea Cao 
5171ebbd144cSAlgea Cao 		ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents",
5172ebbd144cSAlgea Cao 						 "#clock-cells", 0, 0, &args);
5173ebbd144cSAlgea Cao 		if (!ret) {
5174ebbd144cSAlgea Cao 			ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev);
5175ebbd144cSAlgea Cao 			if (ret) {
5176ebbd144cSAlgea Cao 				debug("warn: can't get clk device\n");
5177ebbd144cSAlgea Cao 				return ret;
5178ebbd144cSAlgea Cao 			}
5179ebbd144cSAlgea Cao 		} else {
5180ebbd144cSAlgea Cao 			debug("assigned-clock-parents's node not define\n");
5181ebbd144cSAlgea Cao 		}
5182ebbd144cSAlgea Cao 	}
5183ebbd144cSAlgea Cao 
5184cce1f2abSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
5185cce1f2abSDamon Ding 		vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div;
5186cce1f2abSDamon Ding 
51870a1fb152SZhang Yubing 	if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) {
5188b890760eSAlgea Cao 		if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0)
51890675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll);
5190b890760eSAlgea Cao 		else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1)
51910675a2a4SDamon Ding 			vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll);
5192b890760eSAlgea Cao 
5193b890760eSAlgea Cao 		/*
5194b890760eSAlgea Cao 		 * uboot clk driver won't set dclk parent's rate when use
5195b890760eSAlgea Cao 		 * hdmi phypll as dclk source.
5196b890760eSAlgea Cao 		 * So set dclk rate is meaningless. Set hdmi phypll rate
5197b890760eSAlgea Cao 		 * directly.
5198b890760eSAlgea Cao 		 */
51995f1357a2SZhang Yubing 		if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) {
5200cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000);
52015f1357a2SZhang Yubing 		} else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) {
5202cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000);
52035f1357a2SZhang Yubing 		} else {
52047efea85dSDamon Ding 			if (is_extend_pll(state, &hdmi_phy_pll.dev)) {
5205cce1f2abSDamon Ding 				ret = vop2_clk_set_rate(&hdmi_phy_pll,
5206cce1f2abSDamon Ding 							dclk_rate / vp_dclk_div * 1000);
52077efea85dSDamon Ding 			} else {
5208d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
5209a552a69cSDamon Ding 				ret = vop2_clk_set_rate(&cstate->dclk,
5210a552a69cSDamon Ding 							dclk_rate / vp_dclk_div * 1000);
5211d8e7f4a5SSandy Huang #else
5212d8e7f4a5SSandy Huang 				if (vop2->version == VOP_VERSION_RK3528) {
5213d8e7f4a5SSandy Huang 					void *cru_base = (void *)RK3528_CRU_BASE;
5214d8e7f4a5SSandy Huang 
5215d8e7f4a5SSandy Huang 					/* dclk src switch to hdmiphy pll */
5216d8e7f4a5SSandy Huang 					writel((BIT(0) << 16) | BIT(0), cru_base + 0x450);
5217d8e7f4a5SSandy Huang 					rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000);
5218d8e7f4a5SSandy Huang 					ret = dclk_rate * 1000;
5219d8e7f4a5SSandy Huang 				}
5220d8e7f4a5SSandy Huang #endif
52215f1357a2SZhang Yubing 			}
52227efea85dSDamon Ding 		}
5223631ee99aSZhang Yubing 	} else {
52245f1357a2SZhang Yubing 		if (is_extend_pll(state, &hdmi_phy_pll.dev))
5225cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000);
52265f1357a2SZhang Yubing 		else
5227cce1f2abSDamon Ding 			ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000);
5228edfef528SDamon Ding 	}
522963638f32SDamon Ding 
523063638f32SDamon Ding 	if (IS_ERR_VALUE(ret)) {
523163638f32SDamon Ding 		printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
523263638f32SDamon Ding 		       __func__, cstate->crtc_id, dclk_rate, ret);
523363638f32SDamon Ding 		return ret;
523463638f32SDamon Ding 	} else {
52354d64cedbSDamon Ding 		if (cstate->mcu_timing.mcu_pix_total) {
52364d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) / 1000;
52374d64cedbSDamon Ding 		} else {
52389655ad2fSDamon Ding 			dclk_div_factor = mode->crtc_clock / dclk_rate;
52394d64cedbSDamon Ding 			mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000;
52404d64cedbSDamon Ding 		}
5241edfef528SDamon Ding 		printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock);
5242631ee99aSZhang Yubing 	}
5243ecc31b6eSAndy Yan 
524466724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
5245e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false);
524666724b9cSDamon Ding 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
5247e24e9033SSandy Huang 			RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false);
524866724b9cSDamon Ding 
524958cf1fa3SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total) {
525058cf1fa3SDamon Ding 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
525158cf1fa3SDamon Ding 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
525258cf1fa3SDamon Ding 				STANDBY_EN_SHIFT, 0, false);
52530675a2a4SDamon Ding 		vop3_mcu_mode_setup(state);
525458cf1fa3SDamon Ding 	}
52550675a2a4SDamon Ding 
5256d0408543SAndy Yan 	return 0;
5257d0408543SAndy Yan }
5258d0408543SAndy Yan 
vop2_setup_scale(struct vop2 * vop2,struct vop2_win_data * win,uint32_t src_w,uint32_t src_h,uint32_t dst_w,uint32_t dst_h)5259ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
52603e39a5a1SSandy Huang 			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
52613e39a5a1SSandy Huang 			     uint32_t dst_h)
52623e39a5a1SSandy Huang {
52633e39a5a1SSandy Huang 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
52643e39a5a1SSandy Huang 	uint16_t hscl_filter_mode, vscl_filter_mode;
52655fa6e665SDamon Ding 	uint8_t xgt2 = 0, xgt4 = 0;
52665fa6e665SDamon Ding 	uint8_t ygt2 = 0, ygt4 = 0;
52673e39a5a1SSandy Huang 	uint32_t xfac = 0, yfac = 0;
5268ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
52695fa6e665SDamon Ding 	bool xgt_en = false;
52705fa6e665SDamon Ding 	bool xavg_en = false;
52713e39a5a1SSandy Huang 
52725fa6e665SDamon Ding 	if (is_vop3(vop2)) {
5273a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) {
5274a552a69cSDamon Ding 			if (src_w >= (8 * dst_w)) {
5275a552a69cSDamon Ding 				xgt4 = 1;
5276a552a69cSDamon Ding 				src_w >>= 2;
5277a552a69cSDamon Ding 			} else if (src_w >= (4 * dst_w)) {
5278a552a69cSDamon Ding 				xgt2 = 1;
5279a552a69cSDamon Ding 				src_w >>= 1;
5280a552a69cSDamon Ding 			}
5281a552a69cSDamon Ding 		} else {
52825fa6e665SDamon Ding 			if (src_w >= (4 * dst_w)) {
52835fa6e665SDamon Ding 				xgt4 = 1;
52845fa6e665SDamon Ding 				src_w >>= 2;
52855fa6e665SDamon Ding 			} else if (src_w >= (2 * dst_w)) {
52865fa6e665SDamon Ding 				xgt2 = 1;
52875fa6e665SDamon Ding 				src_w >>= 1;
52885fa6e665SDamon Ding 			}
52895fa6e665SDamon Ding 		}
5290a552a69cSDamon Ding 	}
52913e39a5a1SSandy Huang 
5292183eb252SDamon Ding 	/**
5293183eb252SDamon Ding 	 * The rk3528 is processed as 2 pixel/cycle,
5294183eb252SDamon Ding 	 * so ygt2/ygt4 needs to be triggered in advance to improve performance
5295183eb252SDamon Ding 	 * when src_w is bigger than 1920.
5296183eb252SDamon Ding 	 * dst_h / src_h is at [1, 0.65)     ygt2=0; ygt4=0;
5297183eb252SDamon Ding 	 * dst_h / src_h is at [0.65, 0.35)  ygt2=1; ygt4=0;
5298183eb252SDamon Ding 	 * dst_h / src_h is at [0.35, 0)     ygt2=0; ygt4=1;
5299183eb252SDamon Ding 	 */
5300183eb252SDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
5301183eb252SDamon Ding 		if (src_h >= (100 * dst_h / 35)) {
5302183eb252SDamon Ding 			ygt4 = 1;
5303183eb252SDamon Ding 			src_h >>= 2;
5304183eb252SDamon Ding 		} else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) {
5305183eb252SDamon Ding 			ygt2 = 1;
5306183eb252SDamon Ding 			src_h >>= 1;
5307183eb252SDamon Ding 		}
5308183eb252SDamon Ding 	} else {
5309a552a69cSDamon Ding 		if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) {
5310a552a69cSDamon Ding 			if (src_h >= (8 * dst_h)) {
5311a552a69cSDamon Ding 				ygt4 = 1;
5312a552a69cSDamon Ding 				src_h >>= 2;
5313a552a69cSDamon Ding 			} else if (src_h >= (4 * dst_h)) {
5314a552a69cSDamon Ding 				ygt2 = 1;
5315a552a69cSDamon Ding 				src_h >>= 1;
5316a552a69cSDamon Ding 			}
5317a552a69cSDamon Ding 		} else {
53185fa6e665SDamon Ding 			if (src_h >= (4 * dst_h)) {
53195fa6e665SDamon Ding 				ygt4 = 1;
53203e39a5a1SSandy Huang 				src_h >>= 2;
53215fa6e665SDamon Ding 			} else if (src_h >= (2 * dst_h)) {
53225fa6e665SDamon Ding 				ygt2 = 1;
53233e39a5a1SSandy Huang 				src_h >>= 1;
53245fa6e665SDamon Ding 			}
5325183eb252SDamon Ding 		}
5326a552a69cSDamon Ding 	}
53273e39a5a1SSandy Huang 
53283e39a5a1SSandy Huang 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
53293e39a5a1SSandy Huang 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
53303e39a5a1SSandy Huang 
53313e39a5a1SSandy Huang 	if (yrgb_hor_scl_mode == SCALE_UP)
53325fa6e665SDamon Ding 		hscl_filter_mode = win->hsu_filter_mode;
53333e39a5a1SSandy Huang 	else
53345fa6e665SDamon Ding 		hscl_filter_mode = win->hsd_filter_mode;
53353e39a5a1SSandy Huang 
53363e39a5a1SSandy Huang 	if (yrgb_ver_scl_mode == SCALE_UP)
53375fa6e665SDamon Ding 		vscl_filter_mode = win->vsu_filter_mode;
53383e39a5a1SSandy Huang 	else
53395fa6e665SDamon Ding 		vscl_filter_mode = win->vsd_filter_mode;
53403e39a5a1SSandy Huang 
53413e39a5a1SSandy Huang 	/*
53423e39a5a1SSandy Huang 	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
53433e39a5a1SSandy Huang 	 * at scale down mode
53443e39a5a1SSandy Huang 	 */
53455fa6e665SDamon Ding 	if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) {
53463e39a5a1SSandy Huang 		printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
53473e39a5a1SSandy Huang 		dst_w += 1;
53483e39a5a1SSandy Huang 	}
53493e39a5a1SSandy Huang 
53505fa6e665SDamon Ding 	if (is_vop3(vop2)) {
53515fa6e665SDamon Ding 		xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true);
53525fa6e665SDamon Ding 		yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false);
53535fa6e665SDamon Ding 
53545fa6e665SDamon Ding 		if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG)
53555fa6e665SDamon Ding 			xavg_en = xgt2 || xgt4;
53565fa6e665SDamon Ding 		else
53575fa6e665SDamon Ding 			xgt_en = xgt2 || xgt4;
5358a552a69cSDamon Ding 
5359a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576) {
5360a552a69cSDamon Ding 			bool zme_dering_en = false;
5361a552a69cSDamon Ding 
5362a552a69cSDamon Ding 			if ((yrgb_hor_scl_mode == SCALE_UP &&
5363a552a69cSDamon Ding 			     hscl_filter_mode == VOP2_SCALE_UP_ZME) ||
5364a552a69cSDamon Ding 			    (yrgb_ver_scl_mode == SCALE_UP &&
5365a552a69cSDamon Ding 			     vscl_filter_mode == VOP2_SCALE_UP_ZME))
5366a552a69cSDamon Ding 				zme_dering_en = true;
5367a552a69cSDamon Ding 
5368a552a69cSDamon Ding 			/* Recommended configuration from the algorithm */
5369a552a69cSDamon Ding 			vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset,
5370a552a69cSDamon Ding 				    0x04100d10);
5371a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset,
5372a552a69cSDamon Ding 					EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false);
5373a552a69cSDamon Ding 		}
53745fa6e665SDamon Ding 	} else {
53753e39a5a1SSandy Huang 		xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
53763e39a5a1SSandy Huang 		yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
53775fa6e665SDamon Ding 	}
5378ecc31b6eSAndy Yan 
5379ecc31b6eSAndy Yan 	if (win->type == CLUSTER_LAYER) {
5380ecc31b6eSAndy Yan 		vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
5381ecc31b6eSAndy Yan 			    yfac << 16 | xfac);
5382ecc31b6eSAndy Yan 
53835fa6e665SDamon Ding 		if (is_vop3(vop2)) {
5384ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53855fa6e665SDamon Ding 					EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false);
5386ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53875fa6e665SDamon Ding 					EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false);
53885fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53895fa6e665SDamon Ding 					XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
5390ecc31b6eSAndy Yan 
5391ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53925fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT,
53935fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
5394ecc31b6eSAndy Yan 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53955fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT,
53965fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
53975fa6e665SDamon Ding 		} else {
53985fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53995fa6e665SDamon Ding 					YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT,
54005fa6e665SDamon Ding 					yrgb_hor_scl_mode, false);
54015fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54025fa6e665SDamon Ding 					YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT,
54035fa6e665SDamon Ding 					yrgb_ver_scl_mode, false);
54045fa6e665SDamon Ding 		}
5405ecc31b6eSAndy Yan 
54065fa6e665SDamon Ding 		if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
54075fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54085fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false);
54095fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54105fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false);
54115fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54125fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false);
54135fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54145fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false);
54155fa6e665SDamon Ding 		} else {
54165fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54175fa6e665SDamon Ding 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false);
54185fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54195fa6e665SDamon Ding 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false);
54205fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54215fa6e665SDamon Ding 					AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false);
54225fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54235fa6e665SDamon Ding 					AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false);
54245fa6e665SDamon Ding 		}
5425ecc31b6eSAndy Yan 	} else {
54263e39a5a1SSandy Huang 		vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
54273e39a5a1SSandy Huang 			    yfac << 16 | xfac);
54283e39a5a1SSandy Huang 
54295fa6e665SDamon Ding 		if (is_vop3(vop2)) {
543034a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54315fa6e665SDamon Ding 					EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false);
543234a72bf2SDing Ling Song 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54335fa6e665SDamon Ding 					EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false);
54345fa6e665SDamon Ding 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54355fa6e665SDamon Ding 					XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
54365fa6e665SDamon Ding 		}
54375fa6e665SDamon Ding 
54385fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54395fa6e665SDamon Ding 				YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false);
54405fa6e665SDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54415fa6e665SDamon Ding 				YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false);
54423e39a5a1SSandy Huang 
54433e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54443e39a5a1SSandy Huang 				YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
54453e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54463e39a5a1SSandy Huang 				YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
54473e39a5a1SSandy Huang 
54483e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54493e39a5a1SSandy Huang 				YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
54503e39a5a1SSandy Huang 				hscl_filter_mode, false);
54513e39a5a1SSandy Huang 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54523e39a5a1SSandy Huang 				YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
54533e39a5a1SSandy Huang 				vscl_filter_mode, false);
54543e39a5a1SSandy Huang 	}
5455ecc31b6eSAndy Yan }
54563e39a5a1SSandy Huang 
vop2_axi_config(struct vop2 * vop2,struct vop2_win_data * win)5457a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win)
5458a33b790fSDamon Ding {
5459a33b790fSDamon Ding 	u32 win_offset = win->reg_offset;
5460a33b790fSDamon Ding 
5461a33b790fSDamon Ding 	if (win->type == CLUSTER_LAYER) {
5462a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK,
5463a33b790fSDamon Ding 				CLUSTER_AXI_ID_SHIFT, win->axi_id, false);
5464a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK,
5465a33b790fSDamon Ding 				CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5466a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK,
5467a33b790fSDamon Ding 				CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5468a33b790fSDamon Ding 	} else {
5469a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK,
5470a33b790fSDamon Ding 				ESMART_AXI_ID_SHIFT, win->axi_id, false);
5471a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK,
5472a33b790fSDamon Ding 				ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5473a33b790fSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK,
5474a33b790fSDamon Ding 				ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5475a33b790fSDamon Ding 	}
5476a33b790fSDamon Ding }
5477a33b790fSDamon Ding 
vop2_win_dither_up(uint32_t format)5478840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format)
5479840bf541SDamon Ding {
5480840bf541SDamon Ding 	switch (format) {
5481840bf541SDamon Ding 	case ROCKCHIP_FMT_RGB565:
5482840bf541SDamon Ding 		return true;
5483840bf541SDamon Ding 	default:
5484840bf541SDamon Ding 		return false;
5485840bf541SDamon Ding 	}
5486840bf541SDamon Ding }
5487840bf541SDamon Ding 
vop2_is_mirror_win(struct vop2_win_data * win)54881c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win)
54891c9572c7SDamon Ding {
54901c9572c7SDamon Ding 	return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR);
54911c9572c7SDamon Ding }
54921c9572c7SDamon Ding 
vop2_set_cluster_win(struct display_state * state,struct vop2_win_data * win)54931c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
5494d0408543SAndy Yan {
5495d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5496d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
5497d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
5498d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
54999c7848c3SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
55009c7848c3SDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
5501ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
5502ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
5503ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
5504ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
5505ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
5506ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
5507d0408543SAndy Yan 	int xvir = cstate->xvir;
5508d0408543SAndy Yan 	int y_mirror = 0;
550910ee9f5bSAlgea Cao 	int csc_mode;
5510ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5511ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
5512ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
5513ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
5514ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
5515840bf541SDamon Ding 	bool dither_up;
5516d0408543SAndy Yan 
5517ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
5518ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
5519ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
5520ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
5521ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
5522ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
5523ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
5524ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5525ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5526ee01dbb2SDamon Ding 	}
5527ee01dbb2SDamon Ding 
5528ecc31b6eSAndy Yan 	act_info = (src_h - 1) << 16;
5529ecc31b6eSAndy Yan 	act_info |= (src_w - 1) & 0xffff;
5530ecc31b6eSAndy Yan 
5531ecc31b6eSAndy Yan 	dsp_info = (crtc_h - 1) << 16;
5532ecc31b6eSAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
5533ecc31b6eSAndy Yan 
5534ecc31b6eSAndy Yan 	dsp_stx = crtc_x;
5535ecc31b6eSAndy Yan 	dsp_sty = crtc_y;
5536ecc31b6eSAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5537ecc31b6eSAndy Yan 
5538ecc31b6eSAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5539ecc31b6eSAndy Yan 		y_mirror = 1;
5540ecc31b6eSAndy Yan 	else
5541ecc31b6eSAndy Yan 		y_mirror = 0;
5542ecc31b6eSAndy Yan 
5543ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
5544ecc31b6eSAndy Yan 
5545a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
5546a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
5547a33b790fSDamon Ding 
5548ecc31b6eSAndy Yan 	if (y_mirror)
5549ecc31b6eSAndy Yan 		printf("WARN: y mirror is unsupported by cluster window\n");
5550ecc31b6eSAndy Yan 
55519c7848c3SDamon Ding 	if (is_vop3(vop2)) {
5552a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset,
55534751aa64SDamon Ding 				CLUSTER_PORT_SEL_MASK, CLUSTER_PORT_SEL_SHIFT,
5554a552a69cSDamon Ding 				cstate->crtc_id, false);
5555b888dbc8SSandy Huang 		vop2_ops->setup_win_dly(state, cstate->crtc_id, win->phys_id);
55569c7848c3SDamon Ding 	}
5557a552a69cSDamon Ding 
5558e84ccd9bSDamon Ding 	/*
5559e84ccd9bSDamon Ding 	 * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode.
5560e84ccd9bSDamon Ding 	 */
5561e84ccd9bSDamon Ding 	if (vop2->version >= VOP_VERSION_RK3588)
5562a59754e1SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset,
5563a59754e1SDamon Ding 				EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false);
5564a59754e1SDamon Ding 
5565ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
5566ecc31b6eSAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5567ecc31b6eSAndy Yan 			false);
55681615d939SSandy Huang 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
55691615d939SSandy Huang 			0x1, CLUSTER_RB_SWAP_SHIFT, cstate->rb_swap, false);
5570ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
5571ee01dbb2SDamon Ding 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset,
5572ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
5573ecc31b6eSAndy Yan 
5574ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
5575ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
5576ecc31b6eSAndy Yan 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
5577ecc31b6eSAndy Yan 
5578df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5579df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
5580ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5581ecc31b6eSAndy Yan 			CLUSTER_RGB2YUV_EN_SHIFT,
5582ecc31b6eSAndy Yan 			is_yuv_output(conn_state->bus_format), false);
5583ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
5584ecc31b6eSAndy Yan 			CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
5585840bf541SDamon Ding 
5586840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5587840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5588840bf541SDamon Ding 			CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false);
5589840bf541SDamon Ding 
5590dd579ec5SSandy Huang 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
5591ecc31b6eSAndy Yan 	vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
5592ecc31b6eSAndy Yan 
55931c9572c7SDamon Ding 	return 0;
5594d0408543SAndy Yan }
5595d0408543SAndy Yan 
vop2_set_smart_win(struct display_state * state,struct vop2_win_data * win)55961c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
5597ecc31b6eSAndy Yan {
5598ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5599ecc31b6eSAndy Yan 	struct connector_state *conn_state = &state->conn_state;
5600ecc31b6eSAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
5601ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
56029c7848c3SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
56039c7848c3SDamon Ding 	const struct vop2_ops *vop2_ops = vop2_data->ops;
5604ee01dbb2SDamon Ding 	int src_w = cstate->src_rect.w;
5605ee01dbb2SDamon Ding 	int src_h = cstate->src_rect.h;
5606ee01dbb2SDamon Ding 	int crtc_x = cstate->crtc_rect.x;
5607ee01dbb2SDamon Ding 	int crtc_y = cstate->crtc_rect.y;
5608ee01dbb2SDamon Ding 	int crtc_w = cstate->crtc_rect.w;
5609ee01dbb2SDamon Ding 	int crtc_h = cstate->crtc_rect.h;
5610ecc31b6eSAndy Yan 	int xvir = cstate->xvir;
5611ecc31b6eSAndy Yan 	int y_mirror = 0;
5612ecc31b6eSAndy Yan 	int csc_mode;
5613ecc31b6eSAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5614ee01dbb2SDamon Ding 	/* offset of the right window in splice mode */
5615ee01dbb2SDamon Ding 	u32 splice_pixel_offset = 0;
5616ee01dbb2SDamon Ding 	u32 splice_yrgb_offset = 0;
5617ecc31b6eSAndy Yan 	u32 win_offset = win->reg_offset;
56181c9572c7SDamon Ding 	u32 val;
5619840bf541SDamon Ding 	bool dither_up;
5620ecc31b6eSAndy Yan 
56211c9572c7SDamon Ding 	if (vop2_is_mirror_win(win)) {
56221c9572c7SDamon Ding 		struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id);
56231c9572c7SDamon Ding 
56241c9572c7SDamon Ding 		if (!source_win) {
56251c9572c7SDamon Ding 			printf("invalid source win id %d\n", win->source_win_id);
56261c9572c7SDamon Ding 			return -ENODEV;
56271c9572c7SDamon Ding 		}
56281c9572c7SDamon Ding 
56291c9572c7SDamon Ding 		val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset);
56301c9572c7SDamon Ding 		if (!(val & BIT(WIN_EN_SHIFT))) {
56311c9572c7SDamon Ding 			printf("WARN: the source win should be enabled before mirror win\n");
56321c9572c7SDamon Ding 			return -EAGAIN;
56331c9572c7SDamon Ding 		}
56341c9572c7SDamon Ding 	}
56351c9572c7SDamon Ding 
5636ee01dbb2SDamon Ding 	if (win->splice_mode_right) {
5637ee01dbb2SDamon Ding 		src_w = cstate->right_src_rect.w;
5638ee01dbb2SDamon Ding 		src_h = cstate->right_src_rect.h;
5639ee01dbb2SDamon Ding 		crtc_x = cstate->right_crtc_rect.x;
5640ee01dbb2SDamon Ding 		crtc_y = cstate->right_crtc_rect.y;
5641ee01dbb2SDamon Ding 		crtc_w = cstate->right_crtc_rect.w;
5642ee01dbb2SDamon Ding 		crtc_h = cstate->right_crtc_rect.h;
5643ee01dbb2SDamon Ding 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5644ee01dbb2SDamon Ding 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5645ee01dbb2SDamon Ding 	}
5646ee01dbb2SDamon Ding 
564774bd8269SSandy Huang 	/*
564874bd8269SSandy Huang 	 * This is workaround solution for IC design:
564974bd8269SSandy Huang 	 * esmart can't support scale down when actual_w % 16 == 1.
565074bd8269SSandy Huang 	 */
565174bd8269SSandy Huang 	if (src_w > crtc_w && (src_w & 0xf) == 1) {
565274bd8269SSandy Huang 		printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
565374bd8269SSandy Huang 		src_w -= 1;
565474bd8269SSandy Huang 	}
565574bd8269SSandy Huang 
5656d0408543SAndy Yan 	act_info = (src_h - 1) << 16;
5657d0408543SAndy Yan 	act_info |= (src_w - 1) & 0xffff;
5658d0408543SAndy Yan 
5659d0408543SAndy Yan 	dsp_info = (crtc_h - 1) << 16;
5660d0408543SAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
5661d0408543SAndy Yan 
5662d0408543SAndy Yan 	dsp_stx = crtc_x;
5663d0408543SAndy Yan 	dsp_sty = crtc_y;
5664d0408543SAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5665d0408543SAndy Yan 
5666d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5667d0408543SAndy Yan 		y_mirror = 1;
5668d0408543SAndy Yan 	else
5669d0408543SAndy Yan 		y_mirror = 0;
5670d0408543SAndy Yan 
5671a552a69cSDamon Ding 	if (is_vop3(vop2)) {
5672a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset,
5673a552a69cSDamon Ding 				ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT,
5674a552a69cSDamon Ding 				win->scale_engine_num, false);
5675a552a69cSDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5676a552a69cSDamon Ding 				ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5677a552a69cSDamon Ding 				cstate->crtc_id, false);
5678b888dbc8SSandy Huang 		vop2_ops->setup_win_dly(state, cstate->crtc_id, win->phys_id);
5679a552a69cSDamon Ding 
5680a552a69cSDamon Ding 		/* Merge esmart1/3 from vp1 post to vp0 */
5681a552a69cSDamon Ding 		if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 &&
5682a552a69cSDamon Ding 		    (win->phys_id == ROCKCHIP_VOP2_ESMART1 ||
5683a552a69cSDamon Ding 		     win->phys_id == ROCKCHIP_VOP2_ESMART3))
5684a552a69cSDamon Ding 			vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5685a552a69cSDamon Ding 					ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5686a552a69cSDamon Ding 					1, false);
5687a552a69cSDamon Ding 	}
56885fa6e665SDamon Ding 
5689ecc31b6eSAndy Yan 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
56903e39a5a1SSandy Huang 
5691a552a69cSDamon Ding 	if (vop2->version != VOP_VERSION_RK3568)
5692a33b790fSDamon Ding 		vop2_axi_config(vop2, win);
5693a33b790fSDamon Ding 
5694d0408543SAndy Yan 	if (y_mirror)
5695d0408543SAndy Yan 		cstate->dma_addr += (src_h - 1) * xvir * 4;
5696d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
5697d0408543SAndy Yan 			YMIRROR_EN_SHIFT, y_mirror, false);
5698d0408543SAndy Yan 
5699d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5700d0408543SAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5701d0408543SAndy Yan 			false);
5702a552a69cSDamon Ding 
57031615d939SSandy Huang 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
57041615d939SSandy Huang 			0x1, REGION0_RB_SWAP_SHIFT, cstate->rb_swap, false);
57051615d939SSandy Huang 
5706a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3576)
5707a552a69cSDamon Ding 		vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00);
5708a552a69cSDamon Ding 
5709d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
5710d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
5711ee01dbb2SDamon Ding 		    cstate->dma_addr + splice_yrgb_offset);
5712d0408543SAndy Yan 
5713d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
5714d0408543SAndy Yan 		    act_info);
5715d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
5716d0408543SAndy Yan 		    dsp_info);
5717d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
5718d0408543SAndy Yan 
5719df0a5c43SDamon Ding 	csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5720df0a5c43SDamon Ding 					 CSC_10BIT_DEPTH);
572110ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
572210ee9f5bSAlgea Cao 			RGB2YUV_EN_SHIFT,
572310ee9f5bSAlgea Cao 			is_yuv_output(conn_state->bus_format), false);
572410ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
572510ee9f5bSAlgea Cao 			CSC_MODE_SHIFT, csc_mode, false);
572610ee9f5bSAlgea Cao 
5727840bf541SDamon Ding 	dither_up = vop2_win_dither_up(cstate->format);
5728840bf541SDamon Ding 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5729840bf541SDamon Ding 			REGION0_DITHER_UP_EN_SHIFT, dither_up, false);
5730840bf541SDamon Ding 
5731dd579ec5SSandy Huang 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5732dd579ec5SSandy Huang 			WIN_EN_SHIFT, 1, false);
57331c9572c7SDamon Ding 
57341c9572c7SDamon Ding 	return 0;
5735ecc31b6eSAndy Yan }
5736ecc31b6eSAndy Yan 
vop2_calc_display_rect_for_splice(struct display_state * state)5737ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state)
5738ee01dbb2SDamon Ding {
5739ee01dbb2SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
5740ee01dbb2SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
5741ee01dbb2SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
5742ee01dbb2SDamon Ding 	struct display_rect *src_rect = &cstate->src_rect;
5743ee01dbb2SDamon Ding 	struct display_rect *dst_rect = &cstate->crtc_rect;
5744ee01dbb2SDamon Ding 	struct display_rect left_src, left_dst, right_src, right_dst;
5745ee01dbb2SDamon Ding 	u16 half_hdisplay = mode->crtc_hdisplay >> 1;
5746ee01dbb2SDamon Ding 	int left_src_w, left_dst_w, right_dst_w;
5747ee01dbb2SDamon Ding 
5748ee01dbb2SDamon Ding 	left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x;
5749ee01dbb2SDamon Ding 	if (left_dst_w < 0)
5750ee01dbb2SDamon Ding 		left_dst_w = 0;
5751ee01dbb2SDamon Ding 	right_dst_w = dst_rect->w - left_dst_w;
5752ee01dbb2SDamon Ding 
5753ee01dbb2SDamon Ding 	if (!right_dst_w)
5754ee01dbb2SDamon Ding 		left_src_w = src_rect->w;
5755ee01dbb2SDamon Ding 	else
57560df0fd39SSandy Huang 		left_src_w = src_rect->x + src_rect->w - src_rect->w / 2;
5757ee01dbb2SDamon Ding 
5758ee01dbb2SDamon Ding 	left_src.x = src_rect->x;
5759ee01dbb2SDamon Ding 	left_src.w = left_src_w;
5760ee01dbb2SDamon Ding 	left_dst.x = dst_rect->x;
5761ee01dbb2SDamon Ding 	left_dst.w = left_dst_w;
5762ee01dbb2SDamon Ding 	right_src.x = left_src.x + left_src.w;
5763ee01dbb2SDamon Ding 	right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w;
5764ee01dbb2SDamon Ding 	right_dst.x = dst_rect->x + left_dst_w - half_hdisplay;
5765ee01dbb2SDamon Ding 	right_dst.w = right_dst_w;
5766ee01dbb2SDamon Ding 
5767ee01dbb2SDamon Ding 	left_src.y = src_rect->y;
5768ee01dbb2SDamon Ding 	left_src.h = src_rect->h;
5769ee01dbb2SDamon Ding 	left_dst.y = dst_rect->y;
5770ee01dbb2SDamon Ding 	left_dst.h = dst_rect->h;
5771ee01dbb2SDamon Ding 	right_src.y = src_rect->y;
5772ee01dbb2SDamon Ding 	right_src.h = src_rect->h;
5773ee01dbb2SDamon Ding 	right_dst.y = dst_rect->y;
5774ee01dbb2SDamon Ding 	right_dst.h = dst_rect->h;
5775ee01dbb2SDamon Ding 
5776ee01dbb2SDamon Ding 	memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect));
5777ee01dbb2SDamon Ding 	memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect));
5778ee01dbb2SDamon Ding 	memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect));
5779ee01dbb2SDamon Ding 	memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect));
5780ee01dbb2SDamon Ding }
5781ee01dbb2SDamon Ding 
rockchip_vop2_set_plane(struct display_state * state)5782ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state)
5783ecc31b6eSAndy Yan {
5784ecc31b6eSAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5785ecc31b6eSAndy Yan 	struct vop2 *vop2 = cstate->private;
5786ecc31b6eSAndy Yan 	struct vop2_win_data *win_data;
5787ee01dbb2SDamon Ding 	struct vop2_win_data *splice_win_data;
5788ecc31b6eSAndy Yan 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
57891c9572c7SDamon Ding 	int ret;
5790ecc31b6eSAndy Yan 
5791ee01dbb2SDamon Ding 	if (cstate->crtc_rect.w > cstate->max_output.width) {
5792ecc31b6eSAndy Yan 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
5793ee01dbb2SDamon Ding 		       cstate->crtc_rect.w, cstate->max_output.width);
5794ecc31b6eSAndy Yan 		return -EINVAL;
5795ecc31b6eSAndy Yan 	}
5796ecc31b6eSAndy Yan 
5797ecc31b6eSAndy Yan 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
5798ecc31b6eSAndy Yan 	if (!win_data) {
5799ecc31b6eSAndy Yan 		printf("invalid win id %d\n", primary_plane_id);
5800ecc31b6eSAndy Yan 		return -ENODEV;
5801ecc31b6eSAndy Yan 	}
5802ecc31b6eSAndy Yan 
58035fa6e665SDamon Ding 	/* ignore some plane register according vop3 esmart lb mode */
58045fa6e665SDamon Ding 	if (vop3_ignore_plane(vop2, win_data))
58055fa6e665SDamon Ding 		return -EACCES;
58065fa6e665SDamon Ding 
5807a552a69cSDamon Ding 	if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) {
5808b6ba80b4SDamon Ding 		if (vop2_power_domain_on(vop2, win_data->pd_id))
5809b6ba80b4SDamon Ding 			printf("open vp%d plane pd fail\n", cstate->crtc_id);
5810b6ba80b4SDamon Ding 	}
5811b6ba80b4SDamon Ding 
5812ee01dbb2SDamon Ding 	if (cstate->splice_mode) {
5813ee01dbb2SDamon Ding 		if (win_data->splice_win_id) {
5814ee01dbb2SDamon Ding 			splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id);
5815ee01dbb2SDamon Ding 			splice_win_data->splice_mode_right = true;
5816b6ba80b4SDamon Ding 
5817b6ba80b4SDamon Ding 			if (vop2_power_domain_on(vop2, splice_win_data->pd_id))
5818b6ba80b4SDamon Ding 				printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id);
5819b6ba80b4SDamon Ding 
5820ee01dbb2SDamon Ding 			vop2_calc_display_rect_for_splice(state);
5821ee01dbb2SDamon Ding 			if (win_data->type == CLUSTER_LAYER)
5822ee01dbb2SDamon Ding 				vop2_set_cluster_win(state, splice_win_data);
5823ee01dbb2SDamon Ding 			else
5824ee01dbb2SDamon Ding 				vop2_set_smart_win(state, splice_win_data);
5825ee01dbb2SDamon Ding 		} else {
5826ee01dbb2SDamon Ding 			printf("ERROR: splice mode is unsupported by plane %s\n",
5827a7cb29b7SDamon Ding 			       vop2_plane_phys_id_to_string(primary_plane_id));
5828ee01dbb2SDamon Ding 			return -EINVAL;
5829ee01dbb2SDamon Ding 		}
5830ee01dbb2SDamon Ding 	}
5831ee01dbb2SDamon Ding 
5832ecc31b6eSAndy Yan 	if (win_data->type == CLUSTER_LAYER)
58331c9572c7SDamon Ding 		ret = vop2_set_cluster_win(state, win_data);
5834ecc31b6eSAndy Yan 	else
58351c9572c7SDamon Ding 		ret = vop2_set_smart_win(state, win_data);
58361c9572c7SDamon Ding 	if (ret)
58371c9572c7SDamon Ding 		return ret;
58388895aec1SSandy Huang 
58398895aec1SSandy Huang 	printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
5840a7cb29b7SDamon Ding 		cstate->crtc_id, vop2_plane_phys_id_to_string(primary_plane_id),
5841ee01dbb2SDamon Ding 		cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h,
5842ee01dbb2SDamon Ding 		cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format,
58438895aec1SSandy Huang 		cstate->dma_addr);
58448895aec1SSandy Huang 
5845d0408543SAndy Yan 	return 0;
5846d0408543SAndy Yan }
5847d0408543SAndy Yan 
rockchip_vop2_prepare(struct display_state * state)5848d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state)
5849d0408543SAndy Yan {
5850d0408543SAndy Yan 	return 0;
5851d0408543SAndy Yan }
5852d0408543SAndy Yan 
vop2_dsc_cfg_done(struct display_state * state)585312ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state)
585412ee5af0SDamon Ding {
585512ee5af0SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
585612ee5af0SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
585712ee5af0SDamon Ding 	struct vop2 *vop2 = cstate->private;
585812ee5af0SDamon Ding 	u8 dsc_id = cstate->dsc_id;
585912ee5af0SDamon Ding 	u32 ctrl_regs_offset = (dsc_id * 0x30);
586012ee5af0SDamon Ding 
586112ee5af0SDamon Ding 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
586212ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK,
586312ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
586412ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK,
586512ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
586612ee5af0SDamon Ding 	} else {
586712ee5af0SDamon Ding 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK,
586812ee5af0SDamon Ding 				DSC_CFG_DONE_SHIFT, 1, false);
586912ee5af0SDamon Ding 	}
587012ee5af0SDamon Ding }
587112ee5af0SDamon Ding 
rockchip_vop2_enable(struct display_state * state)5872d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state)
5873d0408543SAndy Yan {
5874d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5875d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
587652ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5877ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5878d0408543SAndy Yan 
5879d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5880d0408543SAndy Yan 			STANDBY_EN_SHIFT, 0, false);
5881ee01dbb2SDamon Ding 
5882ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5883ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5884ee01dbb2SDamon Ding 
5885d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5886d0408543SAndy Yan 
588712ee5af0SDamon Ding 	if (cstate->dsc_enable)
588812ee5af0SDamon Ding 		vop2_dsc_cfg_done(state);
588912ee5af0SDamon Ding 
58900675a2a4SDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
58910675a2a4SDamon Ding 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
58920675a2a4SDamon Ding 				MCU_HOLD_MODE_SHIFT, 0, false);
58930675a2a4SDamon Ding 
5894d0408543SAndy Yan 	return 0;
5895d0408543SAndy Yan }
5896d0408543SAndy Yan 
rk3588_vop2_post_enable(struct display_state * state)5897efa01fe4SZhang Yubing static int rk3588_vop2_post_enable(struct display_state *state)
5898efa01fe4SZhang Yubing {
5899efa01fe4SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
5900efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5901efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5902efa01fe4SZhang Yubing 	int output_if = conn_state->output_if;
5903efa01fe4SZhang Yubing 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5904efa01fe4SZhang Yubing 	int ret, val;
5905efa01fe4SZhang Yubing 
5906efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP0)
5907efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
5908efa01fe4SZhang Yubing 				1, false);
5909efa01fe4SZhang Yubing 
5910efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP1)
5911efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT,
5912efa01fe4SZhang Yubing 				1, false);
5913efa01fe4SZhang Yubing 
5914efa01fe4SZhang Yubing 	if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) {
5915efa01fe4SZhang Yubing 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5916efa01fe4SZhang Yubing 		ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5917efa01fe4SZhang Yubing 					 val & BIT(cstate->crtc_id), 50 * 1000);
5918efa01fe4SZhang Yubing 		if (ret)
5919efa01fe4SZhang Yubing 			printf("%s wait cfg done timeout\n", __func__);
59200686a6a6SZhang Yubing 
59210686a6a6SZhang Yubing 		if (cstate->dclk_rst.dev) {
59220686a6a6SZhang Yubing 			reset_assert(&cstate->dclk_rst);
59230686a6a6SZhang Yubing 			udelay(20);
59240686a6a6SZhang Yubing 			reset_deassert(&cstate->dclk_rst);
59250686a6a6SZhang Yubing 		}
5926efa01fe4SZhang Yubing 	}
5927efa01fe4SZhang Yubing 
5928efa01fe4SZhang Yubing 	return 0;
5929efa01fe4SZhang Yubing }
5930efa01fe4SZhang Yubing 
rk3576_vop2_post_enable(struct display_state * state)5931efa01fe4SZhang Yubing static int rk3576_vop2_post_enable(struct display_state *state)
5932efa01fe4SZhang Yubing {
5933efa01fe4SZhang Yubing 	struct connector_state *conn_state = &state->conn_state;
5934efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5935efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5936efa01fe4SZhang Yubing 	int output_if = conn_state->output_if;
5937efa01fe4SZhang Yubing 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5938efa01fe4SZhang Yubing 	int ret, val;
5939efa01fe4SZhang Yubing 
5940efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP0)
5941efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
5942efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5943efa01fe4SZhang Yubing 
5944efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP1)
5945efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
5946efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5947efa01fe4SZhang Yubing 
5948efa01fe4SZhang Yubing 	if (output_if & VOP_OUTPUT_IF_DP2)
5949efa01fe4SZhang Yubing 		vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
5950efa01fe4SZhang Yubing 				RK3576_IF_OUT_EN_SHIFT, 1, false);
5951efa01fe4SZhang Yubing 
5952efa01fe4SZhang Yubing 	if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
5953efa01fe4SZhang Yubing 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5954efa01fe4SZhang Yubing 		ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5955efa01fe4SZhang Yubing 					 val & BIT(cstate->crtc_id), 50 * 1000);
5956efa01fe4SZhang Yubing 		if (ret)
5957efa01fe4SZhang Yubing 			printf("%s wait cfg done timeout\n", __func__);
59580686a6a6SZhang Yubing 
59590686a6a6SZhang Yubing 		if (cstate->dclk_rst.dev) {
59600686a6a6SZhang Yubing 			reset_assert(&cstate->dclk_rst);
59610686a6a6SZhang Yubing 			udelay(20);
59620686a6a6SZhang Yubing 			reset_deassert(&cstate->dclk_rst);
59630686a6a6SZhang Yubing 		}
5964efa01fe4SZhang Yubing 	}
5965efa01fe4SZhang Yubing 
5966efa01fe4SZhang Yubing 	return 0;
5967efa01fe4SZhang Yubing }
5968efa01fe4SZhang Yubing 
rockchip_vop2_post_enable(struct display_state * state)5969efa01fe4SZhang Yubing static int rockchip_vop2_post_enable(struct display_state *state)
5970efa01fe4SZhang Yubing {
5971efa01fe4SZhang Yubing 	struct crtc_state *cstate = &state->crtc_state;
5972efa01fe4SZhang Yubing 	struct vop2 *vop2 = cstate->private;
5973efa01fe4SZhang Yubing 
5974efa01fe4SZhang Yubing 	if (vop2->version == VOP_VERSION_RK3588)
5975efa01fe4SZhang Yubing 		rk3588_vop2_post_enable(state);
5976efa01fe4SZhang Yubing 	else if (vop2->version == VOP_VERSION_RK3576)
5977efa01fe4SZhang Yubing 		rk3576_vop2_post_enable(state);
5978efa01fe4SZhang Yubing 
5979efa01fe4SZhang Yubing 	return 0;
5980efa01fe4SZhang Yubing }
5981efa01fe4SZhang Yubing 
rockchip_vop2_disable(struct display_state * state)5982d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state)
5983d0408543SAndy Yan {
5984d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
5985d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
598652ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
5987ecc31b6eSAndy Yan 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5988d0408543SAndy Yan 
5989d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5990d0408543SAndy Yan 			STANDBY_EN_SHIFT, 1, false);
5991ee01dbb2SDamon Ding 
5992ee01dbb2SDamon Ding 	if (cstate->splice_mode)
5993ee01dbb2SDamon Ding 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5994ee01dbb2SDamon Ding 
5995d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5996d0408543SAndy Yan 
5997d0408543SAndy Yan 	return 0;
5998d0408543SAndy Yan }
5999d0408543SAndy Yan 
rockchip_vop2_fixup_dts(struct display_state * state,void * blob)6000b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
6001b0989546SSandy Huang {
6002b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
6003b0989546SSandy Huang 	struct vop2 *vop2 = cstate->private;
6004b0989546SSandy Huang 	ofnode vp_node;
6005b0989546SSandy Huang 	struct device_node *port_parent_node = cstate->ports_node;
6006b0989546SSandy Huang 	static bool vop_fix_dts;
6007b0989546SSandy Huang 	const char *path;
6008b0989546SSandy Huang 	u32 plane_mask = 0;
6009b0989546SSandy Huang 	int vp_id = 0;
6010b0989546SSandy Huang 
60116fea745cSDamon Ding 	/*
60126fea745cSDamon Ding 	 * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in
60136fea745cSDamon Ding 	 * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched
60146fea745cSDamon Ding 	 * between different CRTCs flexibly and the userspace do not need
60156fea745cSDamon Ding 	 * the plane_mask to restrict the binding between the crtc and plane.
60166fea745cSDamon Ding 	 * We just find a expected plane for logo display.
60176fea745cSDamon Ding 	 */
60186fea745cSDamon Ding 	if (vop_fix_dts || is_vop3(vop2))
6019b0989546SSandy Huang 		return 0;
6020b0989546SSandy Huang 
6021b0989546SSandy Huang 	ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
6022b0989546SSandy Huang 		path = vp_node.np->full_name;
6023b0989546SSandy Huang 		plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
6024b0989546SSandy Huang 
60258b1fe597SSandy Huang 		if (cstate->crtc->assign_plane)
60268b1fe597SSandy Huang 			continue;
6027b4fa21deSDamon Ding 
6028ee008497SSandy Huang 		printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
6029b0989546SSandy Huang 		       vp_id, plane_mask,
6030ee008497SSandy Huang 		       vop2->vp_plane_mask[vp_id].primary_plane_id,
6031b4fa21deSDamon Ding 		       vop2->vp_plane_mask[vp_id].cursor_plane_id);
6032b0989546SSandy Huang 
6033b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
6034b0989546SSandy Huang 				     plane_mask, 1);
6035b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
6036b0989546SSandy Huang 				     vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
6037b4fa21deSDamon Ding 		if (vop2->vp_plane_mask[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID)
6038ee008497SSandy Huang 			do_fixup_by_path_u32(blob, path, "cursor-win-id",
6039b4fa21deSDamon Ding 					     vop2->vp_plane_mask[vp_id].cursor_plane_id, 1);
6040b0989546SSandy Huang 		vp_id++;
6041b0989546SSandy Huang 	}
6042b0989546SSandy Huang 
6043b0989546SSandy Huang 	vop_fix_dts = true;
6044b0989546SSandy Huang 
6045b0989546SSandy Huang 	return 0;
6046b0989546SSandy Huang }
6047b0989546SSandy Huang 
rockchip_vop2_check(struct display_state * state)6048820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state)
6049820a5c17SDamon Ding {
6050820a5c17SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
6051820a5c17SDamon Ding 	struct rockchip_crtc *crtc = cstate->crtc;
6052820a5c17SDamon Ding 
6053820a5c17SDamon Ding 	if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) {
6054820a5c17SDamon Ding 		printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id);
6055820a5c17SDamon Ding 		return -ENOTSUPP;
6056820a5c17SDamon Ding 	}
6057820a5c17SDamon Ding 
6058820a5c17SDamon Ding 	if (cstate->splice_mode) {
6059820a5c17SDamon Ding 		crtc->splice_mode = true;
6060820a5c17SDamon Ding 		crtc->splice_crtc_id = cstate->splice_crtc_id;
6061820a5c17SDamon Ding 	}
6062820a5c17SDamon Ding 
6063820a5c17SDamon Ding 	return 0;
6064820a5c17SDamon Ding }
6065820a5c17SDamon Ding 
rockchip_vop2_mode_valid(struct display_state * state)606622007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state)
606722007755SDamon Ding {
606822007755SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
606922007755SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
607022007755SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
607122007755SDamon Ding 	struct videomode vm;
607222007755SDamon Ding 
607322007755SDamon Ding 	drm_display_mode_to_videomode(mode, &vm);
607422007755SDamon Ding 
607522007755SDamon Ding 	if (vm.hactive < 32 || vm.vactive < 32 ||
607622007755SDamon Ding 	    (vm.hfront_porch * vm.hsync_len * vm.hback_porch *
607722007755SDamon Ding 	     vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) {
607822007755SDamon Ding 		printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id);
607922007755SDamon Ding 		return -EINVAL;
608022007755SDamon Ding 	}
608122007755SDamon Ding 
608222007755SDamon Ding 	return 0;
608322007755SDamon Ding }
608422007755SDamon Ding 
rockchip_vop2_mode_fixup(struct display_state * state)6085b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state)
6086b02eb70bSDamon Ding {
6087b02eb70bSDamon Ding 	struct connector_state *conn_state = &state->conn_state;
60880e19fecdSDamon Ding 	struct rockchip_connector *conn = conn_state->connector;
6089b02eb70bSDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
6090b02eb70bSDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
6091b02eb70bSDamon Ding 	struct vop2 *vop2 = cstate->private;
6092b02eb70bSDamon Ding 
60930e19fecdSDamon Ding 	if (conn_state->secondary) {
60940e19fecdSDamon Ding 		if (!(conn->dual_channel_mode &&
60950e19fecdSDamon Ding 		      conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) &&
60962b992d78SDamon Ding 		    conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS)
60972b992d78SDamon Ding 			drm_mode_convert_to_split_mode(mode);
60980e19fecdSDamon Ding 	}
60992b992d78SDamon Ding 
61001b5811e7SDamon Ding 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
6101b02eb70bSDamon Ding 
6102243f0077SDamon Ding 	/*
6103640211a0SDamon Ding 	 * For RK3568 and RK3588, the hactive of video timing must
6104640211a0SDamon Ding 	 * be 4-pixel aligned.
6105640211a0SDamon Ding 	 */
6106640211a0SDamon Ding 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) {
6107640211a0SDamon Ding 		if (mode->crtc_hdisplay % 4) {
6108640211a0SDamon Ding 			int old_hdisplay = mode->crtc_hdisplay;
6109640211a0SDamon Ding 			int align = 4 - (mode->crtc_hdisplay % 4);
6110640211a0SDamon Ding 
6111640211a0SDamon Ding 			mode->crtc_hdisplay += align;
6112640211a0SDamon Ding 			mode->crtc_hsync_start += align;
6113640211a0SDamon Ding 			mode->crtc_hsync_end += align;
6114640211a0SDamon Ding 			mode->crtc_htotal += align;
6115640211a0SDamon Ding 
6116640211a0SDamon Ding 			printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n",
6117640211a0SDamon Ding 			       old_hdisplay, mode->hdisplay);
6118640211a0SDamon Ding 		}
6119640211a0SDamon Ding 	}
6120640211a0SDamon Ding 
61214a9e4766SAlgea Cao 	/*
61224a9e4766SAlgea Cao 	 * When the dsc bpp is less than 9, hdmi output will flash on TV.
61234a9e4766SAlgea Cao 	 * It is speculated that the reason is that pixel rate of sink
61244a9e4766SAlgea Cao 	 * decoding is not enough.
61254a9e4766SAlgea Cao 	 * Taking 8bpp as an example, dsc clk needs to be 1/3 of the input
61264a9e4766SAlgea Cao 	 * clk. the theoretical calculation of DEN compression 1/3, at this
61274a9e4766SAlgea Cao 	 * time, the clk of vop dsc to hdmi tx can be reduced to about 260M
61284a9e4766SAlgea Cao 	 * to meet the 8bpp transmission.
61294a9e4766SAlgea Cao 	 * RK3588 dsc clk only supports 1/2 frequency division, so dsc clk
61304a9e4766SAlgea Cao 	 * is 1/2 input clk, which needs to increase blank, which is
61314a9e4766SAlgea Cao 	 * equivalent to compressing the absolute DEN time. TV is likely to
61324a9e4766SAlgea Cao 	 * decode at a decoding rate of around 260M. DEN absolute time
61334a9e4766SAlgea Cao 	 * shortening results in abnormal TV decoding.
61344a9e4766SAlgea Cao 	 * So the value of hblank needs to be reduced when bpp is below 9.
61354a9e4766SAlgea Cao 	 * The measurement can be displayed normally on TV, but reducing
61364a9e4766SAlgea Cao 	 * the hblank will result in non-standard timing of the hdmi output.
61374a9e4766SAlgea Cao 	 * This may cause compatibility issues and hdmi cts certification
61384a9e4766SAlgea Cao 	 * may fail.
61394a9e4766SAlgea Cao 	 */
61404a9e4766SAlgea Cao 	if (vop2->version == VOP_VERSION_RK3588) {
61414a9e4766SAlgea Cao 		if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
61424a9e4766SAlgea Cao 			if (cstate->dsc_sink_cap.target_bits_per_pixel_x16 < 0x90 &&
61434a9e4766SAlgea Cao 			    cstate->dsc_enable) {
61444a9e4766SAlgea Cao 				u8 vrefresh = drm_mode_vrefresh(mode);
61454a9e4766SAlgea Cao 
61464a9e4766SAlgea Cao 				mode->crtc_hsync_start = mode->hdisplay + 10;
61474a9e4766SAlgea Cao 				mode->crtc_hsync_end = mode->crtc_hsync_start + 10;
61484a9e4766SAlgea Cao 				mode->crtc_htotal = mode->crtc_hsync_end + 10;
61494a9e4766SAlgea Cao 				mode->crtc_clock = (u32)mode->crtc_htotal * mode->crtc_vtotal *
61504a9e4766SAlgea Cao 					vrefresh / 1000;
61514a9e4766SAlgea Cao 			}
61524a9e4766SAlgea Cao 		}
61534a9e4766SAlgea Cao 	}
61544a9e4766SAlgea Cao 
615521198dbdSZhang Yubing 	if (vop2->version == VOP_VERSION_RK3576) {
6156640211a0SDamon Ding 		/*
6157243f0077SDamon Ding 		 * For RK3576 YUV420 output, hden signal introduce one cycle delay,
6158243f0077SDamon Ding 		 * so we need to adjust hfp and hbp to compatible with this design.
6159243f0077SDamon Ding 		 */
616021198dbdSZhang Yubing 		if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
6161243f0077SDamon Ding 			mode->crtc_hsync_start += 2;
6162243f0077SDamon Ding 			mode->crtc_hsync_end += 2;
6163243f0077SDamon Ding 		}
616421198dbdSZhang Yubing 		/*
616521198dbdSZhang Yubing 		 * For RK3576 DP output, vp send 2 pixels 1 cycle. So the hactive,
616621198dbdSZhang Yubing 		 * hfp, hsync, hbp should be 2-pixel aligned.
616721198dbdSZhang Yubing 		 */
616821198dbdSZhang Yubing 		if (conn_state->output_if &
616921198dbdSZhang Yubing 		    (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
617021198dbdSZhang Yubing 			mode->crtc_hdisplay += mode->crtc_hdisplay % 2;
617121198dbdSZhang Yubing 			mode->crtc_hsync_start += mode->crtc_hsync_start % 2;
617221198dbdSZhang Yubing 			mode->crtc_hsync_end += mode->crtc_hsync_end % 2;
617321198dbdSZhang Yubing 			mode->crtc_htotal += mode->crtc_htotal % 2;
617421198dbdSZhang Yubing 		}
617521198dbdSZhang Yubing 	}
6176243f0077SDamon Ding 
6177b02eb70bSDamon Ding 	if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656)
6178b02eb70bSDamon Ding 		mode->crtc_clock *= 2;
6179b02eb70bSDamon Ding 
6180b02eb70bSDamon Ding 	/*
6181b02eb70bSDamon Ding 	 * For RK3528, the path of CVBS output is like:
6182b02eb70bSDamon Ding 	 * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
6183b02eb70bSDamon Ding 	 * The vop2 dclk should be four times crtc_clock for CVBS sampling
6184b02eb70bSDamon Ding 	 * clock needs.
6185b02eb70bSDamon Ding 	 */
6186b02eb70bSDamon Ding 	if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656)
6187b02eb70bSDamon Ding 		mode->crtc_clock *= 4;
6188b02eb70bSDamon Ding 
61894d64cedbSDamon Ding 	mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format);
61904d64cedbSDamon Ding 	if (cstate->mcu_timing.mcu_pix_total)
61914d64cedbSDamon Ding 		mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1;
61920675a2a4SDamon Ding 
6193b02eb70bSDamon Ding 	return 0;
6194b02eb70bSDamon Ding }
6195b02eb70bSDamon Ding 
61964c765862SDamon Ding #define FRAC_16_16(mult, div)	(((mult) << 16) / (div))
61974c765862SDamon Ding 
rockchip_vop2_plane_check(struct display_state * state)61984c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state)
61994c765862SDamon Ding {
62004c765862SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
62014c765862SDamon Ding 	struct vop2 *vop2 = cstate->private;
62024c765862SDamon Ding 	struct display_rect *src = &cstate->src_rect;
62034c765862SDamon Ding 	struct display_rect *dst = &cstate->crtc_rect;
62044c765862SDamon Ding 	struct vop2_win_data *win_data;
62054c765862SDamon Ding 	int min_scale, max_scale;
62064c765862SDamon Ding 	int hscale, vscale;
62074c765862SDamon Ding 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
62084c765862SDamon Ding 
62094c765862SDamon Ding 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
62104c765862SDamon Ding 	if (!win_data) {
62114c765862SDamon Ding 		printf("ERROR: invalid win id %d\n", primary_plane_id);
62124c765862SDamon Ding 		return -ENODEV;
62134c765862SDamon Ding 	}
62144c765862SDamon Ding 
62154c765862SDamon Ding 	min_scale = FRAC_16_16(1, win_data->max_downscale_factor);
62164c765862SDamon Ding 	max_scale = FRAC_16_16(win_data->max_upscale_factor, 1);
62174c765862SDamon Ding 
62184c765862SDamon Ding 	hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale);
62194c765862SDamon Ding 	vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale);
62204c765862SDamon Ding 	if (hscale < 0 || vscale < 0) {
62214c765862SDamon Ding 		printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name);
62224c765862SDamon Ding 		return -ERANGE;
62234c765862SDamon Ding 		}
62244c765862SDamon Ding 
62254c765862SDamon Ding 	return 0;
62264c765862SDamon Ding }
6227337d1c13SDamon Ding 
rockchip_vop2_apply_soft_te(struct display_state * state)62288e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state)
62298e7ef808SDamon Ding {
6230d8e7f4a5SSandy Huang 	__maybe_unused struct connector_state *conn_state = &state->conn_state;
62318e7ef808SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
62328e7ef808SDamon Ding 	struct vop2 *vop2 = cstate->private;
62338e7ef808SDamon Ding 	u32 vp_offset = (cstate->crtc_id * 0x100);
62348e7ef808SDamon Ding 	int val = 0;
62358e7ef808SDamon Ding 	int ret = 0;
62368e7ef808SDamon Ding 
62378e7ef808SDamon Ding 	ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val,
62388e7ef808SDamon Ding 				 (val >> EDPI_WMS_FS) & 0x1, 50 * 1000);
62398e7ef808SDamon Ding 	if (!ret) {
6240d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
62418e7ef808SDamon Ding 		ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
62428e7ef808SDamon Ding 					 !val, 50 * 1000);
62438e7ef808SDamon Ding 		if (!ret) {
62448e7ef808SDamon Ding 			ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
62458e7ef808SDamon Ding 						 val, 50 * 1000);
62468e7ef808SDamon Ding 			if (!ret) {
62478e7ef808SDamon Ding 				vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
62488e7ef808SDamon Ding 						EN_MASK, EDPI_WMS_FS, 1, false);
62498e7ef808SDamon Ding 			} else {
62508e7ef808SDamon Ding 				printf("ERROR: vp%d wait for active TE signal timeout\n",
62518e7ef808SDamon Ding 				       cstate->crtc_id);
62528e7ef808SDamon Ding 				return ret;
62538e7ef808SDamon Ding 			}
62548e7ef808SDamon Ding 		} else {
62558e7ef808SDamon Ding 			printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id);
62568e7ef808SDamon Ding 			return ret;
62578e7ef808SDamon Ding 		}
6258d8e7f4a5SSandy Huang #endif
62598e7ef808SDamon Ding 	} else {
62608e7ef808SDamon Ding 		printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id);
62618e7ef808SDamon Ding 		return ret;
62628e7ef808SDamon Ding 	}
62638e7ef808SDamon Ding 
62648e7ef808SDamon Ding 	return 0;
62658e7ef808SDamon Ding }
62668e7ef808SDamon Ding 
rockchip_vop2_regs_dump(struct display_state * state)626772388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state)
626872388c26SDamon Ding {
626972388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
627072388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
627172388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
627272388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
6273a552a69cSDamon Ding 	u32 len = 128;
627472388c26SDamon Ding 	u32 n, i, j;
627572388c26SDamon Ding 	u32 base;
627672388c26SDamon Ding 
627772388c26SDamon Ding 	if (!cstate->crtc->active)
627872388c26SDamon Ding 		return -EINVAL;
627972388c26SDamon Ding 
628072388c26SDamon Ding 	n = vop2_data->dump_regs_size;
628172388c26SDamon Ding 	for (i = 0; i < n; i++) {
628272388c26SDamon Ding 		base = regs[i].offset;
6283a552a69cSDamon Ding 		len = 128;
6284a552a69cSDamon Ding 		if (regs[i].size)
6285a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
628672388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
6287a552a69cSDamon Ding 		for (j = 0; j < len;) {
628872388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
628972388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
629072388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
629172388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
629272388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
629372388c26SDamon Ding 			j += 4;
629472388c26SDamon Ding 		}
629572388c26SDamon Ding 	}
629672388c26SDamon Ding 
629772388c26SDamon Ding 	return 0;
629872388c26SDamon Ding }
629972388c26SDamon Ding 
rockchip_vop2_active_regs_dump(struct display_state * state)630072388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state)
630172388c26SDamon Ding {
630272388c26SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
630372388c26SDamon Ding 	struct vop2 *vop2 = cstate->private;
630472388c26SDamon Ding 	const struct vop2_data *vop2_data = vop2->data;
630572388c26SDamon Ding 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
6306a552a69cSDamon Ding 	u32 len = 128;
630772388c26SDamon Ding 	u32 n, i, j;
630872388c26SDamon Ding 	u32 base;
630972388c26SDamon Ding 	bool enable_state;
631072388c26SDamon Ding 
631172388c26SDamon Ding 	if (!cstate->crtc->active)
631272388c26SDamon Ding 		return -EINVAL;
631372388c26SDamon Ding 
631472388c26SDamon Ding 	n = vop2_data->dump_regs_size;
631572388c26SDamon Ding 	for (i = 0; i < n; i++) {
631672388c26SDamon Ding 		if (regs[i].state_mask) {
631772388c26SDamon Ding 			enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) &
631872388c26SDamon Ding 				       regs[i].state_mask;
631972388c26SDamon Ding 			if (enable_state != regs[i].enable_state)
632072388c26SDamon Ding 				continue;
632172388c26SDamon Ding 		}
632272388c26SDamon Ding 
632372388c26SDamon Ding 		base = regs[i].offset;
6324a552a69cSDamon Ding 		len = 128;
6325a552a69cSDamon Ding 		if (regs[i].size)
6326a552a69cSDamon Ding 			len = min(len, regs[i].size >> 2);
632772388c26SDamon Ding 		printf("\n%s:\n", regs[i].name);
6328a552a69cSDamon Ding 		for (j = 0; j < len;) {
632972388c26SDamon Ding 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
633072388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * j)),
633172388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 1))),
633272388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 2))),
633372388c26SDamon Ding 			       vop2_readl(vop2, base + (4 * (j + 3))));
633472388c26SDamon Ding 			j += 4;
633572388c26SDamon Ding 		}
633672388c26SDamon Ding 	}
633772388c26SDamon Ding 
633872388c26SDamon Ding 	return 0;
633972388c26SDamon Ding }
634072388c26SDamon Ding 
rk3528_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6341b888dbc8SSandy Huang static void rk3528_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
63429c7848c3SDamon Ding {
63439c7848c3SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
63449c7848c3SDamon Ding 	struct vop2 *vop2 = cstate->private;
63459c7848c3SDamon Ding 	uint32_t dly = 0; /* For vop3, the default window delay is 0 */
63469c7848c3SDamon Ding 
6347b888dbc8SSandy Huang 	switch (plane_phy_id) {
63489c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER0:
63499c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_CLUSTER0_CTRL, CLUSTER_DLY_NUM_MASK,
63509c7848c3SDamon Ding 				CLUSTER_DLY_NUM_SHIFT, dly, false);
63519c7848c3SDamon Ding 		break;
63529c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART0:
63539c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL, ESMART_DLY_NUM_MASK,
63549c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
63559c7848c3SDamon Ding 		break;
63569c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART1:
63579c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART1_CTRL, ESMART_DLY_NUM_MASK,
63589c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
63599c7848c3SDamon Ding 		break;
63609c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART2:
63619c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART2_CTRL, ESMART_DLY_NUM_MASK,
63629c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
63639c7848c3SDamon Ding 		break;
63649c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART3:
63659c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART3_CTRL, ESMART_DLY_NUM_MASK,
63669c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
63679c7848c3SDamon Ding 		break;
63689c7848c3SDamon Ding 	}
63699c7848c3SDamon Ding }
63709c7848c3SDamon Ding 
rk3528_setup_overlay(struct display_state * state)6371b7195f56SDamon Ding static void rk3528_setup_overlay(struct display_state *state)
6372b7195f56SDamon Ding {
6373b7195f56SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
6374b7195f56SDamon Ding 	struct vop2 *vop2 = cstate->private;
6375b7195f56SDamon Ding 	struct vop2_win_data *win_data;
6376b7195f56SDamon Ding 	int i;
6377b7195f56SDamon Ding 	u32 offset = 0;
6378b7195f56SDamon Ding 	u8 shift = 0;
6379b7195f56SDamon Ding 
6380b7195f56SDamon Ding 	/* init the layer sel value to 0xff(Disable layer) */
6381b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6382b7195f56SDamon Ding 		offset = 0x100 * i;
6383b7195f56SDamon Ding 		vop2_writel(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 0xffffffff);
6384b7195f56SDamon Ding 	}
6385b7195f56SDamon Ding 
6386b7195f56SDamon Ding 	/* layer sel win id */
6387b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6388b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6389b7195f56SDamon Ding 			offset = 0x100 * i;
6390b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6391b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset,
6392b7195f56SDamon Ding 					LAYER_SEL_MASK, 0, win_data->layer_sel_win_id[i], false);
6393b7195f56SDamon Ding 		}
6394b7195f56SDamon Ding 	}
6395b7195f56SDamon Ding 
6396b7195f56SDamon Ding 	/* win sel port */
6397b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6398b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6399b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6400b7195f56SDamon Ding 			shift = win_data->win_sel_port_offset * 2;
6401b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL,
6402b7195f56SDamon Ding 					LAYER_SEL_PORT_MASK, shift, i, false);
6403b7195f56SDamon Ding 		}
6404b7195f56SDamon Ding 	}
6405b7195f56SDamon Ding }
6406b7195f56SDamon Ding 
rk3568_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6407b888dbc8SSandy Huang static void rk3568_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
64089c7848c3SDamon Ding {
64099c7848c3SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
64109c7848c3SDamon Ding 	struct vop2 *vop2 = cstate->private;
64119c7848c3SDamon Ding 	struct vop2_win_data *win_data;
64129c7848c3SDamon Ding 	uint32_t dly;
64139c7848c3SDamon Ding 
6414b888dbc8SSandy Huang 	win_data = vop2_find_win_by_phys_id(vop2, plane_phy_id);
64159c7848c3SDamon Ding 	dly = win_data->dly[VOP2_DLY_MODE_DEFAULT];
64169c7848c3SDamon Ding 	if (win_data->type == CLUSTER_LAYER)
64179c7848c3SDamon Ding 		dly |= dly << 8;
64189c7848c3SDamon Ding 
6419b888dbc8SSandy Huang 	switch (plane_phy_id) {
64209c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER0:
64219c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
64229c7848c3SDamon Ding 				CLUSTER0_DLY_NUM_SHIFT, dly, false);
64239c7848c3SDamon Ding 		break;
64249c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER1:
64259c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
64269c7848c3SDamon Ding 				CLUSTER1_DLY_NUM_SHIFT, dly, false);
64279c7848c3SDamon Ding 		break;
64289c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER2:
64299c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
64309c7848c3SDamon Ding 				CLUSTER0_DLY_NUM_SHIFT, dly, false);
64319c7848c3SDamon Ding 		break;
64329c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER3:
64339c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
64349c7848c3SDamon Ding 				CLUSTER1_DLY_NUM_SHIFT, dly, false);
64359c7848c3SDamon Ding 		break;
64369c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART0:
64379c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64389c7848c3SDamon Ding 				ESMART0_DLY_NUM_SHIFT, dly, false);
64399c7848c3SDamon Ding 		break;
64409c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART1:
64419c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64429c7848c3SDamon Ding 				ESMART1_DLY_NUM_SHIFT, dly, false);
64439c7848c3SDamon Ding 		break;
64449c7848c3SDamon Ding 	case ROCKCHIP_VOP2_SMART0:
64459c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART2:
64469c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64479c7848c3SDamon Ding 				SMART0_DLY_NUM_SHIFT, dly, false);
64489c7848c3SDamon Ding 		break;
64499c7848c3SDamon Ding 	case ROCKCHIP_VOP2_SMART1:
64509c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART3:
64519c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64529c7848c3SDamon Ding 				SMART1_DLY_NUM_SHIFT, dly, false);
64539c7848c3SDamon Ding 		break;
64549c7848c3SDamon Ding 	}
64559c7848c3SDamon Ding }
64569c7848c3SDamon Ding 
rk3568_setup_overlay(struct display_state * state)6457b7195f56SDamon Ding static void rk3568_setup_overlay(struct display_state *state)
6458b7195f56SDamon Ding {
6459b7195f56SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
6460b7195f56SDamon Ding 	struct vop2 *vop2 = cstate->private;
6461b7195f56SDamon Ding 	struct vop2_win_data *win_data;
6462b7195f56SDamon Ding 	int layer_phy_id = 0;
6463b7195f56SDamon Ding 	int total_used_layer = 0;
6464b7195f56SDamon Ding 	int port_mux = 0;
6465b7195f56SDamon Ding 	int i, j;
6466b7195f56SDamon Ding 	u32 layer_nr = 0;
6467b7195f56SDamon Ding 	u8 shift = 0;
6468b7195f56SDamon Ding 
6469b7195f56SDamon Ding 	/* layer sel win id */
6470b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6471b7195f56SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6472b7195f56SDamon Ding 		for (j = 0; j < layer_nr; j++) {
6473b7195f56SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6474b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6475b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
6476b7195f56SDamon Ding 					shift, win_data->layer_sel_win_id[i], false);
6477b7195f56SDamon Ding 			shift += 4;
6478b7195f56SDamon Ding 		}
6479b7195f56SDamon Ding 	}
6480b7195f56SDamon Ding 
6481b7195f56SDamon Ding 	/* win sel port */
6482b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6483b7195f56SDamon Ding 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6484b7195f56SDamon Ding 		for (j = 0; j < layer_nr; j++) {
6485b7195f56SDamon Ding 			if (!vop2->vp_plane_mask[i].attached_layers[j])
6486b7195f56SDamon Ding 				continue;
6487b7195f56SDamon Ding 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6488b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6489b7195f56SDamon Ding 			shift = win_data->win_sel_port_offset * 2;
6490b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
6491b7195f56SDamon Ding 					LAYER_SEL_PORT_SHIFT + shift, i, false);
6492b7195f56SDamon Ding 		}
6493b7195f56SDamon Ding 	}
6494b7195f56SDamon Ding 
6495b7195f56SDamon Ding 	/**
6496b7195f56SDamon Ding 	 * port mux config
6497b7195f56SDamon Ding 	 */
6498b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6499b7195f56SDamon Ding 		shift = i * 4;
6500b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].attached_layers_nr) {
6501b7195f56SDamon Ding 			total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
6502b7195f56SDamon Ding 			port_mux = total_used_layer - 1;
6503b7195f56SDamon Ding 		} else {
6504b7195f56SDamon Ding 			port_mux = 8;
6505b7195f56SDamon Ding 		}
6506b7195f56SDamon Ding 
6507b7195f56SDamon Ding 		if (i == vop2->data->nr_vps - 1)
6508b7195f56SDamon Ding 			port_mux = vop2->data->nr_mixers;
6509b7195f56SDamon Ding 
6510b7195f56SDamon Ding 		cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
6511b7195f56SDamon Ding 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
6512b7195f56SDamon Ding 				PORT_MUX_SHIFT + shift, port_mux, false);
6513b7195f56SDamon Ding 	}
6514b7195f56SDamon Ding }
6515b7195f56SDamon Ding 
rk3576_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6516b888dbc8SSandy Huang static void rk3576_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
65179c7848c3SDamon Ding {
65189c7848c3SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
65199c7848c3SDamon Ding 	struct vop2 *vop2 = cstate->private;
65209c7848c3SDamon Ding 	uint32_t dly = 0; /* For vop3, the default window delay is 0 */
65219c7848c3SDamon Ding 
6522b888dbc8SSandy Huang 	switch (plane_phy_id) {
65239c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER0:
65249c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER0_DLY_NUM, CLUSTER_DLY_NUM_MASK,
65259c7848c3SDamon Ding 				CLUSTER_DLY_NUM_SHIFT, dly, false);
65269c7848c3SDamon Ding 		break;
65279c7848c3SDamon Ding 	case ROCKCHIP_VOP2_CLUSTER1:
65289c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_CLUSTER1_DLY_NUM, CLUSTER_DLY_NUM_MASK,
65299c7848c3SDamon Ding 				CLUSTER_DLY_NUM_SHIFT, dly, false);
65309c7848c3SDamon Ding 		break;
65319c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART0:
65329c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM, ESMART_DLY_NUM_MASK,
65339c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
65349c7848c3SDamon Ding 		break;
65359c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART1:
65369c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART1_DLY_NUM, ESMART_DLY_NUM_MASK,
65379c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
65389c7848c3SDamon Ding 		break;
65399c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART2:
65409c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART2_DLY_NUM, ESMART_DLY_NUM_MASK,
65419c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
65429c7848c3SDamon Ding 		break;
65439c7848c3SDamon Ding 	case ROCKCHIP_VOP2_ESMART3:
65449c7848c3SDamon Ding 		vop2_mask_write(vop2, RK3576_ESMART3_DLY_NUM, ESMART_DLY_NUM_MASK,
65459c7848c3SDamon Ding 				ESMART_DLY_NUM_SHIFT, dly, false);
65469c7848c3SDamon Ding 		break;
65479c7848c3SDamon Ding 	}
65489c7848c3SDamon Ding }
65499c7848c3SDamon Ding 
rk3576_setup_overlay(struct display_state * state)6550b7195f56SDamon Ding static void rk3576_setup_overlay(struct display_state *state)
6551b7195f56SDamon Ding {
6552b7195f56SDamon Ding 	struct crtc_state *cstate = &state->crtc_state;
6553b7195f56SDamon Ding 	struct vop2 *vop2 = cstate->private;
6554b7195f56SDamon Ding 	struct vop2_win_data *win_data;
6555b7195f56SDamon Ding 	int i;
6556b7195f56SDamon Ding 	u32 offset = 0;
6557b7195f56SDamon Ding 
6558b7195f56SDamon Ding 	/* layer sel win id */
6559b7195f56SDamon Ding 	for (i = 0; i < vop2->data->nr_vps; i++) {
6560b7195f56SDamon Ding 		if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6561b7195f56SDamon Ding 			offset = 0x100 * i;
6562b7195f56SDamon Ding 			win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6563b7195f56SDamon Ding 			vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, LAYER_SEL_MASK,
6564b7195f56SDamon Ding 					0, win_data->layer_sel_win_id[i], false);
6565b7195f56SDamon Ding 		}
6566b7195f56SDamon Ding 	}
6567b7195f56SDamon Ding }
6568b7195f56SDamon Ding 
6569*60e6e79dSSandy Huang #ifdef CONFIG_MOS_SECONDARY
vop2_cluster_disable(void * regs,u32 offset)6570*60e6e79dSSandy Huang static void vop2_cluster_disable(void *regs, u32 offset)
6571*60e6e79dSSandy Huang {
6572*60e6e79dSSandy Huang 	writel(0x0, regs + RK3568_CLUSTER0_WIN0_CTRL0 + offset);
6573*60e6e79dSSandy Huang 	writel(0x0, regs + RK3568_CLUSTER0_WIN1_CTRL0 + offset);
6574*60e6e79dSSandy Huang 	writel(0x0, regs + RK3568_CLUSTER0_CTRL + offset);
6575*60e6e79dSSandy Huang }
6576*60e6e79dSSandy Huang 
vop2_esmart_disable(void * regs,u32 offset)6577*60e6e79dSSandy Huang static void vop2_esmart_disable(void *regs, u32 offset)
6578*60e6e79dSSandy Huang {
6579*60e6e79dSSandy Huang 	writel(0x0, regs + RK3568_ESMART0_REGION0_CTRL + offset);
6580*60e6e79dSSandy Huang 	writel(0x0, regs + RK3568_ESMART0_REGION1_CTRL + offset);
6581*60e6e79dSSandy Huang 	writel(0x0, regs + RK3568_ESMART0_REGION2_CTRL + offset);
6582*60e6e79dSSandy Huang 	writel(0x0, regs + RK3568_ESMART0_REGION3_CTRL + offset);
6583*60e6e79dSSandy Huang }
6584*60e6e79dSSandy Huang 
vop2_vp_irqs_disable(void * regs,u32 vp_id)6585*60e6e79dSSandy Huang static void vop2_vp_irqs_disable(void *regs, u32 vp_id)
6586*60e6e79dSSandy Huang {
6587*60e6e79dSSandy Huang 	u32 offset = 0x10 * vp_id;
6588*60e6e79dSSandy Huang 
6589*60e6e79dSSandy Huang 	writel(0xffff0000, regs + RK3568_VP0_INT_EN + offset);
6590*60e6e79dSSandy Huang 	writel(0xffffffff, regs + RK3568_VP0_INT_CLR + offset);
6591*60e6e79dSSandy Huang }
6592*60e6e79dSSandy Huang 
vop2_axi_irqs_disable(void * regs,u32 axi_id)6593*60e6e79dSSandy Huang static void vop2_axi_irqs_disable(void *regs, u32 axi_id)
6594*60e6e79dSSandy Huang {
6595*60e6e79dSSandy Huang 	u32 offset = 0x10 * axi_id;
6596*60e6e79dSSandy Huang 
6597*60e6e79dSSandy Huang 	writel(0xffff0000, regs + RK3568_VP0_INT_EN + offset);
6598*60e6e79dSSandy Huang 	writel(0xffffffff, regs + RK3568_VP0_INT_CLR + offset);
6599*60e6e79dSSandy Huang }
6600*60e6e79dSSandy Huang 
vop2_vp_in_standby(void * regs,u32 vp_id)6601*60e6e79dSSandy Huang static bool vop2_vp_in_standby(void *regs, u32 vp_id)
6602*60e6e79dSSandy Huang {
6603*60e6e79dSSandy Huang 	u32 offset = vp_id * 0x100;
6604*60e6e79dSSandy Huang 
6605*60e6e79dSSandy Huang 	return !!(readl(regs + RK3568_VP0_DSP_CTRL + offset) & BIT(STANDBY_EN_SHIFT));
6606*60e6e79dSSandy Huang }
6607*60e6e79dSSandy Huang 
vop2_vp_standby(void * regs,u32 vp_id)6608*60e6e79dSSandy Huang static void vop2_vp_standby(void *regs, u32 vp_id)
6609*60e6e79dSSandy Huang {
6610*60e6e79dSSandy Huang 	u32 offset = vp_id * 0x100;
6611*60e6e79dSSandy Huang 
6612*60e6e79dSSandy Huang 	writel(BIT(STANDBY_EN_SHIFT), regs + RK3568_VP0_DSP_CTRL + offset);
6613*60e6e79dSSandy Huang }
6614*60e6e79dSSandy Huang 
vop2_vp_config_done(void * regs,u32 vp_id)6615*60e6e79dSSandy Huang static void vop2_vp_config_done(void *regs, u32 vp_id)
6616*60e6e79dSSandy Huang {
6617*60e6e79dSSandy Huang 	u32 cfg_done = CFG_DONE_EN | BIT(vp_id) | (BIT(vp_id) << 16);
6618*60e6e79dSSandy Huang 	u32 offset = vp_id * 0x100;
6619*60e6e79dSSandy Huang 
6620*60e6e79dSSandy Huang 	writel(cfg_done, regs + RK3568_REG_CFG_DONE + offset);
6621*60e6e79dSSandy Huang }
6622*60e6e79dSSandy Huang 
vop2_iommu_disable(void * regs,u32 axi_id)6623*60e6e79dSSandy Huang static void vop2_iommu_disable(void *regs, u32 axi_id)
6624*60e6e79dSSandy Huang {
6625*60e6e79dSSandy Huang 	u32 val = readl(regs + RK3568_IOMMU0_STATUS);
6626*60e6e79dSSandy Huang 	bool pagefault = val & MMU_PAGE_FAULT_ACTIVE;
6627*60e6e79dSSandy Huang 	u32 offset = axi_id * 0x100;
6628*60e6e79dSSandy Huang 
6629*60e6e79dSSandy Huang 	writel(MMU_DISABLE_PAGING, regs + RK3568_IOMMU0_COMMAND + offset);
6630*60e6e79dSSandy Huang 
6631*60e6e79dSSandy Huang 	if (pagefault) {
6632*60e6e79dSSandy Huang 		printf("iommu%d status:0x%x, pagefault addr: 0x%x\n",
6633*60e6e79dSSandy Huang 			axi_id, val, readl(regs + RK3568_IOMMU0_PAGEFAULT_ADDR + offset));
6634*60e6e79dSSandy Huang 		writel(MMU_FORCE_RESET, regs + RK3568_IOMMU0_COMMAND + offset);
6635*60e6e79dSSandy Huang 	}
6636*60e6e79dSSandy Huang }
6637*60e6e79dSSandy Huang 
rockchip_vop2_reset(struct udevice * dev,u32 axi,u32 vp_mask,u32 plane_mask)6638*60e6e79dSSandy Huang static int rockchip_vop2_reset(struct udevice *dev, u32 axi, u32 vp_mask, u32 plane_mask)
6639*60e6e79dSSandy Huang {
6640*60e6e79dSSandy Huang 	void *regs = dev_read_addr_ptr(dev);
6641*60e6e79dSSandy Huang 	struct rockchip_crtc *crtc = (struct rockchip_crtc *)dev_get_driver_data(dev);
6642*60e6e79dSSandy Huang 	const struct vop2_data *vop2_data = crtc->data;
6643*60e6e79dSSandy Huang 	u32 enabled_vp_mask = 0;
6644*60e6e79dSSandy Huang 	int i = 0;
6645*60e6e79dSSandy Huang 
6646*60e6e79dSSandy Huang 	for (i = 0; i < vop2_data->nr_vps; i++) {
6647*60e6e79dSSandy Huang 		if (BIT(i) & vp_mask) {
6648*60e6e79dSSandy Huang 			if (!vop2_vp_in_standby(regs,i)) {
6649*60e6e79dSSandy Huang 				enabled_vp_mask |= BIT(i);
6650*60e6e79dSSandy Huang 			}
6651*60e6e79dSSandy Huang 		}
6652*60e6e79dSSandy Huang 	}
6653*60e6e79dSSandy Huang 
6654*60e6e79dSSandy Huang 	if (enabled_vp_mask == 0)
6655*60e6e79dSSandy Huang 		return 0;
6656*60e6e79dSSandy Huang 
6657*60e6e79dSSandy Huang 	for (i = 0; i < vop2_data->nr_layers; i++) {
6658*60e6e79dSSandy Huang 		if (BIT(vop2_data->win_data[i].phys_id) & plane_mask) {
6659*60e6e79dSSandy Huang 			if (vop2_data->win_data[i].type == CLUSTER_LAYER)
6660*60e6e79dSSandy Huang 				vop2_cluster_disable(regs, vop2_data->win_data[i].reg_offset);
6661*60e6e79dSSandy Huang 			else
6662*60e6e79dSSandy Huang 				vop2_esmart_disable(regs, vop2_data->win_data[i].reg_offset);
6663*60e6e79dSSandy Huang 		}
6664*60e6e79dSSandy Huang 	}
6665*60e6e79dSSandy Huang 
6666*60e6e79dSSandy Huang 	for (i = 0; i < vop2_data->nr_vps; i++) {
6667*60e6e79dSSandy Huang 		if (BIT(i) & vp_mask)
6668*60e6e79dSSandy Huang 			vop2_vp_config_done(regs, i);
6669*60e6e79dSSandy Huang 	}
6670*60e6e79dSSandy Huang 	mdelay(50);
6671*60e6e79dSSandy Huang 	vop2_iommu_disable(regs, axi);
6672*60e6e79dSSandy Huang 	vop2_axi_irqs_disable(regs, axi);
6673*60e6e79dSSandy Huang 
6674*60e6e79dSSandy Huang 	for (i = 0; i < vop2_data->nr_vps; i++) {
6675*60e6e79dSSandy Huang 		if (BIT(i) & vp_mask) {
6676*60e6e79dSSandy Huang 			vop2_vp_irqs_disable(regs, i);
6677*60e6e79dSSandy Huang 			vop2_vp_standby(regs, i);
6678*60e6e79dSSandy Huang 		}
6679*60e6e79dSSandy Huang 	}
6680*60e6e79dSSandy Huang 	printf("Reset vop success\n");
6681*60e6e79dSSandy Huang 
6682*60e6e79dSSandy Huang 	return 0;
6683*60e6e79dSSandy Huang }
6684*60e6e79dSSandy Huang #else
rockchip_vop2_reset(struct udevice * dev,u32 axi,u32 vp_mask,u32 plane_mask)6685*60e6e79dSSandy Huang static int rockchip_vop2_reset(struct udevice *dev, u32 axi, u32 vp_mask, u32 plane_mask)
6686*60e6e79dSSandy Huang {
6687*60e6e79dSSandy Huang 	return 0;
6688*60e6e79dSSandy Huang }
6689*60e6e79dSSandy Huang #endif
6690*60e6e79dSSandy Huang 
669172388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = {
669272388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
669372388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
669472388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
669572388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
669672388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
669772388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
669872388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
669972388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
670072388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
670172388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
670272388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
670372388c26SDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
670472388c26SDamon Ding 	{ RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1},
670572388c26SDamon Ding };
670672388c26SDamon Ding 
67076fea745cSDamon Ding #define RK3528_PLANE_MASK_BASE \
67086fea745cSDamon Ding 	(BIT(ROCKCHIP_VOP2_CLUSTER0) | \
67096fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART0)  | BIT(ROCKCHIP_VOP2_ESMART1)  | \
67106fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART2)  | BIT(ROCKCHIP_VOP2_ESMART3))
67115fa6e665SDamon Ding 
67125fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = {
67135fa6e665SDamon Ding 	{
67145fa6e665SDamon Ding 		.name = "Esmart0",
67155fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
67165fa6e665SDamon Ding 		.type = ESMART_LAYER,
67176fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
67185fa6e665SDamon Ding 		.win_sel_port_offset = 8,
67195fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 0xff, 0xff, 0xff },
67205fa6e665SDamon Ding 		.reg_offset = 0,
67215fa6e665SDamon Ding 		.axi_id = 0,
67225fa6e665SDamon Ding 		.axi_yrgb_id = 0x06,
67235fa6e665SDamon Ding 		.axi_uv_id = 0x07,
67245fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67255fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67265fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67275fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67285fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
67295fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
673013bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
67315fa6e665SDamon Ding 		.max_upscale_factor = 8,
67325fa6e665SDamon Ding 		.max_downscale_factor = 8,
67335fa6e665SDamon Ding 	},
67345fa6e665SDamon Ding 
67355fa6e665SDamon Ding 	{
67365fa6e665SDamon Ding 		.name = "Esmart1",
67375fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
67385fa6e665SDamon Ding 		.type = ESMART_LAYER,
67396fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
67405fa6e665SDamon Ding 		.win_sel_port_offset = 10,
67415fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0xff, 0xff },
67425fa6e665SDamon Ding 		.reg_offset = 0x200,
67435fa6e665SDamon Ding 		.axi_id = 0,
67445fa6e665SDamon Ding 		.axi_yrgb_id = 0x08,
67455fa6e665SDamon Ding 		.axi_uv_id = 0x09,
67465fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67475fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67485fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67495fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67505fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
67515fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
675213bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
67535fa6e665SDamon Ding 		.max_upscale_factor = 8,
67545fa6e665SDamon Ding 		.max_downscale_factor = 8,
67555fa6e665SDamon Ding 	},
67565fa6e665SDamon Ding 
67575fa6e665SDamon Ding 	{
67585fa6e665SDamon Ding 		.name = "Esmart2",
67595fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
67605fa6e665SDamon Ding 		.type = ESMART_LAYER,
67616fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_CURSOR,
67625fa6e665SDamon Ding 		.win_sel_port_offset = 12,
67635fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 0, 0xff, 0xff },
67645fa6e665SDamon Ding 		.reg_offset = 0x400,
67655fa6e665SDamon Ding 		.axi_id = 0,
67665fa6e665SDamon Ding 		.axi_yrgb_id = 0x0a,
67675fa6e665SDamon Ding 		.axi_uv_id = 0x0b,
67685fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67695fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67705fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67715fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67725fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
67735fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
677413bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
67755fa6e665SDamon Ding 		.max_upscale_factor = 8,
67765fa6e665SDamon Ding 		.max_downscale_factor = 8,
67775fa6e665SDamon Ding 	},
67785fa6e665SDamon Ding 
67795fa6e665SDamon Ding 	{
67805fa6e665SDamon Ding 		.name = "Esmart3",
67815fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
67825fa6e665SDamon Ding 		.type = ESMART_LAYER,
67836fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
67845fa6e665SDamon Ding 		.win_sel_port_offset = 14,
67855fa6e665SDamon Ding 		.layer_sel_win_id = { 0xff, 1, 0xff, 0xff },
67865fa6e665SDamon Ding 		.reg_offset = 0x600,
67875fa6e665SDamon Ding 		.axi_id = 0,
67885fa6e665SDamon Ding 		.axi_yrgb_id = 0x0c,
67895fa6e665SDamon Ding 		.axi_uv_id = 0x0d,
67905fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
67915fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67925fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
67935fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67945fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
67955fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
679613bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP1),
67975fa6e665SDamon Ding 		.max_upscale_factor = 8,
67985fa6e665SDamon Ding 		.max_downscale_factor = 8,
67995fa6e665SDamon Ding 	},
68005fa6e665SDamon Ding 
68015fa6e665SDamon Ding 	{
68025fa6e665SDamon Ding 		.name = "Cluster0",
68035fa6e665SDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
68045fa6e665SDamon Ding 		.type = CLUSTER_LAYER,
68056fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
68065fa6e665SDamon Ding 		.win_sel_port_offset = 0,
68075fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0xff, 0xff, 0xff },
68085fa6e665SDamon Ding 		.reg_offset = 0,
68095fa6e665SDamon Ding 		.axi_id = 0,
68105fa6e665SDamon Ding 		.axi_yrgb_id = 0x02,
68115fa6e665SDamon Ding 		.axi_uv_id = 0x03,
68125fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
68135fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
68145fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
68155fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
68165fa6e665SDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
68175fa6e665SDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
681813bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
68195fa6e665SDamon Ding 		.max_upscale_factor = 8,
68205fa6e665SDamon Ding 		.max_downscale_factor = 8,
68215fa6e665SDamon Ding 	},
68225fa6e665SDamon Ding };
68235fa6e665SDamon Ding 
68245fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = {
68255fa6e665SDamon Ding 	{
68266027c871SZhang Yubing 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM |
68276027c871SZhang Yubing 			   VOP_FEATURE_POST_CSC,
68285fa6e665SDamon Ding 		.max_output = {4096, 4096},
6829b05105abSDamon Ding 		.layer_mix_dly = 6,
6830b05105abSDamon Ding 		.hdr_mix_dly = 2,
6831b05105abSDamon Ding 		.win_dly = 8,
68325fa6e665SDamon Ding 	},
68335fa6e665SDamon Ding 	{
68345fa6e665SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
68355fa6e665SDamon Ding 		.max_output = {1920, 1080},
6836b05105abSDamon Ding 		.layer_mix_dly = 2,
6837b05105abSDamon Ding 		.hdr_mix_dly = 0,
6838b05105abSDamon Ding 		.win_dly = 8,
68395fa6e665SDamon Ding 	},
68405fa6e665SDamon Ding };
68415fa6e665SDamon Ding 
68429c7848c3SDamon Ding static const struct vop2_ops rk3528_vop_ops = {
68439c7848c3SDamon Ding 	.setup_win_dly = rk3528_setup_win_dly,
6844b7195f56SDamon Ding 	.setup_overlay = rk3528_setup_overlay,
6845ef0607a7SDamon Ding 	.assign_plane_mask = rk3528_assign_plane_mask,
68469c7848c3SDamon Ding };
68479c7848c3SDamon Ding 
68485fa6e665SDamon Ding const struct vop2_data rk3528_vop = {
68495fa6e665SDamon Ding 	.version = VOP_VERSION_RK3528,
68505fa6e665SDamon Ding 	.nr_vps = 2,
68515fa6e665SDamon Ding 	.vp_data = rk3528_vp_data,
68525fa6e665SDamon Ding 	.win_data = rk3528_win_data,
68536fea745cSDamon Ding 	.plane_mask_base = RK3528_PLANE_MASK_BASE,
68545fa6e665SDamon Ding 	.nr_layers = 5,
68555fa6e665SDamon Ding 	.nr_mixers = 3,
68565fa6e665SDamon Ding 	.nr_gammas = 2,
68575fa6e665SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE,
685872388c26SDamon Ding 	.dump_regs = rk3528_dump_regs,
685972388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
68609c7848c3SDamon Ding 	.ops = &rk3528_vop_ops,
68619c7848c3SDamon Ding 
686272388c26SDamon Ding };
686372388c26SDamon Ding 
686472388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = {
686572388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
686672388c26SDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
686772388c26SDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
686872388c26SDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
686972388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
687072388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
687172388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
687272388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
687372388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
687472388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
68755fa6e665SDamon Ding };
68765fa6e665SDamon Ding 
68776fea745cSDamon Ding #define RK3562_PLANE_MASK_BASE \
68786fea745cSDamon Ding 	(BIT(ROCKCHIP_VOP2_ESMART0)  | BIT(ROCKCHIP_VOP2_ESMART1)  | \
68796fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART2)  | BIT(ROCKCHIP_VOP2_ESMART3))
6880452afb13SDamon Ding 
6881452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = {
6882452afb13SDamon Ding 	{
6883452afb13SDamon Ding 		.name = "Esmart0",
6884452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
6885452afb13SDamon Ding 		.type = ESMART_LAYER,
68866fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
6887452afb13SDamon Ding 		.win_sel_port_offset = 8,
6888452afb13SDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
6889452afb13SDamon Ding 		.reg_offset = 0,
6890452afb13SDamon Ding 		.axi_id = 0,
6891452afb13SDamon Ding 		.axi_yrgb_id = 0x02,
6892452afb13SDamon Ding 		.axi_uv_id = 0x03,
6893452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6894452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6895452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6896452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
689713bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6898452afb13SDamon Ding 		.max_upscale_factor = 8,
6899452afb13SDamon Ding 		.max_downscale_factor = 8,
6900452afb13SDamon Ding 	},
6901452afb13SDamon Ding 
6902452afb13SDamon Ding 	{
6903452afb13SDamon Ding 		.name = "Esmart1",
6904452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
6905452afb13SDamon Ding 		.type = ESMART_LAYER,
69066fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
6907452afb13SDamon Ding 		.win_sel_port_offset = 10,
6908452afb13SDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
6909452afb13SDamon Ding 		.reg_offset = 0x200,
6910452afb13SDamon Ding 		.axi_id = 0,
6911452afb13SDamon Ding 		.axi_yrgb_id = 0x04,
6912452afb13SDamon Ding 		.axi_uv_id = 0x05,
6913452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6914452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6915452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6916452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
691713bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6918452afb13SDamon Ding 		.max_upscale_factor = 8,
6919452afb13SDamon Ding 		.max_downscale_factor = 8,
6920452afb13SDamon Ding 	},
6921452afb13SDamon Ding 
6922452afb13SDamon Ding 	{
6923452afb13SDamon Ding 		.name = "Esmart2",
6924452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
6925452afb13SDamon Ding 		.type = ESMART_LAYER,
69266fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
6927452afb13SDamon Ding 		.win_sel_port_offset = 12,
6928452afb13SDamon Ding 		.layer_sel_win_id = { 2, 2, 0xff, 0xff },
6929452afb13SDamon Ding 		.reg_offset = 0x400,
6930452afb13SDamon Ding 		.axi_id = 0,
6931452afb13SDamon Ding 		.axi_yrgb_id = 0x06,
6932452afb13SDamon Ding 		.axi_uv_id = 0x07,
6933452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6934452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6935452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6936452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
693713bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6938452afb13SDamon Ding 		.max_upscale_factor = 8,
6939452afb13SDamon Ding 		.max_downscale_factor = 8,
6940452afb13SDamon Ding 	},
6941452afb13SDamon Ding 
6942452afb13SDamon Ding 	{
6943452afb13SDamon Ding 		.name = "Esmart3",
6944452afb13SDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
6945452afb13SDamon Ding 		.type = ESMART_LAYER,
69466fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
6947452afb13SDamon Ding 		.win_sel_port_offset = 14,
6948452afb13SDamon Ding 		.layer_sel_win_id = { 3, 3, 0xff, 0xff },
6949452afb13SDamon Ding 		.reg_offset = 0x600,
6950452afb13SDamon Ding 		.axi_id = 0,
6951452afb13SDamon Ding 		.axi_yrgb_id = 0x08,
6952452afb13SDamon Ding 		.axi_uv_id = 0x0d,
6953452afb13SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
6954452afb13SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6955452afb13SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
6956452afb13SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
695713bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0),
6958452afb13SDamon Ding 		.max_upscale_factor = 8,
6959452afb13SDamon Ding 		.max_downscale_factor = 8,
6960452afb13SDamon Ding 	},
6961452afb13SDamon Ding };
6962452afb13SDamon Ding 
6963452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = {
6964452afb13SDamon Ding 	{
6965452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6966452afb13SDamon Ding 		.max_output = {2048, 4096},
696753d536adSDamon Ding 		.win_dly = 6,
6968452afb13SDamon Ding 		.layer_mix_dly = 8,
6969452afb13SDamon Ding 	},
6970452afb13SDamon Ding 	{
6971452afb13SDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6972452afb13SDamon Ding 		.max_output = {2048, 1080},
6973452afb13SDamon Ding 		.win_dly = 8,
6974452afb13SDamon Ding 		.layer_mix_dly = 8,
6975452afb13SDamon Ding 	},
6976452afb13SDamon Ding };
6977452afb13SDamon Ding 
69789c7848c3SDamon Ding static const struct vop2_ops rk3562_vop_ops = {
69799c7848c3SDamon Ding 	.setup_win_dly = rk3528_setup_win_dly,
6980b7195f56SDamon Ding 	.setup_overlay = rk3528_setup_overlay,
6981ef0607a7SDamon Ding 	.assign_plane_mask = rk3528_assign_plane_mask,
69829c7848c3SDamon Ding };
69839c7848c3SDamon Ding 
6984452afb13SDamon Ding const struct vop2_data rk3562_vop = {
6985452afb13SDamon Ding 	.version = VOP_VERSION_RK3562,
6986452afb13SDamon Ding 	.nr_vps = 2,
6987452afb13SDamon Ding 	.vp_data = rk3562_vp_data,
6988452afb13SDamon Ding 	.win_data = rk3562_win_data,
69896fea745cSDamon Ding 	.plane_mask_base = RK3562_PLANE_MASK_BASE,
6990452afb13SDamon Ding 	.nr_layers = 4,
6991452afb13SDamon Ding 	.nr_mixers = 3,
6992452afb13SDamon Ding 	.nr_gammas = 2,
6993452afb13SDamon Ding 	.esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE,
699472388c26SDamon Ding 	.dump_regs = rk3562_dump_regs,
699572388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
69969c7848c3SDamon Ding 	.ops = &rk3562_vop_ops,
699772388c26SDamon Ding };
699872388c26SDamon Ding 
699972388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = {
700072388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
700172388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
700272388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
700372388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
700472388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
700572388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
700672388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
700772388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
700872388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
700972388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
701072388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
701172388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
7012452afb13SDamon Ding };
7013452afb13SDamon Ding 
7014b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
7015b0989546SSandy Huang 	{ /* one display policy */
7016b0989546SSandy Huang 		{/* main display */
7017b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
7018b0989546SSandy Huang 			.attached_layers_nr = 6,
7019b0989546SSandy Huang 			.attached_layers = {
7020b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
7021b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
7022b0989546SSandy Huang 				},
70232d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7024b0989546SSandy Huang 		},
7025b0989546SSandy Huang 		{/* second display */},
7026b0989546SSandy Huang 		{/* third  display */},
7027b0989546SSandy Huang 		{/* fourth display */},
7028b0989546SSandy Huang 	},
7029b0989546SSandy Huang 
7030b0989546SSandy Huang 	{ /* two display policy */
7031b0989546SSandy Huang 		{/* main display */
7032b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
7033b0989546SSandy Huang 			.attached_layers_nr = 3,
7034b0989546SSandy Huang 			.attached_layers = {
7035b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
7036b0989546SSandy Huang 				},
70372d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7038b0989546SSandy Huang 		},
7039b0989546SSandy Huang 
7040b0989546SSandy Huang 		{/* second display */
7041b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
7042b0989546SSandy Huang 			.attached_layers_nr = 3,
7043b0989546SSandy Huang 			.attached_layers = {
7044b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
7045b0989546SSandy Huang 				},
70462d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7047b0989546SSandy Huang 		},
7048b0989546SSandy Huang 		{/* third  display */},
7049b0989546SSandy Huang 		{/* fourth display */},
7050b0989546SSandy Huang 	},
7051b0989546SSandy Huang 
7052b0989546SSandy Huang 	{ /* three display policy */
7053b0989546SSandy Huang 		{/* main display */
7054b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
7055b0989546SSandy Huang 			.attached_layers_nr = 3,
7056b0989546SSandy Huang 			.attached_layers = {
7057b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
7058b0989546SSandy Huang 				},
70592d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7060b0989546SSandy Huang 		},
7061b0989546SSandy Huang 
7062b0989546SSandy Huang 		{/* second display */
7063b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
7064b0989546SSandy Huang 			.attached_layers_nr = 2,
7065b0989546SSandy Huang 			.attached_layers = {
7066b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
7067b0989546SSandy Huang 				},
70682d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7069b0989546SSandy Huang 		},
7070b0989546SSandy Huang 
7071b0989546SSandy Huang 		{/* third  display */
7072b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7073b0989546SSandy Huang 			.attached_layers_nr = 1,
7074b0989546SSandy Huang 			.attached_layers = { ROCKCHIP_VOP2_ESMART1 },
70752d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7076b0989546SSandy Huang 		},
7077b0989546SSandy Huang 
7078b0989546SSandy Huang 		{/* fourth display */},
7079b0989546SSandy Huang 	},
7080b0989546SSandy Huang 
7081b0989546SSandy Huang 	{/* reserved for four display policy */},
7082b0989546SSandy Huang };
7083b0989546SSandy Huang 
70846fea745cSDamon Ding #define RK3568_PLANE_MASK_BASE \
70856fea745cSDamon Ding 	(BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
70866fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART0)  | BIT(ROCKCHIP_VOP2_ESMART1)  | \
70876fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_SMART0)   | BIT(ROCKCHIP_VOP2_SMART1))
70886fea745cSDamon Ding 
7089b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = {
7090b0989546SSandy Huang 	{
7091b0989546SSandy Huang 		.name = "Cluster0",
7092b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
7093ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
70946fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7095b0989546SSandy Huang 		.win_sel_port_offset = 0,
70965fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0xff },
7097b0989546SSandy Huang 		.reg_offset = 0,
70985fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
70995fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71005fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71015fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
710213bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71034c765862SDamon Ding 		.max_upscale_factor = 4,
71044c765862SDamon Ding 		.max_downscale_factor = 4,
71059c7848c3SDamon Ding 		.dly = { 0, 27, 21 },
7106b0989546SSandy Huang 	},
7107b0989546SSandy Huang 
7108b0989546SSandy Huang 	{
7109b0989546SSandy Huang 		.name = "Cluster1",
7110b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
7111ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
71126fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7113b0989546SSandy Huang 		.win_sel_port_offset = 1,
71145fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 0xff },
7115b0989546SSandy Huang 		.reg_offset = 0x200,
71165fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71175fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71185fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71195fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
712013bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71214c765862SDamon Ding 		.max_upscale_factor = 4,
71224c765862SDamon Ding 		.max_downscale_factor = 4,
71231c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_CLUSTER0,
71241c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
71259c7848c3SDamon Ding 		.dly = { 0, 27, 21 },
7126b0989546SSandy Huang 	},
7127b0989546SSandy Huang 
7128b0989546SSandy Huang 	{
7129b0989546SSandy Huang 		.name = "Esmart0",
7130b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART0,
7131ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
71326fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7133b0989546SSandy Huang 		.win_sel_port_offset = 4,
71345fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 0xff },
7135b0989546SSandy Huang 		.reg_offset = 0,
71365fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71375fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71385fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71395fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
714013bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71414c765862SDamon Ding 		.max_upscale_factor = 8,
71424c765862SDamon Ding 		.max_downscale_factor = 8,
71439c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
7144b0989546SSandy Huang 	},
7145b0989546SSandy Huang 
7146b0989546SSandy Huang 	{
7147b0989546SSandy Huang 		.name = "Esmart1",
7148b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART1,
7149ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
71506fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7151b0989546SSandy Huang 		.win_sel_port_offset = 5,
71525fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 0xff },
7153b0989546SSandy Huang 		.reg_offset = 0x200,
71545fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71555fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71565fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71575fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
715813bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71594c765862SDamon Ding 		.max_upscale_factor = 8,
71604c765862SDamon Ding 		.max_downscale_factor = 8,
71619c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
71621c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_ESMART0,
71631c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
7164b0989546SSandy Huang 	},
7165b0989546SSandy Huang 
7166b0989546SSandy Huang 	{
7167b0989546SSandy Huang 		.name = "Smart0",
7168b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART0,
7169ecc31b6eSAndy Yan 		.type = SMART_LAYER,
71706fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7171b0989546SSandy Huang 		.win_sel_port_offset = 6,
71725fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 0xff },
7173b0989546SSandy Huang 		.reg_offset = 0x400,
71745fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71755fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71765fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71775fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
717813bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71794c765862SDamon Ding 		.max_upscale_factor = 8,
71804c765862SDamon Ding 		.max_downscale_factor = 8,
71819c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
7182b0989546SSandy Huang 	},
7183b0989546SSandy Huang 
7184b0989546SSandy Huang 	{
7185b0989546SSandy Huang 		.name = "Smart1",
7186b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART1,
7187ecc31b6eSAndy Yan 		.type = SMART_LAYER,
71886fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7189b0989546SSandy Huang 		.win_sel_port_offset = 7,
71905fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 0xff },
7191b0989546SSandy Huang 		.reg_offset = 0x600,
71925fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
71935fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71945fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
71955fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
719613bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71974c765862SDamon Ding 		.max_upscale_factor = 8,
71984c765862SDamon Ding 		.max_downscale_factor = 8,
71999c7848c3SDamon Ding 		.dly = { 20, 47, 41 },
72001c9572c7SDamon Ding 		.source_win_id = ROCKCHIP_VOP2_SMART0,
72011c9572c7SDamon Ding 		.feature = WIN_FEATURE_MIRROR,
7202b0989546SSandy Huang 	},
7203b0989546SSandy Huang };
7204b0989546SSandy Huang 
720563cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = {
720663cb669fSSandy Huang 	{
720763cb669fSSandy Huang 		.feature = VOP_FEATURE_OUTPUT_10BIT,
720863cb669fSSandy Huang 		.pre_scan_max_dly = 42,
720963cb669fSSandy Huang 		.max_output = {4096, 2304},
7210d0408543SAndy Yan 	},
721163cb669fSSandy Huang 	{
721263cb669fSSandy Huang 		.feature = 0,
721363cb669fSSandy Huang 		.pre_scan_max_dly = 40,
721463cb669fSSandy Huang 		.max_output = {2048, 1536},
721563cb669fSSandy Huang 	},
721663cb669fSSandy Huang 	{
721763cb669fSSandy Huang 		.feature = 0,
721863cb669fSSandy Huang 		.pre_scan_max_dly = 40,
721963cb669fSSandy Huang 		.max_output = {1920, 1080},
722063cb669fSSandy Huang 	},
722163cb669fSSandy Huang };
7222d0408543SAndy Yan 
72239c7848c3SDamon Ding static const struct vop2_ops rk3568_vop_ops = {
72249c7848c3SDamon Ding 	.setup_win_dly = rk3568_setup_win_dly,
7225b7195f56SDamon Ding 	.setup_overlay = rk3568_setup_overlay,
7226ef0607a7SDamon Ding 	.assign_plane_mask = rk3568_assign_plane_mask,
72279c7848c3SDamon Ding };
72289c7848c3SDamon Ding 
722963cb669fSSandy Huang const struct vop2_data rk3568_vop = {
7230ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3568,
723163cb669fSSandy Huang 	.nr_vps = 3,
723263cb669fSSandy Huang 	.vp_data = rk3568_vp_data,
7233b0989546SSandy Huang 	.win_data = rk3568_win_data,
7234b0989546SSandy Huang 	.plane_mask = rk356x_vp_plane_mask[0],
72356fea745cSDamon Ding 	.plane_mask_base = RK3568_PLANE_MASK_BASE,
7236d0408543SAndy Yan 	.nr_layers = 6,
723763cb669fSSandy Huang 	.nr_mixers = 5,
72381147facaSSandy Huang 	.nr_gammas = 1,
723972388c26SDamon Ding 	.dump_regs = rk3568_dump_regs,
724072388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3568_dump_regs),
72419c7848c3SDamon Ding 	.ops = &rk3568_vop_ops,
7242d0408543SAndy Yan };
7243d0408543SAndy Yan 
72446fea745cSDamon Ding #define RK3576_PLANE_MASK_BASE \
72456fea745cSDamon Ding 	(BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
72466fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART0)  | BIT(ROCKCHIP_VOP2_ESMART1)  | \
72476fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART2)  | BIT(ROCKCHIP_VOP2_ESMART3))
7248a552a69cSDamon Ding 
7249a552a69cSDamon Ding static struct vop2_dump_regs rk3576_dump_regs[] = {
7250a552a69cSDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 },
7251a552a69cSDamon Ding 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 },
7252a552a69cSDamon Ding 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 },
7253a552a69cSDamon Ding 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 },
7254a552a69cSDamon Ding 	{ RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 },
7255a552a69cSDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7256a552a69cSDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7257a552a69cSDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7258a552a69cSDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
7259a552a69cSDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
7260a552a69cSDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 },
7261a552a69cSDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 },
7262a552a69cSDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 },
7263a552a69cSDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 },
7264a552a69cSDamon Ding 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 },
7265a552a69cSDamon Ding };
7266a552a69cSDamon Ding 
7267a552a69cSDamon Ding /*
7268a552a69cSDamon Ding  * RK3576 VOP with 2 Cluster win and 4 Esmart win.
7269a552a69cSDamon Ding  * Every Esmart win support 4 multi-region.
7270a552a69cSDamon Ding  * VP0 can use Cluster0/1 and Esmart0/2
7271a552a69cSDamon Ding  * VP1 can use Cluster0/1 and Esmart1/3
7272a552a69cSDamon Ding  * VP2 can use Esmart0/1/2/3
7273a552a69cSDamon Ding  *
7274a552a69cSDamon Ding  * Scale filter mode:
7275a552a69cSDamon Ding  *
7276a552a69cSDamon Ding  * * Cluster:
7277a552a69cSDamon Ding  * * Support prescale down:
7278a552a69cSDamon Ding  * * H/V: gt2/avg2 or gt4/avg4
7279a552a69cSDamon Ding  * * After prescale down:
7280a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/multi-phase filter for scale up
7281a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/multi-phase filter for scale down
7282a552a69cSDamon Ding  *
7283a552a69cSDamon Ding  * * Esmart:
7284a552a69cSDamon Ding  * * Support prescale down:
7285a552a69cSDamon Ding  * * H: gt2/avg2 or gt4/avg4
7286a552a69cSDamon Ding  * * V: gt2 or gt4
7287a552a69cSDamon Ding  * * After prescale down:
7288a552a69cSDamon Ding  *	* nearest-neighbor/bilinear/bicubic for scale up
7289a552a69cSDamon Ding  *	* nearest-neighbor/bilinear for scale down
7290cc517d73SDamon Ding  *
7291cc517d73SDamon Ding  * AXI config::
7292cc517d73SDamon Ding  *
7293cc517d73SDamon Ding  * * Cluster0 win0: 0xa,  0xb       [AXI0]
7294cc517d73SDamon Ding  * * Cluster0 win1: 0xc,  0xd       [AXI0]
7295cc517d73SDamon Ding  * * Cluster1 win0: 0x6,  0x7       [AXI0]
7296cc517d73SDamon Ding  * * Cluster1 win1: 0x8,  0x9       [AXI0]
7297cc517d73SDamon Ding  * * Esmart0:       0x10, 0x11      [AXI0]
7298cc517d73SDamon Ding  * * Esmart1:       0x12, 0x13      [AXI0]
7299cc517d73SDamon Ding  * * Esmart2:       0xa,  0xb       [AXI1]
7300cc517d73SDamon Ding  * * Esmart3:       0xc,  0xd       [AXI1]
7301cc517d73SDamon Ding  * * Lut dma rid:   0x1,  0x2,  0x3 [AXI0]
7302cc517d73SDamon Ding  * * DCI dma rid:   0x4             [AXI0]
7303cc517d73SDamon Ding  * * Metadata rid:  0x5             [AXI0]
7304cc517d73SDamon Ding  *
7305cc517d73SDamon Ding  * * Limit:
7306cc517d73SDamon Ding  * * (1) 0x0 and 0xf can't be used;
7307cc517d73SDamon Ding  * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf,
7308cc517d73SDamon Ding  * * VOP will dead at the system bandwidth very terrible scene.
7309a552a69cSDamon Ding  */
7310a552a69cSDamon Ding static struct vop2_win_data rk3576_win_data[6] = {
7311a552a69cSDamon Ding 	{
7312a552a69cSDamon Ding 		.name = "Esmart0",
7313a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART0,
7314a552a69cSDamon Ding 		.type = ESMART_LAYER,
73156fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7316a552a69cSDamon Ding 		.layer_sel_win_id = { 2, 0xff, 0, 0xff },
7317a552a69cSDamon Ding 		.reg_offset = 0x0,
7318a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
7319a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
7320a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7321a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
7322a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7323a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7324a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7325a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
7326a552a69cSDamon Ding 		.axi_id = 0,
7327cc517d73SDamon Ding 		.axi_yrgb_id = 0x10,
7328cc517d73SDamon Ding 		.axi_uv_id = 0x11,
732913bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
7330a552a69cSDamon Ding 		.max_upscale_factor = 8,
7331a552a69cSDamon Ding 		.max_downscale_factor = 8,
7332a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH,
7333a552a69cSDamon Ding 	},
7334a552a69cSDamon Ding 	{
7335a552a69cSDamon Ding 		.name = "Esmart1",
7336a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART1,
7337a552a69cSDamon Ding 		.type = ESMART_LAYER,
73386fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7339a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 2, 1, 0xff },
7340a552a69cSDamon Ding 		.reg_offset = 0x200,
7341a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
7342a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
7343a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7344a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
7345a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7346a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7347a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7348a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
7349a552a69cSDamon Ding 		.axi_id = 0,
7350cc517d73SDamon Ding 		.axi_yrgb_id = 0x12,
7351cc517d73SDamon Ding 		.axi_uv_id = 0x13,
735213bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
7353a552a69cSDamon Ding 		.max_upscale_factor = 8,
7354a552a69cSDamon Ding 		.max_downscale_factor = 8,
7355a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
7356a552a69cSDamon Ding 	},
7357a552a69cSDamon Ding 
7358a552a69cSDamon Ding 	{
7359a552a69cSDamon Ding 		.name = "Esmart2",
7360a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART2,
7361a552a69cSDamon Ding 		.type = ESMART_LAYER,
73626fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7363a552a69cSDamon Ding 		.layer_sel_win_id = { 3, 0xff, 2, 0xff },
7364a552a69cSDamon Ding 		.reg_offset = 0x400,
7365a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
7366a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
7367a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7368a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
7369a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7370a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7371a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7372a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
7373a552a69cSDamon Ding 		.axi_id = 1,
7374a552a69cSDamon Ding 		.axi_yrgb_id = 0x0a,
7375a552a69cSDamon Ding 		.axi_uv_id = 0x0b,
737613bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
7377a552a69cSDamon Ding 		.max_upscale_factor = 8,
7378a552a69cSDamon Ding 		.max_downscale_factor = 8,
7379a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
7380a552a69cSDamon Ding 	},
7381a552a69cSDamon Ding 
7382a552a69cSDamon Ding 	{
7383a552a69cSDamon Ding 		.name = "Esmart3",
7384a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_ESMART3,
7385a552a69cSDamon Ding 		.type = ESMART_LAYER,
73866fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7387a552a69cSDamon Ding 		.layer_sel_win_id = { 0xff, 3, 3, 0xff },
7388a552a69cSDamon Ding 		.reg_offset = 0x600,
7389a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_Y,
7390a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
7391a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7392a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
7393a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7394a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7395a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7396a552a69cSDamon Ding 		.pd_id = VOP2_PD_ESMART,
7397a552a69cSDamon Ding 		.axi_id = 1,
7398a552a69cSDamon Ding 		.axi_yrgb_id = 0x0c,
7399a552a69cSDamon Ding 		.axi_uv_id = 0x0d,
740013bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
7401a552a69cSDamon Ding 		.max_upscale_factor = 8,
7402a552a69cSDamon Ding 		.max_downscale_factor = 8,
7403a552a69cSDamon Ding 		.feature = WIN_FEATURE_MULTI_AREA,
7404a552a69cSDamon Ding 	},
7405a552a69cSDamon Ding 
7406a552a69cSDamon Ding 	{
7407a552a69cSDamon Ding 		.name = "Cluster0",
7408a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
7409a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
74106fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7411a552a69cSDamon Ding 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
7412a552a69cSDamon Ding 		.reg_offset = 0x0,
7413a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
7414a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
7415a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7416a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
7417a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7418a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7419a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7420a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
7421cc517d73SDamon Ding 		.axi_yrgb_id = 0x0a,
7422cc517d73SDamon Ding 		.axi_uv_id = 0x0b,
742313bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
7424a552a69cSDamon Ding 		.max_upscale_factor = 8,
7425a552a69cSDamon Ding 		.max_downscale_factor = 8,
7426a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
7427a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI,
7428a552a69cSDamon Ding 	},
7429a552a69cSDamon Ding 
7430a552a69cSDamon Ding 	{
7431a552a69cSDamon Ding 		.name = "Cluster1",
7432a552a69cSDamon Ding 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
7433a552a69cSDamon Ding 		.type = CLUSTER_LAYER,
74346fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7435a552a69cSDamon Ding 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
7436a552a69cSDamon Ding 		.reg_offset = 0x200,
7437a552a69cSDamon Ding 		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
7438a552a69cSDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIL,
7439a552a69cSDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7440a552a69cSDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
7441a552a69cSDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7442a552a69cSDamon Ding 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7443a552a69cSDamon Ding 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7444a552a69cSDamon Ding 		.pd_id = VOP2_PD_CLUSTER,
7445a552a69cSDamon Ding 		.axi_yrgb_id = 0x06,
7446a552a69cSDamon Ding 		.axi_uv_id = 0x07,
744713bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
7448a552a69cSDamon Ding 		.max_upscale_factor = 8,
7449a552a69cSDamon Ding 		.max_downscale_factor = 8,
7450a552a69cSDamon Ding 		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
7451a552a69cSDamon Ding 			   WIN_FEATURE_Y2R_13BIT_DEPTH,
7452a552a69cSDamon Ding 	},
7453a552a69cSDamon Ding };
7454a552a69cSDamon Ding 
745544b1b62cSDamon Ding /*
745644b1b62cSDamon Ding  * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4,
745744b1b62cSDamon Ding  * the urgency signal will be set to 1, when full post line buffer is over 6, the
745844b1b62cSDamon Ding  * urgency signal will be set to 0.
745944b1b62cSDamon Ding  */
746044b1b62cSDamon Ding static struct vop_urgency rk3576_vp0_urgency = {
746144b1b62cSDamon Ding 	.urgen_thl = 4,
746244b1b62cSDamon Ding 	.urgen_thh = 6,
746344b1b62cSDamon Ding };
746444b1b62cSDamon Ding 
7465a552a69cSDamon Ding static struct vop2_vp_data rk3576_vp_data[3] = {
7466a552a69cSDamon Ding 	{
7467a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR |
7468a552a69cSDamon Ding 			   VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT |
7469a552a69cSDamon Ding 			   VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP,
7470a552a69cSDamon Ding 		.max_output = { 4096, 4096 },
7471a552a69cSDamon Ding 		.hdrvivid_dly = 21,
7472a552a69cSDamon Ding 		.sdr2hdr_dly = 21,
7473a552a69cSDamon Ding 		.layer_mix_dly = 8,
7474a552a69cSDamon Ding 		.hdr_mix_dly = 2,
7475a552a69cSDamon Ding 		.win_dly = 10,
7476a552a69cSDamon Ding 		.pixel_rate = 2,
747744b1b62cSDamon Ding 		.urgency = &rk3576_vp0_urgency,
7478a552a69cSDamon Ding 	},
7479a552a69cSDamon Ding 	{
7480a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN |
7481a552a69cSDamon Ding 			   VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2,
7482a552a69cSDamon Ding 		.max_output = { 2560, 2560 },
7483a552a69cSDamon Ding 		.hdrvivid_dly = 0,
7484a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
7485a552a69cSDamon Ding 		.layer_mix_dly = 6,
7486a552a69cSDamon Ding 		.hdr_mix_dly = 0,
7487a552a69cSDamon Ding 		.win_dly = 10,
7488a552a69cSDamon Ding 		.pixel_rate = 1,
7489a552a69cSDamon Ding 	},
7490a552a69cSDamon Ding 	{
7491a552a69cSDamon Ding 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
7492a552a69cSDamon Ding 		.max_output = { 1920, 1920 },
7493a552a69cSDamon Ding 		.hdrvivid_dly = 0,
7494a552a69cSDamon Ding 		.sdr2hdr_dly = 0,
7495a552a69cSDamon Ding 		.layer_mix_dly = 6,
7496a552a69cSDamon Ding 		.hdr_mix_dly = 0,
7497a552a69cSDamon Ding 		.win_dly = 10,
7498a552a69cSDamon Ding 		.pixel_rate = 1,
7499a552a69cSDamon Ding 	},
7500a552a69cSDamon Ding };
7501a552a69cSDamon Ding 
7502a552a69cSDamon Ding static struct vop2_power_domain_data rk3576_vop_pd_data[] = {
7503a552a69cSDamon Ding 	{
7504a552a69cSDamon Ding 		.id = VOP2_PD_CLUSTER,
7505a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1),
7506a552a69cSDamon Ding 	},
7507a552a69cSDamon Ding 	{
7508a552a69cSDamon Ding 		.id = VOP2_PD_ESMART,
7509a552a69cSDamon Ding 		.module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) |
7510a552a69cSDamon Ding 				  BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3),
7511a552a69cSDamon Ding 	},
7512a552a69cSDamon Ding };
7513a552a69cSDamon Ding 
7514a552a69cSDamon Ding static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = {
7515a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_4K_MODE, 2},
7516a552a69cSDamon Ding 	{VOP3_ESMART_4K_4K_2K_2K_MODE, 3}
7517a552a69cSDamon Ding };
7518a552a69cSDamon Ding 
75199c7848c3SDamon Ding static const struct vop2_ops rk3576_vop_ops = {
75209c7848c3SDamon Ding 	.setup_win_dly = rk3576_setup_win_dly,
7521b7195f56SDamon Ding 	.setup_overlay = rk3576_setup_overlay,
7522ef0607a7SDamon Ding 	.assign_plane_mask = rk3528_assign_plane_mask,
75239c7848c3SDamon Ding };
75249c7848c3SDamon Ding 
7525a552a69cSDamon Ding const struct vop2_data rk3576_vop = {
7526a552a69cSDamon Ding 	.version = VOP_VERSION_RK3576,
7527a552a69cSDamon Ding 	.nr_vps = 3,
7528a552a69cSDamon Ding 	.nr_mixers = 4,
7529a552a69cSDamon Ding 	.nr_layers = 6,
7530a552a69cSDamon Ding 	.nr_gammas = 3,
7531a552a69cSDamon Ding 	.esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE,
7532a552a69cSDamon Ding 	.esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map),
7533a552a69cSDamon Ding 	.esmart_lb_mode_map = rk3576_esmart_lb_mode_map,
7534a552a69cSDamon Ding 	.vp_data = rk3576_vp_data,
7535a552a69cSDamon Ding 	.win_data = rk3576_win_data,
75366fea745cSDamon Ding 	.plane_mask_base = RK3576_PLANE_MASK_BASE,
7537a552a69cSDamon Ding 	.pd = rk3576_vop_pd_data,
7538a552a69cSDamon Ding 	.nr_pd = ARRAY_SIZE(rk3576_vop_pd_data),
7539a552a69cSDamon Ding 	.dump_regs = rk3576_dump_regs,
7540a552a69cSDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3576_dump_regs),
75419c7848c3SDamon Ding 	.ops = &rk3576_vop_ops,
7542a552a69cSDamon Ding };
7543a552a69cSDamon Ding 
754472388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = {
754572388c26SDamon Ding 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
754672388c26SDamon Ding 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
754772388c26SDamon Ding 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
754872388c26SDamon Ding 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
754972388c26SDamon Ding 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
755072388c26SDamon Ding 	{ RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 },
755172388c26SDamon Ding 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
755272388c26SDamon Ding 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
755372388c26SDamon Ding 	{ RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 },
755472388c26SDamon Ding 	{ RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 },
755572388c26SDamon Ding 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
755672388c26SDamon Ding 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
755772388c26SDamon Ding 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
755872388c26SDamon Ding 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
755972388c26SDamon Ding 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
756072388c26SDamon Ding };
756172388c26SDamon Ding 
7562ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
7563ecc31b6eSAndy Yan 	{ /* one display policy */
7564ecc31b6eSAndy Yan 		{/* main display */
7565608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
756683d6b087SDamon Ding 			.attached_layers_nr = 4,
7567ecc31b6eSAndy Yan 			.attached_layers = {
756883d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
756983d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7570ecc31b6eSAndy Yan 			},
75712d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7572ecc31b6eSAndy Yan 		},
757383d6b087SDamon Ding 
757483d6b087SDamon Ding 		{/* planes for the splice mode */
757583d6b087SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
757683d6b087SDamon Ding 			.attached_layers_nr = 4,
757783d6b087SDamon Ding 			.attached_layers = {
757883d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
757983d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
758083d6b087SDamon Ding 			},
75812d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
758283d6b087SDamon Ding 		},
7583ecc31b6eSAndy Yan 		{/* third  display */},
7584ecc31b6eSAndy Yan 		{/* fourth display */},
7585ecc31b6eSAndy Yan 	},
7586ecc31b6eSAndy Yan 
7587ecc31b6eSAndy Yan 	{ /* two display policy */
7588ecc31b6eSAndy Yan 		{/* main display */
7589608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7590ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
7591ecc31b6eSAndy Yan 			.attached_layers = {
7592ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
759383d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7594ecc31b6eSAndy Yan 			},
75952d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7596ecc31b6eSAndy Yan 		},
7597ecc31b6eSAndy Yan 
7598ecc31b6eSAndy Yan 		{/* second display */
759983d6b087SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7600ecc31b6eSAndy Yan 			.attached_layers_nr = 4,
7601ecc31b6eSAndy Yan 			.attached_layers = {
760283d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
7603ecc31b6eSAndy Yan 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
7604ecc31b6eSAndy Yan 			},
76052d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7606ecc31b6eSAndy Yan 		},
7607ecc31b6eSAndy Yan 		{/* third  display */},
7608ecc31b6eSAndy Yan 		{/* fourth display */},
7609ecc31b6eSAndy Yan 	},
7610ecc31b6eSAndy Yan 
7611ecc31b6eSAndy Yan 	{ /* three display policy */
7612ecc31b6eSAndy Yan 		{/* main display */
7613608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7614ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
7615ecc31b6eSAndy Yan 			.attached_layers = {
761683d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER2,
761783d6b087SDamon Ding 				  ROCKCHIP_VOP2_ESMART0
7618ecc31b6eSAndy Yan 			},
76192d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7620ecc31b6eSAndy Yan 		},
7621ecc31b6eSAndy Yan 
7622ecc31b6eSAndy Yan 		{/* second display */
7623608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7624ecc31b6eSAndy Yan 			.attached_layers_nr = 3,
7625ecc31b6eSAndy Yan 			.attached_layers = {
762683d6b087SDamon Ding 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_CLUSTER3,
762783d6b087SDamon Ding 				  ROCKCHIP_VOP2_ESMART1
7628ecc31b6eSAndy Yan 			},
76292d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7630ecc31b6eSAndy Yan 		},
7631ecc31b6eSAndy Yan 
7632ecc31b6eSAndy Yan 		{/* third  display */
7633ecc31b6eSAndy Yan 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7634ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7635ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
76362d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7637ecc31b6eSAndy Yan 		},
7638ecc31b6eSAndy Yan 
7639ecc31b6eSAndy Yan 		{/* fourth display */},
7640ecc31b6eSAndy Yan 	},
7641ecc31b6eSAndy Yan 
7642ecc31b6eSAndy Yan 	{ /* four display policy */
7643ecc31b6eSAndy Yan 		{/* main display */
7644608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7645ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7646ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
76472d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7648ecc31b6eSAndy Yan 		},
7649ecc31b6eSAndy Yan 
7650ecc31b6eSAndy Yan 		{/* second display */
7651608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7652ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7653ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
76542d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7655ecc31b6eSAndy Yan 		},
7656ecc31b6eSAndy Yan 
7657ecc31b6eSAndy Yan 		{/* third  display */
7658608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7659ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7660ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
76612d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7662ecc31b6eSAndy Yan 		},
7663ecc31b6eSAndy Yan 
7664ecc31b6eSAndy Yan 		{/* fourth display */
7665608c9f66SDamon Ding 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
7666ecc31b6eSAndy Yan 			.attached_layers_nr = 2,
7667ecc31b6eSAndy Yan 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
76682d3a2f01SDamon Ding 			.cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7669ecc31b6eSAndy Yan 		},
7670ecc31b6eSAndy Yan 	},
7671ecc31b6eSAndy Yan 
7672ecc31b6eSAndy Yan };
7673ecc31b6eSAndy Yan 
76746fea745cSDamon Ding #define RK3588_PLANE_MASK_BASE \
76756fea745cSDamon Ding 	(BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
76766fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_CLUSTER2) | BIT(ROCKCHIP_VOP2_CLUSTER3) | \
76776fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART0)  | BIT(ROCKCHIP_VOP2_ESMART1)  | \
76786fea745cSDamon Ding 	 BIT(ROCKCHIP_VOP2_ESMART2)  | BIT(ROCKCHIP_VOP2_ESMART3))
76796fea745cSDamon Ding 
7680ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = {
7681ecc31b6eSAndy Yan 	{
7682ecc31b6eSAndy Yan 		.name = "Cluster0",
7683ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
7684ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER1,
7685ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
76866fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7687ecc31b6eSAndy Yan 		.win_sel_port_offset = 0,
76885fa6e665SDamon Ding 		.layer_sel_win_id = { 0, 0, 0, 0 },
7689ecc31b6eSAndy Yan 		.reg_offset = 0,
7690a33b790fSDamon Ding 		.axi_id = 0,
7691a33b790fSDamon Ding 		.axi_yrgb_id = 2,
7692a33b790fSDamon Ding 		.axi_uv_id = 3,
7693b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER0,
76945fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
76955fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
76965fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
76975fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
769813bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
76994c765862SDamon Ding 		.max_upscale_factor = 4,
77004c765862SDamon Ding 		.max_downscale_factor = 4,
77019c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7702ecc31b6eSAndy Yan 	},
7703ecc31b6eSAndy Yan 
7704ecc31b6eSAndy Yan 	{
7705ecc31b6eSAndy Yan 		.name = "Cluster1",
7706ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
7707ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
77086fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7709ecc31b6eSAndy Yan 		.win_sel_port_offset = 1,
77105fa6e665SDamon Ding 		.layer_sel_win_id = { 1, 1, 1, 1 },
7711ecc31b6eSAndy Yan 		.reg_offset = 0x200,
7712a33b790fSDamon Ding 		.axi_id = 0,
7713a33b790fSDamon Ding 		.axi_yrgb_id = 6,
7714a33b790fSDamon Ding 		.axi_uv_id = 7,
7715b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER1,
77165fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
77175fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77185fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
77195fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
772013bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77214c765862SDamon Ding 		.max_upscale_factor = 4,
77224c765862SDamon Ding 		.max_downscale_factor = 4,
77239c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7724ecc31b6eSAndy Yan 	},
7725ecc31b6eSAndy Yan 
7726ecc31b6eSAndy Yan 	{
7727ecc31b6eSAndy Yan 		.name = "Cluster2",
7728ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
7729ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
7730ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
77316fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7732ecc31b6eSAndy Yan 		.win_sel_port_offset = 2,
77335fa6e665SDamon Ding 		.layer_sel_win_id = { 4, 4, 4, 4 },
7734ecc31b6eSAndy Yan 		.reg_offset = 0x400,
7735a33b790fSDamon Ding 		.axi_id = 1,
7736a33b790fSDamon Ding 		.axi_yrgb_id = 2,
7737a33b790fSDamon Ding 		.axi_uv_id = 3,
7738b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER2,
77395fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
77405fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77415fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
77425fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
774313bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77444c765862SDamon Ding 		.max_upscale_factor = 4,
77454c765862SDamon Ding 		.max_downscale_factor = 4,
77469c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7747ecc31b6eSAndy Yan 	},
7748ecc31b6eSAndy Yan 
7749ecc31b6eSAndy Yan 	{
7750ecc31b6eSAndy Yan 		.name = "Cluster3",
7751ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
7752ecc31b6eSAndy Yan 		.type = CLUSTER_LAYER,
77536fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_OVERLAY,
7754ecc31b6eSAndy Yan 		.win_sel_port_offset = 3,
77555fa6e665SDamon Ding 		.layer_sel_win_id = { 5, 5, 5, 5 },
7756ecc31b6eSAndy Yan 		.reg_offset = 0x600,
7757a33b790fSDamon Ding 		.axi_id = 1,
7758a33b790fSDamon Ding 		.axi_yrgb_id = 6,
7759a33b790fSDamon Ding 		.axi_uv_id = 7,
7760b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_CLUSTER3,
77615fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
77625fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77635fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
77645fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
776513bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77664c765862SDamon Ding 		.max_upscale_factor = 4,
77674c765862SDamon Ding 		.max_downscale_factor = 4,
77689c7848c3SDamon Ding 		.dly = { 4, 26, 29, 4, 35, 3, 5 },
7769ecc31b6eSAndy Yan 	},
7770ecc31b6eSAndy Yan 
7771ecc31b6eSAndy Yan 	{
7772ecc31b6eSAndy Yan 		.name = "Esmart0",
7773ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART0,
7774ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART1,
7775ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
77766fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7777ecc31b6eSAndy Yan 		.win_sel_port_offset = 4,
77785fa6e665SDamon Ding 		.layer_sel_win_id = { 2, 2, 2, 2 },
7779ecc31b6eSAndy Yan 		.reg_offset = 0,
7780a33b790fSDamon Ding 		.axi_id = 0,
7781a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
7782a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
77835fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
77845fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77855fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
77865fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
778713bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77884c765862SDamon Ding 		.max_upscale_factor = 8,
77894c765862SDamon Ding 		.max_downscale_factor = 8,
77909c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7791ecc31b6eSAndy Yan 	},
7792ecc31b6eSAndy Yan 
7793ecc31b6eSAndy Yan 	{
7794ecc31b6eSAndy Yan 		.name = "Esmart1",
7795ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART1,
7796ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
77976fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7798ecc31b6eSAndy Yan 		.win_sel_port_offset = 5,
77995fa6e665SDamon Ding 		.layer_sel_win_id = { 3, 3, 3, 3 },
7800ecc31b6eSAndy Yan 		.reg_offset = 0x200,
7801a33b790fSDamon Ding 		.axi_id = 0,
7802a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
7803a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
7804b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
78055fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
78065fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
78075fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
78085fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
780913bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
78104c765862SDamon Ding 		.max_upscale_factor = 8,
78114c765862SDamon Ding 		.max_downscale_factor = 8,
78129c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7813ecc31b6eSAndy Yan 	},
7814ecc31b6eSAndy Yan 
7815ecc31b6eSAndy Yan 	{
7816ecc31b6eSAndy Yan 		.name = "Esmart2",
7817ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART2,
7818ee01dbb2SDamon Ding 		.splice_win_id = ROCKCHIP_VOP2_ESMART3,
7819ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
78206fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7821ecc31b6eSAndy Yan 		.win_sel_port_offset = 6,
78225fa6e665SDamon Ding 		.layer_sel_win_id = { 6, 6, 6, 6 },
7823ecc31b6eSAndy Yan 		.reg_offset = 0x400,
7824a33b790fSDamon Ding 		.axi_id = 1,
7825a33b790fSDamon Ding 		.axi_yrgb_id = 0x0a,
7826a33b790fSDamon Ding 		.axi_uv_id = 0x0b,
7827b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
78285fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
78295fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
78305fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
78315fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
783213bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
78334c765862SDamon Ding 		.max_upscale_factor = 8,
78344c765862SDamon Ding 		.max_downscale_factor = 8,
78359c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7836ecc31b6eSAndy Yan 	},
7837ecc31b6eSAndy Yan 
7838ecc31b6eSAndy Yan 	{
7839ecc31b6eSAndy Yan 		.name = "Esmart3",
7840ecc31b6eSAndy Yan 		.phys_id = ROCKCHIP_VOP2_ESMART3,
7841ecc31b6eSAndy Yan 		.type = ESMART_LAYER,
78426fea745cSDamon Ding 		.plane_type = VOP2_PLANE_TYPE_PRIMARY,
7843ecc31b6eSAndy Yan 		.win_sel_port_offset = 7,
78445fa6e665SDamon Ding 		.layer_sel_win_id = { 7, 7, 7, 7 },
7845ecc31b6eSAndy Yan 		.reg_offset = 0x600,
7846a33b790fSDamon Ding 		.axi_id = 1,
7847a33b790fSDamon Ding 		.axi_yrgb_id = 0x0c,
7848a33b790fSDamon Ding 		.axi_uv_id = 0x0d,
7849b6ba80b4SDamon Ding 		.pd_id = VOP2_PD_ESMART,
78505fa6e665SDamon Ding 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
78515fa6e665SDamon Ding 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
78525fa6e665SDamon Ding 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
78535fa6e665SDamon Ding 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
785413bc92e8SDamon Ding 		.possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
78554c765862SDamon Ding 		.max_upscale_factor = 8,
78564c765862SDamon Ding 		.max_downscale_factor = 8,
78579c7848c3SDamon Ding 		.dly = { 23, 45, 48, 23, 54, 22, 24 },
7858ecc31b6eSAndy Yan 	},
7859ecc31b6eSAndy Yan };
7860ecc31b6eSAndy Yan 
786112ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = {
786212ee5af0SDamon Ding 	{0x00000000, "no error detected by DSC encoder"},
786312ee5af0SDamon Ding 	{0x0030ffff, "bits per component error"},
786412ee5af0SDamon Ding 	{0x0040ffff, "multiple mode error"},
786512ee5af0SDamon Ding 	{0x0050ffff, "line buffer depth error"},
786612ee5af0SDamon Ding 	{0x0060ffff, "minor version error"},
786712ee5af0SDamon Ding 	{0x0070ffff, "picture height error"},
786812ee5af0SDamon Ding 	{0x0080ffff, "picture width error"},
786912ee5af0SDamon Ding 	{0x0090ffff, "number of slices error"},
787012ee5af0SDamon Ding 	{0x00c0ffff, "slice height Error "},
787112ee5af0SDamon Ding 	{0x00d0ffff, "slice width error"},
787212ee5af0SDamon Ding 	{0x00e0ffff, "second line BPG offset error"},
787312ee5af0SDamon Ding 	{0x00f0ffff, "non second line BPG offset error"},
787412ee5af0SDamon Ding 	{0x0100ffff, "PPS ID error"},
787512ee5af0SDamon Ding 	{0x0110ffff, "bits per pixel (BPP) Error"},
787612ee5af0SDamon Ding 	{0x0120ffff, "buffer flow error"},  /* dsc_buffer_flow */
787712ee5af0SDamon Ding 
787812ee5af0SDamon Ding 	{0x01510001, "slice 0 RC buffer model overflow error"},
787912ee5af0SDamon Ding 	{0x01510002, "slice 1 RC buffer model overflow error"},
788012ee5af0SDamon Ding 	{0x01510004, "slice 2 RC buffer model overflow error"},
788112ee5af0SDamon Ding 	{0x01510008, "slice 3 RC buffer model overflow error"},
788212ee5af0SDamon Ding 	{0x01510010, "slice 4 RC buffer model overflow error"},
788312ee5af0SDamon Ding 	{0x01510020, "slice 5 RC buffer model overflow error"},
788412ee5af0SDamon Ding 	{0x01510040, "slice 6 RC buffer model overflow error"},
788512ee5af0SDamon Ding 	{0x01510080, "slice 7 RC buffer model overflow error"},
788612ee5af0SDamon Ding 
788712ee5af0SDamon Ding 	{0x01610001, "slice 0 RC buffer model underflow error"},
788812ee5af0SDamon Ding 	{0x01610002, "slice 1 RC buffer model underflow error"},
788912ee5af0SDamon Ding 	{0x01610004, "slice 2 RC buffer model underflow error"},
789012ee5af0SDamon Ding 	{0x01610008, "slice 3 RC buffer model underflow error"},
789112ee5af0SDamon Ding 	{0x01610010, "slice 4 RC buffer model underflow error"},
789212ee5af0SDamon Ding 	{0x01610020, "slice 5 RC buffer model underflow error"},
789312ee5af0SDamon Ding 	{0x01610040, "slice 6 RC buffer model underflow error"},
789412ee5af0SDamon Ding 	{0x01610080, "slice 7 RC buffer model underflow error"},
789512ee5af0SDamon Ding 
789612ee5af0SDamon Ding 	{0xffffffff, "unsuccessful RESET cycle status"},
789712ee5af0SDamon Ding 	{0x00a0ffff, "ICH full error precision settings error"},
789812ee5af0SDamon Ding 	{0x0020ffff, "native mode"},
789912ee5af0SDamon Ding };
790012ee5af0SDamon Ding 
790112ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = {
790212ee5af0SDamon Ding 	{0x00000000, "rate buffer status"},
790312ee5af0SDamon Ding 	{0x00000001, "line buffer status"},
790412ee5af0SDamon Ding 	{0x00000002, "decoder model status"},
790512ee5af0SDamon Ding 	{0x00000003, "pixel buffer status"},
790612ee5af0SDamon Ding 	{0x00000004, "balance fifo buffer status"},
790712ee5af0SDamon Ding 	{0x00000005, "syntax element fifo status"},
790812ee5af0SDamon Ding };
790912ee5af0SDamon Ding 
791012ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = {
791112ee5af0SDamon Ding 	{
791212ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_8K,
791312ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_8K,
791412ee5af0SDamon Ding 		.max_slice_num = 8,
791512ee5af0SDamon Ding 		.max_linebuf_depth = 11,
7916b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
791712ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
791812ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_8k_txp_clk",
791912ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_8k_pxl_clk",
792012ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_8k_cds_clk",
792112ee5af0SDamon Ding 	},
792212ee5af0SDamon Ding 
792312ee5af0SDamon Ding 	{
792412ee5af0SDamon Ding 		.id = ROCKCHIP_VOP2_DSC_4K,
792512ee5af0SDamon Ding 		.pd_id = VOP2_PD_DSC_4K,
792612ee5af0SDamon Ding 		.max_slice_num = 2,
792712ee5af0SDamon Ding 		.max_linebuf_depth = 11,
7928b61227a3SDamon Ding 		.min_bits_per_pixel = 8,
792912ee5af0SDamon Ding 		.dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
793012ee5af0SDamon Ding 		.dsc_txp_clk_name = "dsc_4k_txp_clk",
793112ee5af0SDamon Ding 		.dsc_pxl_clk_name = "dsc_4k_pxl_clk",
793212ee5af0SDamon Ding 		.dsc_cds_clk_name = "dsc_4k_cds_clk",
793312ee5af0SDamon Ding 	},
793412ee5af0SDamon Ding };
793512ee5af0SDamon Ding 
7936ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = {
7937ecc31b6eSAndy Yan 	{
7938ee01dbb2SDamon Ding 		.splice_vp_id = 1,
7939ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7940b890760eSAlgea Cao 		.pre_scan_max_dly = 54,
7941ecc31b6eSAndy Yan 		.max_dclk = 600000,
7942ecc31b6eSAndy Yan 		.max_output = {7680, 4320},
7943ecc31b6eSAndy Yan 	},
7944ecc31b6eSAndy Yan 	{
7945ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7946ee01dbb2SDamon Ding 		.pre_scan_max_dly = 54,
7947ecc31b6eSAndy Yan 		.max_dclk = 600000,
7948ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
7949ecc31b6eSAndy Yan 	},
7950ecc31b6eSAndy Yan 	{
7951ecc31b6eSAndy Yan 		.feature = VOP_FEATURE_OUTPUT_10BIT,
7952ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
7953ecc31b6eSAndy Yan 		.max_dclk = 600000,
7954ecc31b6eSAndy Yan 		.max_output = {4096, 2304},
7955ecc31b6eSAndy Yan 	},
7956ecc31b6eSAndy Yan 	{
7957ecc31b6eSAndy Yan 		.feature = 0,
7958ecc31b6eSAndy Yan 		.pre_scan_max_dly = 52,
7959ecc31b6eSAndy Yan 		.max_dclk = 200000,
7960ecc31b6eSAndy Yan 		.max_output = {1920, 1080},
7961ecc31b6eSAndy Yan 	},
7962ecc31b6eSAndy Yan };
7963ecc31b6eSAndy Yan 
7964b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = {
7965b6ba80b4SDamon Ding 	{
7966b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER0,
7967b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0),
7968b6ba80b4SDamon Ding 	},
7969b6ba80b4SDamon Ding 	{
7970b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER1,
7971b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1),
7972b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7973b6ba80b4SDamon Ding 	},
7974b6ba80b4SDamon Ding 	{
7975b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER2,
7976b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2),
7977b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7978b6ba80b4SDamon Ding 	},
7979b6ba80b4SDamon Ding 	{
7980b6ba80b4SDamon Ding 	  .id = VOP2_PD_CLUSTER3,
7981b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3),
7982b6ba80b4SDamon Ding 	  .parent_id = VOP2_PD_CLUSTER0,
7983b6ba80b4SDamon Ding 	},
7984b6ba80b4SDamon Ding 	{
7985b6ba80b4SDamon Ding 	  .id = VOP2_PD_ESMART,
7986b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) |
7987b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART2) |
7988b6ba80b4SDamon Ding 			    BIT(ROCKCHIP_VOP2_ESMART3),
7989b6ba80b4SDamon Ding 	},
7990b6ba80b4SDamon Ding 	{
7991b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_8K,
7992b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K),
7993b6ba80b4SDamon Ding 	},
7994b6ba80b4SDamon Ding 	{
7995b6ba80b4SDamon Ding 	  .id = VOP2_PD_DSC_4K,
7996b6ba80b4SDamon Ding 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K),
7997b6ba80b4SDamon Ding 	},
7998b6ba80b4SDamon Ding };
7999b6ba80b4SDamon Ding 
80009c7848c3SDamon Ding static const struct vop2_ops rk3588_vop_ops = {
80019c7848c3SDamon Ding 	.setup_win_dly = rk3568_setup_win_dly,
8002b7195f56SDamon Ding 	.setup_overlay = rk3568_setup_overlay,
8003ef0607a7SDamon Ding 	.assign_plane_mask = rk3568_assign_plane_mask,
80049c7848c3SDamon Ding };
80059c7848c3SDamon Ding 
8006ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = {
8007ecc31b6eSAndy Yan 	.version = VOP_VERSION_RK3588,
8008ecc31b6eSAndy Yan 	.nr_vps = 4,
8009ecc31b6eSAndy Yan 	.vp_data = rk3588_vp_data,
8010ecc31b6eSAndy Yan 	.win_data = rk3588_win_data,
8011ecc31b6eSAndy Yan 	.plane_mask = rk3588_vp_plane_mask[0],
80126fea745cSDamon Ding 	.plane_mask_base = RK3588_PLANE_MASK_BASE,
8013b6ba80b4SDamon Ding 	.pd = rk3588_vop_pd_data,
801412ee5af0SDamon Ding 	.dsc = rk3588_dsc_data,
801512ee5af0SDamon Ding 	.dsc_error_ecw = dsc_ecw,
801612ee5af0SDamon Ding 	.dsc_error_buffer_flow = dsc_buffer_flow,
8017ecc31b6eSAndy Yan 	.nr_layers = 8,
8018ecc31b6eSAndy Yan 	.nr_mixers = 7,
8019ecc31b6eSAndy Yan 	.nr_gammas = 4,
8020b6ba80b4SDamon Ding 	.nr_pd = ARRAY_SIZE(rk3588_vop_pd_data),
802112ee5af0SDamon Ding 	.nr_dscs = 2,
802212ee5af0SDamon Ding 	.nr_dsc_ecw = ARRAY_SIZE(dsc_ecw),
802312ee5af0SDamon Ding 	.nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow),
802472388c26SDamon Ding 	.dump_regs = rk3588_dump_regs,
802572388c26SDamon Ding 	.dump_regs_size = ARRAY_SIZE(rk3588_dump_regs),
80269c7848c3SDamon Ding 	.ops = &rk3588_vop_ops,
8027ecc31b6eSAndy Yan };
8028ecc31b6eSAndy Yan 
8029d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
8030*60e6e79dSSandy Huang 	.reset = rockchip_vop2_reset,
8031d0408543SAndy Yan 	.preinit = rockchip_vop2_preinit,
8032d0408543SAndy Yan 	.prepare = rockchip_vop2_prepare,
8033d0408543SAndy Yan 	.init = rockchip_vop2_init,
8034d0408543SAndy Yan 	.set_plane = rockchip_vop2_set_plane,
8035d0408543SAndy Yan 	.enable = rockchip_vop2_enable,
8036efa01fe4SZhang Yubing 	.post_enable = rockchip_vop2_post_enable,
8037d0408543SAndy Yan 	.disable = rockchip_vop2_disable,
8038b0989546SSandy Huang 	.fixup_dts = rockchip_vop2_fixup_dts,
80390675a2a4SDamon Ding 	.send_mcu_cmd = rockchip_vop2_send_mcu_cmd,
8040820a5c17SDamon Ding 	.check = rockchip_vop2_check,
804122007755SDamon Ding 	.mode_valid = rockchip_vop2_mode_valid,
8042b02eb70bSDamon Ding 	.mode_fixup = rockchip_vop2_mode_fixup,
80434c765862SDamon Ding 	.plane_check = rockchip_vop2_plane_check,
804472388c26SDamon Ding 	.regs_dump = rockchip_vop2_regs_dump,
804572388c26SDamon Ding 	.active_regs_dump = rockchip_vop2_active_regs_dump,
80468e7ef808SDamon Ding 	.apply_soft_te = rockchip_vop2_apply_soft_te,
8047d0408543SAndy Yan };
8048