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