xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/rockchip_vop2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <config.h>
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <malloc.h>
11*4882a593Smuzhiyun #include <fdtdec.h>
12*4882a593Smuzhiyun #include <fdt_support.h>
13*4882a593Smuzhiyun #include <regmap.h>
14*4882a593Smuzhiyun #include <asm/arch/cpu.h>
15*4882a593Smuzhiyun #include <asm/unaligned.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <linux/list.h>
18*4882a593Smuzhiyun #include <linux/log2.h>
19*4882a593Smuzhiyun #include <linux/media-bus-format.h>
20*4882a593Smuzhiyun #include <asm/arch/clock.h>
21*4882a593Smuzhiyun #include <asm/gpio.h>
22*4882a593Smuzhiyun #include <linux/err.h>
23*4882a593Smuzhiyun #include <linux/ioport.h>
24*4882a593Smuzhiyun #include <dm/device.h>
25*4882a593Smuzhiyun #include <dm/read.h>
26*4882a593Smuzhiyun #include <dm/ofnode.h>
27*4882a593Smuzhiyun #include <fixp-arith.h>
28*4882a593Smuzhiyun #include <syscon.h>
29*4882a593Smuzhiyun #include <linux/iopoll.h>
30*4882a593Smuzhiyun #include <dm/uclass-internal.h>
31*4882a593Smuzhiyun #include <stdlib.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include "rockchip_display.h"
34*4882a593Smuzhiyun #include "rockchip_crtc.h"
35*4882a593Smuzhiyun #include "rockchip_connector.h"
36*4882a593Smuzhiyun #include "rockchip_phy.h"
37*4882a593Smuzhiyun #include "rockchip_post_csc.h"
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* System registers definition */
40*4882a593Smuzhiyun #define RK3568_REG_CFG_DONE			0x000
41*4882a593Smuzhiyun #define	CFG_DONE_EN				BIT(15)
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define RK3568_VERSION_INFO			0x004
44*4882a593Smuzhiyun #define EN_MASK					1
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define RK3568_AUTO_GATING_CTRL			0x008
47*4882a593Smuzhiyun #define AUTO_GATING_EN_SHIFT			31
48*4882a593Smuzhiyun #define PORT_DCLK_AUTO_GATING_EN_SHIFT		14
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define RK3568_SYS_AXI_LUT_CTRL			0x024
51*4882a593Smuzhiyun #define LUT_DMA_EN_SHIFT			0
52*4882a593Smuzhiyun #define DSP_VS_T_SEL_SHIFT			16
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #define RK3568_DSP_IF_EN			0x028
55*4882a593Smuzhiyun #define RGB_EN_SHIFT				0
56*4882a593Smuzhiyun #define RK3588_DP0_EN_SHIFT			0
57*4882a593Smuzhiyun #define RK3588_DP1_EN_SHIFT			1
58*4882a593Smuzhiyun #define RK3588_RGB_EN_SHIFT			8
59*4882a593Smuzhiyun #define HDMI0_EN_SHIFT				1
60*4882a593Smuzhiyun #define EDP0_EN_SHIFT				3
61*4882a593Smuzhiyun #define RK3588_EDP0_EN_SHIFT			2
62*4882a593Smuzhiyun #define RK3588_HDMI0_EN_SHIFT			3
63*4882a593Smuzhiyun #define MIPI0_EN_SHIFT				4
64*4882a593Smuzhiyun #define RK3588_EDP1_EN_SHIFT			4
65*4882a593Smuzhiyun #define RK3588_HDMI1_EN_SHIFT			5
66*4882a593Smuzhiyun #define RK3588_MIPI0_EN_SHIFT                   6
67*4882a593Smuzhiyun #define MIPI1_EN_SHIFT				20
68*4882a593Smuzhiyun #define RK3588_MIPI1_EN_SHIFT                   7
69*4882a593Smuzhiyun #define LVDS0_EN_SHIFT				5
70*4882a593Smuzhiyun #define LVDS1_EN_SHIFT				24
71*4882a593Smuzhiyun #define BT1120_EN_SHIFT				6
72*4882a593Smuzhiyun #define BT656_EN_SHIFT				7
73*4882a593Smuzhiyun #define IF_MUX_MASK				3
74*4882a593Smuzhiyun #define RGB_MUX_SHIFT				8
75*4882a593Smuzhiyun #define HDMI0_MUX_SHIFT				10
76*4882a593Smuzhiyun #define RK3588_DP0_MUX_SHIFT			12
77*4882a593Smuzhiyun #define RK3588_DP1_MUX_SHIFT			14
78*4882a593Smuzhiyun #define EDP0_MUX_SHIFT				14
79*4882a593Smuzhiyun #define RK3588_HDMI_EDP0_MUX_SHIFT		16
80*4882a593Smuzhiyun #define RK3588_HDMI_EDP1_MUX_SHIFT		18
81*4882a593Smuzhiyun #define MIPI0_MUX_SHIFT				16
82*4882a593Smuzhiyun #define RK3588_MIPI0_MUX_SHIFT			20
83*4882a593Smuzhiyun #define MIPI1_MUX_SHIFT				21
84*4882a593Smuzhiyun #define LVDS0_MUX_SHIFT				18
85*4882a593Smuzhiyun #define LVDS1_MUX_SHIFT				25
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun #define RK3568_DSP_IF_CTRL			0x02c
88*4882a593Smuzhiyun #define LVDS_DUAL_EN_SHIFT			0
89*4882a593Smuzhiyun #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT		1
90*4882a593Smuzhiyun #define LVDS_DUAL_SWAP_EN_SHIFT			2
91*4882a593Smuzhiyun #define BT656_UV_SWAP				4
92*4882a593Smuzhiyun #define BT656_YC_SWAP				5
93*4882a593Smuzhiyun #define BT656_DCLK_POL				6
94*4882a593Smuzhiyun #define RK3588_HDMI_DUAL_EN_SHIFT		8
95*4882a593Smuzhiyun #define RK3588_EDP_DUAL_EN_SHIFT		8
96*4882a593Smuzhiyun #define RK3588_DP_DUAL_EN_SHIFT			9
97*4882a593Smuzhiyun #define RK3568_MIPI_DUAL_EN_SHIFT		10
98*4882a593Smuzhiyun #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT		11
99*4882a593Smuzhiyun #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT		12
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun #define RK3568_DSP_IF_POL			0x030
102*4882a593Smuzhiyun #define IF_CTRL_REG_DONE_IMD_MASK		1
103*4882a593Smuzhiyun #define IF_CTRL_REG_DONE_IMD_SHIFT		28
104*4882a593Smuzhiyun #define IF_CRTL_MIPI_DCLK_POL_SHIT		19
105*4882a593Smuzhiyun #define IF_CRTL_EDP_DCLK_POL_SHIT		15
106*4882a593Smuzhiyun #define IF_CTRL_EDP_PIN_POL_MASK		0x7
107*4882a593Smuzhiyun #define IF_CTRL_EDP_PIN_POL_SHIFT		12
108*4882a593Smuzhiyun #define IF_CRTL_HDMI_DCLK_POL_SHIT		7
109*4882a593Smuzhiyun #define IF_CRTL_HDMI_PIN_POL_MASK		0x7
110*4882a593Smuzhiyun #define IF_CRTL_HDMI_PIN_POL_SHIT		4
111*4882a593Smuzhiyun #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT		3
112*4882a593Smuzhiyun #define IF_CTRL_RGB_LVDS_PIN_POL_MASK		0x7
113*4882a593Smuzhiyun #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT		0
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun #define RK3562_MIPI_DCLK_POL_SHIFT		15
116*4882a593Smuzhiyun #define RK3562_MIPI_PIN_POL_SHIFT		12
117*4882a593Smuzhiyun #define RK3562_IF_PIN_POL_MASK			0x7
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #define RK3588_DP0_PIN_POL_SHIFT		8
120*4882a593Smuzhiyun #define RK3588_DP1_PIN_POL_SHIFT		12
121*4882a593Smuzhiyun #define RK3588_IF_PIN_POL_MASK			0x7
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun #define HDMI_EDP0_DCLK_DIV_SHIFT		16
124*4882a593Smuzhiyun #define HDMI_EDP0_PIXCLK_DIV_SHIFT		18
125*4882a593Smuzhiyun #define HDMI_EDP1_DCLK_DIV_SHIFT		20
126*4882a593Smuzhiyun #define HDMI_EDP1_PIXCLK_DIV_SHIFT		22
127*4882a593Smuzhiyun #define MIPI0_PIXCLK_DIV_SHIFT			24
128*4882a593Smuzhiyun #define MIPI1_PIXCLK_DIV_SHIFT			26
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun #define RK3568_SYS_OTP_WIN_EN			0x50
131*4882a593Smuzhiyun #define OTP_WIN_EN_SHIFT			0
132*4882a593Smuzhiyun #define RK3568_SYS_LUT_PORT_SEL			0x58
133*4882a593Smuzhiyun #define GAMMA_PORT_SEL_MASK			0x3
134*4882a593Smuzhiyun #define GAMMA_PORT_SEL_SHIFT			0
135*4882a593Smuzhiyun #define GAMMA_AHB_WRITE_SEL_MASK		0x3
136*4882a593Smuzhiyun #define GAMMA_AHB_WRITE_SEL_SHIFT		12
137*4882a593Smuzhiyun #define PORT_MERGE_EN_SHIFT			16
138*4882a593Smuzhiyun #define ESMART_LB_MODE_SEL_MASK			0x3
139*4882a593Smuzhiyun #define ESMART_LB_MODE_SEL_SHIFT		26
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun #define RK3568_SYS_PD_CTRL			0x034
142*4882a593Smuzhiyun #define RK3568_VP0_LINE_FLAG			0x70
143*4882a593Smuzhiyun #define RK3568_VP1_LINE_FLAG			0x74
144*4882a593Smuzhiyun #define RK3568_VP2_LINE_FLAG			0x78
145*4882a593Smuzhiyun #define RK3568_SYS0_INT_EN			0x80
146*4882a593Smuzhiyun #define RK3568_SYS0_INT_CLR			0x84
147*4882a593Smuzhiyun #define RK3568_SYS0_INT_STATUS			0x88
148*4882a593Smuzhiyun #define RK3568_SYS1_INT_EN			0x90
149*4882a593Smuzhiyun #define RK3568_SYS1_INT_CLR			0x94
150*4882a593Smuzhiyun #define RK3568_SYS1_INT_STATUS			0x98
151*4882a593Smuzhiyun #define RK3568_VP0_INT_EN			0xA0
152*4882a593Smuzhiyun #define RK3568_VP0_INT_CLR			0xA4
153*4882a593Smuzhiyun #define RK3568_VP0_INT_STATUS			0xA8
154*4882a593Smuzhiyun #define RK3568_VP1_INT_EN			0xB0
155*4882a593Smuzhiyun #define RK3568_VP1_INT_CLR			0xB4
156*4882a593Smuzhiyun #define RK3568_VP1_INT_STATUS			0xB8
157*4882a593Smuzhiyun #define RK3568_VP2_INT_EN			0xC0
158*4882a593Smuzhiyun #define RK3568_VP2_INT_CLR			0xC4
159*4882a593Smuzhiyun #define RK3568_VP2_INT_STATUS			0xC8
160*4882a593Smuzhiyun #define RK3588_CLUSTER0_PD_EN_SHIFT		0
161*4882a593Smuzhiyun #define RK3588_CLUSTER1_PD_EN_SHIFT		1
162*4882a593Smuzhiyun #define RK3588_CLUSTER2_PD_EN_SHIFT		2
163*4882a593Smuzhiyun #define RK3588_CLUSTER3_PD_EN_SHIFT		3
164*4882a593Smuzhiyun #define RK3588_DSC_8K_PD_EN_SHIFT		5
165*4882a593Smuzhiyun #define RK3588_DSC_4K_PD_EN_SHIFT		6
166*4882a593Smuzhiyun #define RK3588_ESMART_PD_EN_SHIFT		7
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun #define RK3588_SYS_VAR_FREQ_CTRL		0x038
169*4882a593Smuzhiyun #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT	20
170*4882a593Smuzhiyun #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT		24
171*4882a593Smuzhiyun #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT	28
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun #define RK3568_SYS_STATUS0			0x60
174*4882a593Smuzhiyun #define RK3588_CLUSTER0_PD_STATUS_SHIFT		8
175*4882a593Smuzhiyun #define RK3588_CLUSTER1_PD_STATUS_SHIFT		9
176*4882a593Smuzhiyun #define RK3588_CLUSTER2_PD_STATUS_SHIFT		10
177*4882a593Smuzhiyun #define RK3588_CLUSTER3_PD_STATUS_SHIFT		11
178*4882a593Smuzhiyun #define RK3588_DSC_8K_PD_STATUS_SHIFT		13
179*4882a593Smuzhiyun #define RK3588_DSC_4K_PD_STATUS_SHIFT		14
180*4882a593Smuzhiyun #define RK3588_ESMART_PD_STATUS_SHIFT		15
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun #define RK3568_SYS_CTRL_LINE_FLAG0		0x70
183*4882a593Smuzhiyun #define LINE_FLAG_NUM_MASK			0x1fff
184*4882a593Smuzhiyun #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT		0
185*4882a593Smuzhiyun #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT		16
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /* DSC CTRL registers definition */
188*4882a593Smuzhiyun #define RK3588_DSC_8K_SYS_CTRL			0x200
189*4882a593Smuzhiyun #define DSC_PORT_SEL_MASK			0x3
190*4882a593Smuzhiyun #define DSC_PORT_SEL_SHIFT			0
191*4882a593Smuzhiyun #define DSC_MAN_MODE_MASK			0x1
192*4882a593Smuzhiyun #define DSC_MAN_MODE_SHIFT			2
193*4882a593Smuzhiyun #define DSC_INTERFACE_MODE_MASK			0x3
194*4882a593Smuzhiyun #define DSC_INTERFACE_MODE_SHIFT		4
195*4882a593Smuzhiyun #define DSC_PIXEL_NUM_MASK			0x3
196*4882a593Smuzhiyun #define DSC_PIXEL_NUM_SHIFT			6
197*4882a593Smuzhiyun #define DSC_PXL_CLK_DIV_MASK			0x1
198*4882a593Smuzhiyun #define DSC_PXL_CLK_DIV_SHIFT			8
199*4882a593Smuzhiyun #define DSC_CDS_CLK_DIV_MASK			0x3
200*4882a593Smuzhiyun #define DSC_CDS_CLK_DIV_SHIFT			12
201*4882a593Smuzhiyun #define DSC_TXP_CLK_DIV_MASK			0x3
202*4882a593Smuzhiyun #define DSC_TXP_CLK_DIV_SHIFT			14
203*4882a593Smuzhiyun #define DSC_INIT_DLY_MODE_MASK			0x1
204*4882a593Smuzhiyun #define DSC_INIT_DLY_MODE_SHIFT			16
205*4882a593Smuzhiyun #define DSC_SCAN_EN_SHIFT			17
206*4882a593Smuzhiyun #define DSC_HALT_EN_SHIFT			18
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun #define RK3588_DSC_8K_RST			0x204
209*4882a593Smuzhiyun #define RST_DEASSERT_MASK			0x1
210*4882a593Smuzhiyun #define RST_DEASSERT_SHIFT			0
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun #define RK3588_DSC_8K_CFG_DONE			0x208
213*4882a593Smuzhiyun #define DSC_CFG_DONE_SHIFT			0
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun #define RK3588_DSC_8K_INIT_DLY			0x20C
216*4882a593Smuzhiyun #define DSC_INIT_DLY_NUM_MASK			0xffff
217*4882a593Smuzhiyun #define DSC_INIT_DLY_NUM_SHIFT			0
218*4882a593Smuzhiyun #define SCAN_TIMING_PARA_IMD_EN_SHIFT		16
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun #define RK3588_DSC_8K_HTOTAL_HS_END		0x210
221*4882a593Smuzhiyun #define DSC_HTOTAL_PW_MASK			0xffffffff
222*4882a593Smuzhiyun #define DSC_HTOTAL_PW_SHIFT			0
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun #define RK3588_DSC_8K_HACT_ST_END		0x214
225*4882a593Smuzhiyun #define DSC_HACT_ST_END_MASK			0xffffffff
226*4882a593Smuzhiyun #define DSC_HACT_ST_END_SHIFT			0
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun #define RK3588_DSC_8K_VTOTAL_VS_END		0x218
229*4882a593Smuzhiyun #define DSC_VTOTAL_PW_MASK			0xffffffff
230*4882a593Smuzhiyun #define DSC_VTOTAL_PW_SHIFT			0
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun #define RK3588_DSC_8K_VACT_ST_END		0x21C
233*4882a593Smuzhiyun #define DSC_VACT_ST_END_MASK			0xffffffff
234*4882a593Smuzhiyun #define DSC_VACT_ST_END_SHIFT			0
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun #define RK3588_DSC_8K_STATUS			0x220
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun /* Overlay registers definition    */
239*4882a593Smuzhiyun #define RK3528_OVL_SYS				0x500
240*4882a593Smuzhiyun #define RK3528_OVL_SYS_PORT_SEL_IMD		0x504
241*4882a593Smuzhiyun #define RK3528_OVL_SYS_GATING_EN_IMD		0x508
242*4882a593Smuzhiyun #define RK3528_OVL_SYS_CLUSTER0_CTRL		0x510
243*4882a593Smuzhiyun #define RK3528_OVL_SYS_ESMART0_CTRL		0x520
244*4882a593Smuzhiyun #define ESMART_DLY_NUM_MASK			0xff
245*4882a593Smuzhiyun #define ESMART_DLY_NUM_SHIFT			0
246*4882a593Smuzhiyun #define RK3528_OVL_SYS_ESMART1_CTRL		0x524
247*4882a593Smuzhiyun #define RK3528_OVL_SYS_ESMART2_CTRL		0x528
248*4882a593Smuzhiyun #define RK3528_OVL_SYS_ESMART3_CTRL		0x52C
249*4882a593Smuzhiyun #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL	0x530
250*4882a593Smuzhiyun #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL	0x534
251*4882a593Smuzhiyun #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x538
252*4882a593Smuzhiyun #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL	0x53c
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun #define RK3528_OVL_PORT0_CTRL			0x600
255*4882a593Smuzhiyun #define RK3568_OVL_CTRL				0x600
256*4882a593Smuzhiyun #define OVL_MODE_SEL_MASK			0x1
257*4882a593Smuzhiyun #define OVL_MODE_SEL_SHIFT			0
258*4882a593Smuzhiyun #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
259*4882a593Smuzhiyun #define RK3528_OVL_PORT0_LAYER_SEL		0x604
260*4882a593Smuzhiyun #define RK3568_OVL_LAYER_SEL			0x604
261*4882a593Smuzhiyun #define LAYER_SEL_MASK				0xf
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun #define RK3568_OVL_PORT_SEL			0x608
264*4882a593Smuzhiyun #define PORT_MUX_MASK				0xf
265*4882a593Smuzhiyun #define PORT_MUX_SHIFT				0
266*4882a593Smuzhiyun #define LAYER_SEL_PORT_MASK			0x3
267*4882a593Smuzhiyun #define LAYER_SEL_PORT_SHIFT			16
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
270*4882a593Smuzhiyun #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
271*4882a593Smuzhiyun #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
272*4882a593Smuzhiyun #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
273*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL	0x620
274*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL	0x624
275*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL	0x628
276*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL	0x62C
277*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL	0x630
278*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL	0x634
279*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL	0x638
280*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL	0x63C
281*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL	0x640
282*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL	0x644
283*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL	0x648
284*4882a593Smuzhiyun #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL	0x64C
285*4882a593Smuzhiyun #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
286*4882a593Smuzhiyun #define RK3568_MIX0_DST_COLOR_CTRL		0x654
287*4882a593Smuzhiyun #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
288*4882a593Smuzhiyun #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
289*4882a593Smuzhiyun #define RK3528_HDR_SRC_COLOR_CTRL		0x660
290*4882a593Smuzhiyun #define RK3528_HDR_DST_COLOR_CTRL		0x664
291*4882a593Smuzhiyun #define RK3528_HDR_SRC_ALPHA_CTRL		0x668
292*4882a593Smuzhiyun #define RK3528_HDR_DST_ALPHA_CTRL		0x66C
293*4882a593Smuzhiyun #define RK3528_OVL_PORT0_BG_MIX_CTRL		0x670
294*4882a593Smuzhiyun #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
295*4882a593Smuzhiyun #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
296*4882a593Smuzhiyun #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
297*4882a593Smuzhiyun #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
298*4882a593Smuzhiyun #define RK3568_VP0_BG_MIX_CTRL			0x6E0
299*4882a593Smuzhiyun #define BG_MIX_CTRL_MASK			0xff
300*4882a593Smuzhiyun #define BG_MIX_CTRL_SHIFT			24
301*4882a593Smuzhiyun #define RK3568_VP1_BG_MIX_CTRL			0x6E4
302*4882a593Smuzhiyun #define RK3568_VP2_BG_MIX_CTRL			0x6E8
303*4882a593Smuzhiyun #define RK3568_CLUSTER_DLY_NUM			0x6F0
304*4882a593Smuzhiyun #define RK3568_SMART_DLY_NUM			0x6F8
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun #define RK3528_OVL_PORT1_CTRL			0x700
307*4882a593Smuzhiyun #define RK3528_OVL_PORT1_LAYER_SEL		0x704
308*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL	0x720
309*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL	0x724
310*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL	0x728
311*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL	0x72C
312*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL	0x730
313*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL	0x734
314*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL	0x738
315*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL	0x73C
316*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL	0x740
317*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL	0x744
318*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL	0x748
319*4882a593Smuzhiyun #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL	0x74C
320*4882a593Smuzhiyun #define RK3528_OVL_PORT1_BG_MIX_CTRL		0x770
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun /* Video Port registers definition */
323*4882a593Smuzhiyun #define RK3568_VP0_DSP_CTRL			0xC00
324*4882a593Smuzhiyun #define OUT_MODE_MASK				0xf
325*4882a593Smuzhiyun #define OUT_MODE_SHIFT				0
326*4882a593Smuzhiyun #define DATA_SWAP_MASK				0x1f
327*4882a593Smuzhiyun #define DATA_SWAP_SHIFT				8
328*4882a593Smuzhiyun #define DSP_BG_SWAP				0x1
329*4882a593Smuzhiyun #define DSP_RB_SWAP				0x2
330*4882a593Smuzhiyun #define DSP_RG_SWAP				0x4
331*4882a593Smuzhiyun #define DSP_DELTA_SWAP				0x8
332*4882a593Smuzhiyun #define CORE_DCLK_DIV_EN_SHIFT			4
333*4882a593Smuzhiyun #define P2I_EN_SHIFT				5
334*4882a593Smuzhiyun #define DSP_FILED_POL				6
335*4882a593Smuzhiyun #define INTERLACE_EN_SHIFT			7
336*4882a593Smuzhiyun #define DSP_X_MIR_EN_SHIFT			13
337*4882a593Smuzhiyun #define POST_DSP_OUT_R2Y_SHIFT			15
338*4882a593Smuzhiyun #define PRE_DITHER_DOWN_EN_SHIFT		16
339*4882a593Smuzhiyun #define DITHER_DOWN_EN_SHIFT			17
340*4882a593Smuzhiyun #define DITHER_DOWN_MODE_SHIFT			20
341*4882a593Smuzhiyun #define GAMMA_UPDATE_EN_SHIFT			22
342*4882a593Smuzhiyun #define DSP_LUT_EN_SHIFT			28
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun #define STANDBY_EN_SHIFT			31
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun #define RK3568_VP0_MIPI_CTRL			0xC04
347*4882a593Smuzhiyun #define DCLK_DIV2_SHIFT				4
348*4882a593Smuzhiyun #define DCLK_DIV2_MASK				0x3
349*4882a593Smuzhiyun #define MIPI_DUAL_EN_SHIFT			20
350*4882a593Smuzhiyun #define MIPI_DUAL_SWAP_EN_SHIFT			21
351*4882a593Smuzhiyun #define EDPI_TE_EN				28
352*4882a593Smuzhiyun #define EDPI_WMS_HOLD_EN			30
353*4882a593Smuzhiyun #define EDPI_WMS_FS				31
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun #define RK3568_VP0_COLOR_BAR_CTRL		0xC08
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun #define RK3568_VP0_DCLK_SEL			0xC0C
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun #define RK3568_VP0_3D_LUT_CTRL			0xC10
361*4882a593Smuzhiyun #define VP0_3D_LUT_EN_SHIFT				0
362*4882a593Smuzhiyun #define VP0_3D_LUT_UPDATE_SHIFT			2
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun #define RK3588_VP0_CLK_CTRL			0xC0C
365*4882a593Smuzhiyun #define DCLK_CORE_DIV_SHIFT			0
366*4882a593Smuzhiyun #define DCLK_OUT_DIV_SHIFT			2
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun #define RK3568_VP0_3D_LUT_MST			0xC20
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun #define RK3568_VP0_DSP_BG			0xC2C
371*4882a593Smuzhiyun #define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
372*4882a593Smuzhiyun #define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
373*4882a593Smuzhiyun #define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
374*4882a593Smuzhiyun #define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
375*4882a593Smuzhiyun #define RK3568_VP0_POST_SCL_CTRL		0xC40
376*4882a593Smuzhiyun #define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
377*4882a593Smuzhiyun #define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
378*4882a593Smuzhiyun #define RK3568_VP0_DSP_HACT_ST_END		0xC4C
379*4882a593Smuzhiyun #define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
380*4882a593Smuzhiyun #define RK3568_VP0_DSP_VACT_ST_END		0xC54
381*4882a593Smuzhiyun #define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
382*4882a593Smuzhiyun #define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun #define RK3568_VP0_BCSH_CTRL			0xC60
385*4882a593Smuzhiyun #define BCSH_CTRL_Y2R_SHIFT			0
386*4882a593Smuzhiyun #define BCSH_CTRL_Y2R_MASK			0x1
387*4882a593Smuzhiyun #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT		2
388*4882a593Smuzhiyun #define BCSH_CTRL_Y2R_CSC_MODE_MASK		0x3
389*4882a593Smuzhiyun #define BCSH_CTRL_R2Y_SHIFT			4
390*4882a593Smuzhiyun #define BCSH_CTRL_R2Y_MASK			0x1
391*4882a593Smuzhiyun #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT		6
392*4882a593Smuzhiyun #define BCSH_CTRL_R2Y_CSC_MODE_MASK		0x3
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun #define RK3568_VP0_BCSH_BCS			0xC64
395*4882a593Smuzhiyun #define BCSH_BRIGHTNESS_SHIFT			0
396*4882a593Smuzhiyun #define BCSH_BRIGHTNESS_MASK			0xFF
397*4882a593Smuzhiyun #define BCSH_CONTRAST_SHIFT			8
398*4882a593Smuzhiyun #define BCSH_CONTRAST_MASK			0x1FF
399*4882a593Smuzhiyun #define BCSH_SATURATION_SHIFT			20
400*4882a593Smuzhiyun #define BCSH_SATURATION_MASK			0x3FF
401*4882a593Smuzhiyun #define BCSH_OUT_MODE_SHIFT			30
402*4882a593Smuzhiyun #define BCSH_OUT_MODE_MASK			0x3
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun #define RK3568_VP0_BCSH_H			0xC68
405*4882a593Smuzhiyun #define BCSH_SIN_HUE_SHIFT			0
406*4882a593Smuzhiyun #define BCSH_SIN_HUE_MASK			0x1FF
407*4882a593Smuzhiyun #define BCSH_COS_HUE_SHIFT			16
408*4882a593Smuzhiyun #define BCSH_COS_HUE_MASK			0x1FF
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun #define RK3568_VP0_BCSH_COLOR			0xC6C
411*4882a593Smuzhiyun #define BCSH_EN_SHIFT				31
412*4882a593Smuzhiyun #define BCSH_EN_MASK				1
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun #define RK3528_VP0_ACM_CTRL			0xCD0
415*4882a593Smuzhiyun #define POST_CSC_COE00_MASK			0xFFFF
416*4882a593Smuzhiyun #define POST_CSC_COE00_SHIFT			16
417*4882a593Smuzhiyun #define POST_R2Y_MODE_MASK			0x7
418*4882a593Smuzhiyun #define POST_R2Y_MODE_SHIFT			8
419*4882a593Smuzhiyun #define POST_CSC_MODE_MASK			0x7
420*4882a593Smuzhiyun #define POST_CSC_MODE_SHIFT			3
421*4882a593Smuzhiyun #define POST_R2Y_EN_MASK			0x1
422*4882a593Smuzhiyun #define POST_R2Y_EN_SHIFT			2
423*4882a593Smuzhiyun #define POST_CSC_EN_MASK			0x1
424*4882a593Smuzhiyun #define POST_CSC_EN_SHIFT			1
425*4882a593Smuzhiyun #define POST_ACM_BYPASS_EN_MASK			0x1
426*4882a593Smuzhiyun #define POST_ACM_BYPASS_EN_SHIFT		0
427*4882a593Smuzhiyun #define RK3528_VP0_CSC_COE01_02			0xCD4
428*4882a593Smuzhiyun #define RK3528_VP0_CSC_COE10_11			0xCD8
429*4882a593Smuzhiyun #define RK3528_VP0_CSC_COE12_20			0xCDC
430*4882a593Smuzhiyun #define RK3528_VP0_CSC_COE21_22			0xCE0
431*4882a593Smuzhiyun #define RK3528_VP0_CSC_OFFSET0			0xCE4
432*4882a593Smuzhiyun #define RK3528_VP0_CSC_OFFSET1			0xCE8
433*4882a593Smuzhiyun #define RK3528_VP0_CSC_OFFSET2			0xCEC
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun #define RK3562_VP0_MCU_CTRL			0xCF8
436*4882a593Smuzhiyun #define MCU_TYPE_SHIFT				31
437*4882a593Smuzhiyun #define MCU_BYPASS_SHIFT			30
438*4882a593Smuzhiyun #define MCU_RS_SHIFT				29
439*4882a593Smuzhiyun #define MCU_FRAME_ST_SHIFT			28
440*4882a593Smuzhiyun #define MCU_HOLD_MODE_SHIFT			27
441*4882a593Smuzhiyun #define MCU_CLK_SEL_SHIFT			26
442*4882a593Smuzhiyun #define MCU_CLK_SEL_MASK			0x1
443*4882a593Smuzhiyun #define MCU_RW_PEND_SHIFT			20
444*4882a593Smuzhiyun #define MCU_RW_PEND_MASK			0x3F
445*4882a593Smuzhiyun #define MCU_RW_PST_SHIFT			16
446*4882a593Smuzhiyun #define MCU_RW_PST_MASK				0xF
447*4882a593Smuzhiyun #define MCU_CS_PEND_SHIFT			10
448*4882a593Smuzhiyun #define MCU_CS_PEND_MASK			0x3F
449*4882a593Smuzhiyun #define MCU_CS_PST_SHIFT			6
450*4882a593Smuzhiyun #define MCU_CS_PST_MASK				0xF
451*4882a593Smuzhiyun #define MCU_PIX_TOTAL_SHIFT			0
452*4882a593Smuzhiyun #define MCU_PIX_TOTAL_MASK			0x3F
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun #define RK3562_VP0_MCU_RW_BYPASS_PORT		0xCFC
455*4882a593Smuzhiyun #define MCU_WRITE_DATA_BYPASS_SHIFT		0
456*4882a593Smuzhiyun #define MCU_WRITE_DATA_BYPASS_MASK		0xFFFFFFFF
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun #define RK3568_VP1_DSP_CTRL			0xD00
459*4882a593Smuzhiyun #define RK3568_VP1_MIPI_CTRL			0xD04
460*4882a593Smuzhiyun #define RK3568_VP1_COLOR_BAR_CTRL		0xD08
461*4882a593Smuzhiyun #define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
462*4882a593Smuzhiyun #define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
463*4882a593Smuzhiyun #define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
464*4882a593Smuzhiyun #define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
465*4882a593Smuzhiyun #define RK3568_VP1_POST_SCL_CTRL		0xD40
466*4882a593Smuzhiyun #define RK3568_VP1_DSP_HACT_INFO		0xD34
467*4882a593Smuzhiyun #define RK3568_VP1_DSP_VACT_INFO		0xD38
468*4882a593Smuzhiyun #define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
469*4882a593Smuzhiyun #define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
470*4882a593Smuzhiyun #define RK3568_VP1_DSP_HACT_ST_END		0xD4C
471*4882a593Smuzhiyun #define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
472*4882a593Smuzhiyun #define RK3568_VP1_DSP_VACT_ST_END		0xD54
473*4882a593Smuzhiyun #define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
474*4882a593Smuzhiyun #define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun #define RK3568_VP2_DSP_CTRL			0xE00
477*4882a593Smuzhiyun #define RK3568_VP2_MIPI_CTRL			0xE04
478*4882a593Smuzhiyun #define RK3568_VP2_COLOR_BAR_CTRL		0xE08
479*4882a593Smuzhiyun #define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
480*4882a593Smuzhiyun #define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
481*4882a593Smuzhiyun #define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
482*4882a593Smuzhiyun #define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
483*4882a593Smuzhiyun #define RK3568_VP2_POST_SCL_CTRL		0xE40
484*4882a593Smuzhiyun #define RK3568_VP2_DSP_HACT_INFO		0xE34
485*4882a593Smuzhiyun #define RK3568_VP2_DSP_VACT_INFO		0xE38
486*4882a593Smuzhiyun #define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
487*4882a593Smuzhiyun #define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
488*4882a593Smuzhiyun #define RK3568_VP2_DSP_HACT_ST_END		0xE4C
489*4882a593Smuzhiyun #define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
490*4882a593Smuzhiyun #define RK3568_VP2_DSP_VACT_ST_END		0xE54
491*4882a593Smuzhiyun #define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
492*4882a593Smuzhiyun #define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun /* Cluster0 register definition */
495*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
496*4882a593Smuzhiyun #define CLUSTER_YUV2RGB_EN_SHIFT		8
497*4882a593Smuzhiyun #define CLUSTER_RGB2YUV_EN_SHIFT		9
498*4882a593Smuzhiyun #define CLUSTER_CSC_MODE_SHIFT			10
499*4882a593Smuzhiyun #define CLUSTER_DITHER_UP_EN_SHIFT		18
500*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
501*4882a593Smuzhiyun #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT	12
502*4882a593Smuzhiyun #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
503*4882a593Smuzhiyun #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT	14
504*4882a593Smuzhiyun #define AVG2_MASK				0x1
505*4882a593Smuzhiyun #define CLUSTER_AVG2_SHIFT			18
506*4882a593Smuzhiyun #define AVG4_MASK				0x1
507*4882a593Smuzhiyun #define CLUSTER_AVG4_SHIFT			19
508*4882a593Smuzhiyun #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT	22
509*4882a593Smuzhiyun #define CLUSTER_XGT_EN_SHIFT			24
510*4882a593Smuzhiyun #define XGT_MODE_MASK				0x3
511*4882a593Smuzhiyun #define CLUSTER_XGT_MODE_SHIFT			25
512*4882a593Smuzhiyun #define CLUSTER_XAVG_EN_SHIFT			27
513*4882a593Smuzhiyun #define CLUSTER_YRGB_GT2_SHIFT			28
514*4882a593Smuzhiyun #define CLUSTER_YRGB_GT4_SHIFT			29
515*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_CTRL2		0x1008
516*4882a593Smuzhiyun #define CLUSTER_AXI_YRGB_ID_MASK		0x1f
517*4882a593Smuzhiyun #define CLUSTER_AXI_YRGB_ID_SHIFT		0
518*4882a593Smuzhiyun #define CLUSTER_AXI_UV_ID_MASK			0x1f
519*4882a593Smuzhiyun #define CLUSTER_AXI_UV_ID_SHIFT			5
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
522*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
523*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_VIR		0x1018
524*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
525*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
526*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
527*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
528*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
529*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
530*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
531*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
532*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
533*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
534*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
535*4882a593Smuzhiyun #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT		7
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
538*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
539*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
540*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
541*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_VIR		0x1098
542*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
543*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
544*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
545*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
546*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
547*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
548*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
549*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
550*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
551*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
552*4882a593Smuzhiyun #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun #define RK3568_CLUSTER0_CTRL			0x1100
555*4882a593Smuzhiyun #define CLUSTER_EN_SHIFT			0
556*4882a593Smuzhiyun #define CLUSTER_AXI_ID_MASK			0x1
557*4882a593Smuzhiyun #define CLUSTER_AXI_ID_SHIFT			13
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
560*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
561*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
562*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
563*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_VIR		0x1218
564*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
565*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
566*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
567*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
568*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
569*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
570*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
571*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
572*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
573*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
574*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
577*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
578*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
579*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
580*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_VIR		0x1298
581*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
582*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
583*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
584*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
585*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
586*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
587*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
588*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
589*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
590*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
591*4882a593Smuzhiyun #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun #define RK3568_CLUSTER1_CTRL			0x1300
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun /* Esmart register definition */
596*4882a593Smuzhiyun #define RK3568_ESMART0_CTRL0			0x1800
597*4882a593Smuzhiyun #define RGB2YUV_EN_SHIFT			1
598*4882a593Smuzhiyun #define CSC_MODE_SHIFT				2
599*4882a593Smuzhiyun #define CSC_MODE_MASK				0x3
600*4882a593Smuzhiyun #define ESMART_LB_SELECT_SHIFT			12
601*4882a593Smuzhiyun #define ESMART_LB_SELECT_MASK			0x3
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun #define RK3568_ESMART0_CTRL1			0x1804
604*4882a593Smuzhiyun #define ESMART_AXI_YRGB_ID_MASK			0x1f
605*4882a593Smuzhiyun #define ESMART_AXI_YRGB_ID_SHIFT		4
606*4882a593Smuzhiyun #define ESMART_AXI_UV_ID_MASK			0x1f
607*4882a593Smuzhiyun #define ESMART_AXI_UV_ID_SHIFT			12
608*4882a593Smuzhiyun #define YMIRROR_EN_SHIFT			31
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun #define RK3568_ESMART0_AXI_CTRL			0x1808
611*4882a593Smuzhiyun #define ESMART_AXI_ID_MASK			0x1
612*4882a593Smuzhiyun #define ESMART_AXI_ID_SHIFT			1
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_CTRL		0x1810
615*4882a593Smuzhiyun #define WIN_EN_SHIFT				0
616*4882a593Smuzhiyun #define WIN_FORMAT_MASK				0x1f
617*4882a593Smuzhiyun #define WIN_FORMAT_SHIFT			1
618*4882a593Smuzhiyun #define REGION0_DITHER_UP_EN_SHIFT		12
619*4882a593Smuzhiyun #define REGION0_RB_SWAP_SHIFT			14
620*4882a593Smuzhiyun #define ESMART_XAVG_EN_SHIFT			20
621*4882a593Smuzhiyun #define ESMART_XGT_EN_SHIFT			21
622*4882a593Smuzhiyun #define ESMART_XGT_MODE_SHIFT			22
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
625*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
626*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_VIR		0x181C
627*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
628*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
629*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
630*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
631*4882a593Smuzhiyun #define YRGB_XSCL_MODE_MASK			0x3
632*4882a593Smuzhiyun #define YRGB_XSCL_MODE_SHIFT			0
633*4882a593Smuzhiyun #define YRGB_XSCL_FILTER_MODE_MASK		0x3
634*4882a593Smuzhiyun #define YRGB_XSCL_FILTER_MODE_SHIFT		2
635*4882a593Smuzhiyun #define YRGB_YSCL_MODE_MASK			0x3
636*4882a593Smuzhiyun #define YRGB_YSCL_MODE_SHIFT			4
637*4882a593Smuzhiyun #define YRGB_YSCL_FILTER_MODE_MASK		0x3
638*4882a593Smuzhiyun #define YRGB_YSCL_FILTER_MODE_SHIFT		6
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
641*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
642*4882a593Smuzhiyun #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
643*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_CTRL		0x1840
644*4882a593Smuzhiyun #define YRGB_GT2_MASK				0x1
645*4882a593Smuzhiyun #define YRGB_GT2_SHIFT				8
646*4882a593Smuzhiyun #define YRGB_GT4_MASK				0x1
647*4882a593Smuzhiyun #define YRGB_GT4_SHIFT				9
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
650*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
651*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_VIR		0x184C
652*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
653*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
654*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
655*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
656*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
657*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
658*4882a593Smuzhiyun #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
659*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_CTRL		0x1870
660*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
661*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
662*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_VIR		0x187C
663*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
664*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
665*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
666*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
667*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
668*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
669*4882a593Smuzhiyun #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
670*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_CTRL		0x18A0
671*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
672*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
673*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_VIR		0x18AC
674*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
675*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
676*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
677*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
678*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
679*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
680*4882a593Smuzhiyun #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun #define RK3568_ESMART1_CTRL0			0x1A00
683*4882a593Smuzhiyun #define RK3568_ESMART1_CTRL1			0x1A04
684*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_CTRL		0x1A10
685*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
686*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
687*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_VIR		0x1A1C
688*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
689*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
690*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
691*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
692*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
693*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
694*4882a593Smuzhiyun #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
695*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_CTRL		0x1A40
696*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
697*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
698*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_VIR		0x1A4C
699*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
700*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
701*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
702*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
703*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
704*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
705*4882a593Smuzhiyun #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
706*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_CTRL		0x1A70
707*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
708*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
709*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_VIR		0x1A7C
710*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
711*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
712*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
713*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
714*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
715*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
716*4882a593Smuzhiyun #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
717*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
718*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
719*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
720*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_VIR		0x1AAC
721*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
722*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
723*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
724*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
725*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
726*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
727*4882a593Smuzhiyun #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun #define RK3568_SMART0_CTRL0			0x1C00
730*4882a593Smuzhiyun #define RK3568_SMART0_CTRL1			0x1C04
731*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_CTRL		0x1C10
732*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
733*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
734*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_VIR		0x1C1C
735*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
736*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
737*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
738*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
739*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
740*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
741*4882a593Smuzhiyun #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
742*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_CTRL		0x1C40
743*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
744*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
745*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_VIR		0x1C4C
746*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
747*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
748*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
749*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
750*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
751*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
752*4882a593Smuzhiyun #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
753*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_CTRL		0x1C70
754*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
755*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
756*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_VIR		0x1C7C
757*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
758*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
759*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
760*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
761*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
762*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
763*4882a593Smuzhiyun #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
764*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_CTRL		0x1CA0
765*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
766*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
767*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_VIR		0x1CAC
768*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
769*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
770*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
771*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
772*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
773*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
774*4882a593Smuzhiyun #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun #define RK3568_SMART1_CTRL0			0x1E00
777*4882a593Smuzhiyun #define RK3568_SMART1_CTRL1			0x1E04
778*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_CTRL		0x1E10
779*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
780*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
781*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_VIR		0x1E1C
782*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
783*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
784*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
785*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
786*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
787*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
788*4882a593Smuzhiyun #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
789*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_CTRL		0x1E40
790*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
791*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
792*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_VIR		0x1E4C
793*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
794*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
795*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
796*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
797*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
798*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
799*4882a593Smuzhiyun #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
800*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_CTRL		0x1E70
801*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
802*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
803*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_VIR		0x1E7C
804*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
805*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
806*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
807*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
808*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
809*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
810*4882a593Smuzhiyun #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
811*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_CTRL		0x1EA0
812*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
813*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
814*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_VIR		0x1EAC
815*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
816*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
817*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
818*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
819*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
820*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
821*4882a593Smuzhiyun #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun /* HDR register definition */
824*4882a593Smuzhiyun #define RK3568_HDR_LUT_CTRL			0x2000
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun #define RK3588_VP3_DSP_CTRL			0xF00
827*4882a593Smuzhiyun #define RK3588_CLUSTER2_WIN0_CTRL0		0x1400
828*4882a593Smuzhiyun #define RK3588_CLUSTER3_WIN0_CTRL0		0x1600
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun /* DSC 8K/4K register definition */
831*4882a593Smuzhiyun #define RK3588_DSC_8K_PPS0_3			0x4000
832*4882a593Smuzhiyun #define RK3588_DSC_8K_CTRL0			0x40A0
833*4882a593Smuzhiyun #define DSC_EN_SHIFT				0
834*4882a593Smuzhiyun #define DSC_RBIT_SHIFT				2
835*4882a593Smuzhiyun #define DSC_RBYT_SHIFT				3
836*4882a593Smuzhiyun #define DSC_FLAL_SHIFT				4
837*4882a593Smuzhiyun #define DSC_MER_SHIFT				5
838*4882a593Smuzhiyun #define DSC_EPB_SHIFT				6
839*4882a593Smuzhiyun #define DSC_EPL_SHIFT				7
840*4882a593Smuzhiyun #define DSC_NSLC_MASK				0x7
841*4882a593Smuzhiyun #define DSC_NSLC_SHIFT				16
842*4882a593Smuzhiyun #define DSC_SBO_SHIFT				28
843*4882a593Smuzhiyun #define DSC_IFEP_SHIFT				29
844*4882a593Smuzhiyun #define DSC_PPS_UPD_SHIFT			31
845*4882a593Smuzhiyun #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT)   | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \
846*4882a593Smuzhiyun 			   (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT)  | (0 << DSC_EPB_SHIFT)  | \
847*4882a593Smuzhiyun 			   (1 << DSC_EPL_SHIFT)  | (1 << DSC_SBO_SHIFT))
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun #define RK3588_DSC_8K_CTRL1			0x40A4
850*4882a593Smuzhiyun #define RK3588_DSC_8K_STS0			0x40A8
851*4882a593Smuzhiyun #define RK3588_DSC_8K_ERS			0x40C4
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun #define RK3588_DSC_4K_PPS0_3			0x4100
854*4882a593Smuzhiyun #define RK3588_DSC_4K_CTRL0			0x41A0
855*4882a593Smuzhiyun #define RK3588_DSC_4K_CTRL1			0x41A4
856*4882a593Smuzhiyun #define RK3588_DSC_4K_STS0			0x41A8
857*4882a593Smuzhiyun #define RK3588_DSC_4K_ERS			0x41C4
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun /* RK3528 HDR register definition */
860*4882a593Smuzhiyun #define RK3528_HDR_LUT_CTRL			0x2000
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun /* RK3528 ACM register definition */
863*4882a593Smuzhiyun #define RK3528_ACM_CTRL				0x6400
864*4882a593Smuzhiyun #define RK3528_ACM_DELTA_RANGE			0x6404
865*4882a593Smuzhiyun #define RK3528_ACM_FETCH_START			0x6408
866*4882a593Smuzhiyun #define RK3528_ACM_FETCH_DONE			0x6420
867*4882a593Smuzhiyun #define RK3528_ACM_YHS_DEL_HY_SEG0		0x6500
868*4882a593Smuzhiyun #define RK3528_ACM_YHS_DEL_HY_SEG152		0x6760
869*4882a593Smuzhiyun #define RK3528_ACM_YHS_DEL_HS_SEG0		0x6764
870*4882a593Smuzhiyun #define RK3528_ACM_YHS_DEL_HS_SEG220		0x6ad4
871*4882a593Smuzhiyun #define RK3528_ACM_YHS_DEL_HGAIN_SEG0		0x6ad8
872*4882a593Smuzhiyun #define RK3528_ACM_YHS_DEL_HGAIN_SEG64		0x6bd8
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun #define RK3568_MAX_REG				0x1ED0
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun #define RK3562_GRF_IOC_VO_IO_CON		0x10500
877*4882a593Smuzhiyun #define RK3568_GRF_VO_CON1			0x0364
878*4882a593Smuzhiyun #define GRF_BT656_CLK_INV_SHIFT			1
879*4882a593Smuzhiyun #define GRF_BT1120_CLK_INV_SHIFT		2
880*4882a593Smuzhiyun #define GRF_RGB_DCLK_INV_SHIFT			3
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun #define RK3588_GRF_VOP_CON2			0x0008
883*4882a593Smuzhiyun #define RK3588_GRF_EDP0_ENABLE_SHIFT		0
884*4882a593Smuzhiyun #define RK3588_GRF_HDMITX0_ENABLE_SHIFT		1
885*4882a593Smuzhiyun #define RK3588_GRF_EDP1_ENABLE_SHIFT		3
886*4882a593Smuzhiyun #define RK3588_GRF_HDMITX1_ENABLE_SHIFT		4
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun #define RK3588_GRF_VO1_CON0			0x0000
889*4882a593Smuzhiyun #define HDMI_SYNC_POL_MASK			0x3
890*4882a593Smuzhiyun #define HDMI0_SYNC_POL_SHIFT			5
891*4882a593Smuzhiyun #define HDMI1_SYNC_POL_SHIFT			7
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun #define RK3588_PMU_BISR_CON3			0x20C
894*4882a593Smuzhiyun #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT	9
895*4882a593Smuzhiyun #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT	10
896*4882a593Smuzhiyun #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT	11
897*4882a593Smuzhiyun #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT	12
898*4882a593Smuzhiyun #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT	13
899*4882a593Smuzhiyun #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT	14
900*4882a593Smuzhiyun #define RK3588_PD_ESMART_REPAIR_EN_SHIFT	15
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun #define RK3588_PMU_BISR_STATUS5			0x294
903*4882a593Smuzhiyun #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI	9
904*4882a593Smuzhiyun #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI	10
905*4882a593Smuzhiyun #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI	11
906*4882a593Smuzhiyun #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI	12
907*4882a593Smuzhiyun #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI		13
908*4882a593Smuzhiyun #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI		14
909*4882a593Smuzhiyun #define RK3588_PD_ESMART_PWR_STAT_SHIFI		15
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun #define VOP2_LAYER_MAX				8
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun #define VOP2_MAX_VP_OUTPUT_WIDTH		4096
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun #define VOP_FEATURE_OUTPUT_10BIT		BIT(0)
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun /* KHz */
918*4882a593Smuzhiyun #define VOP2_MAX_DCLK_RATE			600000
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun /*
921*4882a593Smuzhiyun  * vop2 dsc id
922*4882a593Smuzhiyun  */
923*4882a593Smuzhiyun #define ROCKCHIP_VOP2_DSC_8K	0
924*4882a593Smuzhiyun #define ROCKCHIP_VOP2_DSC_4K	1
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun /*
927*4882a593Smuzhiyun  * vop2 internal power domain id,
928*4882a593Smuzhiyun  * should be all none zero, 0 will be
929*4882a593Smuzhiyun  * treat as invalid;
930*4882a593Smuzhiyun  */
931*4882a593Smuzhiyun #define VOP2_PD_CLUSTER0			BIT(0)
932*4882a593Smuzhiyun #define VOP2_PD_CLUSTER1			BIT(1)
933*4882a593Smuzhiyun #define VOP2_PD_CLUSTER2			BIT(2)
934*4882a593Smuzhiyun #define VOP2_PD_CLUSTER3			BIT(3)
935*4882a593Smuzhiyun #define VOP2_PD_DSC_8K				BIT(5)
936*4882a593Smuzhiyun #define VOP2_PD_DSC_4K				BIT(6)
937*4882a593Smuzhiyun #define VOP2_PD_ESMART				BIT(7)
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun #define VOP2_PLANE_NO_SCALING			BIT(16)
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun #define VOP_FEATURE_OUTPUT_10BIT	BIT(0)
942*4882a593Smuzhiyun #define VOP_FEATURE_AFBDC		BIT(1)
943*4882a593Smuzhiyun #define VOP_FEATURE_ALPHA_SCALE		BIT(2)
944*4882a593Smuzhiyun #define VOP_FEATURE_HDR10		BIT(3)
945*4882a593Smuzhiyun #define VOP_FEATURE_NEXT_HDR		BIT(4)
946*4882a593Smuzhiyun /* a feature to splice two windows and two vps to support resolution > 4096 */
947*4882a593Smuzhiyun #define VOP_FEATURE_SPLICE		BIT(5)
948*4882a593Smuzhiyun #define VOP_FEATURE_OVERSCAN		BIT(6)
949*4882a593Smuzhiyun #define VOP_FEATURE_VIVID_HDR		BIT(7)
950*4882a593Smuzhiyun #define VOP_FEATURE_POST_ACM		BIT(8)
951*4882a593Smuzhiyun #define VOP_FEATURE_POST_CSC		BIT(9)
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun #define WIN_FEATURE_HDR2SDR		BIT(0)
954*4882a593Smuzhiyun #define WIN_FEATURE_SDR2HDR		BIT(1)
955*4882a593Smuzhiyun #define WIN_FEATURE_PRE_OVERLAY		BIT(2)
956*4882a593Smuzhiyun #define WIN_FEATURE_AFBDC		BIT(3)
957*4882a593Smuzhiyun #define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
958*4882a593Smuzhiyun #define WIN_FEATURE_CLUSTER_SUB		BIT(5)
959*4882a593Smuzhiyun /* a mirror win can only get fb address
960*4882a593Smuzhiyun  * from source win:
961*4882a593Smuzhiyun  * Cluster1---->Cluster0
962*4882a593Smuzhiyun  * Esmart1 ---->Esmart0
963*4882a593Smuzhiyun  * Smart1  ---->Smart0
964*4882a593Smuzhiyun  * This is a feather on rk3566
965*4882a593Smuzhiyun  */
966*4882a593Smuzhiyun #define WIN_FEATURE_MIRROR		BIT(6)
967*4882a593Smuzhiyun #define WIN_FEATURE_MULTI_AREA		BIT(7)
968*4882a593Smuzhiyun #define WIN_FEATURE_Y2R_13BIT_DEPTH	BIT(8)
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun #define V4L2_COLORSPACE_BT709F		0xfe
971*4882a593Smuzhiyun #define V4L2_COLORSPACE_BT2020F		0xff
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun enum vop_csc_format {
974*4882a593Smuzhiyun 	CSC_BT601L,
975*4882a593Smuzhiyun 	CSC_BT709L,
976*4882a593Smuzhiyun 	CSC_BT601F,
977*4882a593Smuzhiyun 	CSC_BT2020,
978*4882a593Smuzhiyun 	CSC_BT709L_13BIT,
979*4882a593Smuzhiyun 	CSC_BT709F_13BIT,
980*4882a593Smuzhiyun 	CSC_BT2020L_13BIT,
981*4882a593Smuzhiyun 	CSC_BT2020F_13BIT,
982*4882a593Smuzhiyun };
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun enum vop_csc_bit_depth {
985*4882a593Smuzhiyun 	CSC_10BIT_DEPTH,
986*4882a593Smuzhiyun 	CSC_13BIT_DEPTH,
987*4882a593Smuzhiyun };
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun enum vop2_pol {
990*4882a593Smuzhiyun 	HSYNC_POSITIVE = 0,
991*4882a593Smuzhiyun 	VSYNC_POSITIVE = 1,
992*4882a593Smuzhiyun 	DEN_NEGATIVE   = 2,
993*4882a593Smuzhiyun 	DCLK_INVERT    = 3
994*4882a593Smuzhiyun };
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun enum vop2_bcsh_out_mode {
997*4882a593Smuzhiyun 	BCSH_OUT_MODE_BLACK,
998*4882a593Smuzhiyun 	BCSH_OUT_MODE_BLUE,
999*4882a593Smuzhiyun 	BCSH_OUT_MODE_COLOR_BAR,
1000*4882a593Smuzhiyun 	BCSH_OUT_MODE_NORMAL_VIDEO,
1001*4882a593Smuzhiyun };
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun #define _VOP_REG(off, _mask, _shift, _write_mask) \
1004*4882a593Smuzhiyun 		{ \
1005*4882a593Smuzhiyun 		 .offset = off, \
1006*4882a593Smuzhiyun 		 .mask = _mask, \
1007*4882a593Smuzhiyun 		 .shift = _shift, \
1008*4882a593Smuzhiyun 		 .write_mask = _write_mask, \
1009*4882a593Smuzhiyun 		}
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun #define VOP_REG(off, _mask, _shift) \
1012*4882a593Smuzhiyun 		_VOP_REG(off, _mask, _shift, false)
1013*4882a593Smuzhiyun enum dither_down_mode {
1014*4882a593Smuzhiyun 	RGB888_TO_RGB565 = 0x0,
1015*4882a593Smuzhiyun 	RGB888_TO_RGB666 = 0x1
1016*4882a593Smuzhiyun };
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun enum vop2_video_ports_id {
1019*4882a593Smuzhiyun 	VOP2_VP0,
1020*4882a593Smuzhiyun 	VOP2_VP1,
1021*4882a593Smuzhiyun 	VOP2_VP2,
1022*4882a593Smuzhiyun 	VOP2_VP3,
1023*4882a593Smuzhiyun 	VOP2_VP_MAX,
1024*4882a593Smuzhiyun };
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun enum vop2_layer_type {
1027*4882a593Smuzhiyun 	CLUSTER_LAYER = 0,
1028*4882a593Smuzhiyun 	ESMART_LAYER = 1,
1029*4882a593Smuzhiyun 	SMART_LAYER = 2,
1030*4882a593Smuzhiyun };
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun /* This define must same with kernel win phy id */
1033*4882a593Smuzhiyun enum vop2_layer_phy_id {
1034*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER0 = 0,
1035*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER1,
1036*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART0,
1037*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART1,
1038*4882a593Smuzhiyun 	ROCKCHIP_VOP2_SMART0,
1039*4882a593Smuzhiyun 	ROCKCHIP_VOP2_SMART1,
1040*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER2,
1041*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER3,
1042*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART2,
1043*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART3,
1044*4882a593Smuzhiyun 	ROCKCHIP_VOP2_LAYER_MAX,
1045*4882a593Smuzhiyun };
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun enum vop2_scale_up_mode {
1048*4882a593Smuzhiyun 	VOP2_SCALE_UP_NRST_NBOR,
1049*4882a593Smuzhiyun 	VOP2_SCALE_UP_BIL,
1050*4882a593Smuzhiyun 	VOP2_SCALE_UP_BIC,
1051*4882a593Smuzhiyun };
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun enum vop2_scale_down_mode {
1054*4882a593Smuzhiyun 	VOP2_SCALE_DOWN_NRST_NBOR,
1055*4882a593Smuzhiyun 	VOP2_SCALE_DOWN_BIL,
1056*4882a593Smuzhiyun 	VOP2_SCALE_DOWN_AVG,
1057*4882a593Smuzhiyun };
1058*4882a593Smuzhiyun 
1059*4882a593Smuzhiyun enum scale_mode {
1060*4882a593Smuzhiyun 	SCALE_NONE = 0x0,
1061*4882a593Smuzhiyun 	SCALE_UP   = 0x1,
1062*4882a593Smuzhiyun 	SCALE_DOWN = 0x2
1063*4882a593Smuzhiyun };
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun enum vop_dsc_interface_mode {
1066*4882a593Smuzhiyun 	VOP_DSC_IF_DISABLE = 0,
1067*4882a593Smuzhiyun 	VOP_DSC_IF_HDMI = 1,
1068*4882a593Smuzhiyun 	VOP_DSC_IF_MIPI_DS_MODE = 2,
1069*4882a593Smuzhiyun 	VOP_DSC_IF_MIPI_VIDEO_MODE = 3,
1070*4882a593Smuzhiyun };
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun enum vop3_pre_scale_down_mode {
1073*4882a593Smuzhiyun 	VOP3_PRE_SCALE_UNSPPORT,
1074*4882a593Smuzhiyun 	VOP3_PRE_SCALE_DOWN_GT,
1075*4882a593Smuzhiyun 	VOP3_PRE_SCALE_DOWN_AVG,
1076*4882a593Smuzhiyun };
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun enum vop3_esmart_lb_mode {
1079*4882a593Smuzhiyun 	VOP3_ESMART_8K_MODE,
1080*4882a593Smuzhiyun 	VOP3_ESMART_4K_4K_MODE,
1081*4882a593Smuzhiyun 	VOP3_ESMART_4K_2K_2K_MODE,
1082*4882a593Smuzhiyun 	VOP3_ESMART_2K_2K_2K_2K_MODE,
1083*4882a593Smuzhiyun };
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun struct vop2_layer {
1086*4882a593Smuzhiyun 	u8 id;
1087*4882a593Smuzhiyun 	/**
1088*4882a593Smuzhiyun 	 * @win_phys_id: window id of the layer selected.
1089*4882a593Smuzhiyun 	 * Every layer must make sure to select different
1090*4882a593Smuzhiyun 	 * windows of others.
1091*4882a593Smuzhiyun 	 */
1092*4882a593Smuzhiyun 	u8 win_phys_id;
1093*4882a593Smuzhiyun };
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun struct vop2_power_domain_data {
1096*4882a593Smuzhiyun 	u8 id;
1097*4882a593Smuzhiyun 	u8 parent_id;
1098*4882a593Smuzhiyun 	/*
1099*4882a593Smuzhiyun 	 * @module_id_mask: module id of which module this power domain is belongs to.
1100*4882a593Smuzhiyun 	 * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3
1101*4882a593Smuzhiyun 	 */
1102*4882a593Smuzhiyun 	u32 module_id_mask;
1103*4882a593Smuzhiyun };
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun struct vop2_win_data {
1106*4882a593Smuzhiyun 	char *name;
1107*4882a593Smuzhiyun 	u8 phys_id;
1108*4882a593Smuzhiyun 	enum vop2_layer_type type;
1109*4882a593Smuzhiyun 	u8 win_sel_port_offset;
1110*4882a593Smuzhiyun 	u8 layer_sel_win_id[VOP2_VP_MAX];
1111*4882a593Smuzhiyun 	u8 axi_id;
1112*4882a593Smuzhiyun 	u8 axi_uv_id;
1113*4882a593Smuzhiyun 	u8 axi_yrgb_id;
1114*4882a593Smuzhiyun 	u8 splice_win_id;
1115*4882a593Smuzhiyun 	u8 pd_id;
1116*4882a593Smuzhiyun 	u8 hsu_filter_mode;
1117*4882a593Smuzhiyun 	u8 hsd_filter_mode;
1118*4882a593Smuzhiyun 	u8 vsu_filter_mode;
1119*4882a593Smuzhiyun 	u8 vsd_filter_mode;
1120*4882a593Smuzhiyun 	u8 hsd_pre_filter_mode;
1121*4882a593Smuzhiyun 	u8 vsd_pre_filter_mode;
1122*4882a593Smuzhiyun 	u8 scale_engine_num;
1123*4882a593Smuzhiyun 	u32 reg_offset;
1124*4882a593Smuzhiyun 	u32 max_upscale_factor;
1125*4882a593Smuzhiyun 	u32 max_downscale_factor;
1126*4882a593Smuzhiyun 	bool splice_mode_right;
1127*4882a593Smuzhiyun };
1128*4882a593Smuzhiyun 
1129*4882a593Smuzhiyun struct vop2_vp_data {
1130*4882a593Smuzhiyun 	u32 feature;
1131*4882a593Smuzhiyun 	u8 pre_scan_max_dly;
1132*4882a593Smuzhiyun 	u8 layer_mix_dly;
1133*4882a593Smuzhiyun 	u8 hdr_mix_dly;
1134*4882a593Smuzhiyun 	u8 win_dly;
1135*4882a593Smuzhiyun 	u8 splice_vp_id;
1136*4882a593Smuzhiyun 	struct vop_rect max_output;
1137*4882a593Smuzhiyun 	u32 max_dclk;
1138*4882a593Smuzhiyun };
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun struct vop2_plane_table {
1141*4882a593Smuzhiyun 	enum vop2_layer_phy_id plane_id;
1142*4882a593Smuzhiyun 	enum vop2_layer_type plane_type;
1143*4882a593Smuzhiyun };
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun struct vop2_vp_plane_mask {
1146*4882a593Smuzhiyun 	u8 primary_plane_id; /* use this win to show logo */
1147*4882a593Smuzhiyun 	u8 attached_layers_nr; /* number layers attach to this vp */
1148*4882a593Smuzhiyun 	u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
1149*4882a593Smuzhiyun 	u32 plane_mask;
1150*4882a593Smuzhiyun 	int cursor_plane_id;
1151*4882a593Smuzhiyun };
1152*4882a593Smuzhiyun 
1153*4882a593Smuzhiyun struct vop2_dsc_data {
1154*4882a593Smuzhiyun 	u8 id;
1155*4882a593Smuzhiyun 	u8 pd_id;
1156*4882a593Smuzhiyun 	u8 max_slice_num;
1157*4882a593Smuzhiyun 	u8 max_linebuf_depth;	/* used to generate the bitstream */
1158*4882a593Smuzhiyun 	u8 min_bits_per_pixel;	/* bit num after encoder compress */
1159*4882a593Smuzhiyun 	const char *dsc_txp_clk_src_name;
1160*4882a593Smuzhiyun 	const char *dsc_txp_clk_name;
1161*4882a593Smuzhiyun 	const char *dsc_pxl_clk_name;
1162*4882a593Smuzhiyun 	const char *dsc_cds_clk_name;
1163*4882a593Smuzhiyun };
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun struct dsc_error_info {
1166*4882a593Smuzhiyun 	u32 dsc_error_val;
1167*4882a593Smuzhiyun 	char dsc_error_info[50];
1168*4882a593Smuzhiyun };
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun struct vop2_dump_regs {
1171*4882a593Smuzhiyun 	u32 offset;
1172*4882a593Smuzhiyun 	const char *name;
1173*4882a593Smuzhiyun 	u32 state_base;
1174*4882a593Smuzhiyun 	u32 state_mask;
1175*4882a593Smuzhiyun 	u32 state_shift;
1176*4882a593Smuzhiyun 	bool enable_state;
1177*4882a593Smuzhiyun };
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun struct vop2_data {
1180*4882a593Smuzhiyun 	u32 version;
1181*4882a593Smuzhiyun 	u32 esmart_lb_mode;
1182*4882a593Smuzhiyun 	struct vop2_vp_data *vp_data;
1183*4882a593Smuzhiyun 	struct vop2_win_data *win_data;
1184*4882a593Smuzhiyun 	struct vop2_vp_plane_mask *plane_mask;
1185*4882a593Smuzhiyun 	struct vop2_plane_table *plane_table;
1186*4882a593Smuzhiyun 	struct vop2_power_domain_data *pd;
1187*4882a593Smuzhiyun 	struct vop2_dsc_data *dsc;
1188*4882a593Smuzhiyun 	struct dsc_error_info *dsc_error_ecw;
1189*4882a593Smuzhiyun 	struct dsc_error_info *dsc_error_buffer_flow;
1190*4882a593Smuzhiyun 	struct vop2_dump_regs *dump_regs;
1191*4882a593Smuzhiyun 	u8 *vp_primary_plane_order;
1192*4882a593Smuzhiyun 	u8 nr_vps;
1193*4882a593Smuzhiyun 	u8 nr_layers;
1194*4882a593Smuzhiyun 	u8 nr_mixers;
1195*4882a593Smuzhiyun 	u8 nr_gammas;
1196*4882a593Smuzhiyun 	u8 nr_pd;
1197*4882a593Smuzhiyun 	u8 nr_dscs;
1198*4882a593Smuzhiyun 	u8 nr_dsc_ecw;
1199*4882a593Smuzhiyun 	u8 nr_dsc_buffer_flow;
1200*4882a593Smuzhiyun 	u32 reg_len;
1201*4882a593Smuzhiyun 	u32 dump_regs_size;
1202*4882a593Smuzhiyun };
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun struct vop2 {
1205*4882a593Smuzhiyun 	u32 *regsbak;
1206*4882a593Smuzhiyun 	void *regs;
1207*4882a593Smuzhiyun 	void *grf;
1208*4882a593Smuzhiyun 	void *vop_grf;
1209*4882a593Smuzhiyun 	void *vo1_grf;
1210*4882a593Smuzhiyun 	void *sys_pmu;
1211*4882a593Smuzhiyun 	u32 reg_len;
1212*4882a593Smuzhiyun 	u32 version;
1213*4882a593Smuzhiyun 	u32 esmart_lb_mode;
1214*4882a593Smuzhiyun 	bool global_init;
1215*4882a593Smuzhiyun 	const struct vop2_data *data;
1216*4882a593Smuzhiyun 	struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
1217*4882a593Smuzhiyun };
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun static struct vop2 *rockchip_vop2;
1220*4882a593Smuzhiyun 
is_vop3(struct vop2 * vop2)1221*4882a593Smuzhiyun static inline bool is_vop3(struct vop2 *vop2)
1222*4882a593Smuzhiyun {
1223*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588)
1224*4882a593Smuzhiyun 		return false;
1225*4882a593Smuzhiyun 	else
1226*4882a593Smuzhiyun 		return true;
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun /*
1230*4882a593Smuzhiyun  * bli_sd_factor = (src - 1) / (dst - 1) << 12;
1231*4882a593Smuzhiyun  * avg_sd_factor:
1232*4882a593Smuzhiyun  * bli_su_factor:
1233*4882a593Smuzhiyun  * bic_su_factor:
1234*4882a593Smuzhiyun  * = (src - 1) / (dst - 1) << 16;
1235*4882a593Smuzhiyun  *
1236*4882a593Smuzhiyun  * ygt2 enable: dst get one line from two line of the src
1237*4882a593Smuzhiyun  * ygt4 enable: dst get one line from four line of the src.
1238*4882a593Smuzhiyun  *
1239*4882a593Smuzhiyun  */
1240*4882a593Smuzhiyun #define VOP2_BILI_SCL_DN(src, dst)	(((src - 1) << 12) / (dst - 1))
1241*4882a593Smuzhiyun #define VOP2_COMMON_SCL(src, dst)	(((src - 1) << 16) / (dst - 1))
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)	 \
1244*4882a593Smuzhiyun 				(fac * (dst - 1) >> 12 < (src - 1))
1245*4882a593Smuzhiyun #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
1246*4882a593Smuzhiyun 				(fac * (dst - 1) >> 16 < (src - 1))
1247*4882a593Smuzhiyun #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
1248*4882a593Smuzhiyun 				(fac * (dst - 1) >> 16 < (src - 1))
1249*4882a593Smuzhiyun 
vop2_scale_factor(enum scale_mode mode,int32_t filter_mode,uint32_t src,uint32_t dst)1250*4882a593Smuzhiyun static uint16_t vop2_scale_factor(enum scale_mode mode,
1251*4882a593Smuzhiyun 				  int32_t filter_mode,
1252*4882a593Smuzhiyun 				  uint32_t src, uint32_t dst)
1253*4882a593Smuzhiyun {
1254*4882a593Smuzhiyun 	uint32_t fac = 0;
1255*4882a593Smuzhiyun 	int i = 0;
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	if (mode == SCALE_NONE)
1258*4882a593Smuzhiyun 		return 0;
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 	/*
1261*4882a593Smuzhiyun 	 * A workaround to avoid zero div.
1262*4882a593Smuzhiyun 	 */
1263*4882a593Smuzhiyun 	if ((dst == 1) || (src == 1)) {
1264*4882a593Smuzhiyun 		dst = dst + 1;
1265*4882a593Smuzhiyun 		src = src + 1;
1266*4882a593Smuzhiyun 	}
1267*4882a593Smuzhiyun 
1268*4882a593Smuzhiyun 	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
1269*4882a593Smuzhiyun 		fac = VOP2_BILI_SCL_DN(src, dst);
1270*4882a593Smuzhiyun 		for (i = 0; i < 100; i++) {
1271*4882a593Smuzhiyun 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
1272*4882a593Smuzhiyun 				break;
1273*4882a593Smuzhiyun 			fac -= 1;
1274*4882a593Smuzhiyun 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1275*4882a593Smuzhiyun 		}
1276*4882a593Smuzhiyun 	} else {
1277*4882a593Smuzhiyun 		fac = VOP2_COMMON_SCL(src, dst);
1278*4882a593Smuzhiyun 		for (i = 0; i < 100; i++) {
1279*4882a593Smuzhiyun 			if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
1280*4882a593Smuzhiyun 				break;
1281*4882a593Smuzhiyun 			fac -= 1;
1282*4882a593Smuzhiyun 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1283*4882a593Smuzhiyun 		}
1284*4882a593Smuzhiyun 	}
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	return fac;
1287*4882a593Smuzhiyun }
1288*4882a593Smuzhiyun 
vop3_scale_up_fac_check(uint32_t src,uint32_t dst,uint32_t fac,bool is_hor)1289*4882a593Smuzhiyun static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor)
1290*4882a593Smuzhiyun {
1291*4882a593Smuzhiyun 	if (is_hor)
1292*4882a593Smuzhiyun 		return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac);
1293*4882a593Smuzhiyun 	return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac);
1294*4882a593Smuzhiyun }
1295*4882a593Smuzhiyun 
vop3_scale_factor(enum scale_mode mode,uint32_t src,uint32_t dst,bool is_hor)1296*4882a593Smuzhiyun static uint16_t vop3_scale_factor(enum scale_mode mode,
1297*4882a593Smuzhiyun 				  uint32_t src, uint32_t dst, bool is_hor)
1298*4882a593Smuzhiyun {
1299*4882a593Smuzhiyun 	uint32_t fac = 0;
1300*4882a593Smuzhiyun 	int i = 0;
1301*4882a593Smuzhiyun 
1302*4882a593Smuzhiyun 	if (mode == SCALE_NONE)
1303*4882a593Smuzhiyun 		return 0;
1304*4882a593Smuzhiyun 
1305*4882a593Smuzhiyun 	/*
1306*4882a593Smuzhiyun 	 * A workaround to avoid zero div.
1307*4882a593Smuzhiyun 	 */
1308*4882a593Smuzhiyun 	if ((dst == 1) || (src == 1)) {
1309*4882a593Smuzhiyun 		dst = dst + 1;
1310*4882a593Smuzhiyun 		src = src + 1;
1311*4882a593Smuzhiyun 	}
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	if (mode == SCALE_DOWN) {
1314*4882a593Smuzhiyun 		fac = VOP2_BILI_SCL_DN(src, dst);
1315*4882a593Smuzhiyun 		for (i = 0; i < 100; i++) {
1316*4882a593Smuzhiyun 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
1317*4882a593Smuzhiyun 				break;
1318*4882a593Smuzhiyun 			fac -= 1;
1319*4882a593Smuzhiyun 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1320*4882a593Smuzhiyun 		}
1321*4882a593Smuzhiyun 	} else {
1322*4882a593Smuzhiyun 		fac = VOP2_COMMON_SCL(src, dst);
1323*4882a593Smuzhiyun 		for (i = 0; i < 100; i++) {
1324*4882a593Smuzhiyun 			if (vop3_scale_up_fac_check(src, dst, fac, is_hor))
1325*4882a593Smuzhiyun 				break;
1326*4882a593Smuzhiyun 			fac -= 1;
1327*4882a593Smuzhiyun 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1328*4882a593Smuzhiyun 		}
1329*4882a593Smuzhiyun 	}
1330*4882a593Smuzhiyun 
1331*4882a593Smuzhiyun 	return fac;
1332*4882a593Smuzhiyun }
1333*4882a593Smuzhiyun 
scl_get_scl_mode(int src,int dst)1334*4882a593Smuzhiyun static inline enum scale_mode scl_get_scl_mode(int src, int dst)
1335*4882a593Smuzhiyun {
1336*4882a593Smuzhiyun 	if (src < dst)
1337*4882a593Smuzhiyun 		return SCALE_UP;
1338*4882a593Smuzhiyun 	else if (src > dst)
1339*4882a593Smuzhiyun 		return SCALE_DOWN;
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 	return SCALE_NONE;
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun 
interpolate(int x1,int y1,int x2,int y2,int x)1344*4882a593Smuzhiyun static inline int interpolate(int x1, int y1, int x2, int y2, int x)
1345*4882a593Smuzhiyun {
1346*4882a593Smuzhiyun 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun 
vop2_get_primary_plane(struct vop2 * vop2,u32 plane_mask)1349*4882a593Smuzhiyun static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask)
1350*4882a593Smuzhiyun {
1351*4882a593Smuzhiyun 	int i = 0;
1352*4882a593Smuzhiyun 
1353*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_layers; i++) {
1354*4882a593Smuzhiyun 		if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i]))
1355*4882a593Smuzhiyun 			return vop2->data->vp_primary_plane_order[i];
1356*4882a593Smuzhiyun 	}
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun 	return vop2->data->vp_primary_plane_order[0];
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun 
scl_cal_scale(int src,int dst,int shift)1361*4882a593Smuzhiyun static inline u16 scl_cal_scale(int src, int dst, int shift)
1362*4882a593Smuzhiyun {
1363*4882a593Smuzhiyun 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
1364*4882a593Smuzhiyun }
1365*4882a593Smuzhiyun 
scl_cal_scale2(int src,int dst)1366*4882a593Smuzhiyun static inline u16 scl_cal_scale2(int src, int dst)
1367*4882a593Smuzhiyun {
1368*4882a593Smuzhiyun 	return ((src - 1) << 12) / (dst - 1);
1369*4882a593Smuzhiyun }
1370*4882a593Smuzhiyun 
vop2_writel(struct vop2 * vop2,u32 offset,u32 v)1371*4882a593Smuzhiyun static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
1372*4882a593Smuzhiyun {
1373*4882a593Smuzhiyun 	writel(v, vop2->regs + offset);
1374*4882a593Smuzhiyun 	vop2->regsbak[offset >> 2] = v;
1375*4882a593Smuzhiyun }
1376*4882a593Smuzhiyun 
vop2_readl(struct vop2 * vop2,u32 offset)1377*4882a593Smuzhiyun static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
1378*4882a593Smuzhiyun {
1379*4882a593Smuzhiyun 	return readl(vop2->regs + offset);
1380*4882a593Smuzhiyun }
1381*4882a593Smuzhiyun 
vop2_mask_write(struct vop2 * vop2,u32 offset,u32 mask,u32 shift,u32 v,bool write_mask)1382*4882a593Smuzhiyun static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
1383*4882a593Smuzhiyun 				   u32 mask, u32 shift, u32 v,
1384*4882a593Smuzhiyun 				   bool write_mask)
1385*4882a593Smuzhiyun {
1386*4882a593Smuzhiyun 	if (!mask)
1387*4882a593Smuzhiyun 		return;
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun 	if (write_mask) {
1390*4882a593Smuzhiyun 		v = ((v & mask) << shift) | (mask << (shift + 16));
1391*4882a593Smuzhiyun 	} else {
1392*4882a593Smuzhiyun 		u32 cached_val = vop2->regsbak[offset >> 2];
1393*4882a593Smuzhiyun 
1394*4882a593Smuzhiyun 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
1395*4882a593Smuzhiyun 		vop2->regsbak[offset >> 2] = v;
1396*4882a593Smuzhiyun 	}
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun 	writel(v, vop2->regs + offset);
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun 
vop2_grf_writel(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift,u32 v)1401*4882a593Smuzhiyun static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
1402*4882a593Smuzhiyun 				   u32 mask, u32 shift, u32 v)
1403*4882a593Smuzhiyun {
1404*4882a593Smuzhiyun 	u32 val = 0;
1405*4882a593Smuzhiyun 
1406*4882a593Smuzhiyun 	val = (v << shift) | (mask << (shift + 16));
1407*4882a593Smuzhiyun 	writel(val, grf_base + offset);
1408*4882a593Smuzhiyun }
1409*4882a593Smuzhiyun 
vop2_grf_readl(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift)1410*4882a593Smuzhiyun static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
1411*4882a593Smuzhiyun 				  u32 mask, u32 shift)
1412*4882a593Smuzhiyun {
1413*4882a593Smuzhiyun 	return (readl(grf_base + offset) >> shift) & mask;
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun 
get_output_if_name(u32 output_if,char * name)1416*4882a593Smuzhiyun static char* get_output_if_name(u32 output_if, char *name)
1417*4882a593Smuzhiyun {
1418*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_RGB)
1419*4882a593Smuzhiyun 		strcat(name, " RGB");
1420*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_BT1120)
1421*4882a593Smuzhiyun 		strcat(name, " BT1120");
1422*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_BT656)
1423*4882a593Smuzhiyun 		strcat(name, " BT656");
1424*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_LVDS0)
1425*4882a593Smuzhiyun 		strcat(name, " LVDS0");
1426*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_LVDS1)
1427*4882a593Smuzhiyun 		strcat(name, " LVDS1");
1428*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_MIPI0)
1429*4882a593Smuzhiyun 		strcat(name, " MIPI0");
1430*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_MIPI1)
1431*4882a593Smuzhiyun 		strcat(name, " MIPI1");
1432*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_eDP0)
1433*4882a593Smuzhiyun 		strcat(name, " eDP0");
1434*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_eDP1)
1435*4882a593Smuzhiyun 		strcat(name, " eDP1");
1436*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_DP0)
1437*4882a593Smuzhiyun 		strcat(name, " DP0");
1438*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_DP1)
1439*4882a593Smuzhiyun 		strcat(name, " DP1");
1440*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_HDMI0)
1441*4882a593Smuzhiyun 		strcat(name, " HDMI0");
1442*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_HDMI1)
1443*4882a593Smuzhiyun 		strcat(name, " HDMI1");
1444*4882a593Smuzhiyun 
1445*4882a593Smuzhiyun 	return name;
1446*4882a593Smuzhiyun }
1447*4882a593Smuzhiyun 
get_plane_name(int plane_id,char * name)1448*4882a593Smuzhiyun static char *get_plane_name(int plane_id, char *name)
1449*4882a593Smuzhiyun {
1450*4882a593Smuzhiyun 	switch (plane_id) {
1451*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_CLUSTER0:
1452*4882a593Smuzhiyun 		strcat(name, "Cluster0");
1453*4882a593Smuzhiyun 		break;
1454*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_CLUSTER1:
1455*4882a593Smuzhiyun 		strcat(name, "Cluster1");
1456*4882a593Smuzhiyun 		break;
1457*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_ESMART0:
1458*4882a593Smuzhiyun 		strcat(name, "Esmart0");
1459*4882a593Smuzhiyun 		break;
1460*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_ESMART1:
1461*4882a593Smuzhiyun 		strcat(name, "Esmart1");
1462*4882a593Smuzhiyun 		break;
1463*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_SMART0:
1464*4882a593Smuzhiyun 		strcat(name, "Smart0");
1465*4882a593Smuzhiyun 		break;
1466*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_SMART1:
1467*4882a593Smuzhiyun 		strcat(name, "Smart1");
1468*4882a593Smuzhiyun 		break;
1469*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_CLUSTER2:
1470*4882a593Smuzhiyun 		strcat(name, "Cluster2");
1471*4882a593Smuzhiyun 		break;
1472*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_CLUSTER3:
1473*4882a593Smuzhiyun 		strcat(name, "Cluster3");
1474*4882a593Smuzhiyun 		break;
1475*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_ESMART2:
1476*4882a593Smuzhiyun 		strcat(name, "Esmart2");
1477*4882a593Smuzhiyun 		break;
1478*4882a593Smuzhiyun 	case ROCKCHIP_VOP2_ESMART3:
1479*4882a593Smuzhiyun 		strcat(name, "Esmart3");
1480*4882a593Smuzhiyun 		break;
1481*4882a593Smuzhiyun 	}
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 	return name;
1484*4882a593Smuzhiyun }
1485*4882a593Smuzhiyun 
is_yuv_output(u32 bus_format)1486*4882a593Smuzhiyun static bool is_yuv_output(u32 bus_format)
1487*4882a593Smuzhiyun {
1488*4882a593Smuzhiyun 	switch (bus_format) {
1489*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV8_1X24:
1490*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV10_1X30:
1491*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV10_1X20:
1492*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1493*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1494*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_2X8:
1495*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YVYU8_2X8:
1496*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY8_2X8:
1497*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_VYUY8_2X8:
1498*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_1X16:
1499*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YVYU8_1X16:
1500*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY8_1X16:
1501*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_VYUY8_1X16:
1502*4882a593Smuzhiyun 		return true;
1503*4882a593Smuzhiyun 	default:
1504*4882a593Smuzhiyun 		return false;
1505*4882a593Smuzhiyun 	}
1506*4882a593Smuzhiyun }
1507*4882a593Smuzhiyun 
vop2_convert_csc_mode(int csc_mode,int bit_depth)1508*4882a593Smuzhiyun static int vop2_convert_csc_mode(int csc_mode, int bit_depth)
1509*4882a593Smuzhiyun {
1510*4882a593Smuzhiyun 	switch (csc_mode) {
1511*4882a593Smuzhiyun 	case V4L2_COLORSPACE_SMPTE170M:
1512*4882a593Smuzhiyun 	case V4L2_COLORSPACE_470_SYSTEM_M:
1513*4882a593Smuzhiyun 	case V4L2_COLORSPACE_470_SYSTEM_BG:
1514*4882a593Smuzhiyun 		return CSC_BT601L;
1515*4882a593Smuzhiyun 	case V4L2_COLORSPACE_REC709:
1516*4882a593Smuzhiyun 	case V4L2_COLORSPACE_SMPTE240M:
1517*4882a593Smuzhiyun 	case V4L2_COLORSPACE_DEFAULT:
1518*4882a593Smuzhiyun 		if (bit_depth == CSC_13BIT_DEPTH)
1519*4882a593Smuzhiyun 			return CSC_BT709L_13BIT;
1520*4882a593Smuzhiyun 		else
1521*4882a593Smuzhiyun 			return CSC_BT709L;
1522*4882a593Smuzhiyun 	case V4L2_COLORSPACE_JPEG:
1523*4882a593Smuzhiyun 		return CSC_BT601F;
1524*4882a593Smuzhiyun 	case V4L2_COLORSPACE_BT2020:
1525*4882a593Smuzhiyun 		if (bit_depth == CSC_13BIT_DEPTH)
1526*4882a593Smuzhiyun 			return CSC_BT2020L_13BIT;
1527*4882a593Smuzhiyun 		else
1528*4882a593Smuzhiyun 			return CSC_BT2020;
1529*4882a593Smuzhiyun 	case V4L2_COLORSPACE_BT709F:
1530*4882a593Smuzhiyun 		if (bit_depth == CSC_10BIT_DEPTH) {
1531*4882a593Smuzhiyun 			printf("WARN: Unsupported bt709f at 10bit csc depth, use bt601f instead\n");
1532*4882a593Smuzhiyun 			return CSC_BT601F;
1533*4882a593Smuzhiyun 		} else {
1534*4882a593Smuzhiyun 			return CSC_BT709F_13BIT;
1535*4882a593Smuzhiyun 		}
1536*4882a593Smuzhiyun 	case V4L2_COLORSPACE_BT2020F:
1537*4882a593Smuzhiyun 		if (bit_depth == CSC_10BIT_DEPTH) {
1538*4882a593Smuzhiyun 			printf("WARN: Unsupported bt2020f at 10bit csc depth, use bt601f instead\n");
1539*4882a593Smuzhiyun 			return CSC_BT601F;
1540*4882a593Smuzhiyun 		} else {
1541*4882a593Smuzhiyun 			return CSC_BT2020F_13BIT;
1542*4882a593Smuzhiyun 		}
1543*4882a593Smuzhiyun 	default:
1544*4882a593Smuzhiyun 		return CSC_BT709L;
1545*4882a593Smuzhiyun 	}
1546*4882a593Smuzhiyun }
1547*4882a593Smuzhiyun 
is_uv_swap(u32 bus_format,u32 output_mode)1548*4882a593Smuzhiyun static bool is_uv_swap(u32 bus_format, u32 output_mode)
1549*4882a593Smuzhiyun {
1550*4882a593Smuzhiyun 	/*
1551*4882a593Smuzhiyun 	 * FIXME:
1552*4882a593Smuzhiyun 	 *
1553*4882a593Smuzhiyun 	 * There is no media type for YUV444 output,
1554*4882a593Smuzhiyun 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
1555*4882a593Smuzhiyun 	 * yuv format.
1556*4882a593Smuzhiyun 	 *
1557*4882a593Smuzhiyun 	 * From H/W testing, YUV444 mode need a rb swap.
1558*4882a593Smuzhiyun 	 */
1559*4882a593Smuzhiyun 	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
1560*4882a593Smuzhiyun 	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
1561*4882a593Smuzhiyun 	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
1562*4882a593Smuzhiyun 	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
1563*4882a593Smuzhiyun 	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1564*4882a593Smuzhiyun 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1565*4882a593Smuzhiyun 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
1566*4882a593Smuzhiyun 	     output_mode == ROCKCHIP_OUT_MODE_P888)))
1567*4882a593Smuzhiyun 		return true;
1568*4882a593Smuzhiyun 	else
1569*4882a593Smuzhiyun 		return false;
1570*4882a593Smuzhiyun }
1571*4882a593Smuzhiyun 
is_rb_swap(u32 bus_format,u32 output_mode)1572*4882a593Smuzhiyun static bool is_rb_swap(u32 bus_format, u32 output_mode)
1573*4882a593Smuzhiyun {
1574*4882a593Smuzhiyun 	/*
1575*4882a593Smuzhiyun 	 * The default component order of serial rgb3x8 formats
1576*4882a593Smuzhiyun 	 * is BGR. So it is needed to enable RB swap.
1577*4882a593Smuzhiyun 	 */
1578*4882a593Smuzhiyun 	if (bus_format == MEDIA_BUS_FMT_SRGB888_3X8 ||
1579*4882a593Smuzhiyun 	    bus_format == MEDIA_BUS_FMT_SRGB888_DUMMY_4X8)
1580*4882a593Smuzhiyun 		return true;
1581*4882a593Smuzhiyun 	else
1582*4882a593Smuzhiyun 		return false;
1583*4882a593Smuzhiyun }
1584*4882a593Smuzhiyun 
is_hot_plug_devices(int output_type)1585*4882a593Smuzhiyun static inline bool is_hot_plug_devices(int output_type)
1586*4882a593Smuzhiyun {
1587*4882a593Smuzhiyun 	switch (output_type) {
1588*4882a593Smuzhiyun 	case DRM_MODE_CONNECTOR_HDMIA:
1589*4882a593Smuzhiyun 	case DRM_MODE_CONNECTOR_HDMIB:
1590*4882a593Smuzhiyun 	case DRM_MODE_CONNECTOR_TV:
1591*4882a593Smuzhiyun 	case DRM_MODE_CONNECTOR_DisplayPort:
1592*4882a593Smuzhiyun 	case DRM_MODE_CONNECTOR_VGA:
1593*4882a593Smuzhiyun 	case DRM_MODE_CONNECTOR_Unknown:
1594*4882a593Smuzhiyun 		return true;
1595*4882a593Smuzhiyun 	default:
1596*4882a593Smuzhiyun 		return false;
1597*4882a593Smuzhiyun 	}
1598*4882a593Smuzhiyun }
1599*4882a593Smuzhiyun 
vop2_find_win_by_phys_id(struct vop2 * vop2,int phys_id)1600*4882a593Smuzhiyun static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1601*4882a593Smuzhiyun {
1602*4882a593Smuzhiyun 	int i = 0;
1603*4882a593Smuzhiyun 
1604*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_layers; i++) {
1605*4882a593Smuzhiyun 		if (vop2->data->win_data[i].phys_id == phys_id)
1606*4882a593Smuzhiyun 			return &vop2->data->win_data[i];
1607*4882a593Smuzhiyun 	}
1608*4882a593Smuzhiyun 
1609*4882a593Smuzhiyun 	return NULL;
1610*4882a593Smuzhiyun }
1611*4882a593Smuzhiyun 
vop2_find_pd_data_by_id(struct vop2 * vop2,int pd_id)1612*4882a593Smuzhiyun static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id)
1613*4882a593Smuzhiyun {
1614*4882a593Smuzhiyun 	int i = 0;
1615*4882a593Smuzhiyun 
1616*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_pd; i++) {
1617*4882a593Smuzhiyun 		if (vop2->data->pd[i].id == pd_id)
1618*4882a593Smuzhiyun 			return &vop2->data->pd[i];
1619*4882a593Smuzhiyun 	}
1620*4882a593Smuzhiyun 
1621*4882a593Smuzhiyun 	return NULL;
1622*4882a593Smuzhiyun }
1623*4882a593Smuzhiyun 
rk3568_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1624*4882a593Smuzhiyun static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1625*4882a593Smuzhiyun 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1626*4882a593Smuzhiyun {
1627*4882a593Smuzhiyun 	u32 vp_offset = crtc_id * 0x100;
1628*4882a593Smuzhiyun 	int i;
1629*4882a593Smuzhiyun 
1630*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1631*4882a593Smuzhiyun 			GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1632*4882a593Smuzhiyun 			crtc_id, false);
1633*4882a593Smuzhiyun 
1634*4882a593Smuzhiyun 	for (i = 0; i < lut_len; i++)
1635*4882a593Smuzhiyun 		writel(lut_val[i], lut_regs + i);
1636*4882a593Smuzhiyun 
1637*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1638*4882a593Smuzhiyun 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1639*4882a593Smuzhiyun }
1640*4882a593Smuzhiyun 
rk3588_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1641*4882a593Smuzhiyun static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1642*4882a593Smuzhiyun 				 u32 *lut_regs, u32 *lut_val, int lut_len)
1643*4882a593Smuzhiyun {
1644*4882a593Smuzhiyun 	u32 vp_offset = crtc_id * 0x100;
1645*4882a593Smuzhiyun 	int i;
1646*4882a593Smuzhiyun 
1647*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1648*4882a593Smuzhiyun 			GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1649*4882a593Smuzhiyun 			crtc_id, false);
1650*4882a593Smuzhiyun 
1651*4882a593Smuzhiyun 	for (i = 0; i < lut_len; i++)
1652*4882a593Smuzhiyun 		writel(lut_val[i], lut_regs + i);
1653*4882a593Smuzhiyun 
1654*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1655*4882a593Smuzhiyun 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1656*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1657*4882a593Smuzhiyun 			EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false);
1658*4882a593Smuzhiyun }
1659*4882a593Smuzhiyun 
rockchip_vop2_gamma_lut_init(struct vop2 * vop2,struct display_state * state)1660*4882a593Smuzhiyun static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1661*4882a593Smuzhiyun 					struct display_state *state)
1662*4882a593Smuzhiyun {
1663*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
1664*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1665*4882a593Smuzhiyun 	struct resource gamma_res;
1666*4882a593Smuzhiyun 	fdt_size_t lut_size;
1667*4882a593Smuzhiyun 	int i, lut_len, ret = 0;
1668*4882a593Smuzhiyun 	u32 *lut_regs;
1669*4882a593Smuzhiyun 	u32 *lut_val;
1670*4882a593Smuzhiyun 	u32 r, g, b;
1671*4882a593Smuzhiyun 	struct base2_disp_info *disp_info = conn_state->disp_info;
1672*4882a593Smuzhiyun 	static int gamma_lut_en_num = 1;
1673*4882a593Smuzhiyun 
1674*4882a593Smuzhiyun 	if (gamma_lut_en_num > vop2->data->nr_gammas) {
1675*4882a593Smuzhiyun 		printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
1676*4882a593Smuzhiyun 		return 0;
1677*4882a593Smuzhiyun 	}
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun 	if (!disp_info)
1680*4882a593Smuzhiyun 		return 0;
1681*4882a593Smuzhiyun 
1682*4882a593Smuzhiyun 	if (!disp_info->gamma_lut_data.size)
1683*4882a593Smuzhiyun 		return 0;
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
1686*4882a593Smuzhiyun 	if (ret)
1687*4882a593Smuzhiyun 		printf("failed to get gamma lut res\n");
1688*4882a593Smuzhiyun 	lut_regs = (u32 *)gamma_res.start;
1689*4882a593Smuzhiyun 	lut_size = gamma_res.end - gamma_res.start + 1;
1690*4882a593Smuzhiyun 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
1691*4882a593Smuzhiyun 		printf("failed to get gamma lut register\n");
1692*4882a593Smuzhiyun 		return 0;
1693*4882a593Smuzhiyun 	}
1694*4882a593Smuzhiyun 	lut_len = lut_size / 4;
1695*4882a593Smuzhiyun 	if (lut_len != 256 && lut_len != 1024) {
1696*4882a593Smuzhiyun 		printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
1697*4882a593Smuzhiyun 		return 0;
1698*4882a593Smuzhiyun 	}
1699*4882a593Smuzhiyun 	lut_val = (u32 *)calloc(1, lut_size);
1700*4882a593Smuzhiyun 	for (i = 0; i < lut_len; i++) {
1701*4882a593Smuzhiyun 		r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
1702*4882a593Smuzhiyun 		g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
1703*4882a593Smuzhiyun 		b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
1704*4882a593Smuzhiyun 
1705*4882a593Smuzhiyun 		lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
1706*4882a593Smuzhiyun 	}
1707*4882a593Smuzhiyun 
1708*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3568) {
1709*4882a593Smuzhiyun 		rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len);
1710*4882a593Smuzhiyun 		gamma_lut_en_num++;
1711*4882a593Smuzhiyun 	} else if (vop2->version == VOP_VERSION_RK3588) {
1712*4882a593Smuzhiyun 		rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len);
1713*4882a593Smuzhiyun 		if (cstate->splice_mode) {
1714*4882a593Smuzhiyun 			rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, lut_val, lut_len);
1715*4882a593Smuzhiyun 			gamma_lut_en_num++;
1716*4882a593Smuzhiyun 		}
1717*4882a593Smuzhiyun 		gamma_lut_en_num++;
1718*4882a593Smuzhiyun 	}
1719*4882a593Smuzhiyun 
1720*4882a593Smuzhiyun 	return 0;
1721*4882a593Smuzhiyun }
1722*4882a593Smuzhiyun 
rockchip_vop2_cubic_lut_init(struct vop2 * vop2,struct display_state * state)1723*4882a593Smuzhiyun static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
1724*4882a593Smuzhiyun 					struct display_state *state)
1725*4882a593Smuzhiyun {
1726*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
1727*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1728*4882a593Smuzhiyun 	int i, cubic_lut_len;
1729*4882a593Smuzhiyun 	u32 vp_offset = cstate->crtc_id * 0x100;
1730*4882a593Smuzhiyun 	struct base2_disp_info *disp_info = conn_state->disp_info;
1731*4882a593Smuzhiyun 	struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
1732*4882a593Smuzhiyun 	u32 *cubic_lut_addr;
1733*4882a593Smuzhiyun 
1734*4882a593Smuzhiyun 	if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
1735*4882a593Smuzhiyun 		return 0;
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun 	if (!disp_info->cubic_lut_data.size)
1738*4882a593Smuzhiyun 		return 0;
1739*4882a593Smuzhiyun 
1740*4882a593Smuzhiyun 	cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
1741*4882a593Smuzhiyun 	cubic_lut_len = disp_info->cubic_lut_data.size;
1742*4882a593Smuzhiyun 
1743*4882a593Smuzhiyun 	for (i = 0; i < cubic_lut_len / 2; i++) {
1744*4882a593Smuzhiyun 		*cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
1745*4882a593Smuzhiyun 					((lut->lgreen[2 * i] & 0xfff) << 12) +
1746*4882a593Smuzhiyun 					((lut->lblue[2 * i] & 0xff) << 24);
1747*4882a593Smuzhiyun 		*cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
1748*4882a593Smuzhiyun 					((lut->lred[2 * i + 1] & 0xfff) << 4) +
1749*4882a593Smuzhiyun 					((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
1750*4882a593Smuzhiyun 					((lut->lblue[2 * i + 1] & 0xf) << 28);
1751*4882a593Smuzhiyun 		*cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
1752*4882a593Smuzhiyun 		*cubic_lut_addr++ = 0;
1753*4882a593Smuzhiyun 	}
1754*4882a593Smuzhiyun 
1755*4882a593Smuzhiyun 	if (cubic_lut_len % 2) {
1756*4882a593Smuzhiyun 		*cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
1757*4882a593Smuzhiyun 					((lut->lgreen[2 * i] & 0xfff) << 12) +
1758*4882a593Smuzhiyun 					((lut->lblue[2 * i] & 0xff) << 24);
1759*4882a593Smuzhiyun 		*cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
1760*4882a593Smuzhiyun 		*cubic_lut_addr++ = 0;
1761*4882a593Smuzhiyun 		*cubic_lut_addr = 0;
1762*4882a593Smuzhiyun 	}
1763*4882a593Smuzhiyun 
1764*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
1765*4882a593Smuzhiyun 		    get_cubic_lut_buffer(cstate->crtc_id));
1766*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
1767*4882a593Smuzhiyun 			EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
1768*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
1769*4882a593Smuzhiyun 			EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
1770*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
1771*4882a593Smuzhiyun 			EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
1772*4882a593Smuzhiyun 
1773*4882a593Smuzhiyun 	return 0;
1774*4882a593Smuzhiyun }
1775*4882a593Smuzhiyun 
vop2_bcsh_reg_update(struct display_state * state,struct vop2 * vop2,struct bcsh_state * bcsh_state,int crtc_id)1776*4882a593Smuzhiyun static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2,
1777*4882a593Smuzhiyun 				 struct bcsh_state *bcsh_state, int crtc_id)
1778*4882a593Smuzhiyun {
1779*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1780*4882a593Smuzhiyun 	u32 vp_offset = crtc_id * 0x100;
1781*4882a593Smuzhiyun 
1782*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
1783*4882a593Smuzhiyun 			BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false);
1784*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
1785*4882a593Smuzhiyun 			BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false);
1786*4882a593Smuzhiyun 
1787*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
1788*4882a593Smuzhiyun 			BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
1789*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
1790*4882a593Smuzhiyun 			BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
1791*4882a593Smuzhiyun 
1792*4882a593Smuzhiyun 	if (!cstate->bcsh_en) {
1793*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1794*4882a593Smuzhiyun 				BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
1795*4882a593Smuzhiyun 		return;
1796*4882a593Smuzhiyun 	}
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1799*4882a593Smuzhiyun 			BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
1800*4882a593Smuzhiyun 			bcsh_state->brightness, false);
1801*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1802*4882a593Smuzhiyun 			BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false);
1803*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1804*4882a593Smuzhiyun 			BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
1805*4882a593Smuzhiyun 			bcsh_state->saturation * bcsh_state->contrast / 0x100, false);
1806*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1807*4882a593Smuzhiyun 			BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false);
1808*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1809*4882a593Smuzhiyun 			BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false);
1810*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1811*4882a593Smuzhiyun 			BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
1812*4882a593Smuzhiyun 			BCSH_OUT_MODE_NORMAL_VIDEO, false);
1813*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1814*4882a593Smuzhiyun 			BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
1815*4882a593Smuzhiyun }
1816*4882a593Smuzhiyun 
vop2_tv_config_update(struct display_state * state,struct vop2 * vop2)1817*4882a593Smuzhiyun static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
1818*4882a593Smuzhiyun {
1819*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
1820*4882a593Smuzhiyun 	struct base_bcsh_info *bcsh_info;
1821*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1822*4882a593Smuzhiyun 	struct bcsh_state bcsh_state;
1823*4882a593Smuzhiyun 	int brightness, contrast, saturation, hue, sin_hue, cos_hue;
1824*4882a593Smuzhiyun 
1825*4882a593Smuzhiyun 	if (!conn_state->disp_info)
1826*4882a593Smuzhiyun 		return;
1827*4882a593Smuzhiyun 	bcsh_info = &conn_state->disp_info->bcsh_info;
1828*4882a593Smuzhiyun 	if (!bcsh_info)
1829*4882a593Smuzhiyun 		return;
1830*4882a593Smuzhiyun 
1831*4882a593Smuzhiyun 	if (bcsh_info->brightness != 50 ||
1832*4882a593Smuzhiyun 	    bcsh_info->contrast != 50 ||
1833*4882a593Smuzhiyun 	    bcsh_info->saturation != 50 || bcsh_info->hue != 50)
1834*4882a593Smuzhiyun 		cstate->bcsh_en = true;
1835*4882a593Smuzhiyun 
1836*4882a593Smuzhiyun 	if (cstate->bcsh_en) {
1837*4882a593Smuzhiyun 		if (!cstate->yuv_overlay)
1838*4882a593Smuzhiyun 			cstate->post_r2y_en = 1;
1839*4882a593Smuzhiyun 		if (!is_yuv_output(conn_state->bus_format))
1840*4882a593Smuzhiyun 			cstate->post_y2r_en = 1;
1841*4882a593Smuzhiyun 	} else {
1842*4882a593Smuzhiyun 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
1843*4882a593Smuzhiyun 			cstate->post_r2y_en = 1;
1844*4882a593Smuzhiyun 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
1845*4882a593Smuzhiyun 			cstate->post_y2r_en = 1;
1846*4882a593Smuzhiyun 	}
1847*4882a593Smuzhiyun 
1848*4882a593Smuzhiyun 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH);
1849*4882a593Smuzhiyun 
1850*4882a593Smuzhiyun 	if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
1851*4882a593Smuzhiyun 		brightness = interpolate(0, -128, 100, 127,
1852*4882a593Smuzhiyun 					 bcsh_info->brightness);
1853*4882a593Smuzhiyun 	else
1854*4882a593Smuzhiyun 		brightness = interpolate(0, -32, 100, 31,
1855*4882a593Smuzhiyun 					 bcsh_info->brightness);
1856*4882a593Smuzhiyun 	contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
1857*4882a593Smuzhiyun 	saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
1858*4882a593Smuzhiyun 	hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
1859*4882a593Smuzhiyun 
1860*4882a593Smuzhiyun 
1861*4882a593Smuzhiyun 	/*
1862*4882a593Smuzhiyun 	 *  a:[-30~0):
1863*4882a593Smuzhiyun 	 *    sin_hue = 0x100 - sin(a)*256;
1864*4882a593Smuzhiyun 	 *    cos_hue = cos(a)*256;
1865*4882a593Smuzhiyun 	 *  a:[0~30]
1866*4882a593Smuzhiyun 	 *    sin_hue = sin(a)*256;
1867*4882a593Smuzhiyun 	 *    cos_hue = cos(a)*256;
1868*4882a593Smuzhiyun 	 */
1869*4882a593Smuzhiyun 	sin_hue = fixp_sin32(hue) >> 23;
1870*4882a593Smuzhiyun 	cos_hue = fixp_cos32(hue) >> 23;
1871*4882a593Smuzhiyun 
1872*4882a593Smuzhiyun 	bcsh_state.brightness = brightness;
1873*4882a593Smuzhiyun 	bcsh_state.contrast = contrast;
1874*4882a593Smuzhiyun 	bcsh_state.saturation = saturation;
1875*4882a593Smuzhiyun 	bcsh_state.sin_hue = sin_hue;
1876*4882a593Smuzhiyun 	bcsh_state.cos_hue = cos_hue;
1877*4882a593Smuzhiyun 
1878*4882a593Smuzhiyun 	vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id);
1879*4882a593Smuzhiyun 	if (cstate->splice_mode)
1880*4882a593Smuzhiyun 		vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id);
1881*4882a593Smuzhiyun }
1882*4882a593Smuzhiyun 
vop2_setup_dly_for_vp(struct display_state * state,struct vop2 * vop2,int crtc_id)1883*4882a593Smuzhiyun static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id)
1884*4882a593Smuzhiyun {
1885*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
1886*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
1887*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1888*4882a593Smuzhiyun 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
1889*4882a593Smuzhiyun 	u16 hdisplay = mode->crtc_hdisplay;
1890*4882a593Smuzhiyun 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
1891*4882a593Smuzhiyun 
1892*4882a593Smuzhiyun 	bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly;
1893*4882a593Smuzhiyun 	bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly;
1894*4882a593Smuzhiyun 	bg_dly -= bg_ovl_dly;
1895*4882a593Smuzhiyun 
1896*4882a593Smuzhiyun 	if (cstate->splice_mode)
1897*4882a593Smuzhiyun 		pre_scan_dly = bg_dly + (hdisplay >> 2) - 1;
1898*4882a593Smuzhiyun 	else
1899*4882a593Smuzhiyun 		pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
1900*4882a593Smuzhiyun 
1901*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
1902*4882a593Smuzhiyun 		hsync_len = 8;
1903*4882a593Smuzhiyun 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
1904*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4,
1905*4882a593Smuzhiyun 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
1906*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
1907*4882a593Smuzhiyun }
1908*4882a593Smuzhiyun 
vop3_setup_pipe_dly(struct display_state * state,struct vop2 * vop2,int crtc_id)1909*4882a593Smuzhiyun static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id)
1910*4882a593Smuzhiyun {
1911*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
1912*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
1913*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1914*4882a593Smuzhiyun 	struct vop2_win_data *win_data;
1915*4882a593Smuzhiyun 	u32 bg_dly, pre_scan_dly;
1916*4882a593Smuzhiyun 	u16 hdisplay = mode->crtc_hdisplay;
1917*4882a593Smuzhiyun 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
1918*4882a593Smuzhiyun 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
1919*4882a593Smuzhiyun 	u8 win_id;
1920*4882a593Smuzhiyun 
1921*4882a593Smuzhiyun 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
1922*4882a593Smuzhiyun 	win_id = atoi(&win_data->name[strlen(win_data->name) - 1]);
1923*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL + win_id * 4,
1924*4882a593Smuzhiyun 			ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 0, false);
1925*4882a593Smuzhiyun 
1926*4882a593Smuzhiyun 	bg_dly = vop2->data->vp_data[crtc_id].win_dly +
1927*4882a593Smuzhiyun 		 vop2->data->vp_data[crtc_id].layer_mix_dly +
1928*4882a593Smuzhiyun 		 vop2->data->vp_data[crtc_id].hdr_mix_dly;
1929*4882a593Smuzhiyun 	pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
1930*4882a593Smuzhiyun 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
1931*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100,
1932*4882a593Smuzhiyun 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
1933*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
1934*4882a593Smuzhiyun }
1935*4882a593Smuzhiyun 
vop2_post_config(struct display_state * state,struct vop2 * vop2)1936*4882a593Smuzhiyun static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
1937*4882a593Smuzhiyun {
1938*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
1939*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
1940*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1941*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
1942*4882a593Smuzhiyun 	u16 vtotal = mode->crtc_vtotal;
1943*4882a593Smuzhiyun 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
1944*4882a593Smuzhiyun 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
1945*4882a593Smuzhiyun 	u16 hdisplay = mode->crtc_hdisplay;
1946*4882a593Smuzhiyun 	u16 vdisplay = mode->crtc_vdisplay;
1947*4882a593Smuzhiyun 	u16 hsize =
1948*4882a593Smuzhiyun 	    hdisplay * (conn_state->overscan.left_margin +
1949*4882a593Smuzhiyun 			conn_state->overscan.right_margin) / 200;
1950*4882a593Smuzhiyun 	u16 vsize =
1951*4882a593Smuzhiyun 	    vdisplay * (conn_state->overscan.top_margin +
1952*4882a593Smuzhiyun 			conn_state->overscan.bottom_margin) / 200;
1953*4882a593Smuzhiyun 	u16 hact_end, vact_end;
1954*4882a593Smuzhiyun 	u32 val;
1955*4882a593Smuzhiyun 
1956*4882a593Smuzhiyun 	hsize = round_down(hsize, 2);
1957*4882a593Smuzhiyun 	vsize = round_down(vsize, 2);
1958*4882a593Smuzhiyun 
1959*4882a593Smuzhiyun 	hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
1960*4882a593Smuzhiyun 	hact_end = hact_st + hsize;
1961*4882a593Smuzhiyun 	val = hact_st << 16;
1962*4882a593Smuzhiyun 	val |= hact_end;
1963*4882a593Smuzhiyun 
1964*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
1965*4882a593Smuzhiyun 	vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
1966*4882a593Smuzhiyun 	vact_end = vact_st + vsize;
1967*4882a593Smuzhiyun 	val = vact_st << 16;
1968*4882a593Smuzhiyun 	val |= vact_end;
1969*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
1970*4882a593Smuzhiyun 	val = scl_cal_scale2(vdisplay, vsize) << 16;
1971*4882a593Smuzhiyun 	val |= scl_cal_scale2(hdisplay, hsize);
1972*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
1973*4882a593Smuzhiyun #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
1974*4882a593Smuzhiyun #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
1975*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
1976*4882a593Smuzhiyun 		    POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
1977*4882a593Smuzhiyun 		    POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
1978*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1979*4882a593Smuzhiyun 		u16 vact_st_f1 = vtotal + vact_st + 1;
1980*4882a593Smuzhiyun 		u16 vact_end_f1 = vact_st_f1 + vsize;
1981*4882a593Smuzhiyun 
1982*4882a593Smuzhiyun 		val = vact_st_f1 << 16 | vact_end_f1;
1983*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
1984*4882a593Smuzhiyun 	}
1985*4882a593Smuzhiyun 
1986*4882a593Smuzhiyun 	if (is_vop3(vop2)) {
1987*4882a593Smuzhiyun 		vop3_setup_pipe_dly(state, vop2, cstate->crtc_id);
1988*4882a593Smuzhiyun 	} else {
1989*4882a593Smuzhiyun 		vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id);
1990*4882a593Smuzhiyun 		if (cstate->splice_mode)
1991*4882a593Smuzhiyun 			vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id);
1992*4882a593Smuzhiyun 	}
1993*4882a593Smuzhiyun }
1994*4882a593Smuzhiyun 
vop3_post_acm_config(struct display_state * state,struct vop2 * vop2)1995*4882a593Smuzhiyun static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2)
1996*4882a593Smuzhiyun {
1997*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
1998*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
1999*4882a593Smuzhiyun 	struct acm_data *acm = &conn_state->disp_info->acm_data;
2000*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
2001*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
2002*4882a593Smuzhiyun 	s16 *lut_y;
2003*4882a593Smuzhiyun 	s16 *lut_h;
2004*4882a593Smuzhiyun 	s16 *lut_s;
2005*4882a593Smuzhiyun 	u32 value;
2006*4882a593Smuzhiyun 	int i;
2007*4882a593Smuzhiyun 
2008*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2009*4882a593Smuzhiyun 		POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2010*4882a593Smuzhiyun 	if (!acm->acm_enable) {
2011*4882a593Smuzhiyun 		writel(0, vop2->regs + RK3528_ACM_CTRL);
2012*4882a593Smuzhiyun 		return;
2013*4882a593Smuzhiyun 	}
2014*4882a593Smuzhiyun 
2015*4882a593Smuzhiyun 	printf("post acm enable\n");
2016*4882a593Smuzhiyun 
2017*4882a593Smuzhiyun 	writel(1, vop2->regs + RK3528_ACM_FETCH_START);
2018*4882a593Smuzhiyun 
2019*4882a593Smuzhiyun 	value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) +
2020*4882a593Smuzhiyun 		((mode->vdisplay & 0xfff) << 20);
2021*4882a593Smuzhiyun 	writel(value, vop2->regs + RK3528_ACM_CTRL);
2022*4882a593Smuzhiyun 
2023*4882a593Smuzhiyun 	value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
2024*4882a593Smuzhiyun 		((acm->s_gain << 20) & 0x3ff00000);
2025*4882a593Smuzhiyun 	writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE);
2026*4882a593Smuzhiyun 
2027*4882a593Smuzhiyun 	lut_y = &acm->gain_lut_hy[0];
2028*4882a593Smuzhiyun 	lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
2029*4882a593Smuzhiyun 	lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
2030*4882a593Smuzhiyun 	for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
2031*4882a593Smuzhiyun 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
2032*4882a593Smuzhiyun 			((lut_s[i] << 16) & 0xff0000);
2033*4882a593Smuzhiyun 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
2034*4882a593Smuzhiyun 	}
2035*4882a593Smuzhiyun 
2036*4882a593Smuzhiyun 	lut_y = &acm->gain_lut_hs[0];
2037*4882a593Smuzhiyun 	lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
2038*4882a593Smuzhiyun 	lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
2039*4882a593Smuzhiyun 	for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
2040*4882a593Smuzhiyun 		value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
2041*4882a593Smuzhiyun 			((lut_s[i] << 16) & 0xff0000);
2042*4882a593Smuzhiyun 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
2043*4882a593Smuzhiyun 	}
2044*4882a593Smuzhiyun 
2045*4882a593Smuzhiyun 	lut_y = &acm->delta_lut_h[0];
2046*4882a593Smuzhiyun 	lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
2047*4882a593Smuzhiyun 	lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
2048*4882a593Smuzhiyun 	for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
2049*4882a593Smuzhiyun 		value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
2050*4882a593Smuzhiyun 			((lut_s[i] << 20) & 0x3ff00000);
2051*4882a593Smuzhiyun 		writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
2052*4882a593Smuzhiyun 	}
2053*4882a593Smuzhiyun 
2054*4882a593Smuzhiyun 	writel(1, vop2->regs + RK3528_ACM_FETCH_DONE);
2055*4882a593Smuzhiyun }
2056*4882a593Smuzhiyun 
vop3_post_csc_config(struct display_state * state,struct vop2 * vop2)2057*4882a593Smuzhiyun static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2)
2058*4882a593Smuzhiyun {
2059*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
2060*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2061*4882a593Smuzhiyun 	struct acm_data *acm = &conn_state->disp_info->acm_data;
2062*4882a593Smuzhiyun 	struct csc_info *csc = &conn_state->disp_info->csc_info;
2063*4882a593Smuzhiyun 	struct post_csc_coef csc_coef;
2064*4882a593Smuzhiyun 	bool is_input_yuv = false;
2065*4882a593Smuzhiyun 	bool is_output_yuv = false;
2066*4882a593Smuzhiyun 	bool post_r2y_en = false;
2067*4882a593Smuzhiyun 	bool post_csc_en = false;
2068*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
2069*4882a593Smuzhiyun 	u32 value;
2070*4882a593Smuzhiyun 	int range_type;
2071*4882a593Smuzhiyun 
2072*4882a593Smuzhiyun 	printf("post csc enable\n");
2073*4882a593Smuzhiyun 
2074*4882a593Smuzhiyun 	if (acm->acm_enable) {
2075*4882a593Smuzhiyun 		if (!cstate->yuv_overlay)
2076*4882a593Smuzhiyun 			post_r2y_en = true;
2077*4882a593Smuzhiyun 
2078*4882a593Smuzhiyun 		/* do y2r in csc module */
2079*4882a593Smuzhiyun 		if (!is_yuv_output(conn_state->bus_format))
2080*4882a593Smuzhiyun 			post_csc_en = true;
2081*4882a593Smuzhiyun 	} else {
2082*4882a593Smuzhiyun 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2083*4882a593Smuzhiyun 			post_r2y_en = true;
2084*4882a593Smuzhiyun 
2085*4882a593Smuzhiyun 		/* do y2r in csc module */
2086*4882a593Smuzhiyun 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2087*4882a593Smuzhiyun 			post_csc_en = true;
2088*4882a593Smuzhiyun 	}
2089*4882a593Smuzhiyun 
2090*4882a593Smuzhiyun 	if (csc->csc_enable)
2091*4882a593Smuzhiyun 		post_csc_en = true;
2092*4882a593Smuzhiyun 
2093*4882a593Smuzhiyun 	if (cstate->yuv_overlay || post_r2y_en)
2094*4882a593Smuzhiyun 		is_input_yuv = true;
2095*4882a593Smuzhiyun 
2096*4882a593Smuzhiyun 	if (is_yuv_output(conn_state->bus_format))
2097*4882a593Smuzhiyun 		is_output_yuv = true;
2098*4882a593Smuzhiyun 
2099*4882a593Smuzhiyun 	cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_13BIT_DEPTH);
2100*4882a593Smuzhiyun 
2101*4882a593Smuzhiyun 	if (post_csc_en) {
2102*4882a593Smuzhiyun 		rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv,
2103*4882a593Smuzhiyun 				       is_output_yuv);
2104*4882a593Smuzhiyun 
2105*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2106*4882a593Smuzhiyun 				POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT,
2107*4882a593Smuzhiyun 				csc_coef.csc_coef00, false);
2108*4882a593Smuzhiyun 		value = csc_coef.csc_coef01 & 0xffff;
2109*4882a593Smuzhiyun 		value |= (csc_coef.csc_coef02 << 16) & 0xffff0000;
2110*4882a593Smuzhiyun 		writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02);
2111*4882a593Smuzhiyun 		value = csc_coef.csc_coef10 & 0xffff;
2112*4882a593Smuzhiyun 		value |= (csc_coef.csc_coef11 << 16) & 0xffff0000;
2113*4882a593Smuzhiyun 		writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11);
2114*4882a593Smuzhiyun 		value = csc_coef.csc_coef12 & 0xffff;
2115*4882a593Smuzhiyun 		value |= (csc_coef.csc_coef20 << 16) & 0xffff0000;
2116*4882a593Smuzhiyun 		writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20);
2117*4882a593Smuzhiyun 		value = csc_coef.csc_coef21 & 0xffff;
2118*4882a593Smuzhiyun 		value |= (csc_coef.csc_coef22 << 16) & 0xffff0000;
2119*4882a593Smuzhiyun 		writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22);
2120*4882a593Smuzhiyun 		writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0);
2121*4882a593Smuzhiyun 		writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1);
2122*4882a593Smuzhiyun 		writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2);
2123*4882a593Smuzhiyun 
2124*4882a593Smuzhiyun 		range_type = csc_coef.range_type ? 0 : 1;
2125*4882a593Smuzhiyun 		range_type <<= is_input_yuv ? 0 : 1;
2126*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2127*4882a593Smuzhiyun 				POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false);
2128*4882a593Smuzhiyun 	}
2129*4882a593Smuzhiyun 
2130*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2131*4882a593Smuzhiyun 			POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false);
2132*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2133*4882a593Smuzhiyun 			POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false);
2134*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2135*4882a593Smuzhiyun 			POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false);
2136*4882a593Smuzhiyun }
2137*4882a593Smuzhiyun 
vop3_post_config(struct display_state * state,struct vop2 * vop2)2138*4882a593Smuzhiyun static void vop3_post_config(struct display_state *state, struct vop2 *vop2)
2139*4882a593Smuzhiyun {
2140*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
2141*4882a593Smuzhiyun 	struct base2_disp_info *disp_info = conn_state->disp_info;
2142*4882a593Smuzhiyun 	const char *enable_flag;
2143*4882a593Smuzhiyun 	if (!disp_info) {
2144*4882a593Smuzhiyun 		printf("disp_info is empty\n");
2145*4882a593Smuzhiyun 		return;
2146*4882a593Smuzhiyun 	}
2147*4882a593Smuzhiyun 
2148*4882a593Smuzhiyun 	enable_flag = (const char *)&disp_info->cacm_header;
2149*4882a593Smuzhiyun 	if (strncasecmp(enable_flag, "CACM", 4)) {
2150*4882a593Smuzhiyun 		printf("acm and csc is not support\n");
2151*4882a593Smuzhiyun 		return;
2152*4882a593Smuzhiyun 	}
2153*4882a593Smuzhiyun 
2154*4882a593Smuzhiyun 	vop3_post_acm_config(state, vop2);
2155*4882a593Smuzhiyun 	vop3_post_csc_config(state, vop2);
2156*4882a593Smuzhiyun }
2157*4882a593Smuzhiyun 
2158*4882a593Smuzhiyun /*
2159*4882a593Smuzhiyun  * Read VOP internal power domain on/off status.
2160*4882a593Smuzhiyun  * We should query BISR_STS register in PMU for
2161*4882a593Smuzhiyun  * power up/down status when memory repair is enabled.
2162*4882a593Smuzhiyun  * Return value: 1 for power on, 0 for power off;
2163*4882a593Smuzhiyun  */
vop2_wait_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2164*4882a593Smuzhiyun static int vop2_wait_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2165*4882a593Smuzhiyun {
2166*4882a593Smuzhiyun 	int val = 0;
2167*4882a593Smuzhiyun 	int shift = 0;
2168*4882a593Smuzhiyun 	int shift_factor = 0;
2169*4882a593Smuzhiyun 	bool is_bisr_en = false;
2170*4882a593Smuzhiyun 
2171*4882a593Smuzhiyun 	/*
2172*4882a593Smuzhiyun 	 * The order of pd status bits in BISR_STS register
2173*4882a593Smuzhiyun 	 * is different from that in VOP SYS_STS register.
2174*4882a593Smuzhiyun 	 */
2175*4882a593Smuzhiyun 	if (pd_data->id == VOP2_PD_DSC_8K ||
2176*4882a593Smuzhiyun 	    pd_data->id == VOP2_PD_DSC_4K ||
2177*4882a593Smuzhiyun 	    pd_data->id == VOP2_PD_ESMART)
2178*4882a593Smuzhiyun 			shift_factor = 1;
2179*4882a593Smuzhiyun 
2180*4882a593Smuzhiyun 	shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor;
2181*4882a593Smuzhiyun 	is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift);
2182*4882a593Smuzhiyun 	if (is_bisr_en) {
2183*4882a593Smuzhiyun 		shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor;
2184*4882a593Smuzhiyun 
2185*4882a593Smuzhiyun 		return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
2186*4882a593Smuzhiyun 					  ((val >> shift) & 0x1), 50 * 1000);
2187*4882a593Smuzhiyun 	} else {
2188*4882a593Smuzhiyun 		shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1;
2189*4882a593Smuzhiyun 
2190*4882a593Smuzhiyun 		return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
2191*4882a593Smuzhiyun 					  !((val >> shift) & 0x1), 50 * 1000);
2192*4882a593Smuzhiyun 	}
2193*4882a593Smuzhiyun }
2194*4882a593Smuzhiyun 
vop2_power_domain_on(struct vop2 * vop2,int pd_id)2195*4882a593Smuzhiyun static int vop2_power_domain_on(struct vop2 *vop2, int pd_id)
2196*4882a593Smuzhiyun {
2197*4882a593Smuzhiyun 	struct vop2_power_domain_data *pd_data;
2198*4882a593Smuzhiyun 	int ret = 0;
2199*4882a593Smuzhiyun 
2200*4882a593Smuzhiyun 	if (!pd_id)
2201*4882a593Smuzhiyun 		return 0;
2202*4882a593Smuzhiyun 
2203*4882a593Smuzhiyun 	pd_data = vop2_find_pd_data_by_id(vop2, pd_id);
2204*4882a593Smuzhiyun 	if (!pd_data) {
2205*4882a593Smuzhiyun 		printf("can't find pd_data by id\n");
2206*4882a593Smuzhiyun 		return -EINVAL;
2207*4882a593Smuzhiyun 	}
2208*4882a593Smuzhiyun 
2209*4882a593Smuzhiyun 	if (pd_data->parent_id) {
2210*4882a593Smuzhiyun 		ret = vop2_power_domain_on(vop2, pd_data->parent_id);
2211*4882a593Smuzhiyun 		if (ret) {
2212*4882a593Smuzhiyun 			printf("can't open parent power domain\n");
2213*4882a593Smuzhiyun 			return -EINVAL;
2214*4882a593Smuzhiyun 		}
2215*4882a593Smuzhiyun 	}
2216*4882a593Smuzhiyun 
2217*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_SYS_PD_CTRL, EN_MASK,
2218*4882a593Smuzhiyun 			RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_id) - 1, 0, false);
2219*4882a593Smuzhiyun 	ret = vop2_wait_power_domain_on(vop2, pd_data);
2220*4882a593Smuzhiyun 	if (ret) {
2221*4882a593Smuzhiyun 		printf("wait vop2 power domain timeout\n");
2222*4882a593Smuzhiyun 		return ret;
2223*4882a593Smuzhiyun 	}
2224*4882a593Smuzhiyun 
2225*4882a593Smuzhiyun 	return 0;
2226*4882a593Smuzhiyun }
2227*4882a593Smuzhiyun 
rk3588_vop2_regsbak(struct vop2 * vop2)2228*4882a593Smuzhiyun static void rk3588_vop2_regsbak(struct vop2 *vop2)
2229*4882a593Smuzhiyun {
2230*4882a593Smuzhiyun 	u32 *base = vop2->regs;
2231*4882a593Smuzhiyun 	int i = 0;
2232*4882a593Smuzhiyun 
2233*4882a593Smuzhiyun 	/*
2234*4882a593Smuzhiyun 	 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
2235*4882a593Smuzhiyun 	 */
2236*4882a593Smuzhiyun 	for (i = 0; i < (vop2->reg_len >> 2); i++)
2237*4882a593Smuzhiyun 		vop2->regsbak[i] = base[i];
2238*4882a593Smuzhiyun }
2239*4882a593Smuzhiyun 
vop3_overlay_init(struct vop2 * vop2,struct display_state * state)2240*4882a593Smuzhiyun static void vop3_overlay_init(struct vop2 *vop2, struct display_state *state)
2241*4882a593Smuzhiyun {
2242*4882a593Smuzhiyun 	struct vop2_win_data *win_data;
2243*4882a593Smuzhiyun 	int layer_phy_id = 0;
2244*4882a593Smuzhiyun 	int i, j;
2245*4882a593Smuzhiyun 	u32 ovl_port_offset = 0;
2246*4882a593Smuzhiyun 	u32 layer_nr = 0;
2247*4882a593Smuzhiyun 	u8 shift = 0;
2248*4882a593Smuzhiyun 
2249*4882a593Smuzhiyun 	/* layer sel win id */
2250*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_vps; i++) {
2251*4882a593Smuzhiyun 		shift = 0;
2252*4882a593Smuzhiyun 		ovl_port_offset = 0x100 * i;
2253*4882a593Smuzhiyun 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2254*4882a593Smuzhiyun 		for (j = 0; j < layer_nr; j++) {
2255*4882a593Smuzhiyun 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2256*4882a593Smuzhiyun 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
2257*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + ovl_port_offset, LAYER_SEL_MASK,
2258*4882a593Smuzhiyun 					shift, win_data->layer_sel_win_id[i], false);
2259*4882a593Smuzhiyun 			shift += 4;
2260*4882a593Smuzhiyun 		}
2261*4882a593Smuzhiyun 	}
2262*4882a593Smuzhiyun 
2263*4882a593Smuzhiyun 	/* win sel port */
2264*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_vps; i++) {
2265*4882a593Smuzhiyun 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2266*4882a593Smuzhiyun 		for (j = 0; j < layer_nr; j++) {
2267*4882a593Smuzhiyun 			if (!vop2->vp_plane_mask[i].attached_layers[j])
2268*4882a593Smuzhiyun 				continue;
2269*4882a593Smuzhiyun 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2270*4882a593Smuzhiyun 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
2271*4882a593Smuzhiyun 			shift = win_data->win_sel_port_offset * 2;
2272*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL_IMD, LAYER_SEL_PORT_MASK,
2273*4882a593Smuzhiyun 					shift, i, false);
2274*4882a593Smuzhiyun 		}
2275*4882a593Smuzhiyun 	}
2276*4882a593Smuzhiyun }
2277*4882a593Smuzhiyun 
vop2_overlay_init(struct vop2 * vop2,struct display_state * state)2278*4882a593Smuzhiyun static void vop2_overlay_init(struct vop2 *vop2, struct display_state *state)
2279*4882a593Smuzhiyun {
2280*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2281*4882a593Smuzhiyun 	struct vop2_win_data *win_data;
2282*4882a593Smuzhiyun 	int layer_phy_id = 0;
2283*4882a593Smuzhiyun 	int total_used_layer = 0;
2284*4882a593Smuzhiyun 	int port_mux = 0;
2285*4882a593Smuzhiyun 	int i, j;
2286*4882a593Smuzhiyun 	u32 layer_nr = 0;
2287*4882a593Smuzhiyun 	u8 shift = 0;
2288*4882a593Smuzhiyun 
2289*4882a593Smuzhiyun 	/* layer sel win id */
2290*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_vps; i++) {
2291*4882a593Smuzhiyun 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2292*4882a593Smuzhiyun 		for (j = 0; j < layer_nr; j++) {
2293*4882a593Smuzhiyun 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2294*4882a593Smuzhiyun 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
2295*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
2296*4882a593Smuzhiyun 					shift, win_data->layer_sel_win_id[i], false);
2297*4882a593Smuzhiyun 			shift += 4;
2298*4882a593Smuzhiyun 		}
2299*4882a593Smuzhiyun 	}
2300*4882a593Smuzhiyun 
2301*4882a593Smuzhiyun 	/* win sel port */
2302*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_vps; i++) {
2303*4882a593Smuzhiyun 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2304*4882a593Smuzhiyun 		for (j = 0; j < layer_nr; j++) {
2305*4882a593Smuzhiyun 			if (!vop2->vp_plane_mask[i].attached_layers[j])
2306*4882a593Smuzhiyun 				continue;
2307*4882a593Smuzhiyun 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2308*4882a593Smuzhiyun 			win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
2309*4882a593Smuzhiyun 			shift = win_data->win_sel_port_offset * 2;
2310*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
2311*4882a593Smuzhiyun 					LAYER_SEL_PORT_SHIFT + shift, i, false);
2312*4882a593Smuzhiyun 		}
2313*4882a593Smuzhiyun 	}
2314*4882a593Smuzhiyun 
2315*4882a593Smuzhiyun 	/**
2316*4882a593Smuzhiyun 	 * port mux config
2317*4882a593Smuzhiyun 	 */
2318*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_vps; i++) {
2319*4882a593Smuzhiyun 		shift = i * 4;
2320*4882a593Smuzhiyun 		if (vop2->vp_plane_mask[i].attached_layers_nr) {
2321*4882a593Smuzhiyun 			total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
2322*4882a593Smuzhiyun 			port_mux = total_used_layer - 1;
2323*4882a593Smuzhiyun 		} else {
2324*4882a593Smuzhiyun 			port_mux = 8;
2325*4882a593Smuzhiyun 		}
2326*4882a593Smuzhiyun 
2327*4882a593Smuzhiyun 		if (i == vop2->data->nr_vps - 1)
2328*4882a593Smuzhiyun 			port_mux = vop2->data->nr_mixers;
2329*4882a593Smuzhiyun 
2330*4882a593Smuzhiyun 		cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
2331*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
2332*4882a593Smuzhiyun 				PORT_MUX_SHIFT + shift, port_mux, false);
2333*4882a593Smuzhiyun 	}
2334*4882a593Smuzhiyun }
2335*4882a593Smuzhiyun 
vop3_ignore_plane(struct vop2 * vop2,struct vop2_win_data * win)2336*4882a593Smuzhiyun static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win)
2337*4882a593Smuzhiyun {
2338*4882a593Smuzhiyun 	if (!is_vop3(vop2))
2339*4882a593Smuzhiyun 		return false;
2340*4882a593Smuzhiyun 
2341*4882a593Smuzhiyun 	if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
2342*4882a593Smuzhiyun 	    win->phys_id != ROCKCHIP_VOP2_ESMART0)
2343*4882a593Smuzhiyun 		return true;
2344*4882a593Smuzhiyun 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
2345*4882a593Smuzhiyun 		 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
2346*4882a593Smuzhiyun 		return true;
2347*4882a593Smuzhiyun 	else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
2348*4882a593Smuzhiyun 		 win->phys_id == ROCKCHIP_VOP2_ESMART1)
2349*4882a593Smuzhiyun 		return true;
2350*4882a593Smuzhiyun 	else
2351*4882a593Smuzhiyun 		return false;
2352*4882a593Smuzhiyun }
2353*4882a593Smuzhiyun 
vop3_init_esmart_scale_engine(struct vop2 * vop2)2354*4882a593Smuzhiyun static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
2355*4882a593Smuzhiyun {
2356*4882a593Smuzhiyun 	struct vop2_win_data *win_data;
2357*4882a593Smuzhiyun 	int i;
2358*4882a593Smuzhiyun 	u8 scale_engine_num = 0;
2359*4882a593Smuzhiyun 
2360*4882a593Smuzhiyun 	/* store plane mask for vop2_fixup_dts */
2361*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_layers; i++) {
2362*4882a593Smuzhiyun 		win_data = &vop2->data->win_data[i];
2363*4882a593Smuzhiyun 		if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data))
2364*4882a593Smuzhiyun 			continue;
2365*4882a593Smuzhiyun 
2366*4882a593Smuzhiyun 		win_data->scale_engine_num = scale_engine_num++;
2367*4882a593Smuzhiyun 	}
2368*4882a593Smuzhiyun }
2369*4882a593Smuzhiyun 
vop2_global_initial(struct vop2 * vop2,struct display_state * state)2370*4882a593Smuzhiyun static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
2371*4882a593Smuzhiyun {
2372*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2373*4882a593Smuzhiyun 	struct vop2_vp_plane_mask *plane_mask;
2374*4882a593Smuzhiyun 	int layer_phy_id = 0;
2375*4882a593Smuzhiyun 	int i, j;
2376*4882a593Smuzhiyun 	int ret;
2377*4882a593Smuzhiyun 	u32 layer_nr = 0;
2378*4882a593Smuzhiyun 
2379*4882a593Smuzhiyun 	if (vop2->global_init)
2380*4882a593Smuzhiyun 		return;
2381*4882a593Smuzhiyun 
2382*4882a593Smuzhiyun 	/* OTP must enable at the first time, otherwise mirror layer register is error */
2383*4882a593Smuzhiyun 	if (soc_is_rk3566())
2384*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
2385*4882a593Smuzhiyun 				OTP_WIN_EN_SHIFT, 1, false);
2386*4882a593Smuzhiyun 
2387*4882a593Smuzhiyun 	if (cstate->crtc->assign_plane) {/* dts assign plane */
2388*4882a593Smuzhiyun 		u32 plane_mask;
2389*4882a593Smuzhiyun 		int primary_plane_id;
2390*4882a593Smuzhiyun 
2391*4882a593Smuzhiyun 		for (i = 0; i < vop2->data->nr_vps; i++) {
2392*4882a593Smuzhiyun 			plane_mask = cstate->crtc->vps[i].plane_mask;
2393*4882a593Smuzhiyun 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2394*4882a593Smuzhiyun 			layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */
2395*4882a593Smuzhiyun 			vop2->vp_plane_mask[i].attached_layers_nr = layer_nr;
2396*4882a593Smuzhiyun 			primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
2397*4882a593Smuzhiyun 			if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX)
2398*4882a593Smuzhiyun 				primary_plane_id = vop2_get_primary_plane(vop2, plane_mask);
2399*4882a593Smuzhiyun 			vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id;
2400*4882a593Smuzhiyun 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
2401*4882a593Smuzhiyun 
2402*4882a593Smuzhiyun 			/* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/
2403*4882a593Smuzhiyun 			for (j = 0; j < layer_nr; j++) {
2404*4882a593Smuzhiyun 				vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
2405*4882a593Smuzhiyun 				plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
2406*4882a593Smuzhiyun 			}
2407*4882a593Smuzhiyun 		}
2408*4882a593Smuzhiyun 	} else {/* need soft assign plane mask */
2409*4882a593Smuzhiyun 		/* find the first unplug devices and set it as main display */
2410*4882a593Smuzhiyun 		int main_vp_index = -1;
2411*4882a593Smuzhiyun 		int active_vp_num = 0;
2412*4882a593Smuzhiyun 
2413*4882a593Smuzhiyun 		for (i = 0; i < vop2->data->nr_vps; i++) {
2414*4882a593Smuzhiyun 			if (cstate->crtc->vps[i].enable)
2415*4882a593Smuzhiyun 				active_vp_num++;
2416*4882a593Smuzhiyun 		}
2417*4882a593Smuzhiyun 		printf("VOP have %d active VP\n", active_vp_num);
2418*4882a593Smuzhiyun 
2419*4882a593Smuzhiyun 		if (soc_is_rk3566() && active_vp_num > 2)
2420*4882a593Smuzhiyun 			printf("ERROR: rk3566 only support 2 display output!!\n");
2421*4882a593Smuzhiyun 		plane_mask = vop2->data->plane_mask;
2422*4882a593Smuzhiyun 		plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
2423*4882a593Smuzhiyun 		/*
2424*4882a593Smuzhiyun 		 * For rk3528, one display policy for hdmi store in plane_mask[0], and the other
2425*4882a593Smuzhiyun 		 * for cvbs store in plane_mask[2].
2426*4882a593Smuzhiyun 		 */
2427*4882a593Smuzhiyun 		if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 &&
2428*4882a593Smuzhiyun 		    cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV)
2429*4882a593Smuzhiyun 			plane_mask += 2 * VOP2_VP_MAX;
2430*4882a593Smuzhiyun 
2431*4882a593Smuzhiyun 		if (vop2->version == VOP_VERSION_RK3528) {
2432*4882a593Smuzhiyun 			/*
2433*4882a593Smuzhiyun 			 * For rk3528, the plane mask of vp is limited, only esmart2 can be selected
2434*4882a593Smuzhiyun 			 * by both vp0 and vp1.
2435*4882a593Smuzhiyun 			 */
2436*4882a593Smuzhiyun 			j = 0;
2437*4882a593Smuzhiyun 		} else {
2438*4882a593Smuzhiyun 			for (i = 0; i < vop2->data->nr_vps; i++) {
2439*4882a593Smuzhiyun 				if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
2440*4882a593Smuzhiyun 					vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/
2441*4882a593Smuzhiyun 					main_vp_index = i;
2442*4882a593Smuzhiyun 					break;
2443*4882a593Smuzhiyun 				}
2444*4882a593Smuzhiyun 			}
2445*4882a593Smuzhiyun 
2446*4882a593Smuzhiyun 			/* if no find unplug devices, use vp0 as main display */
2447*4882a593Smuzhiyun 			if (main_vp_index < 0) {
2448*4882a593Smuzhiyun 				main_vp_index = 0;
2449*4882a593Smuzhiyun 				vop2->vp_plane_mask[0] = plane_mask[0];
2450*4882a593Smuzhiyun 			}
2451*4882a593Smuzhiyun 
2452*4882a593Smuzhiyun 			j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */
2453*4882a593Smuzhiyun 		}
2454*4882a593Smuzhiyun 
2455*4882a593Smuzhiyun 		/* init other display except main display */
2456*4882a593Smuzhiyun 		for (i = 0; i < vop2->data->nr_vps; i++) {
2457*4882a593Smuzhiyun 			if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */
2458*4882a593Smuzhiyun 				continue;
2459*4882a593Smuzhiyun 			vop2->vp_plane_mask[i] = plane_mask[j++];
2460*4882a593Smuzhiyun 		}
2461*4882a593Smuzhiyun 
2462*4882a593Smuzhiyun 		/* store plane mask for vop2_fixup_dts */
2463*4882a593Smuzhiyun 		for (i = 0; i < vop2->data->nr_vps; i++) {
2464*4882a593Smuzhiyun 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
2465*4882a593Smuzhiyun 			for (j = 0; j < layer_nr; j++) {
2466*4882a593Smuzhiyun 				layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2467*4882a593Smuzhiyun 				vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
2468*4882a593Smuzhiyun 			}
2469*4882a593Smuzhiyun 		}
2470*4882a593Smuzhiyun 	}
2471*4882a593Smuzhiyun 
2472*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588)
2473*4882a593Smuzhiyun 		rk3588_vop2_regsbak(vop2);
2474*4882a593Smuzhiyun 	else
2475*4882a593Smuzhiyun 		memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
2476*4882a593Smuzhiyun 
2477*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
2478*4882a593Smuzhiyun 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
2479*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
2480*4882a593Smuzhiyun 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
2481*4882a593Smuzhiyun 
2482*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_vps; i++) {
2483*4882a593Smuzhiyun 		printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
2484*4882a593Smuzhiyun 		for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
2485*4882a593Smuzhiyun 			printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]);
2486*4882a593Smuzhiyun 		printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id);
2487*4882a593Smuzhiyun 	}
2488*4882a593Smuzhiyun 
2489*4882a593Smuzhiyun 	if (is_vop3(vop2))
2490*4882a593Smuzhiyun 		vop3_overlay_init(vop2, state);
2491*4882a593Smuzhiyun 	else
2492*4882a593Smuzhiyun 		vop2_overlay_init(vop2, state);
2493*4882a593Smuzhiyun 
2494*4882a593Smuzhiyun 	if (is_vop3(vop2)) {
2495*4882a593Smuzhiyun 		/*
2496*4882a593Smuzhiyun 		 * you can rewrite at dts vop node:
2497*4882a593Smuzhiyun 		 *
2498*4882a593Smuzhiyun 		 * VOP3_ESMART_8K_MODE = 0,
2499*4882a593Smuzhiyun 		 * VOP3_ESMART_4K_4K_MODE = 1,
2500*4882a593Smuzhiyun 		 * VOP3_ESMART_4K_2K_2K_MODE = 2,
2501*4882a593Smuzhiyun 		 * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
2502*4882a593Smuzhiyun 		 *
2503*4882a593Smuzhiyun 		 * &vop {
2504*4882a593Smuzhiyun 		 * 	esmart_lb_mode = /bits/ 8 <2>;
2505*4882a593Smuzhiyun 		 * };
2506*4882a593Smuzhiyun 		 */
2507*4882a593Smuzhiyun 		ret = ofnode_read_u32(cstate->node, "esmart_lb_mode", &vop2->esmart_lb_mode);
2508*4882a593Smuzhiyun 		if (ret < 0)
2509*4882a593Smuzhiyun 			vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
2510*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, ESMART_LB_MODE_SEL_MASK,
2511*4882a593Smuzhiyun 				ESMART_LB_MODE_SEL_SHIFT, vop2->esmart_lb_mode, false);
2512*4882a593Smuzhiyun 
2513*4882a593Smuzhiyun 		vop3_init_esmart_scale_engine(vop2);
2514*4882a593Smuzhiyun 
2515*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK,
2516*4882a593Smuzhiyun 				DSP_VS_T_SEL_SHIFT, 0, false);
2517*4882a593Smuzhiyun 	}
2518*4882a593Smuzhiyun 
2519*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3568)
2520*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
2521*4882a593Smuzhiyun 
2522*4882a593Smuzhiyun 	vop2->global_init = true;
2523*4882a593Smuzhiyun }
2524*4882a593Smuzhiyun 
vop2_initial(struct vop2 * vop2,struct display_state * state)2525*4882a593Smuzhiyun static int vop2_initial(struct vop2 *vop2, struct display_state *state)
2526*4882a593Smuzhiyun {
2527*4882a593Smuzhiyun 	rockchip_vop2_gamma_lut_init(vop2, state);
2528*4882a593Smuzhiyun 	rockchip_vop2_cubic_lut_init(vop2, state);
2529*4882a593Smuzhiyun 
2530*4882a593Smuzhiyun 	return 0;
2531*4882a593Smuzhiyun }
2532*4882a593Smuzhiyun 
2533*4882a593Smuzhiyun /*
2534*4882a593Smuzhiyun  * VOP2 have multi video ports.
2535*4882a593Smuzhiyun  * video port ------- crtc
2536*4882a593Smuzhiyun  */
rockchip_vop2_preinit(struct display_state * state)2537*4882a593Smuzhiyun static int rockchip_vop2_preinit(struct display_state *state)
2538*4882a593Smuzhiyun {
2539*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2540*4882a593Smuzhiyun 	const struct vop2_data *vop2_data = cstate->crtc->data;
2541*4882a593Smuzhiyun 
2542*4882a593Smuzhiyun 	if (!rockchip_vop2) {
2543*4882a593Smuzhiyun 		rockchip_vop2 = calloc(1, sizeof(struct vop2));
2544*4882a593Smuzhiyun 		if (!rockchip_vop2)
2545*4882a593Smuzhiyun 			return -ENOMEM;
2546*4882a593Smuzhiyun 		memset(rockchip_vop2, 0, sizeof(struct vop2));
2547*4882a593Smuzhiyun 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
2548*4882a593Smuzhiyun 		rockchip_vop2->reg_len = RK3568_MAX_REG;
2549*4882a593Smuzhiyun #ifdef CONFIG_SPL_BUILD
2550*4882a593Smuzhiyun 		rockchip_vop2->regs = (void *)RK3528_VOP_BASE;
2551*4882a593Smuzhiyun #else
2552*4882a593Smuzhiyun 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
2553*4882a593Smuzhiyun 		rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
2554*4882a593Smuzhiyun 		if (rockchip_vop2->grf <= 0)
2555*4882a593Smuzhiyun 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
2556*4882a593Smuzhiyun #endif
2557*4882a593Smuzhiyun 		rockchip_vop2->version = vop2_data->version;
2558*4882a593Smuzhiyun 		rockchip_vop2->data = vop2_data;
2559*4882a593Smuzhiyun 		if (rockchip_vop2->version == VOP_VERSION_RK3588) {
2560*4882a593Smuzhiyun 			struct regmap *map;
2561*4882a593Smuzhiyun 
2562*4882a593Smuzhiyun 			rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF);
2563*4882a593Smuzhiyun 			if (rockchip_vop2->vop_grf <= 0)
2564*4882a593Smuzhiyun 				printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf);
2565*4882a593Smuzhiyun 			map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf");
2566*4882a593Smuzhiyun 			rockchip_vop2->vo1_grf = regmap_get_range(map, 0);
2567*4882a593Smuzhiyun 			if (rockchip_vop2->vo1_grf <= 0)
2568*4882a593Smuzhiyun 				printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf);
2569*4882a593Smuzhiyun 			rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
2570*4882a593Smuzhiyun 			if (rockchip_vop2->sys_pmu <= 0)
2571*4882a593Smuzhiyun 				printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu);
2572*4882a593Smuzhiyun 		}
2573*4882a593Smuzhiyun 	}
2574*4882a593Smuzhiyun 
2575*4882a593Smuzhiyun 	cstate->private = rockchip_vop2;
2576*4882a593Smuzhiyun 	cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
2577*4882a593Smuzhiyun 	cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
2578*4882a593Smuzhiyun 
2579*4882a593Smuzhiyun 	vop2_global_initial(rockchip_vop2, state);
2580*4882a593Smuzhiyun 
2581*4882a593Smuzhiyun 	return 0;
2582*4882a593Smuzhiyun }
2583*4882a593Smuzhiyun 
2584*4882a593Smuzhiyun /*
2585*4882a593Smuzhiyun  * calc the dclk on rk3588
2586*4882a593Smuzhiyun  * the available div of dclk is 1, 2, 4
2587*4882a593Smuzhiyun  *
2588*4882a593Smuzhiyun  */
vop2_calc_dclk(unsigned long child_clk,unsigned long max_dclk)2589*4882a593Smuzhiyun static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
2590*4882a593Smuzhiyun {
2591*4882a593Smuzhiyun 	if (child_clk * 4 <= max_dclk)
2592*4882a593Smuzhiyun 		return child_clk * 4;
2593*4882a593Smuzhiyun 	else if (child_clk * 2 <= max_dclk)
2594*4882a593Smuzhiyun 		return child_clk * 2;
2595*4882a593Smuzhiyun 	else if (child_clk <= max_dclk)
2596*4882a593Smuzhiyun 		return child_clk;
2597*4882a593Smuzhiyun 	else
2598*4882a593Smuzhiyun 		return 0;
2599*4882a593Smuzhiyun }
2600*4882a593Smuzhiyun 
2601*4882a593Smuzhiyun /*
2602*4882a593Smuzhiyun  * 4 pixclk/cycle on rk3588
2603*4882a593Smuzhiyun  * RGB/eDP/HDMI: if_pixclk >= dclk_core
2604*4882a593Smuzhiyun  * DP: dp_pixclk = dclk_out <= dclk_core
2605*4882a593Smuzhiyun  * DSI: mipi_pixclk <= dclk_out <= dclk_core
2606*4882a593Smuzhiyun  */
vop2_calc_cru_cfg(struct display_state * state,int * dclk_core_div,int * dclk_out_div,int * if_pixclk_div,int * if_dclk_div)2607*4882a593Smuzhiyun static unsigned long vop2_calc_cru_cfg(struct display_state *state,
2608*4882a593Smuzhiyun 				       int *dclk_core_div, int *dclk_out_div,
2609*4882a593Smuzhiyun 				       int *if_pixclk_div, int *if_dclk_div)
2610*4882a593Smuzhiyun {
2611*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2612*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
2613*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
2614*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
2615*4882a593Smuzhiyun 	unsigned long v_pixclk = mode->crtc_clock;
2616*4882a593Smuzhiyun 	unsigned long dclk_core_rate = v_pixclk >> 2;
2617*4882a593Smuzhiyun 	unsigned long dclk_rate = v_pixclk;
2618*4882a593Smuzhiyun 	unsigned long dclk_out_rate;
2619*4882a593Smuzhiyun 	u64 if_dclk_rate;
2620*4882a593Smuzhiyun 	u64 if_pixclk_rate;
2621*4882a593Smuzhiyun 	int output_type = conn_state->type;
2622*4882a593Smuzhiyun 	int output_mode = conn_state->output_mode;
2623*4882a593Smuzhiyun 	int K = 1;
2624*4882a593Smuzhiyun 
2625*4882a593Smuzhiyun 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE &&
2626*4882a593Smuzhiyun 	    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
2627*4882a593Smuzhiyun 		printf("Dual channel and YUV420 can't work together\n");
2628*4882a593Smuzhiyun 		return -EINVAL;
2629*4882a593Smuzhiyun 	}
2630*4882a593Smuzhiyun 
2631*4882a593Smuzhiyun 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
2632*4882a593Smuzhiyun 	    output_mode == ROCKCHIP_OUT_MODE_YUV420)
2633*4882a593Smuzhiyun 		K = 2;
2634*4882a593Smuzhiyun 
2635*4882a593Smuzhiyun 	if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
2636*4882a593Smuzhiyun 		/*
2637*4882a593Smuzhiyun 		 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
2638*4882a593Smuzhiyun 		 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
2639*4882a593Smuzhiyun 		 */
2640*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
2641*4882a593Smuzhiyun 		    output_mode == ROCKCHIP_OUT_MODE_YUV420) {
2642*4882a593Smuzhiyun 			dclk_rate = dclk_rate >> 1;
2643*4882a593Smuzhiyun 			K = 2;
2644*4882a593Smuzhiyun 		}
2645*4882a593Smuzhiyun 		if (cstate->dsc_enable) {
2646*4882a593Smuzhiyun 			if_pixclk_rate = cstate->dsc_cds_clk_rate << 1;
2647*4882a593Smuzhiyun 			if_dclk_rate = cstate->dsc_cds_clk_rate;
2648*4882a593Smuzhiyun 		} else {
2649*4882a593Smuzhiyun 			if_pixclk_rate = (dclk_core_rate << 1) / K;
2650*4882a593Smuzhiyun 			if_dclk_rate = dclk_core_rate / K;
2651*4882a593Smuzhiyun 		}
2652*4882a593Smuzhiyun 
2653*4882a593Smuzhiyun 		if (v_pixclk > VOP2_MAX_DCLK_RATE)
2654*4882a593Smuzhiyun 			dclk_rate = vop2_calc_dclk(dclk_core_rate,
2655*4882a593Smuzhiyun 						   vop2->data->vp_data[cstate->crtc_id].max_dclk);
2656*4882a593Smuzhiyun 
2657*4882a593Smuzhiyun 		if (!dclk_rate) {
2658*4882a593Smuzhiyun 			printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n",
2659*4882a593Smuzhiyun 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate);
2660*4882a593Smuzhiyun 			return -EINVAL;
2661*4882a593Smuzhiyun 		}
2662*4882a593Smuzhiyun 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
2663*4882a593Smuzhiyun 		*if_dclk_div = dclk_rate / if_dclk_rate;
2664*4882a593Smuzhiyun 		*dclk_core_div = dclk_rate / dclk_core_rate;
2665*4882a593Smuzhiyun 		printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n",
2666*4882a593Smuzhiyun 		       dclk_rate, *if_pixclk_div, *if_dclk_div);
2667*4882a593Smuzhiyun 	} else if (output_type == DRM_MODE_CONNECTOR_eDP) {
2668*4882a593Smuzhiyun 		/* edp_pixclk = edp_dclk > dclk_core */
2669*4882a593Smuzhiyun 		if_pixclk_rate = v_pixclk / K;
2670*4882a593Smuzhiyun 		if_dclk_rate = v_pixclk / K;
2671*4882a593Smuzhiyun 		dclk_rate = if_pixclk_rate * K;
2672*4882a593Smuzhiyun 		*dclk_core_div = dclk_rate / dclk_core_rate;
2673*4882a593Smuzhiyun 		*if_pixclk_div = dclk_rate / if_pixclk_rate;
2674*4882a593Smuzhiyun 		*if_dclk_div = *if_pixclk_div;
2675*4882a593Smuzhiyun 	} else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
2676*4882a593Smuzhiyun 		dclk_out_rate = v_pixclk >> 2;
2677*4882a593Smuzhiyun 		dclk_out_rate = dclk_out_rate / K;
2678*4882a593Smuzhiyun 
2679*4882a593Smuzhiyun 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
2680*4882a593Smuzhiyun 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
2681*4882a593Smuzhiyun 		if (!dclk_rate) {
2682*4882a593Smuzhiyun 			printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n",
2683*4882a593Smuzhiyun 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate);
2684*4882a593Smuzhiyun 			return -EINVAL;
2685*4882a593Smuzhiyun 		}
2686*4882a593Smuzhiyun 		*dclk_out_div = dclk_rate / dclk_out_rate;
2687*4882a593Smuzhiyun 		*dclk_core_div = dclk_rate / dclk_core_rate;
2688*4882a593Smuzhiyun 	} else if (output_type == DRM_MODE_CONNECTOR_DSI) {
2689*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
2690*4882a593Smuzhiyun 			K = 2;
2691*4882a593Smuzhiyun 		if (cstate->dsc_enable)
2692*4882a593Smuzhiyun 			/* dsc output is 96bit, dsi input is 192 bit */
2693*4882a593Smuzhiyun 			if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1;
2694*4882a593Smuzhiyun 		else
2695*4882a593Smuzhiyun 			if_pixclk_rate = dclk_core_rate / K;
2696*4882a593Smuzhiyun 		/* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
2697*4882a593Smuzhiyun 		dclk_out_rate = dclk_core_rate / K;
2698*4882a593Smuzhiyun 		/* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
2699*4882a593Smuzhiyun 		dclk_rate = vop2_calc_dclk(dclk_out_rate,
2700*4882a593Smuzhiyun 					   vop2->data->vp_data[cstate->crtc_id].max_dclk);
2701*4882a593Smuzhiyun 		if (!dclk_rate) {
2702*4882a593Smuzhiyun 			printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n",
2703*4882a593Smuzhiyun 			       vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate);
2704*4882a593Smuzhiyun 			return -EINVAL;
2705*4882a593Smuzhiyun 		}
2706*4882a593Smuzhiyun 
2707*4882a593Smuzhiyun 		if (cstate->dsc_enable)
2708*4882a593Smuzhiyun 			dclk_rate /= cstate->dsc_slice_num;
2709*4882a593Smuzhiyun 
2710*4882a593Smuzhiyun 		*dclk_out_div = dclk_rate / dclk_out_rate;
2711*4882a593Smuzhiyun 		*dclk_core_div = dclk_rate / dclk_core_rate;
2712*4882a593Smuzhiyun 		*if_pixclk_div = 1;       /*mipi pixclk == dclk_out*/
2713*4882a593Smuzhiyun 		if (cstate->dsc_enable)
2714*4882a593Smuzhiyun 			*if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate;
2715*4882a593Smuzhiyun 
2716*4882a593Smuzhiyun 	} else if (output_type == DRM_MODE_CONNECTOR_DPI) {
2717*4882a593Smuzhiyun 		dclk_rate = v_pixclk;
2718*4882a593Smuzhiyun 		*dclk_core_div = dclk_rate / dclk_core_rate;
2719*4882a593Smuzhiyun 	}
2720*4882a593Smuzhiyun 
2721*4882a593Smuzhiyun 	*if_pixclk_div = ilog2(*if_pixclk_div);
2722*4882a593Smuzhiyun 	*if_dclk_div = ilog2(*if_dclk_div);
2723*4882a593Smuzhiyun 	*dclk_core_div = ilog2(*dclk_core_div);
2724*4882a593Smuzhiyun 	*dclk_out_div = ilog2(*dclk_out_div);
2725*4882a593Smuzhiyun 
2726*4882a593Smuzhiyun 	return dclk_rate;
2727*4882a593Smuzhiyun }
2728*4882a593Smuzhiyun 
vop2_calc_dsc_clk(struct display_state * state)2729*4882a593Smuzhiyun static int vop2_calc_dsc_clk(struct display_state *state)
2730*4882a593Smuzhiyun {
2731*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
2732*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
2733*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2734*4882a593Smuzhiyun 	u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */
2735*4882a593Smuzhiyun 	u8 k = 1;
2736*4882a593Smuzhiyun 
2737*4882a593Smuzhiyun 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
2738*4882a593Smuzhiyun 		k = 2;
2739*4882a593Smuzhiyun 
2740*4882a593Smuzhiyun 	cstate->dsc_txp_clk_rate = v_pixclk;
2741*4882a593Smuzhiyun 	do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k));
2742*4882a593Smuzhiyun 
2743*4882a593Smuzhiyun 	cstate->dsc_pxl_clk_rate = v_pixclk;
2744*4882a593Smuzhiyun 	do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k));
2745*4882a593Smuzhiyun 
2746*4882a593Smuzhiyun 	/* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
2747*4882a593Smuzhiyun 	 * cds_dat_width = 96;
2748*4882a593Smuzhiyun 	 * bits_per_pixel = [8-12];
2749*4882a593Smuzhiyun 	 * As cds clk is div from txp clk and only support 1/2/4 div,
2750*4882a593Smuzhiyun 	 * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
2751*4882a593Smuzhiyun 	 * otherwise dsc_cds = crtc_clock / 8;
2752*4882a593Smuzhiyun 	 */
2753*4882a593Smuzhiyun 	cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
2754*4882a593Smuzhiyun 
2755*4882a593Smuzhiyun 	return 0;
2756*4882a593Smuzhiyun }
2757*4882a593Smuzhiyun 
rk3588_vop2_if_cfg(struct display_state * state)2758*4882a593Smuzhiyun static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
2759*4882a593Smuzhiyun {
2760*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2761*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
2762*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
2763*4882a593Smuzhiyun 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
2764*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
2765*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
2766*4882a593Smuzhiyun 	u16 hdisplay = mode->crtc_hdisplay;
2767*4882a593Smuzhiyun 	int output_if = conn_state->output_if;
2768*4882a593Smuzhiyun 	int if_pixclk_div = 0;
2769*4882a593Smuzhiyun 	int if_dclk_div = 0;
2770*4882a593Smuzhiyun 	unsigned long dclk_rate;
2771*4882a593Smuzhiyun 	u32 val;
2772*4882a593Smuzhiyun 
2773*4882a593Smuzhiyun 	if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
2774*4882a593Smuzhiyun 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
2775*4882a593Smuzhiyun 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
2776*4882a593Smuzhiyun 	} else {
2777*4882a593Smuzhiyun 		val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
2778*4882a593Smuzhiyun 		val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
2779*4882a593Smuzhiyun 	}
2780*4882a593Smuzhiyun 
2781*4882a593Smuzhiyun 	if (cstate->dsc_enable) {
2782*4882a593Smuzhiyun 		int k = 1;
2783*4882a593Smuzhiyun 
2784*4882a593Smuzhiyun 		if (!vop2->data->nr_dscs) {
2785*4882a593Smuzhiyun 			printf("Unsupported DSC\n");
2786*4882a593Smuzhiyun 			return 0;
2787*4882a593Smuzhiyun 		}
2788*4882a593Smuzhiyun 
2789*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
2790*4882a593Smuzhiyun 			k = 2;
2791*4882a593Smuzhiyun 
2792*4882a593Smuzhiyun 		cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
2793*4882a593Smuzhiyun 		cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
2794*4882a593Smuzhiyun 		cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num;
2795*4882a593Smuzhiyun 
2796*4882a593Smuzhiyun 		vop2_calc_dsc_clk(state);
2797*4882a593Smuzhiyun 		printf("Enable DSC%d slice:%dx%d, slice num:%d\n",
2798*4882a593Smuzhiyun 		       cstate->dsc_id, dsc_sink_cap->slice_width,
2799*4882a593Smuzhiyun 		       dsc_sink_cap->slice_height, cstate->dsc_slice_num);
2800*4882a593Smuzhiyun 	}
2801*4882a593Smuzhiyun 
2802*4882a593Smuzhiyun 	dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div);
2803*4882a593Smuzhiyun 
2804*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_RGB) {
2805*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
2806*4882a593Smuzhiyun 				4, false);
2807*4882a593Smuzhiyun 	}
2808*4882a593Smuzhiyun 
2809*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_BT1120) {
2810*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
2811*4882a593Smuzhiyun 				3, false);
2812*4882a593Smuzhiyun 	}
2813*4882a593Smuzhiyun 
2814*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_BT656) {
2815*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
2816*4882a593Smuzhiyun 				2, false);
2817*4882a593Smuzhiyun 	}
2818*4882a593Smuzhiyun 
2819*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_MIPI0) {
2820*4882a593Smuzhiyun 		if (cstate->crtc_id == 2)
2821*4882a593Smuzhiyun 			val = 0;
2822*4882a593Smuzhiyun 		else
2823*4882a593Smuzhiyun 			val = 1;
2824*4882a593Smuzhiyun 
2825*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
2826*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2827*4882a593Smuzhiyun 					RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
2828*4882a593Smuzhiyun 
2829*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
2830*4882a593Smuzhiyun 				1, false);
2831*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
2832*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
2833*4882a593Smuzhiyun 				if_pixclk_div, false);
2834*4882a593Smuzhiyun 
2835*4882a593Smuzhiyun 		if (conn_state->hold_mode) {
2836*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2837*4882a593Smuzhiyun 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
2838*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2839*4882a593Smuzhiyun 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
2840*4882a593Smuzhiyun 		}
2841*4882a593Smuzhiyun 	}
2842*4882a593Smuzhiyun 
2843*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_MIPI1) {
2844*4882a593Smuzhiyun 		if (cstate->crtc_id == 2)
2845*4882a593Smuzhiyun 			val = 0;
2846*4882a593Smuzhiyun 		else if (cstate->crtc_id == 3)
2847*4882a593Smuzhiyun 			val = 1;
2848*4882a593Smuzhiyun 		else
2849*4882a593Smuzhiyun 			val = 3; /*VP1*/
2850*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
2851*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2852*4882a593Smuzhiyun 					RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
2853*4882a593Smuzhiyun 
2854*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
2855*4882a593Smuzhiyun 				1, false);
2856*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
2857*4882a593Smuzhiyun 				val, false);
2858*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
2859*4882a593Smuzhiyun 				if_pixclk_div, false);
2860*4882a593Smuzhiyun 
2861*4882a593Smuzhiyun 		if (conn_state->hold_mode) {
2862*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2863*4882a593Smuzhiyun 					EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
2864*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2865*4882a593Smuzhiyun 					EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
2866*4882a593Smuzhiyun 		}
2867*4882a593Smuzhiyun 	}
2868*4882a593Smuzhiyun 
2869*4882a593Smuzhiyun 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
2870*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
2871*4882a593Smuzhiyun 				MIPI_DUAL_EN_SHIFT, 1, false);
2872*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
2873*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
2874*4882a593Smuzhiyun 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
2875*4882a593Smuzhiyun 					false);
2876*4882a593Smuzhiyun 		switch (conn_state->type) {
2877*4882a593Smuzhiyun 		case DRM_MODE_CONNECTOR_DisplayPort:
2878*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2879*4882a593Smuzhiyun 					RK3588_DP_DUAL_EN_SHIFT, 1, false);
2880*4882a593Smuzhiyun 			break;
2881*4882a593Smuzhiyun 		case DRM_MODE_CONNECTOR_eDP:
2882*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2883*4882a593Smuzhiyun 					RK3588_EDP_DUAL_EN_SHIFT, 1, false);
2884*4882a593Smuzhiyun 			break;
2885*4882a593Smuzhiyun 		case DRM_MODE_CONNECTOR_HDMIA:
2886*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2887*4882a593Smuzhiyun 					RK3588_HDMI_DUAL_EN_SHIFT, 1, false);
2888*4882a593Smuzhiyun 			break;
2889*4882a593Smuzhiyun 		case DRM_MODE_CONNECTOR_DSI:
2890*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
2891*4882a593Smuzhiyun 					RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
2892*4882a593Smuzhiyun 			break;
2893*4882a593Smuzhiyun 		default:
2894*4882a593Smuzhiyun 			break;
2895*4882a593Smuzhiyun 		}
2896*4882a593Smuzhiyun 	}
2897*4882a593Smuzhiyun 
2898*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_eDP0) {
2899*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
2900*4882a593Smuzhiyun 				1, false);
2901*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
2902*4882a593Smuzhiyun 				cstate->crtc_id, false);
2903*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
2904*4882a593Smuzhiyun 				if_dclk_div, false);
2905*4882a593Smuzhiyun 
2906*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
2907*4882a593Smuzhiyun 				if_pixclk_div, false);
2908*4882a593Smuzhiyun 
2909*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
2910*4882a593Smuzhiyun 				RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
2911*4882a593Smuzhiyun 	}
2912*4882a593Smuzhiyun 
2913*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_eDP1) {
2914*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
2915*4882a593Smuzhiyun 				1, false);
2916*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
2917*4882a593Smuzhiyun 				cstate->crtc_id, false);
2918*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
2919*4882a593Smuzhiyun 				if_dclk_div, false);
2920*4882a593Smuzhiyun 
2921*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
2922*4882a593Smuzhiyun 				if_pixclk_div, false);
2923*4882a593Smuzhiyun 
2924*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
2925*4882a593Smuzhiyun 				RK3588_GRF_EDP1_ENABLE_SHIFT, 1);
2926*4882a593Smuzhiyun 	}
2927*4882a593Smuzhiyun 
2928*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_HDMI0) {
2929*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
2930*4882a593Smuzhiyun 				1, false);
2931*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
2932*4882a593Smuzhiyun 				cstate->crtc_id, false);
2933*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
2934*4882a593Smuzhiyun 				if_dclk_div, false);
2935*4882a593Smuzhiyun 
2936*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
2937*4882a593Smuzhiyun 				if_pixclk_div, false);
2938*4882a593Smuzhiyun 
2939*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
2940*4882a593Smuzhiyun 				RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1);
2941*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
2942*4882a593Smuzhiyun 				HDMI_SYNC_POL_MASK,
2943*4882a593Smuzhiyun 				HDMI0_SYNC_POL_SHIFT, val);
2944*4882a593Smuzhiyun 	}
2945*4882a593Smuzhiyun 
2946*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_HDMI1) {
2947*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
2948*4882a593Smuzhiyun 				1, false);
2949*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
2950*4882a593Smuzhiyun 				cstate->crtc_id, false);
2951*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
2952*4882a593Smuzhiyun 				if_dclk_div, false);
2953*4882a593Smuzhiyun 
2954*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
2955*4882a593Smuzhiyun 				if_pixclk_div, false);
2956*4882a593Smuzhiyun 
2957*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
2958*4882a593Smuzhiyun 				RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1);
2959*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
2960*4882a593Smuzhiyun 				HDMI_SYNC_POL_MASK,
2961*4882a593Smuzhiyun 				HDMI1_SYNC_POL_SHIFT, val);
2962*4882a593Smuzhiyun 	}
2963*4882a593Smuzhiyun 
2964*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_DP0) {
2965*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
2966*4882a593Smuzhiyun 				1, false);
2967*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
2968*4882a593Smuzhiyun 				cstate->crtc_id, false);
2969*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
2970*4882a593Smuzhiyun 				RK3588_DP0_PIN_POL_SHIFT, val, false);
2971*4882a593Smuzhiyun 	}
2972*4882a593Smuzhiyun 
2973*4882a593Smuzhiyun 	if (output_if & VOP_OUTPUT_IF_DP1) {
2974*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT,
2975*4882a593Smuzhiyun 				1, false);
2976*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
2977*4882a593Smuzhiyun 				cstate->crtc_id, false);
2978*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
2979*4882a593Smuzhiyun 				RK3588_DP1_PIN_POL_SHIFT, val, false);
2980*4882a593Smuzhiyun 	}
2981*4882a593Smuzhiyun 
2982*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
2983*4882a593Smuzhiyun 			DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false);
2984*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
2985*4882a593Smuzhiyun 			DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false);
2986*4882a593Smuzhiyun 
2987*4882a593Smuzhiyun 	return dclk_rate;
2988*4882a593Smuzhiyun }
2989*4882a593Smuzhiyun 
rk3568_vop2_if_cfg(struct display_state * state)2990*4882a593Smuzhiyun static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
2991*4882a593Smuzhiyun {
2992*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
2993*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
2994*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
2995*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
2996*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
2997*4882a593Smuzhiyun 	bool dclk_inv;
2998*4882a593Smuzhiyun 	u32 val;
2999*4882a593Smuzhiyun 
3000*4882a593Smuzhiyun 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3001*4882a593Smuzhiyun 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3002*4882a593Smuzhiyun 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3003*4882a593Smuzhiyun 
3004*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3005*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3006*4882a593Smuzhiyun 				1, false);
3007*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3008*4882a593Smuzhiyun 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3009*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
3010*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3011*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
3012*4882a593Smuzhiyun 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
3013*4882a593Smuzhiyun 	}
3014*4882a593Smuzhiyun 
3015*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
3016*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3017*4882a593Smuzhiyun 				1, false);
3018*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
3019*4882a593Smuzhiyun 				BT1120_EN_SHIFT, 1, false);
3020*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3021*4882a593Smuzhiyun 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3022*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
3023*4882a593Smuzhiyun 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
3024*4882a593Smuzhiyun 	}
3025*4882a593Smuzhiyun 
3026*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
3027*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
3028*4882a593Smuzhiyun 				1, false);
3029*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3030*4882a593Smuzhiyun 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3031*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
3032*4882a593Smuzhiyun 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
3033*4882a593Smuzhiyun 	}
3034*4882a593Smuzhiyun 
3035*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
3036*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
3037*4882a593Smuzhiyun 				1, false);
3038*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3039*4882a593Smuzhiyun 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
3040*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
3041*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3042*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3043*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3044*4882a593Smuzhiyun 	}
3045*4882a593Smuzhiyun 
3046*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
3047*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
3048*4882a593Smuzhiyun 				1, false);
3049*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3050*4882a593Smuzhiyun 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
3051*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
3052*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3053*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3054*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3055*4882a593Smuzhiyun 	}
3056*4882a593Smuzhiyun 
3057*4882a593Smuzhiyun 	if (conn_state->output_flags &
3058*4882a593Smuzhiyun 	    (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE |
3059*4882a593Smuzhiyun 	     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) {
3060*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3061*4882a593Smuzhiyun 				LVDS_DUAL_EN_SHIFT, 1, false);
3062*4882a593Smuzhiyun 		if (conn_state->output_flags &
3063*4882a593Smuzhiyun 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3064*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3065*4882a593Smuzhiyun 					LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1,
3066*4882a593Smuzhiyun 					false);
3067*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3068*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3069*4882a593Smuzhiyun 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
3070*4882a593Smuzhiyun 	}
3071*4882a593Smuzhiyun 
3072*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
3073*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
3074*4882a593Smuzhiyun 				1, false);
3075*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3076*4882a593Smuzhiyun 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
3077*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3078*4882a593Smuzhiyun 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3079*4882a593Smuzhiyun 	}
3080*4882a593Smuzhiyun 
3081*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
3082*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
3083*4882a593Smuzhiyun 				1, false);
3084*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3085*4882a593Smuzhiyun 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
3086*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3087*4882a593Smuzhiyun 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
3088*4882a593Smuzhiyun 	}
3089*4882a593Smuzhiyun 
3090*4882a593Smuzhiyun 	if (conn_state->output_flags &
3091*4882a593Smuzhiyun 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
3092*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3093*4882a593Smuzhiyun 				MIPI_DUAL_EN_SHIFT, 1, false);
3094*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3095*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3096*4882a593Smuzhiyun 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
3097*4882a593Smuzhiyun 					false);
3098*4882a593Smuzhiyun 	}
3099*4882a593Smuzhiyun 
3100*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
3101*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
3102*4882a593Smuzhiyun 				1, false);
3103*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3104*4882a593Smuzhiyun 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
3105*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3106*4882a593Smuzhiyun 				IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
3107*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK,
3108*4882a593Smuzhiyun 				IF_CTRL_EDP_PIN_POL_SHIFT, val, false);
3109*4882a593Smuzhiyun 	}
3110*4882a593Smuzhiyun 
3111*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
3112*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
3113*4882a593Smuzhiyun 				1, false);
3114*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3115*4882a593Smuzhiyun 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
3116*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3117*4882a593Smuzhiyun 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
3118*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
3119*4882a593Smuzhiyun 				IF_CRTL_HDMI_PIN_POL_MASK,
3120*4882a593Smuzhiyun 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
3121*4882a593Smuzhiyun 	}
3122*4882a593Smuzhiyun 
3123*4882a593Smuzhiyun 	return mode->clock;
3124*4882a593Smuzhiyun }
3125*4882a593Smuzhiyun 
rk3528_vop2_if_cfg(struct display_state * state)3126*4882a593Smuzhiyun static unsigned long rk3528_vop2_if_cfg(struct display_state *state)
3127*4882a593Smuzhiyun {
3128*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3129*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
3130*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
3131*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3132*4882a593Smuzhiyun 	u32 val;
3133*4882a593Smuzhiyun 
3134*4882a593Smuzhiyun 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3135*4882a593Smuzhiyun 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3136*4882a593Smuzhiyun 
3137*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
3138*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
3139*4882a593Smuzhiyun 				1, false);
3140*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3141*4882a593Smuzhiyun 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3142*4882a593Smuzhiyun 	}
3143*4882a593Smuzhiyun 
3144*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
3145*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
3146*4882a593Smuzhiyun 				1, false);
3147*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3148*4882a593Smuzhiyun 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
3149*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3150*4882a593Smuzhiyun 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
3151*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
3152*4882a593Smuzhiyun 				IF_CRTL_HDMI_PIN_POL_MASK,
3153*4882a593Smuzhiyun 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
3154*4882a593Smuzhiyun 	}
3155*4882a593Smuzhiyun 
3156*4882a593Smuzhiyun 	return mode->crtc_clock;
3157*4882a593Smuzhiyun }
3158*4882a593Smuzhiyun 
rk3562_vop2_if_cfg(struct display_state * state)3159*4882a593Smuzhiyun static unsigned long rk3562_vop2_if_cfg(struct display_state *state)
3160*4882a593Smuzhiyun {
3161*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3162*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
3163*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
3164*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3165*4882a593Smuzhiyun 	bool dclk_inv;
3166*4882a593Smuzhiyun 	u32 val;
3167*4882a593Smuzhiyun 
3168*4882a593Smuzhiyun 	dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3169*4882a593Smuzhiyun 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3170*4882a593Smuzhiyun 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3171*4882a593Smuzhiyun 
3172*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
3173*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
3174*4882a593Smuzhiyun 				1, false);
3175*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3176*4882a593Smuzhiyun 				RGB_MUX_SHIFT, cstate->crtc_id, false);
3177*4882a593Smuzhiyun 		vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK,
3178*4882a593Smuzhiyun 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
3179*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
3180*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3181*4882a593Smuzhiyun 	}
3182*4882a593Smuzhiyun 
3183*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
3184*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
3185*4882a593Smuzhiyun 				1, false);
3186*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3187*4882a593Smuzhiyun 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
3188*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3189*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
3190*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
3191*4882a593Smuzhiyun 				IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
3192*4882a593Smuzhiyun 	}
3193*4882a593Smuzhiyun 
3194*4882a593Smuzhiyun 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
3195*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
3196*4882a593Smuzhiyun 				1, false);
3197*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
3198*4882a593Smuzhiyun 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
3199*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3200*4882a593Smuzhiyun 				RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false);
3201*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
3202*4882a593Smuzhiyun 				RK3562_MIPI_PIN_POL_SHIFT, val, false);
3203*4882a593Smuzhiyun 	}
3204*4882a593Smuzhiyun 
3205*4882a593Smuzhiyun 	return mode->crtc_clock;
3206*4882a593Smuzhiyun }
3207*4882a593Smuzhiyun 
vop2_post_color_swap(struct display_state * state)3208*4882a593Smuzhiyun static void vop2_post_color_swap(struct display_state *state)
3209*4882a593Smuzhiyun {
3210*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3211*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
3212*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3213*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
3214*4882a593Smuzhiyun 	u32 output_type = conn_state->type;
3215*4882a593Smuzhiyun 	u32 data_swap = 0;
3216*4882a593Smuzhiyun 
3217*4882a593Smuzhiyun 	if (is_uv_swap(conn_state->bus_format, conn_state->output_mode) ||
3218*4882a593Smuzhiyun 	    is_rb_swap(conn_state->bus_format, conn_state->output_mode))
3219*4882a593Smuzhiyun 		data_swap = DSP_RB_SWAP;
3220*4882a593Smuzhiyun 
3221*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588 &&
3222*4882a593Smuzhiyun 	    (output_type == DRM_MODE_CONNECTOR_HDMIA ||
3223*4882a593Smuzhiyun 	     output_type == DRM_MODE_CONNECTOR_eDP) &&
3224*4882a593Smuzhiyun 	    (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
3225*4882a593Smuzhiyun 	     conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
3226*4882a593Smuzhiyun 		data_swap |= DSP_RG_SWAP;
3227*4882a593Smuzhiyun 
3228*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
3229*4882a593Smuzhiyun 			DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false);
3230*4882a593Smuzhiyun }
3231*4882a593Smuzhiyun 
vop2_clk_set_parent(struct clk * clk,struct clk * parent)3232*4882a593Smuzhiyun static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
3233*4882a593Smuzhiyun {
3234*4882a593Smuzhiyun 	int ret = 0;
3235*4882a593Smuzhiyun 
3236*4882a593Smuzhiyun 	if (parent->dev)
3237*4882a593Smuzhiyun 		ret = clk_set_parent(clk, parent);
3238*4882a593Smuzhiyun 	if (ret < 0)
3239*4882a593Smuzhiyun 		debug("failed to set %s as parent for %s\n",
3240*4882a593Smuzhiyun 		      parent->dev->name, clk->dev->name);
3241*4882a593Smuzhiyun }
3242*4882a593Smuzhiyun 
vop2_clk_set_rate(struct clk * clk,ulong rate)3243*4882a593Smuzhiyun static ulong vop2_clk_set_rate(struct clk *clk, ulong rate)
3244*4882a593Smuzhiyun {
3245*4882a593Smuzhiyun 	int ret = 0;
3246*4882a593Smuzhiyun 
3247*4882a593Smuzhiyun 	if (clk->dev)
3248*4882a593Smuzhiyun 		ret = clk_set_rate(clk, rate);
3249*4882a593Smuzhiyun 	if (ret < 0)
3250*4882a593Smuzhiyun 		debug("failed to set %s rate %lu \n", clk->dev->name, rate);
3251*4882a593Smuzhiyun 
3252*4882a593Smuzhiyun 	return ret;
3253*4882a593Smuzhiyun }
3254*4882a593Smuzhiyun 
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)3255*4882a593Smuzhiyun static void vop2_calc_dsc_cru_cfg(struct display_state *state,
3256*4882a593Smuzhiyun 				  int *dsc_txp_clk_div, int *dsc_pxl_clk_div,
3257*4882a593Smuzhiyun 				  int *dsc_cds_clk_div, u64 dclk_rate)
3258*4882a593Smuzhiyun {
3259*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3260*4882a593Smuzhiyun 
3261*4882a593Smuzhiyun 	*dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate;
3262*4882a593Smuzhiyun 	*dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate;
3263*4882a593Smuzhiyun 	*dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate;
3264*4882a593Smuzhiyun 
3265*4882a593Smuzhiyun 	*dsc_txp_clk_div = ilog2(*dsc_txp_clk_div);
3266*4882a593Smuzhiyun 	*dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div);
3267*4882a593Smuzhiyun 	*dsc_cds_clk_div = ilog2(*dsc_cds_clk_div);
3268*4882a593Smuzhiyun }
3269*4882a593Smuzhiyun 
vop2_load_pps(struct display_state * state,struct vop2 * vop2,u8 dsc_id)3270*4882a593Smuzhiyun static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id)
3271*4882a593Smuzhiyun {
3272*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3273*4882a593Smuzhiyun 	struct drm_dsc_picture_parameter_set *pps = &cstate->pps;
3274*4882a593Smuzhiyun 	struct drm_dsc_picture_parameter_set config_pps;
3275*4882a593Smuzhiyun 	const struct vop2_data *vop2_data = vop2->data;
3276*4882a593Smuzhiyun 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
3277*4882a593Smuzhiyun 	u32 *pps_val = (u32 *)&config_pps;
3278*4882a593Smuzhiyun 	u32 decoder_regs_offset = (dsc_id * 0x100);
3279*4882a593Smuzhiyun 	int i = 0;
3280*4882a593Smuzhiyun 
3281*4882a593Smuzhiyun 	memcpy(&config_pps, pps, sizeof(config_pps));
3282*4882a593Smuzhiyun 
3283*4882a593Smuzhiyun 	if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) {
3284*4882a593Smuzhiyun 		config_pps.pps_3 &= 0xf0;
3285*4882a593Smuzhiyun 		config_pps.pps_3 |= dsc_data->max_linebuf_depth;
3286*4882a593Smuzhiyun 		printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
3287*4882a593Smuzhiyun 		       dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf);
3288*4882a593Smuzhiyun 	}
3289*4882a593Smuzhiyun 
3290*4882a593Smuzhiyun 	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
3291*4882a593Smuzhiyun 		config_pps.rc_range_parameters[i] =
3292*4882a593Smuzhiyun 			(pps->rc_range_parameters[i] >> 3 & 0x1f) |
3293*4882a593Smuzhiyun 			((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
3294*4882a593Smuzhiyun 			((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
3295*4882a593Smuzhiyun 			((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
3296*4882a593Smuzhiyun 	}
3297*4882a593Smuzhiyun 
3298*4882a593Smuzhiyun 	for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
3299*4882a593Smuzhiyun 		vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++);
3300*4882a593Smuzhiyun }
3301*4882a593Smuzhiyun 
vop2_dsc_enable(struct display_state * state,struct vop2 * vop2,u8 dsc_id,u64 dclk_rate)3302*4882a593Smuzhiyun static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate)
3303*4882a593Smuzhiyun {
3304*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
3305*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
3306*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3307*4882a593Smuzhiyun 	struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
3308*4882a593Smuzhiyun 	const struct vop2_data *vop2_data = vop2->data;
3309*4882a593Smuzhiyun 	const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
3310*4882a593Smuzhiyun 	bool mipi_ds_mode = false;
3311*4882a593Smuzhiyun 	u8 dsc_interface_mode = 0;
3312*4882a593Smuzhiyun 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
3313*4882a593Smuzhiyun 	u16 hdisplay = mode->crtc_hdisplay;
3314*4882a593Smuzhiyun 	u16 htotal = mode->crtc_htotal;
3315*4882a593Smuzhiyun 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
3316*4882a593Smuzhiyun 	u16 vdisplay = mode->crtc_vdisplay;
3317*4882a593Smuzhiyun 	u16 vtotal = mode->crtc_vtotal;
3318*4882a593Smuzhiyun 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
3319*4882a593Smuzhiyun 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
3320*4882a593Smuzhiyun 	u16 vact_end = vact_st + vdisplay;
3321*4882a593Smuzhiyun 	u32 ctrl_regs_offset = (dsc_id * 0x30);
3322*4882a593Smuzhiyun 	u32 decoder_regs_offset = (dsc_id * 0x100);
3323*4882a593Smuzhiyun 	int dsc_txp_clk_div = 0;
3324*4882a593Smuzhiyun 	int dsc_pxl_clk_div = 0;
3325*4882a593Smuzhiyun 	int dsc_cds_clk_div = 0;
3326*4882a593Smuzhiyun 	int val = 0;
3327*4882a593Smuzhiyun 
3328*4882a593Smuzhiyun 	if (!vop2->data->nr_dscs) {
3329*4882a593Smuzhiyun 		printf("Unsupported DSC\n");
3330*4882a593Smuzhiyun 		return;
3331*4882a593Smuzhiyun 	}
3332*4882a593Smuzhiyun 
3333*4882a593Smuzhiyun 	if (cstate->dsc_slice_num > dsc_data->max_slice_num)
3334*4882a593Smuzhiyun 		printf("DSC%d supported max slice is: %d, current is: %d\n",
3335*4882a593Smuzhiyun 		       dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num);
3336*4882a593Smuzhiyun 
3337*4882a593Smuzhiyun 	if (dsc_data->pd_id) {
3338*4882a593Smuzhiyun 		if (vop2_power_domain_on(vop2, dsc_data->pd_id))
3339*4882a593Smuzhiyun 			printf("open dsc%d pd fail\n", dsc_id);
3340*4882a593Smuzhiyun 	}
3341*4882a593Smuzhiyun 
3342*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK,
3343*4882a593Smuzhiyun 			SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false);
3344*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK,
3345*4882a593Smuzhiyun 			DSC_PORT_SEL_SHIFT, cstate->crtc_id, false);
3346*4882a593Smuzhiyun 	if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
3347*4882a593Smuzhiyun 		dsc_interface_mode = VOP_DSC_IF_HDMI;
3348*4882a593Smuzhiyun 	} else {
3349*4882a593Smuzhiyun 		mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
3350*4882a593Smuzhiyun 		if (mipi_ds_mode)
3351*4882a593Smuzhiyun 			dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
3352*4882a593Smuzhiyun 		else
3353*4882a593Smuzhiyun 			dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
3354*4882a593Smuzhiyun 	}
3355*4882a593Smuzhiyun 
3356*4882a593Smuzhiyun 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3357*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
3358*4882a593Smuzhiyun 				DSC_MAN_MODE_SHIFT, 0, false);
3359*4882a593Smuzhiyun 	else
3360*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
3361*4882a593Smuzhiyun 				DSC_MAN_MODE_SHIFT, 1, false);
3362*4882a593Smuzhiyun 
3363*4882a593Smuzhiyun 	vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate);
3364*4882a593Smuzhiyun 
3365*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK,
3366*4882a593Smuzhiyun 			DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false);
3367*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK,
3368*4882a593Smuzhiyun 			DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false);
3369*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK,
3370*4882a593Smuzhiyun 			DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false);
3371*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK,
3372*4882a593Smuzhiyun 			DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false);
3373*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
3374*4882a593Smuzhiyun 			DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false);
3375*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK,
3376*4882a593Smuzhiyun 			DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false);
3377*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
3378*4882a593Smuzhiyun 			DSC_HALT_EN_SHIFT, mipi_ds_mode, false);
3379*4882a593Smuzhiyun 
3380*4882a593Smuzhiyun 	if (!mipi_ds_mode) {
3381*4882a593Smuzhiyun 		u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
3382*4882a593Smuzhiyun 		u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
3383*4882a593Smuzhiyun 		u64 dsc_cds_rate = cstate->dsc_cds_clk_rate;
3384*4882a593Smuzhiyun 		u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */
3385*4882a593Smuzhiyun 		u32 dly_num, dsc_cds_rate_mhz, val = 0;
3386*4882a593Smuzhiyun 		int k = 1;
3387*4882a593Smuzhiyun 
3388*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3389*4882a593Smuzhiyun 			k = 2;
3390*4882a593Smuzhiyun 
3391*4882a593Smuzhiyun 		if (target_bpp >> 4 < dsc_data->min_bits_per_pixel)
3392*4882a593Smuzhiyun 			printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel);
3393*4882a593Smuzhiyun 
3394*4882a593Smuzhiyun 		/*
3395*4882a593Smuzhiyun 		 * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
3396*4882a593Smuzhiyun 		 * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
3397*4882a593Smuzhiyun 		 * T (dsc_cds) = 1 / dsc_cds_rate_mhz
3398*4882a593Smuzhiyun 		 *
3399*4882a593Smuzhiyun 		 * HDMI:
3400*4882a593Smuzhiyun 		 * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
3401*4882a593Smuzhiyun 		 *                 delay_line_num = 4 - BPP / 8
3402*4882a593Smuzhiyun 		 *                                = (64 - target_bpp / 8) / 16
3403*4882a593Smuzhiyun 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
3404*4882a593Smuzhiyun 		 *
3405*4882a593Smuzhiyun 		 * MIPI DSI[4320 and 9216 is buffer size for DSC]:
3406*4882a593Smuzhiyun 		 * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
3407*4882a593Smuzhiyun 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
3408*4882a593Smuzhiyun 		 * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
3409*4882a593Smuzhiyun 		 *	delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
3410*4882a593Smuzhiyun 		 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
3411*4882a593Smuzhiyun 		 */
3412*4882a593Smuzhiyun 		do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
3413*4882a593Smuzhiyun 		dsc_cds_rate_mhz = dsc_cds_rate;
3414*4882a593Smuzhiyun 		dsc_hsync = hsync_len / 2;
3415*4882a593Smuzhiyun 		if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
3416*4882a593Smuzhiyun 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
3417*4882a593Smuzhiyun 		} else {
3418*4882a593Smuzhiyun 			int dsc_buf_size  = dsc_id == 0 ? 4320 * 8 : 9216 * 2;
3419*4882a593Smuzhiyun 			int delay_line_num = dsc_buf_size / cstate->dsc_slice_num /
3420*4882a593Smuzhiyun 					     be16_to_cpu(cstate->pps.chunk_size);
3421*4882a593Smuzhiyun 
3422*4882a593Smuzhiyun 			delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
3423*4882a593Smuzhiyun 			dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
3424*4882a593Smuzhiyun 
3425*4882a593Smuzhiyun 			/* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
3426*4882a593Smuzhiyun 			if (dsc_hsync < 8)
3427*4882a593Smuzhiyun 				dsc_hsync = 8;
3428*4882a593Smuzhiyun 		}
3429*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK,
3430*4882a593Smuzhiyun 				DSC_INIT_DLY_MODE_SHIFT, 0, false);
3431*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK,
3432*4882a593Smuzhiyun 				DSC_INIT_DLY_NUM_SHIFT, dly_num, false);
3433*4882a593Smuzhiyun 
3434*4882a593Smuzhiyun 		/*
3435*4882a593Smuzhiyun 		 * htotal / dclk_core = dsc_htotal /cds_clk
3436*4882a593Smuzhiyun 		 *
3437*4882a593Smuzhiyun 		 * dclk_core = DCLK / (1 << dclk_core->div_val)
3438*4882a593Smuzhiyun 		 * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
3439*4882a593Smuzhiyun 		 * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
3440*4882a593Smuzhiyun 		 *
3441*4882a593Smuzhiyun 		 * dsc_htotal = htotal * (1 << dclk_core->div_val) /
3442*4882a593Smuzhiyun 		 *              ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
3443*4882a593Smuzhiyun 		 */
3444*4882a593Smuzhiyun 		dsc_htotal = htotal * (1 << cstate->dclk_core_div) /
3445*4882a593Smuzhiyun 			     ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div));
3446*4882a593Smuzhiyun 		val = dsc_htotal << 16 | dsc_hsync;
3447*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK,
3448*4882a593Smuzhiyun 				DSC_HTOTAL_PW_SHIFT, val, false);
3449*4882a593Smuzhiyun 
3450*4882a593Smuzhiyun 		dsc_hact_st = hact_st / 2;
3451*4882a593Smuzhiyun 		dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
3452*4882a593Smuzhiyun 		val = dsc_hact_end << 16 | dsc_hact_st;
3453*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK,
3454*4882a593Smuzhiyun 				DSC_HACT_ST_END_SHIFT, val, false);
3455*4882a593Smuzhiyun 
3456*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK,
3457*4882a593Smuzhiyun 				DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false);
3458*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK,
3459*4882a593Smuzhiyun 				DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false);
3460*4882a593Smuzhiyun 	}
3461*4882a593Smuzhiyun 
3462*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK,
3463*4882a593Smuzhiyun 			RST_DEASSERT_SHIFT, 1, false);
3464*4882a593Smuzhiyun 	udelay(10);
3465*4882a593Smuzhiyun 
3466*4882a593Smuzhiyun 	val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) |
3467*4882a593Smuzhiyun 	       ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT);
3468*4882a593Smuzhiyun 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
3469*4882a593Smuzhiyun 
3470*4882a593Smuzhiyun 	vop2_load_pps(state, vop2, dsc_id);
3471*4882a593Smuzhiyun 
3472*4882a593Smuzhiyun 	val |= (1 << DSC_PPS_UPD_SHIFT);
3473*4882a593Smuzhiyun 	vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
3474*4882a593Smuzhiyun 
3475*4882a593Smuzhiyun 	printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
3476*4882a593Smuzhiyun 	       dsc_id,
3477*4882a593Smuzhiyun 	       cstate->dsc_txp_clk_rate, dsc_txp_clk_div,
3478*4882a593Smuzhiyun 	       cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div,
3479*4882a593Smuzhiyun 	       cstate->dsc_cds_clk_rate, dsc_cds_clk_div);
3480*4882a593Smuzhiyun }
3481*4882a593Smuzhiyun 
is_extend_pll(struct display_state * state,struct udevice ** clk_dev)3482*4882a593Smuzhiyun static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev)
3483*4882a593Smuzhiyun {
3484*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3485*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3486*4882a593Smuzhiyun 	struct udevice *vp_dev, *dev;
3487*4882a593Smuzhiyun 	struct ofnode_phandle_args args;
3488*4882a593Smuzhiyun 	char vp_name[10];
3489*4882a593Smuzhiyun 	int ret;
3490*4882a593Smuzhiyun 
3491*4882a593Smuzhiyun 	if (vop2->version != VOP_VERSION_RK3588)
3492*4882a593Smuzhiyun 		return false;
3493*4882a593Smuzhiyun 
3494*4882a593Smuzhiyun 	sprintf(vp_name, "port@%d", cstate->crtc_id);
3495*4882a593Smuzhiyun 	if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) {
3496*4882a593Smuzhiyun 		debug("warn: can't get vp device\n");
3497*4882a593Smuzhiyun 		return false;
3498*4882a593Smuzhiyun 	}
3499*4882a593Smuzhiyun 
3500*4882a593Smuzhiyun 	ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0,
3501*4882a593Smuzhiyun 					 0, &args);
3502*4882a593Smuzhiyun 	if (ret) {
3503*4882a593Smuzhiyun 		debug("assigned-clock-parents's node not define\n");
3504*4882a593Smuzhiyun 		return false;
3505*4882a593Smuzhiyun 	}
3506*4882a593Smuzhiyun 
3507*4882a593Smuzhiyun 	if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) {
3508*4882a593Smuzhiyun 		debug("warn: can't get clk device\n");
3509*4882a593Smuzhiyun 		return false;
3510*4882a593Smuzhiyun 	}
3511*4882a593Smuzhiyun 
3512*4882a593Smuzhiyun 	if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) {
3513*4882a593Smuzhiyun 		printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name);
3514*4882a593Smuzhiyun 		if (clk_dev)
3515*4882a593Smuzhiyun 			*clk_dev = dev;
3516*4882a593Smuzhiyun 		return true;
3517*4882a593Smuzhiyun 	}
3518*4882a593Smuzhiyun 
3519*4882a593Smuzhiyun 	return false;
3520*4882a593Smuzhiyun }
3521*4882a593Smuzhiyun 
vop3_mcu_mode_setup(struct display_state * state)3522*4882a593Smuzhiyun static void vop3_mcu_mode_setup(struct display_state *state)
3523*4882a593Smuzhiyun {
3524*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3525*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3526*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
3527*4882a593Smuzhiyun 
3528*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3529*4882a593Smuzhiyun 			MCU_TYPE_SHIFT, 1, false);
3530*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3531*4882a593Smuzhiyun 			MCU_HOLD_MODE_SHIFT, 1, false);
3532*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
3533*4882a593Smuzhiyun 			MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false);
3534*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
3535*4882a593Smuzhiyun 			MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false);
3536*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
3537*4882a593Smuzhiyun 			MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false);
3538*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
3539*4882a593Smuzhiyun 			MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false);
3540*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
3541*4882a593Smuzhiyun 			MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false);
3542*4882a593Smuzhiyun }
3543*4882a593Smuzhiyun 
vop3_mcu_bypass_mode_setup(struct display_state * state)3544*4882a593Smuzhiyun static void vop3_mcu_bypass_mode_setup(struct display_state *state)
3545*4882a593Smuzhiyun {
3546*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3547*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3548*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
3549*4882a593Smuzhiyun 
3550*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3551*4882a593Smuzhiyun 			MCU_TYPE_SHIFT, 1, false);
3552*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3553*4882a593Smuzhiyun 			MCU_HOLD_MODE_SHIFT, 1, false);
3554*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
3555*4882a593Smuzhiyun 			MCU_PIX_TOTAL_SHIFT, 53, false);
3556*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
3557*4882a593Smuzhiyun 			MCU_CS_PST_SHIFT, 6, false);
3558*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
3559*4882a593Smuzhiyun 			MCU_CS_PEND_SHIFT, 48, false);
3560*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
3561*4882a593Smuzhiyun 			MCU_RW_PST_SHIFT, 12, false);
3562*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
3563*4882a593Smuzhiyun 			MCU_RW_PEND_SHIFT, 30, false);
3564*4882a593Smuzhiyun }
3565*4882a593Smuzhiyun 
rockchip_vop2_send_mcu_cmd(struct display_state * state,u32 type,u32 value)3566*4882a593Smuzhiyun static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value)
3567*4882a593Smuzhiyun {
3568*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3569*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
3570*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
3571*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3572*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
3573*4882a593Smuzhiyun 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
3574*4882a593Smuzhiyun 
3575*4882a593Smuzhiyun 	/*
3576*4882a593Smuzhiyun 	 * 1.disable port dclk auto gating.
3577*4882a593Smuzhiyun 	 * 2.set mcu bypass mode timing to adapt to the mode of sending cmds.
3578*4882a593Smuzhiyun 	 * 3.make setting of output mode take effect.
3579*4882a593Smuzhiyun 	 * 4.set dclk rate to 150M, in order to sync with hclk in sending cmds.
3580*4882a593Smuzhiyun 	 */
3581*4882a593Smuzhiyun 	if (type == MCU_SETBYPASS && value) {
3582*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
3583*4882a593Smuzhiyun 				AUTO_GATING_EN_SHIFT, 0, false);
3584*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
3585*4882a593Smuzhiyun 				PORT_DCLK_AUTO_GATING_EN_SHIFT, 0, false);
3586*4882a593Smuzhiyun 		vop3_mcu_bypass_mode_setup(state);
3587*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3588*4882a593Smuzhiyun 				STANDBY_EN_SHIFT, 0, false);
3589*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
3590*4882a593Smuzhiyun 		vop2_clk_set_rate(&cstate->dclk, 150000000);
3591*4882a593Smuzhiyun 	}
3592*4882a593Smuzhiyun 
3593*4882a593Smuzhiyun 	switch (type) {
3594*4882a593Smuzhiyun 	case MCU_WRCMD:
3595*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3596*4882a593Smuzhiyun 				MCU_RS_SHIFT, 0, false);
3597*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
3598*4882a593Smuzhiyun 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
3599*4882a593Smuzhiyun 				value, false);
3600*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3601*4882a593Smuzhiyun 				MCU_RS_SHIFT, 1, false);
3602*4882a593Smuzhiyun 		break;
3603*4882a593Smuzhiyun 	case MCU_WRDATA:
3604*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3605*4882a593Smuzhiyun 				MCU_RS_SHIFT, 1, false);
3606*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
3607*4882a593Smuzhiyun 				MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
3608*4882a593Smuzhiyun 				value, false);
3609*4882a593Smuzhiyun 		break;
3610*4882a593Smuzhiyun 	case MCU_SETBYPASS:
3611*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
3612*4882a593Smuzhiyun 				MCU_BYPASS_SHIFT, value ? 1 : 0, false);
3613*4882a593Smuzhiyun 		break;
3614*4882a593Smuzhiyun 	default:
3615*4882a593Smuzhiyun 		break;
3616*4882a593Smuzhiyun 	}
3617*4882a593Smuzhiyun 
3618*4882a593Smuzhiyun 	/*
3619*4882a593Smuzhiyun 	 * 1.restore port dclk auto gating.
3620*4882a593Smuzhiyun 	 * 2.restore mcu data mode timing.
3621*4882a593Smuzhiyun 	 * 3.restore dclk rate to crtc_clock.
3622*4882a593Smuzhiyun 	 */
3623*4882a593Smuzhiyun 	if (type == MCU_SETBYPASS && !value) {
3624*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
3625*4882a593Smuzhiyun 				AUTO_GATING_EN_SHIFT, 1, false);
3626*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
3627*4882a593Smuzhiyun 				PORT_DCLK_AUTO_GATING_EN_SHIFT, 1, false);
3628*4882a593Smuzhiyun 		vop3_mcu_mode_setup(state);
3629*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3630*4882a593Smuzhiyun 				STANDBY_EN_SHIFT, 1, false);
3631*4882a593Smuzhiyun 		vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000);
3632*4882a593Smuzhiyun 	}
3633*4882a593Smuzhiyun 
3634*4882a593Smuzhiyun 	return 0;
3635*4882a593Smuzhiyun }
3636*4882a593Smuzhiyun 
vop2_get_vrefresh(struct display_state * state)3637*4882a593Smuzhiyun static int vop2_get_vrefresh(struct display_state *state)
3638*4882a593Smuzhiyun {
3639*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3640*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
3641*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
3642*4882a593Smuzhiyun 
3643*4882a593Smuzhiyun 	if (cstate->mcu_timing.mcu_pix_total)
3644*4882a593Smuzhiyun 		return mode->vrefresh / cstate->mcu_timing.mcu_pix_total;
3645*4882a593Smuzhiyun 	else
3646*4882a593Smuzhiyun 		return mode->vrefresh;
3647*4882a593Smuzhiyun }
3648*4882a593Smuzhiyun 
rockchip_vop2_init(struct display_state * state)3649*4882a593Smuzhiyun static int rockchip_vop2_init(struct display_state *state)
3650*4882a593Smuzhiyun {
3651*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
3652*4882a593Smuzhiyun 	struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
3653*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
3654*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
3655*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
3656*4882a593Smuzhiyun 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
3657*4882a593Smuzhiyun 	u16 hdisplay = mode->crtc_hdisplay;
3658*4882a593Smuzhiyun 	u16 htotal = mode->crtc_htotal;
3659*4882a593Smuzhiyun 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
3660*4882a593Smuzhiyun 	u16 hact_end = hact_st + hdisplay;
3661*4882a593Smuzhiyun 	u16 vdisplay = mode->crtc_vdisplay;
3662*4882a593Smuzhiyun 	u16 vtotal = mode->crtc_vtotal;
3663*4882a593Smuzhiyun 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
3664*4882a593Smuzhiyun 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
3665*4882a593Smuzhiyun 	u16 vact_end = vact_st + vdisplay;
3666*4882a593Smuzhiyun 	bool yuv_overlay = false;
3667*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
3668*4882a593Smuzhiyun 	u32 line_flag_offset = (cstate->crtc_id * 4);
3669*4882a593Smuzhiyun 	u32 val, act_end;
3670*4882a593Smuzhiyun 	u8 dither_down_en = 0;
3671*4882a593Smuzhiyun 	u8 dither_down_mode = 0;
3672*4882a593Smuzhiyun 	u8 pre_dither_down_en = 0;
3673*4882a593Smuzhiyun 	u8 dclk_div_factor = 0;
3674*4882a593Smuzhiyun 	char output_type_name[30] = {0};
3675*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
3676*4882a593Smuzhiyun 	char dclk_name[9];
3677*4882a593Smuzhiyun #endif
3678*4882a593Smuzhiyun 	struct clk hdmi0_phy_pll;
3679*4882a593Smuzhiyun 	struct clk hdmi1_phy_pll;
3680*4882a593Smuzhiyun 	struct clk hdmi_phy_pll;
3681*4882a593Smuzhiyun 	struct udevice *disp_dev;
3682*4882a593Smuzhiyun 	unsigned long dclk_rate = 0;
3683*4882a593Smuzhiyun 	int ret;
3684*4882a593Smuzhiyun 
3685*4882a593Smuzhiyun 	printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
3686*4882a593Smuzhiyun 	       mode->crtc_hdisplay, mode->vdisplay,
3687*4882a593Smuzhiyun 	       mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
3688*4882a593Smuzhiyun 	       vop2_get_vrefresh(state),
3689*4882a593Smuzhiyun 	       get_output_if_name(conn_state->output_if, output_type_name),
3690*4882a593Smuzhiyun 	       cstate->crtc_id);
3691*4882a593Smuzhiyun 
3692*4882a593Smuzhiyun 	if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
3693*4882a593Smuzhiyun 		cstate->splice_mode = true;
3694*4882a593Smuzhiyun 		cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id;
3695*4882a593Smuzhiyun 		if (!cstate->splice_crtc_id) {
3696*4882a593Smuzhiyun 			printf("%s: Splice mode is unsupported by vp%d\n",
3697*4882a593Smuzhiyun 			       __func__, cstate->crtc_id);
3698*4882a593Smuzhiyun 			return -EINVAL;
3699*4882a593Smuzhiyun 		}
3700*4882a593Smuzhiyun 
3701*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK,
3702*4882a593Smuzhiyun 				PORT_MERGE_EN_SHIFT, 1, false);
3703*4882a593Smuzhiyun 	}
3704*4882a593Smuzhiyun 
3705*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
3706*4882a593Smuzhiyun 			RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false);
3707*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
3708*4882a593Smuzhiyun 			RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false);
3709*4882a593Smuzhiyun 
3710*4882a593Smuzhiyun 	vop2_initial(vop2, state);
3711*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588)
3712*4882a593Smuzhiyun 		dclk_rate = rk3588_vop2_if_cfg(state);
3713*4882a593Smuzhiyun 	else if (vop2->version == VOP_VERSION_RK3568)
3714*4882a593Smuzhiyun 		dclk_rate = rk3568_vop2_if_cfg(state);
3715*4882a593Smuzhiyun 	else if (vop2->version == VOP_VERSION_RK3528)
3716*4882a593Smuzhiyun 		dclk_rate = rk3528_vop2_if_cfg(state);
3717*4882a593Smuzhiyun 	else if (vop2->version == VOP_VERSION_RK3562)
3718*4882a593Smuzhiyun 		dclk_rate = rk3562_vop2_if_cfg(state);
3719*4882a593Smuzhiyun 
3720*4882a593Smuzhiyun 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
3721*4882a593Smuzhiyun 	    !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT))
3722*4882a593Smuzhiyun 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
3723*4882a593Smuzhiyun 
3724*4882a593Smuzhiyun 	vop2_post_color_swap(state);
3725*4882a593Smuzhiyun 
3726*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
3727*4882a593Smuzhiyun 			OUT_MODE_SHIFT, conn_state->output_mode, false);
3728*4882a593Smuzhiyun 
3729*4882a593Smuzhiyun 	switch (conn_state->bus_format) {
3730*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB565_1X16:
3731*4882a593Smuzhiyun 		dither_down_en = 1;
3732*4882a593Smuzhiyun 		dither_down_mode = RGB888_TO_RGB565;
3733*4882a593Smuzhiyun 		pre_dither_down_en = 1;
3734*4882a593Smuzhiyun 		break;
3735*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X18:
3736*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
3737*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
3738*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
3739*4882a593Smuzhiyun 		dither_down_en = 1;
3740*4882a593Smuzhiyun 		dither_down_mode = RGB888_TO_RGB666;
3741*4882a593Smuzhiyun 		pre_dither_down_en = 1;
3742*4882a593Smuzhiyun 		break;
3743*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV8_1X24:
3744*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
3745*4882a593Smuzhiyun 		dither_down_en = 0;
3746*4882a593Smuzhiyun 		pre_dither_down_en = 1;
3747*4882a593Smuzhiyun 		break;
3748*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUV10_1X30:
3749*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
3750*4882a593Smuzhiyun 		dither_down_en = 0;
3751*4882a593Smuzhiyun 		pre_dither_down_en = 0;
3752*4882a593Smuzhiyun 		break;
3753*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV10_1X20:
3754*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X24:
3755*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
3756*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
3757*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB101010_1X30:
3758*4882a593Smuzhiyun 	default:
3759*4882a593Smuzhiyun 		dither_down_en = 0;
3760*4882a593Smuzhiyun 		pre_dither_down_en = 1;
3761*4882a593Smuzhiyun 		break;
3762*4882a593Smuzhiyun 	}
3763*4882a593Smuzhiyun 
3764*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3765*4882a593Smuzhiyun 			DITHER_DOWN_EN_SHIFT, dither_down_en, false);
3766*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3767*4882a593Smuzhiyun 			DITHER_DOWN_MODE_SHIFT, dither_down_mode, false);
3768*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3769*4882a593Smuzhiyun 			PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
3770*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3771*4882a593Smuzhiyun 			DITHER_DOWN_MODE_SHIFT, dither_down_mode, false);
3772*4882a593Smuzhiyun 
3773*4882a593Smuzhiyun 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
3774*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
3775*4882a593Smuzhiyun 			yuv_overlay, false);
3776*4882a593Smuzhiyun 
3777*4882a593Smuzhiyun 	cstate->yuv_overlay = yuv_overlay;
3778*4882a593Smuzhiyun 
3779*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
3780*4882a593Smuzhiyun 		    (htotal << 16) | hsync_len);
3781*4882a593Smuzhiyun 	val = hact_st << 16;
3782*4882a593Smuzhiyun 	val |= hact_end;
3783*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
3784*4882a593Smuzhiyun 	val = vact_st << 16;
3785*4882a593Smuzhiyun 	val |= vact_end;
3786*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
3787*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
3788*4882a593Smuzhiyun 		u16 vact_st_f1 = vtotal + vact_st + 1;
3789*4882a593Smuzhiyun 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
3790*4882a593Smuzhiyun 
3791*4882a593Smuzhiyun 		val = vact_st_f1 << 16 | vact_end_f1;
3792*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
3793*4882a593Smuzhiyun 			    val);
3794*4882a593Smuzhiyun 
3795*4882a593Smuzhiyun 		val = vtotal << 16 | (vtotal + vsync_len);
3796*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
3797*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3798*4882a593Smuzhiyun 				INTERLACE_EN_SHIFT, 1, false);
3799*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3800*4882a593Smuzhiyun 				DSP_FILED_POL, 1, false);
3801*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3802*4882a593Smuzhiyun 				P2I_EN_SHIFT, 1, false);
3803*4882a593Smuzhiyun 		vtotal += vtotal + 1;
3804*4882a593Smuzhiyun 		act_end = vact_end_f1;
3805*4882a593Smuzhiyun 	} else {
3806*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3807*4882a593Smuzhiyun 				INTERLACE_EN_SHIFT, 0, false);
3808*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3809*4882a593Smuzhiyun 				P2I_EN_SHIFT, 0, false);
3810*4882a593Smuzhiyun 		act_end = vact_end;
3811*4882a593Smuzhiyun 	}
3812*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
3813*4882a593Smuzhiyun 		    (vtotal << 16) | vsync_len);
3814*4882a593Smuzhiyun 
3815*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
3816*4882a593Smuzhiyun 	    conn_state->output_if & VOP_OUTPUT_IF_BT656)
3817*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3818*4882a593Smuzhiyun 				CORE_DCLK_DIV_EN_SHIFT, 1, false);
3819*4882a593Smuzhiyun 	else
3820*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3821*4882a593Smuzhiyun 				CORE_DCLK_DIV_EN_SHIFT, 0, false);
3822*4882a593Smuzhiyun 
3823*4882a593Smuzhiyun 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
3824*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3825*4882a593Smuzhiyun 				DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
3826*4882a593Smuzhiyun 	else
3827*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3828*4882a593Smuzhiyun 				DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
3829*4882a593Smuzhiyun 
3830*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
3831*4882a593Smuzhiyun 			OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false);
3832*4882a593Smuzhiyun 
3833*4882a593Smuzhiyun 	if (yuv_overlay)
3834*4882a593Smuzhiyun 		val = 0x20010200;
3835*4882a593Smuzhiyun 	else
3836*4882a593Smuzhiyun 		val = 0;
3837*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
3838*4882a593Smuzhiyun 	if (cstate->splice_mode) {
3839*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
3840*4882a593Smuzhiyun 				OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id,
3841*4882a593Smuzhiyun 				yuv_overlay, false);
3842*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val);
3843*4882a593Smuzhiyun 	}
3844*4882a593Smuzhiyun 
3845*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3846*4882a593Smuzhiyun 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
3847*4882a593Smuzhiyun 
3848*4882a593Smuzhiyun 	if (vp->xmirror_en)
3849*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
3850*4882a593Smuzhiyun 				DSP_X_MIR_EN_SHIFT, 1, false);
3851*4882a593Smuzhiyun 
3852*4882a593Smuzhiyun 	vop2_tv_config_update(state, vop2);
3853*4882a593Smuzhiyun 	vop2_post_config(state, vop2);
3854*4882a593Smuzhiyun 	if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
3855*4882a593Smuzhiyun 		vop3_post_config(state, vop2);
3856*4882a593Smuzhiyun 
3857*4882a593Smuzhiyun 	if (cstate->dsc_enable) {
3858*4882a593Smuzhiyun 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
3859*4882a593Smuzhiyun 			vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL);
3860*4882a593Smuzhiyun 			vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL);
3861*4882a593Smuzhiyun 		} else {
3862*4882a593Smuzhiyun 			vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL);
3863*4882a593Smuzhiyun 		}
3864*4882a593Smuzhiyun 	}
3865*4882a593Smuzhiyun 
3866*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
3867*4882a593Smuzhiyun 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
3868*4882a593Smuzhiyun 	ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk);
3869*4882a593Smuzhiyun 	if (ret) {
3870*4882a593Smuzhiyun 		printf("%s: Failed to get dclk ret=%d\n", __func__, ret);
3871*4882a593Smuzhiyun 		return ret;
3872*4882a593Smuzhiyun 	}
3873*4882a593Smuzhiyun #endif
3874*4882a593Smuzhiyun 
3875*4882a593Smuzhiyun 	ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev);
3876*4882a593Smuzhiyun 	if (!ret) {
3877*4882a593Smuzhiyun 		ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll);
3878*4882a593Smuzhiyun 		if (ret)
3879*4882a593Smuzhiyun 			debug("%s: hdmi0_phy_pll may not define\n", __func__);
3880*4882a593Smuzhiyun 		ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll);
3881*4882a593Smuzhiyun 		if (ret)
3882*4882a593Smuzhiyun 			debug("%s: hdmi1_phy_pll may not define\n", __func__);
3883*4882a593Smuzhiyun 	} else {
3884*4882a593Smuzhiyun 		hdmi0_phy_pll.dev = NULL;
3885*4882a593Smuzhiyun 		hdmi1_phy_pll.dev = NULL;
3886*4882a593Smuzhiyun 		debug("%s: Faile to find display-subsystem node\n", __func__);
3887*4882a593Smuzhiyun 	}
3888*4882a593Smuzhiyun 
3889*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3528) {
3890*4882a593Smuzhiyun 		struct ofnode_phandle_args args;
3891*4882a593Smuzhiyun 
3892*4882a593Smuzhiyun 		ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents",
3893*4882a593Smuzhiyun 						 "#clock-cells", 0, 0, &args);
3894*4882a593Smuzhiyun 		if (!ret) {
3895*4882a593Smuzhiyun 			ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev);
3896*4882a593Smuzhiyun 			if (ret) {
3897*4882a593Smuzhiyun 				debug("warn: can't get clk device\n");
3898*4882a593Smuzhiyun 				return ret;
3899*4882a593Smuzhiyun 			}
3900*4882a593Smuzhiyun 		} else {
3901*4882a593Smuzhiyun 			debug("assigned-clock-parents's node not define\n");
3902*4882a593Smuzhiyun 		}
3903*4882a593Smuzhiyun 	}
3904*4882a593Smuzhiyun 
3905*4882a593Smuzhiyun 	if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) {
3906*4882a593Smuzhiyun 		if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0)
3907*4882a593Smuzhiyun 			vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll);
3908*4882a593Smuzhiyun 		else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1)
3909*4882a593Smuzhiyun 			vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll);
3910*4882a593Smuzhiyun 
3911*4882a593Smuzhiyun 		/*
3912*4882a593Smuzhiyun 		 * uboot clk driver won't set dclk parent's rate when use
3913*4882a593Smuzhiyun 		 * hdmi phypll as dclk source.
3914*4882a593Smuzhiyun 		 * So set dclk rate is meaningless. Set hdmi phypll rate
3915*4882a593Smuzhiyun 		 * directly.
3916*4882a593Smuzhiyun 		 */
3917*4882a593Smuzhiyun 		if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) {
3918*4882a593Smuzhiyun 			ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate * 1000);
3919*4882a593Smuzhiyun 		} else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) {
3920*4882a593Smuzhiyun 			ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate * 1000);
3921*4882a593Smuzhiyun 		} else {
3922*4882a593Smuzhiyun 			if (is_extend_pll(state, &hdmi_phy_pll.dev)) {
3923*4882a593Smuzhiyun 				ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000);
3924*4882a593Smuzhiyun 			} else {
3925*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
3926*4882a593Smuzhiyun 				ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate * 1000);
3927*4882a593Smuzhiyun #else
3928*4882a593Smuzhiyun 				if (vop2->version == VOP_VERSION_RK3528) {
3929*4882a593Smuzhiyun 					void *cru_base = (void *)RK3528_CRU_BASE;
3930*4882a593Smuzhiyun 
3931*4882a593Smuzhiyun 					/* dclk src switch to hdmiphy pll */
3932*4882a593Smuzhiyun 					writel((BIT(0) << 16) | BIT(0), cru_base + 0x450);
3933*4882a593Smuzhiyun 					rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000);
3934*4882a593Smuzhiyun 					ret = dclk_rate * 1000;
3935*4882a593Smuzhiyun 				}
3936*4882a593Smuzhiyun #endif
3937*4882a593Smuzhiyun 			}
3938*4882a593Smuzhiyun 		}
3939*4882a593Smuzhiyun 	} else {
3940*4882a593Smuzhiyun 		if (is_extend_pll(state, &hdmi_phy_pll.dev))
3941*4882a593Smuzhiyun 			ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000);
3942*4882a593Smuzhiyun 		else
3943*4882a593Smuzhiyun 			ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate * 1000);
3944*4882a593Smuzhiyun 	}
3945*4882a593Smuzhiyun 
3946*4882a593Smuzhiyun 	if (IS_ERR_VALUE(ret)) {
3947*4882a593Smuzhiyun 		printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
3948*4882a593Smuzhiyun 		       __func__, cstate->crtc_id, dclk_rate, ret);
3949*4882a593Smuzhiyun 		return ret;
3950*4882a593Smuzhiyun 	} else {
3951*4882a593Smuzhiyun 		dclk_div_factor = mode->clock / dclk_rate;
3952*4882a593Smuzhiyun 		if (vop2->version == VOP_VERSION_RK3528 &&
3953*4882a593Smuzhiyun 		    conn_state->output_if & VOP_OUTPUT_IF_BT656)
3954*4882a593Smuzhiyun 			mode->crtc_clock = ret / 4 / 1000;
3955*4882a593Smuzhiyun 		else
3956*4882a593Smuzhiyun 			mode->crtc_clock = ret * dclk_div_factor / 1000;
3957*4882a593Smuzhiyun 		printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock);
3958*4882a593Smuzhiyun 	}
3959*4882a593Smuzhiyun 
3960*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
3961*4882a593Smuzhiyun 			RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false);
3962*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
3963*4882a593Smuzhiyun 			RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false);
3964*4882a593Smuzhiyun 
3965*4882a593Smuzhiyun 	if (cstate->mcu_timing.mcu_pix_total)
3966*4882a593Smuzhiyun 		vop3_mcu_mode_setup(state);
3967*4882a593Smuzhiyun 
3968*4882a593Smuzhiyun 	return 0;
3969*4882a593Smuzhiyun }
3970*4882a593Smuzhiyun 
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)3971*4882a593Smuzhiyun static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
3972*4882a593Smuzhiyun 			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
3973*4882a593Smuzhiyun 			     uint32_t dst_h)
3974*4882a593Smuzhiyun {
3975*4882a593Smuzhiyun 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
3976*4882a593Smuzhiyun 	uint16_t hscl_filter_mode, vscl_filter_mode;
3977*4882a593Smuzhiyun 	uint8_t xgt2 = 0, xgt4 = 0;
3978*4882a593Smuzhiyun 	uint8_t ygt2 = 0, ygt4 = 0;
3979*4882a593Smuzhiyun 	uint32_t xfac = 0, yfac = 0;
3980*4882a593Smuzhiyun 	u32 win_offset = win->reg_offset;
3981*4882a593Smuzhiyun 	bool xgt_en = false;
3982*4882a593Smuzhiyun 	bool xavg_en = false;
3983*4882a593Smuzhiyun 
3984*4882a593Smuzhiyun 	if (is_vop3(vop2)) {
3985*4882a593Smuzhiyun 		if (src_w >= (4 * dst_w)) {
3986*4882a593Smuzhiyun 			xgt4 = 1;
3987*4882a593Smuzhiyun 			src_w >>= 2;
3988*4882a593Smuzhiyun 		} else if (src_w >= (2 * dst_w)) {
3989*4882a593Smuzhiyun 			xgt2 = 1;
3990*4882a593Smuzhiyun 			src_w >>= 1;
3991*4882a593Smuzhiyun 		}
3992*4882a593Smuzhiyun 	}
3993*4882a593Smuzhiyun 
3994*4882a593Smuzhiyun 	if (src_h >= (4 * dst_h)) {
3995*4882a593Smuzhiyun 		ygt4 = 1;
3996*4882a593Smuzhiyun 		src_h >>= 2;
3997*4882a593Smuzhiyun 	} else if (src_h >= (2 * dst_h)) {
3998*4882a593Smuzhiyun 		ygt2 = 1;
3999*4882a593Smuzhiyun 		src_h >>= 1;
4000*4882a593Smuzhiyun 	}
4001*4882a593Smuzhiyun 
4002*4882a593Smuzhiyun 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
4003*4882a593Smuzhiyun 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
4004*4882a593Smuzhiyun 
4005*4882a593Smuzhiyun 	if (yrgb_hor_scl_mode == SCALE_UP)
4006*4882a593Smuzhiyun 		hscl_filter_mode = win->hsu_filter_mode;
4007*4882a593Smuzhiyun 	else
4008*4882a593Smuzhiyun 		hscl_filter_mode = win->hsd_filter_mode;
4009*4882a593Smuzhiyun 
4010*4882a593Smuzhiyun 	if (yrgb_ver_scl_mode == SCALE_UP)
4011*4882a593Smuzhiyun 		vscl_filter_mode = win->vsu_filter_mode;
4012*4882a593Smuzhiyun 	else
4013*4882a593Smuzhiyun 		vscl_filter_mode = win->vsd_filter_mode;
4014*4882a593Smuzhiyun 
4015*4882a593Smuzhiyun 	/*
4016*4882a593Smuzhiyun 	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
4017*4882a593Smuzhiyun 	 * at scale down mode
4018*4882a593Smuzhiyun 	 */
4019*4882a593Smuzhiyun 	if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) {
4020*4882a593Smuzhiyun 		printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
4021*4882a593Smuzhiyun 		dst_w += 1;
4022*4882a593Smuzhiyun 	}
4023*4882a593Smuzhiyun 
4024*4882a593Smuzhiyun 	if (is_vop3(vop2)) {
4025*4882a593Smuzhiyun 		xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true);
4026*4882a593Smuzhiyun 		yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false);
4027*4882a593Smuzhiyun 
4028*4882a593Smuzhiyun 		if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG)
4029*4882a593Smuzhiyun 			xavg_en = xgt2 || xgt4;
4030*4882a593Smuzhiyun 		else
4031*4882a593Smuzhiyun 			xgt_en = xgt2 || xgt4;
4032*4882a593Smuzhiyun 	} else {
4033*4882a593Smuzhiyun 		xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
4034*4882a593Smuzhiyun 		yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
4035*4882a593Smuzhiyun 	}
4036*4882a593Smuzhiyun 
4037*4882a593Smuzhiyun 	if (win->type == CLUSTER_LAYER) {
4038*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
4039*4882a593Smuzhiyun 			    yfac << 16 | xfac);
4040*4882a593Smuzhiyun 
4041*4882a593Smuzhiyun 		if (is_vop3(vop2)) {
4042*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4043*4882a593Smuzhiyun 					EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false);
4044*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4045*4882a593Smuzhiyun 					EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false);
4046*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4047*4882a593Smuzhiyun 					XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
4048*4882a593Smuzhiyun 
4049*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4050*4882a593Smuzhiyun 					YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT,
4051*4882a593Smuzhiyun 					yrgb_hor_scl_mode, false);
4052*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4053*4882a593Smuzhiyun 					YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT,
4054*4882a593Smuzhiyun 					yrgb_ver_scl_mode, false);
4055*4882a593Smuzhiyun 		} else {
4056*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4057*4882a593Smuzhiyun 					YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT,
4058*4882a593Smuzhiyun 					yrgb_hor_scl_mode, false);
4059*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4060*4882a593Smuzhiyun 					YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT,
4061*4882a593Smuzhiyun 					yrgb_ver_scl_mode, false);
4062*4882a593Smuzhiyun 		}
4063*4882a593Smuzhiyun 
4064*4882a593Smuzhiyun 		if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
4065*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4066*4882a593Smuzhiyun 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false);
4067*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4068*4882a593Smuzhiyun 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false);
4069*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4070*4882a593Smuzhiyun 					AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false);
4071*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4072*4882a593Smuzhiyun 					AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false);
4073*4882a593Smuzhiyun 		} else {
4074*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4075*4882a593Smuzhiyun 					YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false);
4076*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4077*4882a593Smuzhiyun 					YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false);
4078*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4079*4882a593Smuzhiyun 					AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false);
4080*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
4081*4882a593Smuzhiyun 					AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false);
4082*4882a593Smuzhiyun 		}
4083*4882a593Smuzhiyun 	} else {
4084*4882a593Smuzhiyun 		vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
4085*4882a593Smuzhiyun 			    yfac << 16 | xfac);
4086*4882a593Smuzhiyun 
4087*4882a593Smuzhiyun 		if (is_vop3(vop2)) {
4088*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
4089*4882a593Smuzhiyun 					EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false);
4090*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
4091*4882a593Smuzhiyun 					EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false);
4092*4882a593Smuzhiyun 			vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
4093*4882a593Smuzhiyun 					XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
4094*4882a593Smuzhiyun 		}
4095*4882a593Smuzhiyun 
4096*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
4097*4882a593Smuzhiyun 				YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false);
4098*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
4099*4882a593Smuzhiyun 				YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false);
4100*4882a593Smuzhiyun 
4101*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
4102*4882a593Smuzhiyun 				YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
4103*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
4104*4882a593Smuzhiyun 				YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
4105*4882a593Smuzhiyun 
4106*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
4107*4882a593Smuzhiyun 				YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
4108*4882a593Smuzhiyun 				hscl_filter_mode, false);
4109*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
4110*4882a593Smuzhiyun 				YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
4111*4882a593Smuzhiyun 				vscl_filter_mode, false);
4112*4882a593Smuzhiyun 	}
4113*4882a593Smuzhiyun }
4114*4882a593Smuzhiyun 
vop2_axi_config(struct vop2 * vop2,struct vop2_win_data * win)4115*4882a593Smuzhiyun static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win)
4116*4882a593Smuzhiyun {
4117*4882a593Smuzhiyun 	u32 win_offset = win->reg_offset;
4118*4882a593Smuzhiyun 
4119*4882a593Smuzhiyun 	if (win->type == CLUSTER_LAYER) {
4120*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK,
4121*4882a593Smuzhiyun 				CLUSTER_AXI_ID_SHIFT, win->axi_id, false);
4122*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK,
4123*4882a593Smuzhiyun 				CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
4124*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK,
4125*4882a593Smuzhiyun 				CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
4126*4882a593Smuzhiyun 	} else {
4127*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK,
4128*4882a593Smuzhiyun 				ESMART_AXI_ID_SHIFT, win->axi_id, false);
4129*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK,
4130*4882a593Smuzhiyun 				ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
4131*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK,
4132*4882a593Smuzhiyun 				ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
4133*4882a593Smuzhiyun 	}
4134*4882a593Smuzhiyun }
4135*4882a593Smuzhiyun 
vop2_win_dither_up(uint32_t format)4136*4882a593Smuzhiyun static bool vop2_win_dither_up(uint32_t format)
4137*4882a593Smuzhiyun {
4138*4882a593Smuzhiyun 	switch (format) {
4139*4882a593Smuzhiyun 	case ROCKCHIP_FMT_RGB565:
4140*4882a593Smuzhiyun 		return true;
4141*4882a593Smuzhiyun 	default:
4142*4882a593Smuzhiyun 		return false;
4143*4882a593Smuzhiyun 	}
4144*4882a593Smuzhiyun }
4145*4882a593Smuzhiyun 
vop2_set_cluster_win(struct display_state * state,struct vop2_win_data * win)4146*4882a593Smuzhiyun static void vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
4147*4882a593Smuzhiyun {
4148*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4149*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
4150*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
4151*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4152*4882a593Smuzhiyun 	int src_w = cstate->src_rect.w;
4153*4882a593Smuzhiyun 	int src_h = cstate->src_rect.h;
4154*4882a593Smuzhiyun 	int crtc_x = cstate->crtc_rect.x;
4155*4882a593Smuzhiyun 	int crtc_y = cstate->crtc_rect.y;
4156*4882a593Smuzhiyun 	int crtc_w = cstate->crtc_rect.w;
4157*4882a593Smuzhiyun 	int crtc_h = cstate->crtc_rect.h;
4158*4882a593Smuzhiyun 	int xvir = cstate->xvir;
4159*4882a593Smuzhiyun 	int y_mirror = 0;
4160*4882a593Smuzhiyun 	int csc_mode;
4161*4882a593Smuzhiyun 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
4162*4882a593Smuzhiyun 	/* offset of the right window in splice mode */
4163*4882a593Smuzhiyun 	u32 splice_pixel_offset = 0;
4164*4882a593Smuzhiyun 	u32 splice_yrgb_offset = 0;
4165*4882a593Smuzhiyun 	u32 win_offset = win->reg_offset;
4166*4882a593Smuzhiyun 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4167*4882a593Smuzhiyun 	bool dither_up;
4168*4882a593Smuzhiyun 
4169*4882a593Smuzhiyun 	if (win->splice_mode_right) {
4170*4882a593Smuzhiyun 		src_w = cstate->right_src_rect.w;
4171*4882a593Smuzhiyun 		src_h = cstate->right_src_rect.h;
4172*4882a593Smuzhiyun 		crtc_x = cstate->right_crtc_rect.x;
4173*4882a593Smuzhiyun 		crtc_y = cstate->right_crtc_rect.y;
4174*4882a593Smuzhiyun 		crtc_w = cstate->right_crtc_rect.w;
4175*4882a593Smuzhiyun 		crtc_h = cstate->right_crtc_rect.h;
4176*4882a593Smuzhiyun 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
4177*4882a593Smuzhiyun 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
4178*4882a593Smuzhiyun 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
4179*4882a593Smuzhiyun 	}
4180*4882a593Smuzhiyun 
4181*4882a593Smuzhiyun 	act_info = (src_h - 1) << 16;
4182*4882a593Smuzhiyun 	act_info |= (src_w - 1) & 0xffff;
4183*4882a593Smuzhiyun 
4184*4882a593Smuzhiyun 	dsp_info = (crtc_h - 1) << 16;
4185*4882a593Smuzhiyun 	dsp_info |= (crtc_w - 1) & 0xffff;
4186*4882a593Smuzhiyun 
4187*4882a593Smuzhiyun 	dsp_stx = crtc_x;
4188*4882a593Smuzhiyun 	dsp_sty = crtc_y;
4189*4882a593Smuzhiyun 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
4190*4882a593Smuzhiyun 
4191*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
4192*4882a593Smuzhiyun 		y_mirror = 1;
4193*4882a593Smuzhiyun 	else
4194*4882a593Smuzhiyun 		y_mirror = 0;
4195*4882a593Smuzhiyun 
4196*4882a593Smuzhiyun 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
4197*4882a593Smuzhiyun 
4198*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 ||
4199*4882a593Smuzhiyun 	    vop2->version == VOP_VERSION_RK3562)
4200*4882a593Smuzhiyun 		vop2_axi_config(vop2, win);
4201*4882a593Smuzhiyun 
4202*4882a593Smuzhiyun 	if (y_mirror)
4203*4882a593Smuzhiyun 		printf("WARN: y mirror is unsupported by cluster window\n");
4204*4882a593Smuzhiyun 
4205*4882a593Smuzhiyun 	/* rk3588 should set half_blocK_en to 1 in line and tile mode */
4206*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588)
4207*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset,
4208*4882a593Smuzhiyun 				EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false);
4209*4882a593Smuzhiyun 
4210*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
4211*4882a593Smuzhiyun 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
4212*4882a593Smuzhiyun 			false);
4213*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
4214*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset,
4215*4882a593Smuzhiyun 		    cstate->dma_addr + splice_yrgb_offset);
4216*4882a593Smuzhiyun 
4217*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
4218*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
4219*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
4220*4882a593Smuzhiyun 
4221*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
4222*4882a593Smuzhiyun 
4223*4882a593Smuzhiyun 	csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH);
4224*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
4225*4882a593Smuzhiyun 			CLUSTER_RGB2YUV_EN_SHIFT,
4226*4882a593Smuzhiyun 			is_yuv_output(conn_state->bus_format), false);
4227*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
4228*4882a593Smuzhiyun 			CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
4229*4882a593Smuzhiyun 
4230*4882a593Smuzhiyun 	dither_up = vop2_win_dither_up(cstate->format);
4231*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
4232*4882a593Smuzhiyun 			CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false);
4233*4882a593Smuzhiyun 
4234*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
4235*4882a593Smuzhiyun 
4236*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
4237*4882a593Smuzhiyun }
4238*4882a593Smuzhiyun 
vop2_set_smart_win(struct display_state * state,struct vop2_win_data * win)4239*4882a593Smuzhiyun static void vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
4240*4882a593Smuzhiyun {
4241*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4242*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
4243*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
4244*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4245*4882a593Smuzhiyun 	int src_w = cstate->src_rect.w;
4246*4882a593Smuzhiyun 	int src_h = cstate->src_rect.h;
4247*4882a593Smuzhiyun 	int crtc_x = cstate->crtc_rect.x;
4248*4882a593Smuzhiyun 	int crtc_y = cstate->crtc_rect.y;
4249*4882a593Smuzhiyun 	int crtc_w = cstate->crtc_rect.w;
4250*4882a593Smuzhiyun 	int crtc_h = cstate->crtc_rect.h;
4251*4882a593Smuzhiyun 	int xvir = cstate->xvir;
4252*4882a593Smuzhiyun 	int y_mirror = 0;
4253*4882a593Smuzhiyun 	int csc_mode;
4254*4882a593Smuzhiyun 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
4255*4882a593Smuzhiyun 	/* offset of the right window in splice mode */
4256*4882a593Smuzhiyun 	u32 splice_pixel_offset = 0;
4257*4882a593Smuzhiyun 	u32 splice_yrgb_offset = 0;
4258*4882a593Smuzhiyun 	u32 win_offset = win->reg_offset;
4259*4882a593Smuzhiyun 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4260*4882a593Smuzhiyun 	bool dither_up;
4261*4882a593Smuzhiyun 
4262*4882a593Smuzhiyun 	if (win->splice_mode_right) {
4263*4882a593Smuzhiyun 		src_w = cstate->right_src_rect.w;
4264*4882a593Smuzhiyun 		src_h = cstate->right_src_rect.h;
4265*4882a593Smuzhiyun 		crtc_x = cstate->right_crtc_rect.x;
4266*4882a593Smuzhiyun 		crtc_y = cstate->right_crtc_rect.y;
4267*4882a593Smuzhiyun 		crtc_w = cstate->right_crtc_rect.w;
4268*4882a593Smuzhiyun 		crtc_h = cstate->right_crtc_rect.h;
4269*4882a593Smuzhiyun 		splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
4270*4882a593Smuzhiyun 		splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
4271*4882a593Smuzhiyun 		cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
4272*4882a593Smuzhiyun 	}
4273*4882a593Smuzhiyun 
4274*4882a593Smuzhiyun 	/*
4275*4882a593Smuzhiyun 	 * This is workaround solution for IC design:
4276*4882a593Smuzhiyun 	 * esmart can't support scale down when actual_w % 16 == 1.
4277*4882a593Smuzhiyun 	 */
4278*4882a593Smuzhiyun 	if (src_w > crtc_w && (src_w & 0xf) == 1) {
4279*4882a593Smuzhiyun 		printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
4280*4882a593Smuzhiyun 		src_w -= 1;
4281*4882a593Smuzhiyun 	}
4282*4882a593Smuzhiyun 
4283*4882a593Smuzhiyun 	act_info = (src_h - 1) << 16;
4284*4882a593Smuzhiyun 	act_info |= (src_w - 1) & 0xffff;
4285*4882a593Smuzhiyun 
4286*4882a593Smuzhiyun 	dsp_info = (crtc_h - 1) << 16;
4287*4882a593Smuzhiyun 	dsp_info |= (crtc_w - 1) & 0xffff;
4288*4882a593Smuzhiyun 
4289*4882a593Smuzhiyun 	dsp_stx = crtc_x;
4290*4882a593Smuzhiyun 	dsp_sty = crtc_y;
4291*4882a593Smuzhiyun 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
4292*4882a593Smuzhiyun 
4293*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
4294*4882a593Smuzhiyun 		y_mirror = 1;
4295*4882a593Smuzhiyun 	else
4296*4882a593Smuzhiyun 		y_mirror = 0;
4297*4882a593Smuzhiyun 
4298*4882a593Smuzhiyun 	if (is_vop3(vop2))
4299*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, ESMART_LB_SELECT_MASK,
4300*4882a593Smuzhiyun 				ESMART_LB_SELECT_SHIFT, win->scale_engine_num, false);
4301*4882a593Smuzhiyun 
4302*4882a593Smuzhiyun 	vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
4303*4882a593Smuzhiyun 
4304*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 ||
4305*4882a593Smuzhiyun 	    vop2->version == VOP_VERSION_RK3562)
4306*4882a593Smuzhiyun 		vop2_axi_config(vop2, win);
4307*4882a593Smuzhiyun 
4308*4882a593Smuzhiyun 	if (y_mirror)
4309*4882a593Smuzhiyun 		cstate->dma_addr += (src_h - 1) * xvir * 4;
4310*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
4311*4882a593Smuzhiyun 			YMIRROR_EN_SHIFT, y_mirror, false);
4312*4882a593Smuzhiyun 
4313*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
4314*4882a593Smuzhiyun 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
4315*4882a593Smuzhiyun 			false);
4316*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
4317*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
4318*4882a593Smuzhiyun 		    cstate->dma_addr + splice_yrgb_offset);
4319*4882a593Smuzhiyun 
4320*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
4321*4882a593Smuzhiyun 		    act_info);
4322*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
4323*4882a593Smuzhiyun 		    dsp_info);
4324*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
4325*4882a593Smuzhiyun 
4326*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
4327*4882a593Smuzhiyun 			WIN_EN_SHIFT, 1, false);
4328*4882a593Smuzhiyun 
4329*4882a593Smuzhiyun 	csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH);
4330*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
4331*4882a593Smuzhiyun 			RGB2YUV_EN_SHIFT,
4332*4882a593Smuzhiyun 			is_yuv_output(conn_state->bus_format), false);
4333*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
4334*4882a593Smuzhiyun 			CSC_MODE_SHIFT, csc_mode, false);
4335*4882a593Smuzhiyun 
4336*4882a593Smuzhiyun 	dither_up = vop2_win_dither_up(cstate->format);
4337*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
4338*4882a593Smuzhiyun 			REGION0_DITHER_UP_EN_SHIFT, dither_up, false);
4339*4882a593Smuzhiyun 
4340*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
4341*4882a593Smuzhiyun }
4342*4882a593Smuzhiyun 
vop2_calc_display_rect_for_splice(struct display_state * state)4343*4882a593Smuzhiyun static void vop2_calc_display_rect_for_splice(struct display_state *state)
4344*4882a593Smuzhiyun {
4345*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4346*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
4347*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
4348*4882a593Smuzhiyun 	struct display_rect *src_rect = &cstate->src_rect;
4349*4882a593Smuzhiyun 	struct display_rect *dst_rect = &cstate->crtc_rect;
4350*4882a593Smuzhiyun 	struct display_rect left_src, left_dst, right_src, right_dst;
4351*4882a593Smuzhiyun 	u16 half_hdisplay = mode->crtc_hdisplay >> 1;
4352*4882a593Smuzhiyun 	int left_src_w, left_dst_w, right_dst_w;
4353*4882a593Smuzhiyun 
4354*4882a593Smuzhiyun 	left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x;
4355*4882a593Smuzhiyun 	if (left_dst_w < 0)
4356*4882a593Smuzhiyun 		left_dst_w = 0;
4357*4882a593Smuzhiyun 	right_dst_w = dst_rect->w - left_dst_w;
4358*4882a593Smuzhiyun 
4359*4882a593Smuzhiyun 	if (!right_dst_w)
4360*4882a593Smuzhiyun 		left_src_w = src_rect->w;
4361*4882a593Smuzhiyun 	else
4362*4882a593Smuzhiyun 		left_src_w = src_rect->x + src_rect->w - src_rect->w / 2;
4363*4882a593Smuzhiyun 
4364*4882a593Smuzhiyun 	left_src.x = src_rect->x;
4365*4882a593Smuzhiyun 	left_src.w = left_src_w;
4366*4882a593Smuzhiyun 	left_dst.x = dst_rect->x;
4367*4882a593Smuzhiyun 	left_dst.w = left_dst_w;
4368*4882a593Smuzhiyun 	right_src.x = left_src.x + left_src.w;
4369*4882a593Smuzhiyun 	right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w;
4370*4882a593Smuzhiyun 	right_dst.x = dst_rect->x + left_dst_w - half_hdisplay;
4371*4882a593Smuzhiyun 	right_dst.w = right_dst_w;
4372*4882a593Smuzhiyun 
4373*4882a593Smuzhiyun 	left_src.y = src_rect->y;
4374*4882a593Smuzhiyun 	left_src.h = src_rect->h;
4375*4882a593Smuzhiyun 	left_dst.y = dst_rect->y;
4376*4882a593Smuzhiyun 	left_dst.h = dst_rect->h;
4377*4882a593Smuzhiyun 	right_src.y = src_rect->y;
4378*4882a593Smuzhiyun 	right_src.h = src_rect->h;
4379*4882a593Smuzhiyun 	right_dst.y = dst_rect->y;
4380*4882a593Smuzhiyun 	right_dst.h = dst_rect->h;
4381*4882a593Smuzhiyun 
4382*4882a593Smuzhiyun 	memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect));
4383*4882a593Smuzhiyun 	memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect));
4384*4882a593Smuzhiyun 	memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect));
4385*4882a593Smuzhiyun 	memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect));
4386*4882a593Smuzhiyun }
4387*4882a593Smuzhiyun 
rockchip_vop2_set_plane(struct display_state * state)4388*4882a593Smuzhiyun static int rockchip_vop2_set_plane(struct display_state *state)
4389*4882a593Smuzhiyun {
4390*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4391*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4392*4882a593Smuzhiyun 	struct vop2_win_data *win_data;
4393*4882a593Smuzhiyun 	struct vop2_win_data *splice_win_data;
4394*4882a593Smuzhiyun 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
4395*4882a593Smuzhiyun 	char plane_name[10] = {0};
4396*4882a593Smuzhiyun 
4397*4882a593Smuzhiyun 	if (cstate->crtc_rect.w > cstate->max_output.width) {
4398*4882a593Smuzhiyun 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
4399*4882a593Smuzhiyun 		       cstate->crtc_rect.w, cstate->max_output.width);
4400*4882a593Smuzhiyun 		return -EINVAL;
4401*4882a593Smuzhiyun 	}
4402*4882a593Smuzhiyun 
4403*4882a593Smuzhiyun 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
4404*4882a593Smuzhiyun 	if (!win_data) {
4405*4882a593Smuzhiyun 		printf("invalid win id %d\n", primary_plane_id);
4406*4882a593Smuzhiyun 		return -ENODEV;
4407*4882a593Smuzhiyun 	}
4408*4882a593Smuzhiyun 
4409*4882a593Smuzhiyun 	/* ignore some plane register according vop3 esmart lb mode */
4410*4882a593Smuzhiyun 	if (vop3_ignore_plane(vop2, win_data))
4411*4882a593Smuzhiyun 		return -EACCES;
4412*4882a593Smuzhiyun 
4413*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3588) {
4414*4882a593Smuzhiyun 		if (vop2_power_domain_on(vop2, win_data->pd_id))
4415*4882a593Smuzhiyun 			printf("open vp%d plane pd fail\n", cstate->crtc_id);
4416*4882a593Smuzhiyun 	}
4417*4882a593Smuzhiyun 
4418*4882a593Smuzhiyun 	if (cstate->splice_mode) {
4419*4882a593Smuzhiyun 		if (win_data->splice_win_id) {
4420*4882a593Smuzhiyun 			splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id);
4421*4882a593Smuzhiyun 			splice_win_data->splice_mode_right = true;
4422*4882a593Smuzhiyun 
4423*4882a593Smuzhiyun 			if (vop2_power_domain_on(vop2, splice_win_data->pd_id))
4424*4882a593Smuzhiyun 				printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id);
4425*4882a593Smuzhiyun 
4426*4882a593Smuzhiyun 			vop2_calc_display_rect_for_splice(state);
4427*4882a593Smuzhiyun 			if (win_data->type == CLUSTER_LAYER)
4428*4882a593Smuzhiyun 				vop2_set_cluster_win(state, splice_win_data);
4429*4882a593Smuzhiyun 			else
4430*4882a593Smuzhiyun 				vop2_set_smart_win(state, splice_win_data);
4431*4882a593Smuzhiyun 		} else {
4432*4882a593Smuzhiyun 			printf("ERROR: splice mode is unsupported by plane %s\n",
4433*4882a593Smuzhiyun 			       get_plane_name(primary_plane_id, plane_name));
4434*4882a593Smuzhiyun 			return -EINVAL;
4435*4882a593Smuzhiyun 		}
4436*4882a593Smuzhiyun 	}
4437*4882a593Smuzhiyun 
4438*4882a593Smuzhiyun 	if (win_data->type == CLUSTER_LAYER)
4439*4882a593Smuzhiyun 		vop2_set_cluster_win(state, win_data);
4440*4882a593Smuzhiyun 	else
4441*4882a593Smuzhiyun 		vop2_set_smart_win(state, win_data);
4442*4882a593Smuzhiyun 
4443*4882a593Smuzhiyun 	printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
4444*4882a593Smuzhiyun 		cstate->crtc_id, get_plane_name(primary_plane_id, plane_name),
4445*4882a593Smuzhiyun 		cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h,
4446*4882a593Smuzhiyun 		cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format,
4447*4882a593Smuzhiyun 		cstate->dma_addr);
4448*4882a593Smuzhiyun 
4449*4882a593Smuzhiyun 	return 0;
4450*4882a593Smuzhiyun }
4451*4882a593Smuzhiyun 
rockchip_vop2_prepare(struct display_state * state)4452*4882a593Smuzhiyun static int rockchip_vop2_prepare(struct display_state *state)
4453*4882a593Smuzhiyun {
4454*4882a593Smuzhiyun 	return 0;
4455*4882a593Smuzhiyun }
4456*4882a593Smuzhiyun 
vop2_dsc_cfg_done(struct display_state * state)4457*4882a593Smuzhiyun static void vop2_dsc_cfg_done(struct display_state *state)
4458*4882a593Smuzhiyun {
4459*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
4460*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4461*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4462*4882a593Smuzhiyun 	u8 dsc_id = cstate->dsc_id;
4463*4882a593Smuzhiyun 	u32 ctrl_regs_offset = (dsc_id * 0x30);
4464*4882a593Smuzhiyun 
4465*4882a593Smuzhiyun 	if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
4466*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK,
4467*4882a593Smuzhiyun 				DSC_CFG_DONE_SHIFT, 1, false);
4468*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK,
4469*4882a593Smuzhiyun 				DSC_CFG_DONE_SHIFT, 1, false);
4470*4882a593Smuzhiyun 	} else {
4471*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK,
4472*4882a593Smuzhiyun 				DSC_CFG_DONE_SHIFT, 1, false);
4473*4882a593Smuzhiyun 	}
4474*4882a593Smuzhiyun }
4475*4882a593Smuzhiyun 
rockchip_vop2_enable(struct display_state * state)4476*4882a593Smuzhiyun static int rockchip_vop2_enable(struct display_state *state)
4477*4882a593Smuzhiyun {
4478*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4479*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4480*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
4481*4882a593Smuzhiyun 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4482*4882a593Smuzhiyun 
4483*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4484*4882a593Smuzhiyun 			STANDBY_EN_SHIFT, 0, false);
4485*4882a593Smuzhiyun 
4486*4882a593Smuzhiyun 	if (cstate->splice_mode)
4487*4882a593Smuzhiyun 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
4488*4882a593Smuzhiyun 
4489*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
4490*4882a593Smuzhiyun 
4491*4882a593Smuzhiyun 	if (cstate->dsc_enable)
4492*4882a593Smuzhiyun 		vop2_dsc_cfg_done(state);
4493*4882a593Smuzhiyun 
4494*4882a593Smuzhiyun 	if (cstate->mcu_timing.mcu_pix_total)
4495*4882a593Smuzhiyun 		vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4496*4882a593Smuzhiyun 				MCU_HOLD_MODE_SHIFT, 0, false);
4497*4882a593Smuzhiyun 
4498*4882a593Smuzhiyun 	return 0;
4499*4882a593Smuzhiyun }
4500*4882a593Smuzhiyun 
rockchip_vop2_disable(struct display_state * state)4501*4882a593Smuzhiyun static int rockchip_vop2_disable(struct display_state *state)
4502*4882a593Smuzhiyun {
4503*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4504*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4505*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
4506*4882a593Smuzhiyun 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4507*4882a593Smuzhiyun 
4508*4882a593Smuzhiyun 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4509*4882a593Smuzhiyun 			STANDBY_EN_SHIFT, 1, false);
4510*4882a593Smuzhiyun 
4511*4882a593Smuzhiyun 	if (cstate->splice_mode)
4512*4882a593Smuzhiyun 		cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
4513*4882a593Smuzhiyun 
4514*4882a593Smuzhiyun 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
4515*4882a593Smuzhiyun 
4516*4882a593Smuzhiyun 	return 0;
4517*4882a593Smuzhiyun }
4518*4882a593Smuzhiyun 
rockchip_vop2_get_cursor_plane(struct display_state * state,u32 plane_mask,int cursor_plane)4519*4882a593Smuzhiyun static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane)
4520*4882a593Smuzhiyun {
4521*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4522*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4523*4882a593Smuzhiyun 	int i = 0;
4524*4882a593Smuzhiyun 	int correct_cursor_plane = -1;
4525*4882a593Smuzhiyun 	int plane_type = -1;
4526*4882a593Smuzhiyun 
4527*4882a593Smuzhiyun 	if (cursor_plane < 0)
4528*4882a593Smuzhiyun 		return -1;
4529*4882a593Smuzhiyun 
4530*4882a593Smuzhiyun 	if (plane_mask & (1 << cursor_plane))
4531*4882a593Smuzhiyun 		return cursor_plane;
4532*4882a593Smuzhiyun 
4533*4882a593Smuzhiyun 	/* Get current cursor plane type */
4534*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_layers; i++) {
4535*4882a593Smuzhiyun 		if (vop2->data->plane_table[i].plane_id == cursor_plane) {
4536*4882a593Smuzhiyun 			plane_type = vop2->data->plane_table[i].plane_type;
4537*4882a593Smuzhiyun 			break;
4538*4882a593Smuzhiyun 		}
4539*4882a593Smuzhiyun 	}
4540*4882a593Smuzhiyun 
4541*4882a593Smuzhiyun 	/* Get the other same plane type plane id */
4542*4882a593Smuzhiyun 	for (i = 0; i < vop2->data->nr_layers; i++) {
4543*4882a593Smuzhiyun 		if (vop2->data->plane_table[i].plane_type == plane_type &&
4544*4882a593Smuzhiyun 		    vop2->data->plane_table[i].plane_id != cursor_plane) {
4545*4882a593Smuzhiyun 			correct_cursor_plane = vop2->data->plane_table[i].plane_id;
4546*4882a593Smuzhiyun 			break;
4547*4882a593Smuzhiyun 		}
4548*4882a593Smuzhiyun 	}
4549*4882a593Smuzhiyun 
4550*4882a593Smuzhiyun 	/* To check whether the new correct_cursor_plane is attach to current vp */
4551*4882a593Smuzhiyun 	if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) {
4552*4882a593Smuzhiyun 		printf("error: faild to find correct plane as cursor plane\n");
4553*4882a593Smuzhiyun 		return -1;
4554*4882a593Smuzhiyun 	}
4555*4882a593Smuzhiyun 
4556*4882a593Smuzhiyun 	printf("vp%d adjust cursor plane from %d to %d\n",
4557*4882a593Smuzhiyun 	       cstate->crtc_id, cursor_plane, correct_cursor_plane);
4558*4882a593Smuzhiyun 
4559*4882a593Smuzhiyun 	return correct_cursor_plane;
4560*4882a593Smuzhiyun }
4561*4882a593Smuzhiyun 
rockchip_vop2_fixup_dts(struct display_state * state,void * blob)4562*4882a593Smuzhiyun static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
4563*4882a593Smuzhiyun {
4564*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4565*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4566*4882a593Smuzhiyun 	ofnode vp_node;
4567*4882a593Smuzhiyun 	struct device_node *port_parent_node = cstate->ports_node;
4568*4882a593Smuzhiyun 	static bool vop_fix_dts;
4569*4882a593Smuzhiyun 	const char *path;
4570*4882a593Smuzhiyun 	u32 plane_mask = 0;
4571*4882a593Smuzhiyun 	int vp_id = 0;
4572*4882a593Smuzhiyun 	int cursor_plane_id = -1;
4573*4882a593Smuzhiyun 
4574*4882a593Smuzhiyun 	if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528)
4575*4882a593Smuzhiyun 		return 0;
4576*4882a593Smuzhiyun 
4577*4882a593Smuzhiyun 	ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
4578*4882a593Smuzhiyun 		path = vp_node.np->full_name;
4579*4882a593Smuzhiyun 		plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
4580*4882a593Smuzhiyun 
4581*4882a593Smuzhiyun 		if (cstate->crtc->assign_plane)
4582*4882a593Smuzhiyun 			continue;
4583*4882a593Smuzhiyun 		cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask,
4584*4882a593Smuzhiyun 								 cstate->crtc->vps[vp_id].cursor_plane);
4585*4882a593Smuzhiyun 		printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
4586*4882a593Smuzhiyun 		       vp_id, plane_mask,
4587*4882a593Smuzhiyun 		       vop2->vp_plane_mask[vp_id].primary_plane_id,
4588*4882a593Smuzhiyun 		       cursor_plane_id);
4589*4882a593Smuzhiyun 
4590*4882a593Smuzhiyun 		do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
4591*4882a593Smuzhiyun 				     plane_mask, 1);
4592*4882a593Smuzhiyun 		do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
4593*4882a593Smuzhiyun 				     vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
4594*4882a593Smuzhiyun 		if (cursor_plane_id >= 0)
4595*4882a593Smuzhiyun 			do_fixup_by_path_u32(blob, path, "cursor-win-id",
4596*4882a593Smuzhiyun 					     cursor_plane_id, 1);
4597*4882a593Smuzhiyun 		vp_id++;
4598*4882a593Smuzhiyun 	}
4599*4882a593Smuzhiyun 
4600*4882a593Smuzhiyun 	vop_fix_dts = true;
4601*4882a593Smuzhiyun 
4602*4882a593Smuzhiyun 	return 0;
4603*4882a593Smuzhiyun }
4604*4882a593Smuzhiyun 
rockchip_vop2_check(struct display_state * state)4605*4882a593Smuzhiyun static int rockchip_vop2_check(struct display_state *state)
4606*4882a593Smuzhiyun {
4607*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4608*4882a593Smuzhiyun 	struct rockchip_crtc *crtc = cstate->crtc;
4609*4882a593Smuzhiyun 
4610*4882a593Smuzhiyun 	if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) {
4611*4882a593Smuzhiyun 		printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id);
4612*4882a593Smuzhiyun 		return -ENOTSUPP;
4613*4882a593Smuzhiyun 	}
4614*4882a593Smuzhiyun 
4615*4882a593Smuzhiyun 	if (cstate->splice_mode) {
4616*4882a593Smuzhiyun 		crtc->splice_mode = true;
4617*4882a593Smuzhiyun 		crtc->splice_crtc_id = cstate->splice_crtc_id;
4618*4882a593Smuzhiyun 	}
4619*4882a593Smuzhiyun 
4620*4882a593Smuzhiyun 	return 0;
4621*4882a593Smuzhiyun }
4622*4882a593Smuzhiyun 
rockchip_vop2_mode_valid(struct display_state * state)4623*4882a593Smuzhiyun static int rockchip_vop2_mode_valid(struct display_state *state)
4624*4882a593Smuzhiyun {
4625*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
4626*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4627*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
4628*4882a593Smuzhiyun 	struct videomode vm;
4629*4882a593Smuzhiyun 
4630*4882a593Smuzhiyun 	drm_display_mode_to_videomode(mode, &vm);
4631*4882a593Smuzhiyun 
4632*4882a593Smuzhiyun 	if (vm.hactive < 32 || vm.vactive < 32 ||
4633*4882a593Smuzhiyun 	    (vm.hfront_porch * vm.hsync_len * vm.hback_porch *
4634*4882a593Smuzhiyun 	     vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) {
4635*4882a593Smuzhiyun 		printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id);
4636*4882a593Smuzhiyun 		return -EINVAL;
4637*4882a593Smuzhiyun 	}
4638*4882a593Smuzhiyun 
4639*4882a593Smuzhiyun 	return 0;
4640*4882a593Smuzhiyun }
4641*4882a593Smuzhiyun 
rockchip_vop2_mode_fixup(struct display_state * state)4642*4882a593Smuzhiyun static int rockchip_vop2_mode_fixup(struct display_state *state)
4643*4882a593Smuzhiyun {
4644*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
4645*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
4646*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4647*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4648*4882a593Smuzhiyun 
4649*4882a593Smuzhiyun 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
4650*4882a593Smuzhiyun 
4651*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656)
4652*4882a593Smuzhiyun 		mode->crtc_clock *= 2;
4653*4882a593Smuzhiyun 
4654*4882a593Smuzhiyun 	/*
4655*4882a593Smuzhiyun 	 * For RK3528, the path of CVBS output is like:
4656*4882a593Smuzhiyun 	 * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
4657*4882a593Smuzhiyun 	 * The vop2 dclk should be four times crtc_clock for CVBS sampling
4658*4882a593Smuzhiyun 	 * clock needs.
4659*4882a593Smuzhiyun 	 */
4660*4882a593Smuzhiyun 	if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656)
4661*4882a593Smuzhiyun 		mode->crtc_clock *= 4;
4662*4882a593Smuzhiyun 
4663*4882a593Smuzhiyun 	if (cstate->mcu_timing.mcu_pix_total) {
4664*4882a593Smuzhiyun 		if (conn_state->output_mode == ROCKCHIP_OUT_MODE_S888)
4665*4882a593Smuzhiyun 			/*
4666*4882a593Smuzhiyun 			 * For serial output_mode rgb3x8, one pixel need 3 cycles.
4667*4882a593Smuzhiyun 			 * So dclk should be three times mode clock.
4668*4882a593Smuzhiyun 			 */
4669*4882a593Smuzhiyun 			mode->crtc_clock *= 3;
4670*4882a593Smuzhiyun 		else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_S888_DUMMY)
4671*4882a593Smuzhiyun 			/*
4672*4882a593Smuzhiyun 			 * For serial output_mode argb4x8, one pixel need 4 cycles.
4673*4882a593Smuzhiyun 			 * So dclk should be four times mode clock.
4674*4882a593Smuzhiyun 			 */
4675*4882a593Smuzhiyun 			mode->crtc_clock *= 4;
4676*4882a593Smuzhiyun 	}
4677*4882a593Smuzhiyun 
4678*4882a593Smuzhiyun 	if (conn_state->secondary) {
4679*4882a593Smuzhiyun 		mode->crtc_clock *= 2;
4680*4882a593Smuzhiyun 		mode->crtc_hdisplay *= 2;
4681*4882a593Smuzhiyun 		mode->crtc_hsync_start *= 2;
4682*4882a593Smuzhiyun 		mode->crtc_hsync_end *= 2;
4683*4882a593Smuzhiyun 		mode->crtc_htotal *= 2;
4684*4882a593Smuzhiyun 	}
4685*4882a593Smuzhiyun 
4686*4882a593Smuzhiyun 	return 0;
4687*4882a593Smuzhiyun }
4688*4882a593Smuzhiyun 
4689*4882a593Smuzhiyun #define FRAC_16_16(mult, div)	(((mult) << 16) / (div))
4690*4882a593Smuzhiyun 
rockchip_vop2_plane_check(struct display_state * state)4691*4882a593Smuzhiyun static int rockchip_vop2_plane_check(struct display_state *state)
4692*4882a593Smuzhiyun {
4693*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4694*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4695*4882a593Smuzhiyun 	struct display_rect *src = &cstate->src_rect;
4696*4882a593Smuzhiyun 	struct display_rect *dst = &cstate->crtc_rect;
4697*4882a593Smuzhiyun 	struct vop2_win_data *win_data;
4698*4882a593Smuzhiyun 	int min_scale, max_scale;
4699*4882a593Smuzhiyun 	int hscale, vscale;
4700*4882a593Smuzhiyun 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
4701*4882a593Smuzhiyun 
4702*4882a593Smuzhiyun 	win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
4703*4882a593Smuzhiyun 	if (!win_data) {
4704*4882a593Smuzhiyun 		printf("ERROR: invalid win id %d\n", primary_plane_id);
4705*4882a593Smuzhiyun 		return -ENODEV;
4706*4882a593Smuzhiyun 	}
4707*4882a593Smuzhiyun 
4708*4882a593Smuzhiyun 	min_scale = FRAC_16_16(1, win_data->max_downscale_factor);
4709*4882a593Smuzhiyun 	max_scale = FRAC_16_16(win_data->max_upscale_factor, 1);
4710*4882a593Smuzhiyun 
4711*4882a593Smuzhiyun 	hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale);
4712*4882a593Smuzhiyun 	vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale);
4713*4882a593Smuzhiyun 	if (hscale < 0 || vscale < 0) {
4714*4882a593Smuzhiyun 		printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name);
4715*4882a593Smuzhiyun 		return -ERANGE;
4716*4882a593Smuzhiyun 		}
4717*4882a593Smuzhiyun 
4718*4882a593Smuzhiyun 	return 0;
4719*4882a593Smuzhiyun }
4720*4882a593Smuzhiyun 
rockchip_vop2_apply_soft_te(struct display_state * state)4721*4882a593Smuzhiyun static int rockchip_vop2_apply_soft_te(struct display_state *state)
4722*4882a593Smuzhiyun {
4723*4882a593Smuzhiyun 	__maybe_unused struct connector_state *conn_state = &state->conn_state;
4724*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4725*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4726*4882a593Smuzhiyun 	u32 vp_offset = (cstate->crtc_id * 0x100);
4727*4882a593Smuzhiyun 	int val = 0;
4728*4882a593Smuzhiyun 	int ret = 0;
4729*4882a593Smuzhiyun 
4730*4882a593Smuzhiyun 	ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val,
4731*4882a593Smuzhiyun 				 (val >> EDPI_WMS_FS) & 0x1, 50 * 1000);
4732*4882a593Smuzhiyun 	if (!ret) {
4733*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
4734*4882a593Smuzhiyun 		ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
4735*4882a593Smuzhiyun 					 !val, 50 * 1000);
4736*4882a593Smuzhiyun 		if (!ret) {
4737*4882a593Smuzhiyun 			ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
4738*4882a593Smuzhiyun 						 val, 50 * 1000);
4739*4882a593Smuzhiyun 			if (!ret) {
4740*4882a593Smuzhiyun 				vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4741*4882a593Smuzhiyun 						EN_MASK, EDPI_WMS_FS, 1, false);
4742*4882a593Smuzhiyun 			} else {
4743*4882a593Smuzhiyun 				printf("ERROR: vp%d wait for active TE signal timeout\n",
4744*4882a593Smuzhiyun 				       cstate->crtc_id);
4745*4882a593Smuzhiyun 				return ret;
4746*4882a593Smuzhiyun 			}
4747*4882a593Smuzhiyun 		} else {
4748*4882a593Smuzhiyun 			printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id);
4749*4882a593Smuzhiyun 			return ret;
4750*4882a593Smuzhiyun 		}
4751*4882a593Smuzhiyun #endif
4752*4882a593Smuzhiyun 	} else {
4753*4882a593Smuzhiyun 		printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id);
4754*4882a593Smuzhiyun 		return ret;
4755*4882a593Smuzhiyun 	}
4756*4882a593Smuzhiyun 
4757*4882a593Smuzhiyun 	return 0;
4758*4882a593Smuzhiyun }
4759*4882a593Smuzhiyun 
rockchip_vop2_regs_dump(struct display_state * state)4760*4882a593Smuzhiyun static int rockchip_vop2_regs_dump(struct display_state *state)
4761*4882a593Smuzhiyun {
4762*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4763*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4764*4882a593Smuzhiyun 	const struct vop2_data *vop2_data = vop2->data;
4765*4882a593Smuzhiyun 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
4766*4882a593Smuzhiyun 	u32 n, i, j;
4767*4882a593Smuzhiyun 	u32 base;
4768*4882a593Smuzhiyun 
4769*4882a593Smuzhiyun 	if (!cstate->crtc->active)
4770*4882a593Smuzhiyun 		return -EINVAL;
4771*4882a593Smuzhiyun 
4772*4882a593Smuzhiyun 	n = vop2_data->dump_regs_size;
4773*4882a593Smuzhiyun 	for (i = 0; i < n; i++) {
4774*4882a593Smuzhiyun 		base = regs[i].offset;
4775*4882a593Smuzhiyun 		printf("\n%s:\n", regs[i].name);
4776*4882a593Smuzhiyun 		for (j = 0; j < 68;) {
4777*4882a593Smuzhiyun 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
4778*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * j)),
4779*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * (j + 1))),
4780*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * (j + 2))),
4781*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * (j + 3))));
4782*4882a593Smuzhiyun 			j += 4;
4783*4882a593Smuzhiyun 		}
4784*4882a593Smuzhiyun 	}
4785*4882a593Smuzhiyun 
4786*4882a593Smuzhiyun 	return 0;
4787*4882a593Smuzhiyun }
4788*4882a593Smuzhiyun 
rockchip_vop2_active_regs_dump(struct display_state * state)4789*4882a593Smuzhiyun static int rockchip_vop2_active_regs_dump(struct display_state *state)
4790*4882a593Smuzhiyun {
4791*4882a593Smuzhiyun 	struct crtc_state *cstate = &state->crtc_state;
4792*4882a593Smuzhiyun 	struct vop2 *vop2 = cstate->private;
4793*4882a593Smuzhiyun 	const struct vop2_data *vop2_data = vop2->data;
4794*4882a593Smuzhiyun 	const struct vop2_dump_regs *regs = vop2_data->dump_regs;
4795*4882a593Smuzhiyun 	u32 n, i, j;
4796*4882a593Smuzhiyun 	u32 base;
4797*4882a593Smuzhiyun 	bool enable_state;
4798*4882a593Smuzhiyun 
4799*4882a593Smuzhiyun 	if (!cstate->crtc->active)
4800*4882a593Smuzhiyun 		return -EINVAL;
4801*4882a593Smuzhiyun 
4802*4882a593Smuzhiyun 	n = vop2_data->dump_regs_size;
4803*4882a593Smuzhiyun 	for (i = 0; i < n; i++) {
4804*4882a593Smuzhiyun 		if (regs[i].state_mask) {
4805*4882a593Smuzhiyun 			enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) &
4806*4882a593Smuzhiyun 				       regs[i].state_mask;
4807*4882a593Smuzhiyun 			if (enable_state != regs[i].enable_state)
4808*4882a593Smuzhiyun 				continue;
4809*4882a593Smuzhiyun 		}
4810*4882a593Smuzhiyun 
4811*4882a593Smuzhiyun 		base = regs[i].offset;
4812*4882a593Smuzhiyun 		printf("\n%s:\n", regs[i].name);
4813*4882a593Smuzhiyun 		for (j = 0; j < 68;) {
4814*4882a593Smuzhiyun 			printf("%08lx:  %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
4815*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * j)),
4816*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * (j + 1))),
4817*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * (j + 2))),
4818*4882a593Smuzhiyun 			       vop2_readl(vop2, base + (4 * (j + 3))));
4819*4882a593Smuzhiyun 			j += 4;
4820*4882a593Smuzhiyun 		}
4821*4882a593Smuzhiyun 	}
4822*4882a593Smuzhiyun 
4823*4882a593Smuzhiyun 	return 0;
4824*4882a593Smuzhiyun }
4825*4882a593Smuzhiyun 
4826*4882a593Smuzhiyun static struct vop2_dump_regs rk3528_dump_regs[] = {
4827*4882a593Smuzhiyun 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
4828*4882a593Smuzhiyun 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
4829*4882a593Smuzhiyun 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
4830*4882a593Smuzhiyun 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
4831*4882a593Smuzhiyun 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
4832*4882a593Smuzhiyun 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
4833*4882a593Smuzhiyun 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
4834*4882a593Smuzhiyun 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
4835*4882a593Smuzhiyun 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
4836*4882a593Smuzhiyun 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
4837*4882a593Smuzhiyun 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
4838*4882a593Smuzhiyun 	{ RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
4839*4882a593Smuzhiyun 	{ RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1},
4840*4882a593Smuzhiyun };
4841*4882a593Smuzhiyun 
4842*4882a593Smuzhiyun static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
4843*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART0,
4844*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART1,
4845*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART2,
4846*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART3,
4847*4882a593Smuzhiyun };
4848*4882a593Smuzhiyun 
4849*4882a593Smuzhiyun static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
4850*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
4851*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
4852*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
4853*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
4854*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
4855*4882a593Smuzhiyun };
4856*4882a593Smuzhiyun 
4857*4882a593Smuzhiyun static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
4858*4882a593Smuzhiyun 	{ /* one display policy for hdmi */
4859*4882a593Smuzhiyun 		{/* main display */
4860*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
4861*4882a593Smuzhiyun 			.attached_layers_nr = 4,
4862*4882a593Smuzhiyun 			.attached_layers = {
4863*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0,
4864*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2
4865*4882a593Smuzhiyun 				},
4866*4882a593Smuzhiyun 		},
4867*4882a593Smuzhiyun 		{/* second display */},
4868*4882a593Smuzhiyun 		{/* third  display */},
4869*4882a593Smuzhiyun 		{/* fourth display */},
4870*4882a593Smuzhiyun 	},
4871*4882a593Smuzhiyun 
4872*4882a593Smuzhiyun 	{ /* two display policy */
4873*4882a593Smuzhiyun 		{/* main display */
4874*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
4875*4882a593Smuzhiyun 			.attached_layers_nr = 3,
4876*4882a593Smuzhiyun 			.attached_layers = {
4877*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
4878*4882a593Smuzhiyun 				},
4879*4882a593Smuzhiyun 		},
4880*4882a593Smuzhiyun 
4881*4882a593Smuzhiyun 		{/* second display */
4882*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
4883*4882a593Smuzhiyun 			.attached_layers_nr = 2,
4884*4882a593Smuzhiyun 			.attached_layers = {
4885*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
4886*4882a593Smuzhiyun 				},
4887*4882a593Smuzhiyun 		},
4888*4882a593Smuzhiyun 		{/* third  display */},
4889*4882a593Smuzhiyun 		{/* fourth display */},
4890*4882a593Smuzhiyun 	},
4891*4882a593Smuzhiyun 
4892*4882a593Smuzhiyun 	{ /* one display policy for cvbs */
4893*4882a593Smuzhiyun 		{/* main display */
4894*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
4895*4882a593Smuzhiyun 			.attached_layers_nr = 2,
4896*4882a593Smuzhiyun 			.attached_layers = {
4897*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
4898*4882a593Smuzhiyun 				},
4899*4882a593Smuzhiyun 		},
4900*4882a593Smuzhiyun 		{/* second display */},
4901*4882a593Smuzhiyun 		{/* third  display */},
4902*4882a593Smuzhiyun 		{/* fourth display */},
4903*4882a593Smuzhiyun 	},
4904*4882a593Smuzhiyun 
4905*4882a593Smuzhiyun 	{/* reserved */},
4906*4882a593Smuzhiyun };
4907*4882a593Smuzhiyun 
4908*4882a593Smuzhiyun static struct vop2_win_data rk3528_win_data[5] = {
4909*4882a593Smuzhiyun 	{
4910*4882a593Smuzhiyun 		.name = "Esmart0",
4911*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART0,
4912*4882a593Smuzhiyun 		.type = ESMART_LAYER,
4913*4882a593Smuzhiyun 		.win_sel_port_offset = 8,
4914*4882a593Smuzhiyun 		.layer_sel_win_id = { 1, 0xff, 0xff, 0xff },
4915*4882a593Smuzhiyun 		.reg_offset = 0,
4916*4882a593Smuzhiyun 		.axi_id = 0,
4917*4882a593Smuzhiyun 		.axi_yrgb_id = 0x06,
4918*4882a593Smuzhiyun 		.axi_uv_id = 0x07,
4919*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
4920*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4921*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
4922*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4923*4882a593Smuzhiyun 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
4924*4882a593Smuzhiyun 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
4925*4882a593Smuzhiyun 		.max_upscale_factor = 8,
4926*4882a593Smuzhiyun 		.max_downscale_factor = 8,
4927*4882a593Smuzhiyun 	},
4928*4882a593Smuzhiyun 
4929*4882a593Smuzhiyun 	{
4930*4882a593Smuzhiyun 		.name = "Esmart1",
4931*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART1,
4932*4882a593Smuzhiyun 		.type = ESMART_LAYER,
4933*4882a593Smuzhiyun 		.win_sel_port_offset = 10,
4934*4882a593Smuzhiyun 		.layer_sel_win_id = { 2, 0xff, 0xff, 0xff },
4935*4882a593Smuzhiyun 		.reg_offset = 0x200,
4936*4882a593Smuzhiyun 		.axi_id = 0,
4937*4882a593Smuzhiyun 		.axi_yrgb_id = 0x08,
4938*4882a593Smuzhiyun 		.axi_uv_id = 0x09,
4939*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
4940*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4941*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
4942*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4943*4882a593Smuzhiyun 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
4944*4882a593Smuzhiyun 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
4945*4882a593Smuzhiyun 		.max_upscale_factor = 8,
4946*4882a593Smuzhiyun 		.max_downscale_factor = 8,
4947*4882a593Smuzhiyun 	},
4948*4882a593Smuzhiyun 
4949*4882a593Smuzhiyun 	{
4950*4882a593Smuzhiyun 		.name = "Esmart2",
4951*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART2,
4952*4882a593Smuzhiyun 		.type = ESMART_LAYER,
4953*4882a593Smuzhiyun 		.win_sel_port_offset = 12,
4954*4882a593Smuzhiyun 		.layer_sel_win_id = { 3, 0, 0xff, 0xff },
4955*4882a593Smuzhiyun 		.reg_offset = 0x400,
4956*4882a593Smuzhiyun 		.axi_id = 0,
4957*4882a593Smuzhiyun 		.axi_yrgb_id = 0x0a,
4958*4882a593Smuzhiyun 		.axi_uv_id = 0x0b,
4959*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
4960*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4961*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
4962*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4963*4882a593Smuzhiyun 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
4964*4882a593Smuzhiyun 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
4965*4882a593Smuzhiyun 		.max_upscale_factor = 8,
4966*4882a593Smuzhiyun 		.max_downscale_factor = 8,
4967*4882a593Smuzhiyun 	},
4968*4882a593Smuzhiyun 
4969*4882a593Smuzhiyun 	{
4970*4882a593Smuzhiyun 		.name = "Esmart3",
4971*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART3,
4972*4882a593Smuzhiyun 		.type = ESMART_LAYER,
4973*4882a593Smuzhiyun 		.win_sel_port_offset = 14,
4974*4882a593Smuzhiyun 		.layer_sel_win_id = { 0xff, 1, 0xff, 0xff },
4975*4882a593Smuzhiyun 		.reg_offset = 0x600,
4976*4882a593Smuzhiyun 		.axi_id = 0,
4977*4882a593Smuzhiyun 		.axi_yrgb_id = 0x0c,
4978*4882a593Smuzhiyun 		.axi_uv_id = 0x0d,
4979*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
4980*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4981*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
4982*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
4983*4882a593Smuzhiyun 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
4984*4882a593Smuzhiyun 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,	/* gt only */
4985*4882a593Smuzhiyun 		.max_upscale_factor = 8,
4986*4882a593Smuzhiyun 		.max_downscale_factor = 8,
4987*4882a593Smuzhiyun 	},
4988*4882a593Smuzhiyun 
4989*4882a593Smuzhiyun 	{
4990*4882a593Smuzhiyun 		.name = "Cluster0",
4991*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
4992*4882a593Smuzhiyun 		.type = CLUSTER_LAYER,
4993*4882a593Smuzhiyun 		.win_sel_port_offset = 0,
4994*4882a593Smuzhiyun 		.layer_sel_win_id = { 0, 0xff, 0xff, 0xff },
4995*4882a593Smuzhiyun 		.reg_offset = 0,
4996*4882a593Smuzhiyun 		.axi_id = 0,
4997*4882a593Smuzhiyun 		.axi_yrgb_id = 0x02,
4998*4882a593Smuzhiyun 		.axi_uv_id = 0x03,
4999*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5000*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5001*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5002*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5003*4882a593Smuzhiyun 		.hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
5004*4882a593Smuzhiyun 		.vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,	/* gt or avg */
5005*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5006*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5007*4882a593Smuzhiyun 	},
5008*4882a593Smuzhiyun };
5009*4882a593Smuzhiyun 
5010*4882a593Smuzhiyun static struct vop2_vp_data rk3528_vp_data[2] = {
5011*4882a593Smuzhiyun 	{
5012*4882a593Smuzhiyun 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM |
5013*4882a593Smuzhiyun 			   VOP_FEATURE_POST_CSC,
5014*4882a593Smuzhiyun 		.max_output = {4096, 4096},
5015*4882a593Smuzhiyun 		.layer_mix_dly = 6,
5016*4882a593Smuzhiyun 		.hdr_mix_dly = 2,
5017*4882a593Smuzhiyun 		.win_dly = 8,
5018*4882a593Smuzhiyun 	},
5019*4882a593Smuzhiyun 	{
5020*4882a593Smuzhiyun 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
5021*4882a593Smuzhiyun 		.max_output = {1920, 1080},
5022*4882a593Smuzhiyun 		.layer_mix_dly = 2,
5023*4882a593Smuzhiyun 		.hdr_mix_dly = 0,
5024*4882a593Smuzhiyun 		.win_dly = 8,
5025*4882a593Smuzhiyun 	},
5026*4882a593Smuzhiyun };
5027*4882a593Smuzhiyun 
5028*4882a593Smuzhiyun const struct vop2_data rk3528_vop = {
5029*4882a593Smuzhiyun 	.version = VOP_VERSION_RK3528,
5030*4882a593Smuzhiyun 	.nr_vps = 2,
5031*4882a593Smuzhiyun 	.vp_data = rk3528_vp_data,
5032*4882a593Smuzhiyun 	.win_data = rk3528_win_data,
5033*4882a593Smuzhiyun 	.plane_mask = rk3528_vp_plane_mask[0],
5034*4882a593Smuzhiyun 	.plane_table = rk3528_plane_table,
5035*4882a593Smuzhiyun 	.vp_primary_plane_order = rk3528_vp_primary_plane_order,
5036*4882a593Smuzhiyun 	.nr_layers = 5,
5037*4882a593Smuzhiyun 	.nr_mixers = 3,
5038*4882a593Smuzhiyun 	.nr_gammas = 2,
5039*4882a593Smuzhiyun 	.esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE,
5040*4882a593Smuzhiyun 	.dump_regs = rk3528_dump_regs,
5041*4882a593Smuzhiyun 	.dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
5042*4882a593Smuzhiyun };
5043*4882a593Smuzhiyun 
5044*4882a593Smuzhiyun static struct vop2_dump_regs rk3562_dump_regs[] = {
5045*4882a593Smuzhiyun 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
5046*4882a593Smuzhiyun 	{ RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
5047*4882a593Smuzhiyun 	{ RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
5048*4882a593Smuzhiyun 	{ RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
5049*4882a593Smuzhiyun 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
5050*4882a593Smuzhiyun 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
5051*4882a593Smuzhiyun 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
5052*4882a593Smuzhiyun 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
5053*4882a593Smuzhiyun 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
5054*4882a593Smuzhiyun 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
5055*4882a593Smuzhiyun };
5056*4882a593Smuzhiyun 
5057*4882a593Smuzhiyun static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
5058*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART0,
5059*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART1,
5060*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART2,
5061*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART3,
5062*4882a593Smuzhiyun };
5063*4882a593Smuzhiyun 
5064*4882a593Smuzhiyun static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
5065*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
5066*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
5067*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
5068*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
5069*4882a593Smuzhiyun };
5070*4882a593Smuzhiyun 
5071*4882a593Smuzhiyun static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
5072*4882a593Smuzhiyun 	{ /* one display policy for hdmi */
5073*4882a593Smuzhiyun 		{/* main display */
5074*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5075*4882a593Smuzhiyun 			.attached_layers_nr = 4,
5076*4882a593Smuzhiyun 			.attached_layers = {
5077*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_ESMART0,  ROCKCHIP_VOP2_ESMART1,
5078*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_ESMART2,  ROCKCHIP_VOP2_ESMART3
5079*4882a593Smuzhiyun 				},
5080*4882a593Smuzhiyun 		},
5081*4882a593Smuzhiyun 		{/* second display */},
5082*4882a593Smuzhiyun 		{/* third  display */},
5083*4882a593Smuzhiyun 		{/* fourth display */},
5084*4882a593Smuzhiyun 	},
5085*4882a593Smuzhiyun 
5086*4882a593Smuzhiyun 	{ /* two display policy */
5087*4882a593Smuzhiyun 		{/* main display */
5088*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5089*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5090*4882a593Smuzhiyun 			.attached_layers = {
5091*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1
5092*4882a593Smuzhiyun 				},
5093*4882a593Smuzhiyun 		},
5094*4882a593Smuzhiyun 
5095*4882a593Smuzhiyun 		{/* second display */
5096*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
5097*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5098*4882a593Smuzhiyun 			.attached_layers = {
5099*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3
5100*4882a593Smuzhiyun 				},
5101*4882a593Smuzhiyun 		},
5102*4882a593Smuzhiyun 		{/* third  display */},
5103*4882a593Smuzhiyun 		{/* fourth display */},
5104*4882a593Smuzhiyun 	},
5105*4882a593Smuzhiyun 
5106*4882a593Smuzhiyun 	{/* reserved */},
5107*4882a593Smuzhiyun };
5108*4882a593Smuzhiyun 
5109*4882a593Smuzhiyun static struct vop2_win_data rk3562_win_data[4] = {
5110*4882a593Smuzhiyun 	{
5111*4882a593Smuzhiyun 		.name = "Esmart0",
5112*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART0,
5113*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5114*4882a593Smuzhiyun 		.win_sel_port_offset = 8,
5115*4882a593Smuzhiyun 		.layer_sel_win_id = { 0, 0, 0xff, 0xff },
5116*4882a593Smuzhiyun 		.reg_offset = 0,
5117*4882a593Smuzhiyun 		.axi_id = 0,
5118*4882a593Smuzhiyun 		.axi_yrgb_id = 0x02,
5119*4882a593Smuzhiyun 		.axi_uv_id = 0x03,
5120*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5121*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5122*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5123*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5124*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5125*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5126*4882a593Smuzhiyun 	},
5127*4882a593Smuzhiyun 
5128*4882a593Smuzhiyun 	{
5129*4882a593Smuzhiyun 		.name = "Esmart1",
5130*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART1,
5131*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5132*4882a593Smuzhiyun 		.win_sel_port_offset = 10,
5133*4882a593Smuzhiyun 		.layer_sel_win_id = { 1, 1, 0xff, 0xff },
5134*4882a593Smuzhiyun 		.reg_offset = 0x200,
5135*4882a593Smuzhiyun 		.axi_id = 0,
5136*4882a593Smuzhiyun 		.axi_yrgb_id = 0x04,
5137*4882a593Smuzhiyun 		.axi_uv_id = 0x05,
5138*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5139*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5140*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5141*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5142*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5143*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5144*4882a593Smuzhiyun 	},
5145*4882a593Smuzhiyun 
5146*4882a593Smuzhiyun 	{
5147*4882a593Smuzhiyun 		.name = "Esmart2",
5148*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART2,
5149*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5150*4882a593Smuzhiyun 		.win_sel_port_offset = 12,
5151*4882a593Smuzhiyun 		.layer_sel_win_id = { 2, 2, 0xff, 0xff },
5152*4882a593Smuzhiyun 		.reg_offset = 0x400,
5153*4882a593Smuzhiyun 		.axi_id = 0,
5154*4882a593Smuzhiyun 		.axi_yrgb_id = 0x06,
5155*4882a593Smuzhiyun 		.axi_uv_id = 0x07,
5156*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5157*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5158*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5159*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5160*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5161*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5162*4882a593Smuzhiyun 	},
5163*4882a593Smuzhiyun 
5164*4882a593Smuzhiyun 	{
5165*4882a593Smuzhiyun 		.name = "Esmart3",
5166*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART3,
5167*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5168*4882a593Smuzhiyun 		.win_sel_port_offset = 14,
5169*4882a593Smuzhiyun 		.layer_sel_win_id = { 3, 3, 0xff, 0xff },
5170*4882a593Smuzhiyun 		.reg_offset = 0x600,
5171*4882a593Smuzhiyun 		.axi_id = 0,
5172*4882a593Smuzhiyun 		.axi_yrgb_id = 0x08,
5173*4882a593Smuzhiyun 		.axi_uv_id = 0x0d,
5174*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5175*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5176*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5177*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5178*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5179*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5180*4882a593Smuzhiyun 	},
5181*4882a593Smuzhiyun };
5182*4882a593Smuzhiyun 
5183*4882a593Smuzhiyun static struct vop2_vp_data rk3562_vp_data[2] = {
5184*4882a593Smuzhiyun 	{
5185*4882a593Smuzhiyun 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
5186*4882a593Smuzhiyun 		.max_output = {2048, 4096},
5187*4882a593Smuzhiyun 		.win_dly = 8,
5188*4882a593Smuzhiyun 		.layer_mix_dly = 8,
5189*4882a593Smuzhiyun 	},
5190*4882a593Smuzhiyun 	{
5191*4882a593Smuzhiyun 		.feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
5192*4882a593Smuzhiyun 		.max_output = {2048, 1080},
5193*4882a593Smuzhiyun 		.win_dly = 8,
5194*4882a593Smuzhiyun 		.layer_mix_dly = 8,
5195*4882a593Smuzhiyun 	},
5196*4882a593Smuzhiyun };
5197*4882a593Smuzhiyun 
5198*4882a593Smuzhiyun const struct vop2_data rk3562_vop = {
5199*4882a593Smuzhiyun 	.version = VOP_VERSION_RK3562,
5200*4882a593Smuzhiyun 	.nr_vps = 2,
5201*4882a593Smuzhiyun 	.vp_data = rk3562_vp_data,
5202*4882a593Smuzhiyun 	.win_data = rk3562_win_data,
5203*4882a593Smuzhiyun 	.plane_mask = rk3562_vp_plane_mask[0],
5204*4882a593Smuzhiyun 	.plane_table = rk3562_plane_table,
5205*4882a593Smuzhiyun 	.vp_primary_plane_order = rk3562_vp_primary_plane_order,
5206*4882a593Smuzhiyun 	.nr_layers = 4,
5207*4882a593Smuzhiyun 	.nr_mixers = 3,
5208*4882a593Smuzhiyun 	.nr_gammas = 2,
5209*4882a593Smuzhiyun 	.esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE,
5210*4882a593Smuzhiyun 	.dump_regs = rk3562_dump_regs,
5211*4882a593Smuzhiyun 	.dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
5212*4882a593Smuzhiyun };
5213*4882a593Smuzhiyun 
5214*4882a593Smuzhiyun static struct vop2_dump_regs rk3568_dump_regs[] = {
5215*4882a593Smuzhiyun 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
5216*4882a593Smuzhiyun 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
5217*4882a593Smuzhiyun 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
5218*4882a593Smuzhiyun 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
5219*4882a593Smuzhiyun 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
5220*4882a593Smuzhiyun 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
5221*4882a593Smuzhiyun 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
5222*4882a593Smuzhiyun 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
5223*4882a593Smuzhiyun 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
5224*4882a593Smuzhiyun 	{ RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
5225*4882a593Smuzhiyun 	{ RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
5226*4882a593Smuzhiyun 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
5227*4882a593Smuzhiyun };
5228*4882a593Smuzhiyun 
5229*4882a593Smuzhiyun static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
5230*4882a593Smuzhiyun 	ROCKCHIP_VOP2_SMART0,
5231*4882a593Smuzhiyun 	ROCKCHIP_VOP2_SMART1,
5232*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART0,
5233*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART1,
5234*4882a593Smuzhiyun };
5235*4882a593Smuzhiyun 
5236*4882a593Smuzhiyun static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
5237*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
5238*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
5239*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
5240*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
5241*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
5242*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
5243*4882a593Smuzhiyun };
5244*4882a593Smuzhiyun 
5245*4882a593Smuzhiyun static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
5246*4882a593Smuzhiyun 	{ /* one display policy */
5247*4882a593Smuzhiyun 		{/* main display */
5248*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
5249*4882a593Smuzhiyun 			.attached_layers_nr = 6,
5250*4882a593Smuzhiyun 			.attached_layers = {
5251*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
5252*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
5253*4882a593Smuzhiyun 				},
5254*4882a593Smuzhiyun 		},
5255*4882a593Smuzhiyun 		{/* second display */},
5256*4882a593Smuzhiyun 		{/* third  display */},
5257*4882a593Smuzhiyun 		{/* fourth display */},
5258*4882a593Smuzhiyun 	},
5259*4882a593Smuzhiyun 
5260*4882a593Smuzhiyun 	{ /* two display policy */
5261*4882a593Smuzhiyun 		{/* main display */
5262*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
5263*4882a593Smuzhiyun 			.attached_layers_nr = 3,
5264*4882a593Smuzhiyun 			.attached_layers = {
5265*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
5266*4882a593Smuzhiyun 				},
5267*4882a593Smuzhiyun 		},
5268*4882a593Smuzhiyun 
5269*4882a593Smuzhiyun 		{/* second display */
5270*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
5271*4882a593Smuzhiyun 			.attached_layers_nr = 3,
5272*4882a593Smuzhiyun 			.attached_layers = {
5273*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
5274*4882a593Smuzhiyun 				},
5275*4882a593Smuzhiyun 		},
5276*4882a593Smuzhiyun 		{/* third  display */},
5277*4882a593Smuzhiyun 		{/* fourth display */},
5278*4882a593Smuzhiyun 	},
5279*4882a593Smuzhiyun 
5280*4882a593Smuzhiyun 	{ /* three display policy */
5281*4882a593Smuzhiyun 		{/* main display */
5282*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
5283*4882a593Smuzhiyun 			.attached_layers_nr = 3,
5284*4882a593Smuzhiyun 			.attached_layers = {
5285*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
5286*4882a593Smuzhiyun 				},
5287*4882a593Smuzhiyun 		},
5288*4882a593Smuzhiyun 
5289*4882a593Smuzhiyun 		{/* second display */
5290*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
5291*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5292*4882a593Smuzhiyun 			.attached_layers = {
5293*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
5294*4882a593Smuzhiyun 				},
5295*4882a593Smuzhiyun 		},
5296*4882a593Smuzhiyun 
5297*4882a593Smuzhiyun 		{/* third  display */
5298*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
5299*4882a593Smuzhiyun 			.attached_layers_nr = 1,
5300*4882a593Smuzhiyun 			.attached_layers = { ROCKCHIP_VOP2_ESMART1 },
5301*4882a593Smuzhiyun 		},
5302*4882a593Smuzhiyun 
5303*4882a593Smuzhiyun 		{/* fourth display */},
5304*4882a593Smuzhiyun 	},
5305*4882a593Smuzhiyun 
5306*4882a593Smuzhiyun 	{/* reserved for four display policy */},
5307*4882a593Smuzhiyun };
5308*4882a593Smuzhiyun 
5309*4882a593Smuzhiyun static struct vop2_win_data rk3568_win_data[6] = {
5310*4882a593Smuzhiyun 	{
5311*4882a593Smuzhiyun 		.name = "Cluster0",
5312*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
5313*4882a593Smuzhiyun 		.type = CLUSTER_LAYER,
5314*4882a593Smuzhiyun 		.win_sel_port_offset = 0,
5315*4882a593Smuzhiyun 		.layer_sel_win_id = { 0, 0, 0, 0xff },
5316*4882a593Smuzhiyun 		.reg_offset = 0,
5317*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5318*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5319*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5320*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5321*4882a593Smuzhiyun 		.max_upscale_factor = 4,
5322*4882a593Smuzhiyun 		.max_downscale_factor = 4,
5323*4882a593Smuzhiyun 	},
5324*4882a593Smuzhiyun 
5325*4882a593Smuzhiyun 	{
5326*4882a593Smuzhiyun 		.name = "Cluster1",
5327*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
5328*4882a593Smuzhiyun 		.type = CLUSTER_LAYER,
5329*4882a593Smuzhiyun 		.win_sel_port_offset = 1,
5330*4882a593Smuzhiyun 		.layer_sel_win_id = { 1, 1, 1, 0xff },
5331*4882a593Smuzhiyun 		.reg_offset = 0x200,
5332*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5333*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5334*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5335*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5336*4882a593Smuzhiyun 		.max_upscale_factor = 4,
5337*4882a593Smuzhiyun 		.max_downscale_factor = 4,
5338*4882a593Smuzhiyun 	},
5339*4882a593Smuzhiyun 
5340*4882a593Smuzhiyun 	{
5341*4882a593Smuzhiyun 		.name = "Esmart0",
5342*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART0,
5343*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5344*4882a593Smuzhiyun 		.win_sel_port_offset = 4,
5345*4882a593Smuzhiyun 		.layer_sel_win_id = { 2, 2, 2, 0xff },
5346*4882a593Smuzhiyun 		.reg_offset = 0,
5347*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5348*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5349*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5350*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5351*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5352*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5353*4882a593Smuzhiyun 	},
5354*4882a593Smuzhiyun 
5355*4882a593Smuzhiyun 	{
5356*4882a593Smuzhiyun 		.name = "Esmart1",
5357*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART1,
5358*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5359*4882a593Smuzhiyun 		.win_sel_port_offset = 5,
5360*4882a593Smuzhiyun 		.layer_sel_win_id = { 6, 6, 6, 0xff },
5361*4882a593Smuzhiyun 		.reg_offset = 0x200,
5362*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5363*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5364*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5365*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5366*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5367*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5368*4882a593Smuzhiyun 	},
5369*4882a593Smuzhiyun 
5370*4882a593Smuzhiyun 	{
5371*4882a593Smuzhiyun 		.name = "Smart0",
5372*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_SMART0,
5373*4882a593Smuzhiyun 		.type = SMART_LAYER,
5374*4882a593Smuzhiyun 		.win_sel_port_offset = 6,
5375*4882a593Smuzhiyun 		.layer_sel_win_id = { 3, 3, 3, 0xff },
5376*4882a593Smuzhiyun 		.reg_offset = 0x400,
5377*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5378*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5379*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5380*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5381*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5382*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5383*4882a593Smuzhiyun 	},
5384*4882a593Smuzhiyun 
5385*4882a593Smuzhiyun 	{
5386*4882a593Smuzhiyun 		.name = "Smart1",
5387*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_SMART1,
5388*4882a593Smuzhiyun 		.type = SMART_LAYER,
5389*4882a593Smuzhiyun 		.win_sel_port_offset = 7,
5390*4882a593Smuzhiyun 		.layer_sel_win_id = { 7, 7, 7, 0xff },
5391*4882a593Smuzhiyun 		.reg_offset = 0x600,
5392*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5393*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5394*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5395*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5396*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5397*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5398*4882a593Smuzhiyun 	},
5399*4882a593Smuzhiyun };
5400*4882a593Smuzhiyun 
5401*4882a593Smuzhiyun static struct vop2_vp_data rk3568_vp_data[3] = {
5402*4882a593Smuzhiyun 	{
5403*4882a593Smuzhiyun 		.feature = VOP_FEATURE_OUTPUT_10BIT,
5404*4882a593Smuzhiyun 		.pre_scan_max_dly = 42,
5405*4882a593Smuzhiyun 		.max_output = {4096, 2304},
5406*4882a593Smuzhiyun 	},
5407*4882a593Smuzhiyun 	{
5408*4882a593Smuzhiyun 		.feature = 0,
5409*4882a593Smuzhiyun 		.pre_scan_max_dly = 40,
5410*4882a593Smuzhiyun 		.max_output = {2048, 1536},
5411*4882a593Smuzhiyun 	},
5412*4882a593Smuzhiyun 	{
5413*4882a593Smuzhiyun 		.feature = 0,
5414*4882a593Smuzhiyun 		.pre_scan_max_dly = 40,
5415*4882a593Smuzhiyun 		.max_output = {1920, 1080},
5416*4882a593Smuzhiyun 	},
5417*4882a593Smuzhiyun };
5418*4882a593Smuzhiyun 
5419*4882a593Smuzhiyun const struct vop2_data rk3568_vop = {
5420*4882a593Smuzhiyun 	.version = VOP_VERSION_RK3568,
5421*4882a593Smuzhiyun 	.nr_vps = 3,
5422*4882a593Smuzhiyun 	.vp_data = rk3568_vp_data,
5423*4882a593Smuzhiyun 	.win_data = rk3568_win_data,
5424*4882a593Smuzhiyun 	.plane_mask = rk356x_vp_plane_mask[0],
5425*4882a593Smuzhiyun 	.plane_table = rk356x_plane_table,
5426*4882a593Smuzhiyun 	.vp_primary_plane_order = rk3568_vp_primary_plane_order,
5427*4882a593Smuzhiyun 	.nr_layers = 6,
5428*4882a593Smuzhiyun 	.nr_mixers = 5,
5429*4882a593Smuzhiyun 	.nr_gammas = 1,
5430*4882a593Smuzhiyun 	.dump_regs = rk3568_dump_regs,
5431*4882a593Smuzhiyun 	.dump_regs_size = ARRAY_SIZE(rk3568_dump_regs),
5432*4882a593Smuzhiyun };
5433*4882a593Smuzhiyun 
5434*4882a593Smuzhiyun static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = {
5435*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART0,
5436*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART1,
5437*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART2,
5438*4882a593Smuzhiyun 	ROCKCHIP_VOP2_ESMART3,
5439*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER0,
5440*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER1,
5441*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER2,
5442*4882a593Smuzhiyun 	ROCKCHIP_VOP2_CLUSTER3,
5443*4882a593Smuzhiyun };
5444*4882a593Smuzhiyun 
5445*4882a593Smuzhiyun static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
5446*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
5447*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
5448*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER},
5449*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER},
5450*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
5451*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
5452*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART2, ESMART_LAYER},
5453*4882a593Smuzhiyun 	{ROCKCHIP_VOP2_ESMART3, ESMART_LAYER},
5454*4882a593Smuzhiyun };
5455*4882a593Smuzhiyun 
5456*4882a593Smuzhiyun static struct vop2_dump_regs rk3588_dump_regs[] = {
5457*4882a593Smuzhiyun 	{ RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
5458*4882a593Smuzhiyun 	{ RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
5459*4882a593Smuzhiyun 	{ RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
5460*4882a593Smuzhiyun 	{ RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
5461*4882a593Smuzhiyun 	{ RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
5462*4882a593Smuzhiyun 	{ RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 },
5463*4882a593Smuzhiyun 	{ RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
5464*4882a593Smuzhiyun 	{ RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
5465*4882a593Smuzhiyun 	{ RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 },
5466*4882a593Smuzhiyun 	{ RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 },
5467*4882a593Smuzhiyun 	{ RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
5468*4882a593Smuzhiyun 	{ RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
5469*4882a593Smuzhiyun 	{ RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
5470*4882a593Smuzhiyun 	{ RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
5471*4882a593Smuzhiyun 	{ RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
5472*4882a593Smuzhiyun };
5473*4882a593Smuzhiyun 
5474*4882a593Smuzhiyun static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
5475*4882a593Smuzhiyun 	{ /* one display policy */
5476*4882a593Smuzhiyun 		{/* main display */
5477*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5478*4882a593Smuzhiyun 			.attached_layers_nr = 8,
5479*4882a593Smuzhiyun 			.attached_layers = {
5480*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2,
5481*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3,
5482*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3
5483*4882a593Smuzhiyun 			},
5484*4882a593Smuzhiyun 		},
5485*4882a593Smuzhiyun 		{/* second display */},
5486*4882a593Smuzhiyun 		{/* third  display */},
5487*4882a593Smuzhiyun 		{/* fourth display */},
5488*4882a593Smuzhiyun 	},
5489*4882a593Smuzhiyun 
5490*4882a593Smuzhiyun 	{ /* two display policy */
5491*4882a593Smuzhiyun 		{/* main display */
5492*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5493*4882a593Smuzhiyun 			.attached_layers_nr = 4,
5494*4882a593Smuzhiyun 			.attached_layers = {
5495*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
5496*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1
5497*4882a593Smuzhiyun 			},
5498*4882a593Smuzhiyun 		},
5499*4882a593Smuzhiyun 
5500*4882a593Smuzhiyun 		{/* second display */
5501*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
5502*4882a593Smuzhiyun 			.attached_layers_nr = 4,
5503*4882a593Smuzhiyun 			.attached_layers = {
5504*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2,
5505*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
5506*4882a593Smuzhiyun 			},
5507*4882a593Smuzhiyun 		},
5508*4882a593Smuzhiyun 		{/* third  display */},
5509*4882a593Smuzhiyun 		{/* fourth display */},
5510*4882a593Smuzhiyun 	},
5511*4882a593Smuzhiyun 
5512*4882a593Smuzhiyun 	{ /* three display policy */
5513*4882a593Smuzhiyun 		{/* main display */
5514*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5515*4882a593Smuzhiyun 			.attached_layers_nr = 3,
5516*4882a593Smuzhiyun 			.attached_layers = {
5517*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0
5518*4882a593Smuzhiyun 			},
5519*4882a593Smuzhiyun 		},
5520*4882a593Smuzhiyun 
5521*4882a593Smuzhiyun 		{/* second display */
5522*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
5523*4882a593Smuzhiyun 			.attached_layers_nr = 3,
5524*4882a593Smuzhiyun 			.attached_layers = {
5525*4882a593Smuzhiyun 				  ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1
5526*4882a593Smuzhiyun 			},
5527*4882a593Smuzhiyun 		},
5528*4882a593Smuzhiyun 
5529*4882a593Smuzhiyun 		{/* third  display */
5530*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
5531*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5532*4882a593Smuzhiyun 			.attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
5533*4882a593Smuzhiyun 		},
5534*4882a593Smuzhiyun 
5535*4882a593Smuzhiyun 		{/* fourth display */},
5536*4882a593Smuzhiyun 	},
5537*4882a593Smuzhiyun 
5538*4882a593Smuzhiyun 	{ /* four display policy */
5539*4882a593Smuzhiyun 		{/* main display */
5540*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART0,
5541*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5542*4882a593Smuzhiyun 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
5543*4882a593Smuzhiyun 		},
5544*4882a593Smuzhiyun 
5545*4882a593Smuzhiyun 		{/* second display */
5546*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
5547*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5548*4882a593Smuzhiyun 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
5549*4882a593Smuzhiyun 		},
5550*4882a593Smuzhiyun 
5551*4882a593Smuzhiyun 		{/* third  display */
5552*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART2,
5553*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5554*4882a593Smuzhiyun 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
5555*4882a593Smuzhiyun 		},
5556*4882a593Smuzhiyun 
5557*4882a593Smuzhiyun 		{/* fourth display */
5558*4882a593Smuzhiyun 			.primary_plane_id = ROCKCHIP_VOP2_ESMART3,
5559*4882a593Smuzhiyun 			.attached_layers_nr = 2,
5560*4882a593Smuzhiyun 			.attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
5561*4882a593Smuzhiyun 		},
5562*4882a593Smuzhiyun 	},
5563*4882a593Smuzhiyun 
5564*4882a593Smuzhiyun };
5565*4882a593Smuzhiyun 
5566*4882a593Smuzhiyun static struct vop2_win_data rk3588_win_data[8] = {
5567*4882a593Smuzhiyun 	{
5568*4882a593Smuzhiyun 		.name = "Cluster0",
5569*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
5570*4882a593Smuzhiyun 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER1,
5571*4882a593Smuzhiyun 		.type = CLUSTER_LAYER,
5572*4882a593Smuzhiyun 		.win_sel_port_offset = 0,
5573*4882a593Smuzhiyun 		.layer_sel_win_id = { 0, 0, 0, 0 },
5574*4882a593Smuzhiyun 		.reg_offset = 0,
5575*4882a593Smuzhiyun 		.axi_id = 0,
5576*4882a593Smuzhiyun 		.axi_yrgb_id = 2,
5577*4882a593Smuzhiyun 		.axi_uv_id = 3,
5578*4882a593Smuzhiyun 		.pd_id = VOP2_PD_CLUSTER0,
5579*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5580*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5581*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5582*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5583*4882a593Smuzhiyun 		.max_upscale_factor = 4,
5584*4882a593Smuzhiyun 		.max_downscale_factor = 4,
5585*4882a593Smuzhiyun 	},
5586*4882a593Smuzhiyun 
5587*4882a593Smuzhiyun 	{
5588*4882a593Smuzhiyun 		.name = "Cluster1",
5589*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
5590*4882a593Smuzhiyun 		.type = CLUSTER_LAYER,
5591*4882a593Smuzhiyun 		.win_sel_port_offset = 1,
5592*4882a593Smuzhiyun 		.layer_sel_win_id = { 1, 1, 1, 1 },
5593*4882a593Smuzhiyun 		.reg_offset = 0x200,
5594*4882a593Smuzhiyun 		.axi_id = 0,
5595*4882a593Smuzhiyun 		.axi_yrgb_id = 6,
5596*4882a593Smuzhiyun 		.axi_uv_id = 7,
5597*4882a593Smuzhiyun 		.pd_id = VOP2_PD_CLUSTER1,
5598*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5599*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5600*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5601*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5602*4882a593Smuzhiyun 		.max_upscale_factor = 4,
5603*4882a593Smuzhiyun 		.max_downscale_factor = 4,
5604*4882a593Smuzhiyun 	},
5605*4882a593Smuzhiyun 
5606*4882a593Smuzhiyun 	{
5607*4882a593Smuzhiyun 		.name = "Cluster2",
5608*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_CLUSTER2,
5609*4882a593Smuzhiyun 		.splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
5610*4882a593Smuzhiyun 		.type = CLUSTER_LAYER,
5611*4882a593Smuzhiyun 		.win_sel_port_offset = 2,
5612*4882a593Smuzhiyun 		.layer_sel_win_id = { 4, 4, 4, 4 },
5613*4882a593Smuzhiyun 		.reg_offset = 0x400,
5614*4882a593Smuzhiyun 		.axi_id = 1,
5615*4882a593Smuzhiyun 		.axi_yrgb_id = 2,
5616*4882a593Smuzhiyun 		.axi_uv_id = 3,
5617*4882a593Smuzhiyun 		.pd_id = VOP2_PD_CLUSTER2,
5618*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5619*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5620*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5621*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5622*4882a593Smuzhiyun 		.max_upscale_factor = 4,
5623*4882a593Smuzhiyun 		.max_downscale_factor = 4,
5624*4882a593Smuzhiyun 	},
5625*4882a593Smuzhiyun 
5626*4882a593Smuzhiyun 	{
5627*4882a593Smuzhiyun 		.name = "Cluster3",
5628*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_CLUSTER3,
5629*4882a593Smuzhiyun 		.type = CLUSTER_LAYER,
5630*4882a593Smuzhiyun 		.win_sel_port_offset = 3,
5631*4882a593Smuzhiyun 		.layer_sel_win_id = { 5, 5, 5, 5 },
5632*4882a593Smuzhiyun 		.reg_offset = 0x600,
5633*4882a593Smuzhiyun 		.axi_id = 1,
5634*4882a593Smuzhiyun 		.axi_yrgb_id = 6,
5635*4882a593Smuzhiyun 		.axi_uv_id = 7,
5636*4882a593Smuzhiyun 		.pd_id = VOP2_PD_CLUSTER3,
5637*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5638*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5639*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5640*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5641*4882a593Smuzhiyun 		.max_upscale_factor = 4,
5642*4882a593Smuzhiyun 		.max_downscale_factor = 4,
5643*4882a593Smuzhiyun 	},
5644*4882a593Smuzhiyun 
5645*4882a593Smuzhiyun 	{
5646*4882a593Smuzhiyun 		.name = "Esmart0",
5647*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART0,
5648*4882a593Smuzhiyun 		.splice_win_id = ROCKCHIP_VOP2_ESMART1,
5649*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5650*4882a593Smuzhiyun 		.win_sel_port_offset = 4,
5651*4882a593Smuzhiyun 		.layer_sel_win_id = { 2, 2, 2, 2 },
5652*4882a593Smuzhiyun 		.reg_offset = 0,
5653*4882a593Smuzhiyun 		.axi_id = 0,
5654*4882a593Smuzhiyun 		.axi_yrgb_id = 0x0a,
5655*4882a593Smuzhiyun 		.axi_uv_id = 0x0b,
5656*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5657*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5658*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5659*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5660*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5661*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5662*4882a593Smuzhiyun 	},
5663*4882a593Smuzhiyun 
5664*4882a593Smuzhiyun 	{
5665*4882a593Smuzhiyun 		.name = "Esmart1",
5666*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART1,
5667*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5668*4882a593Smuzhiyun 		.win_sel_port_offset = 5,
5669*4882a593Smuzhiyun 		.layer_sel_win_id = { 3, 3, 3, 3 },
5670*4882a593Smuzhiyun 		.reg_offset = 0x200,
5671*4882a593Smuzhiyun 		.axi_id = 0,
5672*4882a593Smuzhiyun 		.axi_yrgb_id = 0x0c,
5673*4882a593Smuzhiyun 		.axi_uv_id = 0x0d,
5674*4882a593Smuzhiyun 		.pd_id = VOP2_PD_ESMART,
5675*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5676*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5677*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5678*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5679*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5680*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5681*4882a593Smuzhiyun 	},
5682*4882a593Smuzhiyun 
5683*4882a593Smuzhiyun 	{
5684*4882a593Smuzhiyun 		.name = "Esmart2",
5685*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART2,
5686*4882a593Smuzhiyun 		.splice_win_id = ROCKCHIP_VOP2_ESMART3,
5687*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5688*4882a593Smuzhiyun 		.win_sel_port_offset = 6,
5689*4882a593Smuzhiyun 		.layer_sel_win_id = { 6, 6, 6, 6 },
5690*4882a593Smuzhiyun 		.reg_offset = 0x400,
5691*4882a593Smuzhiyun 		.axi_id = 1,
5692*4882a593Smuzhiyun 		.axi_yrgb_id = 0x0a,
5693*4882a593Smuzhiyun 		.axi_uv_id = 0x0b,
5694*4882a593Smuzhiyun 		.pd_id = VOP2_PD_ESMART,
5695*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5696*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5697*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5698*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5699*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5700*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5701*4882a593Smuzhiyun 	},
5702*4882a593Smuzhiyun 
5703*4882a593Smuzhiyun 	{
5704*4882a593Smuzhiyun 		.name = "Esmart3",
5705*4882a593Smuzhiyun 		.phys_id = ROCKCHIP_VOP2_ESMART3,
5706*4882a593Smuzhiyun 		.type = ESMART_LAYER,
5707*4882a593Smuzhiyun 		.win_sel_port_offset = 7,
5708*4882a593Smuzhiyun 		.layer_sel_win_id = { 7, 7, 7, 7 },
5709*4882a593Smuzhiyun 		.reg_offset = 0x600,
5710*4882a593Smuzhiyun 		.axi_id = 1,
5711*4882a593Smuzhiyun 		.axi_yrgb_id = 0x0c,
5712*4882a593Smuzhiyun 		.axi_uv_id = 0x0d,
5713*4882a593Smuzhiyun 		.pd_id = VOP2_PD_ESMART,
5714*4882a593Smuzhiyun 		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
5715*4882a593Smuzhiyun 		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5716*4882a593Smuzhiyun 		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
5717*4882a593Smuzhiyun 		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
5718*4882a593Smuzhiyun 		.max_upscale_factor = 8,
5719*4882a593Smuzhiyun 		.max_downscale_factor = 8,
5720*4882a593Smuzhiyun 	},
5721*4882a593Smuzhiyun };
5722*4882a593Smuzhiyun 
5723*4882a593Smuzhiyun static struct dsc_error_info dsc_ecw[] = {
5724*4882a593Smuzhiyun 	{0x00000000, "no error detected by DSC encoder"},
5725*4882a593Smuzhiyun 	{0x0030ffff, "bits per component error"},
5726*4882a593Smuzhiyun 	{0x0040ffff, "multiple mode error"},
5727*4882a593Smuzhiyun 	{0x0050ffff, "line buffer depth error"},
5728*4882a593Smuzhiyun 	{0x0060ffff, "minor version error"},
5729*4882a593Smuzhiyun 	{0x0070ffff, "picture height error"},
5730*4882a593Smuzhiyun 	{0x0080ffff, "picture width error"},
5731*4882a593Smuzhiyun 	{0x0090ffff, "number of slices error"},
5732*4882a593Smuzhiyun 	{0x00c0ffff, "slice height Error "},
5733*4882a593Smuzhiyun 	{0x00d0ffff, "slice width error"},
5734*4882a593Smuzhiyun 	{0x00e0ffff, "second line BPG offset error"},
5735*4882a593Smuzhiyun 	{0x00f0ffff, "non second line BPG offset error"},
5736*4882a593Smuzhiyun 	{0x0100ffff, "PPS ID error"},
5737*4882a593Smuzhiyun 	{0x0110ffff, "bits per pixel (BPP) Error"},
5738*4882a593Smuzhiyun 	{0x0120ffff, "buffer flow error"},  /* dsc_buffer_flow */
5739*4882a593Smuzhiyun 
5740*4882a593Smuzhiyun 	{0x01510001, "slice 0 RC buffer model overflow error"},
5741*4882a593Smuzhiyun 	{0x01510002, "slice 1 RC buffer model overflow error"},
5742*4882a593Smuzhiyun 	{0x01510004, "slice 2 RC buffer model overflow error"},
5743*4882a593Smuzhiyun 	{0x01510008, "slice 3 RC buffer model overflow error"},
5744*4882a593Smuzhiyun 	{0x01510010, "slice 4 RC buffer model overflow error"},
5745*4882a593Smuzhiyun 	{0x01510020, "slice 5 RC buffer model overflow error"},
5746*4882a593Smuzhiyun 	{0x01510040, "slice 6 RC buffer model overflow error"},
5747*4882a593Smuzhiyun 	{0x01510080, "slice 7 RC buffer model overflow error"},
5748*4882a593Smuzhiyun 
5749*4882a593Smuzhiyun 	{0x01610001, "slice 0 RC buffer model underflow error"},
5750*4882a593Smuzhiyun 	{0x01610002, "slice 1 RC buffer model underflow error"},
5751*4882a593Smuzhiyun 	{0x01610004, "slice 2 RC buffer model underflow error"},
5752*4882a593Smuzhiyun 	{0x01610008, "slice 3 RC buffer model underflow error"},
5753*4882a593Smuzhiyun 	{0x01610010, "slice 4 RC buffer model underflow error"},
5754*4882a593Smuzhiyun 	{0x01610020, "slice 5 RC buffer model underflow error"},
5755*4882a593Smuzhiyun 	{0x01610040, "slice 6 RC buffer model underflow error"},
5756*4882a593Smuzhiyun 	{0x01610080, "slice 7 RC buffer model underflow error"},
5757*4882a593Smuzhiyun 
5758*4882a593Smuzhiyun 	{0xffffffff, "unsuccessful RESET cycle status"},
5759*4882a593Smuzhiyun 	{0x00a0ffff, "ICH full error precision settings error"},
5760*4882a593Smuzhiyun 	{0x0020ffff, "native mode"},
5761*4882a593Smuzhiyun };
5762*4882a593Smuzhiyun 
5763*4882a593Smuzhiyun static struct dsc_error_info dsc_buffer_flow[] = {
5764*4882a593Smuzhiyun 	{0x00000000, "rate buffer status"},
5765*4882a593Smuzhiyun 	{0x00000001, "line buffer status"},
5766*4882a593Smuzhiyun 	{0x00000002, "decoder model status"},
5767*4882a593Smuzhiyun 	{0x00000003, "pixel buffer status"},
5768*4882a593Smuzhiyun 	{0x00000004, "balance fifo buffer status"},
5769*4882a593Smuzhiyun 	{0x00000005, "syntax element fifo status"},
5770*4882a593Smuzhiyun };
5771*4882a593Smuzhiyun 
5772*4882a593Smuzhiyun static struct vop2_dsc_data rk3588_dsc_data[] = {
5773*4882a593Smuzhiyun 	{
5774*4882a593Smuzhiyun 		.id = ROCKCHIP_VOP2_DSC_8K,
5775*4882a593Smuzhiyun 		.pd_id = VOP2_PD_DSC_8K,
5776*4882a593Smuzhiyun 		.max_slice_num = 8,
5777*4882a593Smuzhiyun 		.max_linebuf_depth = 11,
5778*4882a593Smuzhiyun 		.min_bits_per_pixel = 8,
5779*4882a593Smuzhiyun 		.dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
5780*4882a593Smuzhiyun 		.dsc_txp_clk_name = "dsc_8k_txp_clk",
5781*4882a593Smuzhiyun 		.dsc_pxl_clk_name = "dsc_8k_pxl_clk",
5782*4882a593Smuzhiyun 		.dsc_cds_clk_name = "dsc_8k_cds_clk",
5783*4882a593Smuzhiyun 	},
5784*4882a593Smuzhiyun 
5785*4882a593Smuzhiyun 	{
5786*4882a593Smuzhiyun 		.id = ROCKCHIP_VOP2_DSC_4K,
5787*4882a593Smuzhiyun 		.pd_id = VOP2_PD_DSC_4K,
5788*4882a593Smuzhiyun 		.max_slice_num = 2,
5789*4882a593Smuzhiyun 		.max_linebuf_depth = 11,
5790*4882a593Smuzhiyun 		.min_bits_per_pixel = 8,
5791*4882a593Smuzhiyun 		.dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
5792*4882a593Smuzhiyun 		.dsc_txp_clk_name = "dsc_4k_txp_clk",
5793*4882a593Smuzhiyun 		.dsc_pxl_clk_name = "dsc_4k_pxl_clk",
5794*4882a593Smuzhiyun 		.dsc_cds_clk_name = "dsc_4k_cds_clk",
5795*4882a593Smuzhiyun 	},
5796*4882a593Smuzhiyun };
5797*4882a593Smuzhiyun 
5798*4882a593Smuzhiyun static struct vop2_vp_data rk3588_vp_data[4] = {
5799*4882a593Smuzhiyun 	{
5800*4882a593Smuzhiyun 		.splice_vp_id = 1,
5801*4882a593Smuzhiyun 		.feature = VOP_FEATURE_OUTPUT_10BIT,
5802*4882a593Smuzhiyun 		.pre_scan_max_dly = 54,
5803*4882a593Smuzhiyun 		.max_dclk = 600000,
5804*4882a593Smuzhiyun 		.max_output = {7680, 4320},
5805*4882a593Smuzhiyun 	},
5806*4882a593Smuzhiyun 	{
5807*4882a593Smuzhiyun 		.feature = VOP_FEATURE_OUTPUT_10BIT,
5808*4882a593Smuzhiyun 		.pre_scan_max_dly = 54,
5809*4882a593Smuzhiyun 		.max_dclk = 600000,
5810*4882a593Smuzhiyun 		.max_output = {4096, 2304},
5811*4882a593Smuzhiyun 	},
5812*4882a593Smuzhiyun 	{
5813*4882a593Smuzhiyun 		.feature = VOP_FEATURE_OUTPUT_10BIT,
5814*4882a593Smuzhiyun 		.pre_scan_max_dly = 52,
5815*4882a593Smuzhiyun 		.max_dclk = 600000,
5816*4882a593Smuzhiyun 		.max_output = {4096, 2304},
5817*4882a593Smuzhiyun 	},
5818*4882a593Smuzhiyun 	{
5819*4882a593Smuzhiyun 		.feature = 0,
5820*4882a593Smuzhiyun 		.pre_scan_max_dly = 52,
5821*4882a593Smuzhiyun 		.max_dclk = 200000,
5822*4882a593Smuzhiyun 		.max_output = {1920, 1080},
5823*4882a593Smuzhiyun 	},
5824*4882a593Smuzhiyun };
5825*4882a593Smuzhiyun 
5826*4882a593Smuzhiyun static struct vop2_power_domain_data rk3588_vop_pd_data[] = {
5827*4882a593Smuzhiyun 	{
5828*4882a593Smuzhiyun 	  .id = VOP2_PD_CLUSTER0,
5829*4882a593Smuzhiyun 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0),
5830*4882a593Smuzhiyun 	},
5831*4882a593Smuzhiyun 	{
5832*4882a593Smuzhiyun 	  .id = VOP2_PD_CLUSTER1,
5833*4882a593Smuzhiyun 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1),
5834*4882a593Smuzhiyun 	  .parent_id = VOP2_PD_CLUSTER0,
5835*4882a593Smuzhiyun 	},
5836*4882a593Smuzhiyun 	{
5837*4882a593Smuzhiyun 	  .id = VOP2_PD_CLUSTER2,
5838*4882a593Smuzhiyun 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2),
5839*4882a593Smuzhiyun 	  .parent_id = VOP2_PD_CLUSTER0,
5840*4882a593Smuzhiyun 	},
5841*4882a593Smuzhiyun 	{
5842*4882a593Smuzhiyun 	  .id = VOP2_PD_CLUSTER3,
5843*4882a593Smuzhiyun 	  .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3),
5844*4882a593Smuzhiyun 	  .parent_id = VOP2_PD_CLUSTER0,
5845*4882a593Smuzhiyun 	},
5846*4882a593Smuzhiyun 	{
5847*4882a593Smuzhiyun 	  .id = VOP2_PD_ESMART,
5848*4882a593Smuzhiyun 	  .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) |
5849*4882a593Smuzhiyun 			    BIT(ROCKCHIP_VOP2_ESMART2) |
5850*4882a593Smuzhiyun 			    BIT(ROCKCHIP_VOP2_ESMART3),
5851*4882a593Smuzhiyun 	},
5852*4882a593Smuzhiyun 	{
5853*4882a593Smuzhiyun 	  .id = VOP2_PD_DSC_8K,
5854*4882a593Smuzhiyun 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K),
5855*4882a593Smuzhiyun 	},
5856*4882a593Smuzhiyun 	{
5857*4882a593Smuzhiyun 	  .id = VOP2_PD_DSC_4K,
5858*4882a593Smuzhiyun 	  .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K),
5859*4882a593Smuzhiyun 	},
5860*4882a593Smuzhiyun };
5861*4882a593Smuzhiyun 
5862*4882a593Smuzhiyun const struct vop2_data rk3588_vop = {
5863*4882a593Smuzhiyun 	.version = VOP_VERSION_RK3588,
5864*4882a593Smuzhiyun 	.nr_vps = 4,
5865*4882a593Smuzhiyun 	.vp_data = rk3588_vp_data,
5866*4882a593Smuzhiyun 	.win_data = rk3588_win_data,
5867*4882a593Smuzhiyun 	.plane_mask = rk3588_vp_plane_mask[0],
5868*4882a593Smuzhiyun 	.plane_table = rk3588_plane_table,
5869*4882a593Smuzhiyun 	.pd = rk3588_vop_pd_data,
5870*4882a593Smuzhiyun 	.dsc = rk3588_dsc_data,
5871*4882a593Smuzhiyun 	.dsc_error_ecw = dsc_ecw,
5872*4882a593Smuzhiyun 	.dsc_error_buffer_flow = dsc_buffer_flow,
5873*4882a593Smuzhiyun 	.vp_primary_plane_order = rk3588_vp_primary_plane_order,
5874*4882a593Smuzhiyun 	.nr_layers = 8,
5875*4882a593Smuzhiyun 	.nr_mixers = 7,
5876*4882a593Smuzhiyun 	.nr_gammas = 4,
5877*4882a593Smuzhiyun 	.nr_pd = ARRAY_SIZE(rk3588_vop_pd_data),
5878*4882a593Smuzhiyun 	.nr_dscs = 2,
5879*4882a593Smuzhiyun 	.nr_dsc_ecw = ARRAY_SIZE(dsc_ecw),
5880*4882a593Smuzhiyun 	.nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow),
5881*4882a593Smuzhiyun 	.dump_regs = rk3588_dump_regs,
5882*4882a593Smuzhiyun 	.dump_regs_size = ARRAY_SIZE(rk3588_dump_regs),
5883*4882a593Smuzhiyun };
5884*4882a593Smuzhiyun 
5885*4882a593Smuzhiyun const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
5886*4882a593Smuzhiyun 	.preinit = rockchip_vop2_preinit,
5887*4882a593Smuzhiyun 	.prepare = rockchip_vop2_prepare,
5888*4882a593Smuzhiyun 	.init = rockchip_vop2_init,
5889*4882a593Smuzhiyun 	.set_plane = rockchip_vop2_set_plane,
5890*4882a593Smuzhiyun 	.enable = rockchip_vop2_enable,
5891*4882a593Smuzhiyun 	.disable = rockchip_vop2_disable,
5892*4882a593Smuzhiyun 	.fixup_dts = rockchip_vop2_fixup_dts,
5893*4882a593Smuzhiyun 	.send_mcu_cmd = rockchip_vop2_send_mcu_cmd,
5894*4882a593Smuzhiyun 	.check = rockchip_vop2_check,
5895*4882a593Smuzhiyun 	.mode_valid = rockchip_vop2_mode_valid,
5896*4882a593Smuzhiyun 	.mode_fixup = rockchip_vop2_mode_fixup,
5897*4882a593Smuzhiyun 	.plane_check = rockchip_vop2_plane_check,
5898*4882a593Smuzhiyun 	.regs_dump = rockchip_vop2_regs_dump,
5899*4882a593Smuzhiyun 	.active_regs_dump = rockchip_vop2_active_regs_dump,
5900*4882a593Smuzhiyun 	.apply_soft_te = rockchip_vop2_apply_soft_te,
5901*4882a593Smuzhiyun };
5902