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