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 <regmap.h>
14 #include <asm/arch/cpu.h>
15 #include <asm/unaligned.h>
16 #include <asm/io.h>
17 #include <linux/list.h>
18 #include <linux/log2.h>
19 #include <linux/media-bus-format.h>
20 #include <asm/arch/clock.h>
21 #include <asm/gpio.h>
22 #include <linux/err.h>
23 #include <linux/ioport.h>
24 #include <dm/device.h>
25 #include <dm/read.h>
26 #include <dm/ofnode.h>
27 #include <fixp-arith.h>
28 #include <syscon.h>
29 #include <linux/iopoll.h>
30 #include <dm/uclass-internal.h>
31 #include <stdlib.h>
32 #include <dm/of_access.h>
33 #include <power-domain.h>
34
35 #include "rockchip_display.h"
36 #include "rockchip_crtc.h"
37 #include "rockchip_connector.h"
38 #include "rockchip_phy.h"
39 #include "rockchip_post_csc.h"
40
41 /* System registers definition */
42 #define RK3568_REG_CFG_DONE 0x000
43 #define CFG_DONE_EN BIT(15)
44
45 #define RK3568_VERSION_INFO 0x004
46 #define EN_MASK 1
47
48 #define RK3568_AUTO_GATING_CTRL 0x008
49 #define AUTO_GATING_EN_SHIFT 31
50 #define PORT_DCLK_AUTO_GATING_EN_SHIFT 14
51 #define ACLK_PRE_AUTO_GATING_EN_SHIFT 7
52
53 #define RK3576_SYS_AXI_HURRY_CTRL0_IMD 0x014
54 #define AXI0_PORT_URGENCY_EN_SHIFT 24
55
56 #define RK3576_SYS_AXI_HURRY_CTRL1_IMD 0x018
57 #define AXI1_PORT_URGENCY_EN_SHIFT 24
58
59 #define RK3576_SYS_MMU_CTRL 0x020
60 #define RKMMU_V2_EN_SHIFT 0
61 #define RKMMU_V2_SEL_AXI_SHIFT 1
62
63 #define RK3568_SYS_AXI_LUT_CTRL 0x024
64 #define LUT_DMA_EN_SHIFT 0
65 #define DSP_VS_T_SEL_SHIFT 16
66
67 #define RK3568_DSP_IF_EN 0x028
68 #define RGB_EN_SHIFT 0
69 #define RK3588_DP0_EN_SHIFT 0
70 #define RK3588_DP1_EN_SHIFT 1
71 #define RK3588_RGB_EN_SHIFT 8
72 #define HDMI0_EN_SHIFT 1
73 #define EDP0_EN_SHIFT 3
74 #define RK3588_EDP0_EN_SHIFT 2
75 #define RK3588_HDMI0_EN_SHIFT 3
76 #define MIPI0_EN_SHIFT 4
77 #define RK3588_EDP1_EN_SHIFT 4
78 #define RK3588_HDMI1_EN_SHIFT 5
79 #define RK3588_MIPI0_EN_SHIFT 6
80 #define MIPI1_EN_SHIFT 20
81 #define RK3588_MIPI1_EN_SHIFT 7
82 #define LVDS0_EN_SHIFT 5
83 #define LVDS1_EN_SHIFT 24
84 #define BT1120_EN_SHIFT 6
85 #define BT656_EN_SHIFT 7
86 #define IF_MUX_MASK 3
87 #define RGB_MUX_SHIFT 8
88 #define HDMI0_MUX_SHIFT 10
89 #define RK3588_DP0_MUX_SHIFT 12
90 #define RK3588_DP1_MUX_SHIFT 14
91 #define EDP0_MUX_SHIFT 14
92 #define RK3588_HDMI_EDP0_MUX_SHIFT 16
93 #define RK3588_HDMI_EDP1_MUX_SHIFT 18
94 #define MIPI0_MUX_SHIFT 16
95 #define RK3588_MIPI0_MUX_SHIFT 20
96 #define MIPI1_MUX_SHIFT 21
97 #define LVDS0_MUX_SHIFT 18
98 #define LVDS1_MUX_SHIFT 25
99
100 #define RK3576_SYS_PORT_CTRL 0x028
101 #define VP_INTR_MERGE_EN_SHIFT 14
102 #define RK3576_DSP_VS_T_SEL_SHIFT 4
103 #define INTERLACE_FRM_REG_DONE_MASK 0x7
104 #define INTERLACE_FRM_REG_DONE_SHIFT 0
105
106 #define RK3568_DSP_IF_CTRL 0x02c
107 #define LVDS_DUAL_EN_SHIFT 0
108 #define RK3588_BT656_UV_SWAP_SHIFT 0
109 #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1
110 #define RK3588_BT656_YC_SWAP_SHIFT 1
111 #define LVDS_DUAL_SWAP_EN_SHIFT 2
112 #define BT656_UV_SWAP 4
113 #define RK3588_BT1120_UV_SWAP_SHIFT 4
114 #define BT656_YC_SWAP 5
115 #define RK3588_BT1120_YC_SWAP_SHIFT 5
116 #define BT656_DCLK_POL 6
117 #define RK3588_HDMI_DUAL_EN_SHIFT 8
118 #define RK3588_EDP_DUAL_EN_SHIFT 8
119 #define RK3588_DP_DUAL_EN_SHIFT 9
120 #define RK3568_MIPI_DUAL_EN_SHIFT 10
121 #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11
122 #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12
123
124 #define RK3568_DSP_IF_POL 0x030
125 #define IF_CTRL_REG_DONE_IMD_SHIFT 28
126 #define IF_CRTL_MIPI_DCLK_POL_SHIT 19
127 #define IF_CTRL_MIPI_PIN_POL_MASK 0x7
128 #define IF_CTRL_MIPI_PIN_POL_SHIFT 16
129 #define IF_CRTL_EDP_DCLK_POL_SHIT 15
130 #define IF_CTRL_EDP_PIN_POL_MASK 0x7
131 #define IF_CTRL_EDP_PIN_POL_SHIFT 12
132 #define IF_CRTL_HDMI_DCLK_POL_SHIT 7
133 #define IF_CRTL_HDMI_PIN_POL_MASK 0x7
134 #define IF_CRTL_HDMI_PIN_POL_SHIT 4
135 #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT 3
136 #define IF_CTRL_RGB_LVDS_PIN_POL_MASK 0x7
137 #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT 0
138
139 #define RK3562_MIPI_DCLK_POL_SHIFT 15
140 #define RK3562_MIPI_PIN_POL_SHIFT 12
141 #define RK3562_IF_PIN_POL_MASK 0x7
142
143 #define RK3588_DP0_PIN_POL_SHIFT 8
144 #define RK3588_DP1_PIN_POL_SHIFT 12
145 #define RK3588_IF_PIN_POL_MASK 0x7
146
147 #define HDMI_EDP0_DCLK_DIV_SHIFT 16
148 #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18
149 #define HDMI_EDP1_DCLK_DIV_SHIFT 20
150 #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22
151 #define MIPI0_PIXCLK_DIV_SHIFT 24
152 #define MIPI1_PIXCLK_DIV_SHIFT 26
153
154 #define RK3576_SYS_CLUSTER_PD_CTRL 0x030
155 #define RK3576_CLUSTER_PD_EN_SHIFT 0
156
157 #define RK3588_SYS_PD_CTRL 0x034
158 #define RK3588_CLUSTER0_PD_EN_SHIFT 0
159 #define RK3588_CLUSTER1_PD_EN_SHIFT 1
160 #define RK3588_CLUSTER2_PD_EN_SHIFT 2
161 #define RK3588_CLUSTER3_PD_EN_SHIFT 3
162 #define RK3588_DSC_8K_PD_EN_SHIFT 5
163 #define RK3588_DSC_4K_PD_EN_SHIFT 6
164 #define RK3588_ESMART_PD_EN_SHIFT 7
165
166 #define RK3576_SYS_ESMART_PD_CTRL 0x034
167 #define RK3576_ESMART_PD_EN_SHIFT 0
168 #define RK3576_ESMART_LB_MODE_SEL_SHIFT 6
169 #define RK3576_ESMART_LB_MODE_SEL_MASK 0x3
170
171 #define RK3568_SYS_OTP_WIN_EN 0x50
172 #define OTP_WIN_EN_SHIFT 0
173 #define RK3568_SYS_LUT_PORT_SEL 0x58
174 #define GAMMA_PORT_SEL_MASK 0x3
175 #define GAMMA_PORT_SEL_SHIFT 0
176 #define GAMMA_AHB_WRITE_SEL_MASK 0x3
177 #define GAMMA_AHB_WRITE_SEL_SHIFT 12
178 #define PORT_MERGE_EN_SHIFT 16
179 #define ESMART_LB_MODE_SEL_MASK 0x3
180 #define ESMART_LB_MODE_SEL_SHIFT 26
181
182 #define RK3568_VP0_LINE_FLAG 0x70
183 #define RK3568_VP1_LINE_FLAG 0x74
184 #define RK3568_VP2_LINE_FLAG 0x78
185 #define RK3568_SYS0_INT_EN 0x80
186 #define RK3568_SYS0_INT_CLR 0x84
187 #define RK3568_SYS0_INT_STATUS 0x88
188 #define RK3568_SYS1_INT_EN 0x90
189 #define RK3568_SYS1_INT_CLR 0x94
190 #define RK3568_SYS1_INT_STATUS 0x98
191 #define RK3568_VP0_INT_EN 0xA0
192 #define RK3568_VP0_INT_CLR 0xA4
193 #define RK3568_VP0_INT_STATUS 0xA8
194 #define RK3568_VP1_INT_EN 0xB0
195 #define RK3568_VP1_INT_CLR 0xB4
196 #define RK3568_VP1_INT_STATUS 0xB8
197 #define RK3568_VP2_INT_EN 0xC0
198 #define RK3568_VP2_INT_CLR 0xC4
199 #define RK3568_VP2_INT_STATUS 0xC8
200 #define RK3568_VP2_INT_RAW_STATUS 0xCC
201 #define RK3588_VP3_INT_EN 0xD0
202 #define RK3588_VP3_INT_CLR 0xD4
203 #define RK3588_VP3_INT_STATUS 0xD8
204 #define RK3576_WB_CTRL 0x100
205 #define RK3576_WB_XSCAL_FACTOR 0x104
206 #define RK3576_WB_YRGB_MST 0x108
207 #define RK3576_WB_CBR_MST 0x10C
208 #define RK3576_WB_VIR_STRIDE 0x110
209 #define RK3576_WB_TIMEOUT_CTRL 0x114
210 #define RK3576_MIPI0_IF_CTRL 0x180
211 #define RK3576_IF_OUT_EN_SHIFT 0
212 #define RK3576_IF_CLK_OUT_EN_SHIFT 1
213 #define RK3576_IF_PORT_SEL_SHIFT 2
214 #define RK3576_IF_PORT_SEL_MASK 0x3
215 #define RK3576_IF_PIN_POL_SHIFT 4
216 #define RK3576_IF_PIN_POL_MASK 0x7
217 #define RK3576_IF_SPLIT_EN_SHIFT 8
218 #define RK3576_IF_DATA1_SEL_SHIFT 9
219 #define RK3576_MIPI_CMD_MODE_SHIFT 11
220 #define RK3576_IF_DCLK_SEL_SHIFT 21
221 #define RK3576_IF_DCLK_SEL_MASK 0x1
222 #define RK3576_IF_PIX_CLK_SEL_SHIFT 20
223 #define RK3576_IF_PIX_CLK_SEL_MASK 0x1
224 #define RK3576_IF_REGDONE_IMD_EN_SHIFT 31
225 #define RK3576_HDMI0_IF_CTRL 0x184
226 #define RK3576_EDP0_IF_CTRL 0x188
227 #define RK3576_DP0_IF_CTRL 0x18C
228 #define RK3576_RGB_IF_CTRL 0x194
229 #define RK3576_BT656_OUT_EN_SHIFT 12
230 #define RK3576_BT656_UV_SWAP_SHIFT 13
231 #define RK3576_BT656_YC_SWAP_SHIFT 14
232 #define RK3576_BT1120_OUT_EN_SHIFT 16
233 #define RK3576_BT1120_UV_SWAP_SHIFT 17
234 #define RK3576_BT1120_YC_SWAP_SHIFT 18
235 #define RK3576_DP1_IF_CTRL 0x1A4
236 #define RK3576_DP2_IF_CTRL 0x1B0
237
238 #define RK3588_SYS_VAR_FREQ_CTRL 0x038
239 #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT 20
240 #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT 24
241 #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT 28
242
243 #define RK3568_SYS_STATUS0 0x60
244 #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8
245 #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9
246 #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10
247 #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11
248 #define RK3588_DSC_8K_PD_STATUS_SHIFT 13
249 #define RK3588_DSC_4K_PD_STATUS_SHIFT 14
250 #define RK3588_ESMART_PD_STATUS_SHIFT 15
251
252 #define RK3568_SYS_CTRL_LINE_FLAG0 0x70
253 #define LINE_FLAG_NUM_MASK 0x1fff
254 #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0
255 #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16
256
257 /* DSC CTRL registers definition */
258 #define RK3588_DSC_8K_SYS_CTRL 0x200
259 #define DSC_PORT_SEL_MASK 0x3
260 #define DSC_PORT_SEL_SHIFT 0
261 #define DSC_MAN_MODE_MASK 0x1
262 #define DSC_MAN_MODE_SHIFT 2
263 #define DSC_INTERFACE_MODE_MASK 0x3
264 #define DSC_INTERFACE_MODE_SHIFT 4
265 #define DSC_PIXEL_NUM_MASK 0x3
266 #define DSC_PIXEL_NUM_SHIFT 6
267 #define DSC_PXL_CLK_DIV_MASK 0x1
268 #define DSC_PXL_CLK_DIV_SHIFT 8
269 #define DSC_CDS_CLK_DIV_MASK 0x3
270 #define DSC_CDS_CLK_DIV_SHIFT 12
271 #define DSC_TXP_CLK_DIV_MASK 0x3
272 #define DSC_TXP_CLK_DIV_SHIFT 14
273 #define DSC_INIT_DLY_MODE_MASK 0x1
274 #define DSC_INIT_DLY_MODE_SHIFT 16
275 #define DSC_SCAN_EN_SHIFT 17
276 #define DSC_HALT_EN_SHIFT 18
277
278 #define RK3588_DSC_8K_RST 0x204
279 #define RST_DEASSERT_MASK 0x1
280 #define RST_DEASSERT_SHIFT 0
281
282 #define RK3588_DSC_8K_CFG_DONE 0x208
283 #define DSC_CFG_DONE_SHIFT 0
284
285 #define RK3588_DSC_8K_INIT_DLY 0x20C
286 #define DSC_INIT_DLY_NUM_MASK 0xffff
287 #define DSC_INIT_DLY_NUM_SHIFT 0
288 #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16
289
290 #define RK3588_DSC_8K_HTOTAL_HS_END 0x210
291 #define DSC_HTOTAL_PW_MASK 0xffffffff
292 #define DSC_HTOTAL_PW_SHIFT 0
293
294 #define RK3588_DSC_8K_HACT_ST_END 0x214
295 #define DSC_HACT_ST_END_MASK 0xffffffff
296 #define DSC_HACT_ST_END_SHIFT 0
297
298 #define RK3588_DSC_8K_VTOTAL_VS_END 0x218
299 #define DSC_VTOTAL_PW_MASK 0xffffffff
300 #define DSC_VTOTAL_PW_SHIFT 0
301
302 #define RK3588_DSC_8K_VACT_ST_END 0x21C
303 #define DSC_VACT_ST_END_MASK 0xffffffff
304 #define DSC_VACT_ST_END_SHIFT 0
305
306 #define RK3588_DSC_8K_STATUS 0x220
307
308 /* Overlay registers definition */
309 #define RK3528_OVL_SYS 0x500
310 #define RK3528_OVL_SYS_PORT_SEL 0x504
311 #define RK3528_OVL_SYS_GATING_EN 0x508
312 #define RK3528_OVL_SYS_CLUSTER0_CTRL 0x510
313 #define CLUSTER_DLY_NUM_SHIFT 0
314 #define RK3528_OVL_SYS_ESMART0_CTRL 0x520
315 #define ESMART_DLY_NUM_MASK 0xff
316 #define ESMART_DLY_NUM_SHIFT 0
317 #define RK3528_OVL_SYS_ESMART1_CTRL 0x524
318 #define RK3528_OVL_SYS_ESMART2_CTRL 0x528
319 #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C
320 #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530
321 #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534
322 #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538
323 #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c
324 #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540
325 #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544
326 #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548
327 #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c
328
329 #define RK3528_OVL_PORT0_CTRL 0x600
330 #define RK3568_OVL_CTRL 0x600
331 #define OVL_MODE_SEL_MASK 0x1
332 #define OVL_MODE_SEL_SHIFT 0
333 #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28
334 #define RK3528_OVL_PORT0_LAYER_SEL 0x604
335 #define RK3568_OVL_LAYER_SEL 0x604
336 #define LAYER_SEL_MASK 0xf
337
338 #define RK3568_OVL_PORT_SEL 0x608
339 #define PORT_MUX_MASK 0xf
340 #define PORT_MUX_SHIFT 0
341 #define LAYER_SEL_PORT_MASK 0x3
342 #define LAYER_SEL_PORT_SHIFT 16
343
344 #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610
345 #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614
346 #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618
347 #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C
348 #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620
349 #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624
350 #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628
351 #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C
352 #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630
353 #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634
354 #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638
355 #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C
356 #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640
357 #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644
358 #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648
359 #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C
360 #define RK3568_MIX0_SRC_COLOR_CTRL 0x650
361 #define RK3568_MIX0_DST_COLOR_CTRL 0x654
362 #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658
363 #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C
364 #define RK3576_EXTRA_SRC_COLOR_CTRL 0x650
365 #define RK3576_EXTRA_DST_COLOR_CTRL 0x654
366 #define RK3576_EXTRA_SRC_ALPHA_CTRL 0x658
367 #define RK3576_EXTRA_DST_ALPHA_CTRL 0x65C
368 #define RK3528_HDR_SRC_COLOR_CTRL 0x660
369 #define RK3528_HDR_DST_COLOR_CTRL 0x664
370 #define RK3528_HDR_SRC_ALPHA_CTRL 0x668
371 #define RK3528_HDR_DST_ALPHA_CTRL 0x66C
372 #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670
373 #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0
374 #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4
375 #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8
376 #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC
377 #define RK3568_VP0_BG_MIX_CTRL 0x6E0
378 #define BG_MIX_CTRL_MASK 0xff
379 #define BG_MIX_CTRL_SHIFT 24
380 #define RK3568_VP1_BG_MIX_CTRL 0x6E4
381 #define RK3568_VP2_BG_MIX_CTRL 0x6E8
382 #define RK3568_CLUSTER_DLY_NUM 0x6F0
383 #define RK3568_CLUSTER_DLY_NUM1 0x6F4
384 #define CLUSTER_DLY_NUM_MASK 0xffff
385 #define CLUSTER0_DLY_NUM_SHIFT 0
386 #define CLUSTER1_DLY_NUM_SHIFT 16
387 #define RK3568_SMART_DLY_NUM 0x6F8
388 #define SMART_DLY_NUM_MASK 0xff
389 #define ESMART0_DLY_NUM_SHIFT 0
390 #define ESMART1_DLY_NUM_SHIFT 8
391 #define SMART0_DLY_NUM_SHIFT 16
392 #define SMART1_DLY_NUM_SHIFT 24
393
394 #define RK3528_OVL_PORT1_CTRL 0x700
395 #define RK3528_OVL_PORT1_LAYER_SEL 0x704
396 #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720
397 #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724
398 #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728
399 #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C
400 #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730
401 #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734
402 #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738
403 #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C
404 #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740
405 #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744
406 #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748
407 #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C
408 #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770
409 #define RK3576_OVL_PORT2_CTRL 0x800
410 #define RK3576_OVL_PORT2_LAYER_SEL 0x804
411 #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL 0x820
412 #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL 0x824
413 #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL 0x828
414 #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL 0x82C
415 #define RK3576_OVL_PORT2_BG_MIX_CTRL 0x870
416
417 /* Video Port registers definition */
418 #define RK3568_VP0_DSP_CTRL 0xC00
419 #define OUT_MODE_MASK 0xf
420 #define OUT_MODE_SHIFT 0
421 #define DATA_SWAP_MASK 0x1f
422 #define DATA_SWAP_SHIFT 8
423 #define DSP_BG_SWAP 0x1
424 #define DSP_RB_SWAP 0x2
425 #define DSP_RG_SWAP 0x4
426 #define DSP_DELTA_SWAP 0x8
427 #define CORE_DCLK_DIV_EN_SHIFT 4
428 #define P2I_EN_SHIFT 5
429 #define DSP_FILED_POL 6
430 #define INTERLACE_EN_SHIFT 7
431 #define DSP_X_MIR_EN_SHIFT 13
432 #define POST_DSP_OUT_R2Y_SHIFT 15
433 #define PRE_DITHER_DOWN_EN_SHIFT 16
434 #define DITHER_DOWN_EN_SHIFT 17
435 #define DITHER_DOWN_SEL_SHIFT 18
436 #define DITHER_DOWN_SEL_MASK 0x3
437 #define DITHER_DOWN_MODE_SHIFT 20
438 #define GAMMA_UPDATE_EN_SHIFT 22
439 #define DSP_LUT_EN_SHIFT 28
440
441 #define STANDBY_EN_SHIFT 31
442
443 #define RK3568_VP0_MIPI_CTRL 0xC04
444 #define DCLK_DIV2_SHIFT 4
445 #define DCLK_DIV2_MASK 0x3
446 #define MIPI_DUAL_EN_SHIFT 20
447 #define MIPI_DUAL_SWAP_EN_SHIFT 21
448 #define EDPI_TE_EN 28
449 #define EDPI_WMS_HOLD_EN 30
450 #define EDPI_WMS_FS 31
451
452
453 #define RK3568_VP0_COLOR_BAR_CTRL 0xC08
454 #define POST_URGENCY_EN_SHIFT 8
455 #define POST_URGENCY_THL_SHIFT 16
456 #define POST_URGENCY_THL_MASK 0xf
457 #define POST_URGENCY_THH_SHIFT 20
458 #define POST_URGENCY_THH_MASK 0xf
459
460 #define RK3568_VP0_DCLK_SEL 0xC0C
461 #define RK3576_DCLK_CORE_SEL_SHIFT 0
462 #define RK3576_DCLK_OUT_SEL_SHIFT 2
463
464 #define RK3568_VP0_3D_LUT_CTRL 0xC10
465 #define VP0_3D_LUT_EN_SHIFT 0
466 #define VP0_3D_LUT_UPDATE_SHIFT 2
467
468 #define RK3588_VP0_CLK_CTRL 0xC0C
469 #define DCLK_CORE_DIV_SHIFT 0
470 #define DCLK_OUT_DIV_SHIFT 2
471
472 #define RK3568_VP0_3D_LUT_MST 0xC20
473
474 #define RK3568_VP0_DSP_BG 0xC2C
475 #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30
476 #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34
477 #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38
478 #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C
479 #define RK3568_VP0_POST_SCL_CTRL 0xC40
480 #define RK3568_VP0_POST_SCALE_MASK 0x3
481 #define RK3568_VP0_POST_SCALE_SHIFT 0
482 #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44
483 #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48
484 #define RK3568_VP0_DSP_HACT_ST_END 0xC4C
485 #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50
486 #define RK3568_VP0_DSP_VACT_ST_END 0xC54
487 #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58
488 #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C
489
490 #define RK3568_VP0_BCSH_CTRL 0xC60
491 #define BCSH_CTRL_Y2R_SHIFT 0
492 #define BCSH_CTRL_Y2R_MASK 0x1
493 #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2
494 #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3
495 #define BCSH_CTRL_R2Y_SHIFT 4
496 #define BCSH_CTRL_R2Y_MASK 0x1
497 #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6
498 #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3
499
500 #define RK3568_VP0_BCSH_BCS 0xC64
501 #define BCSH_BRIGHTNESS_SHIFT 0
502 #define BCSH_BRIGHTNESS_MASK 0xFF
503 #define BCSH_CONTRAST_SHIFT 8
504 #define BCSH_CONTRAST_MASK 0x1FF
505 #define BCSH_SATURATION_SHIFT 20
506 #define BCSH_SATURATION_MASK 0x3FF
507 #define BCSH_OUT_MODE_SHIFT 30
508 #define BCSH_OUT_MODE_MASK 0x3
509
510 #define RK3568_VP0_BCSH_H 0xC68
511 #define BCSH_SIN_HUE_SHIFT 0
512 #define BCSH_SIN_HUE_MASK 0x1FF
513 #define BCSH_COS_HUE_SHIFT 16
514 #define BCSH_COS_HUE_MASK 0x1FF
515
516 #define RK3568_VP0_BCSH_COLOR 0xC6C
517 #define BCSH_EN_SHIFT 31
518 #define BCSH_EN_MASK 1
519
520 #define RK3576_VP0_POST_DITHER_FRC_0 0xCA0
521 #define RK3576_VP0_POST_DITHER_FRC_1 0xCA4
522 #define RK3576_VP0_POST_DITHER_FRC_2 0xCA8
523
524 #define RK3528_VP0_ACM_CTRL 0xCD0
525 #define POST_CSC_COE00_MASK 0xFFFF
526 #define POST_CSC_COE00_SHIFT 16
527 #define POST_R2Y_MODE_MASK 0x7
528 #define POST_R2Y_MODE_SHIFT 8
529 #define POST_CSC_MODE_MASK 0x7
530 #define POST_CSC_MODE_SHIFT 3
531 #define POST_R2Y_EN_MASK 0x1
532 #define POST_R2Y_EN_SHIFT 2
533 #define POST_CSC_EN_MASK 0x1
534 #define POST_CSC_EN_SHIFT 1
535 #define POST_ACM_BYPASS_EN_MASK 0x1
536 #define POST_ACM_BYPASS_EN_SHIFT 0
537 #define RK3528_VP0_CSC_COE01_02 0xCD4
538 #define RK3528_VP0_CSC_COE10_11 0xCD8
539 #define RK3528_VP0_CSC_COE12_20 0xCDC
540 #define RK3528_VP0_CSC_COE21_22 0xCE0
541 #define RK3528_VP0_CSC_OFFSET0 0xCE4
542 #define RK3528_VP0_CSC_OFFSET1 0xCE8
543 #define RK3528_VP0_CSC_OFFSET2 0xCEC
544
545 #define RK3562_VP0_MCU_CTRL 0xCF8
546 #define MCU_TYPE_SHIFT 31
547 #define MCU_BYPASS_SHIFT 30
548 #define MCU_RS_SHIFT 29
549 #define MCU_FRAME_ST_SHIFT 28
550 #define MCU_HOLD_MODE_SHIFT 27
551 #define MCU_CLK_SEL_SHIFT 26
552 #define MCU_CLK_SEL_MASK 0x1
553 #define MCU_RW_PEND_SHIFT 20
554 #define MCU_RW_PEND_MASK 0x3F
555 #define MCU_RW_PST_SHIFT 16
556 #define MCU_RW_PST_MASK 0xF
557 #define MCU_CS_PEND_SHIFT 10
558 #define MCU_CS_PEND_MASK 0x3F
559 #define MCU_CS_PST_SHIFT 6
560 #define MCU_CS_PST_MASK 0xF
561 #define MCU_PIX_TOTAL_SHIFT 0
562 #define MCU_PIX_TOTAL_MASK 0x3F
563
564 #define RK3562_VP0_MCU_RW_BYPASS_PORT 0xCFC
565 #define MCU_WRITE_DATA_BYPASS_SHIFT 0
566 #define MCU_WRITE_DATA_BYPASS_MASK 0xFFFFFFFF
567
568 #define RK3568_VP1_DSP_CTRL 0xD00
569 #define RK3568_VP1_MIPI_CTRL 0xD04
570 #define RK3568_VP1_COLOR_BAR_CTRL 0xD08
571 #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30
572 #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34
573 #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38
574 #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C
575 #define RK3568_VP1_POST_SCL_CTRL 0xD40
576 #define RK3568_VP1_DSP_HACT_INFO 0xD34
577 #define RK3568_VP1_DSP_VACT_INFO 0xD38
578 #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44
579 #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48
580 #define RK3568_VP1_DSP_HACT_ST_END 0xD4C
581 #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50
582 #define RK3568_VP1_DSP_VACT_ST_END 0xD54
583 #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58
584 #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C
585
586 #define RK3568_VP2_DSP_CTRL 0xE00
587 #define RK3568_VP2_MIPI_CTRL 0xE04
588 #define RK3568_VP2_COLOR_BAR_CTRL 0xE08
589 #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30
590 #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34
591 #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38
592 #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C
593 #define RK3568_VP2_POST_SCL_CTRL 0xE40
594 #define RK3568_VP2_DSP_HACT_INFO 0xE34
595 #define RK3568_VP2_DSP_VACT_INFO 0xE38
596 #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44
597 #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48
598 #define RK3568_VP2_DSP_HACT_ST_END 0xE4C
599 #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50
600 #define RK3568_VP2_DSP_VACT_ST_END 0xE54
601 #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58
602 #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C
603 #define RK3568_VP2_BCSH_CTRL 0xE60
604 #define RK3568_VP2_BCSH_BCS 0xE64
605 #define RK3568_VP2_BCSH_H 0xE68
606 #define RK3568_VP2_BCSH_COLOR_BAR 0xE6C
607 #define RK3576_VP2_MCU_CTRL 0xEF8
608 #define RK3576_VP2_MCU_RW_BYPASS_PORT 0xEFC
609
610 /* Cluster0 register definition */
611 #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000
612 #define CLUSTER_YUV2RGB_EN_SHIFT 8
613 #define CLUSTER_RGB2YUV_EN_SHIFT 9
614 #define CLUSTER_CSC_MODE_SHIFT 10
615 #define CLUSTER_RB_SWAP_SHIFT 14
616 #define CLUSTER_DITHER_UP_EN_SHIFT 18
617 #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004
618 #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12
619 #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14
620 #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14
621 #define AVG2_MASK 0x1
622 #define CLUSTER_AVG2_SHIFT 18
623 #define AVG4_MASK 0x1
624 #define CLUSTER_AVG4_SHIFT 19
625 #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22
626 #define CLUSTER_XGT_EN_SHIFT 24
627 #define XGT_MODE_MASK 0x3
628 #define CLUSTER_XGT_MODE_SHIFT 25
629 #define CLUSTER_XAVG_EN_SHIFT 27
630 #define CLUSTER_YRGB_GT2_SHIFT 28
631 #define CLUSTER_YRGB_GT4_SHIFT 29
632 #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008
633 #define CLUSTER_AXI_YRGB_ID_MASK 0x1f
634 #define CLUSTER_AXI_YRGB_ID_SHIFT 0
635 #define CLUSTER_AXI_UV_ID_MASK 0x1f
636 #define CLUSTER_AXI_UV_ID_SHIFT 5
637
638 #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010
639 #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014
640 #define RK3568_CLUSTER0_WIN0_VIR 0x1018
641 #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020
642 #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024
643 #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028
644 #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030
645 #define RK3576_CLUSTER0_WIN0_ZME_CTRL 0x1040
646 #define WIN0_ZME_DERING_EN_SHIFT 3
647 #define WIN0_ZME_GATING_EN_SHIFT 31
648 #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA 0x1044
649 #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054
650 #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058
651 #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C
652 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060
653 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064
654 #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068
655 #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C
656 #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT 7
657 #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET 0x1078
658 #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE 0x107C
659
660 #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080
661 #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084
662 #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090
663 #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094
664 #define RK3568_CLUSTER0_WIN1_VIR 0x1098
665 #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0
666 #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4
667 #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8
668 #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0
669 #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4
670 #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8
671 #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC
672 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0
673 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4
674 #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8
675 #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC
676 #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET 0x10F8
677 #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE 0x10FC
678
679 #define RK3568_CLUSTER0_CTRL 0x1100
680 #define CLUSTER_EN_SHIFT 0
681 #define CLUSTER_AXI_ID_MASK 0x1
682 #define CLUSTER_AXI_ID_SHIFT 13
683 #define RK3576_CLUSTER0_PORT_SEL 0x11F4
684 #define CLUSTER_PORT_SEL_SHIFT 0
685 #define CLUSTER_PORT_SEL_MASK 0x3
686 #define RK3576_CLUSTER0_DLY_NUM 0x11F8
687 #define CLUSTER_WIN0_DLY_NUM_SHIFT 0
688 #define CLUSTER_WIN0_DLY_NUM_MASK 0xff
689 #define CLUSTER_WIN1_DLY_NUM_SHIFT 0
690 #define CLUSTER_WIN1_DLY_NUM_MASK 0xff
691
692 #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200
693 #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204
694 #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210
695 #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214
696 #define RK3568_CLUSTER1_WIN0_VIR 0x1218
697 #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220
698 #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224
699 #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228
700 #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230
701 #define RK3576_CLUSTER1_WIN0_ZME_CTRL 0x1240
702 #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA 0x1244
703 #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254
704 #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258
705 #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C
706 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260
707 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264
708 #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268
709 #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C
710 #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET 0x1278
711 #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE 0x127C
712
713 #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280
714 #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284
715 #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290
716 #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294
717 #define RK3568_CLUSTER1_WIN1_VIR 0x1298
718 #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0
719 #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4
720 #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8
721 #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0
722 #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4
723 #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8
724 #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC
725 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0
726 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4
727 #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8
728 #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC
729 #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET 0x12F8
730 #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE 0x12FC
731
732 #define RK3568_CLUSTER1_CTRL 0x1300
733 #define RK3576_CLUSTER1_PORT_SEL 0x13F4
734 #define RK3576_CLUSTER1_DLY_NUM 0x13F8
735
736 /* Esmart register definition */
737 #define RK3568_ESMART0_CTRL0 0x1800
738 #define RGB2YUV_EN_SHIFT 1
739 #define CSC_MODE_SHIFT 2
740 #define CSC_MODE_MASK 0x3
741 #define ESMART_LB_SELECT_SHIFT 12
742 #define ESMART_LB_SELECT_MASK 0x3
743
744 #define RK3568_ESMART0_CTRL1 0x1804
745 #define ESMART_AXI_YRGB_ID_MASK 0x1f
746 #define ESMART_AXI_YRGB_ID_SHIFT 4
747 #define ESMART_AXI_UV_ID_MASK 0x1f
748 #define ESMART_AXI_UV_ID_SHIFT 12
749 #define YMIRROR_EN_SHIFT 31
750
751 #define RK3568_ESMART0_AXI_CTRL 0x1808
752 #define ESMART_AXI_ID_MASK 0x1
753 #define ESMART_AXI_ID_SHIFT 1
754
755 #define RK3568_ESMART0_REGION0_CTRL 0x1810
756 #define WIN_EN_SHIFT 0
757 #define WIN_FORMAT_MASK 0x1f
758 #define WIN_FORMAT_SHIFT 1
759 #define REGION0_DITHER_UP_EN_SHIFT 12
760 #define REGION0_RB_SWAP_SHIFT 14
761 #define ESMART_XAVG_EN_SHIFT 20
762 #define ESMART_XGT_EN_SHIFT 21
763 #define ESMART_XGT_MODE_SHIFT 22
764
765 #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814
766 #define RK3568_ESMART0_REGION0_CBR_MST 0x1818
767 #define RK3568_ESMART0_REGION0_VIR 0x181C
768 #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820
769 #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824
770 #define RK3568_ESMART0_REGION0_DSP_ST 0x1828
771 #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830
772 #define YRGB_XSCL_MODE_MASK 0x3
773 #define YRGB_XSCL_MODE_SHIFT 0
774 #define YRGB_XSCL_FILTER_MODE_MASK 0x3
775 #define YRGB_XSCL_FILTER_MODE_SHIFT 2
776 #define YRGB_YSCL_MODE_MASK 0x3
777 #define YRGB_YSCL_MODE_SHIFT 4
778 #define YRGB_YSCL_FILTER_MODE_MASK 0x3
779 #define YRGB_YSCL_FILTER_MODE_SHIFT 6
780
781 #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834
782 #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838
783 #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C
784 #define RK3568_ESMART0_REGION1_CTRL 0x1840
785 #define YRGB_GT2_MASK 0x1
786 #define YRGB_GT2_SHIFT 8
787 #define YRGB_GT4_MASK 0x1
788 #define YRGB_GT4_SHIFT 9
789
790 #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844
791 #define RK3568_ESMART0_REGION1_CBR_MST 0x1848
792 #define RK3568_ESMART0_REGION1_VIR 0x184C
793 #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850
794 #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854
795 #define RK3568_ESMART0_REGION1_DSP_ST 0x1858
796 #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860
797 #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864
798 #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868
799 #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C
800 #define RK3568_ESMART0_REGION2_CTRL 0x1870
801 #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874
802 #define RK3568_ESMART0_REGION2_CBR_MST 0x1878
803 #define RK3568_ESMART0_REGION2_VIR 0x187C
804 #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880
805 #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884
806 #define RK3568_ESMART0_REGION2_DSP_ST 0x1888
807 #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890
808 #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894
809 #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898
810 #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C
811 #define RK3568_ESMART0_REGION3_CTRL 0x18A0
812 #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4
813 #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8
814 #define RK3568_ESMART0_REGION3_VIR 0x18AC
815 #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0
816 #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4
817 #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8
818 #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0
819 #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4
820 #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8
821 #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC
822 #define RK3568_ESMART0_COLOR_KEY_CTRL 0x18D0
823 #define RK3576_ESMART0_ALPHA_MAP 0x18D8
824 #define RK3576_ESMART0_PORT_SEL 0x18F4
825 #define ESMART_PORT_SEL_SHIFT 0
826 #define ESMART_PORT_SEL_MASK 0x3
827 #define RK3576_ESMART0_DLY_NUM 0x18F8
828
829 #define RK3568_ESMART1_CTRL0 0x1A00
830 #define RK3568_ESMART1_CTRL1 0x1A04
831 #define RK3568_ESMART1_REGION0_CTRL 0x1A10
832 #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14
833 #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18
834 #define RK3568_ESMART1_REGION0_VIR 0x1A1C
835 #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20
836 #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24
837 #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28
838 #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30
839 #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34
840 #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38
841 #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C
842 #define RK3568_ESMART1_REGION1_CTRL 0x1A40
843 #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44
844 #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48
845 #define RK3568_ESMART1_REGION1_VIR 0x1A4C
846 #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50
847 #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54
848 #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58
849 #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60
850 #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64
851 #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68
852 #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C
853 #define RK3568_ESMART1_REGION2_CTRL 0x1A70
854 #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74
855 #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78
856 #define RK3568_ESMART1_REGION2_VIR 0x1A7C
857 #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80
858 #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84
859 #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88
860 #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90
861 #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94
862 #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98
863 #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C
864 #define RK3568_ESMART1_REGION3_CTRL 0x1AA0
865 #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4
866 #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8
867 #define RK3568_ESMART1_REGION3_VIR 0x1AAC
868 #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0
869 #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4
870 #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8
871 #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0
872 #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4
873 #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8
874 #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC
875 #define RK3576_ESMART1_ALPHA_MAP 0x1AD8
876 #define RK3576_ESMART1_PORT_SEL 0x1AF4
877 #define RK3576_ESMART1_DLY_NUM 0x1AF8
878
879 #define RK3568_SMART0_CTRL0 0x1C00
880 #define RK3568_SMART0_CTRL1 0x1C04
881 #define RK3568_SMART0_REGION0_CTRL 0x1C10
882 #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14
883 #define RK3568_SMART0_REGION0_CBR_MST 0x1C18
884 #define RK3568_SMART0_REGION0_VIR 0x1C1C
885 #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20
886 #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24
887 #define RK3568_SMART0_REGION0_DSP_ST 0x1C28
888 #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30
889 #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34
890 #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38
891 #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C
892 #define RK3568_SMART0_REGION1_CTRL 0x1C40
893 #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44
894 #define RK3568_SMART0_REGION1_CBR_MST 0x1C48
895 #define RK3568_SMART0_REGION1_VIR 0x1C4C
896 #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50
897 #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54
898 #define RK3568_SMART0_REGION1_DSP_ST 0x1C58
899 #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60
900 #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64
901 #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68
902 #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C
903 #define RK3568_SMART0_REGION2_CTRL 0x1C70
904 #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74
905 #define RK3568_SMART0_REGION2_CBR_MST 0x1C78
906 #define RK3568_SMART0_REGION2_VIR 0x1C7C
907 #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80
908 #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84
909 #define RK3568_SMART0_REGION2_DSP_ST 0x1C88
910 #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90
911 #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94
912 #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98
913 #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C
914 #define RK3568_SMART0_REGION3_CTRL 0x1CA0
915 #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4
916 #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8
917 #define RK3568_SMART0_REGION3_VIR 0x1CAC
918 #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0
919 #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4
920 #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8
921 #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0
922 #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4
923 #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8
924 #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC
925 #define RK3576_ESMART2_ALPHA_MAP 0x1CD8
926 #define RK3576_ESMART2_PORT_SEL 0x1CF4
927 #define RK3576_ESMART2_DLY_NUM 0x1CF8
928
929 #define RK3568_SMART1_CTRL0 0x1E00
930 #define RK3568_SMART1_CTRL1 0x1E04
931 #define RK3568_SMART1_REGION0_CTRL 0x1E10
932 #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14
933 #define RK3568_SMART1_REGION0_CBR_MST 0x1E18
934 #define RK3568_SMART1_REGION0_VIR 0x1E1C
935 #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20
936 #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24
937 #define RK3568_SMART1_REGION0_DSP_ST 0x1E28
938 #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30
939 #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34
940 #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38
941 #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C
942 #define RK3568_SMART1_REGION1_CTRL 0x1E40
943 #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44
944 #define RK3568_SMART1_REGION1_CBR_MST 0x1E48
945 #define RK3568_SMART1_REGION1_VIR 0x1E4C
946 #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50
947 #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54
948 #define RK3568_SMART1_REGION1_DSP_ST 0x1E58
949 #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60
950 #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64
951 #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68
952 #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C
953 #define RK3568_SMART1_REGION2_CTRL 0x1E70
954 #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74
955 #define RK3568_SMART1_REGION2_CBR_MST 0x1E78
956 #define RK3568_SMART1_REGION2_VIR 0x1E7C
957 #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80
958 #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84
959 #define RK3568_SMART1_REGION2_DSP_ST 0x1E88
960 #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90
961 #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94
962 #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98
963 #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C
964 #define RK3568_SMART1_REGION3_CTRL 0x1EA0
965 #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4
966 #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8
967 #define RK3568_SMART1_REGION3_VIR 0x1EAC
968 #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0
969 #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4
970 #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8
971 #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0
972 #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4
973 #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8
974 #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC
975 #define RK3576_ESMART3_ALPHA_MAP 0x1ED8
976 #define RK3576_ESMART3_PORT_SEL 0x1EF4
977 #define RK3576_ESMART3_DLY_NUM 0x1EF8
978
979 /* HDR register definition */
980 #define RK3568_HDR_LUT_CTRL 0x2000
981
982 #define RK3588_VP3_DSP_CTRL 0xF00
983 #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400
984 #define RK3588_CLUSTER3_WIN0_CTRL0 0x1600
985
986 /* DSC 8K/4K register definition */
987 #define RK3588_DSC_8K_PPS0_3 0x4000
988 #define RK3588_DSC_8K_CTRL0 0x40A0
989 #define DSC_EN_SHIFT 0
990 #define DSC_RBIT_SHIFT 2
991 #define DSC_RBYT_SHIFT 3
992 #define DSC_FLAL_SHIFT 4
993 #define DSC_MER_SHIFT 5
994 #define DSC_EPB_SHIFT 6
995 #define DSC_EPL_SHIFT 7
996 #define DSC_NSLC_MASK 0x7
997 #define DSC_NSLC_SHIFT 16
998 #define DSC_SBO_SHIFT 28
999 #define DSC_IFEP_SHIFT 29
1000 #define DSC_PPS_UPD_SHIFT 31
1001 #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \
1002 (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \
1003 (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT))
1004
1005 #define RK3588_DSC_8K_CTRL1 0x40A4
1006 #define RK3588_DSC_8K_STS0 0x40A8
1007 #define RK3588_DSC_8K_ERS 0x40C4
1008
1009 #define RK3588_DSC_4K_PPS0_3 0x4100
1010 #define RK3588_DSC_4K_CTRL0 0x41A0
1011 #define RK3588_DSC_4K_CTRL1 0x41A4
1012 #define RK3588_DSC_4K_STS0 0x41A8
1013 #define RK3588_DSC_4K_ERS 0x41C4
1014
1015 /* RK3528 HDR register definition */
1016 #define RK3528_HDR_LUT_CTRL 0x2000
1017
1018 /* RK3528 ACM register definition */
1019 #define RK3528_ACM_CTRL 0x6400
1020 #define RK3528_ACM_DELTA_RANGE 0x6404
1021 #define RK3528_ACM_FETCH_START 0x6408
1022 #define RK3528_ACM_FETCH_DONE 0x6420
1023 #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500
1024 #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760
1025 #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764
1026 #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4
1027 #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8
1028 #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8
1029
1030 #define RK3568_IOMMU0_DTE_ADDR 0x7e00
1031 #define RK3568_IOMMU0_STATUS 0x7e04
1032 #define MMU_PAGING_EN BIT(0)
1033 #define MMU_PAGE_FAULT_ACTIVE BIT(1)
1034 #define RK3568_IOMMU0_COMMAND 0x7e08
1035 #define MMU_ENABLE_PAGING 0
1036 #define MMU_DISABLE_PAGING 1
1037 #define MMU_FORCE_RESET 6
1038 #define RK3568_IOMMU0_PAGEFAULT_ADDR 0x7e0c
1039
1040 /* RK3576 SHARP register definition */
1041 #define RK3576_SHARP_CTRL 0x0000
1042 #define SW_SHARP_ENABLE_SHIFT 0
1043
1044 #define RK3568_MAX_REG 0x1ED0
1045
1046 #define RK3562_GRF_IOC_VO_IO_CON 0x10500
1047 #define RK3568_GRF_VO_CON1 0x0364
1048 #define GRF_BT656_CLK_INV_SHIFT 1
1049 #define GRF_BT1120_CLK_INV_SHIFT 2
1050 #define GRF_RGB_DCLK_INV_SHIFT 3
1051
1052 /* Base SYS_GRF: 0x2600a000*/
1053 #define RK3576_SYS_GRF_MEMFAULT_STATUS0 0x0148
1054
1055 /* Base IOC_GRF: 0x26040000 */
1056 #define RK3576_VCCIO_IOC_MISC_CON8 0x6420
1057 #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT 9
1058 #define RK3576_IOC_VOPLITE_SEL_SHIFT 11
1059
1060 /* Base PMU2: 0x27380000 */
1061 #define RK3576_PMU_PWR_GATE_STS 0x0230
1062 #define PD_VOP_ESMART_DWN_STAT 12
1063 #define PD_VOP_CLUSTER_DWN_STAT 13
1064 #define RK3576_PMU_BISR_PDGEN_CON0 0x0510
1065 #define PD_VOP_ESMART_REPAIR_ENA_SHIFT 12
1066 #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT 13
1067 #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0 0x0570
1068 #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT 12
1069 #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT 13
1070
1071 #define RK3588_GRF_SOC_CON1 0x0304
1072 #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT 14
1073
1074 #define RK3588_GRF_VOP_CON2 0x0008
1075 #define RK3588_GRF_EDP0_ENABLE_SHIFT 0
1076 #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1
1077 #define RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT 2
1078 #define RK3588_GRF_EDP1_ENABLE_SHIFT 3
1079 #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4
1080 #define RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT 5
1081
1082 #define RK3588_GRF_VO1_CON0 0x0000
1083 #define HDMI_SYNC_POL_MASK 0x3
1084 #define HDMI0_SYNC_POL_SHIFT 5
1085 #define HDMI1_SYNC_POL_SHIFT 7
1086
1087 #define RK3588_PMU_BISR_CON3 0x20C
1088 #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9
1089 #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10
1090 #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11
1091 #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12
1092 #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13
1093 #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14
1094 #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15
1095
1096 #define RK3588_PMU_BISR_STATUS5 0x294
1097 #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9
1098 #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10
1099 #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11
1100 #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12
1101 #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13
1102 #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14
1103 #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15
1104
1105 #define VOP2_LAYER_MAX 8
1106
1107 #define VOP2_MAX_VP_OUTPUT_WIDTH 4096
1108
1109 /* KHz */
1110 #define VOP2_MAX_DCLK_RATE 600000
1111
1112 /*
1113 * vop2 dsc id
1114 */
1115 #define ROCKCHIP_VOP2_DSC_8K 0
1116 #define ROCKCHIP_VOP2_DSC_4K 1
1117
1118 /*
1119 * vop2 internal power domain id,
1120 * should be all none zero, 0 will be
1121 * treat as invalid;
1122 */
1123 #define VOP2_PD_CLUSTER0 BIT(0)
1124 #define VOP2_PD_CLUSTER1 BIT(1)
1125 #define VOP2_PD_CLUSTER2 BIT(2)
1126 #define VOP2_PD_CLUSTER3 BIT(3)
1127 #define VOP2_PD_DSC_8K BIT(5)
1128 #define VOP2_PD_DSC_4K BIT(6)
1129 #define VOP2_PD_ESMART BIT(7)
1130 #define VOP2_PD_CLUSTER BIT(8)
1131
1132 #define VOP2_PLANE_NO_SCALING BIT(16)
1133
1134 #define VOP_FEATURE_OUTPUT_10BIT BIT(0)
1135 #define VOP_FEATURE_AFBDC BIT(1)
1136 #define VOP_FEATURE_ALPHA_SCALE BIT(2)
1137 #define VOP_FEATURE_HDR10 BIT(3)
1138 #define VOP_FEATURE_NEXT_HDR BIT(4)
1139 /* a feature to splice two windows and two vps to support resolution > 4096 */
1140 #define VOP_FEATURE_SPLICE BIT(5)
1141 #define VOP_FEATURE_OVERSCAN BIT(6)
1142 #define VOP_FEATURE_VIVID_HDR BIT(7)
1143 #define VOP_FEATURE_POST_ACM BIT(8)
1144 #define VOP_FEATURE_POST_CSC BIT(9)
1145 #define VOP_FEATURE_POST_FRC_V2 BIT(10)
1146 #define VOP_FEATURE_POST_SHARP BIT(11)
1147
1148 #define WIN_FEATURE_HDR2SDR BIT(0)
1149 #define WIN_FEATURE_SDR2HDR BIT(1)
1150 #define WIN_FEATURE_PRE_OVERLAY BIT(2)
1151 #define WIN_FEATURE_AFBDC BIT(3)
1152 #define WIN_FEATURE_CLUSTER_MAIN BIT(4)
1153 #define WIN_FEATURE_CLUSTER_SUB BIT(5)
1154 /* a mirror win can only get fb address
1155 * from source win:
1156 * Cluster1---->Cluster0
1157 * Esmart1 ---->Esmart0
1158 * Smart1 ---->Smart0
1159 * This is a feather on rk3566
1160 */
1161 #define WIN_FEATURE_MIRROR BIT(6)
1162 #define WIN_FEATURE_MULTI_AREA BIT(7)
1163 #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8)
1164 #define WIN_FEATURE_DCI BIT(9)
1165
1166 #define V4L2_COLORSPACE_BT709F 0xfe
1167 #define V4L2_COLORSPACE_BT2020F 0xff
1168
1169 enum vop_csc_format {
1170 CSC_BT601L,
1171 CSC_BT709L,
1172 CSC_BT601F,
1173 CSC_BT2020L,
1174 CSC_BT709L_13BIT,
1175 CSC_BT709F_13BIT,
1176 CSC_BT2020L_13BIT,
1177 CSC_BT2020F_13BIT,
1178 };
1179
1180 enum vop_csc_bit_depth {
1181 CSC_10BIT_DEPTH,
1182 CSC_13BIT_DEPTH,
1183 };
1184
1185 enum vop2_pol {
1186 HSYNC_POSITIVE = 0,
1187 VSYNC_POSITIVE = 1,
1188 DEN_NEGATIVE = 2,
1189 DCLK_INVERT = 3
1190 };
1191
1192 enum vop2_bcsh_out_mode {
1193 BCSH_OUT_MODE_BLACK,
1194 BCSH_OUT_MODE_BLUE,
1195 BCSH_OUT_MODE_COLOR_BAR,
1196 BCSH_OUT_MODE_NORMAL_VIDEO,
1197 };
1198
1199 #define _VOP_REG(off, _mask, _shift, _write_mask) \
1200 { \
1201 .offset = off, \
1202 .mask = _mask, \
1203 .shift = _shift, \
1204 .write_mask = _write_mask, \
1205 }
1206
1207 #define VOP_REG(off, _mask, _shift) \
1208 _VOP_REG(off, _mask, _shift, false)
1209 enum dither_down_mode {
1210 RGB888_TO_RGB565 = 0x0,
1211 RGB888_TO_RGB666 = 0x1
1212 };
1213
1214 enum dither_down_mode_sel {
1215 DITHER_DOWN_ALLEGRO = 0x0,
1216 DITHER_DOWN_FRC = 0x1
1217 };
1218
1219 enum vop2_video_ports_id {
1220 VOP2_VP0,
1221 VOP2_VP1,
1222 VOP2_VP2,
1223 VOP2_VP3,
1224 VOP2_VP_MAX,
1225 };
1226
1227 enum vop2_layer_type {
1228 CLUSTER_LAYER = 0,
1229 ESMART_LAYER = 1,
1230 SMART_LAYER = 2,
1231 };
1232
1233 enum vop2_plane_type {
1234 VOP2_PLANE_TYPE_OVERLAY = 0,
1235 VOP2_PLANE_TYPE_PRIMARY = 1,
1236 VOP2_PLANE_TYPE_CURSOR = 2,
1237 };
1238
1239 /* This define must same with kernel win phy id */
1240 enum vop2_layer_phy_id {
1241 ROCKCHIP_VOP2_CLUSTER0 = 0,
1242 ROCKCHIP_VOP2_CLUSTER1,
1243 ROCKCHIP_VOP2_ESMART0,
1244 ROCKCHIP_VOP2_ESMART1,
1245 ROCKCHIP_VOP2_SMART0,
1246 ROCKCHIP_VOP2_SMART1,
1247 ROCKCHIP_VOP2_CLUSTER2,
1248 ROCKCHIP_VOP2_CLUSTER3,
1249 ROCKCHIP_VOP2_ESMART2,
1250 ROCKCHIP_VOP2_ESMART3,
1251 ROCKCHIP_VOP2_LAYER_MAX,
1252 ROCKCHIP_VOP2_PHY_ID_INVALID = (u8)-1,
1253 };
1254
1255 enum vop2_scale_up_mode {
1256 VOP2_SCALE_UP_NRST_NBOR,
1257 VOP2_SCALE_UP_BIL,
1258 VOP2_SCALE_UP_BIC,
1259 VOP2_SCALE_UP_ZME,
1260 };
1261
1262 enum vop2_scale_down_mode {
1263 VOP2_SCALE_DOWN_NRST_NBOR,
1264 VOP2_SCALE_DOWN_BIL,
1265 VOP2_SCALE_DOWN_AVG,
1266 VOP2_SCALE_DOWN_ZME,
1267 };
1268
1269 enum scale_mode {
1270 SCALE_NONE = 0x0,
1271 SCALE_UP = 0x1,
1272 SCALE_DOWN = 0x2
1273 };
1274
1275 enum vop_dsc_interface_mode {
1276 VOP_DSC_IF_DISABLE = 0,
1277 VOP_DSC_IF_HDMI = 1,
1278 VOP_DSC_IF_MIPI_DS_MODE = 2,
1279 VOP_DSC_IF_MIPI_VIDEO_MODE = 3,
1280 };
1281
1282 enum vop3_pre_scale_down_mode {
1283 VOP3_PRE_SCALE_UNSPPORT,
1284 VOP3_PRE_SCALE_DOWN_GT,
1285 VOP3_PRE_SCALE_DOWN_AVG,
1286 };
1287
1288 /*
1289 * the delay number of a window in different mode.
1290 */
1291 enum vop2_win_dly_mode {
1292 VOP2_DLY_MODE_DEFAULT, /* default mode */
1293 VOP2_DLY_MODE_HISO_S, /* HDR in SDR out mode, as a SDR window */
1294 VOP2_DLY_MODE_HIHO_H, /* HDR in HDR out mode, as a HDR window */
1295 VOP2_DLY_MODE_DOVI_IN_CORE1, /* dovi video input, as dovi core1 */
1296 VOP2_DLY_MODE_DOVI_IN_CORE2, /* dovi video input, as dovi core2 */
1297 VOP2_DLY_MODE_NONDOVI_IN_CORE1, /* ndovi video input, as dovi core1 */
1298 VOP2_DLY_MODE_NONDOVI_IN_CORE2, /* ndovi video input, as dovi core2 */
1299 VOP2_DLY_MODE_MAX,
1300 };
1301
1302 enum vop3_esmart_lb_mode {
1303 VOP3_ESMART_8K_MODE,
1304 VOP3_ESMART_4K_4K_MODE,
1305 VOP3_ESMART_4K_2K_2K_MODE,
1306 VOP3_ESMART_2K_2K_2K_2K_MODE,
1307 VOP3_ESMART_4K_4K_4K_MODE,
1308 VOP3_ESMART_4K_4K_2K_2K_MODE,
1309 };
1310
1311 struct vop2_layer {
1312 u8 id;
1313 /**
1314 * @win_phys_id: window id of the layer selected.
1315 * Every layer must make sure to select different
1316 * windows of others.
1317 */
1318 u8 win_phys_id;
1319 };
1320
1321 struct vop2_power_domain_data {
1322 u16 id;
1323 u16 parent_id;
1324 /*
1325 * @module_id_mask: module id of which module this power domain is belongs to.
1326 * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3
1327 */
1328 u32 module_id_mask;
1329 };
1330
1331 struct vop2_win_data {
1332 char *name;
1333 u8 phys_id;
1334 enum vop2_layer_type type;
1335 enum vop2_plane_type plane_type;
1336 u8 win_sel_port_offset;
1337 u8 layer_sel_win_id[VOP2_VP_MAX];
1338 u8 axi_id;
1339 u8 axi_uv_id;
1340 u8 axi_yrgb_id;
1341 u8 splice_win_id;
1342 u8 hsu_filter_mode;
1343 u8 hsd_filter_mode;
1344 u8 vsu_filter_mode;
1345 u8 vsd_filter_mode;
1346 u8 hsd_pre_filter_mode;
1347 u8 vsd_pre_filter_mode;
1348 u8 scale_engine_num;
1349 u8 source_win_id;
1350 u8 possible_vp_mask;
1351 u8 dly[VOP2_DLY_MODE_MAX];
1352 u16 pd_id;
1353 u32 reg_offset;
1354 u32 max_upscale_factor;
1355 u32 max_downscale_factor;
1356 u32 feature;
1357 u32 supported_rotations;
1358 bool splice_mode_right;
1359 };
1360
1361 struct vop2_vp_data {
1362 u32 feature;
1363 u32 max_dclk;
1364 u8 pre_scan_max_dly;
1365 u8 layer_mix_dly;
1366 u8 hdrvivid_dly;
1367 u8 sdr2hdr_dly;
1368 u8 hdr_mix_dly;
1369 u8 win_dly;
1370 u8 splice_vp_id;
1371 u8 pixel_rate;
1372 struct vop_rect max_output;
1373 struct vop_urgency *urgency;
1374 };
1375
1376 struct vop2_vp_plane_mask {
1377 u8 primary_plane_id; /* use this win to show logo */
1378 u8 cursor_plane_id;
1379 u8 attached_layers_nr; /* number layers attach to this vp */
1380 u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
1381 u32 plane_mask;
1382 };
1383
1384 struct vop2_dsc_data {
1385 u8 id;
1386 u8 max_slice_num;
1387 u8 max_linebuf_depth; /* used to generate the bitstream */
1388 u8 min_bits_per_pixel; /* bit num after encoder compress */
1389 u16 pd_id;
1390 const char *dsc_txp_clk_src_name;
1391 const char *dsc_txp_clk_name;
1392 const char *dsc_pxl_clk_name;
1393 const char *dsc_cds_clk_name;
1394 };
1395
1396 struct dsc_error_info {
1397 u32 dsc_error_val;
1398 char dsc_error_info[50];
1399 };
1400
1401 struct vop2_dump_regs {
1402 u32 offset;
1403 const char *name;
1404 u32 state_base;
1405 u32 state_mask;
1406 u32 state_shift;
1407 bool enable_state;
1408 u32 size;
1409 };
1410
1411 struct vop2_esmart_lb_map {
1412 u8 lb_mode;
1413 u8 lb_map_value;
1414 };
1415
1416 /**
1417 * struct vop2_ops - helper operations for vop2 hardware
1418 *
1419 * These hooks are used by the common part of the vop2 driver to
1420 * implement the proper behaviour of different variants.
1421 */
1422 struct vop2_ops {
1423 void (*setup_win_dly)(struct display_state *state, int crtc_id, u8 plane_phy_id);
1424 void (*setup_overlay)(struct display_state *state);
1425 void (*assign_plane_mask)(struct display_state *state);
1426 };
1427
1428 struct vop2_data {
1429 u32 version;
1430 u32 esmart_lb_mode;
1431 struct vop2_vp_data *vp_data;
1432 struct vop2_win_data *win_data;
1433 struct vop2_vp_plane_mask *plane_mask;
1434 struct vop2_power_domain_data *pd;
1435 struct vop2_dsc_data *dsc;
1436 struct dsc_error_info *dsc_error_ecw;
1437 struct dsc_error_info *dsc_error_buffer_flow;
1438 struct vop2_dump_regs *dump_regs;
1439 const struct vop2_esmart_lb_map *esmart_lb_mode_map;
1440 const struct vop2_ops *ops;
1441 u8 nr_vps;
1442 u8 nr_layers;
1443 u8 nr_mixers;
1444 u8 nr_gammas;
1445 u8 nr_pd;
1446 u8 nr_dscs;
1447 u8 nr_dsc_ecw;
1448 u8 nr_dsc_buffer_flow;
1449 u8 esmart_lb_mode_num;
1450 u32 reg_len;
1451 u32 dump_regs_size;
1452 u32 plane_mask_base;
1453 };
1454
1455 struct vop2 {
1456 u32 *regsbak;
1457 void *regs;
1458 void *grf;
1459 void *vop_grf;
1460 void *vo1_grf;
1461 void *sys_pmu;
1462 void *ioc_grf;
1463 void *sharp_res;
1464 u32 reg_len;
1465 u32 version;
1466 u32 esmart_lb_mode;
1467 bool global_init;
1468 bool merge_irq;
1469 const struct vop2_data *data;
1470 struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
1471 };
1472
1473 static struct vop2 *rockchip_vop2;
1474
1475 /* vop2_layer_phy_id */
1476 static const char *const vop2_layer_name_list[] = {
1477 "Cluster0",
1478 "Cluster1",
1479 "Esmart0",
1480 "Esmart1",
1481 "Smart0",
1482 "Smart1",
1483 "Cluster2",
1484 "Cluster3",
1485 "Esmart2",
1486 "Esmart3",
1487 };
1488
vop2_plane_phys_id_to_string(u8 phys_id)1489 static inline const char *vop2_plane_phys_id_to_string(u8 phys_id)
1490 {
1491 if (phys_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
1492 return "INVALID";
1493
1494 if (phys_id >= ARRAY_SIZE(vop2_layer_name_list))
1495 return NULL;
1496
1497 return vop2_layer_name_list[phys_id];
1498 }
1499
is_vop3(struct vop2 * vop2)1500 static inline bool is_vop3(struct vop2 *vop2)
1501 {
1502 if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588)
1503 return false;
1504 else
1505 return true;
1506 }
1507
1508 /*
1509 * bli_sd_factor = (src - 1) / (dst - 1) << 12;
1510 * avg_sd_factor:
1511 * bli_su_factor:
1512 * bic_su_factor:
1513 * = (src - 1) / (dst - 1) << 16;
1514 *
1515 * ygt2 enable: dst get one line from two line of the src
1516 * ygt4 enable: dst get one line from four line of the src.
1517 *
1518 */
1519 #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1))
1520 #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1))
1521
1522 #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \
1523 (fac * (dst - 1) >> 12 < (src - 1))
1524 #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
1525 (fac * (dst - 1) >> 16 < (src - 1))
1526 #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
1527 (fac * (dst - 1) >> 16 < (src - 1))
1528
vop2_scale_factor(enum scale_mode mode,int32_t filter_mode,uint32_t src,uint32_t dst)1529 static uint16_t vop2_scale_factor(enum scale_mode mode,
1530 int32_t filter_mode,
1531 uint32_t src, uint32_t dst)
1532 {
1533 uint32_t fac = 0;
1534 int i = 0;
1535
1536 if (mode == SCALE_NONE)
1537 return 0;
1538
1539 /*
1540 * A workaround to avoid zero div.
1541 */
1542 if ((dst == 1) || (src == 1)) {
1543 dst = dst + 1;
1544 src = src + 1;
1545 }
1546
1547 if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
1548 fac = VOP2_BILI_SCL_DN(src, dst);
1549 for (i = 0; i < 100; i++) {
1550 if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
1551 break;
1552 fac -= 1;
1553 printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1554 }
1555 } else {
1556 fac = VOP2_COMMON_SCL(src, dst);
1557 for (i = 0; i < 100; i++) {
1558 if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
1559 break;
1560 fac -= 1;
1561 printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1562 }
1563 }
1564
1565 return fac;
1566 }
1567
vop3_scale_up_fac_check(uint32_t src,uint32_t dst,uint32_t fac,bool is_hor)1568 static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor)
1569 {
1570 if (is_hor)
1571 return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac);
1572 return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac);
1573 }
1574
vop3_scale_factor(enum scale_mode mode,uint32_t src,uint32_t dst,bool is_hor)1575 static uint16_t vop3_scale_factor(enum scale_mode mode,
1576 uint32_t src, uint32_t dst, bool is_hor)
1577 {
1578 uint32_t fac = 0;
1579 int i = 0;
1580
1581 if (mode == SCALE_NONE)
1582 return 0;
1583
1584 /*
1585 * A workaround to avoid zero div.
1586 */
1587 if ((dst == 1) || (src == 1)) {
1588 dst = dst + 1;
1589 src = src + 1;
1590 }
1591
1592 if (mode == SCALE_DOWN) {
1593 fac = VOP2_BILI_SCL_DN(src, dst);
1594 for (i = 0; i < 100; i++) {
1595 if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
1596 break;
1597 fac -= 1;
1598 printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1599 }
1600 } else {
1601 fac = VOP2_COMMON_SCL(src, dst);
1602 for (i = 0; i < 100; i++) {
1603 if (vop3_scale_up_fac_check(src, dst, fac, is_hor))
1604 break;
1605 fac -= 1;
1606 printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
1607 }
1608 }
1609
1610 return fac;
1611 }
1612
scl_get_scl_mode(int src,int dst)1613 static inline enum scale_mode scl_get_scl_mode(int src, int dst)
1614 {
1615 if (src < dst)
1616 return SCALE_UP;
1617 else if (src > dst)
1618 return SCALE_DOWN;
1619
1620 return SCALE_NONE;
1621 }
1622
interpolate(int x1,int y1,int x2,int y2,int x)1623 static inline int interpolate(int x1, int y1, int x2, int y2, int x)
1624 {
1625 return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
1626 }
1627
vop2_win_can_attach_to_vp(struct vop2_win_data * win_data,u8 vp_id)1628 static inline bool vop2_win_can_attach_to_vp(struct vop2_win_data *win_data, u8 vp_id)
1629 {
1630 return win_data->possible_vp_mask & BIT(vp_id);
1631 }
1632
vop2_vp_find_attachable_win(struct display_state * state,u8 vp_id)1633 static int vop2_vp_find_attachable_win(struct display_state *state, u8 vp_id)
1634 {
1635 struct crtc_state *cstate = &state->crtc_state;
1636 struct vop2 *vop2 = cstate->private;
1637 u32 plane_mask = cstate->crtc->vps[vp_id].plane_mask;
1638 int i = 0;
1639
1640 if (!plane_mask)
1641 return ROCKCHIP_VOP2_PHY_ID_INVALID;
1642
1643 for (i = 0; i < vop2->data->nr_layers; i++) {
1644 if (vop2_win_can_attach_to_vp(&vop2->data->win_data[i], vp_id))
1645 break;
1646 }
1647
1648 return vop2->data->win_data[i].phys_id;
1649 }
1650
scl_cal_scale(int src,int dst,int shift)1651 static inline u16 scl_cal_scale(int src, int dst, int shift)
1652 {
1653 return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
1654 }
1655
scl_cal_scale2(int src,int dst)1656 static inline u16 scl_cal_scale2(int src, int dst)
1657 {
1658 return ((src - 1) << 12) / (dst - 1);
1659 }
1660
vop2_writel(struct vop2 * vop2,u32 offset,u32 v)1661 static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
1662 {
1663 writel(v, vop2->regs + offset);
1664 vop2->regsbak[offset >> 2] = v;
1665 }
1666
vop2_readl(struct vop2 * vop2,u32 offset)1667 static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
1668 {
1669 return readl(vop2->regs + offset);
1670 }
1671
vop2_mask_write(struct vop2 * vop2,u32 offset,u32 mask,u32 shift,u32 v,bool write_mask)1672 static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
1673 u32 mask, u32 shift, u32 v,
1674 bool write_mask)
1675 {
1676 if (!mask)
1677 return;
1678
1679 if (write_mask) {
1680 v = ((v & mask) << shift) | (mask << (shift + 16));
1681 } else {
1682 u32 cached_val = vop2->regsbak[offset >> 2];
1683
1684 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
1685 vop2->regsbak[offset >> 2] = v;
1686 }
1687
1688 writel(v, vop2->regs + offset);
1689 }
1690
vop2_grf_writel(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift,u32 v)1691 static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
1692 u32 mask, u32 shift, u32 v)
1693 {
1694 u32 val = 0;
1695
1696 val = (v << shift) | (mask << (shift + 16));
1697 writel(val, grf_base + offset);
1698 }
1699
vop2_grf_readl(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift)1700 static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
1701 u32 mask, u32 shift)
1702 {
1703 return (readl(grf_base + offset) >> shift) & mask;
1704 }
1705
is_yuv_output(u32 bus_format)1706 static bool is_yuv_output(u32 bus_format)
1707 {
1708 switch (bus_format) {
1709 case MEDIA_BUS_FMT_YUV8_1X24:
1710 case MEDIA_BUS_FMT_YUV10_1X30:
1711 case MEDIA_BUS_FMT_YUYV10_1X20:
1712 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1713 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1714 case MEDIA_BUS_FMT_YUYV8_2X8:
1715 case MEDIA_BUS_FMT_YVYU8_2X8:
1716 case MEDIA_BUS_FMT_UYVY8_2X8:
1717 case MEDIA_BUS_FMT_VYUY8_2X8:
1718 case MEDIA_BUS_FMT_YUYV8_1X16:
1719 case MEDIA_BUS_FMT_YVYU8_1X16:
1720 case MEDIA_BUS_FMT_UYVY8_1X16:
1721 case MEDIA_BUS_FMT_VYUY8_1X16:
1722 return true;
1723 default:
1724 return false;
1725 }
1726 }
1727
vop2_convert_csc_mode(enum drm_color_encoding color_encoding,enum drm_color_range color_range,int bit_depth)1728 static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding,
1729 enum drm_color_range color_range,
1730 int bit_depth)
1731 {
1732 bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
1733 enum vop_csc_format csc_mode = CSC_BT709L;
1734
1735
1736 switch (color_encoding) {
1737 case DRM_COLOR_YCBCR_BT601:
1738 if (full_range)
1739 csc_mode = CSC_BT601F;
1740 else
1741 csc_mode = CSC_BT601L;
1742 break;
1743
1744 case DRM_COLOR_YCBCR_BT709:
1745 if (full_range) {
1746 csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F;
1747 if (bit_depth != CSC_13BIT_DEPTH)
1748 printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n");
1749 } else {
1750 csc_mode = CSC_BT709L;
1751 }
1752 break;
1753
1754 case DRM_COLOR_YCBCR_BT2020:
1755 if (full_range) {
1756 csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F;
1757 if (bit_depth != CSC_13BIT_DEPTH)
1758 printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n");
1759 } else {
1760 csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L;
1761 }
1762 break;
1763
1764 default:
1765 printf("Unsuport color_encoding:%d\n", color_encoding);
1766 }
1767
1768 return csc_mode;
1769 }
1770
is_uv_swap(struct display_state * state)1771 static bool is_uv_swap(struct display_state *state)
1772 {
1773 struct connector_state *conn_state = &state->conn_state;
1774 u32 bus_format = conn_state->bus_format;
1775 u32 output_mode = conn_state->output_mode;
1776 u32 output_type = conn_state->type;
1777
1778 /*
1779 * FIXME:
1780 *
1781 * There is no media type for YUV444 output,
1782 * so when out_mode is AAAA or P888, assume output is YUV444 on
1783 * yuv format.
1784 *
1785 * From H/W testing, YUV444 mode need a rb swap except eDP.
1786 */
1787 if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
1788 bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
1789 bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
1790 bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
1791 ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1792 bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1793 (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
1794 output_mode == ROCKCHIP_OUT_MODE_P888) &&
1795 !(output_type == DRM_MODE_CONNECTOR_eDP)))
1796 return true;
1797 else
1798 return false;
1799 }
1800
is_rb_swap(struct display_state * state)1801 static bool is_rb_swap(struct display_state *state)
1802 {
1803 struct connector_state *conn_state = &state->conn_state;
1804 u32 bus_format = conn_state->bus_format;
1805
1806 /*
1807 * The default component order of serial rgb3x8 formats
1808 * is BGR. So it is needed to enable RB swap.
1809 */
1810 if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
1811 bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8)
1812 return true;
1813 else
1814 return false;
1815 }
1816
is_yc_swap(u32 bus_format)1817 static bool is_yc_swap(u32 bus_format)
1818 {
1819 switch (bus_format) {
1820 case MEDIA_BUS_FMT_YUYV8_1X16:
1821 case MEDIA_BUS_FMT_YVYU8_1X16:
1822 case MEDIA_BUS_FMT_YUYV8_2X8:
1823 case MEDIA_BUS_FMT_YVYU8_2X8:
1824 return true;
1825 default:
1826 return false;
1827 }
1828 }
1829
is_hot_plug_devices(int output_type)1830 static inline bool is_hot_plug_devices(int output_type)
1831 {
1832 switch (output_type) {
1833 case DRM_MODE_CONNECTOR_HDMIA:
1834 case DRM_MODE_CONNECTOR_HDMIB:
1835 case DRM_MODE_CONNECTOR_TV:
1836 case DRM_MODE_CONNECTOR_DisplayPort:
1837 case DRM_MODE_CONNECTOR_VGA:
1838 case DRM_MODE_CONNECTOR_Unknown:
1839 return true;
1840 default:
1841 return false;
1842 }
1843 }
1844
vop2_find_win_by_phys_id(struct vop2 * vop2,int phys_id)1845 static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1846 {
1847 int i = 0;
1848
1849 for (i = 0; i < vop2->data->nr_layers; i++) {
1850 if (vop2->data->win_data[i].phys_id == phys_id)
1851 return &vop2->data->win_data[i];
1852 }
1853
1854 return NULL;
1855 }
1856
vop2_find_pd_data_by_id(struct vop2 * vop2,int pd_id)1857 static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id)
1858 {
1859 int i = 0;
1860
1861 for (i = 0; i < vop2->data->nr_pd; i++) {
1862 if (vop2->data->pd[i].id == pd_id)
1863 return &vop2->data->pd[i];
1864 }
1865
1866 return NULL;
1867 }
1868
rk3568_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1869 static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1870 u32 *lut_regs, u32 *lut_val, int lut_len)
1871 {
1872 u32 vp_offset = crtc_id * 0x100;
1873 int i;
1874
1875 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1876 GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1877 crtc_id, false);
1878
1879 for (i = 0; i < lut_len; i++)
1880 writel(lut_val[i], lut_regs + i);
1881
1882 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1883 EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1884 }
1885
rk3588_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1886 static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1887 u32 *lut_regs, u32 *lut_val, int lut_len)
1888 {
1889 u32 vp_offset = crtc_id * 0x100;
1890 int i;
1891
1892 if (vop2->version == VOP_VERSION_RK3576)
1893 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1894 GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1895 crtc_id, true);
1896 else
1897 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1898 GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1899 crtc_id, false);
1900
1901 for (i = 0; i < lut_len; i++)
1902 writel(lut_val[i], lut_regs + i);
1903
1904 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1905 EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1906 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1907 EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false);
1908 }
1909
rockchip_vop2_gamma_lut_init(struct vop2 * vop2,struct display_state * state)1910 static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1911 struct display_state *state)
1912 {
1913 struct connector_state *conn_state = &state->conn_state;
1914 struct crtc_state *cstate = &state->crtc_state;
1915 struct resource gamma_res;
1916 fdt_size_t lut_size;
1917 int i, lut_len, ret = 0;
1918 u32 *lut_regs;
1919 u32 r, g, b;
1920 struct base2_disp_info *disp_info = conn_state->disp_info;
1921 static int gamma_lut_en_num = 1;
1922
1923 if (gamma_lut_en_num > vop2->data->nr_gammas) {
1924 printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
1925 return 0;
1926 }
1927
1928 ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
1929 if (ret)
1930 printf("failed to get gamma lut res\n");
1931 lut_regs = (u32 *)gamma_res.start;
1932 lut_size = gamma_res.end - gamma_res.start + 1;
1933 if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
1934 printf("failed to get gamma lut register\n");
1935 return 0;
1936 }
1937 lut_len = lut_size / 4;
1938 if (lut_len != 256 && lut_len != 1024) {
1939 printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
1940 return 0;
1941 }
1942
1943 if (!cstate->lut_val) {
1944 if (!disp_info)
1945 return 0;
1946
1947 if (!disp_info->gamma_lut_data.size)
1948 return 0;
1949
1950 cstate->lut_val = (u32 *)calloc(1, lut_size);
1951 for (i = 0; i < lut_len; i++) {
1952 r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
1953 g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
1954 b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
1955
1956 cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
1957 }
1958 }
1959
1960 if (vop2->version == VOP_VERSION_RK3568) {
1961 rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
1962 cstate->lut_val, lut_len);
1963 gamma_lut_en_num++;
1964 } else {
1965 rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
1966 cstate->lut_val, lut_len);
1967 if (cstate->splice_mode) {
1968 rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs,
1969 cstate->lut_val, lut_len);
1970 gamma_lut_en_num++;
1971 }
1972 gamma_lut_en_num++;
1973 }
1974
1975 free(cstate->lut_val);
1976
1977 return 0;
1978 }
1979
rockchip_vop2_cubic_lut_init(struct vop2 * vop2,struct display_state * state)1980 static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
1981 struct display_state *state)
1982 {
1983 struct connector_state *conn_state = &state->conn_state;
1984 struct crtc_state *cstate = &state->crtc_state;
1985 int i, cubic_lut_len;
1986 u32 vp_offset = cstate->crtc_id * 0x100;
1987 struct base2_disp_info *disp_info = conn_state->disp_info;
1988 struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
1989 u32 *cubic_lut_addr;
1990
1991 if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
1992 return 0;
1993
1994 if (!disp_info->cubic_lut_data.size)
1995 return 0;
1996
1997 cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
1998 cubic_lut_len = disp_info->cubic_lut_data.size;
1999
2000 for (i = 0; i < cubic_lut_len / 2; i++) {
2001 *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
2002 ((lut->lgreen[2 * i] & 0xfff) << 12) +
2003 ((lut->lblue[2 * i] & 0xff) << 24);
2004 *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
2005 ((lut->lred[2 * i + 1] & 0xfff) << 4) +
2006 ((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
2007 ((lut->lblue[2 * i + 1] & 0xf) << 28);
2008 *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
2009 *cubic_lut_addr++ = 0;
2010 }
2011
2012 if (cubic_lut_len % 2) {
2013 *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
2014 ((lut->lgreen[2 * i] & 0xfff) << 12) +
2015 ((lut->lblue[2 * i] & 0xff) << 24);
2016 *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
2017 *cubic_lut_addr++ = 0;
2018 *cubic_lut_addr = 0;
2019 }
2020
2021 vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
2022 get_cubic_lut_buffer(cstate->crtc_id));
2023 vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
2024 EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
2025 vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
2026 EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
2027 vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
2028 EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
2029
2030 return 0;
2031 }
2032
vop2_bcsh_reg_update(struct display_state * state,struct vop2 * vop2,struct bcsh_state * bcsh_state,int crtc_id)2033 static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2,
2034 struct bcsh_state *bcsh_state, int crtc_id)
2035 {
2036 struct crtc_state *cstate = &state->crtc_state;
2037 u32 vp_offset = crtc_id * 0x100;
2038
2039 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
2040 BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false);
2041 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
2042 BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false);
2043
2044 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
2045 BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2046 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
2047 BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2048
2049 if (!cstate->bcsh_en) {
2050 vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2051 BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
2052 return;
2053 }
2054
2055 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2056 BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
2057 bcsh_state->brightness, false);
2058 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2059 BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false);
2060 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2061 BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
2062 bcsh_state->saturation * bcsh_state->contrast / 0x100, false);
2063 vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2064 BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false);
2065 vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2066 BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false);
2067 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2068 BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
2069 BCSH_OUT_MODE_NORMAL_VIDEO, false);
2070 vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2071 BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
2072 }
2073
vop2_tv_config_update(struct display_state * state,struct vop2 * vop2)2074 static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
2075 {
2076 struct connector_state *conn_state = &state->conn_state;
2077 struct base_bcsh_info *bcsh_info;
2078 struct crtc_state *cstate = &state->crtc_state;
2079 struct bcsh_state bcsh_state;
2080 int brightness, contrast, saturation, hue, sin_hue, cos_hue;
2081
2082 if (!conn_state->disp_info)
2083 return;
2084 bcsh_info = &conn_state->disp_info->bcsh_info;
2085 if (!bcsh_info)
2086 return;
2087
2088 if (bcsh_info->brightness != 50 ||
2089 bcsh_info->contrast != 50 ||
2090 bcsh_info->saturation != 50 || bcsh_info->hue != 50)
2091 cstate->bcsh_en = true;
2092
2093 if (cstate->bcsh_en) {
2094 if (!cstate->yuv_overlay)
2095 cstate->post_r2y_en = 1;
2096 if (!is_yuv_output(conn_state->bus_format))
2097 cstate->post_y2r_en = 1;
2098 } else {
2099 if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2100 cstate->post_r2y_en = 1;
2101 if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2102 cstate->post_y2r_en = 1;
2103 }
2104
2105 cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2106 conn_state->color_range,
2107 CSC_10BIT_DEPTH);
2108
2109 if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
2110 brightness = interpolate(0, -128, 100, 127,
2111 bcsh_info->brightness);
2112 else
2113 brightness = interpolate(0, -32, 100, 31,
2114 bcsh_info->brightness);
2115 contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
2116 saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
2117 hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
2118
2119
2120 /*
2121 * a:[-30~0):
2122 * sin_hue = 0x100 - sin(a)*256;
2123 * cos_hue = cos(a)*256;
2124 * a:[0~30]
2125 * sin_hue = sin(a)*256;
2126 * cos_hue = cos(a)*256;
2127 */
2128 sin_hue = fixp_sin32(hue) >> 23;
2129 cos_hue = fixp_cos32(hue) >> 23;
2130
2131 bcsh_state.brightness = brightness;
2132 bcsh_state.contrast = contrast;
2133 bcsh_state.saturation = saturation;
2134 bcsh_state.sin_hue = sin_hue;
2135 bcsh_state.cos_hue = cos_hue;
2136
2137 vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id);
2138 if (cstate->splice_mode)
2139 vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id);
2140 }
2141
vop2_setup_dly_for_vp(struct display_state * state,struct vop2 * vop2,int crtc_id)2142 static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id)
2143 {
2144 struct connector_state *conn_state = &state->conn_state;
2145 struct drm_display_mode *mode = &conn_state->mode;
2146 struct crtc_state *cstate = &state->crtc_state;
2147 u32 bg_ovl_dly, bg_dly, pre_scan_dly;
2148 u16 hdisplay = mode->crtc_hdisplay;
2149 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2150
2151 bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly;
2152 bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly;
2153 bg_dly -= bg_ovl_dly;
2154
2155 /*
2156 * splice mode: hdisplay must roundup as 4 pixel,
2157 * no splice mode: hdisplay must roundup as 2 pixel.
2158 */
2159 if (cstate->splice_mode)
2160 pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1;
2161 else
2162 pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2163
2164 if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
2165 hsync_len = 8;
2166 pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
2167 vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4,
2168 BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2169 vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2170 }
2171
vop3_setup_pipe_dly(struct display_state * state,struct vop2 * vop2,int crtc_id)2172 static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id)
2173 {
2174 struct connector_state *conn_state = &state->conn_state;
2175 struct drm_display_mode *mode = &conn_state->mode;
2176 u32 bg_dly, pre_scan_dly;
2177 u16 hdisplay = mode->crtc_hdisplay;
2178 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2179
2180 bg_dly = vop2->data->vp_data[crtc_id].win_dly +
2181 vop2->data->vp_data[crtc_id].layer_mix_dly +
2182 vop2->data->vp_data[crtc_id].hdr_mix_dly;
2183 /* hdisplay must roundup as 2 pixel */
2184 pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2185 /**
2186 * pre_scan_hblank minimum value is 8, otherwise the win reset signal will
2187 * lead to first line data be zero.
2188 */
2189 pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len);
2190 vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100,
2191 BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2192 vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2193 }
2194
vop2_post_config(struct display_state * state,struct vop2 * vop2)2195 static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
2196 {
2197 struct connector_state *conn_state = &state->conn_state;
2198 struct drm_display_mode *mode = &conn_state->mode;
2199 struct crtc_state *cstate = &state->crtc_state;
2200 const struct vop2_data *vop2_data = vop2->data;
2201 const struct vop2_ops *vop2_ops = vop2_data->ops;
2202 struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[cstate->crtc_id];
2203 u32 vp_offset = (cstate->crtc_id * 0x100);
2204 u16 vtotal = mode->crtc_vtotal;
2205 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
2206 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
2207 u16 hdisplay = mode->crtc_hdisplay;
2208 u16 vdisplay = mode->crtc_vdisplay;
2209 u16 hsize;
2210 u16 vsize;
2211 u16 hact_end, vact_end;
2212 u32 val;
2213
2214 /*
2215 * For RK3576, use the win scale instead of the post scale to configure
2216 * overscan parameters, because the sharp/post scale/split functions are
2217 * mutually exclusice.
2218 */
2219 if (vop2->version == VOP_VERSION_RK3576) {
2220 hsize = hdisplay;
2221 vsize = vdisplay;
2222
2223 cstate->overscan_by_win_scale = true;
2224 } else {
2225 hsize = hdisplay * (conn_state->overscan.left_margin +
2226 conn_state->overscan.right_margin) / 200;
2227 vsize = vdisplay * (conn_state->overscan.top_margin +
2228 conn_state->overscan.bottom_margin) / 200;
2229 hsize = round_down(hsize, 2);
2230 vsize = round_down(vsize, 2);
2231
2232 hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
2233 vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
2234 }
2235
2236 hact_end = hact_st + hsize;
2237 val = hact_st << 16;
2238 val |= hact_end;
2239 vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
2240 vact_end = vact_st + vsize;
2241 val = vact_st << 16;
2242 val |= vact_end;
2243 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
2244 val = scl_cal_scale2(vdisplay, vsize) << 16;
2245 val |= scl_cal_scale2(hdisplay, hsize);
2246 vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
2247 #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0)
2248 #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1)
2249 vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
2250 RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT,
2251 POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
2252 POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false);
2253 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
2254 u16 vact_st_f1 = vtotal + vact_st + 1;
2255 u16 vact_end_f1 = vact_st_f1 + vsize;
2256
2257 val = vact_st_f1 << 16 | vact_end_f1;
2258 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
2259 }
2260
2261 if (is_vop3(vop2)) {
2262 vop3_setup_pipe_dly(state, vop2, cstate->crtc_id);
2263 } else {
2264 vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id);
2265 vop2_ops->setup_win_dly(state, cstate->crtc_id, plane_mask->primary_plane_id);
2266 if (cstate->splice_mode) {
2267 plane_mask = &vop2->vp_plane_mask[cstate->splice_crtc_id];
2268 vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id);
2269 vop2_ops->setup_win_dly(state, cstate->splice_crtc_id, plane_mask->primary_plane_id);
2270 }
2271 }
2272 }
2273
vop3_post_acm_config(struct display_state * state,struct vop2 * vop2)2274 static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2)
2275 {
2276 struct connector_state *conn_state = &state->conn_state;
2277 struct crtc_state *cstate = &state->crtc_state;
2278 struct acm_data *acm = &conn_state->disp_info->acm_data;
2279 struct drm_display_mode *mode = &conn_state->mode;
2280 u32 vp_offset = (cstate->crtc_id * 0x100);
2281 s16 *lut_y;
2282 s16 *lut_h;
2283 s16 *lut_s;
2284 u32 value;
2285 int i;
2286
2287 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2288 POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2289 if (!acm->acm_enable) {
2290 writel(0, vop2->regs + RK3528_ACM_CTRL);
2291 return;
2292 }
2293
2294 printf("post acm enable\n");
2295
2296 writel(1, vop2->regs + RK3528_ACM_FETCH_START);
2297
2298 value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) +
2299 ((mode->vdisplay & 0xfff) << 20);
2300 writel(value, vop2->regs + RK3528_ACM_CTRL);
2301
2302 value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
2303 ((acm->s_gain << 20) & 0x3ff00000);
2304 writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE);
2305
2306 lut_y = &acm->gain_lut_hy[0];
2307 lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
2308 lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
2309 for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
2310 value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
2311 ((lut_s[i] << 16) & 0xff0000);
2312 writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
2313 }
2314
2315 lut_y = &acm->gain_lut_hs[0];
2316 lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
2317 lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
2318 for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
2319 value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
2320 ((lut_s[i] << 16) & 0xff0000);
2321 writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
2322 }
2323
2324 lut_y = &acm->delta_lut_h[0];
2325 lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
2326 lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
2327 for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
2328 value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
2329 ((lut_s[i] << 20) & 0x3ff00000);
2330 writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
2331 }
2332
2333 writel(1, vop2->regs + RK3528_ACM_FETCH_DONE);
2334 }
2335
vop3_get_csc_info_from_bcsh(struct display_state * state,struct csc_info * csc_info)2336 static void vop3_get_csc_info_from_bcsh(struct display_state *state,
2337 struct csc_info *csc_info)
2338 {
2339 struct connector_state *conn_state = &state->conn_state;
2340 struct base_bcsh_info *bcsh_info;
2341
2342 if (!conn_state->disp_info)
2343 return;
2344
2345 bcsh_info = &conn_state->disp_info->bcsh_info;
2346 if (!bcsh_info)
2347 return;
2348
2349 csc_info->r_gain = 256;
2350 csc_info->g_gain = 256;
2351 csc_info->b_gain = 256;
2352 csc_info->r_offset = 256;
2353 csc_info->g_offset = 256;
2354 csc_info->b_offset = 256;
2355 if (bcsh_info->brightness == 50 && bcsh_info->contrast == 50 &&
2356 bcsh_info->saturation == 50 && bcsh_info->hue == 50) {
2357 csc_info->csc_enable = false;
2358 csc_info->brightness = 256;
2359 csc_info->contrast = 256;
2360 csc_info->saturation = 256;
2361 csc_info->hue = 256;
2362 } else {
2363 csc_info->csc_enable = true;
2364 csc_info->brightness = bcsh_info->brightness * 511 / 100;
2365 csc_info->contrast = bcsh_info->contrast * 511 / 100;
2366 csc_info->saturation = bcsh_info->saturation * 511 / 100;
2367 csc_info->hue = bcsh_info->hue * 511 / 100;
2368 }
2369 }
2370
vop3_post_csc_config(struct display_state * state,struct vop2 * vop2)2371 static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2)
2372 {
2373 struct connector_state *conn_state = &state->conn_state;
2374 struct crtc_state *cstate = &state->crtc_state;
2375 struct acm_data *acm = &conn_state->disp_info->acm_data;
2376 struct csc_info *csc = &conn_state->disp_info->csc_info;
2377 struct post_csc_coef csc_coef;
2378 bool is_input_yuv = false;
2379 bool is_output_yuv = false;
2380 bool post_r2y_en = false;
2381 bool post_csc_en = false;
2382 u32 vp_offset = (cstate->crtc_id * 0x100);
2383 u32 value;
2384 int range_type;
2385
2386 printf("post csc enable\n");
2387
2388 if (!csc->csc_enable)
2389 vop3_get_csc_info_from_bcsh(state, csc);
2390
2391 if (acm->acm_enable) {
2392 if (!cstate->yuv_overlay)
2393 post_r2y_en = true;
2394
2395 /* do y2r in csc module */
2396 if (!is_yuv_output(conn_state->bus_format))
2397 post_csc_en = true;
2398 } else {
2399 if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2400 post_r2y_en = true;
2401
2402 /* do y2r in csc module */
2403 if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2404 post_csc_en = true;
2405 }
2406
2407 if (csc->csc_enable)
2408 post_csc_en = true;
2409
2410 if (cstate->yuv_overlay || post_r2y_en)
2411 is_input_yuv = true;
2412
2413 if (is_yuv_output(conn_state->bus_format))
2414 is_output_yuv = true;
2415
2416 cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2417 conn_state->color_range,
2418 CSC_13BIT_DEPTH);
2419
2420 if (post_csc_en) {
2421 rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv,
2422 is_output_yuv);
2423
2424 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2425 POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT,
2426 csc_coef.csc_coef00, false);
2427 value = csc_coef.csc_coef01 & 0xffff;
2428 value |= (csc_coef.csc_coef02 << 16) & 0xffff0000;
2429 writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02);
2430 value = csc_coef.csc_coef10 & 0xffff;
2431 value |= (csc_coef.csc_coef11 << 16) & 0xffff0000;
2432 writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11);
2433 value = csc_coef.csc_coef12 & 0xffff;
2434 value |= (csc_coef.csc_coef20 << 16) & 0xffff0000;
2435 writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20);
2436 value = csc_coef.csc_coef21 & 0xffff;
2437 value |= (csc_coef.csc_coef22 << 16) & 0xffff0000;
2438 writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22);
2439 writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0);
2440 writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1);
2441 writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2);
2442
2443 range_type = csc_coef.range_type ? 0 : 1;
2444 range_type <<= is_input_yuv ? 0 : 1;
2445 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2446 POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false);
2447 }
2448
2449 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2450 POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false);
2451 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2452 POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false);
2453 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2454 POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false);
2455 }
2456
vop3_post_config(struct display_state * state,struct vop2 * vop2)2457 static void vop3_post_config(struct display_state *state, struct vop2 *vop2)
2458 {
2459 struct connector_state *conn_state = &state->conn_state;
2460 struct base2_disp_info *disp_info = conn_state->disp_info;
2461 const char *enable_flag;
2462 if (!disp_info) {
2463 printf("disp_info is empty\n");
2464 return;
2465 }
2466
2467 enable_flag = (const char *)&disp_info->cacm_header;
2468 if (strncasecmp(enable_flag, "CACM", 4)) {
2469 printf("acm and csc is not support\n");
2470 return;
2471 }
2472
2473 vop3_post_acm_config(state, vop2);
2474 vop3_post_csc_config(state, vop2);
2475 }
2476
rk3576_vop2_wait_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2477 static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2,
2478 struct vop2_power_domain_data *pd_data)
2479 {
2480 int val = 0;
2481 bool is_bisr_en, is_otp_bisr_en;
2482
2483 if (pd_data->id == VOP2_PD_CLUSTER) {
2484 is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2485 EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2486 is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2487 EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2488 if (is_bisr_en && is_otp_bisr_en)
2489 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2490 val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1),
2491 50 * 1000);
2492 else
2493 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2494 val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1),
2495 50 * 1000);
2496 } else {
2497 is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2498 EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2499 is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2500 EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2501 if (is_bisr_en && is_otp_bisr_en)
2502 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2503 val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1),
2504 50 * 1000);
2505 else
2506 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2507 val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1),
2508 50 * 1000);
2509 }
2510 }
2511
rk3576_vop2_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2512 static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2513 {
2514 int ret = 0;
2515
2516 if (pd_data->id == VOP2_PD_CLUSTER)
2517 vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK,
2518 RK3576_CLUSTER_PD_EN_SHIFT, 0, true);
2519 else
2520 vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK,
2521 RK3576_ESMART_PD_EN_SHIFT, 0, true);
2522 ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data);
2523 if (ret) {
2524 printf("wait vop2 power domain timeout\n");
2525 return ret;
2526 }
2527
2528 return 0;
2529 }
2530
rk3588_vop2_wait_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2531 static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2,
2532 struct vop2_power_domain_data *pd_data)
2533 {
2534 int val = 0;
2535 int shift = 0;
2536 int shift_factor = 0;
2537 bool is_bisr_en = false;
2538
2539 /*
2540 * The order of pd status bits in BISR_STS register
2541 * is different from that in VOP SYS_STS register.
2542 */
2543 if (pd_data->id == VOP2_PD_DSC_8K ||
2544 pd_data->id == VOP2_PD_DSC_4K ||
2545 pd_data->id == VOP2_PD_ESMART)
2546 shift_factor = 1;
2547
2548 shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor;
2549 is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift);
2550 if (is_bisr_en) {
2551 shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor;
2552
2553 return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
2554 ((val >> shift) & 0x1), 50 * 1000);
2555 } else {
2556 shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1;
2557
2558 return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
2559 !((val >> shift) & 0x1), 50 * 1000);
2560 }
2561 }
2562
rk3588_vop2_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2563 static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2564 {
2565 int ret = 0;
2566
2567 vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK,
2568 RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false);
2569 ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data);
2570 if (ret) {
2571 printf("wait vop2 power domain timeout\n");
2572 return ret;
2573 }
2574
2575 return 0;
2576 }
2577
vop2_power_domain_on(struct vop2 * vop2,int pd_id)2578 static int vop2_power_domain_on(struct vop2 *vop2, int pd_id)
2579 {
2580 struct vop2_power_domain_data *pd_data;
2581 int ret = 0;
2582
2583 if (!pd_id)
2584 return 0;
2585
2586 pd_data = vop2_find_pd_data_by_id(vop2, pd_id);
2587 if (!pd_data) {
2588 printf("can't find pd_data by id\n");
2589 return -EINVAL;
2590 }
2591
2592 if (pd_data->parent_id) {
2593 ret = vop2_power_domain_on(vop2, pd_data->parent_id);
2594 if (ret) {
2595 printf("can't open parent power domain\n");
2596 return -EINVAL;
2597 }
2598 }
2599
2600 /*
2601 * Read VOP internal power domain on/off status.
2602 * We should query BISR_STS register in PMU for
2603 * power up/down status when memory repair is enabled.
2604 * Return value: 1 for power on, 0 for power off;
2605 */
2606 if (vop2->version == VOP_VERSION_RK3576)
2607 ret = rk3576_vop2_power_domain_on(vop2, pd_data);
2608 else
2609 ret = rk3588_vop2_power_domain_on(vop2, pd_data);
2610
2611 return ret;
2612 }
2613
rk3588_vop2_regsbak(struct vop2 * vop2)2614 static void rk3588_vop2_regsbak(struct vop2 *vop2)
2615 {
2616 u32 *base = vop2->regs;
2617 int i = 0;
2618
2619 /*
2620 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
2621 */
2622 for (i = 0; i < (vop2->reg_len >> 2); i++)
2623 vop2->regsbak[i] = base[i];
2624 }
2625
vop3_ignore_plane(struct vop2 * vop2,struct vop2_win_data * win)2626 static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win)
2627 {
2628 if (!is_vop3(vop2))
2629 return false;
2630
2631 if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
2632 win->phys_id != ROCKCHIP_VOP2_ESMART0)
2633 return true;
2634 else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
2635 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
2636 return true;
2637 else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
2638 win->phys_id == ROCKCHIP_VOP2_ESMART1)
2639 return true;
2640 else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE &&
2641 win->phys_id == ROCKCHIP_VOP2_ESMART3)
2642 return true;
2643 else
2644 return false;
2645 }
2646
vop3_init_esmart_scale_engine(struct vop2 * vop2)2647 static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
2648 {
2649 struct vop2_win_data *win_data;
2650 int i;
2651 u8 scale_engine_num = 0;
2652
2653 /* store plane mask for vop2_fixup_dts */
2654 for (i = 0; i < vop2->data->nr_layers; i++) {
2655 win_data = &vop2->data->win_data[i];
2656 if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data))
2657 continue;
2658
2659 win_data->scale_engine_num = scale_engine_num++;
2660 }
2661 }
2662
vop3_get_esmart_lb_mode(struct vop2 * vop2)2663 static int vop3_get_esmart_lb_mode(struct vop2 *vop2)
2664 {
2665 const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map;
2666 int i;
2667
2668 if (!esmart_lb_mode_map)
2669 return vop2->esmart_lb_mode;
2670
2671 for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) {
2672 if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode)
2673 return esmart_lb_mode_map->lb_map_value;
2674 esmart_lb_mode_map++;
2675 }
2676
2677 if (i == vop2->data->esmart_lb_mode_num)
2678 printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode);
2679
2680 return vop2->data->esmart_lb_mode_map[0].lb_map_value;
2681 }
2682
vop2_plane_mask_to_possible_vp_mask(struct display_state * state)2683 static inline void vop2_plane_mask_to_possible_vp_mask(struct display_state *state)
2684 {
2685 struct crtc_state *cstate = &state->crtc_state;
2686 struct vop2 *vop2 = cstate->private;
2687 const struct vop2_data *vop2_data = vop2->data;
2688 struct vop2_win_data *win_data;
2689 u32 plane_mask;
2690 u32 nr_planes;
2691 u32 phys_id;
2692 int i, j;
2693
2694 for (i = 0; i < vop2_data->nr_layers; i++) {
2695 win_data = &vop2_data->win_data[i];
2696 win_data->possible_vp_mask = 0;
2697 }
2698
2699 for (i = 0; i < vop2_data->nr_vps; i++) {
2700 plane_mask = cstate->crtc->vps[i].plane_mask;
2701 nr_planes = hweight32(plane_mask);
2702
2703 for (j = 0; j < nr_planes; j++) {
2704 phys_id = ffs(plane_mask) - 1;
2705 win_data = vop2_find_win_by_phys_id(vop2, phys_id);
2706 win_data->possible_vp_mask |= BIT(i);
2707 plane_mask &= ~BIT(phys_id);
2708 }
2709 }
2710 }
2711
2712 /*
2713 * The function checks whether the 'rockchip,plane-mask' property assigned
2714 * in DTS is valid.
2715 */
vop2_plane_mask_check(struct display_state * state)2716 static bool vop2_plane_mask_check(struct display_state *state)
2717 {
2718 struct crtc_state *cstate = &state->crtc_state;
2719 struct vop2 *vop2 = cstate->private;
2720 struct vop2_win_data *win_data;
2721 u32 assigned_plane_mask = 0, plane_mask = 0;
2722 u32 phys_id;
2723 u32 nr_planes;
2724 u8 primary_plane_id, cursor_plane_id;
2725 int i, j;
2726
2727 /*
2728 * If plane mask is assigned in DTS, then every plane need to be assigned to
2729 * one of all the VPs, and no single plane can be assigned to more than one
2730 * VP.
2731 */
2732 for (i = 0; i < vop2->data->nr_vps; i++) {
2733 plane_mask = cstate->crtc->vps[i].plane_mask;
2734 primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
2735 cursor_plane_id = cstate->crtc->vps[i].cursor_plane_id;
2736 nr_planes = hweight32(plane_mask);
2737
2738 /*
2739 * If the plane mask and primary plane both are assigned in DTS, the
2740 * primary plane should be included in the plane mask of VPx.
2741 */
2742 if (plane_mask && primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
2743 !(BIT(primary_plane_id) & plane_mask)) {
2744 printf("Invalid primary plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n",
2745 vop2_plane_phys_id_to_string(primary_plane_id),
2746 BIT(primary_plane_id), i, plane_mask);
2747 return false;
2748 }
2749
2750 if (cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
2751 cursor_plane_id == primary_plane_id) {
2752 printf("Assigned cursor plane of VP%d [%s] has been assigned as its pirmary plane\n",
2753 i, vop2_plane_phys_id_to_string(cursor_plane_id));
2754 return false;
2755 }
2756
2757 /*
2758 * If the plane mask and cursor plane both are assigned in DTS, the
2759 * cursor plane should be included in the plane mask of VPx.
2760 */
2761 if (plane_mask && cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
2762 !(BIT(cursor_plane_id) & plane_mask)) {
2763 printf("Invalid cursor plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n",
2764 vop2_plane_phys_id_to_string(cursor_plane_id),
2765 BIT(cursor_plane_id), i, plane_mask);
2766 return false;
2767 }
2768
2769 /*
2770 * Every plane assigned to the specific VP should follow the constraints
2771 * of default &vop2_win_data.possible_vp_mask.
2772 */
2773 for (j = 0; j < nr_planes; j++) {
2774 phys_id = ffs(plane_mask) - 1;
2775 win_data = vop2_find_win_by_phys_id(vop2, phys_id);
2776 if (!win_data) {
2777 printf("Invalid plane id %d in VP%d assigned plane mask\n",
2778 phys_id, i);
2779 return false;
2780 }
2781
2782 if (!(vop2_win_can_attach_to_vp(win_data, i))) {
2783 printf("%s can not attach to VP%d\n",
2784 vop2_plane_phys_id_to_string(phys_id), i);
2785 return false;
2786 }
2787
2788 plane_mask &= ~BIT(phys_id);
2789 }
2790
2791 if (assigned_plane_mask & cstate->crtc->vps[i].plane_mask) {
2792 printf("the same window can't be assigned to two vp\n");
2793 return false;
2794 }
2795 assigned_plane_mask |= cstate->crtc->vps[i].plane_mask;
2796 }
2797
2798 if (assigned_plane_mask != vop2->data->plane_mask_base) {
2799 printf("all windows should be assigned, full plane mask: [0x%08x], current plane mask: [0x%08x]\n",
2800 vop2->data->plane_mask_base, assigned_plane_mask);
2801 return false;
2802 }
2803
2804 /*
2805 * If plane_mask assigned in DTS is valid, then convert it to &vop2_win_data.possible_vp_mask
2806 * and replace the default one with it.
2807 */
2808 vop2_plane_mask_to_possible_vp_mask(state);
2809
2810 return true;
2811 }
2812
rockchip_cursor_plane_assign(struct display_state * state,u8 vp_id)2813 static void rockchip_cursor_plane_assign(struct display_state *state, u8 vp_id)
2814 {
2815 struct crtc_state *cstate = &state->crtc_state;
2816 struct vop2 *vop2 = cstate->private;
2817 struct vop2_win_data *win_data;
2818 int i, j;
2819
2820 if (cstate->crtc->vps[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
2821 win_data = vop2_find_win_by_phys_id(vop2, cstate->crtc->vps[vp_id].cursor_plane_id);
2822 if (win_data) {
2823 if (vop2_win_can_attach_to_vp(win_data, vp_id))
2824 vop2->vp_plane_mask[vp_id].cursor_plane_id =
2825 cstate->crtc->vps[vp_id].cursor_plane_id;
2826 return;
2827 }
2828 }
2829
2830 for (i = 0; i < vop2->data->nr_layers; i++) {
2831 win_data = &vop2->data->win_data[i];
2832
2833 if (win_data->plane_type != VOP2_PLANE_TYPE_CURSOR)
2834 continue;
2835
2836 if (!vop2_win_can_attach_to_vp(win_data, vp_id))
2837 continue;
2838
2839 for (j = 0; j < vop2->data->nr_vps; j++) {
2840 if (win_data->phys_id == vop2->vp_plane_mask[j].cursor_plane_id)
2841 break;
2842 }
2843
2844 /* The win has been used as the cursor plane for other VPs */
2845 if (j < vop2->data->nr_vps)
2846 continue;
2847
2848 vop2->vp_plane_mask[vp_id].cursor_plane_id = win_data->phys_id;
2849 return;
2850 }
2851
2852 vop2->vp_plane_mask[vp_id].cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
2853 }
2854
2855 /*
2856 * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in
2857 * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched
2858 * between different CRTCs flexibly and the userspace do not need
2859 * the plane_mask to restrict the switch between the crtc and plane.
2860 * We just find a expected plane for logo display.
2861 */
rk3528_assign_plane_mask(struct display_state * state)2862 static void rk3528_assign_plane_mask(struct display_state *state)
2863 {
2864 struct crtc_state *cstate = &state->crtc_state;
2865 struct vop2 *vop2 = cstate->private;
2866 struct vop2_win_data *win_data;
2867 int active_vp_num = 0;
2868 int i, j, k;
2869
2870 printf("Assign default plane mask\n");
2871
2872 for (i = 0; i < vop2->data->nr_vps; i++) {
2873 if (!cstate->crtc->vps[i].enable)
2874 continue;
2875
2876 for (j = 0; j < vop2->data->nr_layers; j++) {
2877 win_data = &vop2->data->win_data[j];
2878
2879 if (win_data->plane_type != VOP2_PLANE_TYPE_PRIMARY)
2880 continue;
2881
2882 if (!vop2_win_can_attach_to_vp(win_data, i))
2883 continue;
2884
2885 for (k = 0; k < vop2->data->nr_vps; k++) {
2886 if (win_data->phys_id == vop2->vp_plane_mask[k].primary_plane_id)
2887 break;
2888 }
2889
2890 /* The win has been used as the primary plane for other VPs */
2891 if (k < vop2->data->nr_vps)
2892 continue;
2893
2894 vop2->vp_plane_mask[i].attached_layers_nr = 1;
2895 vop2->vp_plane_mask[i].primary_plane_id = win_data->phys_id;
2896 vop2->vp_plane_mask[i].attached_layers[0] = win_data->phys_id;
2897 vop2->vp_plane_mask[i].plane_mask |= BIT(win_data->phys_id);
2898 active_vp_num++;
2899 break;
2900 }
2901
2902 if (vop2->vp_plane_mask[i].primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
2903 printf("ERROR: No primary plane find for video_port%d\n", i);
2904
2905 rockchip_cursor_plane_assign(state, i);
2906 }
2907 printf("VOP have %d active VP\n", active_vp_num);
2908 }
2909
rk3568_assign_plane_mask(struct display_state * state)2910 static void rk3568_assign_plane_mask(struct display_state *state)
2911 {
2912 struct crtc_state *cstate = &state->crtc_state;
2913 struct vop2 *vop2 = cstate->private;
2914 struct vop2_vp_plane_mask *plane_mask;
2915 u32 nr_planes = 0;
2916 int active_vp_num = 0;
2917 int main_vp_index = -1;
2918 int layer_phy_id = 0;
2919 int i, j;
2920
2921 printf("Assign default plane mask\n");
2922
2923 for (i = 0; i < vop2->data->nr_vps; i++) {
2924 if (cstate->crtc->vps[i].enable)
2925 active_vp_num++;
2926 }
2927
2928 printf("VOP have %d active VP\n", active_vp_num);
2929
2930 if (soc_is_rk3566() && active_vp_num > 2)
2931 printf("ERROR: rk3566 only support 2 display output!!\n");
2932 plane_mask = vop2->data->plane_mask;
2933 plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
2934
2935 /*
2936 * For RK3566, the main planes should be enabled before the mirror planes.
2937 * The devices that support hot plug may be disconnected initially, so we
2938 * assign the main planes to the first device that does not support hot
2939 * plug, in order to ensure that the mirror planes are not enabled first.
2940 */
2941 if (soc_is_rk3566()) {
2942 for (i = 0; i < vop2->data->nr_vps; i++) {
2943 if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
2944 /* the first store main display plane mask */
2945 vop2->vp_plane_mask[i] = plane_mask[0];
2946 main_vp_index = i;
2947 break;
2948 }
2949 }
2950
2951 /* if no find unplug devices, use vp0 as main display */
2952 if (main_vp_index < 0) {
2953 main_vp_index = 0;
2954 vop2->vp_plane_mask[0] = plane_mask[0];
2955 }
2956
2957 /* plane_mask[0] store main display, so we from plane_mask[1] */
2958 j = 1;
2959 } else {
2960 /*
2961 * For the platforms except RK3566, we assign the plane mask of
2962 * VPx according to the &vop2_data.plane_mask[active_vp_num][x].
2963 */
2964 j = 0;
2965 }
2966
2967 /* init other display except main display */
2968 for (i = 0; i < vop2->data->nr_vps; i++) {
2969 /* main display or no connect devices */
2970 if (i == main_vp_index || !cstate->crtc->vps[i].enable)
2971 continue;
2972 vop2->vp_plane_mask[i] = plane_mask[j++];
2973 /*
2974 * For rk3588, the main window should attach to the VP0 while
2975 * the splice window should attach to the VP1 when the display
2976 * mode is over 4k.
2977 * If only one VP is enabled and the plane mask is not assigned
2978 * in DTS, all main windows will be assigned to the enabled VPx,
2979 * and all splice windows will be assigned to the VPx+1, in order
2980 * to ensure that the splice mode work well.
2981 */
2982 if (vop2->version == VOP_VERSION_RK3588 && active_vp_num == 1)
2983 vop2->vp_plane_mask[(i + 1) % vop2->data->nr_vps] = plane_mask[j++];
2984 }
2985
2986 /* store plane mask for vop2_fixup_dts */
2987 for (i = 0; i < vop2->data->nr_vps; i++) {
2988 nr_planes = vop2->vp_plane_mask[i].attached_layers_nr;
2989 for (j = 0; j < nr_planes; j++) {
2990 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2991 vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
2992 }
2993 }
2994
2995 /*
2996 * For RK3568 and RK3588, to aovid &vop2.vp_plane_mask[].cursor_plane_id
2997 * being overwritten by &vop2.data->plane_mask[].cursor_plane_id, which
2998 * is always 0, the assignment of cursor plane should be placed at the
2999 * end.
3000 */
3001 for (i = 0; i < vop2->data->nr_vps; i++) {
3002 vop2->vp_plane_mask[i].cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
3003 if (cstate->crtc->vps[i].enable)
3004 rockchip_cursor_plane_assign(state, i);
3005 }
3006 }
3007
vop2_global_initial(struct vop2 * vop2,struct display_state * state)3008 static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
3009 {
3010 struct crtc_state *cstate = &state->crtc_state;
3011 const struct vop2_data *vop2_data = vop2->data;
3012 const struct vop2_ops *vop2_ops = vop2_data->ops;
3013 struct vop2_vp_plane_mask *vp_plane_mask;
3014 u32 nr_planes = 0;
3015 u32 plane_mask;
3016 u8 primary_plane_id;
3017 const u8 *tmp;
3018 int i, j;
3019
3020 if (vop2->global_init)
3021 return;
3022
3023 /*
3024 * Initialize struct vop2_vp_plane_mask, whose main function is to
3025 * fixup the DTS.
3026 */
3027 for (i = 0; i < vop2->data->nr_vps; i++) {
3028 vp_plane_mask = &vop2->vp_plane_mask[i];
3029 /*
3030 * Set default value of the primary plane id and cursor plane
3031 * id to invalid.
3032 */
3033 vp_plane_mask->primary_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
3034 vp_plane_mask->cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
3035 }
3036
3037 /* OTP must enable at the first time, otherwise mirror layer register is error */
3038 if (soc_is_rk3566())
3039 vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
3040 OTP_WIN_EN_SHIFT, 1, false);
3041
3042 /* The plane mask is assigned in DTS */
3043 if (cstate->crtc->assign_plane) {
3044 /* check whether plane mask and primary plane are valid */
3045 if (vop2_plane_mask_check(state)) {
3046 for (i = 0; i < vop2->data->nr_vps; i++) {
3047 plane_mask = cstate->crtc->vps[i].plane_mask;
3048 nr_planes = hweight32(plane_mask); /* use bitmap to store plane mask */
3049 vop2->vp_plane_mask[i].attached_layers_nr = nr_planes;
3050 primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
3051 /*
3052 * If the primary plane of specific VP is not assigned
3053 * in DTS, find a proper primary plane according to the
3054 * &vop2_win_data.possible_vp_mask.
3055 */
3056 if (primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
3057 primary_plane_id = vop2_vp_find_attachable_win(state, i);
3058 vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id;
3059 vop2->vp_plane_mask[i].plane_mask = plane_mask;
3060
3061 /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id] */
3062 for (j = 0; j < nr_planes; j++) {
3063 vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
3064 plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
3065 }
3066 }
3067 } else {
3068 vop2_ops->assign_plane_mask(state);
3069 }
3070 } else {
3071 /*
3072 * If no plane mask assignment, plane mask and primary plane will be
3073 * assigned automatically.
3074 */
3075 vop2_ops->assign_plane_mask(state);
3076 }
3077
3078 if (vop2->version == VOP_VERSION_RK3588)
3079 rk3588_vop2_regsbak(vop2);
3080 else
3081 memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
3082
3083 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
3084 OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
3085 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
3086 IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
3087
3088 for (i = 0; i < vop2->data->nr_vps; i++) {
3089 printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
3090 for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
3091 printf("%s ",
3092 vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].attached_layers[j]));
3093 printf("], primary plane: %s\n",
3094 vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].primary_plane_id));
3095 }
3096
3097 vop2_ops->setup_overlay(state);
3098
3099 if (is_vop3(vop2)) {
3100 /*
3101 * you can rewrite at dts vop node:
3102 *
3103 * VOP3_ESMART_8K_MODE = 0,
3104 * VOP3_ESMART_4K_4K_MODE = 1,
3105 * VOP3_ESMART_4K_2K_2K_MODE = 2,
3106 * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
3107 *
3108 * &vop {
3109 * esmart_lb_mode = /bits/ 8 <2>;
3110 * };
3111 */
3112 tmp = dev_read_u8_array_ptr(cstate->dev, "esmart_lb_mode", 1);
3113 if (tmp)
3114 vop2->esmart_lb_mode = *tmp;
3115 else
3116 vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
3117 if (vop2->version == VOP_VERSION_RK3576)
3118 vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL,
3119 RK3576_ESMART_LB_MODE_SEL_MASK,
3120 RK3576_ESMART_LB_MODE_SEL_SHIFT,
3121 vop3_get_esmart_lb_mode(vop2), true);
3122 else
3123 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
3124 ESMART_LB_MODE_SEL_MASK,
3125 ESMART_LB_MODE_SEL_SHIFT,
3126 vop3_get_esmart_lb_mode(vop2), false);
3127
3128 vop3_init_esmart_scale_engine(vop2);
3129
3130 if (vop2->version == VOP_VERSION_RK3576)
3131 vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
3132 RK3576_DSP_VS_T_SEL_SHIFT, 0, true);
3133 else
3134 vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK,
3135 DSP_VS_T_SEL_SHIFT, 0, false);
3136
3137 /*
3138 * This is a workaround for RK3528/RK3562/RK3576:
3139 *
3140 * The aclk pre auto gating function may disable the aclk
3141 * in some unexpected cases, which detected by hardware
3142 * automatically.
3143 *
3144 * For example, if the above function is enabled, the post
3145 * scale function will be affected, resulting in abnormal
3146 * display.
3147 */
3148 if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 ||
3149 vop2->version == VOP_VERSION_RK3576)
3150 vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
3151 ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false);
3152 }
3153
3154 if (vop2->version == VOP_VERSION_RK3568)
3155 vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
3156
3157 if (vop2->version == VOP_VERSION_RK3576) {
3158 vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq");
3159
3160 /* Default use rkiommu 2.0 for axi0 */
3161 vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 1, true);
3162
3163 /* Init frc2.0 config */
3164 vop2_writel(vop2, 0xca0, 0xc8);
3165 vop2_writel(vop2, 0xca4, 0x01000100);
3166 vop2_writel(vop2, 0xca8, 0x03ff0100);
3167 vop2_writel(vop2, 0xda0, 0xc8);
3168 vop2_writel(vop2, 0xda4, 0x01000100);
3169 vop2_writel(vop2, 0xda8, 0x03ff0100);
3170
3171 if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true)
3172 vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
3173 VP_INTR_MERGE_EN_SHIFT, 1, true);
3174
3175 /* Set reg done every field for interlace */
3176 vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK,
3177 INTERLACE_FRM_REG_DONE_SHIFT, 0, false);
3178 }
3179
3180 vop2->global_init = true;
3181 }
3182
rockchip_vop2_sharp_init(struct vop2 * vop2,struct display_state * state)3183 static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state)
3184 {
3185 struct crtc_state *cstate = &state->crtc_state;
3186 const struct vop2_data *vop2_data = vop2->data;
3187 const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
3188 struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
3189 struct resource sharp_regs;
3190 int ret;
3191
3192 if (!(vp_data->feature & VOP_FEATURE_POST_SHARP) || !vp->sharp_en)
3193 return;
3194
3195 ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs);
3196 if (ret) {
3197 printf("failed to get sharp regs\n");
3198 return;
3199 }
3200 vop2->sharp_res = (void *)sharp_regs.start;
3201
3202 /*
3203 * After vop initialization, keep sw_sharp_enable always on.
3204 * Only enable/disable sharp submodule to avoid black screen.
3205 */
3206 writel(true << SW_SHARP_ENABLE_SHIFT, vop2->sharp_res + RK3576_SHARP_CTRL);
3207 }
3208
rockchip_vop2_acm_init(struct vop2 * vop2,struct display_state * state)3209 static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state)
3210 {
3211 struct crtc_state *cstate = &state->crtc_state;
3212 const struct vop2_data *vop2_data = vop2->data;
3213 const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
3214 struct resource acm_regs;
3215 u32 *acm_reg_base;
3216 u32 vp_offset = (cstate->crtc_id * 0x100);
3217 int ret;
3218
3219 if (!(vp_data->feature & VOP_FEATURE_POST_ACM))
3220 return;
3221
3222 ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs);
3223 if (ret) {
3224 printf("failed to get acm regs\n");
3225 return;
3226 }
3227 acm_reg_base = (u32 *)acm_regs.start;
3228
3229 /*
3230 * Black screen is displayed when acm bypass switched
3231 * between enable and disable. Therefore, disable acm
3232 * bypass by default after system boot.
3233 */
3234 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
3235 POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
3236
3237 writel(0, acm_reg_base + 0);
3238 }
3239
rockchip_vop2_of_get_gamma_lut(struct display_state * state,struct device_node * dsp_lut_node)3240 static int rockchip_vop2_of_get_gamma_lut(struct display_state *state,
3241 struct device_node *dsp_lut_node)
3242 {
3243 struct crtc_state *cstate = &state->crtc_state;
3244 struct resource gamma_res;
3245 fdt_size_t lut_size;
3246 u32 *lut_regs;
3247 u32 *lut;
3248 u32 r, g, b;
3249 int lut_len;
3250 int length;
3251 int i, j;
3252 int ret = 0;
3253
3254 of_get_property(dsp_lut_node, "gamma-lut", &length);
3255 if (!length)
3256 return -EINVAL;
3257
3258 ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
3259 if (ret)
3260 printf("failed to get gamma lut res\n");
3261 lut_regs = (u32 *)gamma_res.start;
3262 lut_size = gamma_res.end - gamma_res.start + 1;
3263 if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
3264 printf("failed to get gamma lut register\n");
3265 return -EINVAL;
3266 }
3267 lut_len = lut_size / 4;
3268
3269 cstate->lut_val = (u32 *)calloc(1, lut_size);
3270 if (!cstate->lut_val)
3271 return -ENOMEM;
3272
3273 length >>= 2;
3274 if (length != lut_len) {
3275 lut = (u32 *)calloc(1, lut_len);
3276 if (!lut) {
3277 free(cstate->lut_val);
3278 return -ENOMEM;
3279 }
3280
3281 ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length);
3282 if (ret) {
3283 printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id);
3284 free(cstate->lut_val);
3285 free(lut);
3286 return -EINVAL;
3287 }
3288
3289 /*
3290 * In order to achieve the same gamma correction effect in different
3291 * platforms, the following conversion helps to translate from 8bit
3292 * gamma table with 256 parameters to 10bit gamma with 1024 parameters.
3293 */
3294 for (i = 0; i < lut_len; i++) {
3295 j = i * length / lut_len;
3296 r = lut[j] / length / length * lut_len / length;
3297 g = lut[j] / length % length * lut_len / length;
3298 b = lut[j] % length * lut_len / length;
3299
3300 cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b;
3301 }
3302 free(lut);
3303 } else {
3304 of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len);
3305 }
3306
3307 return 0;
3308 }
3309
rockchip_vop2_of_get_dsp_lut(struct vop2 * vop2,struct display_state * state)3310 static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state)
3311 {
3312 struct crtc_state *cstate = &state->crtc_state;
3313 struct device_node *dsp_lut_node;
3314 int phandle;
3315 int ret = 0;
3316
3317 phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1);
3318 if (phandle < 0)
3319 return;
3320
3321 dsp_lut_node = of_find_node_by_phandle(phandle);
3322 if (!dsp_lut_node)
3323 return;
3324
3325 ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node);
3326 if (ret)
3327 printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id);
3328 }
3329
vop2_initial(struct vop2 * vop2,struct display_state * state)3330 static int vop2_initial(struct vop2 *vop2, struct display_state *state)
3331 {
3332 rockchip_vop2_of_get_dsp_lut(vop2, state);
3333
3334 rockchip_vop2_gamma_lut_init(vop2, state);
3335 rockchip_vop2_cubic_lut_init(vop2, state);
3336 rockchip_vop2_sharp_init(vop2, state);
3337 rockchip_vop2_acm_init(vop2, state);
3338
3339 return 0;
3340 }
3341
3342 /*
3343 * VOP2 have multi video ports.
3344 * video port ------- crtc
3345 */
rockchip_vop2_preinit(struct display_state * state)3346 static int rockchip_vop2_preinit(struct display_state *state)
3347 {
3348 struct crtc_state *cstate = &state->crtc_state;
3349 const struct vop2_data *vop2_data = cstate->crtc->data;
3350 struct regmap *map;
3351 #if defined(CONFIG_MOS_SUPPORT) && !defined(CONFIG_SPL_BUILD)
3352 struct power_domain pwrdom;
3353 struct clk_bulk clks;
3354 #endif
3355 char dclk_name[16];
3356 int ret;
3357
3358 if (!rockchip_vop2) {
3359 rockchip_vop2 = calloc(1, sizeof(struct vop2));
3360 if (!rockchip_vop2)
3361 return -ENOMEM;
3362 memset(rockchip_vop2, 0, sizeof(struct vop2));
3363 rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
3364 rockchip_vop2->reg_len = RK3568_MAX_REG;
3365 #ifdef CONFIG_SPL_BUILD
3366 rockchip_vop2->regs = (void *)RK3528_VOP_BASE;
3367 #else
3368 rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
3369 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf");
3370 rockchip_vop2->grf = regmap_get_range(map, 0);
3371 if (rockchip_vop2->grf <= 0)
3372 printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
3373 #endif
3374 rockchip_vop2->version = vop2_data->version;
3375 rockchip_vop2->data = vop2_data;
3376 if (rockchip_vop2->version == VOP_VERSION_RK3588) {
3377 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf");
3378 rockchip_vop2->vop_grf = regmap_get_range(map, 0);
3379 if (rockchip_vop2->vop_grf <= 0)
3380 printf("%s: Get syscon vop_grf failed (ret=%p)\n",
3381 __func__, rockchip_vop2->vop_grf);
3382 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf");
3383 rockchip_vop2->vo1_grf = regmap_get_range(map, 0);
3384 if (rockchip_vop2->vo1_grf <= 0)
3385 printf("%s: Get syscon vo1_grf failed (ret=%p)\n",
3386 __func__, rockchip_vop2->vo1_grf);
3387 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3388 rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3389 if (rockchip_vop2->sys_pmu <= 0)
3390 printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3391 __func__, rockchip_vop2->sys_pmu);
3392 } else if (rockchip_vop2->version == VOP_VERSION_RK3576) {
3393 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf");
3394 rockchip_vop2->ioc_grf = regmap_get_range(map, 0);
3395 if (rockchip_vop2->ioc_grf <= 0)
3396 printf("%s: Get syscon ioc_grf failed (ret=%p)\n",
3397 __func__, rockchip_vop2->ioc_grf);
3398 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3399 rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3400 if (rockchip_vop2->sys_pmu <= 0)
3401 printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3402 __func__, rockchip_vop2->sys_pmu);
3403 }
3404 #if defined(CONFIG_MOS_SUPPORT) && !defined(CONFIG_SPL_BUILD)
3405 ret = power_domain_get(cstate->dev, &pwrdom);
3406 if (ret) {
3407 printf("failed to get pwrdom: %d\n", ret);
3408 return ret;
3409 }
3410 ret = power_domain_on(&pwrdom);
3411 if (ret) {
3412 printf("failed to power on pd: %d\n", ret);
3413 return ret;
3414 }
3415 ret = clk_get_bulk(cstate->dev, &clks);
3416 if (ret) {
3417 if (ret != -ENOSYS && ret != -ENOENT) {
3418 printf("failed to get clk: %d\n", ret);
3419 return ret;
3420 }
3421 }
3422 ret = clk_enable_bulk(&clks);
3423 if (ret) {
3424 printf("failed to enable clk: %d\n", ret);
3425 clk_release_bulk(&clks);
3426 return ret;
3427 }
3428 #endif
3429 }
3430
3431 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
3432 if (dev_read_stringlist_search(cstate->dev, "reset-names", dclk_name) > 0) {
3433 ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst);
3434 if (ret < 0) {
3435 printf("%s: failed to get dclk reset: %d\n", __func__, ret);
3436 cstate->dclk_rst.dev = NULL;
3437 }
3438 }
3439
3440 cstate->private = rockchip_vop2;
3441 cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
3442 cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
3443
3444 vop2_global_initial(rockchip_vop2, state);
3445
3446 return 0;
3447 }
3448
3449 /*
3450 * calc the dclk on rk3588
3451 * the available div of dclk is 1, 2, 4
3452 *
3453 */
vop2_calc_dclk(unsigned long child_clk,unsigned long max_dclk)3454 static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
3455 {
3456 if (child_clk * 4 <= max_dclk)
3457 return child_clk * 4;
3458 else if (child_clk * 2 <= max_dclk)
3459 return child_clk * 2;
3460 else if (child_clk <= max_dclk)
3461 return child_clk;
3462 else
3463 return 0;
3464 }
3465
3466 /*
3467 * 4 pixclk/cycle on rk3588
3468 * RGB/eDP/HDMI: if_pixclk >= dclk_core
3469 * DP: dp_pixclk = dclk_out <= dclk_core
3470 * DSI: mipi_pixclk <= dclk_out <= dclk_core
3471 */
vop2_calc_cru_cfg(struct display_state * state,int * dclk_core_div,int * dclk_out_div,int * if_pixclk_div,int * if_dclk_div)3472 static unsigned long vop2_calc_cru_cfg(struct display_state *state,
3473 int *dclk_core_div, int *dclk_out_div,
3474 int *if_pixclk_div, int *if_dclk_div)
3475 {
3476 struct crtc_state *cstate = &state->crtc_state;
3477 struct connector_state *conn_state = &state->conn_state;
3478 struct drm_display_mode *mode = &conn_state->mode;
3479 struct vop2 *vop2 = cstate->private;
3480 unsigned long v_pixclk = mode->crtc_clock * 1000L;
3481 unsigned long dclk_core_rate = v_pixclk >> 2;
3482 unsigned long dclk_rate = v_pixclk;
3483 unsigned long dclk_out_rate;
3484 u64 if_dclk_rate;
3485 u64 if_pixclk_rate;
3486 int output_type = conn_state->type;
3487 int output_mode = conn_state->output_mode;
3488 int K = 1;
3489
3490 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE &&
3491 output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3492 printf("Dual channel and YUV420 can't work together\n");
3493 return -EINVAL;
3494 }
3495
3496 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
3497 output_mode == ROCKCHIP_OUT_MODE_YUV420)
3498 K = 2;
3499
3500 if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
3501 /*
3502 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
3503 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
3504 */
3505 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
3506 output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3507 dclk_rate = dclk_rate >> 1;
3508 K = 2;
3509 }
3510 if (cstate->dsc_enable) {
3511 if_pixclk_rate = cstate->dsc_cds_clk_rate << 1;
3512 if_dclk_rate = cstate->dsc_cds_clk_rate;
3513 } else {
3514 if_pixclk_rate = (dclk_core_rate << 1) / K;
3515 if_dclk_rate = dclk_core_rate / K;
3516 }
3517
3518 if (v_pixclk > VOP2_MAX_DCLK_RATE * 1000L)
3519 dclk_rate = vop2_calc_dclk(dclk_core_rate,
3520 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
3521
3522 if (!dclk_rate) {
3523 printf("HDMI if_pixclk_rate out of range(max_dclk: %ld HZ, dclk_core: %lld HZ)\n",
3524 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, if_pixclk_rate);
3525 return -EINVAL;
3526 }
3527 *if_pixclk_div = dclk_rate / if_pixclk_rate;
3528 *if_dclk_div = dclk_rate / if_dclk_rate;
3529 *dclk_core_div = dclk_rate / dclk_core_rate;
3530 /* For HDMI DSC mode, the dclk_out_div should be the same as dclk_core_div */
3531 if (cstate->dsc_enable)
3532 *dclk_out_div = *dclk_core_div;
3533 printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n",
3534 dclk_rate, *if_pixclk_div, *if_dclk_div);
3535 } else if (output_type == DRM_MODE_CONNECTOR_eDP) {
3536 /* edp_pixclk = edp_dclk > dclk_core */
3537 if_pixclk_rate = v_pixclk / K;
3538 if_dclk_rate = v_pixclk / K;
3539 dclk_rate = if_pixclk_rate * K;
3540 *dclk_core_div = dclk_rate / dclk_core_rate;
3541 *if_pixclk_div = dclk_rate / if_pixclk_rate;
3542 *if_dclk_div = *if_pixclk_div;
3543 } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
3544 dclk_out_rate = v_pixclk >> 2;
3545 dclk_out_rate = dclk_out_rate / K;
3546
3547 dclk_rate = vop2_calc_dclk(dclk_out_rate,
3548 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
3549 if (!dclk_rate) {
3550 printf("DP dclk_core out of range(max_dclk: %ld HZ, dclk_core: %ld HZ)\n",
3551 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_core_rate);
3552 return -EINVAL;
3553 }
3554 *dclk_out_div = dclk_rate / dclk_out_rate;
3555 *dclk_core_div = dclk_rate / dclk_core_rate;
3556 } else if (output_type == DRM_MODE_CONNECTOR_DSI) {
3557 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3558 K = 2;
3559 if (cstate->dsc_enable)
3560 /* dsc output is 96bit, dsi input is 192 bit */
3561 if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1;
3562 else
3563 if_pixclk_rate = dclk_core_rate / K;
3564 /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
3565 dclk_out_rate = dclk_core_rate / K;
3566 /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
3567 dclk_rate = vop2_calc_dclk(dclk_out_rate,
3568 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
3569 if (!dclk_rate) {
3570 printf("MIPI dclk out of range(max_dclk: %ld HZ, dclk_rate: %ld HZ)\n",
3571 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_rate);
3572 return -EINVAL;
3573 }
3574
3575 if (cstate->dsc_enable)
3576 dclk_rate /= cstate->dsc_slice_num;
3577
3578 *dclk_out_div = dclk_rate / dclk_out_rate;
3579 *dclk_core_div = dclk_rate / dclk_core_rate;
3580 *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/
3581 if (cstate->dsc_enable)
3582 *if_pixclk_div = dclk_out_rate / if_pixclk_rate;
3583
3584 } else if (output_type == DRM_MODE_CONNECTOR_DPI) {
3585 dclk_rate = v_pixclk;
3586 *dclk_core_div = dclk_rate / dclk_core_rate;
3587 }
3588
3589 *if_pixclk_div = ilog2(*if_pixclk_div);
3590 *if_dclk_div = ilog2(*if_dclk_div);
3591 *dclk_core_div = ilog2(*dclk_core_div);
3592 /*
3593 * For RK3588, dclk_out is designed for DP, MIPI(both DSC and non-DSC mode)
3594 * and HDMI in DSC mode.
3595 */
3596 if (output_type == DRM_MODE_CONNECTOR_DisplayPort ||
3597 output_type == DRM_MODE_CONNECTOR_DSI ||
3598 (output_type == DRM_MODE_CONNECTOR_HDMIA && cstate->dsc_enable))
3599 *dclk_out_div = ilog2(*dclk_out_div);
3600 else
3601 *dclk_out_div = 0;
3602
3603 return dclk_rate;
3604 }
3605
vop2_calc_dsc_clk(struct display_state * state)3606 static int vop2_calc_dsc_clk(struct display_state *state)
3607 {
3608 struct connector_state *conn_state = &state->conn_state;
3609 struct drm_display_mode *mode = &conn_state->mode;
3610 struct crtc_state *cstate = &state->crtc_state;
3611 u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */
3612 u8 k = 1;
3613
3614 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3615 k = 2;
3616
3617 cstate->dsc_txp_clk_rate = v_pixclk;
3618 do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k));
3619
3620 cstate->dsc_pxl_clk_rate = v_pixclk;
3621 do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k));
3622
3623 /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
3624 * cds_dat_width = 96;
3625 * bits_per_pixel = [8-12];
3626 * As cds clk is div from txp clk and only support 1/2/4 div,
3627 * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
3628 * otherwise dsc_cds = crtc_clock / 8;
3629 */
3630 cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
3631
3632 return 0;
3633 }
3634
rk3588_vop2_if_cfg(struct display_state * state)3635 static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
3636 {
3637 struct crtc_state *cstate = &state->crtc_state;
3638 struct connector_state *conn_state = &state->conn_state;
3639 struct drm_display_mode *mode = &conn_state->mode;
3640 struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
3641 struct vop2 *vop2 = cstate->private;
3642 u32 vp_offset = (cstate->crtc_id * 0x100);
3643 u16 hdisplay = mode->crtc_hdisplay;
3644 int output_if = conn_state->output_if;
3645 int if_pixclk_div = 0;
3646 int if_dclk_div = 0;
3647 unsigned long dclk_rate;
3648 bool dclk_inv, yc_swap = false;
3649 u32 val;
3650
3651 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3652 if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
3653 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
3654 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
3655 } else {
3656 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3657 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3658 }
3659
3660 if (cstate->dsc_enable) {
3661 int k = 1;
3662
3663 if (!vop2->data->nr_dscs) {
3664 printf("Unsupported DSC\n");
3665 return 0;
3666 }
3667
3668 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3669 k = 2;
3670
3671 cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
3672 cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
3673 cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num;
3674
3675 vop2_calc_dsc_clk(state);
3676 printf("Enable DSC%d slice:%dx%d, slice num:%d\n",
3677 cstate->dsc_id, dsc_sink_cap->slice_width,
3678 dsc_sink_cap->slice_height, cstate->dsc_slice_num);
3679 }
3680
3681 dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div);
3682
3683 if (output_if & VOP_OUTPUT_IF_RGB) {
3684 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3685 4, false);
3686 vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
3687 RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3688 }
3689
3690 if (output_if & VOP_OUTPUT_IF_BT1120) {
3691 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3692 3, false);
3693 vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
3694 RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3695 yc_swap = is_yc_swap(conn_state->bus_format);
3696 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT,
3697 yc_swap, false);
3698 }
3699
3700 if (output_if & VOP_OUTPUT_IF_BT656) {
3701 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3702 2, false);
3703 vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
3704 RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3705 yc_swap = is_yc_swap(conn_state->bus_format);
3706 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT,
3707 yc_swap, false);
3708 }
3709
3710 if (output_if & VOP_OUTPUT_IF_MIPI0) {
3711 if (cstate->crtc_id == 2)
3712 val = 0;
3713 else
3714 val = 1;
3715
3716 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
3717 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3718 RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
3719
3720 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
3721 1, false);
3722 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
3723 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
3724 if_pixclk_div, false);
3725
3726 if (conn_state->hold_mode) {
3727 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3728 EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
3729 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3730 EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
3731 }
3732 }
3733
3734 if (output_if & VOP_OUTPUT_IF_MIPI1) {
3735 if (cstate->crtc_id == 2)
3736 val = 0;
3737 else if (cstate->crtc_id == 3)
3738 val = 1;
3739 else
3740 val = 3; /*VP1*/
3741 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
3742 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3743 RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
3744
3745 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
3746 1, false);
3747 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
3748 val, false);
3749 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
3750 if_pixclk_div, false);
3751
3752 if (conn_state->hold_mode) {
3753 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3754 EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
3755 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3756 EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
3757 }
3758 }
3759
3760 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
3761 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
3762 MIPI_DUAL_EN_SHIFT, 1, false);
3763 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3764 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3765 EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
3766 false);
3767 switch (conn_state->type) {
3768 case DRM_MODE_CONNECTOR_DisplayPort:
3769 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3770 RK3588_DP_DUAL_EN_SHIFT, 1, false);
3771 break;
3772 case DRM_MODE_CONNECTOR_eDP:
3773 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3774 RK3588_EDP_DUAL_EN_SHIFT, 1, false);
3775 break;
3776 case DRM_MODE_CONNECTOR_HDMIA:
3777 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3778 RK3588_HDMI_DUAL_EN_SHIFT, 1, false);
3779 break;
3780 case DRM_MODE_CONNECTOR_DSI:
3781 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
3782 RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
3783 break;
3784 default:
3785 break;
3786 }
3787 }
3788
3789 if (output_if & VOP_OUTPUT_IF_eDP0) {
3790 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
3791 1, false);
3792 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3793 cstate->crtc_id, false);
3794 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3795 if_dclk_div, false);
3796
3797 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3798 if_pixclk_div, false);
3799
3800 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3801 RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
3802 }
3803
3804 if (output_if & VOP_OUTPUT_IF_eDP1) {
3805 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
3806 1, false);
3807 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3808 cstate->crtc_id, false);
3809 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3810 if_dclk_div, false);
3811
3812 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3813 if_pixclk_div, false);
3814
3815 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3816 RK3588_GRF_EDP1_ENABLE_SHIFT, 1);
3817 }
3818
3819 if (output_if & VOP_OUTPUT_IF_HDMI0) {
3820 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
3821 1, false);
3822 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3823 cstate->crtc_id, false);
3824 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3825 if_dclk_div, false);
3826
3827 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3828 if_pixclk_div, false);
3829
3830 if (cstate->dsc_enable)
3831 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3832 RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT, 1);
3833
3834 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3835 RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1);
3836 vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3837 HDMI_SYNC_POL_MASK,
3838 HDMI0_SYNC_POL_SHIFT, val);
3839 }
3840
3841 if (output_if & VOP_OUTPUT_IF_HDMI1) {
3842 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
3843 1, false);
3844 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3845 cstate->crtc_id, false);
3846 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3847 if_dclk_div, false);
3848
3849 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3850 if_pixclk_div, false);
3851
3852 if (cstate->dsc_enable)
3853 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3854 RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT, 1);
3855
3856 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3857 RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1);
3858 vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3859 HDMI_SYNC_POL_MASK,
3860 HDMI1_SYNC_POL_SHIFT, val);
3861 }
3862
3863 if (output_if & VOP_OUTPUT_IF_DP0) {
3864 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
3865 cstate->crtc_id, false);
3866 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3867 RK3588_DP0_PIN_POL_SHIFT, val, false);
3868 }
3869
3870 if (output_if & VOP_OUTPUT_IF_DP1) {
3871 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
3872 cstate->crtc_id, false);
3873 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3874 RK3588_DP1_PIN_POL_SHIFT, val, false);
3875 }
3876
3877 vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3878 DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false);
3879 vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3880 DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false);
3881
3882 return dclk_rate / 1000;
3883 }
3884
rk3576_vop2_if_cfg(struct display_state * state)3885 static unsigned long rk3576_vop2_if_cfg(struct display_state *state)
3886 {
3887 struct crtc_state *cstate = &state->crtc_state;
3888 struct connector_state *conn_state = &state->conn_state;
3889 struct drm_display_mode *mode = &conn_state->mode;
3890 struct vop2 *vop2 = cstate->private;
3891 u32 vp_offset = (cstate->crtc_id * 0x100);
3892 u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate;
3893 int output_if = conn_state->output_if;
3894 bool dclk_inv, yc_swap = false;
3895 bool split_mode = !!(conn_state->output_flags &
3896 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE);
3897 bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false;
3898 bool interface_dclk_sel, interface_pix_clk_sel = false;
3899 bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK ||
3900 conn_state->output_if & VOP_OUTPUT_IF_BT656;
3901 unsigned long dclk_in_rate, dclk_core_rate;
3902 u32 val;
3903
3904 if (split_mode) {
3905 printf("WARN: split is enabled, post-scaler shouldn't be set\n");
3906 conn_state->overscan.left_margin = 100;
3907 conn_state->overscan.right_margin = 100;
3908 conn_state->overscan.top_margin = 100;
3909 conn_state->overscan.bottom_margin = 100;
3910
3911 /*
3912 * VOP split and sharp use the same line buffer. If enable
3913 * split, sharp must be disabled completely.
3914 */
3915 if (vop2->data->vp_data[cstate->crtc_id].feature & VOP_FEATURE_POST_SHARP)
3916 writel(false << SW_SHARP_ENABLE_SHIFT,
3917 vop2->sharp_res + RK3576_SHARP_CTRL);
3918 }
3919
3920 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3921 if (output_if & VOP_OUTPUT_IF_MIPI0) {
3922 /*
3923 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3924 * so set VOP hsync/vsync polarity as positive by default.
3925 */
3926 val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3927 } else {
3928 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3929 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3930 }
3931
3932 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 ||
3933 mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode))
3934 cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */
3935 else
3936 cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */
3937 dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div;
3938
3939 if (double_pixel)
3940 dclk_core_rate = mode->crtc_clock / 2;
3941 else
3942 dclk_core_rate = mode->crtc_clock / port_pix_rate;
3943 post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */
3944
3945 if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3946 pix_half_rate = true;
3947 post_dclk_out_sel = true;
3948 }
3949
3950 if (output_if & VOP_OUTPUT_IF_RGB) {
3951 interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3952 /*
3953 * RGB interface_pix_clk_sel will auto config according
3954 * to rgb_en/bt1120_en/bt656_en.
3955 */
3956 } else if (output_if & VOP_OUTPUT_IF_eDP0) {
3957 interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3958 interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0;
3959 } else {
3960 interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3961 interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0;
3962 }
3963
3964 /* dclk_core */
3965 vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3966 RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false);
3967 /* dclk_out */
3968 vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3969 RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false);
3970
3971 if (output_if & VOP_OUTPUT_IF_RGB) {
3972 /* 0: dclk_core, 1: dclk_out */
3973 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3974 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3975
3976 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3977 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3978 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3979 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3980 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3981 RK3576_IF_OUT_EN_SHIFT, 1, false);
3982 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3983 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3984 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3985 RK3576_IF_PIN_POL_SHIFT, val, false);
3986 vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3987 RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv);
3988 }
3989
3990 if (output_if & VOP_OUTPUT_IF_BT1120) {
3991 /* 0: dclk_core, 1: dclk_out */
3992 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3993 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3994
3995 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3996 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3997 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3998 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3999 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4000 RK3576_IF_OUT_EN_SHIFT, 1, false);
4001 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4002 RK3576_BT1120_OUT_EN_SHIFT, 1, false);
4003 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4004 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4005 vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
4006 RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
4007 yc_swap = is_yc_swap(conn_state->bus_format);
4008 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4009 RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false);
4010 }
4011
4012 if (output_if & VOP_OUTPUT_IF_BT656) {
4013 /* 0: dclk_core, 1: dclk_out */
4014 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4015 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4016
4017 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4018 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4019 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4020 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4021 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4022 RK3576_IF_OUT_EN_SHIFT, 1, false);
4023 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4024 RK3576_BT656_OUT_EN_SHIFT, 1, false);
4025 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4026 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4027 vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
4028 RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
4029 yc_swap = is_yc_swap(conn_state->bus_format);
4030 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4031 RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false);
4032 }
4033
4034 if (output_if & VOP_OUTPUT_IF_MIPI0) {
4035 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4036 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4037 /* 0: div2, 1: div4 */
4038 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4039 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4040
4041 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4042 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4043 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4044 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4045 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4046 RK3576_IF_OUT_EN_SHIFT, 1, false);
4047 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4048 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4049 /*
4050 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
4051 * so set VOP hsync/vsync polarity as positive by default.
4052 */
4053 if (vop2->version == VOP_VERSION_RK3576)
4054 val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
4055 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4056 RK3576_IF_PIN_POL_SHIFT, val, false);
4057
4058 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
4059 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4060 RK3576_MIPI_CMD_MODE_SHIFT, 1, false);
4061
4062 if (conn_state->hold_mode) {
4063 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4064 EDPI_TE_EN, !cstate->soft_te, false);
4065 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4066 EDPI_WMS_HOLD_EN, 1, false);
4067 }
4068 }
4069
4070 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
4071 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4072 MIPI_DUAL_EN_SHIFT, 1, false);
4073 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
4074 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4075 MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
4076 switch (conn_state->type) {
4077 case DRM_MODE_CONNECTOR_DisplayPort:
4078 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4079 RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4080 break;
4081 case DRM_MODE_CONNECTOR_eDP:
4082 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4083 RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4084 break;
4085 case DRM_MODE_CONNECTOR_HDMIA:
4086 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4087 RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4088 break;
4089 case DRM_MODE_CONNECTOR_DSI:
4090 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4091 RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4092 break;
4093 default:
4094 break;
4095 }
4096 }
4097
4098 if (output_if & VOP_OUTPUT_IF_eDP0) {
4099 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4100 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4101 /* 0: dclk, 1: port0_dclk */
4102 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4103 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4104
4105 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4106 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4107 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4108 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4109 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4110 RK3576_IF_OUT_EN_SHIFT, 1, false);
4111 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4112 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4113 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4114 RK3576_IF_PIN_POL_SHIFT, val, false);
4115 }
4116
4117 if (output_if & VOP_OUTPUT_IF_HDMI0) {
4118 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4119 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4120 /* 0: div2, 1: div4 */
4121 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4122 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4123
4124 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4125 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4126 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4127 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4128 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4129 RK3576_IF_OUT_EN_SHIFT, 1, false);
4130 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4131 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4132 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4133 RK3576_IF_PIN_POL_SHIFT, val, false);
4134 }
4135
4136 if (output_if & VOP_OUTPUT_IF_DP0) {
4137 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4138 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4139 /* 0: no div, 1: div2 */
4140 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4141 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4142
4143 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4144 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4145 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4146 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4147 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4148 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4149 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4150 RK3576_IF_PIN_POL_SHIFT, val, false);
4151 }
4152
4153 if (output_if & VOP_OUTPUT_IF_DP1) {
4154 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4155 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4156 /* 0: no div, 1: div2 */
4157 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4158 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4159
4160 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
4161 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4162 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
4163 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4164 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4165 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4166 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4167 RK3576_IF_PIN_POL_SHIFT, val, false);
4168 }
4169
4170 if (output_if & VOP_OUTPUT_IF_DP2) {
4171 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4172 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4173 /* 0: no div, 1: div2 */
4174 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4175 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4176
4177 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
4178 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4179 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
4180 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4181 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4182 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4183 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4184 RK3576_IF_PIN_POL_SHIFT, val, false);
4185 }
4186
4187 return mode->crtc_clock;
4188 }
4189
rk3568_vop2_setup_dual_channel_if(struct display_state * state)4190 static void rk3568_vop2_setup_dual_channel_if(struct display_state *state)
4191 {
4192 struct crtc_state *cstate = &state->crtc_state;
4193 struct connector_state *conn_state = &state->conn_state;
4194 struct vop2 *vop2 = cstate->private;
4195 u32 vp_offset = (cstate->crtc_id * 0x100);
4196
4197 if (conn_state->output_flags &
4198 ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) {
4199 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4200 LVDS_DUAL_EN_SHIFT, 1, false);
4201 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4202 LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false);
4203 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
4204 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4205 LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
4206
4207 return;
4208 }
4209
4210 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4211 MIPI_DUAL_EN_SHIFT, 1, false);
4212 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) {
4213 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4214 MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
4215 }
4216
4217 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
4218 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4219 LVDS_DUAL_EN_SHIFT, 1, false);
4220 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4221 LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false);
4222 }
4223 }
4224
rk3568_vop2_if_cfg(struct display_state * state)4225 static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
4226 {
4227 struct crtc_state *cstate = &state->crtc_state;
4228 struct connector_state *conn_state = &state->conn_state;
4229 struct drm_display_mode *mode = &conn_state->mode;
4230 struct vop2 *vop2 = cstate->private;
4231 bool dclk_inv;
4232 u32 val;
4233
4234 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
4235 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4236 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4237
4238 if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
4239 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
4240 1, false);
4241 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4242 RGB_MUX_SHIFT, cstate->crtc_id, false);
4243 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
4244 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4245 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
4246 GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
4247 }
4248
4249 if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
4250 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
4251 1, false);
4252 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
4253 BT1120_EN_SHIFT, 1, false);
4254 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4255 RGB_MUX_SHIFT, cstate->crtc_id, false);
4256 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
4257 GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
4258 }
4259
4260 if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4261 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4262 1, false);
4263 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4264 RGB_MUX_SHIFT, cstate->crtc_id, false);
4265 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
4266 GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
4267 }
4268
4269 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
4270 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
4271 1, false);
4272 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4273 LVDS0_MUX_SHIFT, cstate->crtc_id, false);
4274 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
4275 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4276 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4277 IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4278 }
4279
4280 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
4281 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
4282 1, false);
4283 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4284 LVDS1_MUX_SHIFT, cstate->crtc_id, false);
4285 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
4286 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4287 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4288 IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4289 }
4290
4291
4292 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
4293 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
4294 1, false);
4295 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4296 MIPI0_MUX_SHIFT, cstate->crtc_id, false);
4297 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4298 IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
4299 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
4300 IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
4301 }
4302
4303 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
4304 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
4305 1, false);
4306 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4307 MIPI1_MUX_SHIFT, cstate->crtc_id, false);
4308 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4309 IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
4310 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
4311 IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
4312 }
4313
4314 if (conn_state->output_flags &
4315 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
4316 conn_state->output_flags &
4317 ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)
4318 rk3568_vop2_setup_dual_channel_if(state);
4319
4320 if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
4321 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
4322 1, false);
4323 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4324 EDP0_MUX_SHIFT, cstate->crtc_id, false);
4325 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4326 IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
4327 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK,
4328 IF_CTRL_EDP_PIN_POL_SHIFT, val, false);
4329 }
4330
4331 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4332 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4333 1, false);
4334 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4335 HDMI0_MUX_SHIFT, cstate->crtc_id, false);
4336 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4337 IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
4338 vop2_mask_write(vop2, RK3568_DSP_IF_POL,
4339 IF_CRTL_HDMI_PIN_POL_MASK,
4340 IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4341 }
4342
4343 return mode->crtc_clock;
4344 }
4345
rk3562_vop2_if_cfg(struct display_state * state)4346 static unsigned long rk3562_vop2_if_cfg(struct display_state *state)
4347 {
4348 struct crtc_state *cstate = &state->crtc_state;
4349 struct connector_state *conn_state = &state->conn_state;
4350 struct drm_display_mode *mode = &conn_state->mode;
4351 struct vop2 *vop2 = cstate->private;
4352 bool dclk_inv;
4353 u32 vp_offset = (cstate->crtc_id * 0x100);
4354 u32 val;
4355
4356 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
4357 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4358 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4359
4360 if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
4361 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
4362 1, false);
4363 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4364 RGB_MUX_SHIFT, cstate->crtc_id, false);
4365 vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK,
4366 GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
4367 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
4368 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4369 }
4370
4371 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
4372 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
4373 1, false);
4374 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4375 LVDS0_MUX_SHIFT, cstate->crtc_id, false);
4376 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4377 IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4378 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
4379 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4380 }
4381
4382 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
4383 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
4384 1, false);
4385 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4386 MIPI0_MUX_SHIFT, cstate->crtc_id, false);
4387 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4388 RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false);
4389 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
4390 RK3562_MIPI_PIN_POL_SHIFT, val, false);
4391
4392 if (conn_state->hold_mode) {
4393 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4394 EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
4395 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4396 EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
4397 }
4398 }
4399
4400 return mode->crtc_clock;
4401 }
4402
rk3528_vop2_if_cfg(struct display_state * state)4403 static unsigned long rk3528_vop2_if_cfg(struct display_state *state)
4404 {
4405 struct crtc_state *cstate = &state->crtc_state;
4406 struct connector_state *conn_state = &state->conn_state;
4407 struct drm_display_mode *mode = &conn_state->mode;
4408 struct vop2 *vop2 = cstate->private;
4409 u32 val;
4410
4411 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4412 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4413
4414 if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4415 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4416 1, false);
4417 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4418 RGB_MUX_SHIFT, cstate->crtc_id, false);
4419 }
4420
4421 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4422 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4423 1, false);
4424 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4425 HDMI0_MUX_SHIFT, cstate->crtc_id, false);
4426 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4427 IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
4428 vop2_mask_write(vop2, RK3568_DSP_IF_POL,
4429 IF_CRTL_HDMI_PIN_POL_MASK,
4430 IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4431 }
4432
4433 return mode->crtc_clock;
4434 }
4435
vop2_post_color_swap(struct display_state * state)4436 static void vop2_post_color_swap(struct display_state *state)
4437 {
4438 struct crtc_state *cstate = &state->crtc_state;
4439 struct connector_state *conn_state = &state->conn_state;
4440 struct vop2 *vop2 = cstate->private;
4441 u32 vp_offset = (cstate->crtc_id * 0x100);
4442 u32 output_type = conn_state->type;
4443 u32 data_swap = 0;
4444
4445 if (is_uv_swap(state) || is_rb_swap(state))
4446 data_swap = DSP_RB_SWAP;
4447
4448 if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) {
4449 if ((output_type == DRM_MODE_CONNECTOR_HDMIA ||
4450 output_type == DRM_MODE_CONNECTOR_DisplayPort) &&
4451 (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
4452 conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
4453 data_swap |= DSP_RG_SWAP;
4454 }
4455
4456 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
4457 DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false);
4458 }
4459
vop2_clk_set_parent(struct clk * clk,struct clk * parent)4460 static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
4461 {
4462 #ifndef CONFIG_MOS_SUPPORT
4463 int ret = 0;
4464
4465 if (parent->dev)
4466 ret = clk_set_parent(clk, parent);
4467 if (ret < 0)
4468 debug("failed to set %s as parent for %s\n",
4469 parent->dev->name, clk->dev->name);
4470 #endif
4471 }
4472
vop2_clk_set_rate(struct clk * clk,ulong rate)4473 static ulong vop2_clk_set_rate(struct clk *clk, ulong rate)
4474 {
4475 int ret = 0;
4476
4477 if (clk->dev)
4478 ret = clk_set_rate(clk, rate);
4479 if (ret < 0)
4480 debug("failed to set %s rate %lu \n", clk->dev->name, rate);
4481
4482 return ret;
4483 }
4484
vop2_calc_dsc_cru_cfg(struct display_state * state,int * dsc_txp_clk_div,int * dsc_pxl_clk_div,int * dsc_cds_clk_div,u64 dclk_rate)4485 static void vop2_calc_dsc_cru_cfg(struct display_state *state,
4486 int *dsc_txp_clk_div, int *dsc_pxl_clk_div,
4487 int *dsc_cds_clk_div, u64 dclk_rate)
4488 {
4489 struct crtc_state *cstate = &state->crtc_state;
4490
4491 *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate;
4492 *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate;
4493 *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate;
4494
4495 *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div);
4496 *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div);
4497 *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div);
4498 }
4499
vop2_load_pps(struct display_state * state,struct vop2 * vop2,u8 dsc_id)4500 static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id)
4501 {
4502 struct crtc_state *cstate = &state->crtc_state;
4503 struct drm_dsc_picture_parameter_set *pps = &cstate->pps;
4504 struct drm_dsc_picture_parameter_set config_pps;
4505 const struct vop2_data *vop2_data = vop2->data;
4506 const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
4507 u32 *pps_val = (u32 *)&config_pps;
4508 u32 decoder_regs_offset = (dsc_id * 0x100);
4509 int i = 0;
4510
4511 memcpy(&config_pps, pps, sizeof(config_pps));
4512
4513 if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) {
4514 config_pps.pps_3 &= 0xf0;
4515 config_pps.pps_3 |= dsc_data->max_linebuf_depth;
4516 printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
4517 dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf);
4518 }
4519
4520 for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
4521 config_pps.rc_range_parameters[i] =
4522 (pps->rc_range_parameters[i] >> 3 & 0x1f) |
4523 ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
4524 ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
4525 ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
4526 }
4527
4528 for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
4529 vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++);
4530 }
4531
vop2_dsc_enable(struct display_state * state,struct vop2 * vop2,u8 dsc_id,u64 dclk_rate)4532 static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate)
4533 {
4534 struct connector_state *conn_state = &state->conn_state;
4535 struct drm_display_mode *mode = &conn_state->mode;
4536 struct crtc_state *cstate = &state->crtc_state;
4537 struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
4538 const struct vop2_data *vop2_data = vop2->data;
4539 const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
4540 bool mipi_ds_mode = false;
4541 u8 dsc_interface_mode = 0;
4542 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
4543 u16 hdisplay = mode->crtc_hdisplay;
4544 u16 htotal = mode->crtc_htotal;
4545 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
4546 u16 vdisplay = mode->crtc_vdisplay;
4547 u16 vtotal = mode->crtc_vtotal;
4548 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
4549 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
4550 u16 vact_end = vact_st + vdisplay;
4551 u32 ctrl_regs_offset = (dsc_id * 0x30);
4552 u32 decoder_regs_offset = (dsc_id * 0x100);
4553 int dsc_txp_clk_div = 0;
4554 int dsc_pxl_clk_div = 0;
4555 int dsc_cds_clk_div = 0;
4556 int val = 0;
4557
4558 if (!vop2->data->nr_dscs) {
4559 printf("Unsupported DSC\n");
4560 return;
4561 }
4562
4563 if (cstate->dsc_slice_num > dsc_data->max_slice_num)
4564 printf("DSC%d supported max slice is: %d, current is: %d\n",
4565 dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num);
4566
4567 if (dsc_data->pd_id) {
4568 if (vop2_power_domain_on(vop2, dsc_data->pd_id))
4569 printf("open dsc%d pd fail\n", dsc_id);
4570 }
4571
4572 vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK,
4573 SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false);
4574 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK,
4575 DSC_PORT_SEL_SHIFT, cstate->crtc_id, false);
4576 if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
4577 dsc_interface_mode = VOP_DSC_IF_HDMI;
4578 } else {
4579 mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
4580 if (mipi_ds_mode)
4581 dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
4582 else
4583 dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
4584 }
4585
4586 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
4587 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
4588 DSC_MAN_MODE_SHIFT, 0, false);
4589 else
4590 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
4591 DSC_MAN_MODE_SHIFT, 1, false);
4592
4593 vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate);
4594
4595 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK,
4596 DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false);
4597 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK,
4598 DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false);
4599 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK,
4600 DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false);
4601 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK,
4602 DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false);
4603 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
4604 DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false);
4605 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK,
4606 DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false);
4607 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
4608 DSC_HALT_EN_SHIFT, mipi_ds_mode, false);
4609
4610 if (!mipi_ds_mode) {
4611 u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
4612 u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
4613 u64 dsc_cds_rate = cstate->dsc_cds_clk_rate;
4614 u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */
4615 u32 dly_num, dsc_cds_rate_mhz, val = 0;
4616 int k = 1;
4617
4618 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
4619 k = 2;
4620
4621 if (target_bpp >> 4 < dsc_data->min_bits_per_pixel)
4622 printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel);
4623
4624 /*
4625 * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
4626 * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
4627 * T (dsc_cds) = 1 / dsc_cds_rate_mhz
4628 *
4629 * HDMI:
4630 * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
4631 * delay_line_num = 4 - BPP / 8
4632 * = (64 - target_bpp / 8) / 16
4633 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
4634 *
4635 * MIPI DSI[4320 and 9216 is buffer size for DSC]:
4636 * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
4637 * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
4638 * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
4639 * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
4640 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
4641 */
4642 do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
4643 dsc_cds_rate_mhz = dsc_cds_rate;
4644 dsc_hsync = hsync_len / 2;
4645 if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
4646 dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
4647 } else {
4648 int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2;
4649 int delay_line_num = dsc_buf_size / cstate->dsc_slice_num /
4650 be16_to_cpu(cstate->pps.chunk_size);
4651
4652 delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
4653 dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
4654
4655 /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
4656 if (dsc_hsync < 8)
4657 dsc_hsync = 8;
4658 }
4659 vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK,
4660 DSC_INIT_DLY_MODE_SHIFT, 0, false);
4661 vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK,
4662 DSC_INIT_DLY_NUM_SHIFT, dly_num, false);
4663
4664 /*
4665 * htotal / dclk_core = dsc_htotal /cds_clk
4666 *
4667 * dclk_core = DCLK / (1 << dclk_core->div_val)
4668 * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
4669 * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
4670 *
4671 * dsc_htotal = htotal * (1 << dclk_core->div_val) /
4672 * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
4673 */
4674 dsc_htotal = htotal * (1 << cstate->dclk_core_div) /
4675 ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div));
4676 val = dsc_htotal << 16 | dsc_hsync;
4677 vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK,
4678 DSC_HTOTAL_PW_SHIFT, val, false);
4679
4680 dsc_hact_st = hact_st / 2;
4681 dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
4682 val = dsc_hact_end << 16 | dsc_hact_st;
4683 vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK,
4684 DSC_HACT_ST_END_SHIFT, val, false);
4685
4686 vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK,
4687 DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false);
4688 vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK,
4689 DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false);
4690 }
4691
4692 vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK,
4693 RST_DEASSERT_SHIFT, 1, false);
4694 udelay(10);
4695
4696 val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) |
4697 ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT);
4698 vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
4699
4700 vop2_load_pps(state, vop2, dsc_id);
4701
4702 val |= (1 << DSC_PPS_UPD_SHIFT);
4703 vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
4704
4705 printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
4706 dsc_id,
4707 cstate->dsc_txp_clk_rate, dsc_txp_clk_div,
4708 cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div,
4709 cstate->dsc_cds_clk_rate, dsc_cds_clk_div);
4710 }
4711
is_extend_pll(struct display_state * state,struct udevice ** clk_dev)4712 static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev)
4713 {
4714 struct crtc_state *cstate = &state->crtc_state;
4715 struct vop2 *vop2 = cstate->private;
4716 struct udevice *vp_dev, *dev;
4717 struct ofnode_phandle_args args;
4718 char vp_name[10];
4719 int ret;
4720
4721 if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576)
4722 return false;
4723
4724 sprintf(vp_name, "port@%d", cstate->crtc_id);
4725 if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) {
4726 debug("warn: can't get vp device\n");
4727 return false;
4728 }
4729
4730 ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0,
4731 0, &args);
4732 if (ret) {
4733 debug("assigned-clock-parents's node not define\n");
4734 return false;
4735 }
4736
4737 if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) {
4738 debug("warn: can't get clk device\n");
4739 return false;
4740 }
4741
4742 if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) {
4743 printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name);
4744 if (clk_dev)
4745 *clk_dev = dev;
4746 return true;
4747 }
4748
4749 return false;
4750 }
4751
vop3_mcu_mode_setup(struct display_state * state)4752 static void vop3_mcu_mode_setup(struct display_state *state)
4753 {
4754 struct crtc_state *cstate = &state->crtc_state;
4755 struct vop2 *vop2 = cstate->private;
4756 u32 vp_offset = (cstate->crtc_id * 0x100);
4757
4758 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4759 MCU_TYPE_SHIFT, 1, false);
4760 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4761 MCU_HOLD_MODE_SHIFT, 1, false);
4762 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
4763 MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false);
4764 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
4765 MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false);
4766 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
4767 MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false);
4768 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
4769 MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false);
4770 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
4771 MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false);
4772 }
4773
vop3_mcu_bypass_mode_setup(struct display_state * state)4774 static void vop3_mcu_bypass_mode_setup(struct display_state *state)
4775 {
4776 struct crtc_state *cstate = &state->crtc_state;
4777 struct vop2 *vop2 = cstate->private;
4778 u32 vp_offset = (cstate->crtc_id * 0x100);
4779
4780 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4781 MCU_TYPE_SHIFT, 1, false);
4782 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4783 MCU_HOLD_MODE_SHIFT, 1, false);
4784 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
4785 MCU_PIX_TOTAL_SHIFT, 53, false);
4786 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
4787 MCU_CS_PST_SHIFT, 6, false);
4788 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
4789 MCU_CS_PEND_SHIFT, 48, false);
4790 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
4791 MCU_RW_PST_SHIFT, 12, false);
4792 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
4793 MCU_RW_PEND_SHIFT, 30, false);
4794 }
4795
rockchip_vop2_send_mcu_cmd(struct display_state * state,u32 type,u32 value)4796 static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value)
4797 {
4798 struct crtc_state *cstate = &state->crtc_state;
4799 struct connector_state *conn_state = &state->conn_state;
4800 struct drm_display_mode *mode = &conn_state->mode;
4801 struct vop2 *vop2 = cstate->private;
4802 u32 vp_offset = (cstate->crtc_id * 0x100);
4803
4804 /*
4805 * 1.set mcu bypass mode timing.
4806 * 2.set dclk rate to 150M.
4807 */
4808 if (type == MCU_SETBYPASS && value) {
4809 vop3_mcu_bypass_mode_setup(state);
4810 vop2_clk_set_rate(&cstate->dclk, 150000000);
4811 }
4812
4813 switch (type) {
4814 case MCU_WRCMD:
4815 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4816 MCU_RS_SHIFT, 0, false);
4817 vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
4818 MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
4819 value, false);
4820 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4821 MCU_RS_SHIFT, 1, false);
4822 break;
4823 case MCU_WRDATA:
4824 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4825 MCU_RS_SHIFT, 1, false);
4826 vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
4827 MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
4828 value, false);
4829 break;
4830 case MCU_SETBYPASS:
4831 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
4832 MCU_BYPASS_SHIFT, value ? 1 : 0, false);
4833 break;
4834 default:
4835 break;
4836 }
4837
4838 /*
4839 * 1.restore mcu data mode timing.
4840 * 2.restore dclk rate to crtc_clock.
4841 */
4842 if (type == MCU_SETBYPASS && !value) {
4843 vop3_mcu_mode_setup(state);
4844 vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000);
4845 }
4846
4847 return 0;
4848 }
4849
vop2_dither_setup(struct vop2 * vop2,int bus_format,int crtc_id)4850 static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id)
4851 {
4852 const struct vop2_data *vop2_data = vop2->data;
4853 const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id];
4854 u32 vp_offset = crtc_id * 0x100;
4855 bool pre_dither_down_en = false;
4856
4857 switch (bus_format) {
4858 case MEDIA_BUS_FMT_RGB565_1X16:
4859 case MEDIA_BUS_FMT_RGB565_2X8_LE:
4860 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4861 PRE_DITHER_DOWN_EN_SHIFT, true, false);
4862 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4863 DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false);
4864 pre_dither_down_en = true;
4865 break;
4866 case MEDIA_BUS_FMT_RGB666_1X18:
4867 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
4868 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
4869 case MEDIA_BUS_FMT_RGB666_3X6:
4870 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4871 PRE_DITHER_DOWN_EN_SHIFT, true, false);
4872 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4873 DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false);
4874 pre_dither_down_en = true;
4875 break;
4876 case MEDIA_BUS_FMT_YUYV8_1X16:
4877 case MEDIA_BUS_FMT_YUV8_1X24:
4878 case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
4879 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4880 PRE_DITHER_DOWN_EN_SHIFT, false, false);
4881 pre_dither_down_en = true;
4882 break;
4883 case MEDIA_BUS_FMT_YUYV10_1X20:
4884 case MEDIA_BUS_FMT_YUV10_1X30:
4885 case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
4886 case MEDIA_BUS_FMT_RGB101010_1X30:
4887 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4888 PRE_DITHER_DOWN_EN_SHIFT, false, false);
4889 pre_dither_down_en = false;
4890 break;
4891 case MEDIA_BUS_FMT_RGB888_3X8:
4892 case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
4893 case MEDIA_BUS_FMT_RGB888_1X24:
4894 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
4895 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
4896 default:
4897 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4898 PRE_DITHER_DOWN_EN_SHIFT, false, false);
4899 pre_dither_down_en = true;
4900 break;
4901 }
4902
4903 if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0)
4904 pre_dither_down_en = false;
4905
4906 if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) {
4907 if (vop2->version == VOP_VERSION_RK3576) {
4908 vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000);
4909 vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100);
4910 vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100);
4911 }
4912
4913 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4914 PRE_DITHER_DOWN_EN_SHIFT, 0, false);
4915 /* enable frc2.0 do 10->8 */
4916 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4917 DITHER_DOWN_EN_SHIFT, 1, false);
4918 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4919 DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false);
4920 } else {
4921 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4922 PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
4923 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4924 DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false);
4925 }
4926 }
4927
rockchip_vop2_init(struct display_state * state)4928 static int rockchip_vop2_init(struct display_state *state)
4929 {
4930 struct crtc_state *cstate = &state->crtc_state;
4931 struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
4932 struct connector_state *conn_state = &state->conn_state;
4933 struct drm_display_mode *mode = &conn_state->mode;
4934 struct vop2 *vop2 = cstate->private;
4935 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
4936 u16 hdisplay = mode->crtc_hdisplay;
4937 u16 htotal = mode->crtc_htotal;
4938 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
4939 u16 hact_end = hact_st + hdisplay;
4940 u16 vdisplay = mode->crtc_vdisplay;
4941 u16 vtotal = mode->crtc_vtotal;
4942 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
4943 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
4944 u16 vact_end = vact_st + vdisplay;
4945 bool yuv_overlay = false;
4946 u32 vp_offset = (cstate->crtc_id * 0x100);
4947 u32 line_flag_offset = (cstate->crtc_id * 4);
4948 u32 val, act_end;
4949 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4950 u8 dclk_div_factor = 0;
4951 u8 vp_dclk_div = 1;
4952 char output_type_name[30] = {0};
4953 #ifndef CONFIG_SPL_BUILD
4954 char dclk_name[9];
4955 #endif
4956 struct clk hdmi0_phy_pll;
4957 struct clk hdmi1_phy_pll;
4958 struct clk hdmi_phy_pll;
4959 struct udevice *disp_dev;
4960 unsigned long dclk_rate = 0;
4961 int ret;
4962
4963 printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
4964 mode->crtc_hdisplay, mode->vdisplay,
4965 mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
4966 mode->vrefresh,
4967 rockchip_get_output_if_name(conn_state->output_if, output_type_name),
4968 cstate->crtc_id);
4969
4970 if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
4971 cstate->splice_mode = true;
4972 cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id;
4973 if (!cstate->splice_crtc_id) {
4974 printf("%s: Splice mode is unsupported by vp%d\n",
4975 __func__, cstate->crtc_id);
4976 return -EINVAL;
4977 }
4978
4979 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK,
4980 PORT_MERGE_EN_SHIFT, 1, false);
4981 }
4982
4983 vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4984 RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4985 vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4986 RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4987
4988 if (vop2->data->vp_data[cstate->crtc_id].urgency) {
4989 u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl;
4990 u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh;
4991
4992 vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK,
4993 AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
4994 vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK,
4995 AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
4996 vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK,
4997 POST_URGENCY_EN_SHIFT, 1, false);
4998 vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK,
4999 POST_URGENCY_THL_SHIFT, urgen_thl, false);
5000 vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK,
5001 POST_URGENCY_THH_SHIFT, urgen_thh, false);
5002 }
5003
5004 vop2_initial(vop2, state);
5005 if (vop2->version == VOP_VERSION_RK3588)
5006 dclk_rate = rk3588_vop2_if_cfg(state);
5007 else if (vop2->version == VOP_VERSION_RK3576)
5008 dclk_rate = rk3576_vop2_if_cfg(state);
5009 else if (vop2->version == VOP_VERSION_RK3568)
5010 dclk_rate = rk3568_vop2_if_cfg(state);
5011 else if (vop2->version == VOP_VERSION_RK3562)
5012 dclk_rate = rk3562_vop2_if_cfg(state);
5013 else if (vop2->version == VOP_VERSION_RK3528)
5014 dclk_rate = rk3528_vop2_if_cfg(state);
5015
5016 if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
5017 !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
5018 conn_state->output_if & VOP_OUTPUT_IF_BT656)
5019 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
5020
5021 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
5022 if (vop2->version == VOP_VERSION_RK3588 &&
5023 conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
5024 conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420;
5025 } else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) {
5026 if (vop2->version == VOP_VERSION_RK3576 &&
5027 conn_state->type == DRM_MODE_CONNECTOR_eDP)
5028 conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422;
5029 else if (vop2->version == VOP_VERSION_RK3588 &&
5030 conn_state->type == DRM_MODE_CONNECTOR_eDP)
5031 conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422;
5032 else if (vop2->version == VOP_VERSION_RK3576 &&
5033 conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
5034 conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422;
5035 else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
5036 conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422;
5037 }
5038
5039 vop2_post_color_swap(state);
5040
5041 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
5042 OUT_MODE_SHIFT, conn_state->output_mode, false);
5043
5044 vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id);
5045 if (cstate->splice_mode)
5046 vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id);
5047
5048 yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
5049 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
5050 yuv_overlay, false);
5051
5052 cstate->yuv_overlay = yuv_overlay;
5053
5054 vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
5055 (htotal << 16) | hsync_len);
5056 val = hact_st << 16;
5057 val |= hact_end;
5058 vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
5059 val = vact_st << 16;
5060 val |= vact_end;
5061 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
5062 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
5063 u16 vact_st_f1 = vtotal + vact_st + 1;
5064 u16 vact_end_f1 = vact_st_f1 + vdisplay;
5065
5066 val = vact_st_f1 << 16 | vact_end_f1;
5067 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
5068 val);
5069
5070 val = vtotal << 16 | (vtotal + vsync_len);
5071 vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
5072 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5073 INTERLACE_EN_SHIFT, 1, false);
5074 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5075 DSP_FILED_POL, 1, false);
5076 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5077 P2I_EN_SHIFT, 1, false);
5078 vtotal += vtotal + 1;
5079 act_end = vact_end_f1;
5080 } else {
5081 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5082 INTERLACE_EN_SHIFT, 0, false);
5083 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5084 P2I_EN_SHIFT, 0, false);
5085 act_end = vact_end;
5086 }
5087 vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
5088 (vtotal << 16) | vsync_len);
5089
5090 if (vop2->version == VOP_VERSION_RK3528 ||
5091 vop2->version == VOP_VERSION_RK3562 ||
5092 vop2->version == VOP_VERSION_RK3568) {
5093 if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
5094 conn_state->output_if & VOP_OUTPUT_IF_BT656)
5095 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5096 CORE_DCLK_DIV_EN_SHIFT, 1, false);
5097 else
5098 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5099 CORE_DCLK_DIV_EN_SHIFT, 0, false);
5100
5101 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
5102 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
5103 DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
5104 else
5105 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
5106 DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
5107 }
5108
5109 vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
5110 OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false);
5111
5112 if (yuv_overlay)
5113 val = 0x20010200;
5114 else
5115 val = 0;
5116 vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
5117 if (cstate->splice_mode) {
5118 vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
5119 OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id,
5120 yuv_overlay, false);
5121 vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val);
5122 }
5123
5124 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5125 POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
5126
5127 if (vp->xmirror_en)
5128 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5129 DSP_X_MIR_EN_SHIFT, 1, false);
5130
5131 vop2_tv_config_update(state, vop2);
5132 vop2_post_config(state, vop2);
5133 if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
5134 vop3_post_config(state, vop2);
5135
5136 if (cstate->dsc_enable) {
5137 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
5138 vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL);
5139 vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL);
5140 } else {
5141 vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL);
5142 }
5143 }
5144
5145 #ifndef CONFIG_SPL_BUILD
5146 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
5147 ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk);
5148 if (ret) {
5149 printf("%s: Failed to get dclk ret=%d\n", __func__, ret);
5150 return ret;
5151 }
5152 #endif
5153
5154 ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev);
5155 if (!ret) {
5156 ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll);
5157 if (ret)
5158 debug("%s: hdmi0_phy_pll may not define\n", __func__);
5159 ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll);
5160 if (ret)
5161 debug("%s: hdmi1_phy_pll may not define\n", __func__);
5162 } else {
5163 hdmi0_phy_pll.dev = NULL;
5164 hdmi1_phy_pll.dev = NULL;
5165 debug("%s: Faile to find display-subsystem node\n", __func__);
5166 }
5167
5168 if (vop2->version == VOP_VERSION_RK3528) {
5169 struct ofnode_phandle_args args;
5170
5171 ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents",
5172 "#clock-cells", 0, 0, &args);
5173 if (!ret) {
5174 ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev);
5175 if (ret) {
5176 debug("warn: can't get clk device\n");
5177 return ret;
5178 }
5179 } else {
5180 debug("assigned-clock-parents's node not define\n");
5181 }
5182 }
5183
5184 if (vop2->version == VOP_VERSION_RK3576)
5185 vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div;
5186
5187 if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) {
5188 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0)
5189 vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll);
5190 else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1)
5191 vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll);
5192
5193 /*
5194 * uboot clk driver won't set dclk parent's rate when use
5195 * hdmi phypll as dclk source.
5196 * So set dclk rate is meaningless. Set hdmi phypll rate
5197 * directly.
5198 */
5199 if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) {
5200 ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000);
5201 } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) {
5202 ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000);
5203 } else {
5204 if (is_extend_pll(state, &hdmi_phy_pll.dev)) {
5205 ret = vop2_clk_set_rate(&hdmi_phy_pll,
5206 dclk_rate / vp_dclk_div * 1000);
5207 } else {
5208 #ifndef CONFIG_SPL_BUILD
5209 ret = vop2_clk_set_rate(&cstate->dclk,
5210 dclk_rate / vp_dclk_div * 1000);
5211 #else
5212 if (vop2->version == VOP_VERSION_RK3528) {
5213 void *cru_base = (void *)RK3528_CRU_BASE;
5214
5215 /* dclk src switch to hdmiphy pll */
5216 writel((BIT(0) << 16) | BIT(0), cru_base + 0x450);
5217 rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000);
5218 ret = dclk_rate * 1000;
5219 }
5220 #endif
5221 }
5222 }
5223 } else {
5224 if (is_extend_pll(state, &hdmi_phy_pll.dev))
5225 ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000);
5226 else
5227 ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000);
5228 }
5229
5230 if (IS_ERR_VALUE(ret)) {
5231 printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
5232 __func__, cstate->crtc_id, dclk_rate, ret);
5233 return ret;
5234 } else {
5235 if (cstate->mcu_timing.mcu_pix_total) {
5236 mode->crtc_clock = roundup(ret, 1000) / 1000;
5237 } else {
5238 dclk_div_factor = mode->crtc_clock / dclk_rate;
5239 mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000;
5240 }
5241 printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock);
5242 }
5243
5244 vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
5245 RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false);
5246 vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
5247 RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false);
5248
5249 if (cstate->mcu_timing.mcu_pix_total) {
5250 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5251 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5252 STANDBY_EN_SHIFT, 0, false);
5253 vop3_mcu_mode_setup(state);
5254 }
5255
5256 return 0;
5257 }
5258
vop2_setup_scale(struct vop2 * vop2,struct vop2_win_data * win,uint32_t src_w,uint32_t src_h,uint32_t dst_w,uint32_t dst_h)5259 static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
5260 uint32_t src_w, uint32_t src_h, uint32_t dst_w,
5261 uint32_t dst_h)
5262 {
5263 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
5264 uint16_t hscl_filter_mode, vscl_filter_mode;
5265 uint8_t xgt2 = 0, xgt4 = 0;
5266 uint8_t ygt2 = 0, ygt4 = 0;
5267 uint32_t xfac = 0, yfac = 0;
5268 u32 win_offset = win->reg_offset;
5269 bool xgt_en = false;
5270 bool xavg_en = false;
5271
5272 if (is_vop3(vop2)) {
5273 if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) {
5274 if (src_w >= (8 * dst_w)) {
5275 xgt4 = 1;
5276 src_w >>= 2;
5277 } else if (src_w >= (4 * dst_w)) {
5278 xgt2 = 1;
5279 src_w >>= 1;
5280 }
5281 } else {
5282 if (src_w >= (4 * dst_w)) {
5283 xgt4 = 1;
5284 src_w >>= 2;
5285 } else if (src_w >= (2 * dst_w)) {
5286 xgt2 = 1;
5287 src_w >>= 1;
5288 }
5289 }
5290 }
5291
5292 /**
5293 * The rk3528 is processed as 2 pixel/cycle,
5294 * so ygt2/ygt4 needs to be triggered in advance to improve performance
5295 * when src_w is bigger than 1920.
5296 * dst_h / src_h is at [1, 0.65) ygt2=0; ygt4=0;
5297 * dst_h / src_h is at [0.65, 0.35) ygt2=1; ygt4=0;
5298 * dst_h / src_h is at [0.35, 0) ygt2=0; ygt4=1;
5299 */
5300 if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
5301 if (src_h >= (100 * dst_h / 35)) {
5302 ygt4 = 1;
5303 src_h >>= 2;
5304 } else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) {
5305 ygt2 = 1;
5306 src_h >>= 1;
5307 }
5308 } else {
5309 if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) {
5310 if (src_h >= (8 * dst_h)) {
5311 ygt4 = 1;
5312 src_h >>= 2;
5313 } else if (src_h >= (4 * dst_h)) {
5314 ygt2 = 1;
5315 src_h >>= 1;
5316 }
5317 } else {
5318 if (src_h >= (4 * dst_h)) {
5319 ygt4 = 1;
5320 src_h >>= 2;
5321 } else if (src_h >= (2 * dst_h)) {
5322 ygt2 = 1;
5323 src_h >>= 1;
5324 }
5325 }
5326 }
5327
5328 yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
5329 yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
5330
5331 if (yrgb_hor_scl_mode == SCALE_UP)
5332 hscl_filter_mode = win->hsu_filter_mode;
5333 else
5334 hscl_filter_mode = win->hsd_filter_mode;
5335
5336 if (yrgb_ver_scl_mode == SCALE_UP)
5337 vscl_filter_mode = win->vsu_filter_mode;
5338 else
5339 vscl_filter_mode = win->vsd_filter_mode;
5340
5341 /*
5342 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
5343 * at scale down mode
5344 */
5345 if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) {
5346 printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
5347 dst_w += 1;
5348 }
5349
5350 if (is_vop3(vop2)) {
5351 xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true);
5352 yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false);
5353
5354 if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG)
5355 xavg_en = xgt2 || xgt4;
5356 else
5357 xgt_en = xgt2 || xgt4;
5358
5359 if (vop2->version == VOP_VERSION_RK3576) {
5360 bool zme_dering_en = false;
5361
5362 if ((yrgb_hor_scl_mode == SCALE_UP &&
5363 hscl_filter_mode == VOP2_SCALE_UP_ZME) ||
5364 (yrgb_ver_scl_mode == SCALE_UP &&
5365 vscl_filter_mode == VOP2_SCALE_UP_ZME))
5366 zme_dering_en = true;
5367
5368 /* Recommended configuration from the algorithm */
5369 vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset,
5370 0x04100d10);
5371 vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset,
5372 EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false);
5373 }
5374 } else {
5375 xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
5376 yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
5377 }
5378
5379 if (win->type == CLUSTER_LAYER) {
5380 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
5381 yfac << 16 | xfac);
5382
5383 if (is_vop3(vop2)) {
5384 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5385 EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false);
5386 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5387 EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false);
5388 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5389 XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
5390
5391 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5392 YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT,
5393 yrgb_hor_scl_mode, false);
5394 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5395 YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT,
5396 yrgb_ver_scl_mode, false);
5397 } else {
5398 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5399 YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT,
5400 yrgb_hor_scl_mode, false);
5401 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5402 YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT,
5403 yrgb_ver_scl_mode, false);
5404 }
5405
5406 if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
5407 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5408 YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false);
5409 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5410 YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false);
5411 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5412 AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false);
5413 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5414 AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false);
5415 } else {
5416 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5417 YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false);
5418 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5419 YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false);
5420 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5421 AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false);
5422 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
5423 AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false);
5424 }
5425 } else {
5426 vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
5427 yfac << 16 | xfac);
5428
5429 if (is_vop3(vop2)) {
5430 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5431 EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false);
5432 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5433 EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false);
5434 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5435 XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
5436 }
5437
5438 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5439 YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false);
5440 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5441 YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false);
5442
5443 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
5444 YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
5445 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
5446 YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
5447
5448 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
5449 YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
5450 hscl_filter_mode, false);
5451 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
5452 YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
5453 vscl_filter_mode, false);
5454 }
5455 }
5456
vop2_axi_config(struct vop2 * vop2,struct vop2_win_data * win)5457 static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win)
5458 {
5459 u32 win_offset = win->reg_offset;
5460
5461 if (win->type == CLUSTER_LAYER) {
5462 vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK,
5463 CLUSTER_AXI_ID_SHIFT, win->axi_id, false);
5464 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK,
5465 CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5466 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK,
5467 CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5468 } else {
5469 vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK,
5470 ESMART_AXI_ID_SHIFT, win->axi_id, false);
5471 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK,
5472 ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5473 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK,
5474 ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5475 }
5476 }
5477
vop2_win_dither_up(uint32_t format)5478 static bool vop2_win_dither_up(uint32_t format)
5479 {
5480 switch (format) {
5481 case ROCKCHIP_FMT_RGB565:
5482 return true;
5483 default:
5484 return false;
5485 }
5486 }
5487
vop2_is_mirror_win(struct vop2_win_data * win)5488 static bool vop2_is_mirror_win(struct vop2_win_data *win)
5489 {
5490 return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR);
5491 }
5492
vop2_set_cluster_win(struct display_state * state,struct vop2_win_data * win)5493 static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
5494 {
5495 struct crtc_state *cstate = &state->crtc_state;
5496 struct connector_state *conn_state = &state->conn_state;
5497 struct drm_display_mode *mode = &conn_state->mode;
5498 struct vop2 *vop2 = cstate->private;
5499 const struct vop2_data *vop2_data = vop2->data;
5500 const struct vop2_ops *vop2_ops = vop2_data->ops;
5501 int src_w = cstate->src_rect.w;
5502 int src_h = cstate->src_rect.h;
5503 int crtc_x = cstate->crtc_rect.x;
5504 int crtc_y = cstate->crtc_rect.y;
5505 int crtc_w = cstate->crtc_rect.w;
5506 int crtc_h = cstate->crtc_rect.h;
5507 int xvir = cstate->xvir;
5508 int y_mirror = 0;
5509 int csc_mode;
5510 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5511 /* offset of the right window in splice mode */
5512 u32 splice_pixel_offset = 0;
5513 u32 splice_yrgb_offset = 0;
5514 u32 win_offset = win->reg_offset;
5515 bool dither_up;
5516
5517 if (win->splice_mode_right) {
5518 src_w = cstate->right_src_rect.w;
5519 src_h = cstate->right_src_rect.h;
5520 crtc_x = cstate->right_crtc_rect.x;
5521 crtc_y = cstate->right_crtc_rect.y;
5522 crtc_w = cstate->right_crtc_rect.w;
5523 crtc_h = cstate->right_crtc_rect.h;
5524 splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5525 splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5526 }
5527
5528 act_info = (src_h - 1) << 16;
5529 act_info |= (src_w - 1) & 0xffff;
5530
5531 dsp_info = (crtc_h - 1) << 16;
5532 dsp_info |= (crtc_w - 1) & 0xffff;
5533
5534 dsp_stx = crtc_x;
5535 dsp_sty = crtc_y;
5536 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5537
5538 if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5539 y_mirror = 1;
5540 else
5541 y_mirror = 0;
5542
5543 vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
5544
5545 if (vop2->version != VOP_VERSION_RK3568)
5546 vop2_axi_config(vop2, win);
5547
5548 if (y_mirror)
5549 printf("WARN: y mirror is unsupported by cluster window\n");
5550
5551 if (is_vop3(vop2)) {
5552 vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset,
5553 CLUSTER_PORT_SEL_MASK, CLUSTER_PORT_SEL_SHIFT,
5554 cstate->crtc_id, false);
5555 vop2_ops->setup_win_dly(state, cstate->crtc_id, win->phys_id);
5556 }
5557
5558 /*
5559 * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode.
5560 */
5561 if (vop2->version >= VOP_VERSION_RK3588)
5562 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset,
5563 EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false);
5564
5565 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
5566 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5567 false);
5568 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
5569 0x1, CLUSTER_RB_SWAP_SHIFT, cstate->rb_swap, false);
5570 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
5571 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset,
5572 cstate->dma_addr + splice_yrgb_offset);
5573
5574 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
5575 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
5576 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
5577
5578 csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5579 CSC_10BIT_DEPTH);
5580 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5581 CLUSTER_RGB2YUV_EN_SHIFT,
5582 is_yuv_output(conn_state->bus_format), false);
5583 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
5584 CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
5585
5586 dither_up = vop2_win_dither_up(cstate->format);
5587 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5588 CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false);
5589
5590 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
5591 vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
5592
5593 return 0;
5594 }
5595
vop2_set_smart_win(struct display_state * state,struct vop2_win_data * win)5596 static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
5597 {
5598 struct crtc_state *cstate = &state->crtc_state;
5599 struct connector_state *conn_state = &state->conn_state;
5600 struct drm_display_mode *mode = &conn_state->mode;
5601 struct vop2 *vop2 = cstate->private;
5602 const struct vop2_data *vop2_data = vop2->data;
5603 const struct vop2_ops *vop2_ops = vop2_data->ops;
5604 int src_w = cstate->src_rect.w;
5605 int src_h = cstate->src_rect.h;
5606 int crtc_x = cstate->crtc_rect.x;
5607 int crtc_y = cstate->crtc_rect.y;
5608 int crtc_w = cstate->crtc_rect.w;
5609 int crtc_h = cstate->crtc_rect.h;
5610 int xvir = cstate->xvir;
5611 int y_mirror = 0;
5612 int csc_mode;
5613 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5614 /* offset of the right window in splice mode */
5615 u32 splice_pixel_offset = 0;
5616 u32 splice_yrgb_offset = 0;
5617 u32 win_offset = win->reg_offset;
5618 u32 val;
5619 bool dither_up;
5620
5621 if (vop2_is_mirror_win(win)) {
5622 struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id);
5623
5624 if (!source_win) {
5625 printf("invalid source win id %d\n", win->source_win_id);
5626 return -ENODEV;
5627 }
5628
5629 val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset);
5630 if (!(val & BIT(WIN_EN_SHIFT))) {
5631 printf("WARN: the source win should be enabled before mirror win\n");
5632 return -EAGAIN;
5633 }
5634 }
5635
5636 if (win->splice_mode_right) {
5637 src_w = cstate->right_src_rect.w;
5638 src_h = cstate->right_src_rect.h;
5639 crtc_x = cstate->right_crtc_rect.x;
5640 crtc_y = cstate->right_crtc_rect.y;
5641 crtc_w = cstate->right_crtc_rect.w;
5642 crtc_h = cstate->right_crtc_rect.h;
5643 splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5644 splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5645 }
5646
5647 /*
5648 * This is workaround solution for IC design:
5649 * esmart can't support scale down when actual_w % 16 == 1.
5650 */
5651 if (src_w > crtc_w && (src_w & 0xf) == 1) {
5652 printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
5653 src_w -= 1;
5654 }
5655
5656 act_info = (src_h - 1) << 16;
5657 act_info |= (src_w - 1) & 0xffff;
5658
5659 dsp_info = (crtc_h - 1) << 16;
5660 dsp_info |= (crtc_w - 1) & 0xffff;
5661
5662 dsp_stx = crtc_x;
5663 dsp_sty = crtc_y;
5664 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5665
5666 if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5667 y_mirror = 1;
5668 else
5669 y_mirror = 0;
5670
5671 if (is_vop3(vop2)) {
5672 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset,
5673 ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT,
5674 win->scale_engine_num, false);
5675 vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5676 ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5677 cstate->crtc_id, false);
5678 vop2_ops->setup_win_dly(state, cstate->crtc_id, win->phys_id);
5679
5680 /* Merge esmart1/3 from vp1 post to vp0 */
5681 if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 &&
5682 (win->phys_id == ROCKCHIP_VOP2_ESMART1 ||
5683 win->phys_id == ROCKCHIP_VOP2_ESMART3))
5684 vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5685 ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5686 1, false);
5687 }
5688
5689 vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
5690
5691 if (vop2->version != VOP_VERSION_RK3568)
5692 vop2_axi_config(vop2, win);
5693
5694 if (y_mirror)
5695 cstate->dma_addr += (src_h - 1) * xvir * 4;
5696 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
5697 YMIRROR_EN_SHIFT, y_mirror, false);
5698
5699 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5700 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5701 false);
5702
5703 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5704 0x1, REGION0_RB_SWAP_SHIFT, cstate->rb_swap, false);
5705
5706 if (vop2->version == VOP_VERSION_RK3576)
5707 vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00);
5708
5709 vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
5710 vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
5711 cstate->dma_addr + splice_yrgb_offset);
5712
5713 vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
5714 act_info);
5715 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
5716 dsp_info);
5717 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
5718
5719 csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5720 CSC_10BIT_DEPTH);
5721 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
5722 RGB2YUV_EN_SHIFT,
5723 is_yuv_output(conn_state->bus_format), false);
5724 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
5725 CSC_MODE_SHIFT, csc_mode, false);
5726
5727 dither_up = vop2_win_dither_up(cstate->format);
5728 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5729 REGION0_DITHER_UP_EN_SHIFT, dither_up, false);
5730
5731 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5732 WIN_EN_SHIFT, 1, false);
5733
5734 return 0;
5735 }
5736
vop2_calc_display_rect_for_splice(struct display_state * state)5737 static void vop2_calc_display_rect_for_splice(struct display_state *state)
5738 {
5739 struct crtc_state *cstate = &state->crtc_state;
5740 struct connector_state *conn_state = &state->conn_state;
5741 struct drm_display_mode *mode = &conn_state->mode;
5742 struct display_rect *src_rect = &cstate->src_rect;
5743 struct display_rect *dst_rect = &cstate->crtc_rect;
5744 struct display_rect left_src, left_dst, right_src, right_dst;
5745 u16 half_hdisplay = mode->crtc_hdisplay >> 1;
5746 int left_src_w, left_dst_w, right_dst_w;
5747
5748 left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x;
5749 if (left_dst_w < 0)
5750 left_dst_w = 0;
5751 right_dst_w = dst_rect->w - left_dst_w;
5752
5753 if (!right_dst_w)
5754 left_src_w = src_rect->w;
5755 else
5756 left_src_w = src_rect->x + src_rect->w - src_rect->w / 2;
5757
5758 left_src.x = src_rect->x;
5759 left_src.w = left_src_w;
5760 left_dst.x = dst_rect->x;
5761 left_dst.w = left_dst_w;
5762 right_src.x = left_src.x + left_src.w;
5763 right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w;
5764 right_dst.x = dst_rect->x + left_dst_w - half_hdisplay;
5765 right_dst.w = right_dst_w;
5766
5767 left_src.y = src_rect->y;
5768 left_src.h = src_rect->h;
5769 left_dst.y = dst_rect->y;
5770 left_dst.h = dst_rect->h;
5771 right_src.y = src_rect->y;
5772 right_src.h = src_rect->h;
5773 right_dst.y = dst_rect->y;
5774 right_dst.h = dst_rect->h;
5775
5776 memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect));
5777 memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect));
5778 memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect));
5779 memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect));
5780 }
5781
rockchip_vop2_set_plane(struct display_state * state)5782 static int rockchip_vop2_set_plane(struct display_state *state)
5783 {
5784 struct crtc_state *cstate = &state->crtc_state;
5785 struct vop2 *vop2 = cstate->private;
5786 struct vop2_win_data *win_data;
5787 struct vop2_win_data *splice_win_data;
5788 u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
5789 int ret;
5790
5791 if (cstate->crtc_rect.w > cstate->max_output.width) {
5792 printf("ERROR: output w[%d] exceeded max width[%d]\n",
5793 cstate->crtc_rect.w, cstate->max_output.width);
5794 return -EINVAL;
5795 }
5796
5797 win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
5798 if (!win_data) {
5799 printf("invalid win id %d\n", primary_plane_id);
5800 return -ENODEV;
5801 }
5802
5803 /* ignore some plane register according vop3 esmart lb mode */
5804 if (vop3_ignore_plane(vop2, win_data))
5805 return -EACCES;
5806
5807 if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) {
5808 if (vop2_power_domain_on(vop2, win_data->pd_id))
5809 printf("open vp%d plane pd fail\n", cstate->crtc_id);
5810 }
5811
5812 if (cstate->splice_mode) {
5813 if (win_data->splice_win_id) {
5814 splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id);
5815 splice_win_data->splice_mode_right = true;
5816
5817 if (vop2_power_domain_on(vop2, splice_win_data->pd_id))
5818 printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id);
5819
5820 vop2_calc_display_rect_for_splice(state);
5821 if (win_data->type == CLUSTER_LAYER)
5822 vop2_set_cluster_win(state, splice_win_data);
5823 else
5824 vop2_set_smart_win(state, splice_win_data);
5825 } else {
5826 printf("ERROR: splice mode is unsupported by plane %s\n",
5827 vop2_plane_phys_id_to_string(primary_plane_id));
5828 return -EINVAL;
5829 }
5830 }
5831
5832 if (win_data->type == CLUSTER_LAYER)
5833 ret = vop2_set_cluster_win(state, win_data);
5834 else
5835 ret = vop2_set_smart_win(state, win_data);
5836 if (ret)
5837 return ret;
5838
5839 printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
5840 cstate->crtc_id, vop2_plane_phys_id_to_string(primary_plane_id),
5841 cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h,
5842 cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format,
5843 cstate->dma_addr);
5844
5845 return 0;
5846 }
5847
rockchip_vop2_prepare(struct display_state * state)5848 static int rockchip_vop2_prepare(struct display_state *state)
5849 {
5850 return 0;
5851 }
5852
vop2_dsc_cfg_done(struct display_state * state)5853 static void vop2_dsc_cfg_done(struct display_state *state)
5854 {
5855 struct connector_state *conn_state = &state->conn_state;
5856 struct crtc_state *cstate = &state->crtc_state;
5857 struct vop2 *vop2 = cstate->private;
5858 u8 dsc_id = cstate->dsc_id;
5859 u32 ctrl_regs_offset = (dsc_id * 0x30);
5860
5861 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
5862 vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK,
5863 DSC_CFG_DONE_SHIFT, 1, false);
5864 vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK,
5865 DSC_CFG_DONE_SHIFT, 1, false);
5866 } else {
5867 vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK,
5868 DSC_CFG_DONE_SHIFT, 1, false);
5869 }
5870 }
5871
rockchip_vop2_enable(struct display_state * state)5872 static int rockchip_vop2_enable(struct display_state *state)
5873 {
5874 struct crtc_state *cstate = &state->crtc_state;
5875 struct vop2 *vop2 = cstate->private;
5876 u32 vp_offset = (cstate->crtc_id * 0x100);
5877 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5878
5879 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5880 STANDBY_EN_SHIFT, 0, false);
5881
5882 if (cstate->splice_mode)
5883 cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5884
5885 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5886
5887 if (cstate->dsc_enable)
5888 vop2_dsc_cfg_done(state);
5889
5890 if (cstate->mcu_timing.mcu_pix_total)
5891 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
5892 MCU_HOLD_MODE_SHIFT, 0, false);
5893
5894 return 0;
5895 }
5896
rk3588_vop2_post_enable(struct display_state * state)5897 static int rk3588_vop2_post_enable(struct display_state *state)
5898 {
5899 struct connector_state *conn_state = &state->conn_state;
5900 struct crtc_state *cstate = &state->crtc_state;
5901 struct vop2 *vop2 = cstate->private;
5902 int output_if = conn_state->output_if;
5903 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5904 int ret, val;
5905
5906 if (output_if & VOP_OUTPUT_IF_DP0)
5907 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
5908 1, false);
5909
5910 if (output_if & VOP_OUTPUT_IF_DP1)
5911 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT,
5912 1, false);
5913
5914 if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) {
5915 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5916 ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5917 val & BIT(cstate->crtc_id), 50 * 1000);
5918 if (ret)
5919 printf("%s wait cfg done timeout\n", __func__);
5920
5921 if (cstate->dclk_rst.dev) {
5922 reset_assert(&cstate->dclk_rst);
5923 udelay(20);
5924 reset_deassert(&cstate->dclk_rst);
5925 }
5926 }
5927
5928 return 0;
5929 }
5930
rk3576_vop2_post_enable(struct display_state * state)5931 static int rk3576_vop2_post_enable(struct display_state *state)
5932 {
5933 struct connector_state *conn_state = &state->conn_state;
5934 struct crtc_state *cstate = &state->crtc_state;
5935 struct vop2 *vop2 = cstate->private;
5936 int output_if = conn_state->output_if;
5937 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5938 int ret, val;
5939
5940 if (output_if & VOP_OUTPUT_IF_DP0)
5941 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
5942 RK3576_IF_OUT_EN_SHIFT, 1, false);
5943
5944 if (output_if & VOP_OUTPUT_IF_DP1)
5945 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
5946 RK3576_IF_OUT_EN_SHIFT, 1, false);
5947
5948 if (output_if & VOP_OUTPUT_IF_DP2)
5949 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
5950 RK3576_IF_OUT_EN_SHIFT, 1, false);
5951
5952 if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
5953 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5954 ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5955 val & BIT(cstate->crtc_id), 50 * 1000);
5956 if (ret)
5957 printf("%s wait cfg done timeout\n", __func__);
5958
5959 if (cstate->dclk_rst.dev) {
5960 reset_assert(&cstate->dclk_rst);
5961 udelay(20);
5962 reset_deassert(&cstate->dclk_rst);
5963 }
5964 }
5965
5966 return 0;
5967 }
5968
rockchip_vop2_post_enable(struct display_state * state)5969 static int rockchip_vop2_post_enable(struct display_state *state)
5970 {
5971 struct crtc_state *cstate = &state->crtc_state;
5972 struct vop2 *vop2 = cstate->private;
5973
5974 if (vop2->version == VOP_VERSION_RK3588)
5975 rk3588_vop2_post_enable(state);
5976 else if (vop2->version == VOP_VERSION_RK3576)
5977 rk3576_vop2_post_enable(state);
5978
5979 return 0;
5980 }
5981
rockchip_vop2_disable(struct display_state * state)5982 static int rockchip_vop2_disable(struct display_state *state)
5983 {
5984 struct crtc_state *cstate = &state->crtc_state;
5985 struct vop2 *vop2 = cstate->private;
5986 u32 vp_offset = (cstate->crtc_id * 0x100);
5987 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5988
5989 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5990 STANDBY_EN_SHIFT, 1, false);
5991
5992 if (cstate->splice_mode)
5993 cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5994
5995 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5996
5997 return 0;
5998 }
5999
rockchip_vop2_fixup_dts(struct display_state * state,void * blob)6000 static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
6001 {
6002 struct crtc_state *cstate = &state->crtc_state;
6003 struct vop2 *vop2 = cstate->private;
6004 ofnode vp_node;
6005 struct device_node *port_parent_node = cstate->ports_node;
6006 static bool vop_fix_dts;
6007 const char *path;
6008 u32 plane_mask = 0;
6009 int vp_id = 0;
6010
6011 /*
6012 * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in
6013 * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched
6014 * between different CRTCs flexibly and the userspace do not need
6015 * the plane_mask to restrict the binding between the crtc and plane.
6016 * We just find a expected plane for logo display.
6017 */
6018 if (vop_fix_dts || is_vop3(vop2))
6019 return 0;
6020
6021 ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
6022 path = vp_node.np->full_name;
6023 plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
6024
6025 if (cstate->crtc->assign_plane)
6026 continue;
6027
6028 printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
6029 vp_id, plane_mask,
6030 vop2->vp_plane_mask[vp_id].primary_plane_id,
6031 vop2->vp_plane_mask[vp_id].cursor_plane_id);
6032
6033 do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
6034 plane_mask, 1);
6035 do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
6036 vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
6037 if (vop2->vp_plane_mask[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID)
6038 do_fixup_by_path_u32(blob, path, "cursor-win-id",
6039 vop2->vp_plane_mask[vp_id].cursor_plane_id, 1);
6040 vp_id++;
6041 }
6042
6043 vop_fix_dts = true;
6044
6045 return 0;
6046 }
6047
rockchip_vop2_check(struct display_state * state)6048 static int rockchip_vop2_check(struct display_state *state)
6049 {
6050 struct crtc_state *cstate = &state->crtc_state;
6051 struct rockchip_crtc *crtc = cstate->crtc;
6052
6053 if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) {
6054 printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id);
6055 return -ENOTSUPP;
6056 }
6057
6058 if (cstate->splice_mode) {
6059 crtc->splice_mode = true;
6060 crtc->splice_crtc_id = cstate->splice_crtc_id;
6061 }
6062
6063 return 0;
6064 }
6065
rockchip_vop2_mode_valid(struct display_state * state)6066 static int rockchip_vop2_mode_valid(struct display_state *state)
6067 {
6068 struct connector_state *conn_state = &state->conn_state;
6069 struct crtc_state *cstate = &state->crtc_state;
6070 struct drm_display_mode *mode = &conn_state->mode;
6071 struct videomode vm;
6072
6073 drm_display_mode_to_videomode(mode, &vm);
6074
6075 if (vm.hactive < 32 || vm.vactive < 32 ||
6076 (vm.hfront_porch * vm.hsync_len * vm.hback_porch *
6077 vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) {
6078 printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id);
6079 return -EINVAL;
6080 }
6081
6082 return 0;
6083 }
6084
rockchip_vop2_mode_fixup(struct display_state * state)6085 static int rockchip_vop2_mode_fixup(struct display_state *state)
6086 {
6087 struct connector_state *conn_state = &state->conn_state;
6088 struct rockchip_connector *conn = conn_state->connector;
6089 struct drm_display_mode *mode = &conn_state->mode;
6090 struct crtc_state *cstate = &state->crtc_state;
6091 struct vop2 *vop2 = cstate->private;
6092
6093 if (conn_state->secondary) {
6094 if (!(conn->dual_channel_mode &&
6095 conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) &&
6096 conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS)
6097 drm_mode_convert_to_split_mode(mode);
6098 }
6099
6100 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
6101
6102 /*
6103 * For RK3568 and RK3588, the hactive of video timing must
6104 * be 4-pixel aligned.
6105 */
6106 if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) {
6107 if (mode->crtc_hdisplay % 4) {
6108 int old_hdisplay = mode->crtc_hdisplay;
6109 int align = 4 - (mode->crtc_hdisplay % 4);
6110
6111 mode->crtc_hdisplay += align;
6112 mode->crtc_hsync_start += align;
6113 mode->crtc_hsync_end += align;
6114 mode->crtc_htotal += align;
6115
6116 printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n",
6117 old_hdisplay, mode->hdisplay);
6118 }
6119 }
6120
6121 /*
6122 * When the dsc bpp is less than 9, hdmi output will flash on TV.
6123 * It is speculated that the reason is that pixel rate of sink
6124 * decoding is not enough.
6125 * Taking 8bpp as an example, dsc clk needs to be 1/3 of the input
6126 * clk. the theoretical calculation of DEN compression 1/3, at this
6127 * time, the clk of vop dsc to hdmi tx can be reduced to about 260M
6128 * to meet the 8bpp transmission.
6129 * RK3588 dsc clk only supports 1/2 frequency division, so dsc clk
6130 * is 1/2 input clk, which needs to increase blank, which is
6131 * equivalent to compressing the absolute DEN time. TV is likely to
6132 * decode at a decoding rate of around 260M. DEN absolute time
6133 * shortening results in abnormal TV decoding.
6134 * So the value of hblank needs to be reduced when bpp is below 9.
6135 * The measurement can be displayed normally on TV, but reducing
6136 * the hblank will result in non-standard timing of the hdmi output.
6137 * This may cause compatibility issues and hdmi cts certification
6138 * may fail.
6139 */
6140 if (vop2->version == VOP_VERSION_RK3588) {
6141 if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
6142 if (cstate->dsc_sink_cap.target_bits_per_pixel_x16 < 0x90 &&
6143 cstate->dsc_enable) {
6144 u8 vrefresh = drm_mode_vrefresh(mode);
6145
6146 mode->crtc_hsync_start = mode->hdisplay + 10;
6147 mode->crtc_hsync_end = mode->crtc_hsync_start + 10;
6148 mode->crtc_htotal = mode->crtc_hsync_end + 10;
6149 mode->crtc_clock = (u32)mode->crtc_htotal * mode->crtc_vtotal *
6150 vrefresh / 1000;
6151 }
6152 }
6153 }
6154
6155 if (vop2->version == VOP_VERSION_RK3576) {
6156 /*
6157 * For RK3576 YUV420 output, hden signal introduce one cycle delay,
6158 * so we need to adjust hfp and hbp to compatible with this design.
6159 */
6160 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
6161 mode->crtc_hsync_start += 2;
6162 mode->crtc_hsync_end += 2;
6163 }
6164 /*
6165 * For RK3576 DP output, vp send 2 pixels 1 cycle. So the hactive,
6166 * hfp, hsync, hbp should be 2-pixel aligned.
6167 */
6168 if (conn_state->output_if &
6169 (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
6170 mode->crtc_hdisplay += mode->crtc_hdisplay % 2;
6171 mode->crtc_hsync_start += mode->crtc_hsync_start % 2;
6172 mode->crtc_hsync_end += mode->crtc_hsync_end % 2;
6173 mode->crtc_htotal += mode->crtc_htotal % 2;
6174 }
6175 }
6176
6177 if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656)
6178 mode->crtc_clock *= 2;
6179
6180 /*
6181 * For RK3528, the path of CVBS output is like:
6182 * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
6183 * The vop2 dclk should be four times crtc_clock for CVBS sampling
6184 * clock needs.
6185 */
6186 if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656)
6187 mode->crtc_clock *= 4;
6188
6189 mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format);
6190 if (cstate->mcu_timing.mcu_pix_total)
6191 mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1;
6192
6193 return 0;
6194 }
6195
6196 #define FRAC_16_16(mult, div) (((mult) << 16) / (div))
6197
rockchip_vop2_plane_check(struct display_state * state)6198 static int rockchip_vop2_plane_check(struct display_state *state)
6199 {
6200 struct crtc_state *cstate = &state->crtc_state;
6201 struct vop2 *vop2 = cstate->private;
6202 struct display_rect *src = &cstate->src_rect;
6203 struct display_rect *dst = &cstate->crtc_rect;
6204 struct vop2_win_data *win_data;
6205 int min_scale, max_scale;
6206 int hscale, vscale;
6207 u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
6208
6209 win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
6210 if (!win_data) {
6211 printf("ERROR: invalid win id %d\n", primary_plane_id);
6212 return -ENODEV;
6213 }
6214
6215 min_scale = FRAC_16_16(1, win_data->max_downscale_factor);
6216 max_scale = FRAC_16_16(win_data->max_upscale_factor, 1);
6217
6218 hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale);
6219 vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale);
6220 if (hscale < 0 || vscale < 0) {
6221 printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name);
6222 return -ERANGE;
6223 }
6224
6225 return 0;
6226 }
6227
rockchip_vop2_apply_soft_te(struct display_state * state)6228 static int rockchip_vop2_apply_soft_te(struct display_state *state)
6229 {
6230 __maybe_unused struct connector_state *conn_state = &state->conn_state;
6231 struct crtc_state *cstate = &state->crtc_state;
6232 struct vop2 *vop2 = cstate->private;
6233 u32 vp_offset = (cstate->crtc_id * 0x100);
6234 int val = 0;
6235 int ret = 0;
6236
6237 ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val,
6238 (val >> EDPI_WMS_FS) & 0x1, 50 * 1000);
6239 if (!ret) {
6240 #ifndef CONFIG_SPL_BUILD
6241 ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
6242 !val, 50 * 1000);
6243 if (!ret) {
6244 ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
6245 val, 50 * 1000);
6246 if (!ret) {
6247 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
6248 EN_MASK, EDPI_WMS_FS, 1, false);
6249 } else {
6250 printf("ERROR: vp%d wait for active TE signal timeout\n",
6251 cstate->crtc_id);
6252 return ret;
6253 }
6254 } else {
6255 printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id);
6256 return ret;
6257 }
6258 #endif
6259 } else {
6260 printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id);
6261 return ret;
6262 }
6263
6264 return 0;
6265 }
6266
rockchip_vop2_regs_dump(struct display_state * state)6267 static int rockchip_vop2_regs_dump(struct display_state *state)
6268 {
6269 struct crtc_state *cstate = &state->crtc_state;
6270 struct vop2 *vop2 = cstate->private;
6271 const struct vop2_data *vop2_data = vop2->data;
6272 const struct vop2_dump_regs *regs = vop2_data->dump_regs;
6273 u32 len = 128;
6274 u32 n, i, j;
6275 u32 base;
6276
6277 if (!cstate->crtc->active)
6278 return -EINVAL;
6279
6280 n = vop2_data->dump_regs_size;
6281 for (i = 0; i < n; i++) {
6282 base = regs[i].offset;
6283 len = 128;
6284 if (regs[i].size)
6285 len = min(len, regs[i].size >> 2);
6286 printf("\n%s:\n", regs[i].name);
6287 for (j = 0; j < len;) {
6288 printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
6289 vop2_readl(vop2, base + (4 * j)),
6290 vop2_readl(vop2, base + (4 * (j + 1))),
6291 vop2_readl(vop2, base + (4 * (j + 2))),
6292 vop2_readl(vop2, base + (4 * (j + 3))));
6293 j += 4;
6294 }
6295 }
6296
6297 return 0;
6298 }
6299
rockchip_vop2_active_regs_dump(struct display_state * state)6300 static int rockchip_vop2_active_regs_dump(struct display_state *state)
6301 {
6302 struct crtc_state *cstate = &state->crtc_state;
6303 struct vop2 *vop2 = cstate->private;
6304 const struct vop2_data *vop2_data = vop2->data;
6305 const struct vop2_dump_regs *regs = vop2_data->dump_regs;
6306 u32 len = 128;
6307 u32 n, i, j;
6308 u32 base;
6309 bool enable_state;
6310
6311 if (!cstate->crtc->active)
6312 return -EINVAL;
6313
6314 n = vop2_data->dump_regs_size;
6315 for (i = 0; i < n; i++) {
6316 if (regs[i].state_mask) {
6317 enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) &
6318 regs[i].state_mask;
6319 if (enable_state != regs[i].enable_state)
6320 continue;
6321 }
6322
6323 base = regs[i].offset;
6324 len = 128;
6325 if (regs[i].size)
6326 len = min(len, regs[i].size >> 2);
6327 printf("\n%s:\n", regs[i].name);
6328 for (j = 0; j < len;) {
6329 printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
6330 vop2_readl(vop2, base + (4 * j)),
6331 vop2_readl(vop2, base + (4 * (j + 1))),
6332 vop2_readl(vop2, base + (4 * (j + 2))),
6333 vop2_readl(vop2, base + (4 * (j + 3))));
6334 j += 4;
6335 }
6336 }
6337
6338 return 0;
6339 }
6340
rk3528_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6341 static void rk3528_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
6342 {
6343 struct crtc_state *cstate = &state->crtc_state;
6344 struct vop2 *vop2 = cstate->private;
6345 uint32_t dly = 0; /* For vop3, the default window delay is 0 */
6346
6347 switch (plane_phy_id) {
6348 case ROCKCHIP_VOP2_CLUSTER0:
6349 vop2_mask_write(vop2, RK3528_OVL_SYS_CLUSTER0_CTRL, CLUSTER_DLY_NUM_MASK,
6350 CLUSTER_DLY_NUM_SHIFT, dly, false);
6351 break;
6352 case ROCKCHIP_VOP2_ESMART0:
6353 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL, ESMART_DLY_NUM_MASK,
6354 ESMART_DLY_NUM_SHIFT, dly, false);
6355 break;
6356 case ROCKCHIP_VOP2_ESMART1:
6357 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART1_CTRL, ESMART_DLY_NUM_MASK,
6358 ESMART_DLY_NUM_SHIFT, dly, false);
6359 break;
6360 case ROCKCHIP_VOP2_ESMART2:
6361 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART2_CTRL, ESMART_DLY_NUM_MASK,
6362 ESMART_DLY_NUM_SHIFT, dly, false);
6363 break;
6364 case ROCKCHIP_VOP2_ESMART3:
6365 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART3_CTRL, ESMART_DLY_NUM_MASK,
6366 ESMART_DLY_NUM_SHIFT, dly, false);
6367 break;
6368 }
6369 }
6370
rk3528_setup_overlay(struct display_state * state)6371 static void rk3528_setup_overlay(struct display_state *state)
6372 {
6373 struct crtc_state *cstate = &state->crtc_state;
6374 struct vop2 *vop2 = cstate->private;
6375 struct vop2_win_data *win_data;
6376 int i;
6377 u32 offset = 0;
6378 u8 shift = 0;
6379
6380 /* init the layer sel value to 0xff(Disable layer) */
6381 for (i = 0; i < vop2->data->nr_vps; i++) {
6382 offset = 0x100 * i;
6383 vop2_writel(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 0xffffffff);
6384 }
6385
6386 /* layer sel win id */
6387 for (i = 0; i < vop2->data->nr_vps; i++) {
6388 if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6389 offset = 0x100 * i;
6390 win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6391 vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset,
6392 LAYER_SEL_MASK, 0, win_data->layer_sel_win_id[i], false);
6393 }
6394 }
6395
6396 /* win sel port */
6397 for (i = 0; i < vop2->data->nr_vps; i++) {
6398 if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6399 win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6400 shift = win_data->win_sel_port_offset * 2;
6401 vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL,
6402 LAYER_SEL_PORT_MASK, shift, i, false);
6403 }
6404 }
6405 }
6406
rk3568_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6407 static void rk3568_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
6408 {
6409 struct crtc_state *cstate = &state->crtc_state;
6410 struct vop2 *vop2 = cstate->private;
6411 struct vop2_win_data *win_data;
6412 uint32_t dly;
6413
6414 win_data = vop2_find_win_by_phys_id(vop2, plane_phy_id);
6415 dly = win_data->dly[VOP2_DLY_MODE_DEFAULT];
6416 if (win_data->type == CLUSTER_LAYER)
6417 dly |= dly << 8;
6418
6419 switch (plane_phy_id) {
6420 case ROCKCHIP_VOP2_CLUSTER0:
6421 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
6422 CLUSTER0_DLY_NUM_SHIFT, dly, false);
6423 break;
6424 case ROCKCHIP_VOP2_CLUSTER1:
6425 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
6426 CLUSTER1_DLY_NUM_SHIFT, dly, false);
6427 break;
6428 case ROCKCHIP_VOP2_CLUSTER2:
6429 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
6430 CLUSTER0_DLY_NUM_SHIFT, dly, false);
6431 break;
6432 case ROCKCHIP_VOP2_CLUSTER3:
6433 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
6434 CLUSTER1_DLY_NUM_SHIFT, dly, false);
6435 break;
6436 case ROCKCHIP_VOP2_ESMART0:
6437 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
6438 ESMART0_DLY_NUM_SHIFT, dly, false);
6439 break;
6440 case ROCKCHIP_VOP2_ESMART1:
6441 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
6442 ESMART1_DLY_NUM_SHIFT, dly, false);
6443 break;
6444 case ROCKCHIP_VOP2_SMART0:
6445 case ROCKCHIP_VOP2_ESMART2:
6446 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
6447 SMART0_DLY_NUM_SHIFT, dly, false);
6448 break;
6449 case ROCKCHIP_VOP2_SMART1:
6450 case ROCKCHIP_VOP2_ESMART3:
6451 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
6452 SMART1_DLY_NUM_SHIFT, dly, false);
6453 break;
6454 }
6455 }
6456
rk3568_setup_overlay(struct display_state * state)6457 static void rk3568_setup_overlay(struct display_state *state)
6458 {
6459 struct crtc_state *cstate = &state->crtc_state;
6460 struct vop2 *vop2 = cstate->private;
6461 struct vop2_win_data *win_data;
6462 int layer_phy_id = 0;
6463 int total_used_layer = 0;
6464 int port_mux = 0;
6465 int i, j;
6466 u32 layer_nr = 0;
6467 u8 shift = 0;
6468
6469 /* layer sel win id */
6470 for (i = 0; i < vop2->data->nr_vps; i++) {
6471 layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6472 for (j = 0; j < layer_nr; j++) {
6473 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6474 win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6475 vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
6476 shift, win_data->layer_sel_win_id[i], false);
6477 shift += 4;
6478 }
6479 }
6480
6481 /* win sel port */
6482 for (i = 0; i < vop2->data->nr_vps; i++) {
6483 layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6484 for (j = 0; j < layer_nr; j++) {
6485 if (!vop2->vp_plane_mask[i].attached_layers[j])
6486 continue;
6487 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6488 win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6489 shift = win_data->win_sel_port_offset * 2;
6490 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
6491 LAYER_SEL_PORT_SHIFT + shift, i, false);
6492 }
6493 }
6494
6495 /**
6496 * port mux config
6497 */
6498 for (i = 0; i < vop2->data->nr_vps; i++) {
6499 shift = i * 4;
6500 if (vop2->vp_plane_mask[i].attached_layers_nr) {
6501 total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
6502 port_mux = total_used_layer - 1;
6503 } else {
6504 port_mux = 8;
6505 }
6506
6507 if (i == vop2->data->nr_vps - 1)
6508 port_mux = vop2->data->nr_mixers;
6509
6510 cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
6511 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
6512 PORT_MUX_SHIFT + shift, port_mux, false);
6513 }
6514 }
6515
rk3576_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6516 static void rk3576_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
6517 {
6518 struct crtc_state *cstate = &state->crtc_state;
6519 struct vop2 *vop2 = cstate->private;
6520 uint32_t dly = 0; /* For vop3, the default window delay is 0 */
6521
6522 switch (plane_phy_id) {
6523 case ROCKCHIP_VOP2_CLUSTER0:
6524 vop2_mask_write(vop2, RK3576_CLUSTER0_DLY_NUM, CLUSTER_DLY_NUM_MASK,
6525 CLUSTER_DLY_NUM_SHIFT, dly, false);
6526 break;
6527 case ROCKCHIP_VOP2_CLUSTER1:
6528 vop2_mask_write(vop2, RK3576_CLUSTER1_DLY_NUM, CLUSTER_DLY_NUM_MASK,
6529 CLUSTER_DLY_NUM_SHIFT, dly, false);
6530 break;
6531 case ROCKCHIP_VOP2_ESMART0:
6532 vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM, ESMART_DLY_NUM_MASK,
6533 ESMART_DLY_NUM_SHIFT, dly, false);
6534 break;
6535 case ROCKCHIP_VOP2_ESMART1:
6536 vop2_mask_write(vop2, RK3576_ESMART1_DLY_NUM, ESMART_DLY_NUM_MASK,
6537 ESMART_DLY_NUM_SHIFT, dly, false);
6538 break;
6539 case ROCKCHIP_VOP2_ESMART2:
6540 vop2_mask_write(vop2, RK3576_ESMART2_DLY_NUM, ESMART_DLY_NUM_MASK,
6541 ESMART_DLY_NUM_SHIFT, dly, false);
6542 break;
6543 case ROCKCHIP_VOP2_ESMART3:
6544 vop2_mask_write(vop2, RK3576_ESMART3_DLY_NUM, ESMART_DLY_NUM_MASK,
6545 ESMART_DLY_NUM_SHIFT, dly, false);
6546 break;
6547 }
6548 }
6549
rk3576_setup_overlay(struct display_state * state)6550 static void rk3576_setup_overlay(struct display_state *state)
6551 {
6552 struct crtc_state *cstate = &state->crtc_state;
6553 struct vop2 *vop2 = cstate->private;
6554 struct vop2_win_data *win_data;
6555 int i;
6556 u32 offset = 0;
6557
6558 /* layer sel win id */
6559 for (i = 0; i < vop2->data->nr_vps; i++) {
6560 if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6561 offset = 0x100 * i;
6562 win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6563 vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, LAYER_SEL_MASK,
6564 0, win_data->layer_sel_win_id[i], false);
6565 }
6566 }
6567 }
6568
6569 #ifdef CONFIG_MOS_SECONDARY
vop2_cluster_disable(void * regs,u32 offset)6570 static void vop2_cluster_disable(void *regs, u32 offset)
6571 {
6572 writel(0x0, regs + RK3568_CLUSTER0_WIN0_CTRL0 + offset);
6573 writel(0x0, regs + RK3568_CLUSTER0_WIN1_CTRL0 + offset);
6574 writel(0x0, regs + RK3568_CLUSTER0_CTRL + offset);
6575 }
6576
vop2_esmart_disable(void * regs,u32 offset)6577 static void vop2_esmart_disable(void *regs, u32 offset)
6578 {
6579 writel(0x0, regs + RK3568_ESMART0_REGION0_CTRL + offset);
6580 writel(0x0, regs + RK3568_ESMART0_REGION1_CTRL + offset);
6581 writel(0x0, regs + RK3568_ESMART0_REGION2_CTRL + offset);
6582 writel(0x0, regs + RK3568_ESMART0_REGION3_CTRL + offset);
6583 }
6584
vop2_vp_irqs_disable(void * regs,u32 vp_id)6585 static void vop2_vp_irqs_disable(void *regs, u32 vp_id)
6586 {
6587 u32 offset = 0x10 * vp_id;
6588
6589 writel(0xffff0000, regs + RK3568_VP0_INT_EN + offset);
6590 writel(0xffffffff, regs + RK3568_VP0_INT_CLR + offset);
6591 }
6592
vop2_axi_irqs_disable(void * regs,u32 axi_id)6593 static void vop2_axi_irqs_disable(void *regs, u32 axi_id)
6594 {
6595 u32 offset = 0x10 * axi_id;
6596
6597 writel(0xffff0000, regs + RK3568_VP0_INT_EN + offset);
6598 writel(0xffffffff, regs + RK3568_VP0_INT_CLR + offset);
6599 }
6600
vop2_vp_in_standby(void * regs,u32 vp_id)6601 static bool vop2_vp_in_standby(void *regs, u32 vp_id)
6602 {
6603 u32 offset = vp_id * 0x100;
6604
6605 return !!(readl(regs + RK3568_VP0_DSP_CTRL + offset) & BIT(STANDBY_EN_SHIFT));
6606 }
6607
vop2_vp_standby(void * regs,u32 vp_id)6608 static void vop2_vp_standby(void *regs, u32 vp_id)
6609 {
6610 u32 offset = vp_id * 0x100;
6611
6612 writel(BIT(STANDBY_EN_SHIFT), regs + RK3568_VP0_DSP_CTRL + offset);
6613 }
6614
vop2_vp_config_done(void * regs,u32 vp_id)6615 static void vop2_vp_config_done(void *regs, u32 vp_id)
6616 {
6617 u32 cfg_done = CFG_DONE_EN | BIT(vp_id) | (BIT(vp_id) << 16);
6618 u32 offset = vp_id * 0x100;
6619
6620 writel(cfg_done, regs + RK3568_REG_CFG_DONE + offset);
6621 }
6622
vop2_iommu_disable(void * regs,u32 axi_id)6623 static void vop2_iommu_disable(void *regs, u32 axi_id)
6624 {
6625 u32 val = readl(regs + RK3568_IOMMU0_STATUS);
6626 bool pagefault = val & MMU_PAGE_FAULT_ACTIVE;
6627 u32 offset = axi_id * 0x100;
6628
6629 writel(MMU_DISABLE_PAGING, regs + RK3568_IOMMU0_COMMAND + offset);
6630
6631 if (pagefault) {
6632 printf("iommu%d status:0x%x, pagefault addr: 0x%x\n",
6633 axi_id, val, readl(regs + RK3568_IOMMU0_PAGEFAULT_ADDR + offset));
6634 writel(MMU_FORCE_RESET, regs + RK3568_IOMMU0_COMMAND + offset);
6635 }
6636 }
6637
rockchip_vop2_reset(struct udevice * dev,u32 axi,u32 vp_mask,u32 plane_mask)6638 static int rockchip_vop2_reset(struct udevice *dev, u32 axi, u32 vp_mask, u32 plane_mask)
6639 {
6640 void *regs = dev_read_addr_ptr(dev);
6641 struct rockchip_crtc *crtc = (struct rockchip_crtc *)dev_get_driver_data(dev);
6642 const struct vop2_data *vop2_data = crtc->data;
6643 u32 enabled_vp_mask = 0;
6644 int i = 0;
6645
6646 for (i = 0; i < vop2_data->nr_vps; i++) {
6647 if (BIT(i) & vp_mask) {
6648 if (!vop2_vp_in_standby(regs,i)) {
6649 enabled_vp_mask |= BIT(i);
6650 }
6651 }
6652 }
6653
6654 if (enabled_vp_mask == 0)
6655 return 0;
6656
6657 for (i = 0; i < vop2_data->nr_layers; i++) {
6658 if (BIT(vop2_data->win_data[i].phys_id) & plane_mask) {
6659 if (vop2_data->win_data[i].type == CLUSTER_LAYER)
6660 vop2_cluster_disable(regs, vop2_data->win_data[i].reg_offset);
6661 else
6662 vop2_esmart_disable(regs, vop2_data->win_data[i].reg_offset);
6663 }
6664 }
6665
6666 for (i = 0; i < vop2_data->nr_vps; i++) {
6667 if (BIT(i) & vp_mask)
6668 vop2_vp_config_done(regs, i);
6669 }
6670 mdelay(50);
6671 vop2_iommu_disable(regs, axi);
6672 vop2_axi_irqs_disable(regs, axi);
6673
6674 for (i = 0; i < vop2_data->nr_vps; i++) {
6675 if (BIT(i) & vp_mask) {
6676 vop2_vp_irqs_disable(regs, i);
6677 vop2_vp_standby(regs, i);
6678 }
6679 }
6680 printf("Reset vop success\n");
6681
6682 return 0;
6683 }
6684 #else
rockchip_vop2_reset(struct udevice * dev,u32 axi,u32 vp_mask,u32 plane_mask)6685 static int rockchip_vop2_reset(struct udevice *dev, u32 axi, u32 vp_mask, u32 plane_mask)
6686 {
6687 return 0;
6688 }
6689 #endif
6690
6691 static struct vop2_dump_regs rk3528_dump_regs[] = {
6692 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
6693 { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
6694 { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
6695 { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
6696 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
6697 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
6698 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
6699 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
6700 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
6701 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
6702 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
6703 { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
6704 { RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1},
6705 };
6706
6707 #define RK3528_PLANE_MASK_BASE \
6708 (BIT(ROCKCHIP_VOP2_CLUSTER0) | \
6709 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
6710 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
6711
6712 static struct vop2_win_data rk3528_win_data[5] = {
6713 {
6714 .name = "Esmart0",
6715 .phys_id = ROCKCHIP_VOP2_ESMART0,
6716 .type = ESMART_LAYER,
6717 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
6718 .win_sel_port_offset = 8,
6719 .layer_sel_win_id = { 1, 0xff, 0xff, 0xff },
6720 .reg_offset = 0,
6721 .axi_id = 0,
6722 .axi_yrgb_id = 0x06,
6723 .axi_uv_id = 0x07,
6724 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6725 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6726 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6727 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6728 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
6729 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
6730 .possible_vp_mask = BIT(VOP2_VP0),
6731 .max_upscale_factor = 8,
6732 .max_downscale_factor = 8,
6733 },
6734
6735 {
6736 .name = "Esmart1",
6737 .phys_id = ROCKCHIP_VOP2_ESMART1,
6738 .type = ESMART_LAYER,
6739 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
6740 .win_sel_port_offset = 10,
6741 .layer_sel_win_id = { 2, 0xff, 0xff, 0xff },
6742 .reg_offset = 0x200,
6743 .axi_id = 0,
6744 .axi_yrgb_id = 0x08,
6745 .axi_uv_id = 0x09,
6746 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6747 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6748 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6749 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6750 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
6751 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
6752 .possible_vp_mask = BIT(VOP2_VP0),
6753 .max_upscale_factor = 8,
6754 .max_downscale_factor = 8,
6755 },
6756
6757 {
6758 .name = "Esmart2",
6759 .phys_id = ROCKCHIP_VOP2_ESMART2,
6760 .type = ESMART_LAYER,
6761 .plane_type = VOP2_PLANE_TYPE_CURSOR,
6762 .win_sel_port_offset = 12,
6763 .layer_sel_win_id = { 3, 0, 0xff, 0xff },
6764 .reg_offset = 0x400,
6765 .axi_id = 0,
6766 .axi_yrgb_id = 0x0a,
6767 .axi_uv_id = 0x0b,
6768 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6769 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6770 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6771 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6772 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
6773 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
6774 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
6775 .max_upscale_factor = 8,
6776 .max_downscale_factor = 8,
6777 },
6778
6779 {
6780 .name = "Esmart3",
6781 .phys_id = ROCKCHIP_VOP2_ESMART3,
6782 .type = ESMART_LAYER,
6783 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
6784 .win_sel_port_offset = 14,
6785 .layer_sel_win_id = { 0xff, 1, 0xff, 0xff },
6786 .reg_offset = 0x600,
6787 .axi_id = 0,
6788 .axi_yrgb_id = 0x0c,
6789 .axi_uv_id = 0x0d,
6790 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6791 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6792 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6793 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6794 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
6795 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
6796 .possible_vp_mask = BIT(VOP2_VP1),
6797 .max_upscale_factor = 8,
6798 .max_downscale_factor = 8,
6799 },
6800
6801 {
6802 .name = "Cluster0",
6803 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
6804 .type = CLUSTER_LAYER,
6805 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
6806 .win_sel_port_offset = 0,
6807 .layer_sel_win_id = { 0, 0xff, 0xff, 0xff },
6808 .reg_offset = 0,
6809 .axi_id = 0,
6810 .axi_yrgb_id = 0x02,
6811 .axi_uv_id = 0x03,
6812 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6813 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6814 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6815 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6816 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
6817 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
6818 .possible_vp_mask = BIT(VOP2_VP0),
6819 .max_upscale_factor = 8,
6820 .max_downscale_factor = 8,
6821 },
6822 };
6823
6824 static struct vop2_vp_data rk3528_vp_data[2] = {
6825 {
6826 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM |
6827 VOP_FEATURE_POST_CSC,
6828 .max_output = {4096, 4096},
6829 .layer_mix_dly = 6,
6830 .hdr_mix_dly = 2,
6831 .win_dly = 8,
6832 },
6833 {
6834 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6835 .max_output = {1920, 1080},
6836 .layer_mix_dly = 2,
6837 .hdr_mix_dly = 0,
6838 .win_dly = 8,
6839 },
6840 };
6841
6842 static const struct vop2_ops rk3528_vop_ops = {
6843 .setup_win_dly = rk3528_setup_win_dly,
6844 .setup_overlay = rk3528_setup_overlay,
6845 .assign_plane_mask = rk3528_assign_plane_mask,
6846 };
6847
6848 const struct vop2_data rk3528_vop = {
6849 .version = VOP_VERSION_RK3528,
6850 .nr_vps = 2,
6851 .vp_data = rk3528_vp_data,
6852 .win_data = rk3528_win_data,
6853 .plane_mask_base = RK3528_PLANE_MASK_BASE,
6854 .nr_layers = 5,
6855 .nr_mixers = 3,
6856 .nr_gammas = 2,
6857 .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE,
6858 .dump_regs = rk3528_dump_regs,
6859 .dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
6860 .ops = &rk3528_vop_ops,
6861
6862 };
6863
6864 static struct vop2_dump_regs rk3562_dump_regs[] = {
6865 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
6866 { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
6867 { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
6868 { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
6869 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
6870 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
6871 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
6872 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
6873 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
6874 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
6875 };
6876
6877 #define RK3562_PLANE_MASK_BASE \
6878 (BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
6879 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
6880
6881 static struct vop2_win_data rk3562_win_data[4] = {
6882 {
6883 .name = "Esmart0",
6884 .phys_id = ROCKCHIP_VOP2_ESMART0,
6885 .type = ESMART_LAYER,
6886 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
6887 .win_sel_port_offset = 8,
6888 .layer_sel_win_id = { 0, 0, 0xff, 0xff },
6889 .reg_offset = 0,
6890 .axi_id = 0,
6891 .axi_yrgb_id = 0x02,
6892 .axi_uv_id = 0x03,
6893 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6894 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6895 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6896 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6897 .possible_vp_mask = BIT(VOP2_VP0),
6898 .max_upscale_factor = 8,
6899 .max_downscale_factor = 8,
6900 },
6901
6902 {
6903 .name = "Esmart1",
6904 .phys_id = ROCKCHIP_VOP2_ESMART1,
6905 .type = ESMART_LAYER,
6906 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
6907 .win_sel_port_offset = 10,
6908 .layer_sel_win_id = { 1, 1, 0xff, 0xff },
6909 .reg_offset = 0x200,
6910 .axi_id = 0,
6911 .axi_yrgb_id = 0x04,
6912 .axi_uv_id = 0x05,
6913 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6914 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6915 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6916 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6917 .possible_vp_mask = BIT(VOP2_VP0),
6918 .max_upscale_factor = 8,
6919 .max_downscale_factor = 8,
6920 },
6921
6922 {
6923 .name = "Esmart2",
6924 .phys_id = ROCKCHIP_VOP2_ESMART2,
6925 .type = ESMART_LAYER,
6926 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
6927 .win_sel_port_offset = 12,
6928 .layer_sel_win_id = { 2, 2, 0xff, 0xff },
6929 .reg_offset = 0x400,
6930 .axi_id = 0,
6931 .axi_yrgb_id = 0x06,
6932 .axi_uv_id = 0x07,
6933 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6934 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6935 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6936 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6937 .possible_vp_mask = BIT(VOP2_VP0),
6938 .max_upscale_factor = 8,
6939 .max_downscale_factor = 8,
6940 },
6941
6942 {
6943 .name = "Esmart3",
6944 .phys_id = ROCKCHIP_VOP2_ESMART3,
6945 .type = ESMART_LAYER,
6946 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
6947 .win_sel_port_offset = 14,
6948 .layer_sel_win_id = { 3, 3, 0xff, 0xff },
6949 .reg_offset = 0x600,
6950 .axi_id = 0,
6951 .axi_yrgb_id = 0x08,
6952 .axi_uv_id = 0x0d,
6953 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6954 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6955 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6956 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6957 .possible_vp_mask = BIT(VOP2_VP0),
6958 .max_upscale_factor = 8,
6959 .max_downscale_factor = 8,
6960 },
6961 };
6962
6963 static struct vop2_vp_data rk3562_vp_data[2] = {
6964 {
6965 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6966 .max_output = {2048, 4096},
6967 .win_dly = 6,
6968 .layer_mix_dly = 8,
6969 },
6970 {
6971 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6972 .max_output = {2048, 1080},
6973 .win_dly = 8,
6974 .layer_mix_dly = 8,
6975 },
6976 };
6977
6978 static const struct vop2_ops rk3562_vop_ops = {
6979 .setup_win_dly = rk3528_setup_win_dly,
6980 .setup_overlay = rk3528_setup_overlay,
6981 .assign_plane_mask = rk3528_assign_plane_mask,
6982 };
6983
6984 const struct vop2_data rk3562_vop = {
6985 .version = VOP_VERSION_RK3562,
6986 .nr_vps = 2,
6987 .vp_data = rk3562_vp_data,
6988 .win_data = rk3562_win_data,
6989 .plane_mask_base = RK3562_PLANE_MASK_BASE,
6990 .nr_layers = 4,
6991 .nr_mixers = 3,
6992 .nr_gammas = 2,
6993 .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE,
6994 .dump_regs = rk3562_dump_regs,
6995 .dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
6996 .ops = &rk3562_vop_ops,
6997 };
6998
6999 static struct vop2_dump_regs rk3568_dump_regs[] = {
7000 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
7001 { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
7002 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
7003 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
7004 { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
7005 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
7006 { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
7007 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
7008 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
7009 { RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
7010 { RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
7011 { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
7012 };
7013
7014 static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
7015 { /* one display policy */
7016 {/* main display */
7017 .primary_plane_id = ROCKCHIP_VOP2_SMART0,
7018 .attached_layers_nr = 6,
7019 .attached_layers = {
7020 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
7021 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
7022 },
7023 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7024 },
7025 {/* second display */},
7026 {/* third display */},
7027 {/* fourth display */},
7028 },
7029
7030 { /* two display policy */
7031 {/* main display */
7032 .primary_plane_id = ROCKCHIP_VOP2_SMART0,
7033 .attached_layers_nr = 3,
7034 .attached_layers = {
7035 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
7036 },
7037 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7038 },
7039
7040 {/* second display */
7041 .primary_plane_id = ROCKCHIP_VOP2_SMART1,
7042 .attached_layers_nr = 3,
7043 .attached_layers = {
7044 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
7045 },
7046 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7047 },
7048 {/* third display */},
7049 {/* fourth display */},
7050 },
7051
7052 { /* three display policy */
7053 {/* main display */
7054 .primary_plane_id = ROCKCHIP_VOP2_SMART0,
7055 .attached_layers_nr = 3,
7056 .attached_layers = {
7057 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
7058 },
7059 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7060 },
7061
7062 {/* second display */
7063 .primary_plane_id = ROCKCHIP_VOP2_SMART1,
7064 .attached_layers_nr = 2,
7065 .attached_layers = {
7066 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
7067 },
7068 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7069 },
7070
7071 {/* third display */
7072 .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7073 .attached_layers_nr = 1,
7074 .attached_layers = { ROCKCHIP_VOP2_ESMART1 },
7075 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7076 },
7077
7078 {/* fourth display */},
7079 },
7080
7081 {/* reserved for four display policy */},
7082 };
7083
7084 #define RK3568_PLANE_MASK_BASE \
7085 (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
7086 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
7087 BIT(ROCKCHIP_VOP2_SMART0) | BIT(ROCKCHIP_VOP2_SMART1))
7088
7089 static struct vop2_win_data rk3568_win_data[6] = {
7090 {
7091 .name = "Cluster0",
7092 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
7093 .type = CLUSTER_LAYER,
7094 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7095 .win_sel_port_offset = 0,
7096 .layer_sel_win_id = { 0, 0, 0, 0xff },
7097 .reg_offset = 0,
7098 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7099 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7100 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7101 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7102 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
7103 .max_upscale_factor = 4,
7104 .max_downscale_factor = 4,
7105 .dly = { 0, 27, 21 },
7106 },
7107
7108 {
7109 .name = "Cluster1",
7110 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
7111 .type = CLUSTER_LAYER,
7112 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7113 .win_sel_port_offset = 1,
7114 .layer_sel_win_id = { 1, 1, 1, 0xff },
7115 .reg_offset = 0x200,
7116 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7117 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7118 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7119 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7120 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
7121 .max_upscale_factor = 4,
7122 .max_downscale_factor = 4,
7123 .source_win_id = ROCKCHIP_VOP2_CLUSTER0,
7124 .feature = WIN_FEATURE_MIRROR,
7125 .dly = { 0, 27, 21 },
7126 },
7127
7128 {
7129 .name = "Esmart0",
7130 .phys_id = ROCKCHIP_VOP2_ESMART0,
7131 .type = ESMART_LAYER,
7132 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7133 .win_sel_port_offset = 4,
7134 .layer_sel_win_id = { 2, 2, 2, 0xff },
7135 .reg_offset = 0,
7136 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7137 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7138 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7139 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7140 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
7141 .max_upscale_factor = 8,
7142 .max_downscale_factor = 8,
7143 .dly = { 20, 47, 41 },
7144 },
7145
7146 {
7147 .name = "Esmart1",
7148 .phys_id = ROCKCHIP_VOP2_ESMART1,
7149 .type = ESMART_LAYER,
7150 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7151 .win_sel_port_offset = 5,
7152 .layer_sel_win_id = { 6, 6, 6, 0xff },
7153 .reg_offset = 0x200,
7154 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7155 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7156 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7157 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7158 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
7159 .max_upscale_factor = 8,
7160 .max_downscale_factor = 8,
7161 .dly = { 20, 47, 41 },
7162 .source_win_id = ROCKCHIP_VOP2_ESMART0,
7163 .feature = WIN_FEATURE_MIRROR,
7164 },
7165
7166 {
7167 .name = "Smart0",
7168 .phys_id = ROCKCHIP_VOP2_SMART0,
7169 .type = SMART_LAYER,
7170 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7171 .win_sel_port_offset = 6,
7172 .layer_sel_win_id = { 3, 3, 3, 0xff },
7173 .reg_offset = 0x400,
7174 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7175 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7176 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7177 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7178 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
7179 .max_upscale_factor = 8,
7180 .max_downscale_factor = 8,
7181 .dly = { 20, 47, 41 },
7182 },
7183
7184 {
7185 .name = "Smart1",
7186 .phys_id = ROCKCHIP_VOP2_SMART1,
7187 .type = SMART_LAYER,
7188 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7189 .win_sel_port_offset = 7,
7190 .layer_sel_win_id = { 7, 7, 7, 0xff },
7191 .reg_offset = 0x600,
7192 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7193 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7194 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7195 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7196 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
7197 .max_upscale_factor = 8,
7198 .max_downscale_factor = 8,
7199 .dly = { 20, 47, 41 },
7200 .source_win_id = ROCKCHIP_VOP2_SMART0,
7201 .feature = WIN_FEATURE_MIRROR,
7202 },
7203 };
7204
7205 static struct vop2_vp_data rk3568_vp_data[3] = {
7206 {
7207 .feature = VOP_FEATURE_OUTPUT_10BIT,
7208 .pre_scan_max_dly = 42,
7209 .max_output = {4096, 2304},
7210 },
7211 {
7212 .feature = 0,
7213 .pre_scan_max_dly = 40,
7214 .max_output = {2048, 1536},
7215 },
7216 {
7217 .feature = 0,
7218 .pre_scan_max_dly = 40,
7219 .max_output = {1920, 1080},
7220 },
7221 };
7222
7223 static const struct vop2_ops rk3568_vop_ops = {
7224 .setup_win_dly = rk3568_setup_win_dly,
7225 .setup_overlay = rk3568_setup_overlay,
7226 .assign_plane_mask = rk3568_assign_plane_mask,
7227 };
7228
7229 const struct vop2_data rk3568_vop = {
7230 .version = VOP_VERSION_RK3568,
7231 .nr_vps = 3,
7232 .vp_data = rk3568_vp_data,
7233 .win_data = rk3568_win_data,
7234 .plane_mask = rk356x_vp_plane_mask[0],
7235 .plane_mask_base = RK3568_PLANE_MASK_BASE,
7236 .nr_layers = 6,
7237 .nr_mixers = 5,
7238 .nr_gammas = 1,
7239 .dump_regs = rk3568_dump_regs,
7240 .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs),
7241 .ops = &rk3568_vop_ops,
7242 };
7243
7244 #define RK3576_PLANE_MASK_BASE \
7245 (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
7246 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
7247 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
7248
7249 static struct vop2_dump_regs rk3576_dump_regs[] = {
7250 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 },
7251 { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 },
7252 { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 },
7253 { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 },
7254 { RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 },
7255 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7256 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7257 { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7258 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
7259 { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
7260 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 },
7261 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 },
7262 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 },
7263 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 },
7264 { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 },
7265 };
7266
7267 /*
7268 * RK3576 VOP with 2 Cluster win and 4 Esmart win.
7269 * Every Esmart win support 4 multi-region.
7270 * VP0 can use Cluster0/1 and Esmart0/2
7271 * VP1 can use Cluster0/1 and Esmart1/3
7272 * VP2 can use Esmart0/1/2/3
7273 *
7274 * Scale filter mode:
7275 *
7276 * * Cluster:
7277 * * Support prescale down:
7278 * * H/V: gt2/avg2 or gt4/avg4
7279 * * After prescale down:
7280 * * nearest-neighbor/bilinear/multi-phase filter for scale up
7281 * * nearest-neighbor/bilinear/multi-phase filter for scale down
7282 *
7283 * * Esmart:
7284 * * Support prescale down:
7285 * * H: gt2/avg2 or gt4/avg4
7286 * * V: gt2 or gt4
7287 * * After prescale down:
7288 * * nearest-neighbor/bilinear/bicubic for scale up
7289 * * nearest-neighbor/bilinear for scale down
7290 *
7291 * AXI config::
7292 *
7293 * * Cluster0 win0: 0xa, 0xb [AXI0]
7294 * * Cluster0 win1: 0xc, 0xd [AXI0]
7295 * * Cluster1 win0: 0x6, 0x7 [AXI0]
7296 * * Cluster1 win1: 0x8, 0x9 [AXI0]
7297 * * Esmart0: 0x10, 0x11 [AXI0]
7298 * * Esmart1: 0x12, 0x13 [AXI0]
7299 * * Esmart2: 0xa, 0xb [AXI1]
7300 * * Esmart3: 0xc, 0xd [AXI1]
7301 * * Lut dma rid: 0x1, 0x2, 0x3 [AXI0]
7302 * * DCI dma rid: 0x4 [AXI0]
7303 * * Metadata rid: 0x5 [AXI0]
7304 *
7305 * * Limit:
7306 * * (1) 0x0 and 0xf can't be used;
7307 * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf,
7308 * * VOP will dead at the system bandwidth very terrible scene.
7309 */
7310 static struct vop2_win_data rk3576_win_data[6] = {
7311 {
7312 .name = "Esmart0",
7313 .phys_id = ROCKCHIP_VOP2_ESMART0,
7314 .type = ESMART_LAYER,
7315 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7316 .layer_sel_win_id = { 2, 0xff, 0, 0xff },
7317 .reg_offset = 0x0,
7318 .supported_rotations = DRM_MODE_REFLECT_Y,
7319 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7320 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7321 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7322 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7323 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7324 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7325 .pd_id = VOP2_PD_ESMART,
7326 .axi_id = 0,
7327 .axi_yrgb_id = 0x10,
7328 .axi_uv_id = 0x11,
7329 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
7330 .max_upscale_factor = 8,
7331 .max_downscale_factor = 8,
7332 .feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH,
7333 },
7334 {
7335 .name = "Esmart1",
7336 .phys_id = ROCKCHIP_VOP2_ESMART1,
7337 .type = ESMART_LAYER,
7338 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7339 .layer_sel_win_id = { 0xff, 2, 1, 0xff },
7340 .reg_offset = 0x200,
7341 .supported_rotations = DRM_MODE_REFLECT_Y,
7342 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7343 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7344 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7345 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7346 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7347 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7348 .pd_id = VOP2_PD_ESMART,
7349 .axi_id = 0,
7350 .axi_yrgb_id = 0x12,
7351 .axi_uv_id = 0x13,
7352 .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
7353 .max_upscale_factor = 8,
7354 .max_downscale_factor = 8,
7355 .feature = WIN_FEATURE_MULTI_AREA,
7356 },
7357
7358 {
7359 .name = "Esmart2",
7360 .phys_id = ROCKCHIP_VOP2_ESMART2,
7361 .type = ESMART_LAYER,
7362 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7363 .layer_sel_win_id = { 3, 0xff, 2, 0xff },
7364 .reg_offset = 0x400,
7365 .supported_rotations = DRM_MODE_REFLECT_Y,
7366 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7367 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7368 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7369 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7370 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7371 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7372 .pd_id = VOP2_PD_ESMART,
7373 .axi_id = 1,
7374 .axi_yrgb_id = 0x0a,
7375 .axi_uv_id = 0x0b,
7376 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
7377 .max_upscale_factor = 8,
7378 .max_downscale_factor = 8,
7379 .feature = WIN_FEATURE_MULTI_AREA,
7380 },
7381
7382 {
7383 .name = "Esmart3",
7384 .phys_id = ROCKCHIP_VOP2_ESMART3,
7385 .type = ESMART_LAYER,
7386 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7387 .layer_sel_win_id = { 0xff, 3, 3, 0xff },
7388 .reg_offset = 0x600,
7389 .supported_rotations = DRM_MODE_REFLECT_Y,
7390 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7391 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7392 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7393 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7394 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7395 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7396 .pd_id = VOP2_PD_ESMART,
7397 .axi_id = 1,
7398 .axi_yrgb_id = 0x0c,
7399 .axi_uv_id = 0x0d,
7400 .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
7401 .max_upscale_factor = 8,
7402 .max_downscale_factor = 8,
7403 .feature = WIN_FEATURE_MULTI_AREA,
7404 },
7405
7406 {
7407 .name = "Cluster0",
7408 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
7409 .type = CLUSTER_LAYER,
7410 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7411 .layer_sel_win_id = { 0, 0, 0xff, 0xff },
7412 .reg_offset = 0x0,
7413 .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
7414 .hsu_filter_mode = VOP2_SCALE_UP_BIL,
7415 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7416 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7417 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7418 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7419 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7420 .pd_id = VOP2_PD_CLUSTER,
7421 .axi_yrgb_id = 0x0a,
7422 .axi_uv_id = 0x0b,
7423 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
7424 .max_upscale_factor = 8,
7425 .max_downscale_factor = 8,
7426 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
7427 WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI,
7428 },
7429
7430 {
7431 .name = "Cluster1",
7432 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
7433 .type = CLUSTER_LAYER,
7434 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7435 .layer_sel_win_id = { 1, 1, 0xff, 0xff },
7436 .reg_offset = 0x200,
7437 .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
7438 .hsu_filter_mode = VOP2_SCALE_UP_BIL,
7439 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7440 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7441 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7442 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7443 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7444 .pd_id = VOP2_PD_CLUSTER,
7445 .axi_yrgb_id = 0x06,
7446 .axi_uv_id = 0x07,
7447 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
7448 .max_upscale_factor = 8,
7449 .max_downscale_factor = 8,
7450 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
7451 WIN_FEATURE_Y2R_13BIT_DEPTH,
7452 },
7453 };
7454
7455 /*
7456 * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4,
7457 * the urgency signal will be set to 1, when full post line buffer is over 6, the
7458 * urgency signal will be set to 0.
7459 */
7460 static struct vop_urgency rk3576_vp0_urgency = {
7461 .urgen_thl = 4,
7462 .urgen_thh = 6,
7463 };
7464
7465 static struct vop2_vp_data rk3576_vp_data[3] = {
7466 {
7467 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR |
7468 VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT |
7469 VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP,
7470 .max_output = { 4096, 4096 },
7471 .hdrvivid_dly = 21,
7472 .sdr2hdr_dly = 21,
7473 .layer_mix_dly = 8,
7474 .hdr_mix_dly = 2,
7475 .win_dly = 10,
7476 .pixel_rate = 2,
7477 .urgency = &rk3576_vp0_urgency,
7478 },
7479 {
7480 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN |
7481 VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2,
7482 .max_output = { 2560, 2560 },
7483 .hdrvivid_dly = 0,
7484 .sdr2hdr_dly = 0,
7485 .layer_mix_dly = 6,
7486 .hdr_mix_dly = 0,
7487 .win_dly = 10,
7488 .pixel_rate = 1,
7489 },
7490 {
7491 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
7492 .max_output = { 1920, 1920 },
7493 .hdrvivid_dly = 0,
7494 .sdr2hdr_dly = 0,
7495 .layer_mix_dly = 6,
7496 .hdr_mix_dly = 0,
7497 .win_dly = 10,
7498 .pixel_rate = 1,
7499 },
7500 };
7501
7502 static struct vop2_power_domain_data rk3576_vop_pd_data[] = {
7503 {
7504 .id = VOP2_PD_CLUSTER,
7505 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1),
7506 },
7507 {
7508 .id = VOP2_PD_ESMART,
7509 .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) |
7510 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3),
7511 },
7512 };
7513
7514 static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = {
7515 {VOP3_ESMART_4K_4K_4K_MODE, 2},
7516 {VOP3_ESMART_4K_4K_2K_2K_MODE, 3}
7517 };
7518
7519 static const struct vop2_ops rk3576_vop_ops = {
7520 .setup_win_dly = rk3576_setup_win_dly,
7521 .setup_overlay = rk3576_setup_overlay,
7522 .assign_plane_mask = rk3528_assign_plane_mask,
7523 };
7524
7525 const struct vop2_data rk3576_vop = {
7526 .version = VOP_VERSION_RK3576,
7527 .nr_vps = 3,
7528 .nr_mixers = 4,
7529 .nr_layers = 6,
7530 .nr_gammas = 3,
7531 .esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE,
7532 .esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map),
7533 .esmart_lb_mode_map = rk3576_esmart_lb_mode_map,
7534 .vp_data = rk3576_vp_data,
7535 .win_data = rk3576_win_data,
7536 .plane_mask_base = RK3576_PLANE_MASK_BASE,
7537 .pd = rk3576_vop_pd_data,
7538 .nr_pd = ARRAY_SIZE(rk3576_vop_pd_data),
7539 .dump_regs = rk3576_dump_regs,
7540 .dump_regs_size = ARRAY_SIZE(rk3576_dump_regs),
7541 .ops = &rk3576_vop_ops,
7542 };
7543
7544 static struct vop2_dump_regs rk3588_dump_regs[] = {
7545 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
7546 { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
7547 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
7548 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
7549 { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
7550 { RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 },
7551 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
7552 { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
7553 { RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 },
7554 { RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 },
7555 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
7556 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
7557 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
7558 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
7559 { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
7560 };
7561
7562 static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
7563 { /* one display policy */
7564 {/* main display */
7565 .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7566 .attached_layers_nr = 4,
7567 .attached_layers = {
7568 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
7569 ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7570 },
7571 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7572 },
7573
7574 {/* planes for the splice mode */
7575 .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7576 .attached_layers_nr = 4,
7577 .attached_layers = {
7578 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
7579 ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
7580 },
7581 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7582 },
7583 {/* third display */},
7584 {/* fourth display */},
7585 },
7586
7587 { /* two display policy */
7588 {/* main display */
7589 .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7590 .attached_layers_nr = 4,
7591 .attached_layers = {
7592 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
7593 ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7594 },
7595 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7596 },
7597
7598 {/* second display */
7599 .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7600 .attached_layers_nr = 4,
7601 .attached_layers = {
7602 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
7603 ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
7604 },
7605 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7606 },
7607 {/* third display */},
7608 {/* fourth display */},
7609 },
7610
7611 { /* three display policy */
7612 {/* main display */
7613 .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7614 .attached_layers_nr = 3,
7615 .attached_layers = {
7616 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER2,
7617 ROCKCHIP_VOP2_ESMART0
7618 },
7619 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7620 },
7621
7622 {/* second display */
7623 .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7624 .attached_layers_nr = 3,
7625 .attached_layers = {
7626 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_CLUSTER3,
7627 ROCKCHIP_VOP2_ESMART1
7628 },
7629 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7630 },
7631
7632 {/* third display */
7633 .primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7634 .attached_layers_nr = 2,
7635 .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
7636 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7637 },
7638
7639 {/* fourth display */},
7640 },
7641
7642 { /* four display policy */
7643 {/* main display */
7644 .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7645 .attached_layers_nr = 2,
7646 .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
7647 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7648 },
7649
7650 {/* second display */
7651 .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7652 .attached_layers_nr = 2,
7653 .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
7654 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7655 },
7656
7657 {/* third display */
7658 .primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7659 .attached_layers_nr = 2,
7660 .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
7661 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7662 },
7663
7664 {/* fourth display */
7665 .primary_plane_id = ROCKCHIP_VOP2_ESMART3,
7666 .attached_layers_nr = 2,
7667 .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
7668 .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7669 },
7670 },
7671
7672 };
7673
7674 #define RK3588_PLANE_MASK_BASE \
7675 (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
7676 BIT(ROCKCHIP_VOP2_CLUSTER2) | BIT(ROCKCHIP_VOP2_CLUSTER3) | \
7677 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
7678 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
7679
7680 static struct vop2_win_data rk3588_win_data[8] = {
7681 {
7682 .name = "Cluster0",
7683 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
7684 .splice_win_id = ROCKCHIP_VOP2_CLUSTER1,
7685 .type = CLUSTER_LAYER,
7686 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7687 .win_sel_port_offset = 0,
7688 .layer_sel_win_id = { 0, 0, 0, 0 },
7689 .reg_offset = 0,
7690 .axi_id = 0,
7691 .axi_yrgb_id = 2,
7692 .axi_uv_id = 3,
7693 .pd_id = VOP2_PD_CLUSTER0,
7694 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7695 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7696 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7697 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7698 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7699 .max_upscale_factor = 4,
7700 .max_downscale_factor = 4,
7701 .dly = { 4, 26, 29, 4, 35, 3, 5 },
7702 },
7703
7704 {
7705 .name = "Cluster1",
7706 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
7707 .type = CLUSTER_LAYER,
7708 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7709 .win_sel_port_offset = 1,
7710 .layer_sel_win_id = { 1, 1, 1, 1 },
7711 .reg_offset = 0x200,
7712 .axi_id = 0,
7713 .axi_yrgb_id = 6,
7714 .axi_uv_id = 7,
7715 .pd_id = VOP2_PD_CLUSTER1,
7716 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7717 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7718 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7719 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7720 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7721 .max_upscale_factor = 4,
7722 .max_downscale_factor = 4,
7723 .dly = { 4, 26, 29, 4, 35, 3, 5 },
7724 },
7725
7726 {
7727 .name = "Cluster2",
7728 .phys_id = ROCKCHIP_VOP2_CLUSTER2,
7729 .splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
7730 .type = CLUSTER_LAYER,
7731 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7732 .win_sel_port_offset = 2,
7733 .layer_sel_win_id = { 4, 4, 4, 4 },
7734 .reg_offset = 0x400,
7735 .axi_id = 1,
7736 .axi_yrgb_id = 2,
7737 .axi_uv_id = 3,
7738 .pd_id = VOP2_PD_CLUSTER2,
7739 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7740 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7741 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7742 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7743 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7744 .max_upscale_factor = 4,
7745 .max_downscale_factor = 4,
7746 .dly = { 4, 26, 29, 4, 35, 3, 5 },
7747 },
7748
7749 {
7750 .name = "Cluster3",
7751 .phys_id = ROCKCHIP_VOP2_CLUSTER3,
7752 .type = CLUSTER_LAYER,
7753 .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7754 .win_sel_port_offset = 3,
7755 .layer_sel_win_id = { 5, 5, 5, 5 },
7756 .reg_offset = 0x600,
7757 .axi_id = 1,
7758 .axi_yrgb_id = 6,
7759 .axi_uv_id = 7,
7760 .pd_id = VOP2_PD_CLUSTER3,
7761 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7762 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7763 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7764 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7765 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7766 .max_upscale_factor = 4,
7767 .max_downscale_factor = 4,
7768 .dly = { 4, 26, 29, 4, 35, 3, 5 },
7769 },
7770
7771 {
7772 .name = "Esmart0",
7773 .phys_id = ROCKCHIP_VOP2_ESMART0,
7774 .splice_win_id = ROCKCHIP_VOP2_ESMART1,
7775 .type = ESMART_LAYER,
7776 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7777 .win_sel_port_offset = 4,
7778 .layer_sel_win_id = { 2, 2, 2, 2 },
7779 .reg_offset = 0,
7780 .axi_id = 0,
7781 .axi_yrgb_id = 0x0a,
7782 .axi_uv_id = 0x0b,
7783 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7784 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7785 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7786 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7787 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7788 .max_upscale_factor = 8,
7789 .max_downscale_factor = 8,
7790 .dly = { 23, 45, 48, 23, 54, 22, 24 },
7791 },
7792
7793 {
7794 .name = "Esmart1",
7795 .phys_id = ROCKCHIP_VOP2_ESMART1,
7796 .type = ESMART_LAYER,
7797 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7798 .win_sel_port_offset = 5,
7799 .layer_sel_win_id = { 3, 3, 3, 3 },
7800 .reg_offset = 0x200,
7801 .axi_id = 0,
7802 .axi_yrgb_id = 0x0c,
7803 .axi_uv_id = 0x0d,
7804 .pd_id = VOP2_PD_ESMART,
7805 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7806 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7807 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7808 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7809 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7810 .max_upscale_factor = 8,
7811 .max_downscale_factor = 8,
7812 .dly = { 23, 45, 48, 23, 54, 22, 24 },
7813 },
7814
7815 {
7816 .name = "Esmart2",
7817 .phys_id = ROCKCHIP_VOP2_ESMART2,
7818 .splice_win_id = ROCKCHIP_VOP2_ESMART3,
7819 .type = ESMART_LAYER,
7820 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7821 .win_sel_port_offset = 6,
7822 .layer_sel_win_id = { 6, 6, 6, 6 },
7823 .reg_offset = 0x400,
7824 .axi_id = 1,
7825 .axi_yrgb_id = 0x0a,
7826 .axi_uv_id = 0x0b,
7827 .pd_id = VOP2_PD_ESMART,
7828 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7829 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7830 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7831 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7832 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7833 .max_upscale_factor = 8,
7834 .max_downscale_factor = 8,
7835 .dly = { 23, 45, 48, 23, 54, 22, 24 },
7836 },
7837
7838 {
7839 .name = "Esmart3",
7840 .phys_id = ROCKCHIP_VOP2_ESMART3,
7841 .type = ESMART_LAYER,
7842 .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7843 .win_sel_port_offset = 7,
7844 .layer_sel_win_id = { 7, 7, 7, 7 },
7845 .reg_offset = 0x600,
7846 .axi_id = 1,
7847 .axi_yrgb_id = 0x0c,
7848 .axi_uv_id = 0x0d,
7849 .pd_id = VOP2_PD_ESMART,
7850 .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7851 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7852 .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7853 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7854 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
7855 .max_upscale_factor = 8,
7856 .max_downscale_factor = 8,
7857 .dly = { 23, 45, 48, 23, 54, 22, 24 },
7858 },
7859 };
7860
7861 static struct dsc_error_info dsc_ecw[] = {
7862 {0x00000000, "no error detected by DSC encoder"},
7863 {0x0030ffff, "bits per component error"},
7864 {0x0040ffff, "multiple mode error"},
7865 {0x0050ffff, "line buffer depth error"},
7866 {0x0060ffff, "minor version error"},
7867 {0x0070ffff, "picture height error"},
7868 {0x0080ffff, "picture width error"},
7869 {0x0090ffff, "number of slices error"},
7870 {0x00c0ffff, "slice height Error "},
7871 {0x00d0ffff, "slice width error"},
7872 {0x00e0ffff, "second line BPG offset error"},
7873 {0x00f0ffff, "non second line BPG offset error"},
7874 {0x0100ffff, "PPS ID error"},
7875 {0x0110ffff, "bits per pixel (BPP) Error"},
7876 {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */
7877
7878 {0x01510001, "slice 0 RC buffer model overflow error"},
7879 {0x01510002, "slice 1 RC buffer model overflow error"},
7880 {0x01510004, "slice 2 RC buffer model overflow error"},
7881 {0x01510008, "slice 3 RC buffer model overflow error"},
7882 {0x01510010, "slice 4 RC buffer model overflow error"},
7883 {0x01510020, "slice 5 RC buffer model overflow error"},
7884 {0x01510040, "slice 6 RC buffer model overflow error"},
7885 {0x01510080, "slice 7 RC buffer model overflow error"},
7886
7887 {0x01610001, "slice 0 RC buffer model underflow error"},
7888 {0x01610002, "slice 1 RC buffer model underflow error"},
7889 {0x01610004, "slice 2 RC buffer model underflow error"},
7890 {0x01610008, "slice 3 RC buffer model underflow error"},
7891 {0x01610010, "slice 4 RC buffer model underflow error"},
7892 {0x01610020, "slice 5 RC buffer model underflow error"},
7893 {0x01610040, "slice 6 RC buffer model underflow error"},
7894 {0x01610080, "slice 7 RC buffer model underflow error"},
7895
7896 {0xffffffff, "unsuccessful RESET cycle status"},
7897 {0x00a0ffff, "ICH full error precision settings error"},
7898 {0x0020ffff, "native mode"},
7899 };
7900
7901 static struct dsc_error_info dsc_buffer_flow[] = {
7902 {0x00000000, "rate buffer status"},
7903 {0x00000001, "line buffer status"},
7904 {0x00000002, "decoder model status"},
7905 {0x00000003, "pixel buffer status"},
7906 {0x00000004, "balance fifo buffer status"},
7907 {0x00000005, "syntax element fifo status"},
7908 };
7909
7910 static struct vop2_dsc_data rk3588_dsc_data[] = {
7911 {
7912 .id = ROCKCHIP_VOP2_DSC_8K,
7913 .pd_id = VOP2_PD_DSC_8K,
7914 .max_slice_num = 8,
7915 .max_linebuf_depth = 11,
7916 .min_bits_per_pixel = 8,
7917 .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
7918 .dsc_txp_clk_name = "dsc_8k_txp_clk",
7919 .dsc_pxl_clk_name = "dsc_8k_pxl_clk",
7920 .dsc_cds_clk_name = "dsc_8k_cds_clk",
7921 },
7922
7923 {
7924 .id = ROCKCHIP_VOP2_DSC_4K,
7925 .pd_id = VOP2_PD_DSC_4K,
7926 .max_slice_num = 2,
7927 .max_linebuf_depth = 11,
7928 .min_bits_per_pixel = 8,
7929 .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
7930 .dsc_txp_clk_name = "dsc_4k_txp_clk",
7931 .dsc_pxl_clk_name = "dsc_4k_pxl_clk",
7932 .dsc_cds_clk_name = "dsc_4k_cds_clk",
7933 },
7934 };
7935
7936 static struct vop2_vp_data rk3588_vp_data[4] = {
7937 {
7938 .splice_vp_id = 1,
7939 .feature = VOP_FEATURE_OUTPUT_10BIT,
7940 .pre_scan_max_dly = 54,
7941 .max_dclk = 600000,
7942 .max_output = {7680, 4320},
7943 },
7944 {
7945 .feature = VOP_FEATURE_OUTPUT_10BIT,
7946 .pre_scan_max_dly = 54,
7947 .max_dclk = 600000,
7948 .max_output = {4096, 2304},
7949 },
7950 {
7951 .feature = VOP_FEATURE_OUTPUT_10BIT,
7952 .pre_scan_max_dly = 52,
7953 .max_dclk = 600000,
7954 .max_output = {4096, 2304},
7955 },
7956 {
7957 .feature = 0,
7958 .pre_scan_max_dly = 52,
7959 .max_dclk = 200000,
7960 .max_output = {1920, 1080},
7961 },
7962 };
7963
7964 static struct vop2_power_domain_data rk3588_vop_pd_data[] = {
7965 {
7966 .id = VOP2_PD_CLUSTER0,
7967 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0),
7968 },
7969 {
7970 .id = VOP2_PD_CLUSTER1,
7971 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1),
7972 .parent_id = VOP2_PD_CLUSTER0,
7973 },
7974 {
7975 .id = VOP2_PD_CLUSTER2,
7976 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2),
7977 .parent_id = VOP2_PD_CLUSTER0,
7978 },
7979 {
7980 .id = VOP2_PD_CLUSTER3,
7981 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3),
7982 .parent_id = VOP2_PD_CLUSTER0,
7983 },
7984 {
7985 .id = VOP2_PD_ESMART,
7986 .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) |
7987 BIT(ROCKCHIP_VOP2_ESMART2) |
7988 BIT(ROCKCHIP_VOP2_ESMART3),
7989 },
7990 {
7991 .id = VOP2_PD_DSC_8K,
7992 .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K),
7993 },
7994 {
7995 .id = VOP2_PD_DSC_4K,
7996 .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K),
7997 },
7998 };
7999
8000 static const struct vop2_ops rk3588_vop_ops = {
8001 .setup_win_dly = rk3568_setup_win_dly,
8002 .setup_overlay = rk3568_setup_overlay,
8003 .assign_plane_mask = rk3568_assign_plane_mask,
8004 };
8005
8006 const struct vop2_data rk3588_vop = {
8007 .version = VOP_VERSION_RK3588,
8008 .nr_vps = 4,
8009 .vp_data = rk3588_vp_data,
8010 .win_data = rk3588_win_data,
8011 .plane_mask = rk3588_vp_plane_mask[0],
8012 .plane_mask_base = RK3588_PLANE_MASK_BASE,
8013 .pd = rk3588_vop_pd_data,
8014 .dsc = rk3588_dsc_data,
8015 .dsc_error_ecw = dsc_ecw,
8016 .dsc_error_buffer_flow = dsc_buffer_flow,
8017 .nr_layers = 8,
8018 .nr_mixers = 7,
8019 .nr_gammas = 4,
8020 .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data),
8021 .nr_dscs = 2,
8022 .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw),
8023 .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow),
8024 .dump_regs = rk3588_dump_regs,
8025 .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs),
8026 .ops = &rk3588_vop_ops,
8027 };
8028
8029 const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
8030 .reset = rockchip_vop2_reset,
8031 .preinit = rockchip_vop2_preinit,
8032 .prepare = rockchip_vop2_prepare,
8033 .init = rockchip_vop2_init,
8034 .set_plane = rockchip_vop2_set_plane,
8035 .enable = rockchip_vop2_enable,
8036 .post_enable = rockchip_vop2_post_enable,
8037 .disable = rockchip_vop2_disable,
8038 .fixup_dts = rockchip_vop2_fixup_dts,
8039 .send_mcu_cmd = rockchip_vop2_send_mcu_cmd,
8040 .check = rockchip_vop2_check,
8041 .mode_valid = rockchip_vop2_mode_valid,
8042 .mode_fixup = rockchip_vop2_mode_fixup,
8043 .plane_check = rockchip_vop2_plane_check,
8044 .regs_dump = rockchip_vop2_regs_dump,
8045 .active_regs_dump = rockchip_vop2_active_regs_dump,
8046 .apply_soft_te = rockchip_vop2_apply_soft_te,
8047 };
8048