xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_vop2.c (revision feffd38e6d7f7ff7fb50564e9b9d39689b7bc4f9)
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>
13*feffd38eSSandy 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>
21d0408543SAndy Yan #include <dm/device.h>
22d0408543SAndy Yan #include <dm/read.h>
23d0408543SAndy Yan #include <syscon.h>
24d0408543SAndy Yan 
25d0408543SAndy Yan #include "rockchip_display.h"
26d0408543SAndy Yan #include "rockchip_crtc.h"
27d0408543SAndy Yan #include "rockchip_connector.h"
28d0408543SAndy Yan 
29d0408543SAndy Yan /* System registers definition */
30d0408543SAndy Yan #define RK3568_REG_CFG_DONE			0x000
31d0408543SAndy Yan #define	CFG_DONE_EN				BIT(15)
32d0408543SAndy Yan 
33d0408543SAndy Yan #define RK3568_VERSION_INFO			0x004
34d0408543SAndy Yan 
35d0408543SAndy Yan #define EN_MASK					1
36d0408543SAndy Yan 
37d0408543SAndy Yan #define RK3568_DSP_IF_EN			0x028
38d0408543SAndy Yan #define RGB_EN_SHIFT				0
39d0408543SAndy Yan #define HDMI0_EN_SHIFT				1
40d0408543SAndy Yan #define EDP0_EN_SHIFT				3
41d0408543SAndy Yan #define MIPI0_EN_SHIFT				4
42d0408543SAndy Yan #define MIPI1_EN_SHIFT				20
43d0408543SAndy Yan #define LVDS0_EN_SHIFT				5
44d0408543SAndy Yan #define LVDS1_EN_SHIFT				24
45d0408543SAndy Yan #define BT1120_EN_SHIFT				6
46d0408543SAndy Yan #define BT656_EN_SHIFT				7
47d0408543SAndy Yan #define IF_MUX_MASK				3
48d0408543SAndy Yan #define RGB_MUX_SHIFT				8
49d0408543SAndy Yan #define HDMI0_MUX_SHIFT				10
50d0408543SAndy Yan #define EDP0_MUX_SHIFT				14
51d0408543SAndy Yan #define MIPI0_MUX_SHIFT				16
52d0408543SAndy Yan #define MIPI1_MUX_SHIFT				21
5311f53190SSandy Huang #define LVDS0_MUX_SHIFT				18
54d0408543SAndy Yan #define LVDS1_MUX_SHIFT				25
55d0408543SAndy Yan 
56d0408543SAndy Yan #define RK3568_DSP_IF_CTRL			0x02c
57d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT			0
58d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT		1
59d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT			2
60d0408543SAndy Yan #define RK3568_DSP_IF_POL			0x030
61d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_MASK		1
62d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT		28
63d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT		19
64d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT		15
65d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT		7
6610ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK		0x7
6710ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT		4
68d0408543SAndy Yan #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT		3
69*feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN			0x50
70*feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT			0
71d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG			0x70
72d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG			0x74
73d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG			0x78
74d0408543SAndy Yan #define RK3568_SYS0_INT_EN			0x80
75d0408543SAndy Yan #define RK3568_SYS0_INT_CLR			0x84
76d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS			0x88
77d0408543SAndy Yan #define RK3568_SYS1_INT_EN			0x90
78d0408543SAndy Yan #define RK3568_SYS1_INT_CLR			0x94
79d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS			0x98
80d0408543SAndy Yan #define RK3568_VP0_INT_EN			0xA0
81d0408543SAndy Yan #define RK3568_VP0_INT_CLR			0xA4
82d0408543SAndy Yan #define RK3568_VP0_INT_STATUS			0xA8
83d0408543SAndy Yan #define RK3568_VP1_INT_EN			0xB0
84d0408543SAndy Yan #define RK3568_VP1_INT_CLR			0xB4
85d0408543SAndy Yan #define RK3568_VP1_INT_STATUS			0xB8
86d0408543SAndy Yan #define RK3568_VP2_INT_EN			0xC0
87d0408543SAndy Yan #define RK3568_VP2_INT_CLR			0xC4
88d0408543SAndy Yan #define RK3568_VP2_INT_STATUS			0xC8
89d0408543SAndy Yan 
90d0408543SAndy Yan /* Video Port registers definition */
91d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL				0xC00
92d0408543SAndy Yan #define OUT_MODE_MASK					0xf
93d0408543SAndy Yan #define OUT_MODE_SHIFT					0
9410ee9f5bSAlgea Cao #define DATA_SWAP_MASK					0x1f
9510ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT					8
9610ee9f5bSAlgea Cao #define DSP_RB_SWAP					2
9710ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT				4
98d0408543SAndy Yan #define P2I_EN_SHIFT					5
99d0408543SAndy Yan #define INTERLACE_EN_SHIFT				7
10010ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT				15
101d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT			16
102d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT				17
103d0408543SAndy Yan #define STANDBY_EN_SHIFT				31
104d0408543SAndy Yan 
105d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL				0xC04
10610ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT					4
10710ee9f5bSAlgea Cao #define DCLK_DIV2_MASK					0x3
108d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT				20
109d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT				21
110d0408543SAndy Yan 
111d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL			0xC08
112d0408543SAndy Yan #define RK3568_VP0_DSP_BG				0xC2C
113d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING			0xC30
114d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO			0xC34
115d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO			0xC38
116d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB			0xC3C
117d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL			0xC40
118d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1		0xC44
119d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END			0xC48
120d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END			0xC4C
121d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END			0xC50
122d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END			0xC54
123d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1			0xC58
124d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1			0xC5C
125d0408543SAndy Yan 
126d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL				0xD00
127d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL				0xD04
128d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL			0xD08
129d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING			0xD30
130d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO			0xD34
131d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO			0xD38
132d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB			0xD3C
133d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL			0xD40
134d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO			0xD34
135d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO			0xD38
136d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1		0xD44
137d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END			0xD48
138d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END			0xD4C
139d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END			0xD50
140d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END			0xD54
141d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1			0xD58
142d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1			0xD5C
143d0408543SAndy Yan 
144d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL				0xE00
145d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL				0xE04
146d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL			0xE08
147d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING			0xE30
148d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO			0xE34
149d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO			0xE38
150d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB			0xE3C
151d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL			0xE40
152d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO			0xE34
153d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO			0xE38
154d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1		0xE44
155d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END			0xE48
156d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END			0xE4C
157d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END			0xE50
158d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END			0xE54
159d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1			0xE58
160d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1			0xE5C
161d0408543SAndy Yan 
162d0408543SAndy Yan /* Overlay registers definition    */
163d0408543SAndy Yan #define RK3568_OVL_CTRL				0x600
164d0408543SAndy Yan #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT		28
165d0408543SAndy Yan #define RK3568_OVL_LAYER_SEL			0x604
166d0408543SAndy Yan #define LAYER_SEL_MASK				0xf
167d0408543SAndy Yan 
168d0408543SAndy Yan #define RK3568_OVL_PORT_SEL			0x608
169d0408543SAndy Yan #define PORT_MUX_MASK				0xf
170d0408543SAndy Yan #define PORT_MUX_SHIFT				0
171d0408543SAndy Yan #define LAYER_SEL_PORT_MASK			0x3
172d0408543SAndy Yan #define LAYER_SEL_PORT_SHIFT			24
173d0408543SAndy Yan 
174d0408543SAndy Yan #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
175d0408543SAndy Yan #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
176d0408543SAndy Yan #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
177d0408543SAndy Yan #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
178d0408543SAndy Yan #define RK3568_MIX0_SRC_COLOR_CTRL		0x650
179d0408543SAndy Yan #define RK3568_MIX0_DST_COLOR_CTRL		0x654
180d0408543SAndy Yan #define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
181d0408543SAndy Yan #define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
182d0408543SAndy Yan #define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
183d0408543SAndy Yan #define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
184d0408543SAndy Yan #define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
185d0408543SAndy Yan #define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
186d0408543SAndy Yan #define RK3568_VP0_BG_MIX_CTRL			0x6E0
187d0408543SAndy Yan #define RK3568_VP1_BG_MIX_CTRL			0x6E4
188d0408543SAndy Yan #define RK3568_VP2_BG_MIX_CTRL			0x6E8
189d0408543SAndy Yan #define RK3568_CLUSTER_DLY_NUM			0x6F0
190d0408543SAndy Yan #define RK3568_SMART_DLY_NUM			0x6F8
191d0408543SAndy Yan 
192d0408543SAndy Yan /* Cluster0 register definition */
193d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0		0x1000
194d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1		0x1004
195d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST		0x1010
196d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST		0x1014
197d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR		0x1018
198d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO		0x1020
199d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO		0x1024
200d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST		0x1028
201d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB	0x1030
202d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE	0x1054
203d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR	0x1058
204d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH	0x105C
205d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE	0x1060
206d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET	0x1064
207d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET	0x1068
208d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL		0x106C
209d0408543SAndy Yan 
210d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0		0x1080
211d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1		0x1084
212d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST		0x1090
213d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST		0x1094
214d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR		0x1098
215d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO		0x10A0
216d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO		0x10A4
217d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST		0x10A8
218d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB	0x10B0
219d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE	0x10D4
220d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR	0x10D8
221d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH	0x10DC
222d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE	0x10E0
223d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET	0x10E4
224d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET	0x10E8
225d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL		0x10EC
226d0408543SAndy Yan 
227d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL			0x1100
228d0408543SAndy Yan 
229d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0		0x1200
230d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1		0x1204
231d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST		0x1210
232d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST		0x1214
233d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR		0x1218
234d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO		0x1220
235d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO		0x1224
236d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST		0x1228
237d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB	0x1230
238d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE	0x1254
239d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR	0x1258
240d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH	0x125C
241d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE	0x1260
242d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET	0x1264
243d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET	0x1268
244d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL		0x126C
245d0408543SAndy Yan 
246d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0		0x1280
247d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1		0x1284
248d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST		0x1290
249d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST		0x1294
250d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR		0x1298
251d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO		0x12A0
252d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO		0x12A4
253d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST		0x12A8
254d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB	0x12B0
255d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE	0x12D4
256d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR	0x12D8
257d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH	0x12DC
258d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE	0x12E0
259d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET	0x12E4
260d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET	0x12E8
261d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL		0x12EC
262d0408543SAndy Yan 
263d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL			0x1300
264d0408543SAndy Yan 
265d0408543SAndy Yan /* Esmart register definition */
266d0408543SAndy Yan #define RK3568_ESMART0_CTRL0			0x1800
26710ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT			1
26810ee9f5bSAlgea Cao #define CSC_MODE_SHIFT				2
26910ee9f5bSAlgea Cao #define CSC_MODE_MASK				0x3
270d0408543SAndy Yan 
271d0408543SAndy Yan #define RK3568_ESMART0_CTRL1			0x1804
272d0408543SAndy Yan #define YMIRROR_EN_SHIFT			31
273d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL		0x1810
27410ee9f5bSAlgea Cao #define REGION0_RB_SWAP_SHIFT			14
275d0408543SAndy Yan #define WIN_EN_SHIFT				0
276d0408543SAndy Yan #define WIN_FORMAT_MASK				0x1f
277d0408543SAndy Yan #define WIN_FORMAT_SHIFT			1
278d0408543SAndy Yan 
279d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST		0x1814
280d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST		0x1818
281d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR		0x181C
282d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO		0x1820
283d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO		0x1824
284d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST		0x1828
285d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL		0x1830
286d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB	0x1834
287d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR	0x1838
288d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET	0x183C
289d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL		0x1840
290d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST		0x1844
291d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST		0x1848
292d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR		0x184C
293d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO		0x1850
294d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO		0x1854
295d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST		0x1858
296d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL		0x1860
297d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB	0x1864
298d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR	0x1868
299d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET	0x186C
300d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL		0x1870
301d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST		0x1874
302d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST		0x1878
303d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR		0x187C
304d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO		0x1880
305d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO		0x1884
306d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST		0x1888
307d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL		0x1890
308d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB	0x1894
309d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR	0x1898
310d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET	0x189C
311d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL		0x18A0
312d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST		0x18A4
313d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST		0x18A8
314d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR		0x18AC
315d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO		0x18B0
316d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO		0x18B4
317d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST		0x18B8
318d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL		0x18C0
319d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB	0x18C4
320d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR	0x18C8
321d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET	0x18CC
322d0408543SAndy Yan 
323d0408543SAndy Yan #define RK3568_ESMART1_CTRL0			0x1A00
324d0408543SAndy Yan #define RK3568_ESMART1_CTRL1			0x1A04
325d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL		0x1A10
326d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST		0x1A14
327d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST		0x1A18
328d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR		0x1A1C
329d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO		0x1A20
330d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO		0x1A24
331d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST		0x1A28
332d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL		0x1A30
333d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB	0x1A34
334d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR	0x1A38
335d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET	0x1A3C
336d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL		0x1A40
337d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST		0x1A44
338d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST		0x1A48
339d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR		0x1A4C
340d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO		0x1A50
341d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO		0x1A54
342d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST		0x1A58
343d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL		0x1A60
344d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB	0x1A64
345d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR	0x1A68
346d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET	0x1A6C
347d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL		0x1A70
348d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST		0x1A74
349d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST		0x1A78
350d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR		0x1A7C
351d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO		0x1A80
352d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO		0x1A84
353d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST		0x1A88
354d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL		0x1A90
355d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB	0x1A94
356d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR	0x1A98
357d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET	0x1A9C
358d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL		0x1AA0
359d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST		0x1AA4
360d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST		0x1AA8
361d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR		0x1AAC
362d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO		0x1AB0
363d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO		0x1AB4
364d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST		0x1AB8
365d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL		0x1AC0
366d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB	0x1AC4
367d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR	0x1AC8
368d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET	0x1ACC
369d0408543SAndy Yan 
370d0408543SAndy Yan #define RK3568_SMART0_CTRL0			0x1C00
371d0408543SAndy Yan #define RK3568_SMART0_CTRL1			0x1C04
372d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL		0x1C10
373d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST		0x1C14
374d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST		0x1C18
375d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR		0x1C1C
376d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO		0x1C20
377d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO		0x1C24
378d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST		0x1C28
379d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL		0x1C30
380d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB	0x1C34
381d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR	0x1C38
382d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET	0x1C3C
383d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL		0x1C40
384d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST		0x1C44
385d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST		0x1C48
386d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR		0x1C4C
387d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO		0x1C50
388d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO		0x1C54
389d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST		0x1C58
390d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL		0x1C60
391d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB	0x1C64
392d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR	0x1C68
393d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET	0x1C6C
394d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL		0x1C70
395d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST		0x1C74
396d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST		0x1C78
397d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR		0x1C7C
398d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO		0x1C80
399d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO		0x1C84
400d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST		0x1C88
401d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL		0x1C90
402d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB	0x1C94
403d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR	0x1C98
404d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET	0x1C9C
405d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL		0x1CA0
406d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST		0x1CA4
407d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST		0x1CA8
408d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR		0x1CAC
409d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO		0x1CB0
410d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO		0x1CB4
411d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST		0x1CB8
412d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL		0x1CC0
413d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB	0x1CC4
414d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR	0x1CC8
415d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET	0x1CCC
416d0408543SAndy Yan 
417d0408543SAndy Yan #define RK3568_SMART1_CTRL0			0x1E00
418d0408543SAndy Yan #define RK3568_SMART1_CTRL1			0x1E04
419d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL		0x1E10
420d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST		0x1E14
421d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST		0x1E18
422d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR		0x1E1C
423d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO		0x1E20
424d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO		0x1E24
425d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST		0x1E28
426d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL		0x1E30
427d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB	0x1E34
428d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR	0x1E38
429d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET	0x1E3C
430d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL		0x1E40
431d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST		0x1E44
432d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST		0x1E48
433d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR		0x1E4C
434d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO		0x1E50
435d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO		0x1E54
436d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST		0x1E58
437d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL		0x1E60
438d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB	0x1E64
439d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR	0x1E68
440d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET	0x1E6C
441d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL		0x1E70
442d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST		0x1E74
443d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST		0x1E78
444d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR		0x1E7C
445d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO		0x1E80
446d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO		0x1E84
447d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST		0x1E88
448d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL		0x1E90
449d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB	0x1E94
450d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR	0x1E98
451d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET	0x1E9C
452d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL		0x1EA0
453d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST		0x1EA4
454d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST		0x1EA8
455d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR		0x1EAC
456d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO		0x1EB0
457d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO		0x1EB4
458d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST		0x1EB8
459d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL		0x1EC0
460d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB	0x1EC4
461d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR	0x1EC8
462d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET	0x1ECC
463d0408543SAndy Yan 
464d0408543SAndy Yan #define RK3568_MAX_REG				0x1ED0
465d0408543SAndy Yan 
46652ee18acSSandy Huang #define RK3568_GRF_VO_CON1			0x0364
46752ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT			1
46852ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT		2
46952ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT			3
47052ee18acSSandy Huang 
471d0408543SAndy Yan #define VOP2_LAYER_MAX				8
472d0408543SAndy Yan #define VOP2_MAX_VP				4
473d0408543SAndy Yan 
47410ee9f5bSAlgea Cao enum vop2_csc_format {
47510ee9f5bSAlgea Cao 	CSC_BT601L,
47610ee9f5bSAlgea Cao 	CSC_BT709L,
47710ee9f5bSAlgea Cao 	CSC_BT601F,
47810ee9f5bSAlgea Cao 	CSC_BT2020,
47910ee9f5bSAlgea Cao };
48010ee9f5bSAlgea Cao 
48110ee9f5bSAlgea Cao enum vop2_pol {
48210ee9f5bSAlgea Cao 	HSYNC_POSITIVE = 0,
48310ee9f5bSAlgea Cao 	VSYNC_POSITIVE = 1,
48410ee9f5bSAlgea Cao 	DEN_NEGATIVE   = 2,
48510ee9f5bSAlgea Cao 	DCLK_INVERT    = 3
48610ee9f5bSAlgea Cao };
48710ee9f5bSAlgea Cao 
488d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \
489d0408543SAndy Yan 		{ \
490d0408543SAndy Yan 		 .offset = off, \
491d0408543SAndy Yan 		 .mask = _mask, \
492d0408543SAndy Yan 		 .shift = _shift, \
493d0408543SAndy Yan 		 .write_mask = _write_mask, \
494d0408543SAndy Yan 		}
495d0408543SAndy Yan 
496d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \
497d0408543SAndy Yan 		_VOP_REG(off, _mask, _shift, false)
498d0408543SAndy Yan enum dither_down_mode {
499d0408543SAndy Yan 	RGB888_TO_RGB565 = 0x0,
500d0408543SAndy Yan 	RGB888_TO_RGB666 = 0x1
501d0408543SAndy Yan };
502d0408543SAndy Yan 
503d0408543SAndy Yan enum vop2_video_ports_id {
504d0408543SAndy Yan 	VOP2_VP0,
505d0408543SAndy Yan 	VOP2_VP1,
506d0408543SAndy Yan 	VOP2_VP2,
507d0408543SAndy Yan 	VOP2_VP3,
508d0408543SAndy Yan 	VOP2_VP_MAX,
509d0408543SAndy Yan };
510d0408543SAndy Yan 
511d0408543SAndy Yan struct vop2_layer {
512d0408543SAndy Yan 	uint8_t id;
513d0408543SAndy Yan 	/**
514d0408543SAndy Yan 	 * @win_phys_id: window id of the layer selected.
515d0408543SAndy Yan 	 * Every layer must make sure to select different
516d0408543SAndy Yan 	 * windows of others.
517d0408543SAndy Yan 	 */
518d0408543SAndy Yan 	uint8_t win_phys_id;
519d0408543SAndy Yan };
520d0408543SAndy Yan 
521d0408543SAndy Yan struct vop2_win {
522d0408543SAndy Yan 	uint8_t id;
523d0408543SAndy Yan 	uint8_t layer_id;
524d0408543SAndy Yan 	uint8_t phys_id;
525d0408543SAndy Yan };
526d0408543SAndy Yan 
527d0408543SAndy Yan struct vop2_data {
52852ee18acSSandy Huang 	u32 version;
529d0408543SAndy Yan 	struct vop_rect max_output[VOP2_MAX_VP];
530d0408543SAndy Yan 	/**
531d0408543SAndy Yan 	 * win_id: id of window attach to VP0,VP1,VP2,VP3,
532d0408543SAndy Yan 	 * Only support one window for one VP in u-boot.
533d0408543SAndy Yan 	 *
534d0408543SAndy Yan 	 */
535d0408543SAndy Yan 	uint8_t win_id[VOP2_MAX_VP];
536d0408543SAndy Yan 	uint8_t nr_vps;
537d0408543SAndy Yan 	uint8_t nr_layers;
538d0408543SAndy Yan 	/**
539d0408543SAndy Yan 	 * win_sel_id: from register LAYER_SEL
540d0408543SAndy Yan 	 *
541d0408543SAndy Yan 	 */
542d0408543SAndy Yan 	uint8_t win_sel_id[VOP2_LAYER_MAX];
543d0408543SAndy Yan };
544d0408543SAndy Yan 
545d0408543SAndy Yan struct vop2 {
546d0408543SAndy Yan 	u32 *regsbak;
547d0408543SAndy Yan 	void *regs;
548d0408543SAndy Yan 	void *grf;
54952ee18acSSandy Huang 	u32 reg_len;
55052ee18acSSandy Huang 	u32 version;
551d0408543SAndy Yan 	const struct vop2_data *data;
552d0408543SAndy Yan 	/**
553d0408543SAndy Yan 	 * @nr_wins: active wins attached to the video port
554d0408543SAndy Yan 	 */
555d0408543SAndy Yan 	uint8_t nr_wins[VOP2_VP_MAX];
556d0408543SAndy Yan 	struct vop2_win win[VOP2_LAYER_MAX];
557d0408543SAndy Yan 	struct vop2_layer layer[VOP2_LAYER_MAX];
558d0408543SAndy Yan };
559d0408543SAndy Yan 
560d0408543SAndy Yan static struct vop2 *rockchip_vop2;
561d0408543SAndy Yan static void vop2_setup_win_for_vp(struct display_state *state);
562d0408543SAndy Yan 
563d0408543SAndy Yan static inline uint16_t scl_cal_scale(int src, int dst, int shift)
564d0408543SAndy Yan {
565d0408543SAndy Yan 	return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
566d0408543SAndy Yan }
567d0408543SAndy Yan 
568d0408543SAndy Yan static inline uint16_t scl_cal_scale2(int src, int dst)
569d0408543SAndy Yan {
570d0408543SAndy Yan 	return ((src - 1) << 12) / (dst - 1);
571d0408543SAndy Yan }
572d0408543SAndy Yan 
57352ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
574d0408543SAndy Yan {
575d0408543SAndy Yan 	writel(v, vop2->regs + offset);
576d0408543SAndy Yan 	vop2->regsbak[offset >> 2] = v;
577d0408543SAndy Yan }
578d0408543SAndy Yan 
57952ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
580d0408543SAndy Yan {
581d0408543SAndy Yan 	return readl(vop2->regs + offset);
582d0408543SAndy Yan }
583d0408543SAndy Yan 
58452ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
58552ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v,
586d0408543SAndy Yan 				   bool write_mask)
587d0408543SAndy Yan {
588d0408543SAndy Yan 	if (!mask)
589d0408543SAndy Yan 		return;
590d0408543SAndy Yan 
591d0408543SAndy Yan 	if (write_mask) {
592d0408543SAndy Yan 		v = ((v & mask) << shift) | (mask << (shift + 16));
593d0408543SAndy Yan 	} else {
59452ee18acSSandy Huang 		u32 cached_val = vop2->regsbak[offset >> 2];
595d0408543SAndy Yan 
596d0408543SAndy Yan 		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
597d0408543SAndy Yan 		vop2->regsbak[offset >> 2] = v;
598d0408543SAndy Yan 	}
599d0408543SAndy Yan 
600d0408543SAndy Yan 	writel(v, vop2->regs + offset);
601d0408543SAndy Yan }
602d0408543SAndy Yan 
60352ee18acSSandy Huang static inline void vop2_grf_writel(struct vop2 *vop, u32 offset,
60452ee18acSSandy Huang 				   u32 mask, u32 shift, u32 v)
60552ee18acSSandy Huang {
60652ee18acSSandy Huang 	u32 val = 0;
60752ee18acSSandy Huang 
60852ee18acSSandy Huang 	val = (v << shift) | (mask << (shift + 16));
60952ee18acSSandy Huang 	writel(val, vop->grf + offset);
61052ee18acSSandy Huang }
61152ee18acSSandy Huang 
612d0408543SAndy Yan static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
613d0408543SAndy Yan {
614d0408543SAndy Yan 	return us * mode->clock / mode->htotal / 1000;
615d0408543SAndy Yan }
616d0408543SAndy Yan 
61752ee18acSSandy Huang static bool is_yuv_output(u32 bus_format)
618d0408543SAndy Yan {
619d0408543SAndy Yan 	switch (bus_format) {
620d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
621d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
622d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
623d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
624d0408543SAndy Yan 		return true;
625d0408543SAndy Yan 	default:
626d0408543SAndy Yan 		return false;
627d0408543SAndy Yan 	}
628d0408543SAndy Yan }
629d0408543SAndy Yan 
63010ee9f5bSAlgea Cao static int vop2_convert_csc_mode(int csc_mode)
63110ee9f5bSAlgea Cao {
63210ee9f5bSAlgea Cao 	switch (csc_mode) {
63310ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_SMPTE170M:
63410ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_470_SYSTEM_M:
63510ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_470_SYSTEM_BG:
63610ee9f5bSAlgea Cao 		return CSC_BT601L;
63710ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_REC709:
63810ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_SMPTE240M:
63910ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_DEFAULT:
64010ee9f5bSAlgea Cao 		return CSC_BT709L;
64110ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_JPEG:
64210ee9f5bSAlgea Cao 		return CSC_BT601F;
64310ee9f5bSAlgea Cao 	case V4L2_COLORSPACE_BT2020:
64410ee9f5bSAlgea Cao 		return CSC_BT2020;
64510ee9f5bSAlgea Cao 	default:
64610ee9f5bSAlgea Cao 		return CSC_BT709L;
64710ee9f5bSAlgea Cao 	}
64810ee9f5bSAlgea Cao }
64910ee9f5bSAlgea Cao 
65052ee18acSSandy Huang static __maybe_unused bool is_uv_swap(u32 bus_format, u32 output_mode)
651d0408543SAndy Yan {
652d0408543SAndy Yan 	/*
653d0408543SAndy Yan 	 * FIXME:
654d0408543SAndy Yan 	 *
655d0408543SAndy Yan 	 * There is no media type for YUV444 output,
656d0408543SAndy Yan 	 * so when out_mode is AAAA or P888, assume output is YUV444 on
657d0408543SAndy Yan 	 * yuv format.
658d0408543SAndy Yan 	 *
659d0408543SAndy Yan 	 * From H/W testing, YUV444 mode need a rb swap.
660d0408543SAndy Yan 	 */
661d0408543SAndy Yan 	if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
662d0408543SAndy Yan 	     bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
663d0408543SAndy Yan 	    (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
664d0408543SAndy Yan 	     output_mode == ROCKCHIP_OUT_MODE_P888))
665d0408543SAndy Yan 		return true;
666d0408543SAndy Yan 	else
667d0408543SAndy Yan 		return false;
668d0408543SAndy Yan }
669d0408543SAndy Yan 
670d0408543SAndy Yan static int rockchip_vop2_init_gamma(struct vop2 *vop2,
671d0408543SAndy Yan 				    struct display_state *state)
672d0408543SAndy Yan {
673d0408543SAndy Yan 	return 0;
674d0408543SAndy Yan }
675d0408543SAndy Yan 
676d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
677d0408543SAndy Yan {
678d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
679d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
68052ee18acSSandy Huang 	struct crtc_state *cstate = &state->crtc_state;
68152ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
682d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
683d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
684d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
685d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
686d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
687d0408543SAndy Yan 	u16 hsize =
688d0408543SAndy Yan 	    hdisplay * (conn_state->overscan.left_margin +
689d0408543SAndy Yan 			conn_state->overscan.right_margin) / 200;
690d0408543SAndy Yan 	u16 vsize =
691d0408543SAndy Yan 	    vdisplay * (conn_state->overscan.top_margin +
692d0408543SAndy Yan 			conn_state->overscan.bottom_margin) / 200;
693d0408543SAndy Yan 	u16 hact_end, vact_end;
694d0408543SAndy Yan 	u32 val;
6952b2e3d70SSandy Huang 	u16 nr_mixers = 5, used_layer = 2, pre_scan_max_dly;
696d0408543SAndy Yan 	u32 bg_ovl_dly, bg_dly, pre_scan_dly;
697d0408543SAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
698d0408543SAndy Yan 
6992b2e3d70SSandy Huang 	if (cstate->crtc_id == 0)
7002b2e3d70SSandy Huang 		pre_scan_max_dly = 69;
7012b2e3d70SSandy Huang 	else
7022b2e3d70SSandy Huang 		pre_scan_max_dly = 40;
7032b2e3d70SSandy Huang 
704d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
705d0408543SAndy Yan 		vsize = round_down(vsize, 2);
706d0408543SAndy Yan 
707d0408543SAndy Yan 	hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
708d0408543SAndy Yan 	hact_end = hact_st + hsize;
709d0408543SAndy Yan 	val = hact_st << 16;
710d0408543SAndy Yan 	val |= hact_end;
711d0408543SAndy Yan 
71252ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
713d0408543SAndy Yan 	vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
714d0408543SAndy Yan 	vact_end = vact_st + vsize;
715d0408543SAndy Yan 	val = vact_st << 16;
716d0408543SAndy Yan 	val |= vact_end;
71752ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
718d0408543SAndy Yan 	val = scl_cal_scale2(vdisplay, vsize) << 16;
719d0408543SAndy Yan 	val |= scl_cal_scale2(hdisplay, hsize);
72052ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
721d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
722d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
72352ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
724d0408543SAndy Yan 		    POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
725d0408543SAndy Yan 		    POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
726d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
727d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
728d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vsize;
729d0408543SAndy Yan 
730d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
73152ee18acSSandy Huang 		vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
732d0408543SAndy Yan 	}
733d0408543SAndy Yan 
734d0408543SAndy Yan 	bg_ovl_dly = (nr_mixers - used_layer) << 1;
735d0408543SAndy Yan 	bg_dly = pre_scan_max_dly - bg_ovl_dly;
736d0408543SAndy Yan 	pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
737d0408543SAndy Yan 	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
73852ee18acSSandy Huang 	vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + vp_offset, pre_scan_dly);
739d0408543SAndy Yan }
740d0408543SAndy Yan 
741d0408543SAndy Yan static void vop2_layer_map_initial(struct vop2 *vop2)
742d0408543SAndy Yan {
743d0408543SAndy Yan 	struct vop2_layer *layer;
744d0408543SAndy Yan 	struct vop2_win *win;
74552ee18acSSandy Huang 	u32 layer_map, sel;
746d0408543SAndy Yan 	int i, j;
747d0408543SAndy Yan 
748d0408543SAndy Yan 	layer_map = vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
749d0408543SAndy Yan 
750d0408543SAndy Yan 	for (i = 0; i < vop2->data->nr_layers; i++) {
751d0408543SAndy Yan 		sel = (layer_map >> (4 * i)) & 0xf;
752d0408543SAndy Yan 		layer = &vop2->layer[i];
753d0408543SAndy Yan 		win = NULL;
754d0408543SAndy Yan 		for (j = 0; j < vop2->data->nr_layers; j++) {
755d0408543SAndy Yan 			if (sel == vop2->data->win_sel_id[j]) {
756d0408543SAndy Yan 				win = &vop2->win[j];
757d0408543SAndy Yan 				break;
758d0408543SAndy Yan 			}
759d0408543SAndy Yan 		}
760d0408543SAndy Yan 
761d0408543SAndy Yan 		if (!win) {
762d0408543SAndy Yan 			printf("invalid layer map :0x%x\n", layer_map);
763d0408543SAndy Yan 			return;
764d0408543SAndy Yan 		}
765d0408543SAndy Yan 
766d0408543SAndy Yan 		layer->win_phys_id = j;
767d0408543SAndy Yan 		win->layer_id = i;
768d0408543SAndy Yan 		debug("layer%d select %d\n", i, j);
769d0408543SAndy Yan 	}
770d0408543SAndy Yan }
771d0408543SAndy Yan 
772d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state)
773d0408543SAndy Yan {
774d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
775d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
776d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
777d0408543SAndy Yan 	char dclk_name[9];
778d0408543SAndy Yan 	struct clk dclk;
779d0408543SAndy Yan 	uint8_t shift = 0;
780d0408543SAndy Yan 	int i, ret;
781d0408543SAndy Yan 
782d0408543SAndy Yan 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
783d0408543SAndy Yan 	ret = clk_set_defaults(cstate->dev);
784d0408543SAndy Yan 	if (ret)
785d0408543SAndy Yan 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
786d0408543SAndy Yan 	snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
787d0408543SAndy Yan 	ret = clk_get_by_name(cstate->dev, dclk_name, &dclk);
788d0408543SAndy Yan 	if (!ret)
789d0408543SAndy Yan 		ret = clk_set_rate(&dclk, mode->clock * 1000);
790d0408543SAndy Yan 
791d0408543SAndy Yan 	if (IS_ERR_VALUE(ret)) {
792d0408543SAndy Yan 		printf("%s: Failed to set dclk: ret=%d\n", __func__, ret);
793d0408543SAndy Yan 		return ret;
794d0408543SAndy Yan 	}
795d0408543SAndy Yan 
796*feffd38eSSandy Huang 	if (soc_is_rk3566())
797*feffd38eSSandy Huang 		vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
798*feffd38eSSandy Huang 				OTP_WIN_EN_SHIFT, 1, false);
799d0408543SAndy Yan 	memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
800d0408543SAndy Yan 
801d0408543SAndy Yan 	rockchip_vop2_init_gamma(vop2, state);
802d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
803d0408543SAndy Yan 			OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
804d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
805d0408543SAndy Yan 			IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
806d0408543SAndy Yan 	for (i = 0; i < vop2->data->nr_vps - 1; i++) {
807d0408543SAndy Yan 		shift = i * 4;
808d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, PORT_MUX_SHIFT + shift, 8, false);	//todo
809d0408543SAndy Yan 	}
810d0408543SAndy Yan 
811d0408543SAndy Yan 	vop2_layer_map_initial(vop2);
812d0408543SAndy Yan 
813d0408543SAndy Yan 	return 0;
814d0408543SAndy Yan }
815d0408543SAndy Yan 
816d0408543SAndy Yan /*
817d0408543SAndy Yan  * VOP2 have multi video ports.
818d0408543SAndy Yan  * video port ------- crtc
819d0408543SAndy Yan  */
820d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state)
821d0408543SAndy Yan {
822d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
823d0408543SAndy Yan 	const struct vop2_data *vop2_data = cstate->crtc->data;
824d0408543SAndy Yan 
825d0408543SAndy Yan 	if (!rockchip_vop2) {
826d0408543SAndy Yan 		rockchip_vop2 = malloc(sizeof(struct vop2));
827d0408543SAndy Yan 		if (!rockchip_vop2)
828d0408543SAndy Yan 			return -ENOMEM;
829d0408543SAndy Yan 		rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
830d0408543SAndy Yan 		rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
831d0408543SAndy Yan 		rockchip_vop2->reg_len = RK3568_MAX_REG;
832d0408543SAndy Yan 		rockchip_vop2->grf =
833d0408543SAndy Yan 		    syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
834d0408543SAndy Yan 		if (rockchip_vop2->grf <= 0)
835d0408543SAndy Yan 			printf("%s: Get syscon grf failed (ret=%p)\n", __func__,
836d0408543SAndy Yan 			       rockchip_vop2->grf);
837d0408543SAndy Yan 
838d0408543SAndy Yan 		rockchip_vop2->version = vop2_data->version;
839d0408543SAndy Yan 		rockchip_vop2->data = vop2_data;
840d0408543SAndy Yan 	}
841d0408543SAndy Yan 
842d0408543SAndy Yan 	cstate->private = rockchip_vop2;
843d0408543SAndy Yan 	cstate->max_output = vop2_data->max_output[cstate->crtc_id];
844d0408543SAndy Yan 
845d0408543SAndy Yan 	return 0;
846d0408543SAndy Yan }
847d0408543SAndy Yan 
848d0408543SAndy Yan static int rockchip_vop2_init(struct display_state *state)
849d0408543SAndy Yan {
850d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
851d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
852d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
853d0408543SAndy Yan 	//const struct rockchip_crtc *crtc = cstate->crtc;
854d0408543SAndy Yan 	//const struct vop2_data *vop2_data = crtc->data;
855d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
856d0408543SAndy Yan 	u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
857d0408543SAndy Yan 	u16 hdisplay = mode->crtc_hdisplay;
858d0408543SAndy Yan 	u16 htotal = mode->crtc_htotal;
859d0408543SAndy Yan 	u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
860d0408543SAndy Yan 	u16 hact_end = hact_st + hdisplay;
861d0408543SAndy Yan 	u16 vdisplay = mode->crtc_vdisplay;
862d0408543SAndy Yan 	u16 vtotal = mode->crtc_vtotal;
863d0408543SAndy Yan 	u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
864d0408543SAndy Yan 	u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
865d0408543SAndy Yan 	u16 vact_end = vact_st + vdisplay;
866d0408543SAndy Yan 	bool yuv_overlay = false;
867d0408543SAndy Yan 	//bool yuv_overlay = false, post_r2y_en = false, post_y2r_en = false;
86852ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
869d0408543SAndy Yan 	//struct clk dclk;
870d0408543SAndy Yan 	//fdt_size_t len;
871d0408543SAndy Yan 	u32 val;
872d0408543SAndy Yan 	//int ret;
873d0408543SAndy Yan 	bool dclk_inv;
874d0408543SAndy Yan 	uint8_t dither_down_en = 0;
875d0408543SAndy Yan 	uint8_t pre_dither_down_en = 0;
876d0408543SAndy Yan 	//uint8_t dither_down_mode = RGB888_TO_RGB666;
877d0408543SAndy Yan 
878d0408543SAndy Yan 	vop2_initial(vop2, state);
879d0408543SAndy Yan 	dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1;
88010ee9f5bSAlgea Cao 	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
88110ee9f5bSAlgea Cao 	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
882d0408543SAndy Yan 
883d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
884d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
885d0408543SAndy Yan 				1, false);
886d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
887d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
888d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
889d0408543SAndy Yan 				IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, !!dclk_inv,
890d0408543SAndy Yan 				false);
89152ee18acSSandy Huang 		vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK,
89252ee18acSSandy Huang 				GRF_RGB_DCLK_INV_SHIFT, !dclk_inv);
893d0408543SAndy Yan 	}
894d0408543SAndy Yan 
895d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
89652ee18acSSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
89752ee18acSSandy Huang 				1, false);
898d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
899d0408543SAndy Yan 				BT1120_EN_SHIFT, 1, false);
900d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
901d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
90252ee18acSSandy Huang 		vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK,
90352ee18acSSandy Huang 				GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
904d0408543SAndy Yan 	}
905d0408543SAndy Yan 
906d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
907d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
908d0408543SAndy Yan 				1, false);
909d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
910d0408543SAndy Yan 				RGB_MUX_SHIFT, cstate->crtc_id, false);
91152ee18acSSandy Huang 		vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK,
91252ee18acSSandy Huang 				GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
913d0408543SAndy Yan 	}
914d0408543SAndy Yan 
915d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
916d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
917d0408543SAndy Yan 				1, false);
918d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
919d0408543SAndy Yan 				LVDS0_MUX_SHIFT, cstate->crtc_id, false);
92011f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
92111f53190SSandy Huang 				IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false);
922d0408543SAndy Yan 	}
923d0408543SAndy Yan 
924d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
925d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
926d0408543SAndy Yan 				1, false);
927d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
928d0408543SAndy Yan 				LVDS1_MUX_SHIFT, cstate->crtc_id, false);
92911f53190SSandy Huang 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
93011f53190SSandy Huang 				IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false);
931d0408543SAndy Yan 	}
932d0408543SAndy Yan 
933d0408543SAndy Yan 	if (conn_state->output_flags &
934d0408543SAndy Yan 	    (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE |
935d0408543SAndy Yan 	     ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) {
936d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
937d0408543SAndy Yan 				LVDS_DUAL_EN_SHIFT, 1, false);
938d0408543SAndy Yan 		if (conn_state->output_flags &
939d0408543SAndy Yan 		    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
940d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
941d0408543SAndy Yan 					LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1,
942d0408543SAndy Yan 					false);
943d0408543SAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
944d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
945d0408543SAndy Yan 					LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
946d0408543SAndy Yan 	}
947d0408543SAndy Yan 
948d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
949d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
950d0408543SAndy Yan 				1, false);
951d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
952d0408543SAndy Yan 				MIPI0_MUX_SHIFT, cstate->crtc_id, false);
953d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
954d0408543SAndy Yan 				IF_CRTL_MIPI_DCLK_POL_SHIT, ! !dclk_inv, false);
955d0408543SAndy Yan 	}
956d0408543SAndy Yan 
957d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
958d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
959d0408543SAndy Yan 				1, false);
960d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
961d0408543SAndy Yan 				MIPI1_MUX_SHIFT, cstate->crtc_id, false);
962d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
963d0408543SAndy Yan 				IF_CRTL_MIPI_DCLK_POL_SHIT, ! !dclk_inv, false);
964d0408543SAndy Yan 	}
965d0408543SAndy Yan 
966d0408543SAndy Yan 	if (conn_state->output_flags &
967d0408543SAndy Yan 	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
968d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
969d0408543SAndy Yan 				MIPI_DUAL_EN_SHIFT, 1, false);
970d0408543SAndy Yan 		if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
971d0408543SAndy Yan 			vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
972d0408543SAndy Yan 					EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
973d0408543SAndy Yan 					false);
974d0408543SAndy Yan 	}
975d0408543SAndy Yan 
976d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
977d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
978d0408543SAndy Yan 				1, false);
979d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
980d0408543SAndy Yan 				EDP0_MUX_SHIFT, cstate->crtc_id, false);
981d0408543SAndy Yan 	}
982d0408543SAndy Yan 
983d0408543SAndy Yan 	if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
984d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
985d0408543SAndy Yan 				1, false);
986d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
987d0408543SAndy Yan 				HDMI0_MUX_SHIFT, cstate->crtc_id, false);
98810ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
98910ee9f5bSAlgea Cao 				IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
99010ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_DSP_IF_POL,
99110ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_MASK,
99210ee9f5bSAlgea Cao 				IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
993d0408543SAndy Yan 	}
99410ee9f5bSAlgea Cao 
9957bdd0eb6SSandy Huang 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && cstate->crtc_id != 0)
9967bdd0eb6SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
9977bdd0eb6SSandy Huang 
99810ee9f5bSAlgea Cao 	if (is_uv_swap(conn_state->bus_format, conn_state->output_mode))
99910ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
100010ee9f5bSAlgea Cao 				DATA_SWAP_MASK, DATA_SWAP_SHIFT, DSP_RB_SWAP,
100110ee9f5bSAlgea Cao 				false);
100210ee9f5bSAlgea Cao 	else
100310ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
100410ee9f5bSAlgea Cao 				DATA_SWAP_MASK, DATA_SWAP_SHIFT, 0,
100510ee9f5bSAlgea Cao 				false);
100610ee9f5bSAlgea Cao 
1007d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
1008d0408543SAndy Yan 			OUT_MODE_SHIFT, conn_state->output_mode, false);
1009d0408543SAndy Yan 
1010d0408543SAndy Yan 	switch (conn_state->bus_format) {
1011d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB565_1X16:
1012d0408543SAndy Yan 		dither_down_en = 1;
1013d0408543SAndy Yan 		break;
1014d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X18:
1015d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
1016d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
1017d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
1018d0408543SAndy Yan 		dither_down_en = 1;
1019d0408543SAndy Yan 		break;
1020d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV8_1X24:
1021d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1022d0408543SAndy Yan 		dither_down_en = 0;
1023d0408543SAndy Yan 		pre_dither_down_en = 1;
1024d0408543SAndy Yan 		break;
1025d0408543SAndy Yan 	case MEDIA_BUS_FMT_YUV10_1X30:
1026d0408543SAndy Yan 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1027d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB888_1X24:
1028d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
1029d0408543SAndy Yan 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
1030d0408543SAndy Yan 	default:
1031d0408543SAndy Yan 		dither_down_en = 0;
1032d0408543SAndy Yan 		pre_dither_down_en = 0;
1033d0408543SAndy Yan 		break;
1034d0408543SAndy Yan 	}
1035d0408543SAndy Yan 
1036d0408543SAndy Yan 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA)
1037d0408543SAndy Yan 		pre_dither_down_en = 0;
1038d0408543SAndy Yan 	else
1039d0408543SAndy Yan 		pre_dither_down_en = 1;
1040d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1041d0408543SAndy Yan 			DITHER_DOWN_EN_SHIFT, dither_down_en, false);
1042d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1043d0408543SAndy Yan 			PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
1044d0408543SAndy Yan 
1045d0408543SAndy Yan 	yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
1046d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
1047d0408543SAndy Yan 			yuv_overlay, false);
1048d0408543SAndy Yan 
1049d0408543SAndy Yan 	cstate->yuv_overlay = yuv_overlay;
1050d0408543SAndy Yan 
1051d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
1052d0408543SAndy Yan 		    (htotal << 16) | hsync_len);
1053d0408543SAndy Yan 	val = hact_st << 16;
1054d0408543SAndy Yan 	val |= hact_end;
1055d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
1056d0408543SAndy Yan 	val = vact_st << 16;
1057d0408543SAndy Yan 	val |= vact_end;
1058d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
1059d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1060d0408543SAndy Yan 		u16 vact_st_f1 = vtotal + vact_st + 1;
1061d0408543SAndy Yan 		u16 vact_end_f1 = vact_st_f1 + vdisplay;
1062d0408543SAndy Yan 
1063d0408543SAndy Yan 		val = vact_st_f1 << 16 | vact_end_f1;
1064d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
1065d0408543SAndy Yan 			    val);
1066d0408543SAndy Yan 
1067d0408543SAndy Yan 		val = vtotal << 16 | (vtotal + vsync_len);
1068d0408543SAndy Yan 		vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
1069d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1070d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 1, false);
1071d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1072d0408543SAndy Yan 				P2I_EN_SHIFT, 1, false);
1073d0408543SAndy Yan 		vtotal += vtotal + 1;
1074d0408543SAndy Yan 	} else {
1075d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1076d0408543SAndy Yan 				INTERLACE_EN_SHIFT, 0, false);
1077d0408543SAndy Yan 		vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1078d0408543SAndy Yan 				P2I_EN_SHIFT, 0, false);
1079d0408543SAndy Yan 	}
1080d0408543SAndy Yan 	vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
1081d0408543SAndy Yan 		    (vtotal << 16) | vsync_len);
1082d0408543SAndy Yan 	val = ! !(mode->flags & DRM_MODE_FLAG_DBLCLK);
1083d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
108410ee9f5bSAlgea Cao 			CORE_DCLK_DIV_EN_SHIFT, val, false);
108510ee9f5bSAlgea Cao 
108610ee9f5bSAlgea Cao 	if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
108710ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, DCLK_DIV2_MASK,
108810ee9f5bSAlgea Cao 				DCLK_DIV2_SHIFT, 0x3, false);
108910ee9f5bSAlgea Cao 	else
109010ee9f5bSAlgea Cao 		vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, DCLK_DIV2_MASK,
109110ee9f5bSAlgea Cao 				DCLK_DIV2_SHIFT, 0, false);
109210ee9f5bSAlgea Cao 
109310ee9f5bSAlgea Cao 	if (yuv_overlay)
109410ee9f5bSAlgea Cao 		val = 0x20010200;
109510ee9f5bSAlgea Cao 	else
109610ee9f5bSAlgea Cao 		val = 0;
109710ee9f5bSAlgea Cao 	vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
109810ee9f5bSAlgea Cao 
109910ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
110010ee9f5bSAlgea Cao 			POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
1101d0408543SAndy Yan 
1102d0408543SAndy Yan 	vop2_post_config(state, vop2);
1103d0408543SAndy Yan 	vop2_setup_win_for_vp(state);
1104d0408543SAndy Yan 
1105d0408543SAndy Yan 	return 0;
1106d0408543SAndy Yan }
1107d0408543SAndy Yan 
1108d0408543SAndy Yan static void vop2_setup_win_for_vp(struct display_state *state)
1109d0408543SAndy Yan {
1110d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1111d0408543SAndy Yan 	const struct rockchip_crtc *crtc = cstate->crtc;
1112d0408543SAndy Yan 	const struct vop2_data *vop2_data = crtc->data;
1113d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
1114d0408543SAndy Yan 	u8 port_id = cstate->crtc_id;
1115d0408543SAndy Yan 	struct vop2_win *win;
1116d0408543SAndy Yan 	struct vop2_layer *layer;
1117d0408543SAndy Yan 	u8 used_layers = 0;
1118d0408543SAndy Yan 	u8 layer_id, win_phys_id, win_sel_id;
1119d0408543SAndy Yan 	u8 shift;
1120d0408543SAndy Yan 	int i;
1121d0408543SAndy Yan 
1122d0408543SAndy Yan 	for (i = 0; i < port_id; i++)
1123d0408543SAndy Yan 		used_layers += vop2->nr_wins[i];
1124d0408543SAndy Yan 
1125d0408543SAndy Yan 	vop2->nr_wins[port_id]++;
1126d0408543SAndy Yan 	/*
1127d0408543SAndy Yan 	 * Win and layer must map one by one, if a win is selected
1128d0408543SAndy Yan 	 * by two layers, unexpected error may happen.
1129d0408543SAndy Yan 	 * So when we attach a new win to a layer, we also move the
1130d0408543SAndy Yan 	 * old win of the layer to the layer where the new win comes from.
1131d0408543SAndy Yan 	 *
1132d0408543SAndy Yan 	 */
1133d0408543SAndy Yan 	layer = &vop2->layer[used_layers];
1134d0408543SAndy Yan 	win = &vop2->win[port_id];
1135d0408543SAndy Yan 	shift = port_id * 2;
1136d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
1137d0408543SAndy Yan 			LAYER_SEL_PORT_SHIFT + shift, port_id, false);
1138d0408543SAndy Yan 	shift = used_layers * 4;
1139d0408543SAndy Yan 	win_phys_id = vop2->data->win_id[port_id];
1140d0408543SAndy Yan 	win_sel_id = vop2->data->win_sel_id[win_phys_id];
1141d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_PORT_MASK, shift,
1142d0408543SAndy Yan 			win_sel_id, false);
1143d0408543SAndy Yan 	layer_id = win->layer_id;
1144d0408543SAndy Yan 	win_phys_id = layer->win_phys_id;
1145d0408543SAndy Yan 	win->layer_id = layer->id;
1146d0408543SAndy Yan 	layer->win_phys_id = win->phys_id;
1147d0408543SAndy Yan 	layer = &vop2->layer[layer_id];
1148d0408543SAndy Yan 	win = &vop2->win[win_phys_id];
1149d0408543SAndy Yan 	shift = layer_id * 4;
1150d0408543SAndy Yan 	win_sel_id = vop2->data->win_sel_id[win_phys_id];
1151d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_PORT_MASK, shift,
1152d0408543SAndy Yan 			win_sel_id, false);
1153d0408543SAndy Yan 	win->layer_id = layer_id;
1154d0408543SAndy Yan 	layer->win_phys_id = win_phys_id;
1155d0408543SAndy Yan 
1156d0408543SAndy Yan 	if (port_id == (vop2_data->nr_vps - 1))
1157d0408543SAndy Yan 		used_layers = vop2_data->nr_layers;
1158d0408543SAndy Yan 	shift = port_id * 4;
1159d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, shift,
1160d0408543SAndy Yan 			used_layers, false);
1161d0408543SAndy Yan 
116252ee18acSSandy Huang 	if (port_id == 0) {
11632b2e3d70SSandy Huang 		vop2_writel(vop2, 0x604, 0x54760123);
11642b2e3d70SSandy Huang 		vop2_writel(vop2, 0x608, 0x00000755);
11652b2e3d70SSandy Huang 		vop2_writel(vop2, 0x6e0, 0x2a000000);
116652ee18acSSandy Huang 	} else {
11672b2e3d70SSandy Huang 		vop2_writel(vop2, 0x604, 0x54760312);
11682b2e3d70SSandy Huang 		vop2_writel(vop2, 0x608, 0x55050728);
116952ee18acSSandy Huang 		vop2_writel(vop2, 0x6e4, 0x1e000000);
117052ee18acSSandy Huang 	}
1171d0408543SAndy Yan }
1172d0408543SAndy Yan 
1173d0408543SAndy Yan static int rockchip_vop2_set_plane(struct display_state *state)
1174d0408543SAndy Yan {
1175d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1176d0408543SAndy Yan 	struct connector_state *conn_state = &state->conn_state;
1177d0408543SAndy Yan 	struct drm_display_mode *mode = &conn_state->mode;
1178d0408543SAndy Yan 	u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
1179d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
1180d0408543SAndy Yan 	int src_w = cstate->src_w;
1181d0408543SAndy Yan 	int src_h = cstate->src_h;
1182d0408543SAndy Yan 	int crtc_x = cstate->crtc_x;
1183d0408543SAndy Yan 	int crtc_y = cstate->crtc_y;
1184d0408543SAndy Yan 	int crtc_w = cstate->crtc_w;
1185d0408543SAndy Yan 	int crtc_h = cstate->crtc_h;
1186d0408543SAndy Yan 	int xvir = cstate->xvir;
1187d0408543SAndy Yan 	int y_mirror = 0;
118810ee9f5bSAlgea Cao 	int csc_mode;
11892b2e3d70SSandy Huang 	u32 win_offset;
119052ee18acSSandy Huang 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id);
1191d0408543SAndy Yan 
11922b2e3d70SSandy Huang 	if (cstate->crtc_id == 1)
11932b2e3d70SSandy Huang 		win_offset = 0x400; /* port 1 use smart0*/
11942b2e3d70SSandy Huang 	else
11952b2e3d70SSandy Huang 		win_offset = 0; /* port 0 use esmart0*/
11962b2e3d70SSandy Huang 
1197d0408543SAndy Yan 	if (crtc_w > cstate->max_output.width) {
1198d0408543SAndy Yan 		printf("ERROR: output w[%d] exceeded max width[%d]\n",
1199d0408543SAndy Yan 		       crtc_w, cstate->max_output.width);
1200d0408543SAndy Yan 		return -EINVAL;
1201d0408543SAndy Yan 	}
1202d0408543SAndy Yan 
1203d0408543SAndy Yan 	act_info = (src_h - 1) << 16;
1204d0408543SAndy Yan 	act_info |= (src_w - 1) & 0xffff;
1205d0408543SAndy Yan 
1206d0408543SAndy Yan 	dsp_info = (crtc_h - 1) << 16;
1207d0408543SAndy Yan 	dsp_info |= (crtc_w - 1) & 0xffff;
1208d0408543SAndy Yan 
1209d0408543SAndy Yan 	dsp_stx = crtc_x;
1210d0408543SAndy Yan 	dsp_sty = crtc_y;
1211d0408543SAndy Yan 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
1212d0408543SAndy Yan 
1213d0408543SAndy Yan 	if (mode->flags & DRM_MODE_FLAG_YMIRROR)
1214d0408543SAndy Yan 		y_mirror = 1;
1215d0408543SAndy Yan 	else
1216d0408543SAndy Yan 		y_mirror = 0;
1217d0408543SAndy Yan 
1218d0408543SAndy Yan 	if (y_mirror)
1219d0408543SAndy Yan 		cstate->dma_addr += (src_h - 1) * xvir * 4;
1220d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
1221d0408543SAndy Yan 			YMIRROR_EN_SHIFT, y_mirror, false);
1222d0408543SAndy Yan 
1223d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
1224d0408543SAndy Yan 			WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
1225d0408543SAndy Yan 			false);
1226d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
1227d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
1228d0408543SAndy Yan 		    cstate->dma_addr);
1229d0408543SAndy Yan 
1230d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
1231d0408543SAndy Yan 		    act_info);
1232d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
1233d0408543SAndy Yan 		    dsp_info);
1234d0408543SAndy Yan 	vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
1235d0408543SAndy Yan 
1236d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
1237d0408543SAndy Yan 			WIN_EN_SHIFT, 1, false);
1238d0408543SAndy Yan 
123910ee9f5bSAlgea Cao 	csc_mode = vop2_convert_csc_mode(conn_state->color_space);
124010ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
124110ee9f5bSAlgea Cao 			RGB2YUV_EN_SHIFT,
124210ee9f5bSAlgea Cao 			is_yuv_output(conn_state->bus_format), false);
124310ee9f5bSAlgea Cao 	vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
124410ee9f5bSAlgea Cao 			CSC_MODE_SHIFT, csc_mode, false);
124510ee9f5bSAlgea Cao 
1246d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
1247d0408543SAndy Yan 	return 0;
1248d0408543SAndy Yan }
1249d0408543SAndy Yan 
1250d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state)
1251d0408543SAndy Yan {
1252d0408543SAndy Yan 	return 0;
1253d0408543SAndy Yan }
1254d0408543SAndy Yan 
1255d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state)
1256d0408543SAndy Yan {
1257d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1258d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
125952ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
126052ee18acSSandy Huang 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id);
1261d0408543SAndy Yan 
1262d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1263d0408543SAndy Yan 			STANDBY_EN_SHIFT, 0, false);
1264d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
1265d0408543SAndy Yan 
1266d0408543SAndy Yan 	return 0;
1267d0408543SAndy Yan }
1268d0408543SAndy Yan 
1269d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state)
1270d0408543SAndy Yan {
1271d0408543SAndy Yan 	struct crtc_state *cstate = &state->crtc_state;
1272d0408543SAndy Yan 	struct vop2 *vop2 = cstate->private;
127352ee18acSSandy Huang 	u32 vp_offset = (cstate->crtc_id * 0x100);
127452ee18acSSandy Huang 	u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id);
1275d0408543SAndy Yan 
1276d0408543SAndy Yan 	vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
1277d0408543SAndy Yan 			STANDBY_EN_SHIFT, 1, false);
1278d0408543SAndy Yan 	vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
1279d0408543SAndy Yan 
1280d0408543SAndy Yan 	return 0;
1281d0408543SAndy Yan }
1282d0408543SAndy Yan 
1283d0408543SAndy Yan const struct vop2_data rk3568_vop = {
1284d0408543SAndy Yan 	.nr_vps = 3,
1285d0408543SAndy Yan 	.max_output = {
1286d0408543SAndy Yan 		       [VOP2_VP0] = {4096, 2304},
1287d0408543SAndy Yan 		       [VOP2_VP1] = {2048, 1536},
1288d0408543SAndy Yan 		       [VOP2_VP2] = {1920, 1080},
1289d0408543SAndy Yan 		       },
1290d0408543SAndy Yan 
1291d0408543SAndy Yan 	/*
1292d0408543SAndy Yan 	 * Cluster0-Win0: 0
1293d0408543SAndy Yan 	 * Cluster1-Win0: 1
1294d0408543SAndy Yan 	 * Esmart0-Win0:  2
1295d0408543SAndy Yan 	 * Esmart1-Win0:  3
1296d0408543SAndy Yan 	 * Smart0-Win0:   4
1297d0408543SAndy Yan 	 * Smart1-Win0:   5
1298d0408543SAndy Yan 	 */
1299d0408543SAndy Yan 	.win_id = {
1300d0408543SAndy Yan 		   [VOP2_VP0] = 2,
1301d0408543SAndy Yan 		   [VOP2_VP1] = 3,
1302d0408543SAndy Yan 		   [VOP2_VP2] = 4,
1303d0408543SAndy Yan 		   },
1304d0408543SAndy Yan 
1305d0408543SAndy Yan 	/**
1306d0408543SAndy Yan 	 * Win select id: from register LAYER_SEL
1307d0408543SAndy Yan 	 *
1308d0408543SAndy Yan 	 * Cluster0-Win0: 0
1309d0408543SAndy Yan 	 * Cluster1-Win0: 1
1310d0408543SAndy Yan 	 * Esmart0-Win0:  2
1311d0408543SAndy Yan 	 * Esmart1-Win0:  6
1312d0408543SAndy Yan 	 * Smart0-Win0:   3
1313d0408543SAndy Yan 	 * Smart1-Win0:   7
1314d0408543SAndy Yan 	 */
1315d0408543SAndy Yan 	.win_sel_id = {0, 1, 2, 6, 3, 7},
1316d0408543SAndy Yan 	.nr_layers = 6,
1317d0408543SAndy Yan };
1318d0408543SAndy Yan 
1319d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
1320d0408543SAndy Yan 	.preinit = rockchip_vop2_preinit,
1321d0408543SAndy Yan 	.prepare = rockchip_vop2_prepare,
1322d0408543SAndy Yan 	.init = rockchip_vop2_init,
1323d0408543SAndy Yan 	.set_plane = rockchip_vop2_set_plane,
1324d0408543SAndy Yan 	.enable = rockchip_vop2_enable,
1325d0408543SAndy Yan 	.disable = rockchip_vop2_disable,
1326d0408543SAndy Yan };
1327