xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_vop2.c (revision a0ea2d9244dc04b69a1aa5986dc133b45f4f2fc2)
1d0408543SAndy Yan // SPDX-License-Identifier: GPL-2.0-only
2d0408543SAndy Yan /*
3d0408543SAndy Yan  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
4d0408543SAndy Yan  *
5d0408543SAndy Yan  */
6d0408543SAndy Yan 
7d0408543SAndy Yan #include <config.h>
8d0408543SAndy Yan #include <common.h>
9d0408543SAndy Yan #include <errno.h>
10d0408543SAndy Yan #include <malloc.h>
11d0408543SAndy Yan #include <fdtdec.h>
12d0408543SAndy Yan #include <fdt_support.h>
13feffd38eSSandy Huang #include <asm/arch/cpu.h>
14d0408543SAndy Yan #include <asm/unaligned.h>
15d0408543SAndy Yan #include <asm/io.h>
16d0408543SAndy Yan #include <linux/list.h>
17d0408543SAndy Yan #include <linux/media-bus-format.h>
18d0408543SAndy Yan #include <clk.h>
19d0408543SAndy Yan #include <asm/arch/clock.h>
20d0408543SAndy Yan #include <linux/err.h>
211147facaSSandy Huang #include <linux/ioport.h>
22d0408543SAndy Yan #include <dm/device.h>
23d0408543SAndy Yan #include <dm/read.h>
24ac500a1fSSandy Huang #include <fixp-arith.h>
25d0408543SAndy Yan #include <syscon.h>
26d0408543SAndy Yan 
27d0408543SAndy Yan #include "rockchip_display.h"
28d0408543SAndy Yan #include "rockchip_crtc.h"
29d0408543SAndy Yan #include "rockchip_connector.h"
30d0408543SAndy Yan 
31d0408543SAndy Yan /* System registers definition */
32d0408543SAndy Yan #define RK3568_REG_CFG_DONE			0x000
33d0408543SAndy Yan #define	CFG_DONE_EN				BIT(15)
34d0408543SAndy Yan 
35d0408543SAndy Yan #define RK3568_VERSION_INFO			0x004
36d0408543SAndy Yan #define EN_MASK					1
37d0408543SAndy Yan 
3863cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL			0x008
3963cb669fSSandy Huang 
406414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL			0x024
416414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT			0
426414e3bcSSandy Huang 
43d0408543SAndy Yan #define RK3568_DSP_IF_EN			0x028
44d0408543SAndy Yan #define RGB_EN_SHIFT				0
45d0408543SAndy Yan #define HDMI0_EN_SHIFT				1
46d0408543SAndy Yan #define EDP0_EN_SHIFT				3
47d0408543SAndy Yan #define MIPI0_EN_SHIFT				4
48d0408543SAndy Yan #define MIPI1_EN_SHIFT				20
49d0408543SAndy Yan #define LVDS0_EN_SHIFT				5
50d0408543SAndy Yan #define LVDS1_EN_SHIFT				24
51d0408543SAndy Yan #define BT1120_EN_SHIFT				6
52d0408543SAndy Yan #define BT656_EN_SHIFT				7
53d0408543SAndy Yan #define IF_MUX_MASK				3
54d0408543SAndy Yan #define RGB_MUX_SHIFT				8
55d0408543SAndy Yan #define HDMI0_MUX_SHIFT				10
56d0408543SAndy Yan #define EDP0_MUX_SHIFT				14
57d0408543SAndy Yan #define MIPI0_MUX_SHIFT				16
58d0408543SAndy Yan #define MIPI1_MUX_SHIFT				21
5911f53190SSandy Huang #define LVDS0_MUX_SHIFT				18
60d0408543SAndy Yan #define LVDS1_MUX_SHIFT				25
61d0408543SAndy Yan 
62d0408543SAndy Yan #define RK3568_DSP_IF_CTRL			0x02c
63d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT			0
64d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT		1
65d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT			2
66d0408543SAndy Yan #define RK3568_DSP_IF_POL			0x030
67d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_MASK		1
68d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT		28
69d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT		19
70d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT		15
71d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT		7
7210ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK		0x7
7310ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT		4
74d0408543SAndy Yan #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT		3
75feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN			0x50
76feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT			0
771147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL			0x58
781147facaSSandy Huang #define GAMMA_PORT_SEL_MASK			0x3
791147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT			0
801147facaSSandy Huang 
81d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG			0x70
82d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG			0x74
83d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG			0x78
84d0408543SAndy Yan #define RK3568_SYS0_INT_EN			0x80
85d0408543SAndy Yan #define RK3568_SYS0_INT_CLR			0x84
86d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS			0x88
87d0408543SAndy Yan #define RK3568_SYS1_INT_EN			0x90
88d0408543SAndy Yan #define RK3568_SYS1_INT_CLR			0x94
89d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS			0x98
90d0408543SAndy Yan #define RK3568_VP0_INT_EN			0xA0
91d0408543SAndy Yan #define RK3568_VP0_INT_CLR			0xA4
92d0408543SAndy Yan #define RK3568_VP0_INT_STATUS			0xA8
93d0408543SAndy Yan #define RK3568_VP1_INT_EN			0xB0
94d0408543SAndy Yan #define RK3568_VP1_INT_CLR			0xB4
95d0408543SAndy Yan #define RK3568_VP1_INT_STATUS			0xB8
96d0408543SAndy Yan #define RK3568_VP2_INT_EN			0xC0
97d0408543SAndy Yan #define RK3568_VP2_INT_CLR			0xC4
98d0408543SAndy Yan #define RK3568_VP2_INT_STATUS			0xC8
99d0408543SAndy Yan 
10063cb669fSSandy Huang /* Overlay registers definition    */
10163cb669fSSandy Huang #define RK3568_OVL_CTRL				0x600
10263cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
10363cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL			0x604
10463cb669fSSandy Huang #define LAYER_SEL_MASK				0xf
10563cb669fSSandy Huang 
10663cb669fSSandy Huang #define RK3568_OVL_PORT_SEL			0x608
10763cb669fSSandy Huang #define PORT_MUX_MASK				0xf
10863cb669fSSandy Huang #define PORT_MUX_SHIFT				0
10963cb669fSSandy Huang #define LAYER_SEL_PORT_MASK			0x3
11063cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT			16
11163cb669fSSandy Huang 
11263cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
11363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
11463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
11563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
11663cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
11763cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL		0x654
11863cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
11963cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
12063cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
12163cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
12263cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
12363cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
12463cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL			0x6E0
12563cb669fSSandy Huang #define BG_MIX_CTRL_MASK			0xff
12663cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT			24
12763cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL			0x6E4
12863cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL			0x6E8
12963cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM			0x6F0
13063cb669fSSandy Huang #define RK3568_SMART_DLY_NUM			0x6F8
13163cb669fSSandy Huang 
132d0408543SAndy Yan /* Video Port registers definition */
133d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL			0xC00
134d0408543SAndy Yan #define OUT_MODE_MASK				0xf
135d0408543SAndy Yan #define OUT_MODE_SHIFT				0
13610ee9f5bSAlgea Cao #define DATA_SWAP_MASK				0x1f
13710ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT				8
13810ee9f5bSAlgea Cao #define DSP_RB_SWAP				2
13910ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT			4
140d0408543SAndy Yan #define P2I_EN_SHIFT				5
1417a20be36SSandy Huang #define DSP_FILED_POL				6
142d0408543SAndy Yan #define INTERLACE_EN_SHIFT			7
14310ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT			15
144d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT		16
145d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT			17
1461147facaSSandy Huang #define DSP_LUT_EN_SHIFT			28
1471147facaSSandy Huang 
148d0408543SAndy Yan #define STANDBY_EN_SHIFT			31
149d0408543SAndy Yan 
150d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL			0xC04
15110ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT				4
15210ee9f5bSAlgea Cao #define DCLK_DIV2_MASK				0x3
153d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT			20
154d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT			21
155d0408543SAndy Yan 
156d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL		0xC08
1576414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL			0xC10
1586414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT				0
1596414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT			2
1606414e3bcSSandy Huang 
1616414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST			0xC20
1626414e3bcSSandy Huang 
163d0408543SAndy Yan #define RK3568_VP0_DSP_BG			0xC2C
164d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
165d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
166d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
167d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
168d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL		0xC40
169d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
170d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
171d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END		0xC4C
172d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
173d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END		0xC54
174d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
175d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
176d0408543SAndy Yan 
177ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL			0xC60
178ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT			0
179ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK			0x1
180ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT		2
181ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK		0x3
182ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT			4
183ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK			0x1
184ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT		6
185ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK		0x3
186ac500a1fSSandy Huang 
187ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS			0xC64
188ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT			0
189ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK			0xFF
190ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT			8
191ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK			0x1FF
192ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT			20
193ac500a1fSSandy Huang #define BCSH_SATURATION_MASK			0x3FF
194ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT			30
195ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK			0x3
196ac500a1fSSandy Huang 
197ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H			0xC68
198ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT			0
199ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK			0x1FF
200ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT			16
201ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK			0x1FF
202ac500a1fSSandy Huang 
203ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR			0xC6C
204ac500a1fSSandy Huang #define BCSH_EN_SHIFT				31
205ac500a1fSSandy Huang #define BCSH_EN_MASK				1
206ac500a1fSSandy Huang 
207d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL			0xD00
208d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL			0xD04
209d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL		0xD08
210d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
211d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
212d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
213d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
214d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL		0xD40
215d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO		0xD34
216d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO		0xD38
217d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
218d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
219d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END		0xD4C
220d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
221d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END		0xD54
222d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
223d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
224d0408543SAndy Yan 
225d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL			0xE00
226d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL			0xE04
227d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL		0xE08
228d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
229d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
230d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
231d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
232d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL		0xE40
233d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO		0xE34
234d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO		0xE38
235d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
236d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
237d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END		0xE4C
238d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
239d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END		0xE54
240d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
241d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
242d0408543SAndy Yan 
243d0408543SAndy Yan /* Cluster0 register definition */
244d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
245d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
246d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
247d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
248d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR		0x1018
249d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
250d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
251d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
252d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
253d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
254d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
255d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
256d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
257d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
258d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
259d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
260d0408543SAndy Yan 
261d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
262d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
263d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
264d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
265d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR		0x1098
266d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
267d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
268d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
269d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
270d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
271d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
272d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
273d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
274d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
275d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
276d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
277d0408543SAndy Yan 
278d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL			0x1100
279d0408543SAndy Yan 
280d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
281d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
282d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
283d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
284d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR		0x1218
285d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
286d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
287d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
288d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
289d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
290d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
291d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
292d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
293d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
294d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
295d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
296d0408543SAndy Yan 
297d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
298d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
299d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
300d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
301d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR		0x1298
302d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
303d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
304d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
305d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
306d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
307d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
308d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
309d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
310d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
311d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
312d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
313d0408543SAndy Yan 
314d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL			0x1300
315d0408543SAndy Yan 
316d0408543SAndy Yan /* Esmart register definition */
317d0408543SAndy Yan #define RK3568_ESMART0_CTRL0			0x1800
31810ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT			1
31910ee9f5bSAlgea Cao #define CSC_MODE_SHIFT				2
32010ee9f5bSAlgea Cao #define CSC_MODE_MASK				0x3
321d0408543SAndy Yan 
322d0408543SAndy Yan #define RK3568_ESMART0_CTRL1			0x1804
323d0408543SAndy Yan #define YMIRROR_EN_SHIFT			31
324d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL		0x1810
32510ee9f5bSAlgea Cao #define REGION0_RB_SWAP_SHIFT			14
326d0408543SAndy Yan #define WIN_EN_SHIFT				0
327d0408543SAndy Yan #define WIN_FORMAT_MASK				0x1f
328d0408543SAndy Yan #define WIN_FORMAT_SHIFT			1
329d0408543SAndy Yan 
330d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
331d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
332d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR		0x181C
333d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
334d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
335d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
336d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
3373e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK			0x3
3383e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT			0
3393e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK		0x3
3403e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT		2
3413e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK			0x3
3423e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT			4
3433e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK		0x3
3443e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT		6
3453e39a5a1SSandy Huang 
346d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
347d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
348d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
349d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL		0x1840
3503e39a5a1SSandy Huang #define YRGB_GT2_MASK				0x1
3513e39a5a1SSandy Huang #define YRGB_GT2_SHIFT				8
3523e39a5a1SSandy Huang #define YRGB_GT4_MASK				0x1
3533e39a5a1SSandy Huang #define YRGB_GT4_SHIFT				9
3543e39a5a1SSandy Huang 
355d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
356d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
357d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR		0x184C
358d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
359d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
360d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
361d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
362d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
363d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
364d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
365d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL		0x1870
366d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
367d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
368d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR		0x187C
369d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
370d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
371d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
372d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
373d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
374d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
375d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
376d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL		0x18A0
377d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
378d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
379d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR		0x18AC
380d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
381d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
382d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
383d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
384d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
385d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
386d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
387d0408543SAndy Yan 
388d0408543SAndy Yan #define RK3568_ESMART1_CTRL0			0x1A00
389d0408543SAndy Yan #define RK3568_ESMART1_CTRL1			0x1A04
390d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL		0x1A10
391d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
392d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
393d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR		0x1A1C
394d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
395d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
396d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
397d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
398d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
399d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
400d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
401d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL		0x1A40
402d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
403d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
404d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR		0x1A4C
405d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
406d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
407d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
408d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
409d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
410d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
411d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
412d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL		0x1A70
413d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
414d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
415d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR		0x1A7C
416d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
417d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
418d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
419d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
420d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
421d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
422d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
423d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
424d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
425d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
426d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR		0x1AAC
427d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
428d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
429d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
430d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
431d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
432d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
433d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
434d0408543SAndy Yan 
435d0408543SAndy Yan #define RK3568_SMART0_CTRL0			0x1C00
436d0408543SAndy Yan #define RK3568_SMART0_CTRL1			0x1C04
437d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL		0x1C10
438d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
439d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
440d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR		0x1C1C
441d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
442d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
443d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
444d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
445d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
446d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
447d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
448d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL		0x1C40
449d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
450d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
451d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR		0x1C4C
452d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
453d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
454d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
455d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
456d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
457d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
458d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
459d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL		0x1C70
460d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
461d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
462d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR		0x1C7C
463d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
464d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
465d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
466d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
467d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
468d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
469d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
470d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL		0x1CA0
471d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
472d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
473d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR		0x1CAC
474d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
475d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
476d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
477d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
478d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
479d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
480d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
481d0408543SAndy Yan 
482d0408543SAndy Yan #define RK3568_SMART1_CTRL0			0x1E00
483d0408543SAndy Yan #define RK3568_SMART1_CTRL1			0x1E04
484d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL		0x1E10
485d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
486d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
487d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR		0x1E1C
488d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
489d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
490d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
491d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
492d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
493d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
494d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
495d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL		0x1E40
496d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
497d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
498d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR		0x1E4C
499d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
500d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
501d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
502d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
503d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
504d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
505d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
506d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL		0x1E70
507d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
508d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
509d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR		0x1E7C
510d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
511d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
512d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
513d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
514d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
515d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
516d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
517d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL		0x1EA0
518d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
519d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
520d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR		0x1EAC
521d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
522d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
523d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
524d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
525d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
526d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
527d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
528d0408543SAndy Yan 
529d0408543SAndy Yan #define RK3568_MAX_REG				0x1ED0
530d0408543SAndy Yan 
53152ee18acSSandy Huang #define RK3568_GRF_VO_CON1			0x0364
53252ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT			1
53352ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT		2
53452ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT			3
53552ee18acSSandy Huang 
536d0408543SAndy Yan #define VOP2_LAYER_MAX				8
53763cb669fSSandy Huang 
53863cb669fSSandy Huang #define VOP_FEATURE_OUTPUT_10BIT		BIT(0)
539d0408543SAndy Yan 
54010ee9f5bSAlgea Cao enum vop2_csc_format {
54110ee9f5bSAlgea Cao 	CSC_BT601L,
54210ee9f5bSAlgea Cao 	CSC_BT709L,
54310ee9f5bSAlgea Cao 	CSC_BT601F,
54410ee9f5bSAlgea Cao 	CSC_BT2020,
54510ee9f5bSAlgea Cao };
54610ee9f5bSAlgea Cao 
54710ee9f5bSAlgea Cao enum vop2_pol {
54810ee9f5bSAlgea Cao 	HSYNC_POSITIVE = 0,
54910ee9f5bSAlgea Cao 	VSYNC_POSITIVE = 1,
55010ee9f5bSAlgea Cao 	DEN_NEGATIVE   = 2,
55110ee9f5bSAlgea Cao 	DCLK_INVERT    = 3
55210ee9f5bSAlgea Cao };
55310ee9f5bSAlgea Cao 
554ac500a1fSSandy Huang enum vop2_bcsh_out_mode {
555ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLACK,
556ac500a1fSSandy Huang 	BCSH_OUT_MODE_BLUE,
557ac500a1fSSandy Huang 	BCSH_OUT_MODE_COLOR_BAR,
558ac500a1fSSandy Huang 	BCSH_OUT_MODE_NORMAL_VIDEO,
559ac500a1fSSandy Huang };
560ac500a1fSSandy Huang 
561d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \
562d0408543SAndy Yan 		{ \
563d0408543SAndy Yan 		 .offset = off, \
564d0408543SAndy Yan 		 .mask = _mask, \
565d0408543SAndy Yan 		 .shift = _shift, \
566d0408543SAndy Yan 		 .write_mask = _write_mask, \
567d0408543SAndy Yan 		}
568d0408543SAndy Yan 
569d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \
570d0408543SAndy Yan 		_VOP_REG(off, _mask, _shift, false)
571d0408543SAndy Yan enum dither_down_mode {
572d0408543SAndy Yan 	RGB888_TO_RGB565 = 0x0,
573d0408543SAndy Yan 	RGB888_TO_RGB666 = 0x1
574d0408543SAndy Yan };
575d0408543SAndy Yan 
576d0408543SAndy Yan enum vop2_video_ports_id {
577d0408543SAndy Yan 	VOP2_VP0,
578d0408543SAndy Yan 	VOP2_VP1,
579d0408543SAndy Yan 	VOP2_VP2,
580d0408543SAndy Yan 	VOP2_VP3,
581d0408543SAndy Yan 	VOP2_VP_MAX,
582d0408543SAndy Yan };
583d0408543SAndy Yan 
584ee008497SSandy Huang enum vop2_layer_type {
585ee008497SSandy Huang 	CLUSTER_LAYER = 0,
586ee008497SSandy Huang 	ESMART_LAYER = 1,
587ee008497SSandy Huang 	SMART_LAYER = 2,
588ee008497SSandy Huang };
589ee008497SSandy Huang 
590b0989546SSandy Huang /* This define must same with kernel win phy id */
591b0989546SSandy Huang enum vop2_layer_phy_id {
592b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER0 = 0,
593b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER1,
594b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART0,
595b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART1,
596b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART0,
597b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART1,
598b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER2,
599b0989546SSandy Huang 	ROCKCHIP_VOP2_CLUSTER3,
600b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART2,
601b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART3,
602ee008497SSandy Huang 	ROCKCHIP_VOP2_LAYER_MAX,
603d0408543SAndy Yan };
604d0408543SAndy Yan 
6053e39a5a1SSandy Huang enum vop2_scale_up_mode {
6063e39a5a1SSandy Huang 	VOP2_SCALE_UP_NRST_NBOR,
6073e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIL,
6083e39a5a1SSandy Huang 	VOP2_SCALE_UP_BIC,
6093e39a5a1SSandy Huang };
6103e39a5a1SSandy Huang 
6113e39a5a1SSandy Huang enum vop2_scale_down_mode {
6123e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_NRST_NBOR,
6133e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_BIL,
6143e39a5a1SSandy Huang 	VOP2_SCALE_DOWN_AVG,
6153e39a5a1SSandy Huang };
6163e39a5a1SSandy Huang 
6173e39a5a1SSandy Huang enum scale_mode {
6183e39a5a1SSandy Huang 	SCALE_NONE = 0x0,
6193e39a5a1SSandy Huang 	SCALE_UP   = 0x1,
6203e39a5a1SSandy Huang 	SCALE_DOWN = 0x2
6213e39a5a1SSandy Huang };
6223e39a5a1SSandy Huang 
6233e39a5a1SSandy Huang struct vop2_layer {
6243e39a5a1SSandy Huang 	u8 id;
6253e39a5a1SSandy Huang 	/**
6263e39a5a1SSandy Huang 	 * @win_phys_id: window id of the layer selected.
6273e39a5a1SSandy Huang 	 * Every layer must make sure to select different
6283e39a5a1SSandy Huang 	 * windows of others.
6293e39a5a1SSandy Huang 	 */
6303e39a5a1SSandy Huang 	u8 win_phys_id;
6313e39a5a1SSandy Huang };
6323e39a5a1SSandy Huang 
633b0989546SSandy Huang struct vop2_win_data {
634b0989546SSandy Huang 	char *name;
63563cb669fSSandy Huang 	u8 phys_id;
636b0989546SSandy Huang 	u8 win_sel_port_offset;
637b0989546SSandy Huang 	u8 layer_sel_win_id;
638b0989546SSandy Huang 	u32 reg_offset;
63963cb669fSSandy Huang };
64063cb669fSSandy Huang 
64163cb669fSSandy Huang struct vop2_vp_data {
64263cb669fSSandy Huang 	u32 feature;
64363cb669fSSandy Huang 	u8 pre_scan_max_dly;
64463cb669fSSandy Huang 	struct vop_rect max_output;
645d0408543SAndy Yan };
646d0408543SAndy Yan 
647ee008497SSandy Huang struct vop2_plane_table {
648ee008497SSandy Huang 	enum vop2_layer_phy_id plane_id;
649ee008497SSandy Huang 	enum vop2_layer_type plane_type;
650ee008497SSandy Huang };
651ee008497SSandy Huang 
652b0989546SSandy Huang struct vop2_vp_plane_mask {
653b0989546SSandy Huang 	u8 primary_plane_id; /* use this win to show logo */
654b0989546SSandy Huang 	u8 attached_layers_nr; /* number layers attach to this vp */
655b0989546SSandy Huang 	u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
656b0989546SSandy Huang 	u32 plane_mask;
657ee008497SSandy Huang 	int cursor_plane_id;
658b0989546SSandy Huang };
659b0989546SSandy Huang 
660d0408543SAndy Yan struct vop2_data {
66152ee18acSSandy Huang 	u32 version;
66263cb669fSSandy Huang 	struct vop2_vp_data *vp_data;
663b0989546SSandy Huang 	struct vop2_win_data *win_data;
664b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
665ee008497SSandy Huang 	struct vop2_plane_table *plane_table;
66663cb669fSSandy Huang 	u8 nr_vps;
66763cb669fSSandy Huang 	u8 nr_layers;
66863cb669fSSandy Huang 	u8 nr_mixers;
6691147facaSSandy Huang 	u8 nr_gammas;
670d0408543SAndy Yan };
671d0408543SAndy Yan 
672d0408543SAndy Yan struct vop2 {
673d0408543SAndy Yan 	u32 *regsbak;
674d0408543SAndy Yan 	void *regs;
675d0408543SAndy Yan 	void *grf;
67652ee18acSSandy Huang 	u32 reg_len;
67752ee18acSSandy Huang 	u32 version;
67863cb669fSSandy Huang 	bool global_init;
679d0408543SAndy Yan 	const struct vop2_data *data;
680b0989546SSandy Huang 	struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
681d0408543SAndy Yan };
682d0408543SAndy Yan 
683d0408543SAndy Yan static struct vop2 *rockchip_vop2;
6843e39a5a1SSandy Huang /*
6853e39a5a1SSandy Huang  * bli_sd_factor = (src - 1) / (dst - 1) << 12;
6863e39a5a1SSandy Huang  * avg_sd_factor:
6873e39a5a1SSandy Huang  * bli_su_factor:
6883e39a5a1SSandy Huang  * bic_su_factor:
6893e39a5a1SSandy Huang  * = (src - 1) / (dst - 1) << 16;
6903e39a5a1SSandy Huang  *
6913e39a5a1SSandy Huang  * gt2 enable: dst get one line from two line of the src
6923e39a5a1SSandy Huang  * gt4 enable: dst get one line from four line of the src.
6933e39a5a1SSandy Huang  *
6943e39a5a1SSandy Huang  */
6953e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst)	(((src - 1) << 12) / (dst - 1))
6963e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst)	(((src - 1) << 16) / (dst - 1))
6973e39a5a1SSandy Huang 
6983e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)	 \
6993e39a5a1SSandy Huang 				(fac * (dst - 1) >> 12 < (src - 1))
7003e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
7013e39a5a1SSandy Huang 				(fac * (dst - 1) >> 16 < (src - 1))
7023e39a5a1SSandy Huang 
7033e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode,
7043e39a5a1SSandy Huang 				  int32_t filter_mode,
7053e39a5a1SSandy Huang 				  uint32_t src, uint32_t dst)
7063e39a5a1SSandy Huang {
7073e39a5a1SSandy Huang 	uint32_t fac = 0;
7083e39a5a1SSandy Huang 	int i = 0;
7093e39a5a1SSandy Huang 
7103e39a5a1SSandy Huang 	if (mode == SCALE_NONE)
7113e39a5a1SSandy Huang 		return 0;
7123e39a5a1SSandy Huang 
7133e39a5a1SSandy Huang 	/*
7143e39a5a1SSandy Huang 	 * A workaround to avoid zero div.
7153e39a5a1SSandy Huang 	 */
7163e39a5a1SSandy Huang 	if ((dst == 1) || (src == 1)) {
7173e39a5a1SSandy Huang 		dst = dst + 1;
7183e39a5a1SSandy Huang 		src = src + 1;
7193e39a5a1SSandy Huang 	}
7203e39a5a1SSandy Huang 
7213e39a5a1SSandy Huang 	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
7223e39a5a1SSandy Huang 		fac = VOP2_BILI_SCL_DN(src, dst);
7233e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
7243e39a5a1SSandy Huang 			if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
7253e39a5a1SSandy Huang 				break;
7263e39a5a1SSandy Huang 			fac -= 1;
7273e39a5a1SSandy Huang 			printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
7283e39a5a1SSandy Huang 		}
7293e39a5a1SSandy Huang 	} else {
7303e39a5a1SSandy Huang 		fac = VOP2_COMMON_SCL(src, dst);
7313e39a5a1SSandy Huang 		for (i = 0; i < 100; i++) {
7323e39a5a1SSandy Huang 			if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
7333e39a5a1SSandy Huang 				break;
7343e39a5a1SSandy Huang 			fac -= 1;
7353e39a5a1SSandy Huang 			printf("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
7363e39a5a1SSandy Huang 		}
7373e39a5a1SSandy Huang 	}
7383e39a5a1SSandy Huang 
7393e39a5a1SSandy Huang 	return fac;
7403e39a5a1SSandy Huang }
7413e39a5a1SSandy Huang 
7423e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst)
7433e39a5a1SSandy Huang {
7443e39a5a1SSandy Huang 	if (src < dst)
7453e39a5a1SSandy Huang 		return SCALE_UP;
7463e39a5a1SSandy Huang 	else if (src > dst)
7473e39a5a1SSandy Huang 		return SCALE_DOWN;
7483e39a5a1SSandy Huang 
7493e39a5a1SSandy Huang 	return SCALE_NONE;
7503e39a5a1SSandy Huang }
751d0408543SAndy Yan 
752b0989546SSandy Huang static u8 vop2_vp_primary_plane_order[VOP2_VP_MAX] = {
753b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART0,
754b0989546SSandy Huang 	ROCKCHIP_VOP2_SMART1,
755b0989546SSandy Huang 	ROCKCHIP_VOP2_ESMART1,
756b0989546SSandy Huang };
757b0989546SSandy Huang 
758ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x)
759ac500a1fSSandy Huang {
760ac500a1fSSandy Huang 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
761ac500a1fSSandy Huang }
762ac500a1fSSandy Huang 
763b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask)
764b0989546SSandy Huang {
765b0989546SSandy Huang 	int i = 0;
766b0989546SSandy Huang 
767b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
768b0989546SSandy Huang 		if (plane_mask & BIT(vop2_vp_primary_plane_order[i]))
769b0989546SSandy Huang 			return vop2_vp_primary_plane_order[i];
770b0989546SSandy Huang 	}
771b0989546SSandy Huang 
772b0989546SSandy Huang 	return ROCKCHIP_VOP2_SMART0;
773b0989546SSandy Huang }
774b0989546SSandy Huang 
77563cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift)
776d0408543SAndy Yan {
777d0408543SAndy Yan 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
778d0408543SAndy Yan }
779d0408543SAndy Yan 
78063cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst)
781d0408543SAndy Yan {
782d0408543SAndy Yan 	return ((src - 1) << 12) / (dst - 1);
783d0408543SAndy Yan }
784d0408543SAndy Yan 
78552ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
786d0408543SAndy Yan {
787d0408543SAndy Yan 	writel(v, vop2->regs + offset);
788d0408543SAndy Yan 	vop2->regsbak[offset >> 2] = v;
789d0408543SAndy Yan }
790d0408543SAndy Yan 
79152ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
792d0408543SAndy Yan {
793d0408543SAndy Yan 	return readl(vop2->regs + offset);
794d0408543SAndy Yan }
795d0408543SAndy Yan 
79652ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
79752ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v,
798d0408543SAndy Yan 				   bool write_mask)
799d0408543SAndy Yan {
800d0408543SAndy Yan 	if (!mask)
801d0408543SAndy Yan 		return;
802d0408543SAndy Yan 
803d0408543SAndy Yan 	if (write_mask) {
804d0408543SAndy Yan 		v = ((v & mask) << shift) | (mask << (shift + 16));
805d0408543SAndy Yan 	} else {
80652ee18acSSandy Huang 		u32 cached_val = vop2->regsbak[offset >> 2];
807d0408543SAndy Yan 
808d0408543SAndy Yan 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
809d0408543SAndy Yan 		vop2->regsbak[offset >> 2] = v;
810d0408543SAndy Yan 	}
811d0408543SAndy Yan 
812d0408543SAndy Yan 	writel(v, vop2->regs + offset);
813d0408543SAndy Yan }
814d0408543SAndy Yan 
81552ee18acSSandy Huang static inline void vop2_grf_writel(struct vop2 *vop, u32 offset,
81652ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v)
81752ee18acSSandy Huang {
81852ee18acSSandy Huang 	u32 val = 0;
81952ee18acSSandy Huang 
82052ee18acSSandy Huang 	val = (v << shift) | (mask << (shift + 16));
82152ee18acSSandy Huang 	writel(val, vop->grf + offset);
82252ee18acSSandy Huang }
82352ee18acSSandy Huang 
824d0408543SAndy Yan static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
825d0408543SAndy Yan {
826d0408543SAndy Yan 	return us * mode->clock / mode->htotal / 1000;
827d0408543SAndy Yan }
828d0408543SAndy Yan 
8298895aec1SSandy Huang static char* get_output_if_name(u32 output_if, char *name)
8308895aec1SSandy Huang {
8318895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_RGB)
8328895aec1SSandy Huang 		strcat(name, " RGB");
8338895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_BT1120)
8348895aec1SSandy Huang 		strcat(name, " BT1120");
8358895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_BT656)
8368895aec1SSandy Huang 		strcat(name, " BT656");
8378895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_LVDS0)
8388895aec1SSandy Huang 		strcat(name, " LVDS0");
8398895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_LVDS1)
8408895aec1SSandy Huang 		strcat(name, " LVDS1");
8418895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_MIPI0)
8428895aec1SSandy Huang 		strcat(name, " MIPI0");
8438895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_MIPI1)
8448895aec1SSandy Huang 		strcat(name, " MIPI1");
8458895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_eDP0)
8468895aec1SSandy Huang 		strcat(name, " eDP0");
8478895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_eDP1)
8488895aec1SSandy Huang 		strcat(name, " eDP1");
8498895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_DP0)
8508895aec1SSandy Huang 		strcat(name, " DP0");
8518895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_DP1)
8528895aec1SSandy Huang 		strcat(name, " DP1");
8538895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_HDMI0)
8548895aec1SSandy Huang 		strcat(name, " HDMI0");
8558895aec1SSandy Huang 	if (output_if & VOP_OUTPUT_IF_HDMI1)
8568895aec1SSandy Huang 		strcat(name, " HDMI1");
8578895aec1SSandy Huang 
8588895aec1SSandy Huang 	return name;
8598895aec1SSandy Huang }
8608895aec1SSandy Huang 
8618895aec1SSandy Huang static char *get_plane_name(int plane_id, char *name)
8628895aec1SSandy Huang {
8638895aec1SSandy Huang 	switch (plane_id) {
8648895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER0:
8658895aec1SSandy Huang 		strcat(name, "Cluster0");
8668895aec1SSandy Huang 		break;
8678895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER1:
8688895aec1SSandy Huang 		strcat(name, "Cluster1");
8698895aec1SSandy Huang 		break;
8708895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART0:
8718895aec1SSandy Huang 		strcat(name, "Esmart0");
8728895aec1SSandy Huang 		break;
8738895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART1:
8748895aec1SSandy Huang 		strcat(name, "Esmart1");
8758895aec1SSandy Huang 		break;
8768895aec1SSandy Huang 	case ROCKCHIP_VOP2_SMART0:
8778895aec1SSandy Huang 		strcat(name, "Smart0");
8788895aec1SSandy Huang 		break;
8798895aec1SSandy Huang 	case ROCKCHIP_VOP2_SMART1:
8808895aec1SSandy Huang 		strcat(name, "Smart1");
8818895aec1SSandy Huang 		break;
8828895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER2:
8838895aec1SSandy Huang 		strcat(name, "Cluster2");
8848895aec1SSandy Huang 		break;
8858895aec1SSandy Huang 	case ROCKCHIP_VOP2_CLUSTER3:
8868895aec1SSandy Huang 		strcat(name, "Cluster3");
8878895aec1SSandy Huang 		break;
8888895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART2:
8898895aec1SSandy Huang 		strcat(name, "Esmart2");
8908895aec1SSandy Huang 		break;
8918895aec1SSandy Huang 	case ROCKCHIP_VOP2_ESMART3:
8928895aec1SSandy Huang 		strcat(name, "Esmart3");
8938895aec1SSandy Huang 		break;
8948895aec1SSandy Huang 	}
8958895aec1SSandy Huang 
8968895aec1SSandy Huang 	return name;
8978895aec1SSandy Huang }
8988895aec1SSandy Huang 
89952ee18acSSandy Huang static bool is_yuv_output(u32 bus_format)
900d0408543SAndy Yan {
901d0408543SAndy Yan 	switch (bus_format) {
902d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
903d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
904d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
905d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
906*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_2X8:
907*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_2X8:
908*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_2X8:
909*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_2X8:
910*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YUYV8_1X16:
911*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_YVYU8_1X16:
912*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_UYVY8_1X16:
913*a0ea2d92SDamon Ding 	case MEDIA_BUS_FMT_VYUY8_1X16:
914d0408543SAndy Yan 		return true;
915d0408543SAndy Yan 	default:
916d0408543SAndy Yan 		return false;
917d0408543SAndy Yan 	}
918d0408543SAndy Yan }
919d0408543SAndy Yan 
92010ee9f5bSAlgea Cao static int vop2_convert_csc_mode(int csc_mode)
92110ee9f5bSAlgea Cao {
92210ee9f5bSAlgea Cao 	switch (csc_mode) {
92310ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_SMPTE170M:
92410ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_470_SYSTEM_M:
92510ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_470_SYSTEM_BG:
92610ee9f5bSAlgea Cao 		return CSC_BT601L;
92710ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_REC709:
92810ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_SMPTE240M:
92910ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_DEFAULT:
93010ee9f5bSAlgea Cao 		return CSC_BT709L;
93110ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_JPEG:
93210ee9f5bSAlgea Cao 		return CSC_BT601F;
93310ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_BT2020:
93410ee9f5bSAlgea Cao 		return CSC_BT2020;
93510ee9f5bSAlgea Cao 	default:
93610ee9f5bSAlgea Cao 		return CSC_BT709L;
93710ee9f5bSAlgea Cao 	}
93810ee9f5bSAlgea Cao }
93910ee9f5bSAlgea Cao 
940b0989546SSandy Huang static bool is_uv_swap(u32 bus_format, u32 output_mode)
941d0408543SAndy Yan {
942d0408543SAndy Yan 	/*
943d0408543SAndy Yan 	 * FIXME:
944d0408543SAndy Yan 	 *
945d0408543SAndy Yan 	 * There is no media type for YUV444 output,
946d0408543SAndy Yan 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
947d0408543SAndy Yan 	 * yuv format.
948d0408543SAndy Yan 	 *
949d0408543SAndy Yan 	 * From H/W testing, YUV444 mode need a rb swap.
950d0408543SAndy Yan 	 */
951d0408543SAndy Yan 	if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
952d0408543SAndy Yan 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
953d0408543SAndy Yan 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
954d0408543SAndy Yan 	     output_mode == ROCKCHIP_OUT_MODE_P888))
955d0408543SAndy Yan 		return true;
956d0408543SAndy Yan 	else
957d0408543SAndy Yan 		return false;
958d0408543SAndy Yan }
959d0408543SAndy Yan 
960b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type)
96163cb669fSSandy Huang {
962b0989546SSandy Huang 	switch (output_type) {
963b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIA:
964b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_HDMIB:
965b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_TV:
966b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_DisplayPort:
967b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_VGA:
968b0989546SSandy Huang 	case DRM_MODE_CONNECTOR_Unknown:
969b0989546SSandy Huang 		return true;
970b0989546SSandy Huang 	default:
971b0989546SSandy Huang 		return false;
97263cb669fSSandy Huang 	}
97363cb669fSSandy Huang }
97463cb669fSSandy Huang 
9751147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
976d0408543SAndy Yan 					struct display_state *state)
977d0408543SAndy Yan {
9781147facaSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
9791147facaSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
9801147facaSSandy Huang 	struct resource gamma_res;
9811147facaSSandy Huang 	fdt_size_t lut_size;
9821147facaSSandy Huang 	int i, lut_len, ret = 0;
9831147facaSSandy Huang 	u32 *lut_regs;
9841147facaSSandy Huang 	u32 *lut_val;
9851147facaSSandy Huang 	u32 r, g, b;
9861147facaSSandy Huang 	u32 vp_offset = cstate->crtc_id * 0x100;
9871147facaSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
9881147facaSSandy Huang 	static int gamma_lut_en_num = 1;
9891147facaSSandy Huang 
9901147facaSSandy Huang 	if (gamma_lut_en_num > vop2->data->nr_gammas) {
9911147facaSSandy Huang 		printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
9921147facaSSandy Huang 		return 0;
9931147facaSSandy Huang 	}
9941147facaSSandy Huang 
9951147facaSSandy Huang 	if (!disp_info)
9961147facaSSandy Huang 		return 0;
9971147facaSSandy Huang 
9981147facaSSandy Huang 	if (!disp_info->gamma_lut_data.size)
9991147facaSSandy Huang 		return 0;
10001147facaSSandy Huang 
10011147facaSSandy Huang 	ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
10021147facaSSandy Huang 	if (ret)
10031147facaSSandy Huang 		printf("failed to get gamma lut res\n");
10041147facaSSandy Huang 	lut_regs = (u32 *)gamma_res.start;
10051147facaSSandy Huang 	lut_size = gamma_res.end - gamma_res.start + 1;
10061147facaSSandy Huang 	if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
10071147facaSSandy Huang 		printf("failed to get gamma lut register\n");
10081147facaSSandy Huang 		return 0;
10091147facaSSandy Huang 	}
10101147facaSSandy Huang 	lut_len = lut_size / 4;
10111147facaSSandy Huang 	if (lut_len != 256 && lut_len != 1024) {
10121147facaSSandy Huang 		printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
10131147facaSSandy Huang 		return 0;
10141147facaSSandy Huang 	}
10151147facaSSandy Huang 	lut_val = (u32 *)calloc(1, lut_size);
10161147facaSSandy Huang 	for (i = 0; i < lut_len; i++) {
10171147facaSSandy Huang 		r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
10181147facaSSandy Huang 		g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
10191147facaSSandy Huang 		b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
10201147facaSSandy Huang 
10211147facaSSandy Huang 		lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
10221147facaSSandy Huang 	}
10231147facaSSandy Huang 
10241147facaSSandy Huang 	for (i = 0; i < lut_len; i++)
10251147facaSSandy Huang 		writel(lut_val[i], lut_regs + i);
10261147facaSSandy Huang 
10271147facaSSandy Huang 	vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
10281147facaSSandy Huang 			GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
10291147facaSSandy Huang 			cstate->crtc_id , false);
10301147facaSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
10311147facaSSandy Huang 			EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
10321147facaSSandy Huang 	gamma_lut_en_num++;
10331147facaSSandy Huang 
1034d0408543SAndy Yan 	return 0;
1035d0408543SAndy Yan }
1036d0408543SAndy Yan 
10376414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
10386414e3bcSSandy Huang 					struct display_state *state)
10396414e3bcSSandy Huang {
10406414e3bcSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
10416414e3bcSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
10426414e3bcSSandy Huang 	int i, cubic_lut_len;
10436414e3bcSSandy Huang 	u32 vp_offset = cstate->crtc_id * 0x100;
10446414e3bcSSandy Huang 	struct base2_disp_info *disp_info = conn_state->disp_info;
10456414e3bcSSandy Huang 	struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
10466414e3bcSSandy Huang 	u32 *cubic_lut_addr;
10476414e3bcSSandy Huang 
10486414e3bcSSandy Huang 	if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
10496414e3bcSSandy Huang 		return 0;
10506414e3bcSSandy Huang 
10516414e3bcSSandy Huang 	if (!disp_info->cubic_lut_data.size)
10526414e3bcSSandy Huang 		return 0;
10536414e3bcSSandy Huang 
10546414e3bcSSandy Huang 	cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
10556414e3bcSSandy Huang 	cubic_lut_len = disp_info->cubic_lut_data.size;
10566414e3bcSSandy Huang 
10576414e3bcSSandy Huang 	for (i = 0; i < cubic_lut_len / 2; i++) {
10586414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
10596414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
10606414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
10616414e3bcSSandy Huang 		*cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
10626414e3bcSSandy Huang 					((lut->lred[2 * i + 1] & 0xfff) << 4) +
10636414e3bcSSandy Huang 					((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
10646414e3bcSSandy Huang 					((lut->lblue[2 * i + 1] & 0xf) << 28);
10656414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
10666414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
10676414e3bcSSandy Huang 	}
10686414e3bcSSandy Huang 
10696414e3bcSSandy Huang 	if (cubic_lut_len % 2) {
10706414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
10716414e3bcSSandy Huang 					((lut->lgreen[2 * i] & 0xfff) << 12) +
10726414e3bcSSandy Huang 					((lut->lblue[2 * i] & 0xff) << 24);
10736414e3bcSSandy Huang 		*cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
10746414e3bcSSandy Huang 		*cubic_lut_addr++ = 0;
10756414e3bcSSandy Huang 		*cubic_lut_addr = 0;
10766414e3bcSSandy Huang 	}
10776414e3bcSSandy Huang 
10786414e3bcSSandy Huang 	vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
10796414e3bcSSandy Huang 		    get_cubic_lut_buffer(cstate->crtc_id));
10806414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
10816414e3bcSSandy Huang 			EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
10826414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
10836414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
10846414e3bcSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
10856414e3bcSSandy Huang 			EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
10866414e3bcSSandy Huang 
10876414e3bcSSandy Huang 	return 0;
10886414e3bcSSandy Huang }
10896414e3bcSSandy Huang 
1090ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
1091ac500a1fSSandy Huang {
1092ac500a1fSSandy Huang 	struct connector_state *conn_state = &state->conn_state;
1093ac500a1fSSandy Huang 	struct base_bcsh_info *bcsh_info;
1094ac500a1fSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
1095ac500a1fSSandy Huang 	int brightness, contrast, saturation, hue, sin_hue, cos_hue;
1096ac500a1fSSandy Huang 	bool bcsh_en = false, post_r2y_en = false, post_y2r_en = false;
1097ac500a1fSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
1098ac500a1fSSandy Huang 	int post_csc_mode;
1099ac500a1fSSandy Huang 
1100ac500a1fSSandy Huang 	if (!conn_state->disp_info)
1101ac500a1fSSandy Huang 		return;
1102ac500a1fSSandy Huang 	bcsh_info = &conn_state->disp_info->bcsh_info;
1103ac500a1fSSandy Huang 	if (!bcsh_info)
1104ac500a1fSSandy Huang 		return;
1105ac500a1fSSandy Huang 
1106ac500a1fSSandy Huang 	if (bcsh_info->brightness != 50 ||
1107ac500a1fSSandy Huang 	    bcsh_info->contrast != 50 ||
1108ac500a1fSSandy Huang 	    bcsh_info->saturation != 50 || bcsh_info->hue != 50)
1109ac500a1fSSandy Huang 		bcsh_en = true;
1110ac500a1fSSandy Huang 
1111ac500a1fSSandy Huang 	if (bcsh_en) {
1112ac500a1fSSandy Huang 		if (!cstate->yuv_overlay)
1113ac500a1fSSandy Huang 			post_r2y_en = 1;
1114ac500a1fSSandy Huang 		if (!is_yuv_output(conn_state->bus_format))
1115ac500a1fSSandy Huang 			post_y2r_en = 1;
1116ac500a1fSSandy Huang 	} else {
1117ac500a1fSSandy Huang 		if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
1118ac500a1fSSandy Huang 			post_r2y_en = 1;
1119ac500a1fSSandy Huang 		if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
1120ac500a1fSSandy Huang 			post_y2r_en = 1;
1121ac500a1fSSandy Huang 	}
1122ac500a1fSSandy Huang 
1123ac500a1fSSandy Huang 	post_csc_mode = vop2_convert_csc_mode(conn_state->color_space);
1124ac500a1fSSandy Huang 
1125ac500a1fSSandy Huang 
1126ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
1127ac500a1fSSandy Huang 			BCSH_CTRL_R2Y_SHIFT, post_r2y_en, false);
1128ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
1129ac500a1fSSandy Huang 			BCSH_CTRL_Y2R_SHIFT, post_y2r_en, false);
1130ac500a1fSSandy Huang 
1131ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
1132ac500a1fSSandy Huang 			BCSH_CTRL_R2Y_CSC_MODE_SHIFT, post_csc_mode, false);
1133ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
1134ac500a1fSSandy Huang 			BCSH_CTRL_Y2R_CSC_MODE_SHIFT, post_csc_mode, false);
1135ac500a1fSSandy Huang 	if (!bcsh_en) {
1136ac500a1fSSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1137ac500a1fSSandy Huang 				BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
1138ac500a1fSSandy Huang 		return;
1139ac500a1fSSandy Huang 	}
1140ac500a1fSSandy Huang 
1141ac500a1fSSandy Huang 	if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
1142ac500a1fSSandy Huang 		brightness = interpolate(0, -128, 100, 127,
1143ac500a1fSSandy Huang 					 bcsh_info->brightness);
1144ac500a1fSSandy Huang 	else
1145ac500a1fSSandy Huang 		brightness = interpolate(0, -32, 100, 31,
1146ac500a1fSSandy Huang 					 bcsh_info->brightness);
1147ac500a1fSSandy Huang 	contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
1148ac500a1fSSandy Huang 	saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
1149ac500a1fSSandy Huang 	hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
1150ac500a1fSSandy Huang 
1151ac500a1fSSandy Huang 
1152ac500a1fSSandy Huang 	/*
1153ac500a1fSSandy Huang 	 *  a:[-30~0):
1154ac500a1fSSandy Huang 	 *    sin_hue = 0x100 - sin(a)*256;
1155ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
1156ac500a1fSSandy Huang 	 *  a:[0~30]
1157ac500a1fSSandy Huang 	 *    sin_hue = sin(a)*256;
1158ac500a1fSSandy Huang 	 *    cos_hue = cos(a)*256;
1159ac500a1fSSandy Huang 	 */
1160ac500a1fSSandy Huang 	sin_hue = fixp_sin32(hue) >> 23;
1161ac500a1fSSandy Huang 	cos_hue = fixp_cos32(hue) >> 23;
1162ac500a1fSSandy Huang 
1163ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1164ac500a1fSSandy Huang 			BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
1165ac500a1fSSandy Huang 			brightness, false);
1166ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1167ac500a1fSSandy Huang 			BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, contrast, false);
1168ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1169ac500a1fSSandy Huang 			BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
1170ac500a1fSSandy Huang 			saturation * contrast / 0x100, false);
1171ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1172ac500a1fSSandy Huang 			BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, sin_hue, false);
1173ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
1174ac500a1fSSandy Huang 			BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, cos_hue, false);
1175ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
1176ac500a1fSSandy Huang 			 BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
1177ac500a1fSSandy Huang 			BCSH_OUT_MODE_NORMAL_VIDEO, false);
1178ac500a1fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
1179ac500a1fSSandy Huang 			BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
1180ac500a1fSSandy Huang }
1181ac500a1fSSandy Huang 
1182d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
1183d0408543SAndy Yan {
1184d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
1185d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
118652ee18acSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
118752ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
1188d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
1189d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
1190d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
1191d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
1192d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
1193d0408543SAndy Yan 	u16 hsize =
1194d0408543SAndy Yan 	    hdisplay * (conn_state->overscan.left_margin +
1195d0408543SAndy Yan 			conn_state->overscan.right_margin) / 200;
1196d0408543SAndy Yan 	u16 vsize =
1197d0408543SAndy Yan 	    vdisplay * (conn_state->overscan.top_margin +
1198d0408543SAndy Yan 			conn_state->overscan.bottom_margin) / 200;
1199d0408543SAndy Yan 	u16 hact_end, vact_end;
1200d0408543SAndy Yan 	u32 val;
1201d0408543SAndy Yan 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
1202d0408543SAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
1203d0408543SAndy Yan 
120474bd8269SSandy Huang 	hsize = round_down(hsize, 2);
1205d0408543SAndy Yan 	vsize = round_down(vsize, 2);
1206d0408543SAndy Yan 
1207d0408543SAndy Yan 	hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
1208d0408543SAndy Yan 	hact_end = hact_st + hsize;
1209d0408543SAndy Yan 	val = hact_st << 16;
1210d0408543SAndy Yan 	val |= hact_end;
1211d0408543SAndy Yan 
121252ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
1213d0408543SAndy Yan 	vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
1214d0408543SAndy Yan 	vact_end = vact_st + vsize;
1215d0408543SAndy Yan 	val = vact_st << 16;
1216d0408543SAndy Yan 	val |= vact_end;
121752ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
1218d0408543SAndy Yan 	val = scl_cal_scale2(vdisplay, vsize) << 16;
1219d0408543SAndy Yan 	val |= scl_cal_scale2(hdisplay, hsize);
122052ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
1221d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
1222d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
122352ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
1224d0408543SAndy Yan 		    POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
1225d0408543SAndy Yan 		    POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
1226d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1227d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
1228d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vsize;
1229d0408543SAndy Yan 
1230d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
123152ee18acSSandy Huang 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
1232d0408543SAndy Yan 	}
1233d0408543SAndy Yan 
123463cb669fSSandy Huang 	bg_ovl_dly = cstate->crtc->vps[cstate->crtc_id].bg_ovl_dly;
123563cb669fSSandy Huang 	bg_dly =  vop2->data->vp_data[cstate->crtc_id].pre_scan_max_dly;
123663cb669fSSandy Huang 	bg_dly -= bg_ovl_dly;
1237d0408543SAndy Yan 	pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
1238d0408543SAndy Yan 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
123963cb669fSSandy Huang 	vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + cstate->crtc_id * 4,
124063cb669fSSandy Huang 			BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
124152ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + vp_offset, pre_scan_dly);
1242d0408543SAndy Yan }
1243d0408543SAndy Yan 
1244b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
1245d0408543SAndy Yan {
1246b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
1247b0989546SSandy Huang 	int i, j, port_mux = 0, total_used_layer = 0;
124863cb669fSSandy Huang 	u8 shift = 0;
1249b0989546SSandy Huang 	int layer_phy_id = 0;
1250b0989546SSandy Huang 	u32 layer_nr = 0;
1251b0989546SSandy Huang 	struct vop2_win_data *win_data;
1252b0989546SSandy Huang 	struct vop2_vp_plane_mask *plane_mask;
1253d0408543SAndy Yan 
125463cb669fSSandy Huang 	if (vop2->global_init)
1255d0408543SAndy Yan 		return;
125663cb669fSSandy Huang 
1257b0989546SSandy Huang 	/* OTP must enable at the first time, otherwise mirror layer register is error */
125863cb669fSSandy Huang 	if (soc_is_rk3566())
125963cb669fSSandy Huang 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
126063cb669fSSandy Huang 				OTP_WIN_EN_SHIFT, 1, false);
1261b0989546SSandy Huang 
1262b0989546SSandy Huang 	memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
126363cb669fSSandy Huang 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
126463cb669fSSandy Huang 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
126563cb669fSSandy Huang 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
126663cb669fSSandy Huang 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
1267b0989546SSandy Huang 
1268b0989546SSandy Huang 	if (cstate->crtc->assign_plane) {/* dts assign plane */
1269b0989546SSandy Huang 		u32 plane_mask;
1270b0989546SSandy Huang 		int primary_plane_id;
1271b0989546SSandy Huang 
1272b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
1273b0989546SSandy Huang 			plane_mask = cstate->crtc->vps[i].plane_mask;
1274b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
1275b0989546SSandy Huang 			layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */
1276b0989546SSandy Huang 			vop2->vp_plane_mask[i].attached_layers_nr = layer_nr;
1277b0989546SSandy Huang 			primary_plane_id = vop2_get_primary_plane(vop2, plane_mask);
1278b0989546SSandy Huang 			vop2->vp_plane_mask[i].primary_plane_id =  primary_plane_id;
1279b0989546SSandy Huang 			vop2->vp_plane_mask[i].plane_mask = plane_mask;
1280b0989546SSandy Huang 
1281b0989546SSandy Huang 			/* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/
1282b0989546SSandy Huang 			for (j = 0; j < layer_nr; j++) {
1283b0989546SSandy Huang 				vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
1284b0989546SSandy Huang 				plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
128563cb669fSSandy Huang 			}
1286b0989546SSandy Huang 		}
1287b0989546SSandy Huang 	} else {/* need soft assign plane mask */
1288b0989546SSandy Huang 		/* find the first unplug devices and set it as main display */
1289b0989546SSandy Huang 		int main_vp_index = -1;
1290b0989546SSandy Huang 		int active_vp_num = 0;
1291b0989546SSandy Huang 
1292b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
1293b0989546SSandy Huang 			if (cstate->crtc->vps[i].enable)
1294b0989546SSandy Huang 				active_vp_num++;
1295b0989546SSandy Huang 		}
1296b0989546SSandy Huang 		printf("VOP have %d active VP\n", active_vp_num);
1297b0989546SSandy Huang 
1298b0989546SSandy Huang 		if (soc_is_rk3566() && active_vp_num > 2)
1299b0989546SSandy Huang 			printf("ERROR: rk3566 only support 2 display output!!\n");
1300b0989546SSandy Huang 		plane_mask = vop2->data->plane_mask;
1301b0989546SSandy Huang 		plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
1302b0989546SSandy Huang 
1303b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
1304b0989546SSandy Huang 			if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
1305b0989546SSandy Huang 				vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/
1306b0989546SSandy Huang 				main_vp_index = i;
1307e007876dSSandy Huang 				break;
1308b0989546SSandy Huang 			}
1309b0989546SSandy Huang 		}
1310b0989546SSandy Huang 
1311b0989546SSandy Huang 		/* if no find unplug devices, use vp0 as main display */
1312b0989546SSandy Huang 		if (main_vp_index < 0) {
1313b0989546SSandy Huang 			main_vp_index = 0;
1314b0989546SSandy Huang 			vop2->vp_plane_mask[0] = plane_mask[0];
1315b0989546SSandy Huang 		}
1316b0989546SSandy Huang 
1317b0989546SSandy Huang 		j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */
1318b0989546SSandy Huang 
1319b0989546SSandy Huang 		/* init other display except main display */
1320b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
1321b0989546SSandy Huang 			if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */
1322b0989546SSandy Huang 				continue;
1323b0989546SSandy Huang 			vop2->vp_plane_mask[i] = plane_mask[j++];
1324b0989546SSandy Huang 		}
1325b0989546SSandy Huang 
1326b0989546SSandy Huang 		/* store plane mask for vop2_fixup_dts */
1327b0989546SSandy Huang 		for (i = 0; i < vop2->data->nr_vps; i++) {
1328b0989546SSandy Huang 			layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
1329efb5a62dSSandy Huang 			/* rk3566 only support 3+3 policy */
1330efb5a62dSSandy Huang 			if (soc_is_rk3566() && active_vp_num == 1) {
1331efb5a62dSSandy Huang 				if (cstate->crtc->vps[i].enable) {
1332efb5a62dSSandy Huang 					for (j = 0; j < 3; j++) {
1333efb5a62dSSandy Huang 						layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1334efb5a62dSSandy Huang 						vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
1335efb5a62dSSandy Huang 					}
1336efb5a62dSSandy Huang 				}
1337efb5a62dSSandy Huang 			} else {
1338b0989546SSandy Huang 				for (j = 0; j < layer_nr; j++) {
1339b0989546SSandy Huang 					layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1340b0989546SSandy Huang 					vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
1341b0989546SSandy Huang 				}
1342b0989546SSandy Huang 			}
1343b0989546SSandy Huang 		}
1344efb5a62dSSandy Huang 	}
1345b0989546SSandy Huang 
1346b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
1347b0989546SSandy Huang 		printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
1348b0989546SSandy Huang 		for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
1349b0989546SSandy Huang 			printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]);
1350b0989546SSandy Huang 		printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id);
1351b0989546SSandy Huang 	}
1352b0989546SSandy Huang 
1353b0989546SSandy Huang 	shift = 0;
1354b0989546SSandy Huang 	/* layer sel win id */
1355b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
1356b0989546SSandy Huang 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
1357b0989546SSandy Huang 		for (j = 0; j < layer_nr; j++) {
1358b0989546SSandy Huang 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1359b0989546SSandy Huang 			win_data = &vop2->data->win_data[layer_phy_id];
1360b0989546SSandy Huang 			vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
1361b0989546SSandy Huang 					shift, win_data->layer_sel_win_id, false);
1362b0989546SSandy Huang 			shift += 4;
1363b0989546SSandy Huang 		}
1364b0989546SSandy Huang 	}
1365b0989546SSandy Huang 
1366b0989546SSandy Huang 	/* win sel port */
1367b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
1368b0989546SSandy Huang 		layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
1369b0989546SSandy Huang 		for (j = 0; j < layer_nr; j++) {
1370b0989546SSandy Huang 			if (!cstate->crtc->vps[i].enable)
1371b0989546SSandy Huang 				continue;
1372b0989546SSandy Huang 			layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
1373b0989546SSandy Huang 			win_data = &vop2->data->win_data[layer_phy_id];
1374b0989546SSandy Huang 			shift = win_data->win_sel_port_offset * 2;
1375b0989546SSandy Huang 			vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
1376b0989546SSandy Huang 					LAYER_SEL_PORT_SHIFT + shift, i, false);
1377b0989546SSandy Huang 		}
1378b0989546SSandy Huang 	}
1379b0989546SSandy Huang 
138063cb669fSSandy Huang 	/**
138163cb669fSSandy Huang 	 * port mux config
138263cb669fSSandy Huang 	 */
1383b0989546SSandy Huang 	for (i = 0; i < vop2->data->nr_vps; i++) {
138463cb669fSSandy Huang 		shift = i * 4;
138563cb669fSSandy Huang 		if (cstate->crtc->vps[i].enable) {
1386b0989546SSandy Huang 			total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
138763cb669fSSandy Huang 			port_mux = total_used_layer - 1;
138863cb669fSSandy Huang 		} else {
138963cb669fSSandy Huang 			port_mux = 8;
1390d0408543SAndy Yan 		}
1391d0408543SAndy Yan 
1392b0989546SSandy Huang 		if (i == vop2->data->nr_vps - 1)
139363cb669fSSandy Huang 			port_mux = vop2->data->nr_mixers;
139463cb669fSSandy Huang 
139563cb669fSSandy Huang 		cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
139663cb669fSSandy Huang 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
139763cb669fSSandy Huang 				PORT_MUX_SHIFT + shift, port_mux, false);
139863cb669fSSandy Huang 	}
139963cb669fSSandy Huang 
140063cb669fSSandy Huang 	vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
140163cb669fSSandy Huang 
140263cb669fSSandy Huang 	vop2->global_init = true;
1403d0408543SAndy Yan }
1404d0408543SAndy Yan 
1405d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state)
1406d0408543SAndy Yan {
1407d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1408d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
1409d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
1410d0408543SAndy Yan 	char dclk_name[9];
1411d0408543SAndy Yan 	struct clk dclk;
141263cb669fSSandy Huang 	int ret;
1413d0408543SAndy Yan 
1414d0408543SAndy Yan 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1415d0408543SAndy Yan 	ret = clk_set_defaults(cstate->dev);
1416d0408543SAndy Yan 	if (ret)
1417d0408543SAndy Yan 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1418d0408543SAndy Yan 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
1419d0408543SAndy Yan 	ret = clk_get_by_name(cstate->dev, dclk_name, &dclk);
1420d0408543SAndy Yan 	if (!ret)
1421d0408543SAndy Yan 		ret = clk_set_rate(&dclk, mode->clock * 1000);
1422d0408543SAndy Yan 	if (IS_ERR_VALUE(ret)) {
1423b0989546SSandy Huang 		printf("%s: Failed to set vp%d dclk[%d khz]: ret=%d\n",
1424b0989546SSandy Huang 		       __func__, cstate->crtc_id, mode->clock, ret);
1425d0408543SAndy Yan 		return ret;
1426d0408543SAndy Yan 	}
1427d0408543SAndy Yan 
14281147facaSSandy Huang 	rockchip_vop2_gamma_lut_init(vop2, state);
14296414e3bcSSandy Huang 	rockchip_vop2_cubic_lut_init(vop2, state);
1430d0408543SAndy Yan 
1431d0408543SAndy Yan 	return 0;
1432d0408543SAndy Yan }
1433d0408543SAndy Yan 
1434d0408543SAndy Yan /*
1435d0408543SAndy Yan  * VOP2 have multi video ports.
1436d0408543SAndy Yan  * video port ------- crtc
1437d0408543SAndy Yan  */
1438d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state)
1439d0408543SAndy Yan {
1440d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1441d0408543SAndy Yan 	const struct vop2_data *vop2_data = cstate->crtc->data;
1442d0408543SAndy Yan 
1443d0408543SAndy Yan 	if (!rockchip_vop2) {
14440d2d6a97SSandy Huang 		rockchip_vop2 = calloc(1, sizeof(struct vop2));
1445d0408543SAndy Yan 		if (!rockchip_vop2)
1446d0408543SAndy Yan 			return -ENOMEM;
1447d0408543SAndy Yan 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
1448d0408543SAndy Yan 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
1449d0408543SAndy Yan 		rockchip_vop2->reg_len = RK3568_MAX_REG;
145063cb669fSSandy Huang 		rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1451d0408543SAndy Yan 		if (rockchip_vop2->grf <= 0)
145263cb669fSSandy Huang 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
1453d0408543SAndy Yan 
1454d0408543SAndy Yan 		rockchip_vop2->version = vop2_data->version;
1455d0408543SAndy Yan 		rockchip_vop2->data = vop2_data;
1456d0408543SAndy Yan 	}
1457d0408543SAndy Yan 
1458d0408543SAndy Yan 	cstate->private = rockchip_vop2;
145963cb669fSSandy Huang 	cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
146063cb669fSSandy Huang 	cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
1461d0408543SAndy Yan 
146289912f2dSSandy Huang 	vop2_global_initial(rockchip_vop2, state);
146389912f2dSSandy Huang 
1464d0408543SAndy Yan 	return 0;
1465d0408543SAndy Yan }
1466d0408543SAndy Yan 
1467d0408543SAndy Yan static int rockchip_vop2_init(struct display_state *state)
1468d0408543SAndy Yan {
1469d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1470d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
1471d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
1472d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
1473d0408543SAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
1474d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
1475d0408543SAndy Yan 	u16 htotal = mode->crtc_htotal;
1476d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
1477d0408543SAndy Yan 	u16 hact_end = hact_st + hdisplay;
1478d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
1479d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
1480d0408543SAndy Yan 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
1481d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
1482d0408543SAndy Yan 	u16 vact_end = vact_st + vdisplay;
1483d0408543SAndy Yan 	bool yuv_overlay = false;
148452ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
1485d0408543SAndy Yan 	u32 val;
1486d0408543SAndy Yan 	bool dclk_inv;
148763cb669fSSandy Huang 	u8 dither_down_en = 0;
148863cb669fSSandy Huang 	u8 pre_dither_down_en = 0;
14898895aec1SSandy Huang 	char output_type_name[30] = {0};
14908895aec1SSandy Huang 
14918895aec1SSandy Huang 	printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
14928895aec1SSandy Huang 	       mode->hdisplay, mode->vdisplay,
14938895aec1SSandy Huang 	       mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
14948895aec1SSandy Huang 	       mode->vscan,
14958895aec1SSandy Huang 	       get_output_if_name(conn_state->output_if, output_type_name),
14968895aec1SSandy Huang 	       cstate->crtc_id);
1497d0408543SAndy Yan 
1498d0408543SAndy Yan 	vop2_initial(vop2, state);
1499d0408543SAndy Yan 	dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1;
150010ee9f5bSAlgea Cao 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
150110ee9f5bSAlgea Cao 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
1502d0408543SAndy Yan 
1503d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
1504d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
1505d0408543SAndy Yan 				1, false);
1506d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1507d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
150852ee18acSSandy Huang 		vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK,
1509c55d261eSSandy Huang 				GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
1510d0408543SAndy Yan 	}
1511d0408543SAndy Yan 
1512d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
151352ee18acSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
151452ee18acSSandy Huang 				1, false);
1515d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
1516d0408543SAndy Yan 				BT1120_EN_SHIFT, 1, false);
1517d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1518d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
151952ee18acSSandy Huang 		vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK,
152052ee18acSSandy Huang 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
1521d0408543SAndy Yan 	}
1522d0408543SAndy Yan 
1523d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
1524d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
1525d0408543SAndy Yan 				1, false);
1526d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1527d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
152852ee18acSSandy Huang 		vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK,
152952ee18acSSandy Huang 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
1530d0408543SAndy Yan 	}
1531d0408543SAndy Yan 
1532d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
1533d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
1534d0408543SAndy Yan 				1, false);
1535d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1536d0408543SAndy Yan 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
153711f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
153811f53190SSandy Huang 				IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false);
1539d0408543SAndy Yan 	}
1540d0408543SAndy Yan 
1541d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
1542d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
1543d0408543SAndy Yan 				1, false);
1544d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1545d0408543SAndy Yan 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
154611f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
154711f53190SSandy Huang 				IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false);
1548d0408543SAndy Yan 	}
1549d0408543SAndy Yan 
1550d0408543SAndy Yan 	if (conn_state->output_flags &
1551d0408543SAndy Yan 	    (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE |
1552d0408543SAndy Yan 	     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) {
1553d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
1554d0408543SAndy Yan 				LVDS_DUAL_EN_SHIFT, 1, false);
1555d0408543SAndy Yan 		if (conn_state->output_flags &
1556d0408543SAndy Yan 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
1557d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
1558d0408543SAndy Yan 					LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1,
1559d0408543SAndy Yan 					false);
1560d0408543SAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
1561d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
1562d0408543SAndy Yan 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
1563d0408543SAndy Yan 	}
1564d0408543SAndy Yan 
1565d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
1566d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
1567d0408543SAndy Yan 				1, false);
1568d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1569d0408543SAndy Yan 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
1570d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
1571c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
1572d0408543SAndy Yan 	}
1573d0408543SAndy Yan 
1574d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
1575d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
1576d0408543SAndy Yan 				1, false);
1577d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1578d0408543SAndy Yan 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
1579d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
1580c55d261eSSandy Huang 				IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
1581d0408543SAndy Yan 	}
1582d0408543SAndy Yan 
1583d0408543SAndy Yan 	if (conn_state->output_flags &
1584d0408543SAndy Yan 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
1585d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
1586d0408543SAndy Yan 				MIPI_DUAL_EN_SHIFT, 1, false);
1587d0408543SAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
1588d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
1589d0408543SAndy Yan 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
1590d0408543SAndy Yan 					false);
1591d0408543SAndy Yan 	}
1592d0408543SAndy Yan 
1593d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
1594d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
1595d0408543SAndy Yan 				1, false);
1596d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1597d0408543SAndy Yan 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
1598c55d261eSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
1599c55d261eSSandy Huang 				IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
1600d0408543SAndy Yan 	}
1601d0408543SAndy Yan 
1602d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
1603d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
1604d0408543SAndy Yan 				1, false);
1605d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
1606d0408543SAndy Yan 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
160710ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
160810ee9f5bSAlgea Cao 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
160910ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
161010ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_MASK,
161110ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
1612d0408543SAndy Yan 	}
161310ee9f5bSAlgea Cao 
161463cb669fSSandy Huang 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
161563cb669fSSandy Huang 	    !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT))
16167bdd0eb6SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
16177bdd0eb6SSandy Huang 
161810ee9f5bSAlgea Cao 	if (is_uv_swap(conn_state->bus_format, conn_state->output_mode))
161910ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
162010ee9f5bSAlgea Cao 				DATA_SWAP_MASK, DATA_SWAP_SHIFT, DSP_RB_SWAP,
162110ee9f5bSAlgea Cao 				false);
162210ee9f5bSAlgea Cao 	else
162310ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
162410ee9f5bSAlgea Cao 				DATA_SWAP_MASK, DATA_SWAP_SHIFT, 0,
162510ee9f5bSAlgea Cao 				false);
162610ee9f5bSAlgea Cao 
1627d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
1628d0408543SAndy Yan 			OUT_MODE_SHIFT, conn_state->output_mode, false);
1629d0408543SAndy Yan 
1630d0408543SAndy Yan 	switch (conn_state->bus_format) {
1631d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB565_1X16:
1632d0408543SAndy Yan 		dither_down_en = 1;
1633d0408543SAndy Yan 		break;
1634d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X18:
1635d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
1636d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
1637d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
1638d0408543SAndy Yan 		dither_down_en = 1;
1639d0408543SAndy Yan 		break;
1640d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
1641d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1642d0408543SAndy Yan 		dither_down_en = 0;
1643d0408543SAndy Yan 		pre_dither_down_en = 1;
1644d0408543SAndy Yan 		break;
1645d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
1646d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1647d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB888_1X24:
1648d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
1649d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
1650d0408543SAndy Yan 	default:
1651d0408543SAndy Yan 		dither_down_en = 0;
1652d0408543SAndy Yan 		pre_dither_down_en = 0;
1653d0408543SAndy Yan 		break;
1654d0408543SAndy Yan 	}
1655d0408543SAndy Yan 
1656d0408543SAndy Yan 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA)
1657d0408543SAndy Yan 		pre_dither_down_en = 0;
1658d0408543SAndy Yan 	else
1659d0408543SAndy Yan 		pre_dither_down_en = 1;
1660d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1661d0408543SAndy Yan 			DITHER_DOWN_EN_SHIFT, dither_down_en, false);
1662d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1663d0408543SAndy Yan 			PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
1664d0408543SAndy Yan 
1665d0408543SAndy Yan 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
1666d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
1667d0408543SAndy Yan 			yuv_overlay, false);
1668d0408543SAndy Yan 
1669d0408543SAndy Yan 	cstate->yuv_overlay = yuv_overlay;
1670d0408543SAndy Yan 
1671d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
1672d0408543SAndy Yan 		    (htotal << 16) | hsync_len);
1673d0408543SAndy Yan 	val = hact_st << 16;
1674d0408543SAndy Yan 	val |= hact_end;
1675d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
1676d0408543SAndy Yan 	val = vact_st << 16;
1677d0408543SAndy Yan 	val |= vact_end;
1678d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
1679d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1680d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
1681d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
1682d0408543SAndy Yan 
1683d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
1684d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
1685d0408543SAndy Yan 			    val);
1686d0408543SAndy Yan 
1687d0408543SAndy Yan 		val = vtotal << 16 | (vtotal + vsync_len);
1688d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
1689d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1690d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 1, false);
1691d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
16927a20be36SSandy Huang 				DSP_FILED_POL, 1, false);
16937a20be36SSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1694d0408543SAndy Yan 				P2I_EN_SHIFT, 1, false);
1695d0408543SAndy Yan 		vtotal += vtotal + 1;
1696d0408543SAndy Yan 	} else {
1697d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1698d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 0, false);
1699d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1700d0408543SAndy Yan 				P2I_EN_SHIFT, 0, false);
1701d0408543SAndy Yan 	}
1702d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
1703d0408543SAndy Yan 		    (vtotal << 16) | vsync_len);
1704d0408543SAndy Yan 	val = !!(mode->flags & DRM_MODE_FLAG_DBLCLK);
1705d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
170610ee9f5bSAlgea Cao 			CORE_DCLK_DIV_EN_SHIFT, val, false);
170710ee9f5bSAlgea Cao 
170810ee9f5bSAlgea Cao 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
170963cb669fSSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
171063cb669fSSandy Huang 				DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
171110ee9f5bSAlgea Cao 	else
171263cb669fSSandy Huang 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
171363cb669fSSandy Huang 				DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
171410ee9f5bSAlgea Cao 
171510ee9f5bSAlgea Cao 	if (yuv_overlay)
171610ee9f5bSAlgea Cao 		val = 0x20010200;
171710ee9f5bSAlgea Cao 	else
171810ee9f5bSAlgea Cao 		val = 0;
171910ee9f5bSAlgea Cao 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
172010ee9f5bSAlgea Cao 
172110ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
172210ee9f5bSAlgea Cao 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
1723d0408543SAndy Yan 
1724ac500a1fSSandy Huang 	vop2_tv_config_update(state, vop2);
1725d0408543SAndy Yan 	vop2_post_config(state, vop2);
1726d0408543SAndy Yan 
1727d0408543SAndy Yan 	return 0;
1728d0408543SAndy Yan }
1729d0408543SAndy Yan 
17303e39a5a1SSandy Huang static void vop2_setup_scale(struct vop2 *vop2, uint32_t win_offset,
17313e39a5a1SSandy Huang 			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
17323e39a5a1SSandy Huang 			     uint32_t dst_h)
17333e39a5a1SSandy Huang {
17343e39a5a1SSandy Huang 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
17353e39a5a1SSandy Huang 	uint16_t hscl_filter_mode, vscl_filter_mode;
17363e39a5a1SSandy Huang 	uint8_t gt2 = 0, gt4 = 0;
17373e39a5a1SSandy Huang 	uint32_t xfac = 0, yfac = 0;
17383e39a5a1SSandy Huang 	uint16_t hsu_filter_mode = VOP2_SCALE_UP_BIC;
17393e39a5a1SSandy Huang 	uint16_t hsd_filter_mode = VOP2_SCALE_DOWN_BIL;
17403e39a5a1SSandy Huang 	uint16_t vsu_filter_mode = VOP2_SCALE_UP_BIL;
17413e39a5a1SSandy Huang 	uint16_t vsd_filter_mode = VOP2_SCALE_DOWN_BIL;
17423e39a5a1SSandy Huang 
17433e39a5a1SSandy Huang 	if (src_h >= (4 * dst_h))
17443e39a5a1SSandy Huang 		gt4 = 1;
17453e39a5a1SSandy Huang 	else if (src_h >= (2 * dst_h))
17463e39a5a1SSandy Huang 		gt2 = 1;
17473e39a5a1SSandy Huang 
17483e39a5a1SSandy Huang 	if (gt4)
17493e39a5a1SSandy Huang 		src_h >>= 2;
17503e39a5a1SSandy Huang 	else if (gt2)
17513e39a5a1SSandy Huang 		src_h >>= 1;
17523e39a5a1SSandy Huang 
17533e39a5a1SSandy Huang 	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
17543e39a5a1SSandy Huang 	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
17553e39a5a1SSandy Huang 
17563e39a5a1SSandy Huang 	if (yrgb_hor_scl_mode == SCALE_UP)
17573e39a5a1SSandy Huang 		hscl_filter_mode = hsu_filter_mode;
17583e39a5a1SSandy Huang 	else
17593e39a5a1SSandy Huang 		hscl_filter_mode = hsd_filter_mode;
17603e39a5a1SSandy Huang 
17613e39a5a1SSandy Huang 	if (yrgb_ver_scl_mode == SCALE_UP)
17623e39a5a1SSandy Huang 		vscl_filter_mode = vsu_filter_mode;
17633e39a5a1SSandy Huang 	else
17643e39a5a1SSandy Huang 		vscl_filter_mode = vsd_filter_mode;
17653e39a5a1SSandy Huang 
17663e39a5a1SSandy Huang 	/*
17673e39a5a1SSandy Huang 	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
17683e39a5a1SSandy Huang 	 * at scale down mode
17693e39a5a1SSandy Huang 	 */
17703e39a5a1SSandy Huang 	if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) {
17713e39a5a1SSandy Huang 		printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
17723e39a5a1SSandy Huang 		dst_w += 1;
17733e39a5a1SSandy Huang 	}
17743e39a5a1SSandy Huang 
17753e39a5a1SSandy Huang 	xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
17763e39a5a1SSandy Huang 	yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
17773e39a5a1SSandy Huang 	vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
17783e39a5a1SSandy Huang 		    yfac << 16 | xfac);
17793e39a5a1SSandy Huang 
178034a72bf2SDing Ling Song 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
17813e39a5a1SSandy Huang 			YRGB_GT2_MASK, YRGB_GT2_SHIFT, gt2, false);
178234a72bf2SDing Ling Song 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
17833e39a5a1SSandy Huang 			YRGB_GT4_MASK, YRGB_GT4_SHIFT, gt4, false);
17843e39a5a1SSandy Huang 
17853e39a5a1SSandy Huang 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
17863e39a5a1SSandy Huang 			YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
17873e39a5a1SSandy Huang 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
17883e39a5a1SSandy Huang 			YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
17893e39a5a1SSandy Huang 
17903e39a5a1SSandy Huang 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
17913e39a5a1SSandy Huang 			YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
17923e39a5a1SSandy Huang 			hscl_filter_mode, false);
17933e39a5a1SSandy Huang 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
17943e39a5a1SSandy Huang 			YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
17953e39a5a1SSandy Huang 			vscl_filter_mode, false);
17963e39a5a1SSandy Huang }
17973e39a5a1SSandy Huang 
1798d0408543SAndy Yan static int rockchip_vop2_set_plane(struct display_state *state)
1799d0408543SAndy Yan {
1800d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1801d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
1802d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
1803d0408543SAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
1804d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
1805d0408543SAndy Yan 	int src_w = cstate->src_w;
1806d0408543SAndy Yan 	int src_h = cstate->src_h;
1807d0408543SAndy Yan 	int crtc_x = cstate->crtc_x;
1808d0408543SAndy Yan 	int crtc_y = cstate->crtc_y;
1809d0408543SAndy Yan 	int crtc_w = cstate->crtc_w;
1810d0408543SAndy Yan 	int crtc_h = cstate->crtc_h;
1811d0408543SAndy Yan 	int xvir = cstate->xvir;
1812d0408543SAndy Yan 	int y_mirror = 0;
181310ee9f5bSAlgea Cao 	int csc_mode;
18142b2e3d70SSandy Huang 	u32 win_offset;
181552ee18acSSandy Huang 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id);
1816b0989546SSandy Huang 	u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
18178895aec1SSandy Huang 	char plane_name[10] = {0};
1818d0408543SAndy Yan 
1819b0989546SSandy Huang 	win_offset = vop2->data->win_data[primary_plane_id].reg_offset;
1820d0408543SAndy Yan 	if (crtc_w > cstate->max_output.width) {
1821d0408543SAndy Yan 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
1822d0408543SAndy Yan 		       crtc_w, cstate->max_output.width);
1823d0408543SAndy Yan 		return -EINVAL;
1824d0408543SAndy Yan 	}
1825d0408543SAndy Yan 
182674bd8269SSandy Huang 	/*
182774bd8269SSandy Huang 	 * This is workaround solution for IC design:
182874bd8269SSandy Huang 	 * esmart can't support scale down when actual_w % 16 == 1.
182974bd8269SSandy Huang 	 */
183074bd8269SSandy Huang 	if (src_w > crtc_w && (src_w & 0xf) == 1) {
183174bd8269SSandy Huang 		printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
183274bd8269SSandy Huang 		src_w -= 1;
183374bd8269SSandy Huang 	}
183474bd8269SSandy Huang 
1835d0408543SAndy Yan 	act_info = (src_h - 1) << 16;
1836d0408543SAndy Yan 	act_info |= (src_w - 1) & 0xffff;
1837d0408543SAndy Yan 
1838d0408543SAndy Yan 	dsp_info = (crtc_h - 1) << 16;
1839d0408543SAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
1840d0408543SAndy Yan 
1841d0408543SAndy Yan 	dsp_stx = crtc_x;
1842d0408543SAndy Yan 	dsp_sty = crtc_y;
1843d0408543SAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
1844d0408543SAndy Yan 
1845d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
1846d0408543SAndy Yan 		y_mirror = 1;
1847d0408543SAndy Yan 	else
1848d0408543SAndy Yan 		y_mirror = 0;
1849d0408543SAndy Yan 
18503e39a5a1SSandy Huang 	vop2_setup_scale(vop2, win_offset, src_w, src_h, crtc_w, crtc_h);
18513e39a5a1SSandy Huang 
1852d0408543SAndy Yan 	if (y_mirror)
1853d0408543SAndy Yan 		cstate->dma_addr += (src_h - 1) * xvir * 4;
1854d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
1855d0408543SAndy Yan 			YMIRROR_EN_SHIFT, y_mirror, false);
1856d0408543SAndy Yan 
1857d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
1858d0408543SAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
1859d0408543SAndy Yan 			false);
1860d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
1861d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
1862d0408543SAndy Yan 		    cstate->dma_addr);
1863d0408543SAndy Yan 
1864d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
1865d0408543SAndy Yan 		    act_info);
1866d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
1867d0408543SAndy Yan 		    dsp_info);
1868d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
1869d0408543SAndy Yan 
1870d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
1871d0408543SAndy Yan 			WIN_EN_SHIFT, 1, false);
1872d0408543SAndy Yan 
187310ee9f5bSAlgea Cao 	csc_mode = vop2_convert_csc_mode(conn_state->color_space);
187410ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
187510ee9f5bSAlgea Cao 			RGB2YUV_EN_SHIFT,
187610ee9f5bSAlgea Cao 			is_yuv_output(conn_state->bus_format), false);
187710ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
187810ee9f5bSAlgea Cao 			CSC_MODE_SHIFT, csc_mode, false);
187910ee9f5bSAlgea Cao 
1880d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
18818895aec1SSandy Huang 
18828895aec1SSandy Huang 	printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
18838895aec1SSandy Huang 		cstate->crtc_id, get_plane_name(primary_plane_id, plane_name),
18848895aec1SSandy Huang 		src_w, src_h, crtc_w, crtc_h, crtc_x, crtc_y, cstate->format,
18858895aec1SSandy Huang 		cstate->dma_addr);
18868895aec1SSandy Huang 
1887d0408543SAndy Yan 	return 0;
1888d0408543SAndy Yan }
1889d0408543SAndy Yan 
1890d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state)
1891d0408543SAndy Yan {
1892d0408543SAndy Yan 	return 0;
1893d0408543SAndy Yan }
1894d0408543SAndy Yan 
1895d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state)
1896d0408543SAndy Yan {
1897d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1898d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
189952ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
190052ee18acSSandy Huang 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id);
1901d0408543SAndy Yan 
1902d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1903d0408543SAndy Yan 			STANDBY_EN_SHIFT, 0, false);
1904d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
1905d0408543SAndy Yan 
1906d0408543SAndy Yan 	return 0;
1907d0408543SAndy Yan }
1908d0408543SAndy Yan 
1909d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state)
1910d0408543SAndy Yan {
1911d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1912d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
191352ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
191452ee18acSSandy Huang 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id);
1915d0408543SAndy Yan 
1916d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1917d0408543SAndy Yan 			STANDBY_EN_SHIFT, 1, false);
1918d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
1919d0408543SAndy Yan 
1920d0408543SAndy Yan 	return 0;
1921d0408543SAndy Yan }
1922d0408543SAndy Yan 
1923ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane)
1924ee008497SSandy Huang {
1925ee008497SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
1926ee008497SSandy Huang 	struct vop2 *vop2 = cstate->private;
1927ee008497SSandy Huang 	int i = 0;
1928ee008497SSandy Huang 	int correct_cursor_plane = -1;
1929ee008497SSandy Huang 	int plane_type = -1;
1930ee008497SSandy Huang 
1931ee008497SSandy Huang 	if (cursor_plane < 0)
1932ee008497SSandy Huang 		return -1;
1933ee008497SSandy Huang 
1934ee008497SSandy Huang 	if (plane_mask & (1 << cursor_plane))
1935ee008497SSandy Huang 		return cursor_plane;
1936ee008497SSandy Huang 
1937ee008497SSandy Huang 	/* Get current cursor plane type */
1938ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
1939ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_id == cursor_plane) {
1940ee008497SSandy Huang 			plane_type = vop2->data->plane_table[i].plane_type;
1941ee008497SSandy Huang 			break;
1942ee008497SSandy Huang 		}
1943ee008497SSandy Huang 	}
1944ee008497SSandy Huang 
1945ee008497SSandy Huang 	/* Get the other same plane type plane id */
1946ee008497SSandy Huang 	for (i = 0; i < vop2->data->nr_layers; i++) {
1947ee008497SSandy Huang 		if (vop2->data->plane_table[i].plane_type == plane_type &&
1948ee008497SSandy Huang 		    vop2->data->plane_table[i].plane_id != cursor_plane) {
1949ee008497SSandy Huang 			correct_cursor_plane = vop2->data->plane_table[i].plane_id;
1950ee008497SSandy Huang 			break;
1951ee008497SSandy Huang 		}
1952ee008497SSandy Huang 	}
1953ee008497SSandy Huang 
1954ee008497SSandy Huang 	/* To check whether the new correct_cursor_plane is attach to current vp */
1955ee008497SSandy Huang 	if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) {
1956ee008497SSandy Huang 		printf("error: faild to find correct plane as cursor plane\n");
1957ee008497SSandy Huang 		return -1;
1958ee008497SSandy Huang 	}
1959ee008497SSandy Huang 
1960ee008497SSandy Huang 	printf("vp%d adjust cursor plane from %d to %d\n",
1961ee008497SSandy Huang 	       cstate->crtc_id, cursor_plane, correct_cursor_plane);
1962ee008497SSandy Huang 
1963ee008497SSandy Huang 	return correct_cursor_plane;
1964ee008497SSandy Huang }
1965ee008497SSandy Huang 
1966b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
1967b0989546SSandy Huang {
1968b0989546SSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
1969b0989546SSandy Huang 	struct vop2 *vop2 = cstate->private;
1970b0989546SSandy Huang 	ofnode vp_node;
1971b0989546SSandy Huang 	struct device_node *port_parent_node = cstate->ports_node;
1972b0989546SSandy Huang 	static bool vop_fix_dts;
1973b0989546SSandy Huang 	const char *path;
1974b0989546SSandy Huang 	u32 plane_mask = 0;
1975b0989546SSandy Huang 	int vp_id = 0;
1976ee008497SSandy Huang 	int cursor_plane_id = -1;
1977b0989546SSandy Huang 
1978b0989546SSandy Huang 	if (vop_fix_dts)
1979b0989546SSandy Huang 		return 0;
1980b0989546SSandy Huang 
1981b0989546SSandy Huang 	ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
1982b0989546SSandy Huang 		path = vp_node.np->full_name;
1983b0989546SSandy Huang 		plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
1984b0989546SSandy Huang 
19858b1fe597SSandy Huang 		if (cstate->crtc->assign_plane)
19868b1fe597SSandy Huang 			continue;
1987ee008497SSandy Huang 		cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask,
1988ee008497SSandy Huang 								 cstate->crtc->vps[vp_id].cursor_plane);
1989ee008497SSandy Huang 		printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
1990b0989546SSandy Huang 		       vp_id, plane_mask,
1991ee008497SSandy Huang 		       vop2->vp_plane_mask[vp_id].primary_plane_id,
1992ee008497SSandy Huang 		       cursor_plane_id);
1993b0989546SSandy Huang 
1994b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
1995b0989546SSandy Huang 				     plane_mask, 1);
1996b0989546SSandy Huang 		do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
1997b0989546SSandy Huang 				     vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
1998ee008497SSandy Huang 		if (cursor_plane_id >= 0)
1999ee008497SSandy Huang 			do_fixup_by_path_u32(blob, path, "cursor-win-id",
2000ee008497SSandy Huang 					     cursor_plane_id, 1);
2001b0989546SSandy Huang 		vp_id++;
2002b0989546SSandy Huang 	}
2003b0989546SSandy Huang 
2004b0989546SSandy Huang 	vop_fix_dts = true;
2005b0989546SSandy Huang 
2006b0989546SSandy Huang 	return 0;
2007b0989546SSandy Huang }
2008b0989546SSandy Huang 
2009ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = {
2010ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER},
2011ee008497SSandy Huang 	{ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER},
2012ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART0, ESMART_LAYER},
2013ee008497SSandy Huang 	{ROCKCHIP_VOP2_ESMART1, ESMART_LAYER},
2014ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
2015ee008497SSandy Huang 	{ROCKCHIP_VOP2_SMART0, SMART_LAYER},
2016ee008497SSandy Huang };
2017ee008497SSandy Huang 
2018b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
2019b0989546SSandy Huang 	{ /* one display policy */
2020b0989546SSandy Huang 		{/* main display */
2021b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
2022b0989546SSandy Huang 			.attached_layers_nr = 6,
2023b0989546SSandy Huang 			.attached_layers = {
2024b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
2025b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
2026b0989546SSandy Huang 				},
2027b0989546SSandy Huang 		},
2028b0989546SSandy Huang 		{/* second display */},
2029b0989546SSandy Huang 		{/* third  display */},
2030b0989546SSandy Huang 		{/* fourth display */},
2031b0989546SSandy Huang 	},
2032b0989546SSandy Huang 
2033b0989546SSandy Huang 	{ /* two display policy */
2034b0989546SSandy Huang 		{/* main display */
2035b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
2036b0989546SSandy Huang 			.attached_layers_nr = 3,
2037b0989546SSandy Huang 			.attached_layers = {
2038b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
2039b0989546SSandy Huang 				},
2040b0989546SSandy Huang 		},
2041b0989546SSandy Huang 
2042b0989546SSandy Huang 		{/* second display */
2043b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
2044b0989546SSandy Huang 			.attached_layers_nr = 3,
2045b0989546SSandy Huang 			.attached_layers = {
2046b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
2047b0989546SSandy Huang 				},
2048b0989546SSandy Huang 		},
2049b0989546SSandy Huang 		{/* third  display */},
2050b0989546SSandy Huang 		{/* fourth display */},
2051b0989546SSandy Huang 	},
2052b0989546SSandy Huang 
2053b0989546SSandy Huang 	{ /* three display policy */
2054b0989546SSandy Huang 		{/* main display */
2055b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART0,
2056b0989546SSandy Huang 			.attached_layers_nr = 3,
2057b0989546SSandy Huang 			.attached_layers = {
2058b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
2059b0989546SSandy Huang 				},
2060b0989546SSandy Huang 		},
2061b0989546SSandy Huang 
2062b0989546SSandy Huang 		{/* second display */
2063b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_SMART1,
2064b0989546SSandy Huang 			.attached_layers_nr = 2,
2065b0989546SSandy Huang 			.attached_layers = {
2066b0989546SSandy Huang 				  ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
2067b0989546SSandy Huang 				},
2068b0989546SSandy Huang 		},
2069b0989546SSandy Huang 
2070b0989546SSandy Huang 		{/* third  display */
2071b0989546SSandy Huang 			.primary_plane_id = ROCKCHIP_VOP2_ESMART1,
2072b0989546SSandy Huang 			.attached_layers_nr = 1,
2073b0989546SSandy Huang 			.attached_layers = { ROCKCHIP_VOP2_ESMART1 },
2074b0989546SSandy Huang 		},
2075b0989546SSandy Huang 
2076b0989546SSandy Huang 		{/* fourth display */},
2077b0989546SSandy Huang 	},
2078b0989546SSandy Huang 
2079b0989546SSandy Huang 	{/* reserved for four display policy */},
2080b0989546SSandy Huang };
2081b0989546SSandy Huang 
2082b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = {
2083b0989546SSandy Huang 	{
2084b0989546SSandy Huang 		.name = "Cluster0",
2085b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
2086b0989546SSandy Huang 		.win_sel_port_offset = 0,
2087b0989546SSandy Huang 		.layer_sel_win_id = 0,
2088b0989546SSandy Huang 		.reg_offset = 0,
2089b0989546SSandy Huang 	},
2090b0989546SSandy Huang 
2091b0989546SSandy Huang 	{
2092b0989546SSandy Huang 		.name = "Cluster1",
2093b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
2094b0989546SSandy Huang 		.win_sel_port_offset = 1,
2095b0989546SSandy Huang 		.layer_sel_win_id = 1,
2096b0989546SSandy Huang 		.reg_offset = 0x200,
2097b0989546SSandy Huang 	},
2098b0989546SSandy Huang 
2099b0989546SSandy Huang 	{
2100b0989546SSandy Huang 		.name = "Esmart0",
2101b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART0,
2102b0989546SSandy Huang 		.win_sel_port_offset = 4,
2103b0989546SSandy Huang 		.layer_sel_win_id = 2,
2104b0989546SSandy Huang 		.reg_offset = 0,
2105b0989546SSandy Huang 	},
2106b0989546SSandy Huang 
2107b0989546SSandy Huang 	{
2108b0989546SSandy Huang 		.name = "Esmart1",
2109b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_ESMART1,
2110b0989546SSandy Huang 		.win_sel_port_offset = 5,
2111b0989546SSandy Huang 		.layer_sel_win_id = 6,
2112b0989546SSandy Huang 		.reg_offset = 0x200,
2113b0989546SSandy Huang 	},
2114b0989546SSandy Huang 
2115b0989546SSandy Huang 	{
2116b0989546SSandy Huang 		.name = "Smart0",
2117b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART0,
2118b0989546SSandy Huang 		.win_sel_port_offset = 6,
2119b0989546SSandy Huang 		.layer_sel_win_id = 3,
2120b0989546SSandy Huang 		.reg_offset = 0x400,
2121b0989546SSandy Huang 	},
2122b0989546SSandy Huang 
2123b0989546SSandy Huang 	{
2124b0989546SSandy Huang 		.name = "Smart1",
2125b0989546SSandy Huang 		.phys_id = ROCKCHIP_VOP2_SMART1,
2126b0989546SSandy Huang 		.win_sel_port_offset = 7,
2127b0989546SSandy Huang 		.layer_sel_win_id = 7,
2128b0989546SSandy Huang 		.reg_offset = 0x600,
2129b0989546SSandy Huang 	},
2130b0989546SSandy Huang };
2131b0989546SSandy Huang 
213263cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = {
213363cb669fSSandy Huang 	{
213463cb669fSSandy Huang 		.feature = VOP_FEATURE_OUTPUT_10BIT,
213563cb669fSSandy Huang 		.pre_scan_max_dly = 42,
213663cb669fSSandy Huang 		.max_output = {4096, 2304},
2137d0408543SAndy Yan 	},
213863cb669fSSandy Huang 	{
213963cb669fSSandy Huang 		.feature = 0,
214063cb669fSSandy Huang 		.pre_scan_max_dly = 40,
214163cb669fSSandy Huang 		.max_output = {2048, 1536},
214263cb669fSSandy Huang 	},
214363cb669fSSandy Huang 	{
214463cb669fSSandy Huang 		.feature = 0,
214563cb669fSSandy Huang 		.pre_scan_max_dly = 40,
214663cb669fSSandy Huang 		.max_output = {1920, 1080},
214763cb669fSSandy Huang 	},
214863cb669fSSandy Huang };
2149d0408543SAndy Yan 
215063cb669fSSandy Huang const struct vop2_data rk3568_vop = {
215163cb669fSSandy Huang 	.nr_vps = 3,
215263cb669fSSandy Huang 	.vp_data = rk3568_vp_data,
2153b0989546SSandy Huang 	.win_data = rk3568_win_data,
2154b0989546SSandy Huang 	.plane_mask = rk356x_vp_plane_mask[0],
2155ee008497SSandy Huang 	.plane_table = rk356x_plane_table,
2156d0408543SAndy Yan 	.nr_layers = 6,
215763cb669fSSandy Huang 	.nr_mixers = 5,
21581147facaSSandy Huang 	.nr_gammas = 1,
2159d0408543SAndy Yan };
2160d0408543SAndy Yan 
2161d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
2162d0408543SAndy Yan 	.preinit = rockchip_vop2_preinit,
2163d0408543SAndy Yan 	.prepare = rockchip_vop2_prepare,
2164d0408543SAndy Yan 	.init = rockchip_vop2_init,
2165d0408543SAndy Yan 	.set_plane = rockchip_vop2_set_plane,
2166d0408543SAndy Yan 	.enable = rockchip_vop2_enable,
2167d0408543SAndy Yan 	.disable = rockchip_vop2_disable,
2168b0989546SSandy Huang 	.fixup_dts = rockchip_vop2_fixup_dts,
2169d0408543SAndy Yan };
2170