1d0408543SAndy Yan // SPDX-License-Identifier: GPL-2.0-only
2d0408543SAndy Yan /*
3d0408543SAndy Yan * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
4d0408543SAndy Yan *
5d0408543SAndy Yan */
6d0408543SAndy Yan
7d0408543SAndy Yan #include <config.h>
8d0408543SAndy Yan #include <common.h>
9d0408543SAndy Yan #include <errno.h>
10d0408543SAndy Yan #include <malloc.h>
11d0408543SAndy Yan #include <fdtdec.h>
12d0408543SAndy Yan #include <fdt_support.h>
13b890760eSAlgea Cao #include <regmap.h>
14feffd38eSSandy Huang #include <asm/arch/cpu.h>
15d0408543SAndy Yan #include <asm/unaligned.h>
16d0408543SAndy Yan #include <asm/io.h>
17d0408543SAndy Yan #include <linux/list.h>
18ecc31b6eSAndy Yan #include <linux/log2.h>
19d0408543SAndy Yan #include <linux/media-bus-format.h>
20d0408543SAndy Yan #include <asm/arch/clock.h>
218e7ef808SDamon Ding #include <asm/gpio.h>
22d0408543SAndy Yan #include <linux/err.h>
231147facaSSandy Huang #include <linux/ioport.h>
24d0408543SAndy Yan #include <dm/device.h>
25d0408543SAndy Yan #include <dm/read.h>
265fa6e665SDamon Ding #include <dm/ofnode.h>
27ac500a1fSSandy Huang #include <fixp-arith.h>
28d0408543SAndy Yan #include <syscon.h>
2960e469f5SDamon Ding #include <linux/iopoll.h>
305f1357a2SZhang Yubing #include <dm/uclass-internal.h>
31452afb13SDamon Ding #include <stdlib.h>
320669ab1fSDamon Ding #include <dm/of_access.h>
33789e70ecSFinley Xiao #include <power-domain.h>
34d0408543SAndy Yan
35d0408543SAndy Yan #include "rockchip_display.h"
36d0408543SAndy Yan #include "rockchip_crtc.h"
37d0408543SAndy Yan #include "rockchip_connector.h"
38d8e7f4a5SSandy Huang #include "rockchip_phy.h"
396027c871SZhang Yubing #include "rockchip_post_csc.h"
40d0408543SAndy Yan
41d0408543SAndy Yan /* System registers definition */
42d0408543SAndy Yan #define RK3568_REG_CFG_DONE 0x000
43d0408543SAndy Yan #define CFG_DONE_EN BIT(15)
44d0408543SAndy Yan
45d0408543SAndy Yan #define RK3568_VERSION_INFO 0x004
46d0408543SAndy Yan #define EN_MASK 1
47d0408543SAndy Yan
4863cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL 0x008
490675a2a4SDamon Ding #define AUTO_GATING_EN_SHIFT 31
500675a2a4SDamon Ding #define PORT_DCLK_AUTO_GATING_EN_SHIFT 14
51bb7ec356SDamon Ding #define ACLK_PRE_AUTO_GATING_EN_SHIFT 7
5263cb669fSSandy Huang
5344b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL0_IMD 0x014
5444b1b62cSDamon Ding #define AXI0_PORT_URGENCY_EN_SHIFT 24
5544b1b62cSDamon Ding
5644b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL1_IMD 0x018
5744b1b62cSDamon Ding #define AXI1_PORT_URGENCY_EN_SHIFT 24
5844b1b62cSDamon Ding
59a552a69cSDamon Ding #define RK3576_SYS_MMU_CTRL 0x020
60a552a69cSDamon Ding #define RKMMU_V2_EN_SHIFT 0
61a552a69cSDamon Ding #define RKMMU_V2_SEL_AXI_SHIFT 1
62a552a69cSDamon Ding
636414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL 0x024
646414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT 0
65aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT 16
666414e3bcSSandy Huang
67d0408543SAndy Yan #define RK3568_DSP_IF_EN 0x028
68d0408543SAndy Yan #define RGB_EN_SHIFT 0
69ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT 0
70ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT 1
71ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT 8
72d0408543SAndy Yan #define HDMI0_EN_SHIFT 1
73d0408543SAndy Yan #define EDP0_EN_SHIFT 3
74ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT 2
75ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT 3
76d0408543SAndy Yan #define MIPI0_EN_SHIFT 4
77ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT 4
78ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT 5
79ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT 6
80d0408543SAndy Yan #define MIPI1_EN_SHIFT 20
81ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT 7
82d0408543SAndy Yan #define LVDS0_EN_SHIFT 5
83d0408543SAndy Yan #define LVDS1_EN_SHIFT 24
84d0408543SAndy Yan #define BT1120_EN_SHIFT 6
85d0408543SAndy Yan #define BT656_EN_SHIFT 7
86d0408543SAndy Yan #define IF_MUX_MASK 3
87d0408543SAndy Yan #define RGB_MUX_SHIFT 8
88d0408543SAndy Yan #define HDMI0_MUX_SHIFT 10
89ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT 12
90ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT 14
91d0408543SAndy Yan #define EDP0_MUX_SHIFT 14
92ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT 16
93ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT 18
94d0408543SAndy Yan #define MIPI0_MUX_SHIFT 16
95ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT 20
96d0408543SAndy Yan #define MIPI1_MUX_SHIFT 21
9711f53190SSandy Huang #define LVDS0_MUX_SHIFT 18
98d0408543SAndy Yan #define LVDS1_MUX_SHIFT 25
99d0408543SAndy Yan
100a552a69cSDamon Ding #define RK3576_SYS_PORT_CTRL 0x028
101a552a69cSDamon Ding #define VP_INTR_MERGE_EN_SHIFT 14
10212ee4de7SDamon Ding #define RK3576_DSP_VS_T_SEL_SHIFT 4
103a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_MASK 0x7
104a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_SHIFT 0
105a552a69cSDamon Ding
106d0408543SAndy Yan #define RK3568_DSP_IF_CTRL 0x02c
107d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT 0
1085d2768f7SDamon Ding #define RK3588_BT656_UV_SWAP_SHIFT 0
109d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1
1105d2768f7SDamon Ding #define RK3588_BT656_YC_SWAP_SHIFT 1
111d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT 2
1125fa6e665SDamon Ding #define BT656_UV_SWAP 4
1135d2768f7SDamon Ding #define RK3588_BT1120_UV_SWAP_SHIFT 4
1145fa6e665SDamon Ding #define BT656_YC_SWAP 5
1155d2768f7SDamon Ding #define RK3588_BT1120_YC_SWAP_SHIFT 5
1165fa6e665SDamon Ding #define BT656_DCLK_POL 6
1170a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT 8
1180a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT 8
1190a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT 9
12041874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT 10
12141874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11
12241874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12
12341874944SGuochun Huang
124d0408543SAndy Yan #define RK3568_DSP_IF_POL 0x030
125d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT 28
126d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT 19
127de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_MASK 0x7
128de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_SHIFT 16
129d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT 15
1307bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_MASK 0x7
1317bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_SHIFT 12
132d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT 7
13310ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK 0x7
13410ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT 4
13515f69071SDamon Ding #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT 3
13615f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_MASK 0x7
13715f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT 0
138ecc31b6eSAndy Yan
139452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT 15
140452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT 12
141452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK 0x7
142452afb13SDamon Ding
143ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT 8
144ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT 12
145ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK 0x7
146ecc31b6eSAndy Yan
147ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT 16
148ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18
149ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT 20
150ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22
151ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT 24
152ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT 26
153ecc31b6eSAndy Yan
154a552a69cSDamon Ding #define RK3576_SYS_CLUSTER_PD_CTRL 0x030
155a552a69cSDamon Ding #define RK3576_CLUSTER_PD_EN_SHIFT 0
156a552a69cSDamon Ding
157a552a69cSDamon Ding #define RK3588_SYS_PD_CTRL 0x034
158a552a69cSDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT 0
159a552a69cSDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT 1
160a552a69cSDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT 2
161a552a69cSDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT 3
162a552a69cSDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT 5
163a552a69cSDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT 6
164a552a69cSDamon Ding #define RK3588_ESMART_PD_EN_SHIFT 7
165a552a69cSDamon Ding
166a552a69cSDamon Ding #define RK3576_SYS_ESMART_PD_CTRL 0x034
167a552a69cSDamon Ding #define RK3576_ESMART_PD_EN_SHIFT 0
168a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_SHIFT 6
169a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_MASK 0x3
170a552a69cSDamon Ding
171feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN 0x50
172feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT 0
1731147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL 0x58
1741147facaSSandy Huang #define GAMMA_PORT_SEL_MASK 0x3
1751147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT 0
176db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK 0x3
177db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT 12
178ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT 16
1795fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK 0x3
1805fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT 26
1811147facaSSandy Huang
182d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG 0x70
183d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG 0x74
184d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG 0x78
185d0408543SAndy Yan #define RK3568_SYS0_INT_EN 0x80
186d0408543SAndy Yan #define RK3568_SYS0_INT_CLR 0x84
187d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS 0x88
188d0408543SAndy Yan #define RK3568_SYS1_INT_EN 0x90
189d0408543SAndy Yan #define RK3568_SYS1_INT_CLR 0x94
190d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS 0x98
191d0408543SAndy Yan #define RK3568_VP0_INT_EN 0xA0
192d0408543SAndy Yan #define RK3568_VP0_INT_CLR 0xA4
193d0408543SAndy Yan #define RK3568_VP0_INT_STATUS 0xA8
194d0408543SAndy Yan #define RK3568_VP1_INT_EN 0xB0
195d0408543SAndy Yan #define RK3568_VP1_INT_CLR 0xB4
196d0408543SAndy Yan #define RK3568_VP1_INT_STATUS 0xB8
197d0408543SAndy Yan #define RK3568_VP2_INT_EN 0xC0
198d0408543SAndy Yan #define RK3568_VP2_INT_CLR 0xC4
199d0408543SAndy Yan #define RK3568_VP2_INT_STATUS 0xC8
200a552a69cSDamon Ding #define RK3568_VP2_INT_RAW_STATUS 0xCC
201a552a69cSDamon Ding #define RK3588_VP3_INT_EN 0xD0
202a552a69cSDamon Ding #define RK3588_VP3_INT_CLR 0xD4
203a552a69cSDamon Ding #define RK3588_VP3_INT_STATUS 0xD8
204a552a69cSDamon Ding #define RK3576_WB_CTRL 0x100
205a552a69cSDamon Ding #define RK3576_WB_XSCAL_FACTOR 0x104
206a552a69cSDamon Ding #define RK3576_WB_YRGB_MST 0x108
207a552a69cSDamon Ding #define RK3576_WB_CBR_MST 0x10C
208a552a69cSDamon Ding #define RK3576_WB_VIR_STRIDE 0x110
209a552a69cSDamon Ding #define RK3576_WB_TIMEOUT_CTRL 0x114
210a552a69cSDamon Ding #define RK3576_MIPI0_IF_CTRL 0x180
211a552a69cSDamon Ding #define RK3576_IF_OUT_EN_SHIFT 0
212a552a69cSDamon Ding #define RK3576_IF_CLK_OUT_EN_SHIFT 1
213a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_SHIFT 2
214a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_MASK 0x3
215a552a69cSDamon Ding #define RK3576_IF_PIN_POL_SHIFT 4
216a552a69cSDamon Ding #define RK3576_IF_PIN_POL_MASK 0x7
217a552a69cSDamon Ding #define RK3576_IF_SPLIT_EN_SHIFT 8
218a552a69cSDamon Ding #define RK3576_IF_DATA1_SEL_SHIFT 9
219a552a69cSDamon Ding #define RK3576_MIPI_CMD_MODE_SHIFT 11
220a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_SHIFT 21
221a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_MASK 0x1
222a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_SHIFT 20
223a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_MASK 0x1
224a552a69cSDamon Ding #define RK3576_IF_REGDONE_IMD_EN_SHIFT 31
225a552a69cSDamon Ding #define RK3576_HDMI0_IF_CTRL 0x184
226a552a69cSDamon Ding #define RK3576_EDP0_IF_CTRL 0x188
227a552a69cSDamon Ding #define RK3576_DP0_IF_CTRL 0x18C
228a552a69cSDamon Ding #define RK3576_RGB_IF_CTRL 0x194
229a552a69cSDamon Ding #define RK3576_BT656_OUT_EN_SHIFT 12
230a552a69cSDamon Ding #define RK3576_BT656_UV_SWAP_SHIFT 13
231a552a69cSDamon Ding #define RK3576_BT656_YC_SWAP_SHIFT 14
232a552a69cSDamon Ding #define RK3576_BT1120_OUT_EN_SHIFT 16
233a552a69cSDamon Ding #define RK3576_BT1120_UV_SWAP_SHIFT 17
234a552a69cSDamon Ding #define RK3576_BT1120_YC_SWAP_SHIFT 18
235a552a69cSDamon Ding #define RK3576_DP1_IF_CTRL 0x1A4
236a552a69cSDamon Ding #define RK3576_DP2_IF_CTRL 0x1B0
23760e469f5SDamon Ding
238cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL 0x038
239cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT 20
240cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT 24
241cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT 28
242cd6c85a9SDamon Ding
24360e469f5SDamon Ding #define RK3568_SYS_STATUS0 0x60
24460e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8
24560e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9
24660e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10
24760e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11
248b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT 13
249b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT 14
25060e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT 15
251d0408543SAndy Yan
25266724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0 0x70
25366724b9cSDamon Ding #define LINE_FLAG_NUM_MASK 0x1fff
25466724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0
25566724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16
25666724b9cSDamon Ding
25712ee5af0SDamon Ding /* DSC CTRL registers definition */
25812ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL 0x200
25912ee5af0SDamon Ding #define DSC_PORT_SEL_MASK 0x3
26012ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT 0
26112ee5af0SDamon Ding #define DSC_MAN_MODE_MASK 0x1
26212ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT 2
26312ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK 0x3
26412ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT 4
26512ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK 0x3
26612ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT 6
26712ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK 0x1
26812ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT 8
26912ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK 0x3
27012ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT 12
27112ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK 0x3
27212ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT 14
27312ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK 0x1
27412ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT 16
27512ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT 17
27612ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT 18
27712ee5af0SDamon Ding
27812ee5af0SDamon Ding #define RK3588_DSC_8K_RST 0x204
27912ee5af0SDamon Ding #define RST_DEASSERT_MASK 0x1
28012ee5af0SDamon Ding #define RST_DEASSERT_SHIFT 0
28112ee5af0SDamon Ding
28212ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE 0x208
28312ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT 0
28412ee5af0SDamon Ding
28512ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY 0x20C
28612ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK 0xffff
28712ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT 0
28812ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16
28912ee5af0SDamon Ding
29012ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END 0x210
29112ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK 0xffffffff
29212ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT 0
29312ee5af0SDamon Ding
29412ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END 0x214
29512ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK 0xffffffff
29612ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT 0
29712ee5af0SDamon Ding
29812ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END 0x218
29912ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK 0xffffffff
30012ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT 0
30112ee5af0SDamon Ding
30212ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END 0x21C
30312ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK 0xffffffff
30412ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT 0
30512ee5af0SDamon Ding
30612ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS 0x220
30712ee5af0SDamon Ding
30863cb669fSSandy Huang /* Overlay registers definition */
3095fa6e665SDamon Ding #define RK3528_OVL_SYS 0x500
310a552a69cSDamon Ding #define RK3528_OVL_SYS_PORT_SEL 0x504
311a552a69cSDamon Ding #define RK3528_OVL_SYS_GATING_EN 0x508
3125fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL 0x510
3139c7848c3SDamon Ding #define CLUSTER_DLY_NUM_SHIFT 0
3145fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL 0x520
315452afb13SDamon Ding #define ESMART_DLY_NUM_MASK 0xff
316452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT 0
3175fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL 0x524
3185fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL 0x528
3195fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C
3205fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530
3215fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534
3225fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538
3235fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c
324a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540
325a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544
326a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548
327a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c
3285fa6e665SDamon Ding
3295fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL 0x600
33063cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600
331ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK 0x1
332ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT 0
33363cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28
3345fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL 0x604
33563cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604
33663cb669fSSandy Huang #define LAYER_SEL_MASK 0xf
33763cb669fSSandy Huang
33863cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608
33963cb669fSSandy Huang #define PORT_MUX_MASK 0xf
34063cb669fSSandy Huang #define PORT_MUX_SHIFT 0
34163cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3
34263cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16
34363cb669fSSandy Huang
34463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610
34563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614
34663cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618
34763cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C
3485fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620
3495fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624
3505fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628
3515fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C
3525fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630
3535fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634
3545fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638
3555fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C
3565fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640
3575fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644
3585fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648
3595fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C
36063cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650
36163cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654
36263cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658
36363cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C
364a552a69cSDamon Ding #define RK3576_EXTRA_SRC_COLOR_CTRL 0x650
365a552a69cSDamon Ding #define RK3576_EXTRA_DST_COLOR_CTRL 0x654
366a552a69cSDamon Ding #define RK3576_EXTRA_SRC_ALPHA_CTRL 0x658
367a552a69cSDamon Ding #define RK3576_EXTRA_DST_ALPHA_CTRL 0x65C
3685fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL 0x660
3695fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL 0x664
3705fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL 0x668
3715fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL 0x66C
3725fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670
37363cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0
37463cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4
37563cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8
37663cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC
37763cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0
37863cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff
37963cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24
38063cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4
38163cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8
38263cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0
3839c7848c3SDamon Ding #define RK3568_CLUSTER_DLY_NUM1 0x6F4
3849c7848c3SDamon Ding #define CLUSTER_DLY_NUM_MASK 0xffff
3859c7848c3SDamon Ding #define CLUSTER0_DLY_NUM_SHIFT 0
3869c7848c3SDamon Ding #define CLUSTER1_DLY_NUM_SHIFT 16
38763cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8
3889c7848c3SDamon Ding #define SMART_DLY_NUM_MASK 0xff
3899c7848c3SDamon Ding #define ESMART0_DLY_NUM_SHIFT 0
3909c7848c3SDamon Ding #define ESMART1_DLY_NUM_SHIFT 8
3919c7848c3SDamon Ding #define SMART0_DLY_NUM_SHIFT 16
3929c7848c3SDamon Ding #define SMART1_DLY_NUM_SHIFT 24
39363cb669fSSandy Huang
3945fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL 0x700
3955fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL 0x704
3965fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720
3975fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724
3985fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728
3995fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C
4005fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730
4015fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734
4025fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738
4035fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C
4045fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740
4055fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744
4065fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748
4075fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C
4085fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770
409a552a69cSDamon Ding #define RK3576_OVL_PORT2_CTRL 0x800
410a552a69cSDamon Ding #define RK3576_OVL_PORT2_LAYER_SEL 0x804
411a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL 0x820
412a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL 0x824
413a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL 0x828
414a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL 0x82C
415a552a69cSDamon Ding #define RK3576_OVL_PORT2_BG_MIX_CTRL 0x870
4165fa6e665SDamon Ding
417d0408543SAndy Yan /* Video Port registers definition */
418d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00
419d0408543SAndy Yan #define OUT_MODE_MASK 0xf
420d0408543SAndy Yan #define OUT_MODE_SHIFT 0
42110ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f
42210ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8
42365747de7SDamon Ding #define DSP_BG_SWAP 0x1
42465747de7SDamon Ding #define DSP_RB_SWAP 0x2
42565747de7SDamon Ding #define DSP_RG_SWAP 0x4
42665747de7SDamon Ding #define DSP_DELTA_SWAP 0x8
42710ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4
428d0408543SAndy Yan #define P2I_EN_SHIFT 5
4297a20be36SSandy Huang #define DSP_FILED_POL 6
430d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7
431c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT 13
43210ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15
433d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16
434d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17
435e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_SHIFT 18
436e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_MASK 0x3
437452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT 20
438db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT 22
4391147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28
4401147facaSSandy Huang
441d0408543SAndy Yan #define STANDBY_EN_SHIFT 31
442d0408543SAndy Yan
443d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04
44410ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4
44510ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3
446d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20
447d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21
44841874944SGuochun Huang #define EDPI_TE_EN 28
44941874944SGuochun Huang #define EDPI_WMS_HOLD_EN 30
45041874944SGuochun Huang #define EDPI_WMS_FS 31
45141874944SGuochun Huang
452d0408543SAndy Yan
453d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08
45444b1b62cSDamon Ding #define POST_URGENCY_EN_SHIFT 8
45544b1b62cSDamon Ding #define POST_URGENCY_THL_SHIFT 16
45644b1b62cSDamon Ding #define POST_URGENCY_THL_MASK 0xf
45744b1b62cSDamon Ding #define POST_URGENCY_THH_SHIFT 20
45844b1b62cSDamon Ding #define POST_URGENCY_THH_MASK 0xf
4595fa6e665SDamon Ding
4605fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL 0xC0C
461a552a69cSDamon Ding #define RK3576_DCLK_CORE_SEL_SHIFT 0
462a552a69cSDamon Ding #define RK3576_DCLK_OUT_SEL_SHIFT 2
4635fa6e665SDamon Ding
4646414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10
4656414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0
4666414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2
4676414e3bcSSandy Huang
468ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C
469ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0
470ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2
471ecc31b6eSAndy Yan
4726414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20
4736414e3bcSSandy Huang
474d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C
475d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30
476d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34
477d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38
478d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C
479d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40
4807504507fSSandy Huang #define RK3568_VP0_POST_SCALE_MASK 0x3
4817504507fSSandy Huang #define RK3568_VP0_POST_SCALE_SHIFT 0
482d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44
483d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48
484d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C
485d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50
486d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54
487d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58
488d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C
489d0408543SAndy Yan
490ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60
491ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0
492ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1
493ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2
494ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3
495ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4
496ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1
497ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6
498ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3
499ac500a1fSSandy Huang
500ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64
501ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0
502ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF
503ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8
504ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF
505ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20
506ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF
507ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30
508ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3
509ac500a1fSSandy Huang
510ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68
511ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0
512ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF
513ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16
514ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF
515ac500a1fSSandy Huang
516ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C
517ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31
518ac500a1fSSandy Huang #define BCSH_EN_MASK 1
519ac500a1fSSandy Huang
520a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_0 0xCA0
521a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_1 0xCA4
522a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_2 0xCA8
523a552a69cSDamon Ding
5246027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL 0xCD0
5256027c871SZhang Yubing #define POST_CSC_COE00_MASK 0xFFFF
5266027c871SZhang Yubing #define POST_CSC_COE00_SHIFT 16
5276027c871SZhang Yubing #define POST_R2Y_MODE_MASK 0x7
5286027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT 8
5296027c871SZhang Yubing #define POST_CSC_MODE_MASK 0x7
5306027c871SZhang Yubing #define POST_CSC_MODE_SHIFT 3
5316027c871SZhang Yubing #define POST_R2Y_EN_MASK 0x1
5326027c871SZhang Yubing #define POST_R2Y_EN_SHIFT 2
5336027c871SZhang Yubing #define POST_CSC_EN_MASK 0x1
5346027c871SZhang Yubing #define POST_CSC_EN_SHIFT 1
5356027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK 0x1
5366027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT 0
5376027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02 0xCD4
5386027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11 0xCD8
5396027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20 0xCDC
5406027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22 0xCE0
5416027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0 0xCE4
5426027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1 0xCE8
5436027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2 0xCEC
5446027c871SZhang Yubing
5450675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL 0xCF8
5460675a2a4SDamon Ding #define MCU_TYPE_SHIFT 31
5470675a2a4SDamon Ding #define MCU_BYPASS_SHIFT 30
5480675a2a4SDamon Ding #define MCU_RS_SHIFT 29
5490675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT 28
5500675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT 27
5510675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT 26
5520675a2a4SDamon Ding #define MCU_CLK_SEL_MASK 0x1
5530675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT 20
5540675a2a4SDamon Ding #define MCU_RW_PEND_MASK 0x3F
5550675a2a4SDamon Ding #define MCU_RW_PST_SHIFT 16
5560675a2a4SDamon Ding #define MCU_RW_PST_MASK 0xF
5570675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT 10
5580675a2a4SDamon Ding #define MCU_CS_PEND_MASK 0x3F
5590675a2a4SDamon Ding #define MCU_CS_PST_SHIFT 6
5600675a2a4SDamon Ding #define MCU_CS_PST_MASK 0xF
5610675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT 0
5620675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK 0x3F
5630675a2a4SDamon Ding
5640675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT 0xCFC
5650675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT 0
5660675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK 0xFFFFFFFF
5670675a2a4SDamon Ding
568d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00
569d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04
570d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08
571d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30
572d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34
573d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38
574d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C
575d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40
576d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34
577d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38
578d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44
579d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48
580d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C
581d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50
582d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54
583d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58
584d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C
585d0408543SAndy Yan
586d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00
587d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04
588d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08
589d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30
590d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34
591d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38
592d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C
593d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40
594d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34
595d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38
596d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44
597d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48
598d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C
599d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50
600d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54
601d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58
602d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C
603a552a69cSDamon Ding #define RK3568_VP2_BCSH_CTRL 0xE60
604a552a69cSDamon Ding #define RK3568_VP2_BCSH_BCS 0xE64
605a552a69cSDamon Ding #define RK3568_VP2_BCSH_H 0xE68
606a552a69cSDamon Ding #define RK3568_VP2_BCSH_COLOR_BAR 0xE6C
607a552a69cSDamon Ding #define RK3576_VP2_MCU_CTRL 0xEF8
608a552a69cSDamon Ding #define RK3576_VP2_MCU_RW_BYPASS_PORT 0xEFC
609d0408543SAndy Yan
610d0408543SAndy Yan /* Cluster0 register definition */
611d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000
612ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8
613ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9
614ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10
6151615d939SSandy Huang #define CLUSTER_RB_SWAP_SHIFT 14
616840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT 18
617d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004
6185fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12
6195fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14
6205fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14
6215fa6e665SDamon Ding #define AVG2_MASK 0x1
6225fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT 18
6235fa6e665SDamon Ding #define AVG4_MASK 0x1
6245fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT 19
6255fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22
6265fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT 24
6275fa6e665SDamon Ding #define XGT_MODE_MASK 0x3
6285fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT 25
6295fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT 27
630ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28
631ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29
632a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008
633a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK 0x1f
634a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT 0
635a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK 0x1f
636a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT 5
637a33b790fSDamon Ding
638d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010
639d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014
640d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018
641d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020
642d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024
643d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028
644d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030
645a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_CTRL 0x1040
646a552a69cSDamon Ding #define WIN0_ZME_DERING_EN_SHIFT 3
647a552a69cSDamon Ding #define WIN0_ZME_GATING_EN_SHIFT 31
648a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA 0x1044
649d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054
650d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058
651d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C
652d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060
653d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064
654d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068
655d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C
656a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT 7
657a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET 0x1078
658a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE 0x107C
659d0408543SAndy Yan
660d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080
661d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084
662d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090
663d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094
664d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098
665d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0
666d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4
667d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8
668d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0
669d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4
670d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8
671d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC
672d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0
673d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4
674d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8
675d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC
676a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET 0x10F8
677a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE 0x10FC
678d0408543SAndy Yan
679d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100
680ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0
681a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK 0x1
682a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT 13
683a552a69cSDamon Ding #define RK3576_CLUSTER0_PORT_SEL 0x11F4
684a552a69cSDamon Ding #define CLUSTER_PORT_SEL_SHIFT 0
685a552a69cSDamon Ding #define CLUSTER_PORT_SEL_MASK 0x3
686a552a69cSDamon Ding #define RK3576_CLUSTER0_DLY_NUM 0x11F8
687a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_SHIFT 0
688a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_MASK 0xff
689a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_SHIFT 0
690a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_MASK 0xff
691d0408543SAndy Yan
692d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200
693d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204
694d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210
695d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214
696d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218
697d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220
698d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224
699d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228
700d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230
701a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_CTRL 0x1240
702a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA 0x1244
703d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254
704d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258
705d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C
706d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260
707d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264
708d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268
709d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C
710a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET 0x1278
711a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE 0x127C
712d0408543SAndy Yan
713d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280
714d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284
715d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290
716d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294
717d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298
718d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0
719d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4
720d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8
721d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0
722d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4
723d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8
724d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC
725d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0
726d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4
727d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8
728d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC
729a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET 0x12F8
730a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE 0x12FC
731d0408543SAndy Yan
732d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300
733a552a69cSDamon Ding #define RK3576_CLUSTER1_PORT_SEL 0x13F4
734a552a69cSDamon Ding #define RK3576_CLUSTER1_DLY_NUM 0x13F8
735d0408543SAndy Yan
736d0408543SAndy Yan /* Esmart register definition */
737d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800
73810ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1
73910ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2
74010ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3
7415fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT 12
7425fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK 0x3
743d0408543SAndy Yan
744d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804
745a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK 0x1f
746a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT 4
747a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK 0x1f
748a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT 12
749d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31
750a33b790fSDamon Ding
751a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL 0x1808
752a33b790fSDamon Ding #define ESMART_AXI_ID_MASK 0x1
753a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT 1
754a33b790fSDamon Ding
755d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810
756d0408543SAndy Yan #define WIN_EN_SHIFT 0
757d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f
758d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1
759840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT 12
7605fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT 14
7615fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT 20
7625fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT 21
7635fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT 22
764d0408543SAndy Yan
765d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814
766d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818
767d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C
768d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820
769d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824
770d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828
771d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830
7723e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3
7733e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0
7743e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3
7753e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2
7763e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3
7773e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4
7783e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3
7793e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6
7803e39a5a1SSandy Huang
781d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834
782d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838
783d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C
784d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840
7853e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1
7863e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8
7873e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1
7883e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9
7893e39a5a1SSandy Huang
790d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844
791d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848
792d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C
793d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850
794d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854
795d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858
796d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860
797d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864
798d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868
799d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C
800d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870
801d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874
802d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878
803d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C
804d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880
805d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884
806d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888
807d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890
808d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894
809d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898
810d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C
811d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0
812d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4
813d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8
814d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC
815d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0
816d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4
817d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8
818d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0
819d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4
820d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8
821d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC
822a552a69cSDamon Ding #define RK3568_ESMART0_COLOR_KEY_CTRL 0x18D0
823a552a69cSDamon Ding #define RK3576_ESMART0_ALPHA_MAP 0x18D8
824a552a69cSDamon Ding #define RK3576_ESMART0_PORT_SEL 0x18F4
825a552a69cSDamon Ding #define ESMART_PORT_SEL_SHIFT 0
826a552a69cSDamon Ding #define ESMART_PORT_SEL_MASK 0x3
827a552a69cSDamon Ding #define RK3576_ESMART0_DLY_NUM 0x18F8
828d0408543SAndy Yan
829d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00
830d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04
831d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10
832d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14
833d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18
834d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C
835d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20
836d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24
837d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28
838d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30
839d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34
840d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38
841d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C
842d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40
843d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44
844d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48
845d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C
846d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50
847d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54
848d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58
849d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60
850d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64
851d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68
852d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C
853d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70
854d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74
855d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78
856d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C
857d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80
858d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84
859d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88
860d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90
861d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94
862d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98
863d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C
864d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0
865d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4
866d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8
867d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC
868d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0
869d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4
870d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8
871d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0
872d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4
873d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8
874d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC
875a552a69cSDamon Ding #define RK3576_ESMART1_ALPHA_MAP 0x1AD8
876a552a69cSDamon Ding #define RK3576_ESMART1_PORT_SEL 0x1AF4
877a552a69cSDamon Ding #define RK3576_ESMART1_DLY_NUM 0x1AF8
878d0408543SAndy Yan
879d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00
880d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04
881d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10
882d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14
883d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18
884d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C
885d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20
886d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24
887d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28
888d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30
889d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34
890d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38
891d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C
892d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40
893d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44
894d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48
895d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C
896d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50
897d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54
898d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58
899d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60
900d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64
901d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68
902d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C
903d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70
904d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74
905d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78
906d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C
907d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80
908d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84
909d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88
910d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90
911d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94
912d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98
913d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C
914d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0
915d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4
916d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8
917d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC
918d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0
919d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4
920d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8
921d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0
922d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4
923d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8
924d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC
925a552a69cSDamon Ding #define RK3576_ESMART2_ALPHA_MAP 0x1CD8
926a552a69cSDamon Ding #define RK3576_ESMART2_PORT_SEL 0x1CF4
927a552a69cSDamon Ding #define RK3576_ESMART2_DLY_NUM 0x1CF8
928d0408543SAndy Yan
929d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00
930d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04
931d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10
932d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14
933d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18
934d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C
935d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20
936d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24
937d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28
938d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30
939d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34
940d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38
941d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C
942d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40
943d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44
944d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48
945d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C
946d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50
947d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54
948d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58
949d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60
950d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64
951d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68
952d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C
953d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70
954d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74
955d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78
956d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C
957d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80
958d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84
959d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88
960d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90
961d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94
962d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98
963d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C
964d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0
965d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4
966d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8
967d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC
968d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0
969d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4
970d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8
971d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0
972d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4
973d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8
974d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC
975a552a69cSDamon Ding #define RK3576_ESMART3_ALPHA_MAP 0x1ED8
976a552a69cSDamon Ding #define RK3576_ESMART3_PORT_SEL 0x1EF4
977a552a69cSDamon Ding #define RK3576_ESMART3_DLY_NUM 0x1EF8
978d0408543SAndy Yan
97972388c26SDamon Ding /* HDR register definition */
98072388c26SDamon Ding #define RK3568_HDR_LUT_CTRL 0x2000
98172388c26SDamon Ding
98272388c26SDamon Ding #define RK3588_VP3_DSP_CTRL 0xF00
98372388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400
98472388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0 0x1600
98572388c26SDamon Ding
98612ee5af0SDamon Ding /* DSC 8K/4K register definition */
98712ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3 0x4000
98812ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0 0x40A0
98912ee5af0SDamon Ding #define DSC_EN_SHIFT 0
99012ee5af0SDamon Ding #define DSC_RBIT_SHIFT 2
99112ee5af0SDamon Ding #define DSC_RBYT_SHIFT 3
99212ee5af0SDamon Ding #define DSC_FLAL_SHIFT 4
99312ee5af0SDamon Ding #define DSC_MER_SHIFT 5
99412ee5af0SDamon Ding #define DSC_EPB_SHIFT 6
99512ee5af0SDamon Ding #define DSC_EPL_SHIFT 7
9961ace1b6dSDamon Ding #define DSC_NSLC_MASK 0x7
99712ee5af0SDamon Ding #define DSC_NSLC_SHIFT 16
99812ee5af0SDamon Ding #define DSC_SBO_SHIFT 28
99912ee5af0SDamon Ding #define DSC_IFEP_SHIFT 29
100012ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT 31
1001baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \
1002baf2c414SDamon Ding (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \
1003baf2c414SDamon Ding (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT))
100412ee5af0SDamon Ding
100512ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1 0x40A4
100612ee5af0SDamon Ding #define RK3588_DSC_8K_STS0 0x40A8
100712ee5af0SDamon Ding #define RK3588_DSC_8K_ERS 0x40C4
100812ee5af0SDamon Ding
100912ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3 0x4100
101012ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0 0x41A0
101112ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1 0x41A4
101212ee5af0SDamon Ding #define RK3588_DSC_4K_STS0 0x41A8
101312ee5af0SDamon Ding #define RK3588_DSC_4K_ERS 0x41C4
101412ee5af0SDamon Ding
101572388c26SDamon Ding /* RK3528 HDR register definition */
101672388c26SDamon Ding #define RK3528_HDR_LUT_CTRL 0x2000
101772388c26SDamon Ding
10186027c871SZhang Yubing /* RK3528 ACM register definition */
10196027c871SZhang Yubing #define RK3528_ACM_CTRL 0x6400
10206027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE 0x6404
10216027c871SZhang Yubing #define RK3528_ACM_FETCH_START 0x6408
10226027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE 0x6420
10236027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500
10246027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760
10256027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764
10266027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4
10276027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8
10286027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8
10296027c871SZhang Yubing
1030*60e6e79dSSandy Huang #define RK3568_IOMMU0_DTE_ADDR 0x7e00
1031*60e6e79dSSandy Huang #define RK3568_IOMMU0_STATUS 0x7e04
1032*60e6e79dSSandy Huang #define MMU_PAGING_EN BIT(0)
1033*60e6e79dSSandy Huang #define MMU_PAGE_FAULT_ACTIVE BIT(1)
1034*60e6e79dSSandy Huang #define RK3568_IOMMU0_COMMAND 0x7e08
1035*60e6e79dSSandy Huang #define MMU_ENABLE_PAGING 0
1036*60e6e79dSSandy Huang #define MMU_DISABLE_PAGING 1
1037*60e6e79dSSandy Huang #define MMU_FORCE_RESET 6
1038*60e6e79dSSandy Huang #define RK3568_IOMMU0_PAGEFAULT_ADDR 0x7e0c
1039*60e6e79dSSandy Huang
104045ec9215SDamon Ding /* RK3576 SHARP register definition */
104145ec9215SDamon Ding #define RK3576_SHARP_CTRL 0x0000
104245ec9215SDamon Ding #define SW_SHARP_ENABLE_SHIFT 0
104345ec9215SDamon Ding
1044d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0
1045d0408543SAndy Yan
1046452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON 0x10500
104752ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364
104852ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1
104952ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2
105052ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3
105152ee18acSSandy Huang
1052a552a69cSDamon Ding /* Base SYS_GRF: 0x2600a000*/
1053a552a69cSDamon Ding #define RK3576_SYS_GRF_MEMFAULT_STATUS0 0x0148
1054a552a69cSDamon Ding
1055a552a69cSDamon Ding /* Base IOC_GRF: 0x26040000 */
1056a552a69cSDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8 0x6420
1057a552a69cSDamon Ding #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT 9
1058a552a69cSDamon Ding #define RK3576_IOC_VOPLITE_SEL_SHIFT 11
1059a552a69cSDamon Ding
1060a552a69cSDamon Ding /* Base PMU2: 0x27380000 */
1061a552a69cSDamon Ding #define RK3576_PMU_PWR_GATE_STS 0x0230
1062a552a69cSDamon Ding #define PD_VOP_ESMART_DWN_STAT 12
1063a552a69cSDamon Ding #define PD_VOP_CLUSTER_DWN_STAT 13
1064a552a69cSDamon Ding #define RK3576_PMU_BISR_PDGEN_CON0 0x0510
1065a552a69cSDamon Ding #define PD_VOP_ESMART_REPAIR_ENA_SHIFT 12
1066a552a69cSDamon Ding #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT 13
1067a552a69cSDamon Ding #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0 0x0570
1068a552a69cSDamon Ding #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT 12
1069a552a69cSDamon Ding #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT 13
1070a552a69cSDamon Ding
10715d2768f7SDamon Ding #define RK3588_GRF_SOC_CON1 0x0304
10725d2768f7SDamon Ding #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT 14
10735d2768f7SDamon Ding
1074ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008
1075ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0
1076ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1
10772e42aca5SDamon Ding #define RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT 2
1078ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3
1079ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4
10802e42aca5SDamon Ding #define RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT 5
1081ecc31b6eSAndy Yan
1082b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0 0x0000
1083b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK 0x3
1084b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT 5
1085b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT 7
1086b890760eSAlgea Cao
108760e469f5SDamon Ding #define RK3588_PMU_BISR_CON3 0x20C
108860e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9
108960e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10
109060e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11
109160e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12
1092b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13
1093b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14
109460e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15
109560e469f5SDamon Ding
109660e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5 0x294
109760e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9
109860e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10
109960e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11
110060e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12
1101b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13
1102b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14
110360e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15
110460e469f5SDamon Ding
1105d0408543SAndy Yan #define VOP2_LAYER_MAX 8
110663cb669fSSandy Huang
1107ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH 4096
1108ee01dbb2SDamon Ding
1109631ee99aSZhang Yubing /* KHz */
1110631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE 600000
1111631ee99aSZhang Yubing
1112b6ba80b4SDamon Ding /*
1113b6ba80b4SDamon Ding * vop2 dsc id
1114b6ba80b4SDamon Ding */
1115b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K 0
1116b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K 1
1117b6ba80b4SDamon Ding
1118b6ba80b4SDamon Ding /*
1119b6ba80b4SDamon Ding * vop2 internal power domain id,
1120b6ba80b4SDamon Ding * should be all none zero, 0 will be
1121b6ba80b4SDamon Ding * treat as invalid;
1122b6ba80b4SDamon Ding */
1123b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0 BIT(0)
1124b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1 BIT(1)
1125b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2 BIT(2)
1126b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3 BIT(3)
1127b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K BIT(5)
1128b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K BIT(6)
1129b6ba80b4SDamon Ding #define VOP2_PD_ESMART BIT(7)
1130a552a69cSDamon Ding #define VOP2_PD_CLUSTER BIT(8)
1131b6ba80b4SDamon Ding
11324c765862SDamon Ding #define VOP2_PLANE_NO_SCALING BIT(16)
11334c765862SDamon Ding
11345fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT BIT(0)
11355fa6e665SDamon Ding #define VOP_FEATURE_AFBDC BIT(1)
11365fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE BIT(2)
11375fa6e665SDamon Ding #define VOP_FEATURE_HDR10 BIT(3)
11385fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR BIT(4)
11395fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */
11405fa6e665SDamon Ding #define VOP_FEATURE_SPLICE BIT(5)
11415fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN BIT(6)
11426027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR BIT(7)
11436027c871SZhang Yubing #define VOP_FEATURE_POST_ACM BIT(8)
11446027c871SZhang Yubing #define VOP_FEATURE_POST_CSC BIT(9)
1145a552a69cSDamon Ding #define VOP_FEATURE_POST_FRC_V2 BIT(10)
1146a552a69cSDamon Ding #define VOP_FEATURE_POST_SHARP BIT(11)
11475fa6e665SDamon Ding
11485fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR BIT(0)
11495fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR BIT(1)
11505fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY BIT(2)
11515fa6e665SDamon Ding #define WIN_FEATURE_AFBDC BIT(3)
11525fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN BIT(4)
11535fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB BIT(5)
11545fa6e665SDamon Ding /* a mirror win can only get fb address
11555fa6e665SDamon Ding * from source win:
11565fa6e665SDamon Ding * Cluster1---->Cluster0
11575fa6e665SDamon Ding * Esmart1 ---->Esmart0
11585fa6e665SDamon Ding * Smart1 ---->Smart0
11595fa6e665SDamon Ding * This is a feather on rk3566
11605fa6e665SDamon Ding */
11615fa6e665SDamon Ding #define WIN_FEATURE_MIRROR BIT(6)
11625fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA BIT(7)
11635fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8)
1164a552a69cSDamon Ding #define WIN_FEATURE_DCI BIT(9)
11655fa6e665SDamon Ding
11665fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F 0xfe
11675fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F 0xff
11685fa6e665SDamon Ding
11695fa6e665SDamon Ding enum vop_csc_format {
117010ee9f5bSAlgea Cao CSC_BT601L,
117110ee9f5bSAlgea Cao CSC_BT709L,
117210ee9f5bSAlgea Cao CSC_BT601F,
1173df0a5c43SDamon Ding CSC_BT2020L,
11745fa6e665SDamon Ding CSC_BT709L_13BIT,
11755fa6e665SDamon Ding CSC_BT709F_13BIT,
11765fa6e665SDamon Ding CSC_BT2020L_13BIT,
11775fa6e665SDamon Ding CSC_BT2020F_13BIT,
11785fa6e665SDamon Ding };
11795fa6e665SDamon Ding
11805fa6e665SDamon Ding enum vop_csc_bit_depth {
11815fa6e665SDamon Ding CSC_10BIT_DEPTH,
11825fa6e665SDamon Ding CSC_13BIT_DEPTH,
118310ee9f5bSAlgea Cao };
118410ee9f5bSAlgea Cao
118510ee9f5bSAlgea Cao enum vop2_pol {
118610ee9f5bSAlgea Cao HSYNC_POSITIVE = 0,
118710ee9f5bSAlgea Cao VSYNC_POSITIVE = 1,
118810ee9f5bSAlgea Cao DEN_NEGATIVE = 2,
118910ee9f5bSAlgea Cao DCLK_INVERT = 3
119010ee9f5bSAlgea Cao };
119110ee9f5bSAlgea Cao
1192ac500a1fSSandy Huang enum vop2_bcsh_out_mode {
1193ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK,
1194ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE,
1195ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR,
1196ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO,
1197ac500a1fSSandy Huang };
1198ac500a1fSSandy Huang
1199d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \
1200d0408543SAndy Yan { \
1201d0408543SAndy Yan .offset = off, \
1202d0408543SAndy Yan .mask = _mask, \
1203d0408543SAndy Yan .shift = _shift, \
1204d0408543SAndy Yan .write_mask = _write_mask, \
1205d0408543SAndy Yan }
1206d0408543SAndy Yan
1207d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \
1208d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false)
1209d0408543SAndy Yan enum dither_down_mode {
1210d0408543SAndy Yan RGB888_TO_RGB565 = 0x0,
1211d0408543SAndy Yan RGB888_TO_RGB666 = 0x1
1212d0408543SAndy Yan };
1213d0408543SAndy Yan
1214a552a69cSDamon Ding enum dither_down_mode_sel {
1215a552a69cSDamon Ding DITHER_DOWN_ALLEGRO = 0x0,
1216a552a69cSDamon Ding DITHER_DOWN_FRC = 0x1
1217a552a69cSDamon Ding };
1218a552a69cSDamon Ding
1219d0408543SAndy Yan enum vop2_video_ports_id {
1220d0408543SAndy Yan VOP2_VP0,
1221d0408543SAndy Yan VOP2_VP1,
1222d0408543SAndy Yan VOP2_VP2,
1223d0408543SAndy Yan VOP2_VP3,
1224d0408543SAndy Yan VOP2_VP_MAX,
1225d0408543SAndy Yan };
1226d0408543SAndy Yan
1227ee008497SSandy Huang enum vop2_layer_type {
1228ee008497SSandy Huang CLUSTER_LAYER = 0,
1229ee008497SSandy Huang ESMART_LAYER = 1,
1230ee008497SSandy Huang SMART_LAYER = 2,
1231ee008497SSandy Huang };
1232ee008497SSandy Huang
12336fea745cSDamon Ding enum vop2_plane_type {
12346fea745cSDamon Ding VOP2_PLANE_TYPE_OVERLAY = 0,
12356fea745cSDamon Ding VOP2_PLANE_TYPE_PRIMARY = 1,
12366fea745cSDamon Ding VOP2_PLANE_TYPE_CURSOR = 2,
12376fea745cSDamon Ding };
12386fea745cSDamon Ding
1239b0989546SSandy Huang /* This define must same with kernel win phy id */
1240b0989546SSandy Huang enum vop2_layer_phy_id {
1241b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0,
1242b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1,
1243b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0,
1244b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1,
1245b0989546SSandy Huang ROCKCHIP_VOP2_SMART0,
1246b0989546SSandy Huang ROCKCHIP_VOP2_SMART1,
1247b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2,
1248b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3,
1249b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2,
1250b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3,
1251ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX,
1252a7cb29b7SDamon Ding ROCKCHIP_VOP2_PHY_ID_INVALID = (u8)-1,
1253d0408543SAndy Yan };
1254d0408543SAndy Yan
12553e39a5a1SSandy Huang enum vop2_scale_up_mode {
12563e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR,
12573e39a5a1SSandy Huang VOP2_SCALE_UP_BIL,
12583e39a5a1SSandy Huang VOP2_SCALE_UP_BIC,
1259a552a69cSDamon Ding VOP2_SCALE_UP_ZME,
12603e39a5a1SSandy Huang };
12613e39a5a1SSandy Huang
12623e39a5a1SSandy Huang enum vop2_scale_down_mode {
12633e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR,
12643e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL,
12653e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG,
1266a552a69cSDamon Ding VOP2_SCALE_DOWN_ZME,
12673e39a5a1SSandy Huang };
12683e39a5a1SSandy Huang
12693e39a5a1SSandy Huang enum scale_mode {
12703e39a5a1SSandy Huang SCALE_NONE = 0x0,
12713e39a5a1SSandy Huang SCALE_UP = 0x1,
12723e39a5a1SSandy Huang SCALE_DOWN = 0x2
12733e39a5a1SSandy Huang };
12743e39a5a1SSandy Huang
127512ee5af0SDamon Ding enum vop_dsc_interface_mode {
127612ee5af0SDamon Ding VOP_DSC_IF_DISABLE = 0,
127712ee5af0SDamon Ding VOP_DSC_IF_HDMI = 1,
127812ee5af0SDamon Ding VOP_DSC_IF_MIPI_DS_MODE = 2,
127912ee5af0SDamon Ding VOP_DSC_IF_MIPI_VIDEO_MODE = 3,
128012ee5af0SDamon Ding };
128112ee5af0SDamon Ding
12825fa6e665SDamon Ding enum vop3_pre_scale_down_mode {
12835fa6e665SDamon Ding VOP3_PRE_SCALE_UNSPPORT,
12845fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_GT,
12855fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_AVG,
12865fa6e665SDamon Ding };
12875fa6e665SDamon Ding
12889c7848c3SDamon Ding /*
12899c7848c3SDamon Ding * the delay number of a window in different mode.
12909c7848c3SDamon Ding */
12919c7848c3SDamon Ding enum vop2_win_dly_mode {
12929c7848c3SDamon Ding VOP2_DLY_MODE_DEFAULT, /* default mode */
12939c7848c3SDamon Ding VOP2_DLY_MODE_HISO_S, /* HDR in SDR out mode, as a SDR window */
12949c7848c3SDamon Ding VOP2_DLY_MODE_HIHO_H, /* HDR in HDR out mode, as a HDR window */
12959c7848c3SDamon Ding VOP2_DLY_MODE_DOVI_IN_CORE1, /* dovi video input, as dovi core1 */
12969c7848c3SDamon Ding VOP2_DLY_MODE_DOVI_IN_CORE2, /* dovi video input, as dovi core2 */
12979c7848c3SDamon Ding VOP2_DLY_MODE_NONDOVI_IN_CORE1, /* ndovi video input, as dovi core1 */
12989c7848c3SDamon Ding VOP2_DLY_MODE_NONDOVI_IN_CORE2, /* ndovi video input, as dovi core2 */
12999c7848c3SDamon Ding VOP2_DLY_MODE_MAX,
13009c7848c3SDamon Ding };
13019c7848c3SDamon Ding
13025fa6e665SDamon Ding enum vop3_esmart_lb_mode {
13035fa6e665SDamon Ding VOP3_ESMART_8K_MODE,
13045fa6e665SDamon Ding VOP3_ESMART_4K_4K_MODE,
13055fa6e665SDamon Ding VOP3_ESMART_4K_2K_2K_MODE,
13065fa6e665SDamon Ding VOP3_ESMART_2K_2K_2K_2K_MODE,
1307a552a69cSDamon Ding VOP3_ESMART_4K_4K_4K_MODE,
1308a552a69cSDamon Ding VOP3_ESMART_4K_4K_2K_2K_MODE,
13095fa6e665SDamon Ding };
13105fa6e665SDamon Ding
13113e39a5a1SSandy Huang struct vop2_layer {
13123e39a5a1SSandy Huang u8 id;
13133e39a5a1SSandy Huang /**
13143e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected.
13153e39a5a1SSandy Huang * Every layer must make sure to select different
13163e39a5a1SSandy Huang * windows of others.
13173e39a5a1SSandy Huang */
13183e39a5a1SSandy Huang u8 win_phys_id;
13193e39a5a1SSandy Huang };
13203e39a5a1SSandy Huang
132160e469f5SDamon Ding struct vop2_power_domain_data {
1322a552a69cSDamon Ding u16 id;
1323a552a69cSDamon Ding u16 parent_id;
1324b6ba80b4SDamon Ding /*
1325b6ba80b4SDamon Ding * @module_id_mask: module id of which module this power domain is belongs to.
1326b6ba80b4SDamon Ding * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3
1327b6ba80b4SDamon Ding */
1328b6ba80b4SDamon Ding u32 module_id_mask;
132960e469f5SDamon Ding };
133060e469f5SDamon Ding
1331b0989546SSandy Huang struct vop2_win_data {
1332b0989546SSandy Huang char *name;
133363cb669fSSandy Huang u8 phys_id;
1334ecc31b6eSAndy Yan enum vop2_layer_type type;
13356fea745cSDamon Ding enum vop2_plane_type plane_type;
1336b0989546SSandy Huang u8 win_sel_port_offset;
13375fa6e665SDamon Ding u8 layer_sel_win_id[VOP2_VP_MAX];
1338a33b790fSDamon Ding u8 axi_id;
1339a33b790fSDamon Ding u8 axi_uv_id;
1340a33b790fSDamon Ding u8 axi_yrgb_id;
1341ee01dbb2SDamon Ding u8 splice_win_id;
13425fa6e665SDamon Ding u8 hsu_filter_mode;
13435fa6e665SDamon Ding u8 hsd_filter_mode;
13445fa6e665SDamon Ding u8 vsu_filter_mode;
13455fa6e665SDamon Ding u8 vsd_filter_mode;
13465fa6e665SDamon Ding u8 hsd_pre_filter_mode;
13475fa6e665SDamon Ding u8 vsd_pre_filter_mode;
13485fa6e665SDamon Ding u8 scale_engine_num;
13491c9572c7SDamon Ding u8 source_win_id;
135013bc92e8SDamon Ding u8 possible_vp_mask;
13519c7848c3SDamon Ding u8 dly[VOP2_DLY_MODE_MAX];
1352a552a69cSDamon Ding u16 pd_id;
1353b0989546SSandy Huang u32 reg_offset;
13544c765862SDamon Ding u32 max_upscale_factor;
13554c765862SDamon Ding u32 max_downscale_factor;
13561c9572c7SDamon Ding u32 feature;
1357a552a69cSDamon Ding u32 supported_rotations;
1358ee01dbb2SDamon Ding bool splice_mode_right;
135963cb669fSSandy Huang };
136063cb669fSSandy Huang
136163cb669fSSandy Huang struct vop2_vp_data {
136263cb669fSSandy Huang u32 feature;
136344b1b62cSDamon Ding u32 max_dclk;
136463cb669fSSandy Huang u8 pre_scan_max_dly;
1365452afb13SDamon Ding u8 layer_mix_dly;
1366a552a69cSDamon Ding u8 hdrvivid_dly;
1367a552a69cSDamon Ding u8 sdr2hdr_dly;
1368452afb13SDamon Ding u8 hdr_mix_dly;
1369452afb13SDamon Ding u8 win_dly;
1370ee01dbb2SDamon Ding u8 splice_vp_id;
1371a552a69cSDamon Ding u8 pixel_rate;
137263cb669fSSandy Huang struct vop_rect max_output;
137344b1b62cSDamon Ding struct vop_urgency *urgency;
1374d0408543SAndy Yan };
1375d0408543SAndy Yan
1376b0989546SSandy Huang struct vop2_vp_plane_mask {
1377b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */
1378b4fa21deSDamon Ding u8 cursor_plane_id;
1379b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */
1380b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */
1381b0989546SSandy Huang u32 plane_mask;
1382b0989546SSandy Huang };
1383b0989546SSandy Huang
138412ee5af0SDamon Ding struct vop2_dsc_data {
138512ee5af0SDamon Ding u8 id;
138612ee5af0SDamon Ding u8 max_slice_num;
138712ee5af0SDamon Ding u8 max_linebuf_depth; /* used to generate the bitstream */
138812ee5af0SDamon Ding u8 min_bits_per_pixel; /* bit num after encoder compress */
1389a552a69cSDamon Ding u16 pd_id;
139012ee5af0SDamon Ding const char *dsc_txp_clk_src_name;
139112ee5af0SDamon Ding const char *dsc_txp_clk_name;
139212ee5af0SDamon Ding const char *dsc_pxl_clk_name;
139312ee5af0SDamon Ding const char *dsc_cds_clk_name;
139412ee5af0SDamon Ding };
139512ee5af0SDamon Ding
139612ee5af0SDamon Ding struct dsc_error_info {
139712ee5af0SDamon Ding u32 dsc_error_val;
139812ee5af0SDamon Ding char dsc_error_info[50];
139912ee5af0SDamon Ding };
140012ee5af0SDamon Ding
140172388c26SDamon Ding struct vop2_dump_regs {
140272388c26SDamon Ding u32 offset;
140372388c26SDamon Ding const char *name;
140472388c26SDamon Ding u32 state_base;
140572388c26SDamon Ding u32 state_mask;
140672388c26SDamon Ding u32 state_shift;
140772388c26SDamon Ding bool enable_state;
1408a552a69cSDamon Ding u32 size;
1409a552a69cSDamon Ding };
1410a552a69cSDamon Ding
1411a552a69cSDamon Ding struct vop2_esmart_lb_map {
1412a552a69cSDamon Ding u8 lb_mode;
1413a552a69cSDamon Ding u8 lb_map_value;
141472388c26SDamon Ding };
141572388c26SDamon Ding
14169c7848c3SDamon Ding /**
14179c7848c3SDamon Ding * struct vop2_ops - helper operations for vop2 hardware
14189c7848c3SDamon Ding *
14199c7848c3SDamon Ding * These hooks are used by the common part of the vop2 driver to
14209c7848c3SDamon Ding * implement the proper behaviour of different variants.
14219c7848c3SDamon Ding */
14229c7848c3SDamon Ding struct vop2_ops {
1423b888dbc8SSandy Huang void (*setup_win_dly)(struct display_state *state, int crtc_id, u8 plane_phy_id);
1424b7195f56SDamon Ding void (*setup_overlay)(struct display_state *state);
1425ef0607a7SDamon Ding void (*assign_plane_mask)(struct display_state *state);
14269c7848c3SDamon Ding };
14279c7848c3SDamon Ding
1428d0408543SAndy Yan struct vop2_data {
142952ee18acSSandy Huang u32 version;
14305fa6e665SDamon Ding u32 esmart_lb_mode;
143163cb669fSSandy Huang struct vop2_vp_data *vp_data;
1432b0989546SSandy Huang struct vop2_win_data *win_data;
1433b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask;
1434b6ba80b4SDamon Ding struct vop2_power_domain_data *pd;
143512ee5af0SDamon Ding struct vop2_dsc_data *dsc;
143612ee5af0SDamon Ding struct dsc_error_info *dsc_error_ecw;
143712ee5af0SDamon Ding struct dsc_error_info *dsc_error_buffer_flow;
143872388c26SDamon Ding struct vop2_dump_regs *dump_regs;
1439a552a69cSDamon Ding const struct vop2_esmart_lb_map *esmart_lb_mode_map;
14409c7848c3SDamon Ding const struct vop2_ops *ops;
144163cb669fSSandy Huang u8 nr_vps;
144263cb669fSSandy Huang u8 nr_layers;
144363cb669fSSandy Huang u8 nr_mixers;
14441147facaSSandy Huang u8 nr_gammas;
1445b6ba80b4SDamon Ding u8 nr_pd;
144612ee5af0SDamon Ding u8 nr_dscs;
144712ee5af0SDamon Ding u8 nr_dsc_ecw;
144812ee5af0SDamon Ding u8 nr_dsc_buffer_flow;
1449a552a69cSDamon Ding u8 esmart_lb_mode_num;
1450ecc31b6eSAndy Yan u32 reg_len;
145172388c26SDamon Ding u32 dump_regs_size;
14526fea745cSDamon Ding u32 plane_mask_base;
1453d0408543SAndy Yan };
1454d0408543SAndy Yan
1455d0408543SAndy Yan struct vop2 {
1456d0408543SAndy Yan u32 *regsbak;
1457d0408543SAndy Yan void *regs;
1458d0408543SAndy Yan void *grf;
1459ecc31b6eSAndy Yan void *vop_grf;
1460ecc31b6eSAndy Yan void *vo1_grf;
146160e469f5SDamon Ding void *sys_pmu;
1462a552a69cSDamon Ding void *ioc_grf;
146345ec9215SDamon Ding void *sharp_res;
146452ee18acSSandy Huang u32 reg_len;
146552ee18acSSandy Huang u32 version;
14665fa6e665SDamon Ding u32 esmart_lb_mode;
146763cb669fSSandy Huang bool global_init;
1468a552a69cSDamon Ding bool merge_irq;
1469d0408543SAndy Yan const struct vop2_data *data;
1470b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX];
1471d0408543SAndy Yan };
1472d0408543SAndy Yan
1473d0408543SAndy Yan static struct vop2 *rockchip_vop2;
14745fa6e665SDamon Ding
147527cec8e2SDamon Ding /* vop2_layer_phy_id */
147627cec8e2SDamon Ding static const char *const vop2_layer_name_list[] = {
147727cec8e2SDamon Ding "Cluster0",
147827cec8e2SDamon Ding "Cluster1",
147927cec8e2SDamon Ding "Esmart0",
148027cec8e2SDamon Ding "Esmart1",
148127cec8e2SDamon Ding "Smart0",
148227cec8e2SDamon Ding "Smart1",
148327cec8e2SDamon Ding "Cluster2",
148427cec8e2SDamon Ding "Cluster3",
148527cec8e2SDamon Ding "Esmart2",
148627cec8e2SDamon Ding "Esmart3",
148727cec8e2SDamon Ding };
148827cec8e2SDamon Ding
vop2_plane_phys_id_to_string(u8 phys_id)1489a7cb29b7SDamon Ding static inline const char *vop2_plane_phys_id_to_string(u8 phys_id)
149027cec8e2SDamon Ding {
1491a7cb29b7SDamon Ding if (phys_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
149227cec8e2SDamon Ding return "INVALID";
149327cec8e2SDamon Ding
1494a7cb29b7SDamon Ding if (phys_id >= ARRAY_SIZE(vop2_layer_name_list))
149527cec8e2SDamon Ding return NULL;
149627cec8e2SDamon Ding
1497a7cb29b7SDamon Ding return vop2_layer_name_list[phys_id];
149827cec8e2SDamon Ding }
149927cec8e2SDamon Ding
is_vop3(struct vop2 * vop2)15005fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2)
15015fa6e665SDamon Ding {
15025fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588)
15035fa6e665SDamon Ding return false;
15045fa6e665SDamon Ding else
15055fa6e665SDamon Ding return true;
15065fa6e665SDamon Ding }
15075fa6e665SDamon Ding
15083e39a5a1SSandy Huang /*
15093e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12;
15103e39a5a1SSandy Huang * avg_sd_factor:
15113e39a5a1SSandy Huang * bli_su_factor:
15123e39a5a1SSandy Huang * bic_su_factor:
15133e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16;
15143e39a5a1SSandy Huang *
15155fa6e665SDamon Ding * ygt2 enable: dst get one line from two line of the src
15165fa6e665SDamon Ding * ygt4 enable: dst get one line from four line of the src.
15173e39a5a1SSandy Huang *
15183e39a5a1SSandy Huang */
15193e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1))
15203e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1))
15213e39a5a1SSandy Huang
15223e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \
15233e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1))
15243e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \
15253e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1))
15265fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \
15275fa6e665SDamon Ding (fac * (dst - 1) >> 16 < (src - 1))
15283e39a5a1SSandy Huang
vop2_scale_factor(enum scale_mode mode,int32_t filter_mode,uint32_t src,uint32_t dst)15293e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode,
15303e39a5a1SSandy Huang int32_t filter_mode,
15313e39a5a1SSandy Huang uint32_t src, uint32_t dst)
15323e39a5a1SSandy Huang {
15333e39a5a1SSandy Huang uint32_t fac = 0;
15343e39a5a1SSandy Huang int i = 0;
15353e39a5a1SSandy Huang
15363e39a5a1SSandy Huang if (mode == SCALE_NONE)
15373e39a5a1SSandy Huang return 0;
15383e39a5a1SSandy Huang
15393e39a5a1SSandy Huang /*
15403e39a5a1SSandy Huang * A workaround to avoid zero div.
15413e39a5a1SSandy Huang */
15423e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) {
15433e39a5a1SSandy Huang dst = dst + 1;
15443e39a5a1SSandy Huang src = src + 1;
15453e39a5a1SSandy Huang }
15463e39a5a1SSandy Huang
15473e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
15483e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst);
15493e39a5a1SSandy Huang for (i = 0; i < 100; i++) {
15503e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
15513e39a5a1SSandy Huang break;
15523e39a5a1SSandy Huang fac -= 1;
15533e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15543e39a5a1SSandy Huang }
15553e39a5a1SSandy Huang } else {
15563e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst);
15573e39a5a1SSandy Huang for (i = 0; i < 100; i++) {
15583e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac))
15593e39a5a1SSandy Huang break;
15603e39a5a1SSandy Huang fac -= 1;
15613e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15623e39a5a1SSandy Huang }
15633e39a5a1SSandy Huang }
15643e39a5a1SSandy Huang
15653e39a5a1SSandy Huang return fac;
15663e39a5a1SSandy Huang }
15673e39a5a1SSandy Huang
vop3_scale_up_fac_check(uint32_t src,uint32_t dst,uint32_t fac,bool is_hor)15685fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor)
15695fa6e665SDamon Ding {
15705fa6e665SDamon Ding if (is_hor)
15715fa6e665SDamon Ding return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac);
15725fa6e665SDamon Ding return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac);
15735fa6e665SDamon Ding }
15745fa6e665SDamon Ding
vop3_scale_factor(enum scale_mode mode,uint32_t src,uint32_t dst,bool is_hor)15755fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode,
15765fa6e665SDamon Ding uint32_t src, uint32_t dst, bool is_hor)
15775fa6e665SDamon Ding {
15785fa6e665SDamon Ding uint32_t fac = 0;
15795fa6e665SDamon Ding int i = 0;
15805fa6e665SDamon Ding
15815fa6e665SDamon Ding if (mode == SCALE_NONE)
15825fa6e665SDamon Ding return 0;
15835fa6e665SDamon Ding
15845fa6e665SDamon Ding /*
15855fa6e665SDamon Ding * A workaround to avoid zero div.
15865fa6e665SDamon Ding */
15875fa6e665SDamon Ding if ((dst == 1) || (src == 1)) {
15885fa6e665SDamon Ding dst = dst + 1;
15895fa6e665SDamon Ding src = src + 1;
15905fa6e665SDamon Ding }
15915fa6e665SDamon Ding
15925fa6e665SDamon Ding if (mode == SCALE_DOWN) {
15935fa6e665SDamon Ding fac = VOP2_BILI_SCL_DN(src, dst);
15945fa6e665SDamon Ding for (i = 0; i < 100; i++) {
15955fa6e665SDamon Ding if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac))
15965fa6e665SDamon Ding break;
15975fa6e665SDamon Ding fac -= 1;
15985fa6e665SDamon Ding printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
15995fa6e665SDamon Ding }
16005fa6e665SDamon Ding } else {
16015fa6e665SDamon Ding fac = VOP2_COMMON_SCL(src, dst);
16025fa6e665SDamon Ding for (i = 0; i < 100; i++) {
16035fa6e665SDamon Ding if (vop3_scale_up_fac_check(src, dst, fac, is_hor))
16045fa6e665SDamon Ding break;
16055fa6e665SDamon Ding fac -= 1;
16065fa6e665SDamon Ding printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
16075fa6e665SDamon Ding }
16085fa6e665SDamon Ding }
16095fa6e665SDamon Ding
16105fa6e665SDamon Ding return fac;
16115fa6e665SDamon Ding }
16125fa6e665SDamon Ding
scl_get_scl_mode(int src,int dst)16133e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst)
16143e39a5a1SSandy Huang {
16153e39a5a1SSandy Huang if (src < dst)
16163e39a5a1SSandy Huang return SCALE_UP;
16173e39a5a1SSandy Huang else if (src > dst)
16183e39a5a1SSandy Huang return SCALE_DOWN;
16193e39a5a1SSandy Huang
16203e39a5a1SSandy Huang return SCALE_NONE;
16213e39a5a1SSandy Huang }
1622d0408543SAndy Yan
interpolate(int x1,int y1,int x2,int y2,int x)1623ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x)
1624ac500a1fSSandy Huang {
1625ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
1626ac500a1fSSandy Huang }
1627ac500a1fSSandy Huang
vop2_win_can_attach_to_vp(struct vop2_win_data * win_data,u8 vp_id)16286fea745cSDamon Ding static inline bool vop2_win_can_attach_to_vp(struct vop2_win_data *win_data, u8 vp_id)
1629b0989546SSandy Huang {
16306fea745cSDamon Ding return win_data->possible_vp_mask & BIT(vp_id);
1631ecc31b6eSAndy Yan }
1632b0989546SSandy Huang
vop2_vp_find_attachable_win(struct display_state * state,u8 vp_id)16336fea745cSDamon Ding static int vop2_vp_find_attachable_win(struct display_state *state, u8 vp_id)
16346fea745cSDamon Ding {
16356fea745cSDamon Ding struct crtc_state *cstate = &state->crtc_state;
16366fea745cSDamon Ding struct vop2 *vop2 = cstate->private;
16376fea745cSDamon Ding u32 plane_mask = cstate->crtc->vps[vp_id].plane_mask;
16386fea745cSDamon Ding int i = 0;
16396fea745cSDamon Ding
16406fea745cSDamon Ding if (!plane_mask)
16416fea745cSDamon Ding return ROCKCHIP_VOP2_PHY_ID_INVALID;
16426fea745cSDamon Ding
16436fea745cSDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) {
16446fea745cSDamon Ding if (vop2_win_can_attach_to_vp(&vop2->data->win_data[i], vp_id))
16456fea745cSDamon Ding break;
16466fea745cSDamon Ding }
16476fea745cSDamon Ding
16486fea745cSDamon Ding return vop2->data->win_data[i].phys_id;
1649b0989546SSandy Huang }
1650b0989546SSandy Huang
scl_cal_scale(int src,int dst,int shift)165163cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift)
1652d0408543SAndy Yan {
1653d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
1654d0408543SAndy Yan }
1655d0408543SAndy Yan
scl_cal_scale2(int src,int dst)165663cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst)
1657d0408543SAndy Yan {
1658d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1);
1659d0408543SAndy Yan }
1660d0408543SAndy Yan
vop2_writel(struct vop2 * vop2,u32 offset,u32 v)166152ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
1662d0408543SAndy Yan {
1663d0408543SAndy Yan writel(v, vop2->regs + offset);
1664d0408543SAndy Yan vop2->regsbak[offset >> 2] = v;
1665d0408543SAndy Yan }
1666d0408543SAndy Yan
vop2_readl(struct vop2 * vop2,u32 offset)166752ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
1668d0408543SAndy Yan {
1669d0408543SAndy Yan return readl(vop2->regs + offset);
1670d0408543SAndy Yan }
1671d0408543SAndy Yan
vop2_mask_write(struct vop2 * vop2,u32 offset,u32 mask,u32 shift,u32 v,bool write_mask)167252ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset,
167352ee18acSSandy Huang u32 mask, u32 shift, u32 v,
1674d0408543SAndy Yan bool write_mask)
1675d0408543SAndy Yan {
1676d0408543SAndy Yan if (!mask)
1677d0408543SAndy Yan return;
1678d0408543SAndy Yan
1679d0408543SAndy Yan if (write_mask) {
1680d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16));
1681d0408543SAndy Yan } else {
168252ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2];
1683d0408543SAndy Yan
1684d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
1685d0408543SAndy Yan vop2->regsbak[offset >> 2] = v;
1686d0408543SAndy Yan }
1687d0408543SAndy Yan
1688d0408543SAndy Yan writel(v, vop2->regs + offset);
1689d0408543SAndy Yan }
1690d0408543SAndy Yan
vop2_grf_writel(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift,u32 v)1691ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset,
169252ee18acSSandy Huang u32 mask, u32 shift, u32 v)
169352ee18acSSandy Huang {
169452ee18acSSandy Huang u32 val = 0;
169552ee18acSSandy Huang
169652ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16));
1697ecc31b6eSAndy Yan writel(val, grf_base + offset);
169852ee18acSSandy Huang }
169952ee18acSSandy Huang
vop2_grf_readl(struct vop2 * vop,void * grf_base,u32 offset,u32 mask,u32 shift)170060e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset,
170160e469f5SDamon Ding u32 mask, u32 shift)
170260e469f5SDamon Ding {
170360e469f5SDamon Ding return (readl(grf_base + offset) >> shift) & mask;
170460e469f5SDamon Ding }
170560e469f5SDamon Ding
is_yuv_output(u32 bus_format)170652ee18acSSandy Huang static bool is_yuv_output(u32 bus_format)
1707d0408543SAndy Yan {
1708d0408543SAndy Yan switch (bus_format) {
1709d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24:
1710d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30:
1711034a46b5SAlgea Cao case MEDIA_BUS_FMT_YUYV10_1X20:
1712d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
1713d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
1714a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8:
1715a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8:
1716a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8:
1717a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8:
1718a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16:
1719a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16:
1720a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16:
1721a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16:
1722d0408543SAndy Yan return true;
1723d0408543SAndy Yan default:
1724d0408543SAndy Yan return false;
1725d0408543SAndy Yan }
1726d0408543SAndy Yan }
1727d0408543SAndy Yan
vop2_convert_csc_mode(enum drm_color_encoding color_encoding,enum drm_color_range color_range,int bit_depth)1728df0a5c43SDamon Ding static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding,
1729df0a5c43SDamon Ding enum drm_color_range color_range,
1730df0a5c43SDamon Ding int bit_depth)
173110ee9f5bSAlgea Cao {
1732df0a5c43SDamon Ding bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0;
1733df0a5c43SDamon Ding enum vop_csc_format csc_mode = CSC_BT709L;
1734df0a5c43SDamon Ding
1735df0a5c43SDamon Ding
1736df0a5c43SDamon Ding switch (color_encoding) {
1737df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT601:
1738df0a5c43SDamon Ding if (full_range)
1739df0a5c43SDamon Ding csc_mode = CSC_BT601F;
17405fa6e665SDamon Ding else
1741df0a5c43SDamon Ding csc_mode = CSC_BT601L;
1742df0a5c43SDamon Ding break;
1743df0a5c43SDamon Ding
1744df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT709:
1745df0a5c43SDamon Ding if (full_range) {
1746df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F;
1747df0a5c43SDamon Ding if (bit_depth != CSC_13BIT_DEPTH)
1748df0a5c43SDamon Ding printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n");
17495fa6e665SDamon Ding } else {
1750df0a5c43SDamon Ding csc_mode = CSC_BT709L;
17515fa6e665SDamon Ding }
1752df0a5c43SDamon Ding break;
1753df0a5c43SDamon Ding
1754df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT2020:
1755df0a5c43SDamon Ding if (full_range) {
1756df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F;
1757df0a5c43SDamon Ding if (bit_depth != CSC_13BIT_DEPTH)
1758df0a5c43SDamon Ding printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n");
17595fa6e665SDamon Ding } else {
1760df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L;
17615fa6e665SDamon Ding }
1762df0a5c43SDamon Ding break;
1763df0a5c43SDamon Ding
176410ee9f5bSAlgea Cao default:
1765df0a5c43SDamon Ding printf("Unsuport color_encoding:%d\n", color_encoding);
176610ee9f5bSAlgea Cao }
1767df0a5c43SDamon Ding
1768df0a5c43SDamon Ding return csc_mode;
176910ee9f5bSAlgea Cao }
177010ee9f5bSAlgea Cao
is_uv_swap(struct display_state * state)1771c8820b76SDamon Ding static bool is_uv_swap(struct display_state *state)
1772d0408543SAndy Yan {
1773c8820b76SDamon Ding struct connector_state *conn_state = &state->conn_state;
1774c8820b76SDamon Ding u32 bus_format = conn_state->bus_format;
1775c8820b76SDamon Ding u32 output_mode = conn_state->output_mode;
1776c8820b76SDamon Ding u32 output_type = conn_state->type;
1777c8820b76SDamon Ding
1778d0408543SAndy Yan /*
1779d0408543SAndy Yan * FIXME:
1780d0408543SAndy Yan *
1781d0408543SAndy Yan * There is no media type for YUV444 output,
1782d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on
1783d0408543SAndy Yan * yuv format.
1784d0408543SAndy Yan *
1785c8820b76SDamon Ding * From H/W testing, YUV444 mode need a rb swap except eDP.
1786d0408543SAndy Yan */
17873e59c137SSandy Huang if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
17883e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
17893e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
17903e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
17913e59c137SSandy Huang ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
1792d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
1793d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
1794c8820b76SDamon Ding output_mode == ROCKCHIP_OUT_MODE_P888) &&
1795c8820b76SDamon Ding !(output_type == DRM_MODE_CONNECTOR_eDP)))
1796d0408543SAndy Yan return true;
1797d0408543SAndy Yan else
1798d0408543SAndy Yan return false;
1799d0408543SAndy Yan }
1800d0408543SAndy Yan
is_rb_swap(struct display_state * state)1801c8820b76SDamon Ding static bool is_rb_swap(struct display_state *state)
18020675a2a4SDamon Ding {
1803c8820b76SDamon Ding struct connector_state *conn_state = &state->conn_state;
1804c8820b76SDamon Ding u32 bus_format = conn_state->bus_format;
1805c8820b76SDamon Ding
18060675a2a4SDamon Ding /*
18070675a2a4SDamon Ding * The default component order of serial rgb3x8 formats
18080675a2a4SDamon Ding * is BGR. So it is needed to enable RB swap.
18090675a2a4SDamon Ding */
1810b7b383ebSDamon Ding if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 ||
1811b7b383ebSDamon Ding bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8)
18120675a2a4SDamon Ding return true;
18130675a2a4SDamon Ding else
18140675a2a4SDamon Ding return false;
18150675a2a4SDamon Ding }
18160675a2a4SDamon Ding
is_yc_swap(u32 bus_format)18175d2768f7SDamon Ding static bool is_yc_swap(u32 bus_format)
18185d2768f7SDamon Ding {
18195d2768f7SDamon Ding switch (bus_format) {
18205d2768f7SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16:
18215d2768f7SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16:
18225d2768f7SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8:
18235d2768f7SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8:
18245d2768f7SDamon Ding return true;
18255d2768f7SDamon Ding default:
18265d2768f7SDamon Ding return false;
18275d2768f7SDamon Ding }
18285d2768f7SDamon Ding }
18295d2768f7SDamon Ding
is_hot_plug_devices(int output_type)1830b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type)
183163cb669fSSandy Huang {
1832b0989546SSandy Huang switch (output_type) {
1833b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA:
1834b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB:
1835b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV:
1836b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort:
1837b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA:
1838b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown:
1839b0989546SSandy Huang return true;
1840b0989546SSandy Huang default:
1841b0989546SSandy Huang return false;
184263cb669fSSandy Huang }
184363cb669fSSandy Huang }
184463cb669fSSandy Huang
vop2_find_win_by_phys_id(struct vop2 * vop2,int phys_id)1845ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id)
1846ecc31b6eSAndy Yan {
1847ecc31b6eSAndy Yan int i = 0;
1848ecc31b6eSAndy Yan
1849ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) {
1850ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id)
1851ecc31b6eSAndy Yan return &vop2->data->win_data[i];
1852ecc31b6eSAndy Yan }
1853ecc31b6eSAndy Yan
1854ecc31b6eSAndy Yan return NULL;
1855ecc31b6eSAndy Yan }
1856ecc31b6eSAndy Yan
vop2_find_pd_data_by_id(struct vop2 * vop2,int pd_id)1857b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id)
1858b6ba80b4SDamon Ding {
1859b6ba80b4SDamon Ding int i = 0;
1860b6ba80b4SDamon Ding
1861b6ba80b4SDamon Ding for (i = 0; i < vop2->data->nr_pd; i++) {
1862b6ba80b4SDamon Ding if (vop2->data->pd[i].id == pd_id)
1863b6ba80b4SDamon Ding return &vop2->data->pd[i];
1864b6ba80b4SDamon Ding }
1865b6ba80b4SDamon Ding
1866b6ba80b4SDamon Ding return NULL;
1867b6ba80b4SDamon Ding }
1868b6ba80b4SDamon Ding
rk3568_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1869db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1870db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len)
1871db328a0dSDamon Ding {
1872db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100;
1873db328a0dSDamon Ding int i;
1874db328a0dSDamon Ding
1875db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1876db328a0dSDamon Ding GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT,
1877db328a0dSDamon Ding crtc_id, false);
1878db328a0dSDamon Ding
1879db328a0dSDamon Ding for (i = 0; i < lut_len; i++)
1880db328a0dSDamon Ding writel(lut_val[i], lut_regs + i);
1881db328a0dSDamon Ding
1882db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1883db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1884db328a0dSDamon Ding }
1885db328a0dSDamon Ding
rk3588_vop2_load_lut(struct vop2 * vop2,int crtc_id,u32 * lut_regs,u32 * lut_val,int lut_len)1886db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id,
1887db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len)
1888db328a0dSDamon Ding {
1889db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100;
1890db328a0dSDamon Ding int i;
1891db328a0dSDamon Ding
18921828f293SDamon Ding if (vop2->version == VOP_VERSION_RK3576)
18931828f293SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
18941828f293SDamon Ding GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
18951828f293SDamon Ding crtc_id, true);
18961828f293SDamon Ding else
1897db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
1898db328a0dSDamon Ding GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT,
1899db328a0dSDamon Ding crtc_id, false);
1900db328a0dSDamon Ding
1901db328a0dSDamon Ding for (i = 0; i < lut_len; i++)
1902db328a0dSDamon Ding writel(lut_val[i], lut_regs + i);
1903db328a0dSDamon Ding
1904db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1905db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false);
1906db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
1907db328a0dSDamon Ding EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false);
1908db328a0dSDamon Ding }
1909db328a0dSDamon Ding
rockchip_vop2_gamma_lut_init(struct vop2 * vop2,struct display_state * state)19101147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2,
1911d0408543SAndy Yan struct display_state *state)
1912d0408543SAndy Yan {
19131147facaSSandy Huang struct connector_state *conn_state = &state->conn_state;
19141147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state;
19151147facaSSandy Huang struct resource gamma_res;
19161147facaSSandy Huang fdt_size_t lut_size;
19171147facaSSandy Huang int i, lut_len, ret = 0;
19181147facaSSandy Huang u32 *lut_regs;
19191147facaSSandy Huang u32 r, g, b;
19201147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info;
19211147facaSSandy Huang static int gamma_lut_en_num = 1;
19221147facaSSandy Huang
19231147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) {
19241147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas);
19251147facaSSandy Huang return 0;
19261147facaSSandy Huang }
19271147facaSSandy Huang
19281147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
19291147facaSSandy Huang if (ret)
19301147facaSSandy Huang printf("failed to get gamma lut res\n");
19311147facaSSandy Huang lut_regs = (u32 *)gamma_res.start;
19321147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1;
19331147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
19341147facaSSandy Huang printf("failed to get gamma lut register\n");
19351147facaSSandy Huang return 0;
19361147facaSSandy Huang }
19371147facaSSandy Huang lut_len = lut_size / 4;
19381147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) {
19391147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len);
19401147facaSSandy Huang return 0;
19411147facaSSandy Huang }
19420669ab1fSDamon Ding
19430669ab1fSDamon Ding if (!cstate->lut_val) {
19440669ab1fSDamon Ding if (!disp_info)
19450669ab1fSDamon Ding return 0;
19460669ab1fSDamon Ding
19470669ab1fSDamon Ding if (!disp_info->gamma_lut_data.size)
19480669ab1fSDamon Ding return 0;
19490669ab1fSDamon Ding
19500669ab1fSDamon Ding cstate->lut_val = (u32 *)calloc(1, lut_size);
19511147facaSSandy Huang for (i = 0; i < lut_len; i++) {
19521147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff;
19531147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff;
19541147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff;
19551147facaSSandy Huang
19560669ab1fSDamon Ding cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r;
19570669ab1fSDamon Ding }
19581147facaSSandy Huang }
19591147facaSSandy Huang
1960db328a0dSDamon Ding if (vop2->version == VOP_VERSION_RK3568) {
19610669ab1fSDamon Ding rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
19620669ab1fSDamon Ding cstate->lut_val, lut_len);
19631147facaSSandy Huang gamma_lut_en_num++;
196418d9b8adSDamon Ding } else {
19650669ab1fSDamon Ding rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs,
19660669ab1fSDamon Ding cstate->lut_val, lut_len);
1967db328a0dSDamon Ding if (cstate->splice_mode) {
19680669ab1fSDamon Ding rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs,
19690669ab1fSDamon Ding cstate->lut_val, lut_len);
1970db328a0dSDamon Ding gamma_lut_en_num++;
1971db328a0dSDamon Ding }
1972db328a0dSDamon Ding gamma_lut_en_num++;
1973db328a0dSDamon Ding }
19741147facaSSandy Huang
19750669ab1fSDamon Ding free(cstate->lut_val);
19760669ab1fSDamon Ding
1977d0408543SAndy Yan return 0;
1978d0408543SAndy Yan }
1979d0408543SAndy Yan
rockchip_vop2_cubic_lut_init(struct vop2 * vop2,struct display_state * state)19806414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2,
19816414e3bcSSandy Huang struct display_state *state)
19826414e3bcSSandy Huang {
19836414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state;
19846414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state;
19856414e3bcSSandy Huang int i, cubic_lut_len;
19866414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100;
19876414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info;
19886414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data;
19896414e3bcSSandy Huang u32 *cubic_lut_addr;
19906414e3bcSSandy Huang
19916414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0)
19926414e3bcSSandy Huang return 0;
19936414e3bcSSandy Huang
19946414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size)
19956414e3bcSSandy Huang return 0;
19966414e3bcSSandy Huang
19976414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id);
19986414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size;
19996414e3bcSSandy Huang
20006414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) {
20016414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) +
20026414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) +
20036414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24);
20046414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) +
20056414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) +
20066414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) +
20076414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28);
20086414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4;
20096414e3bcSSandy Huang *cubic_lut_addr++ = 0;
20106414e3bcSSandy Huang }
20116414e3bcSSandy Huang
20126414e3bcSSandy Huang if (cubic_lut_len % 2) {
20136414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) +
20146414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) +
20156414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24);
20166414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8;
20176414e3bcSSandy Huang *cubic_lut_addr++ = 0;
20186414e3bcSSandy Huang *cubic_lut_addr = 0;
20196414e3bcSSandy Huang }
20206414e3bcSSandy Huang
20216414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset,
20226414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id));
20236414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL,
20246414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false);
20256414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
20266414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false);
20276414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset,
20286414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false);
20296414e3bcSSandy Huang
20306414e3bcSSandy Huang return 0;
20316414e3bcSSandy Huang }
20326414e3bcSSandy Huang
vop2_bcsh_reg_update(struct display_state * state,struct vop2 * vop2,struct bcsh_state * bcsh_state,int crtc_id)2033ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2,
2034ee01dbb2SDamon Ding struct bcsh_state *bcsh_state, int crtc_id)
2035ee01dbb2SDamon Ding {
2036ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state;
2037ee01dbb2SDamon Ding u32 vp_offset = crtc_id * 0x100;
2038ee01dbb2SDamon Ding
2039ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK,
2040ee01dbb2SDamon Ding BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false);
2041ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK,
2042ee01dbb2SDamon Ding BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false);
2043ee01dbb2SDamon Ding
2044ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK,
2045ee01dbb2SDamon Ding BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2046ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK,
2047ee01dbb2SDamon Ding BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false);
2048ee01dbb2SDamon Ding
2049ee01dbb2SDamon Ding if (!cstate->bcsh_en) {
2050ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2051ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false);
2052ee01dbb2SDamon Ding return;
2053ee01dbb2SDamon Ding }
2054ee01dbb2SDamon Ding
2055ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2056ee01dbb2SDamon Ding BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT,
2057ee01dbb2SDamon Ding bcsh_state->brightness, false);
2058ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2059ee01dbb2SDamon Ding BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false);
2060ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2061ee01dbb2SDamon Ding BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT,
2062ee01dbb2SDamon Ding bcsh_state->saturation * bcsh_state->contrast / 0x100, false);
2063ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2064ee01dbb2SDamon Ding BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false);
2065ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset,
2066ee01dbb2SDamon Ding BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false);
2067ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset,
2068ee01dbb2SDamon Ding BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT,
2069ee01dbb2SDamon Ding BCSH_OUT_MODE_NORMAL_VIDEO, false);
2070ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset,
2071ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false);
2072ee01dbb2SDamon Ding }
2073ee01dbb2SDamon Ding
vop2_tv_config_update(struct display_state * state,struct vop2 * vop2)2074ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2)
2075ac500a1fSSandy Huang {
2076ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state;
2077ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info;
2078ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state;
2079ee01dbb2SDamon Ding struct bcsh_state bcsh_state;
2080ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue;
2081ac500a1fSSandy Huang
2082ac500a1fSSandy Huang if (!conn_state->disp_info)
2083ac500a1fSSandy Huang return;
2084ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info;
2085ac500a1fSSandy Huang if (!bcsh_info)
2086ac500a1fSSandy Huang return;
2087ac500a1fSSandy Huang
2088ac500a1fSSandy Huang if (bcsh_info->brightness != 50 ||
2089ac500a1fSSandy Huang bcsh_info->contrast != 50 ||
2090ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50)
2091ee01dbb2SDamon Ding cstate->bcsh_en = true;
2092ac500a1fSSandy Huang
2093ee01dbb2SDamon Ding if (cstate->bcsh_en) {
2094ac500a1fSSandy Huang if (!cstate->yuv_overlay)
2095ee01dbb2SDamon Ding cstate->post_r2y_en = 1;
2096ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format))
2097ee01dbb2SDamon Ding cstate->post_y2r_en = 1;
2098ac500a1fSSandy Huang } else {
2099ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
2100ee01dbb2SDamon Ding cstate->post_r2y_en = 1;
2101ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
2102ee01dbb2SDamon Ding cstate->post_y2r_en = 1;
2103ac500a1fSSandy Huang }
2104ac500a1fSSandy Huang
2105df0a5c43SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2106df0a5c43SDamon Ding conn_state->color_range,
2107df0a5c43SDamon Ding CSC_10BIT_DEPTH);
2108ac500a1fSSandy Huang
2109ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT)
2110ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127,
2111ac500a1fSSandy Huang bcsh_info->brightness);
2112ac500a1fSSandy Huang else
2113ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31,
2114ac500a1fSSandy Huang bcsh_info->brightness);
2115ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast);
2116ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation);
2117ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue);
2118ac500a1fSSandy Huang
2119ac500a1fSSandy Huang
2120ac500a1fSSandy Huang /*
2121ac500a1fSSandy Huang * a:[-30~0):
2122ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256;
2123ac500a1fSSandy Huang * cos_hue = cos(a)*256;
2124ac500a1fSSandy Huang * a:[0~30]
2125ac500a1fSSandy Huang * sin_hue = sin(a)*256;
2126ac500a1fSSandy Huang * cos_hue = cos(a)*256;
2127ac500a1fSSandy Huang */
2128ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23;
2129ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23;
2130ac500a1fSSandy Huang
2131ee01dbb2SDamon Ding bcsh_state.brightness = brightness;
2132ee01dbb2SDamon Ding bcsh_state.contrast = contrast;
2133ee01dbb2SDamon Ding bcsh_state.saturation = saturation;
2134ee01dbb2SDamon Ding bcsh_state.sin_hue = sin_hue;
2135ee01dbb2SDamon Ding bcsh_state.cos_hue = cos_hue;
2136ee01dbb2SDamon Ding
2137ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id);
2138ee01dbb2SDamon Ding if (cstate->splice_mode)
2139ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id);
2140ee01dbb2SDamon Ding }
2141ee01dbb2SDamon Ding
vop2_setup_dly_for_vp(struct display_state * state,struct vop2 * vop2,int crtc_id)2142ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id)
2143ee01dbb2SDamon Ding {
2144ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state;
2145ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode;
2146ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state;
2147ee01dbb2SDamon Ding u32 bg_ovl_dly, bg_dly, pre_scan_dly;
2148ee01dbb2SDamon Ding u16 hdisplay = mode->crtc_hdisplay;
2149ee01dbb2SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2150ee01dbb2SDamon Ding
2151ee01dbb2SDamon Ding bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly;
2152ee01dbb2SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly;
2153ee01dbb2SDamon Ding bg_dly -= bg_ovl_dly;
2154ee01dbb2SDamon Ding
2155a552a69cSDamon Ding /*
2156a552a69cSDamon Ding * splice mode: hdisplay must roundup as 4 pixel,
2157a552a69cSDamon Ding * no splice mode: hdisplay must roundup as 2 pixel.
2158a552a69cSDamon Ding */
2159ee01dbb2SDamon Ding if (cstate->splice_mode)
2160a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1;
2161ee01dbb2SDamon Ding else
2162a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2163ee01dbb2SDamon Ding
2164ee01dbb2SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8)
2165ee01dbb2SDamon Ding hsync_len = 8;
2166ee01dbb2SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
2167ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4,
2168ee01dbb2SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2169ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2170ac500a1fSSandy Huang }
2171ac500a1fSSandy Huang
vop3_setup_pipe_dly(struct display_state * state,struct vop2 * vop2,int crtc_id)2172452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id)
2173452afb13SDamon Ding {
2174452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state;
2175452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode;
2176452afb13SDamon Ding u32 bg_dly, pre_scan_dly;
2177452afb13SDamon Ding u16 hdisplay = mode->crtc_hdisplay;
2178452afb13SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2179452afb13SDamon Ding
2180452afb13SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].win_dly +
2181452afb13SDamon Ding vop2->data->vp_data[crtc_id].layer_mix_dly +
2182452afb13SDamon Ding vop2->data->vp_data[crtc_id].hdr_mix_dly;
2183a552a69cSDamon Ding /* hdisplay must roundup as 2 pixel */
2184a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1;
2185a552a69cSDamon Ding /**
2186a552a69cSDamon Ding * pre_scan_hblank minimum value is 8, otherwise the win reset signal will
2187a552a69cSDamon Ding * lead to first line data be zero.
2188a552a69cSDamon Ding */
2189a552a69cSDamon Ding pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len);
2190452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100,
2191452afb13SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false);
2192452afb13SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly);
2193452afb13SDamon Ding }
2194452afb13SDamon Ding
vop2_post_config(struct display_state * state,struct vop2 * vop2)2195d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2)
2196d0408543SAndy Yan {
2197d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state;
2198d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode;
219952ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state;
22009c7848c3SDamon Ding const struct vop2_data *vop2_data = vop2->data;
22019c7848c3SDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops;
2202b888dbc8SSandy Huang struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[cstate->crtc_id];
220352ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100);
2204d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal;
2205d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
2206d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
2207d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay;
2208d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay;
2209668e6278SDamon Ding u16 hsize;
2210668e6278SDamon Ding u16 vsize;
2211d0408543SAndy Yan u16 hact_end, vact_end;
2212d0408543SAndy Yan u32 val;
2213d0408543SAndy Yan
2214668e6278SDamon Ding /*
2215668e6278SDamon Ding * For RK3576, use the win scale instead of the post scale to configure
2216668e6278SDamon Ding * overscan parameters, because the sharp/post scale/split functions are
2217668e6278SDamon Ding * mutually exclusice.
2218668e6278SDamon Ding */
2219668e6278SDamon Ding if (vop2->version == VOP_VERSION_RK3576) {
2220668e6278SDamon Ding hsize = hdisplay;
2221668e6278SDamon Ding vsize = vdisplay;
2222668e6278SDamon Ding
2223668e6278SDamon Ding cstate->overscan_by_win_scale = true;
2224668e6278SDamon Ding } else {
2225668e6278SDamon Ding hsize = hdisplay * (conn_state->overscan.left_margin +
2226668e6278SDamon Ding conn_state->overscan.right_margin) / 200;
2227668e6278SDamon Ding vsize = vdisplay * (conn_state->overscan.top_margin +
2228668e6278SDamon Ding conn_state->overscan.bottom_margin) / 200;
222974bd8269SSandy Huang hsize = round_down(hsize, 2);
2230d0408543SAndy Yan vsize = round_down(vsize, 2);
2231d0408543SAndy Yan
2232d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200;
2233668e6278SDamon Ding vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200;
2234668e6278SDamon Ding }
2235668e6278SDamon Ding
2236d0408543SAndy Yan hact_end = hact_st + hsize;
2237d0408543SAndy Yan val = hact_st << 16;
2238d0408543SAndy Yan val |= hact_end;
223952ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val);
2240d0408543SAndy Yan vact_end = vact_st + vsize;
2241d0408543SAndy Yan val = vact_st << 16;
2242d0408543SAndy Yan val |= vact_end;
224352ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val);
2244d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16;
2245d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize);
224652ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val);
2247d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0)
2248d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1)
22497504507fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset,
22507504507fSSandy Huang RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT,
2251d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
22527504507fSSandy Huang POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false);
2253d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
2254d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1;
2255d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize;
2256d0408543SAndy Yan
2257d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1;
225852ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val);
2259d0408543SAndy Yan }
2260d0408543SAndy Yan
2261452afb13SDamon Ding if (is_vop3(vop2)) {
2262452afb13SDamon Ding vop3_setup_pipe_dly(state, vop2, cstate->crtc_id);
2263452afb13SDamon Ding } else {
2264ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id);
2265b888dbc8SSandy Huang vop2_ops->setup_win_dly(state, cstate->crtc_id, plane_mask->primary_plane_id);
22669c7848c3SDamon Ding if (cstate->splice_mode) {
2267b888dbc8SSandy Huang plane_mask = &vop2->vp_plane_mask[cstate->splice_crtc_id];
2268ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id);
2269b888dbc8SSandy Huang vop2_ops->setup_win_dly(state, cstate->splice_crtc_id, plane_mask->primary_plane_id);
22709c7848c3SDamon Ding }
2271d0408543SAndy Yan }
2272452afb13SDamon Ding }
2273d0408543SAndy Yan
vop3_post_acm_config(struct display_state * state,struct vop2 * vop2)22746027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2)
22756027c871SZhang Yubing {
22766027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state;
22776027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state;
22786027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data;
22796027c871SZhang Yubing struct drm_display_mode *mode = &conn_state->mode;
22806027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100);
22816027c871SZhang Yubing s16 *lut_y;
22826027c871SZhang Yubing s16 *lut_h;
22836027c871SZhang Yubing s16 *lut_s;
22846027c871SZhang Yubing u32 value;
22856027c871SZhang Yubing int i;
22866027c871SZhang Yubing
22876027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
2288b8db91d0SZhang Yubing POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
2289b8db91d0SZhang Yubing if (!acm->acm_enable) {
2290b8db91d0SZhang Yubing writel(0, vop2->regs + RK3528_ACM_CTRL);
22916027c871SZhang Yubing return;
22926027c871SZhang Yubing }
22936027c871SZhang Yubing
22946027c871SZhang Yubing printf("post acm enable\n");
22956027c871SZhang Yubing
22966027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_START);
22976027c871SZhang Yubing
22986027c871SZhang Yubing value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) +
22996027c871SZhang Yubing ((mode->vdisplay & 0xfff) << 20);
23006027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_CTRL);
23016027c871SZhang Yubing
23026027c871SZhang Yubing value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) +
23036027c871SZhang Yubing ((acm->s_gain << 20) & 0x3ff00000);
23046027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE);
23056027c871SZhang Yubing
23066027c871SZhang Yubing lut_y = &acm->gain_lut_hy[0];
23076027c871SZhang Yubing lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH];
23086027c871SZhang Yubing lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2];
23096027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) {
23106027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
23116027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000);
23126027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2));
23136027c871SZhang Yubing }
23146027c871SZhang Yubing
23156027c871SZhang Yubing lut_y = &acm->gain_lut_hs[0];
23166027c871SZhang Yubing lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH];
23176027c871SZhang Yubing lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2];
23186027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) {
23196027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) +
23206027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000);
23216027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2));
23226027c871SZhang Yubing }
23236027c871SZhang Yubing
23246027c871SZhang Yubing lut_y = &acm->delta_lut_h[0];
23256027c871SZhang Yubing lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH];
23266027c871SZhang Yubing lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2];
23276027c871SZhang Yubing for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) {
23286027c871SZhang Yubing value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) +
23296027c871SZhang Yubing ((lut_s[i] << 20) & 0x3ff00000);
23306027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2));
23316027c871SZhang Yubing }
23326027c871SZhang Yubing
23336027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_DONE);
23346027c871SZhang Yubing }
23356027c871SZhang Yubing
vop3_get_csc_info_from_bcsh(struct display_state * state,struct csc_info * csc_info)233628dc0247SDamon Ding static void vop3_get_csc_info_from_bcsh(struct display_state *state,
233728dc0247SDamon Ding struct csc_info *csc_info)
233828dc0247SDamon Ding {
233928dc0247SDamon Ding struct connector_state *conn_state = &state->conn_state;
234028dc0247SDamon Ding struct base_bcsh_info *bcsh_info;
234128dc0247SDamon Ding
234228dc0247SDamon Ding if (!conn_state->disp_info)
234328dc0247SDamon Ding return;
234428dc0247SDamon Ding
234528dc0247SDamon Ding bcsh_info = &conn_state->disp_info->bcsh_info;
234628dc0247SDamon Ding if (!bcsh_info)
234728dc0247SDamon Ding return;
234828dc0247SDamon Ding
234928dc0247SDamon Ding csc_info->r_gain = 256;
235028dc0247SDamon Ding csc_info->g_gain = 256;
235128dc0247SDamon Ding csc_info->b_gain = 256;
235228dc0247SDamon Ding csc_info->r_offset = 256;
235328dc0247SDamon Ding csc_info->g_offset = 256;
235428dc0247SDamon Ding csc_info->b_offset = 256;
235528dc0247SDamon Ding if (bcsh_info->brightness == 50 && bcsh_info->contrast == 50 &&
235628dc0247SDamon Ding bcsh_info->saturation == 50 && bcsh_info->hue == 50) {
235728dc0247SDamon Ding csc_info->csc_enable = false;
235828dc0247SDamon Ding csc_info->brightness = 256;
235928dc0247SDamon Ding csc_info->contrast = 256;
236028dc0247SDamon Ding csc_info->saturation = 256;
236128dc0247SDamon Ding csc_info->hue = 256;
236228dc0247SDamon Ding } else {
236328dc0247SDamon Ding csc_info->csc_enable = true;
236428dc0247SDamon Ding csc_info->brightness = bcsh_info->brightness * 511 / 100;
236528dc0247SDamon Ding csc_info->contrast = bcsh_info->contrast * 511 / 100;
236628dc0247SDamon Ding csc_info->saturation = bcsh_info->saturation * 511 / 100;
236728dc0247SDamon Ding csc_info->hue = bcsh_info->hue * 511 / 100;
236828dc0247SDamon Ding }
236928dc0247SDamon Ding }
237028dc0247SDamon Ding
vop3_post_csc_config(struct display_state * state,struct vop2 * vop2)23716027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2)
23726027c871SZhang Yubing {
23736027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state;
23746027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state;
23756027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data;
23766027c871SZhang Yubing struct csc_info *csc = &conn_state->disp_info->csc_info;
23776027c871SZhang Yubing struct post_csc_coef csc_coef;
23786027c871SZhang Yubing bool is_input_yuv = false;
23796027c871SZhang Yubing bool is_output_yuv = false;
23806027c871SZhang Yubing bool post_r2y_en = false;
23816027c871SZhang Yubing bool post_csc_en = false;
23826027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100);
23836027c871SZhang Yubing u32 value;
23846027c871SZhang Yubing int range_type;
23856027c871SZhang Yubing
23866027c871SZhang Yubing printf("post csc enable\n");
23876027c871SZhang Yubing
238828dc0247SDamon Ding if (!csc->csc_enable)
238928dc0247SDamon Ding vop3_get_csc_info_from_bcsh(state, csc);
239028dc0247SDamon Ding
23916027c871SZhang Yubing if (acm->acm_enable) {
23926027c871SZhang Yubing if (!cstate->yuv_overlay)
23936027c871SZhang Yubing post_r2y_en = true;
23946027c871SZhang Yubing
23956027c871SZhang Yubing /* do y2r in csc module */
23966027c871SZhang Yubing if (!is_yuv_output(conn_state->bus_format))
23976027c871SZhang Yubing post_csc_en = true;
23986027c871SZhang Yubing } else {
23996027c871SZhang Yubing if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format))
24006027c871SZhang Yubing post_r2y_en = true;
24016027c871SZhang Yubing
24026027c871SZhang Yubing /* do y2r in csc module */
24036027c871SZhang Yubing if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format))
24046027c871SZhang Yubing post_csc_en = true;
24056027c871SZhang Yubing }
24066027c871SZhang Yubing
24076027c871SZhang Yubing if (csc->csc_enable)
24086027c871SZhang Yubing post_csc_en = true;
24096027c871SZhang Yubing
24106027c871SZhang Yubing if (cstate->yuv_overlay || post_r2y_en)
24116027c871SZhang Yubing is_input_yuv = true;
24126027c871SZhang Yubing
24136027c871SZhang Yubing if (is_yuv_output(conn_state->bus_format))
24146027c871SZhang Yubing is_output_yuv = true;
24156027c871SZhang Yubing
2416df0a5c43SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding,
2417df0a5c43SDamon Ding conn_state->color_range,
2418df0a5c43SDamon Ding CSC_13BIT_DEPTH);
24196027c871SZhang Yubing
24206027c871SZhang Yubing if (post_csc_en) {
24216027c871SZhang Yubing rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv,
24226027c871SZhang Yubing is_output_yuv);
24236027c871SZhang Yubing
24246027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24256027c871SZhang Yubing POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT,
24266027c871SZhang Yubing csc_coef.csc_coef00, false);
24275743c73eSZhang Yubing value = csc_coef.csc_coef01 & 0xffff;
24285743c73eSZhang Yubing value |= (csc_coef.csc_coef02 << 16) & 0xffff0000;
24296027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02);
24305743c73eSZhang Yubing value = csc_coef.csc_coef10 & 0xffff;
24315743c73eSZhang Yubing value |= (csc_coef.csc_coef11 << 16) & 0xffff0000;
24326027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11);
24335743c73eSZhang Yubing value = csc_coef.csc_coef12 & 0xffff;
24345743c73eSZhang Yubing value |= (csc_coef.csc_coef20 << 16) & 0xffff0000;
24356027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20);
24365743c73eSZhang Yubing value = csc_coef.csc_coef21 & 0xffff;
24375743c73eSZhang Yubing value |= (csc_coef.csc_coef22 << 16) & 0xffff0000;
24386027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22);
24396027c871SZhang Yubing writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0);
24406027c871SZhang Yubing writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1);
24416027c871SZhang Yubing writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2);
24426027c871SZhang Yubing
24436027c871SZhang Yubing range_type = csc_coef.range_type ? 0 : 1;
24446027c871SZhang Yubing range_type <<= is_input_yuv ? 0 : 1;
24456027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24466027c871SZhang Yubing POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false);
24476027c871SZhang Yubing }
24486027c871SZhang Yubing
24496027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24505743c73eSZhang Yubing POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false);
24516027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24526027c871SZhang Yubing POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false);
24536027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
24546027c871SZhang Yubing POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false);
24556027c871SZhang Yubing }
24566027c871SZhang Yubing
vop3_post_config(struct display_state * state,struct vop2 * vop2)24576027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2)
24586027c871SZhang Yubing {
24596027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state;
24606027c871SZhang Yubing struct base2_disp_info *disp_info = conn_state->disp_info;
24616027c871SZhang Yubing const char *enable_flag;
24626027c871SZhang Yubing if (!disp_info) {
24636027c871SZhang Yubing printf("disp_info is empty\n");
24646027c871SZhang Yubing return;
24656027c871SZhang Yubing }
24666027c871SZhang Yubing
24676027c871SZhang Yubing enable_flag = (const char *)&disp_info->cacm_header;
24686027c871SZhang Yubing if (strncasecmp(enable_flag, "CACM", 4)) {
24696027c871SZhang Yubing printf("acm and csc is not support\n");
24706027c871SZhang Yubing return;
24716027c871SZhang Yubing }
24726027c871SZhang Yubing
24736027c871SZhang Yubing vop3_post_acm_config(state, vop2);
24746027c871SZhang Yubing vop3_post_csc_config(state, vop2);
24756027c871SZhang Yubing }
24766027c871SZhang Yubing
rk3576_vop2_wait_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2477a552a69cSDamon Ding static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2,
2478a552a69cSDamon Ding struct vop2_power_domain_data *pd_data)
2479a552a69cSDamon Ding {
2480a552a69cSDamon Ding int val = 0;
2481a552a69cSDamon Ding bool is_bisr_en, is_otp_bisr_en;
2482a552a69cSDamon Ding
2483a552a69cSDamon Ding if (pd_data->id == VOP2_PD_CLUSTER) {
2484a552a69cSDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2485a552a69cSDamon Ding EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2486a552a69cSDamon Ding is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2487a552a69cSDamon Ding EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT);
2488a552a69cSDamon Ding if (is_bisr_en && is_otp_bisr_en)
2489a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2490a552a69cSDamon Ding val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1),
2491a552a69cSDamon Ding 50 * 1000);
2492a552a69cSDamon Ding else
2493a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
24940e0a0ff9SDamon Ding val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1),
2495a552a69cSDamon Ding 50 * 1000);
2496a552a69cSDamon Ding } else {
2497a552a69cSDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0,
2498a552a69cSDamon Ding EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2499a552a69cSDamon Ding is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0,
2500a552a69cSDamon Ding EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT);
2501a552a69cSDamon Ding if (is_bisr_en && is_otp_bisr_en)
2502a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0,
2503a552a69cSDamon Ding val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1),
2504a552a69cSDamon Ding 50 * 1000);
2505a552a69cSDamon Ding else
2506a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS,
2507a552a69cSDamon Ding val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1),
2508a552a69cSDamon Ding 50 * 1000);
2509a552a69cSDamon Ding }
2510a552a69cSDamon Ding }
2511a552a69cSDamon Ding
rk3576_vop2_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2512a552a69cSDamon Ding static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2513a552a69cSDamon Ding {
2514a552a69cSDamon Ding int ret = 0;
2515a552a69cSDamon Ding
2516a552a69cSDamon Ding if (pd_data->id == VOP2_PD_CLUSTER)
2517a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK,
2518a552a69cSDamon Ding RK3576_CLUSTER_PD_EN_SHIFT, 0, true);
2519a552a69cSDamon Ding else
2520a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK,
2521a552a69cSDamon Ding RK3576_ESMART_PD_EN_SHIFT, 0, true);
2522a552a69cSDamon Ding ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data);
2523a552a69cSDamon Ding if (ret) {
2524a552a69cSDamon Ding printf("wait vop2 power domain timeout\n");
2525a552a69cSDamon Ding return ret;
2526a552a69cSDamon Ding }
2527a552a69cSDamon Ding
2528a552a69cSDamon Ding return 0;
2529a552a69cSDamon Ding }
2530a552a69cSDamon Ding
rk3588_vop2_wait_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2531a552a69cSDamon Ding static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2,
2532a552a69cSDamon Ding struct vop2_power_domain_data *pd_data)
253360e469f5SDamon Ding {
253460e469f5SDamon Ding int val = 0;
253560e469f5SDamon Ding int shift = 0;
2536b6ba80b4SDamon Ding int shift_factor = 0;
253760e469f5SDamon Ding bool is_bisr_en = false;
253860e469f5SDamon Ding
2539b6ba80b4SDamon Ding /*
2540b6ba80b4SDamon Ding * The order of pd status bits in BISR_STS register
2541b6ba80b4SDamon Ding * is different from that in VOP SYS_STS register.
2542b6ba80b4SDamon Ding */
2543b6ba80b4SDamon Ding if (pd_data->id == VOP2_PD_DSC_8K ||
2544b6ba80b4SDamon Ding pd_data->id == VOP2_PD_DSC_4K ||
2545b6ba80b4SDamon Ding pd_data->id == VOP2_PD_ESMART)
2546b6ba80b4SDamon Ding shift_factor = 1;
2547b6ba80b4SDamon Ding
2548b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor;
2549b6ba80b4SDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift);
255060e469f5SDamon Ding if (is_bisr_en) {
2551b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor;
2552b6ba80b4SDamon Ding
255360e469f5SDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val,
2554d2e91fdcSDamon Ding ((val >> shift) & 0x1), 50 * 1000);
255560e469f5SDamon Ding } else {
2556b6ba80b4SDamon Ding shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1;
2557b6ba80b4SDamon Ding
255860e469f5SDamon Ding return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val,
255960e469f5SDamon Ding !((val >> shift) & 0x1), 50 * 1000);
256060e469f5SDamon Ding }
256160e469f5SDamon Ding }
256260e469f5SDamon Ding
rk3588_vop2_power_domain_on(struct vop2 * vop2,struct vop2_power_domain_data * pd_data)2563a552a69cSDamon Ding static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data)
2564a552a69cSDamon Ding {
2565a552a69cSDamon Ding int ret = 0;
2566a552a69cSDamon Ding
2567a552a69cSDamon Ding vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK,
2568a552a69cSDamon Ding RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false);
2569a552a69cSDamon Ding ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data);
2570a552a69cSDamon Ding if (ret) {
2571a552a69cSDamon Ding printf("wait vop2 power domain timeout\n");
2572a552a69cSDamon Ding return ret;
2573a552a69cSDamon Ding }
2574a552a69cSDamon Ding
2575a552a69cSDamon Ding return 0;
2576a552a69cSDamon Ding }
2577a552a69cSDamon Ding
vop2_power_domain_on(struct vop2 * vop2,int pd_id)2578b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id)
257960e469f5SDamon Ding {
258060e469f5SDamon Ding struct vop2_power_domain_data *pd_data;
258160e469f5SDamon Ding int ret = 0;
258260e469f5SDamon Ding
2583b6ba80b4SDamon Ding if (!pd_id)
2584b6ba80b4SDamon Ding return 0;
2585b6ba80b4SDamon Ding
2586b6ba80b4SDamon Ding pd_data = vop2_find_pd_data_by_id(vop2, pd_id);
2587b6ba80b4SDamon Ding if (!pd_data) {
2588b6ba80b4SDamon Ding printf("can't find pd_data by id\n");
258960e469f5SDamon Ding return -EINVAL;
259060e469f5SDamon Ding }
25912c66af11SDamon Ding
2592b6ba80b4SDamon Ding if (pd_data->parent_id) {
2593b6ba80b4SDamon Ding ret = vop2_power_domain_on(vop2, pd_data->parent_id);
259460e469f5SDamon Ding if (ret) {
259560e469f5SDamon Ding printf("can't open parent power domain\n");
259660e469f5SDamon Ding return -EINVAL;
259760e469f5SDamon Ding }
259860e469f5SDamon Ding }
259960e469f5SDamon Ding
2600a552a69cSDamon Ding /*
2601a552a69cSDamon Ding * Read VOP internal power domain on/off status.
2602a552a69cSDamon Ding * We should query BISR_STS register in PMU for
2603a552a69cSDamon Ding * power up/down status when memory repair is enabled.
2604a552a69cSDamon Ding * Return value: 1 for power on, 0 for power off;
2605a552a69cSDamon Ding */
2606a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576)
2607a552a69cSDamon Ding ret = rk3576_vop2_power_domain_on(vop2, pd_data);
2608a552a69cSDamon Ding else
2609a552a69cSDamon Ding ret = rk3588_vop2_power_domain_on(vop2, pd_data);
261060e469f5SDamon Ding
2611a552a69cSDamon Ding return ret;
261260e469f5SDamon Ding }
261360e469f5SDamon Ding
rk3588_vop2_regsbak(struct vop2 * vop2)2614ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2)
2615ecc31b6eSAndy Yan {
2616ecc31b6eSAndy Yan u32 *base = vop2->regs;
2617ecc31b6eSAndy Yan int i = 0;
2618ecc31b6eSAndy Yan
2619ecc31b6eSAndy Yan /*
2620ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU
2621ecc31b6eSAndy Yan */
2622ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++)
2623ecc31b6eSAndy Yan vop2->regsbak[i] = base[i];
2624ecc31b6eSAndy Yan }
2625ecc31b6eSAndy Yan
vop3_ignore_plane(struct vop2 * vop2,struct vop2_win_data * win)26265fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win)
26275fa6e665SDamon Ding {
26285fa6e665SDamon Ding if (!is_vop3(vop2))
26295fa6e665SDamon Ding return false;
26305fa6e665SDamon Ding
26315fa6e665SDamon Ding if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE &&
26325fa6e665SDamon Ding win->phys_id != ROCKCHIP_VOP2_ESMART0)
26335fa6e665SDamon Ding return true;
26345fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE &&
26355fa6e665SDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3))
26365fa6e665SDamon Ding return true;
26375fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE &&
26385fa6e665SDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART1)
26395fa6e665SDamon Ding return true;
2640a552a69cSDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE &&
2641a552a69cSDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART3)
2642a552a69cSDamon Ding return true;
26435fa6e665SDamon Ding else
26445fa6e665SDamon Ding return false;
26455fa6e665SDamon Ding }
26465fa6e665SDamon Ding
vop3_init_esmart_scale_engine(struct vop2 * vop2)26475fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2)
26485fa6e665SDamon Ding {
26495fa6e665SDamon Ding struct vop2_win_data *win_data;
2650fa4ecc32SDamon Ding int i;
26515fa6e665SDamon Ding u8 scale_engine_num = 0;
26525fa6e665SDamon Ding
26535fa6e665SDamon Ding /* store plane mask for vop2_fixup_dts */
2654fa4ecc32SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) {
2655fa4ecc32SDamon Ding win_data = &vop2->data->win_data[i];
26565fa6e665SDamon Ding if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data))
26575fa6e665SDamon Ding continue;
26585fa6e665SDamon Ding
26595fa6e665SDamon Ding win_data->scale_engine_num = scale_engine_num++;
26605fa6e665SDamon Ding }
26615fa6e665SDamon Ding }
26625fa6e665SDamon Ding
vop3_get_esmart_lb_mode(struct vop2 * vop2)2663a552a69cSDamon Ding static int vop3_get_esmart_lb_mode(struct vop2 *vop2)
2664a552a69cSDamon Ding {
2665a552a69cSDamon Ding const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map;
2666a552a69cSDamon Ding int i;
2667a552a69cSDamon Ding
2668a552a69cSDamon Ding if (!esmart_lb_mode_map)
2669a552a69cSDamon Ding return vop2->esmart_lb_mode;
2670a552a69cSDamon Ding
2671a552a69cSDamon Ding for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) {
2672a552a69cSDamon Ding if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode)
2673a552a69cSDamon Ding return esmart_lb_mode_map->lb_map_value;
2674a552a69cSDamon Ding esmart_lb_mode_map++;
2675a552a69cSDamon Ding }
2676a552a69cSDamon Ding
2677a552a69cSDamon Ding if (i == vop2->data->esmart_lb_mode_num)
2678a552a69cSDamon Ding printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode);
2679a552a69cSDamon Ding
2680a552a69cSDamon Ding return vop2->data->esmart_lb_mode_map[0].lb_map_value;
2681a552a69cSDamon Ding }
2682a552a69cSDamon Ding
vop2_plane_mask_to_possible_vp_mask(struct display_state * state)26836fea745cSDamon Ding static inline void vop2_plane_mask_to_possible_vp_mask(struct display_state *state)
2684d0408543SAndy Yan {
2685b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state;
26866fea745cSDamon Ding struct vop2 *vop2 = cstate->private;
2687b7195f56SDamon Ding const struct vop2_data *vop2_data = vop2->data;
26886fea745cSDamon Ding struct vop2_win_data *win_data;
2689b0989546SSandy Huang u32 plane_mask;
26906fea745cSDamon Ding u32 nr_planes;
26916fea745cSDamon Ding u32 phys_id;
26926fea745cSDamon Ding int i, j;
2693b0989546SSandy Huang
26946fea745cSDamon Ding for (i = 0; i < vop2_data->nr_layers; i++) {
26956fea745cSDamon Ding win_data = &vop2_data->win_data[i];
26966fea745cSDamon Ding win_data->possible_vp_mask = 0;
26976fea745cSDamon Ding }
26986fea745cSDamon Ding
26996fea745cSDamon Ding for (i = 0; i < vop2_data->nr_vps; i++) {
27006fea745cSDamon Ding plane_mask = cstate->crtc->vps[i].plane_mask;
27016fea745cSDamon Ding nr_planes = hweight32(plane_mask);
27026fea745cSDamon Ding
27036fea745cSDamon Ding for (j = 0; j < nr_planes; j++) {
27046fea745cSDamon Ding phys_id = ffs(plane_mask) - 1;
27056fea745cSDamon Ding win_data = vop2_find_win_by_phys_id(vop2, phys_id);
27066fea745cSDamon Ding win_data->possible_vp_mask |= BIT(i);
27076fea745cSDamon Ding plane_mask &= ~BIT(phys_id);
27086fea745cSDamon Ding }
27096fea745cSDamon Ding }
27106fea745cSDamon Ding }
27116fea745cSDamon Ding
27126fea745cSDamon Ding /*
27136fea745cSDamon Ding * The function checks whether the 'rockchip,plane-mask' property assigned
27146fea745cSDamon Ding * in DTS is valid.
27156fea745cSDamon Ding */
vop2_plane_mask_check(struct display_state * state)27166fea745cSDamon Ding static bool vop2_plane_mask_check(struct display_state *state)
27176fea745cSDamon Ding {
27186fea745cSDamon Ding struct crtc_state *cstate = &state->crtc_state;
27196fea745cSDamon Ding struct vop2 *vop2 = cstate->private;
27206fea745cSDamon Ding struct vop2_win_data *win_data;
27216fea745cSDamon Ding u32 assigned_plane_mask = 0, plane_mask = 0;
27226fea745cSDamon Ding u32 phys_id;
27236fea745cSDamon Ding u32 nr_planes;
2724b4fa21deSDamon Ding u8 primary_plane_id, cursor_plane_id;
27256fea745cSDamon Ding int i, j;
27266fea745cSDamon Ding
27276fea745cSDamon Ding /*
27286fea745cSDamon Ding * If plane mask is assigned in DTS, then every plane need to be assigned to
27296fea745cSDamon Ding * one of all the VPs, and no single plane can be assigned to more than one
27306fea745cSDamon Ding * VP.
27316fea745cSDamon Ding */
2732b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) {
2733b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask;
27345fc2b656SDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
2735b4fa21deSDamon Ding cursor_plane_id = cstate->crtc->vps[i].cursor_plane_id;
27366fea745cSDamon Ding nr_planes = hweight32(plane_mask);
2737b0989546SSandy Huang
27386fea745cSDamon Ding /*
27396fea745cSDamon Ding * If the plane mask and primary plane both are assigned in DTS, the
27406fea745cSDamon Ding * primary plane should be included in the plane mask of VPx.
27416fea745cSDamon Ding */
27426fea745cSDamon Ding if (plane_mask && primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
27436fea745cSDamon Ding !(BIT(primary_plane_id) & plane_mask)) {
27446fea745cSDamon Ding printf("Invalid primary plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n",
27456fea745cSDamon Ding vop2_plane_phys_id_to_string(primary_plane_id),
27466fea745cSDamon Ding BIT(primary_plane_id), i, plane_mask);
27476fea745cSDamon Ding return false;
274863cb669fSSandy Huang }
27496fea745cSDamon Ding
2750b4fa21deSDamon Ding if (cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
2751b4fa21deSDamon Ding cursor_plane_id == primary_plane_id) {
2752b4fa21deSDamon Ding printf("Assigned cursor plane of VP%d [%s] has been assigned as its pirmary plane\n",
2753b4fa21deSDamon Ding i, vop2_plane_phys_id_to_string(cursor_plane_id));
2754b4fa21deSDamon Ding return false;
2755b4fa21deSDamon Ding }
2756b4fa21deSDamon Ding
2757b4fa21deSDamon Ding /*
2758b4fa21deSDamon Ding * If the plane mask and cursor plane both are assigned in DTS, the
2759b4fa21deSDamon Ding * cursor plane should be included in the plane mask of VPx.
2760b4fa21deSDamon Ding */
2761b4fa21deSDamon Ding if (plane_mask && cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID &&
2762b4fa21deSDamon Ding !(BIT(cursor_plane_id) & plane_mask)) {
2763b4fa21deSDamon Ding printf("Invalid cursor plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n",
2764b4fa21deSDamon Ding vop2_plane_phys_id_to_string(cursor_plane_id),
2765b4fa21deSDamon Ding BIT(cursor_plane_id), i, plane_mask);
2766b4fa21deSDamon Ding return false;
2767b4fa21deSDamon Ding }
2768b4fa21deSDamon Ding
27696fea745cSDamon Ding /*
27706fea745cSDamon Ding * Every plane assigned to the specific VP should follow the constraints
27716fea745cSDamon Ding * of default &vop2_win_data.possible_vp_mask.
27726fea745cSDamon Ding */
27736fea745cSDamon Ding for (j = 0; j < nr_planes; j++) {
27746fea745cSDamon Ding phys_id = ffs(plane_mask) - 1;
27756fea745cSDamon Ding win_data = vop2_find_win_by_phys_id(vop2, phys_id);
27766fea745cSDamon Ding if (!win_data) {
27776fea745cSDamon Ding printf("Invalid plane id %d in VP%d assigned plane mask\n",
27786fea745cSDamon Ding phys_id, i);
27796fea745cSDamon Ding return false;
2780b0989546SSandy Huang }
27816fea745cSDamon Ding
27826fea745cSDamon Ding if (!(vop2_win_can_attach_to_vp(win_data, i))) {
27836fea745cSDamon Ding printf("%s can not attach to VP%d\n",
27846fea745cSDamon Ding vop2_plane_phys_id_to_string(phys_id), i);
27856fea745cSDamon Ding return false;
27866fea745cSDamon Ding }
27876fea745cSDamon Ding
27886fea745cSDamon Ding plane_mask &= ~BIT(phys_id);
27896fea745cSDamon Ding }
27906fea745cSDamon Ding
27916fea745cSDamon Ding if (assigned_plane_mask & cstate->crtc->vps[i].plane_mask) {
27926fea745cSDamon Ding printf("the same window can't be assigned to two vp\n");
27936fea745cSDamon Ding return false;
27946fea745cSDamon Ding }
27956fea745cSDamon Ding assigned_plane_mask |= cstate->crtc->vps[i].plane_mask;
27966fea745cSDamon Ding }
27976fea745cSDamon Ding
27986fea745cSDamon Ding if (assigned_plane_mask != vop2->data->plane_mask_base) {
27996fea745cSDamon Ding printf("all windows should be assigned, full plane mask: [0x%08x], current plane mask: [0x%08x]\n",
28006fea745cSDamon Ding vop2->data->plane_mask_base, assigned_plane_mask);
28016fea745cSDamon Ding return false;
28026fea745cSDamon Ding }
28036fea745cSDamon Ding
28046fea745cSDamon Ding /*
28056fea745cSDamon Ding * If plane_mask assigned in DTS is valid, then convert it to &vop2_win_data.possible_vp_mask
28066fea745cSDamon Ding * and replace the default one with it.
28076fea745cSDamon Ding */
28086fea745cSDamon Ding vop2_plane_mask_to_possible_vp_mask(state);
28096fea745cSDamon Ding
28106fea745cSDamon Ding return true;
28116fea745cSDamon Ding }
28126fea745cSDamon Ding
rockchip_cursor_plane_assign(struct display_state * state,u8 vp_id)2813b4fa21deSDamon Ding static void rockchip_cursor_plane_assign(struct display_state *state, u8 vp_id)
2814b4fa21deSDamon Ding {
2815b4fa21deSDamon Ding struct crtc_state *cstate = &state->crtc_state;
2816b4fa21deSDamon Ding struct vop2 *vop2 = cstate->private;
2817b4fa21deSDamon Ding struct vop2_win_data *win_data;
2818b4fa21deSDamon Ding int i, j;
2819b4fa21deSDamon Ding
2820b4fa21deSDamon Ding if (cstate->crtc->vps[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
2821b4fa21deSDamon Ding win_data = vop2_find_win_by_phys_id(vop2, cstate->crtc->vps[vp_id].cursor_plane_id);
2822b4fa21deSDamon Ding if (win_data) {
2823b4fa21deSDamon Ding if (vop2_win_can_attach_to_vp(win_data, vp_id))
2824b4fa21deSDamon Ding vop2->vp_plane_mask[vp_id].cursor_plane_id =
2825b4fa21deSDamon Ding cstate->crtc->vps[vp_id].cursor_plane_id;
2826b4fa21deSDamon Ding return;
2827b4fa21deSDamon Ding }
2828b4fa21deSDamon Ding }
2829b4fa21deSDamon Ding
2830b4fa21deSDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) {
2831b4fa21deSDamon Ding win_data = &vop2->data->win_data[i];
2832b4fa21deSDamon Ding
2833b4fa21deSDamon Ding if (win_data->plane_type != VOP2_PLANE_TYPE_CURSOR)
2834b4fa21deSDamon Ding continue;
2835b4fa21deSDamon Ding
2836b4fa21deSDamon Ding if (!vop2_win_can_attach_to_vp(win_data, vp_id))
2837b4fa21deSDamon Ding continue;
2838b4fa21deSDamon Ding
2839b4fa21deSDamon Ding for (j = 0; j < vop2->data->nr_vps; j++) {
2840b4fa21deSDamon Ding if (win_data->phys_id == vop2->vp_plane_mask[j].cursor_plane_id)
2841b4fa21deSDamon Ding break;
2842b4fa21deSDamon Ding }
2843b4fa21deSDamon Ding
2844b4fa21deSDamon Ding /* The win has been used as the cursor plane for other VPs */
2845b4fa21deSDamon Ding if (j < vop2->data->nr_vps)
2846b4fa21deSDamon Ding continue;
2847b4fa21deSDamon Ding
2848b4fa21deSDamon Ding vop2->vp_plane_mask[vp_id].cursor_plane_id = win_data->phys_id;
2849b4fa21deSDamon Ding return;
2850b4fa21deSDamon Ding }
2851b4fa21deSDamon Ding
2852b4fa21deSDamon Ding vop2->vp_plane_mask[vp_id].cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
2853b4fa21deSDamon Ding }
2854b4fa21deSDamon Ding
28556fea745cSDamon Ding /*
28566fea745cSDamon Ding * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in
28576fea745cSDamon Ding * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched
28586fea745cSDamon Ding * between different CRTCs flexibly and the userspace do not need
2859ef0607a7SDamon Ding * the plane_mask to restrict the switch between the crtc and plane.
28606fea745cSDamon Ding * We just find a expected plane for logo display.
28616fea745cSDamon Ding */
rk3528_assign_plane_mask(struct display_state * state)2862ef0607a7SDamon Ding static void rk3528_assign_plane_mask(struct display_state *state)
2863ef0607a7SDamon Ding {
2864ef0607a7SDamon Ding struct crtc_state *cstate = &state->crtc_state;
2865ef0607a7SDamon Ding struct vop2 *vop2 = cstate->private;
2866ef0607a7SDamon Ding struct vop2_win_data *win_data;
2867ef0607a7SDamon Ding int active_vp_num = 0;
2868ef0607a7SDamon Ding int i, j, k;
2869ef0607a7SDamon Ding
2870ef0607a7SDamon Ding printf("Assign default plane mask\n");
2871ef0607a7SDamon Ding
2872a552a69cSDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
28736fea745cSDamon Ding if (!cstate->crtc->vps[i].enable)
28746fea745cSDamon Ding continue;
28756fea745cSDamon Ding
28766fea745cSDamon Ding for (j = 0; j < vop2->data->nr_layers; j++) {
28776fea745cSDamon Ding win_data = &vop2->data->win_data[j];
28786fea745cSDamon Ding
28796fea745cSDamon Ding if (win_data->plane_type != VOP2_PLANE_TYPE_PRIMARY)
28806fea745cSDamon Ding continue;
28816fea745cSDamon Ding
28826fea745cSDamon Ding if (!vop2_win_can_attach_to_vp(win_data, i))
28836fea745cSDamon Ding continue;
28846fea745cSDamon Ding
28856fea745cSDamon Ding for (k = 0; k < vop2->data->nr_vps; k++) {
28866fea745cSDamon Ding if (win_data->phys_id == vop2->vp_plane_mask[k].primary_plane_id)
28876fea745cSDamon Ding break;
2888a552a69cSDamon Ding }
28896fea745cSDamon Ding
28906fea745cSDamon Ding /* The win has been used as the primary plane for other VPs */
28916fea745cSDamon Ding if (k < vop2->data->nr_vps)
28926fea745cSDamon Ding continue;
28936fea745cSDamon Ding
28946fea745cSDamon Ding vop2->vp_plane_mask[i].attached_layers_nr = 1;
28956fea745cSDamon Ding vop2->vp_plane_mask[i].primary_plane_id = win_data->phys_id;
28966fea745cSDamon Ding vop2->vp_plane_mask[i].attached_layers[0] = win_data->phys_id;
28976fea745cSDamon Ding vop2->vp_plane_mask[i].plane_mask |= BIT(win_data->phys_id);
28986fea745cSDamon Ding active_vp_num++;
28996fea745cSDamon Ding break;
29006fea745cSDamon Ding }
29016fea745cSDamon Ding
29026fea745cSDamon Ding if (vop2->vp_plane_mask[i].primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
29036fea745cSDamon Ding printf("ERROR: No primary plane find for video_port%d\n", i);
290465365de1SDamon Ding
290565365de1SDamon Ding rockchip_cursor_plane_assign(state, i);
2906a552a69cSDamon Ding }
2907a552a69cSDamon Ding printf("VOP have %d active VP\n", active_vp_num);
2908ef0607a7SDamon Ding }
2909ef0607a7SDamon Ding
rk3568_assign_plane_mask(struct display_state * state)2910ef0607a7SDamon Ding static void rk3568_assign_plane_mask(struct display_state *state)
2911ef0607a7SDamon Ding {
2912ef0607a7SDamon Ding struct crtc_state *cstate = &state->crtc_state;
2913ef0607a7SDamon Ding struct vop2 *vop2 = cstate->private;
2914ef0607a7SDamon Ding struct vop2_vp_plane_mask *plane_mask;
2915ef0607a7SDamon Ding u32 nr_planes = 0;
2916ef0607a7SDamon Ding int active_vp_num = 0;
2917ef0607a7SDamon Ding int main_vp_index = -1;
2918ef0607a7SDamon Ding int layer_phy_id = 0;
2919ef0607a7SDamon Ding int i, j;
2920ef0607a7SDamon Ding
2921ef0607a7SDamon Ding printf("Assign default plane mask\n");
2922ef0607a7SDamon Ding
2923b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) {
292465365de1SDamon Ding if (cstate->crtc->vps[i].enable)
2925b0989546SSandy Huang active_vp_num++;
2926b0989546SSandy Huang }
292765365de1SDamon Ding
2928b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num);
2929b0989546SSandy Huang
2930b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2)
2931b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n");
2932b0989546SSandy Huang plane_mask = vop2->data->plane_mask;
2933b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX;
2934b0989546SSandy Huang
29357a290128SDamon Ding /*
29367a290128SDamon Ding * For RK3566, the main planes should be enabled before the mirror planes.
29377a290128SDamon Ding * The devices that support hot plug may be disconnected initially, so we
29387a290128SDamon Ding * assign the main planes to the first device that does not support hot
29397a290128SDamon Ding * plug, in order to ensure that the mirror planes are not enabled first.
29407a290128SDamon Ding */
29417a290128SDamon Ding if (soc_is_rk3566()) {
2942b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) {
2943b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) {
2944a552a69cSDamon Ding /* the first store main display plane mask */
2945a552a69cSDamon Ding vop2->vp_plane_mask[i] = plane_mask[0];
2946b0989546SSandy Huang main_vp_index = i;
2947e007876dSSandy Huang break;
2948b0989546SSandy Huang }
2949b0989546SSandy Huang }
2950b0989546SSandy Huang
2951b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */
2952b0989546SSandy Huang if (main_vp_index < 0) {
2953b0989546SSandy Huang main_vp_index = 0;
2954b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0];
2955b0989546SSandy Huang }
2956b0989546SSandy Huang
2957a552a69cSDamon Ding /* plane_mask[0] store main display, so we from plane_mask[1] */
2958a552a69cSDamon Ding j = 1;
29597a290128SDamon Ding } else {
29607a290128SDamon Ding /*
29617a290128SDamon Ding * For the platforms except RK3566, we assign the plane mask of
29627a290128SDamon Ding * VPx according to the &vop2_data.plane_mask[active_vp_num][x].
29637a290128SDamon Ding */
29647a290128SDamon Ding j = 0;
29657a290128SDamon Ding }
2966b0989546SSandy Huang
2967b0989546SSandy Huang /* init other display except main display */
2968b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) {
2969a552a69cSDamon Ding /* main display or no connect devices */
2970a552a69cSDamon Ding if (i == main_vp_index || !cstate->crtc->vps[i].enable)
2971b0989546SSandy Huang continue;
2972b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++];
297383d6b087SDamon Ding /*
297483d6b087SDamon Ding * For rk3588, the main window should attach to the VP0 while
297583d6b087SDamon Ding * the splice window should attach to the VP1 when the display
297683d6b087SDamon Ding * mode is over 4k.
297783d6b087SDamon Ding * If only one VP is enabled and the plane mask is not assigned
297883d6b087SDamon Ding * in DTS, all main windows will be assigned to the enabled VPx,
297983d6b087SDamon Ding * and all splice windows will be assigned to the VPx+1, in order
298083d6b087SDamon Ding * to ensure that the splice mode work well.
298183d6b087SDamon Ding */
298283d6b087SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && active_vp_num == 1)
298383d6b087SDamon Ding vop2->vp_plane_mask[(i + 1) % vop2->data->nr_vps] = plane_mask[j++];
2984b0989546SSandy Huang }
29856fea745cSDamon Ding
2986b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */
2987b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) {
29886fea745cSDamon Ding nr_planes = vop2->vp_plane_mask[i].attached_layers_nr;
29896fea745cSDamon Ding for (j = 0; j < nr_planes; j++) {
2990b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
2991b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id);
2992b0989546SSandy Huang }
2993b0989546SSandy Huang }
299465365de1SDamon Ding
299565365de1SDamon Ding /*
299665365de1SDamon Ding * For RK3568 and RK3588, to aovid &vop2.vp_plane_mask[].cursor_plane_id
299765365de1SDamon Ding * being overwritten by &vop2.data->plane_mask[].cursor_plane_id, which
299865365de1SDamon Ding * is always 0, the assignment of cursor plane should be placed at the
299965365de1SDamon Ding * end.
300065365de1SDamon Ding */
300165365de1SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
300265365de1SDamon Ding vop2->vp_plane_mask[i].cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
300365365de1SDamon Ding if (cstate->crtc->vps[i].enable)
300465365de1SDamon Ding rockchip_cursor_plane_assign(state, i);
300565365de1SDamon Ding }
3006b0989546SSandy Huang }
30076fea745cSDamon Ding
vop2_global_initial(struct vop2 * vop2,struct display_state * state)30086fea745cSDamon Ding static void vop2_global_initial(struct vop2 *vop2, struct display_state *state)
30096fea745cSDamon Ding {
30106fea745cSDamon Ding struct crtc_state *cstate = &state->crtc_state;
30116fea745cSDamon Ding const struct vop2_data *vop2_data = vop2->data;
30126fea745cSDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops;
30132d3a2f01SDamon Ding struct vop2_vp_plane_mask *vp_plane_mask;
30146fea745cSDamon Ding u32 nr_planes = 0;
30156fea745cSDamon Ding u32 plane_mask;
30166fea745cSDamon Ding u8 primary_plane_id;
30176fea745cSDamon Ding const u8 *tmp;
30186fea745cSDamon Ding int i, j;
30196fea745cSDamon Ding
30206fea745cSDamon Ding if (vop2->global_init)
30216fea745cSDamon Ding return;
30226fea745cSDamon Ding
30232d3a2f01SDamon Ding /*
30242d3a2f01SDamon Ding * Initialize struct vop2_vp_plane_mask, whose main function is to
30252d3a2f01SDamon Ding * fixup the DTS.
30262d3a2f01SDamon Ding */
30272d3a2f01SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
30282d3a2f01SDamon Ding vp_plane_mask = &vop2->vp_plane_mask[i];
30292d3a2f01SDamon Ding /*
30302d3a2f01SDamon Ding * Set default value of the primary plane id and cursor plane
30312d3a2f01SDamon Ding * id to invalid.
30322d3a2f01SDamon Ding */
30332d3a2f01SDamon Ding vp_plane_mask->primary_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
30342d3a2f01SDamon Ding vp_plane_mask->cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID;
30352d3a2f01SDamon Ding }
30362d3a2f01SDamon Ding
30376fea745cSDamon Ding /* OTP must enable at the first time, otherwise mirror layer register is error */
30386fea745cSDamon Ding if (soc_is_rk3566())
30396fea745cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK,
30406fea745cSDamon Ding OTP_WIN_EN_SHIFT, 1, false);
30416fea745cSDamon Ding
30426fea745cSDamon Ding /* The plane mask is assigned in DTS */
30436fea745cSDamon Ding if (cstate->crtc->assign_plane) {
30446fea745cSDamon Ding /* check whether plane mask and primary plane are valid */
30456fea745cSDamon Ding if (vop2_plane_mask_check(state)) {
30466fea745cSDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
30476fea745cSDamon Ding plane_mask = cstate->crtc->vps[i].plane_mask;
30486fea745cSDamon Ding nr_planes = hweight32(plane_mask); /* use bitmap to store plane mask */
30496fea745cSDamon Ding vop2->vp_plane_mask[i].attached_layers_nr = nr_planes;
30506fea745cSDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id;
30516fea745cSDamon Ding /*
30526fea745cSDamon Ding * If the primary plane of specific VP is not assigned
30536fea745cSDamon Ding * in DTS, find a proper primary plane according to the
30546fea745cSDamon Ding * &vop2_win_data.possible_vp_mask.
30556fea745cSDamon Ding */
30566fea745cSDamon Ding if (primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID)
30576fea745cSDamon Ding primary_plane_id = vop2_vp_find_attachable_win(state, i);
30586fea745cSDamon Ding vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id;
30596fea745cSDamon Ding vop2->vp_plane_mask[i].plane_mask = plane_mask;
30606fea745cSDamon Ding
30616fea745cSDamon Ding /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id] */
30626fea745cSDamon Ding for (j = 0; j < nr_planes; j++) {
30636fea745cSDamon Ding vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1;
30646fea745cSDamon Ding plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]);
30656fea745cSDamon Ding }
30666fea745cSDamon Ding }
30676fea745cSDamon Ding } else {
3068ef0607a7SDamon Ding vop2_ops->assign_plane_mask(state);
30696fea745cSDamon Ding }
30706fea745cSDamon Ding } else {
30716fea745cSDamon Ding /*
30726fea745cSDamon Ding * If no plane mask assignment, plane mask and primary plane will be
30736fea745cSDamon Ding * assigned automatically.
30746fea745cSDamon Ding */
3075ef0607a7SDamon Ding vop2_ops->assign_plane_mask(state);
30766fea745cSDamon Ding }
3077b0989546SSandy Huang
307860e469f5SDamon Ding if (vop2->version == VOP_VERSION_RK3588)
307960e469f5SDamon Ding rk3588_vop2_regsbak(vop2);
308060e469f5SDamon Ding else
308160e469f5SDamon Ding memcpy(vop2->regsbak, vop2->regs, vop2->reg_len);
308260e469f5SDamon Ding
308360e469f5SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK,
308460e469f5SDamon Ding OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false);
308560e469f5SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
308660e469f5SDamon Ding IF_CTRL_REG_DONE_IMD_SHIFT, 1, false);
308760e469f5SDamon Ding
3088b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) {
3089b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr);
3090b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++)
309127cec8e2SDamon Ding printf("%s ",
3092a7cb29b7SDamon Ding vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].attached_layers[j]));
309327cec8e2SDamon Ding printf("], primary plane: %s\n",
3094a7cb29b7SDamon Ding vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].primary_plane_id));
3095b0989546SSandy Huang }
3096b0989546SSandy Huang
3097b7195f56SDamon Ding vop2_ops->setup_overlay(state);
3098b0989546SSandy Huang
30995fa6e665SDamon Ding if (is_vop3(vop2)) {
31005fa6e665SDamon Ding /*
31015fa6e665SDamon Ding * you can rewrite at dts vop node:
31025fa6e665SDamon Ding *
31035fa6e665SDamon Ding * VOP3_ESMART_8K_MODE = 0,
31045fa6e665SDamon Ding * VOP3_ESMART_4K_4K_MODE = 1,
31055fa6e665SDamon Ding * VOP3_ESMART_4K_2K_2K_MODE = 2,
31065fa6e665SDamon Ding * VOP3_ESMART_2K_2K_2K_2K_MODE = 3,
31075fa6e665SDamon Ding *
31085fa6e665SDamon Ding * &vop {
31095fa6e665SDamon Ding * esmart_lb_mode = /bits/ 8 <2>;
31105fa6e665SDamon Ding * };
311163cb669fSSandy Huang */
311251e1509eSDamon Ding tmp = dev_read_u8_array_ptr(cstate->dev, "esmart_lb_mode", 1);
311351e1509eSDamon Ding if (tmp)
311451e1509eSDamon Ding vop2->esmart_lb_mode = *tmp;
311551e1509eSDamon Ding else
31165fa6e665SDamon Ding vop2->esmart_lb_mode = vop2->data->esmart_lb_mode;
3117a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576)
3118a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL,
3119a552a69cSDamon Ding RK3576_ESMART_LB_MODE_SEL_MASK,
3120a552a69cSDamon Ding RK3576_ESMART_LB_MODE_SEL_SHIFT,
3121a552a69cSDamon Ding vop3_get_esmart_lb_mode(vop2), true);
3122a552a69cSDamon Ding else
3123a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL,
3124a552a69cSDamon Ding ESMART_LB_MODE_SEL_MASK,
3125a552a69cSDamon Ding ESMART_LB_MODE_SEL_SHIFT,
3126f6e9a2a3SDamon Ding vop3_get_esmart_lb_mode(vop2), false);
3127d0408543SAndy Yan
31285fa6e665SDamon Ding vop3_init_esmart_scale_engine(vop2);
3129aa670293SDamon Ding
313012ee4de7SDamon Ding if (vop2->version == VOP_VERSION_RK3576)
313112ee4de7SDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
313212ee4de7SDamon Ding RK3576_DSP_VS_T_SEL_SHIFT, 0, true);
313312ee4de7SDamon Ding else
3134aa670293SDamon Ding vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK,
3135aa670293SDamon Ding DSP_VS_T_SEL_SHIFT, 0, false);
3136bb7ec356SDamon Ding
3137bb7ec356SDamon Ding /*
3138bb7ec356SDamon Ding * This is a workaround for RK3528/RK3562/RK3576:
3139bb7ec356SDamon Ding *
3140bb7ec356SDamon Ding * The aclk pre auto gating function may disable the aclk
3141bb7ec356SDamon Ding * in some unexpected cases, which detected by hardware
3142bb7ec356SDamon Ding * automatically.
3143bb7ec356SDamon Ding *
3144bb7ec356SDamon Ding * For example, if the above function is enabled, the post
3145bb7ec356SDamon Ding * scale function will be affected, resulting in abnormal
3146bb7ec356SDamon Ding * display.
3147bb7ec356SDamon Ding */
3148bb7ec356SDamon Ding if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 ||
3149bb7ec356SDamon Ding vop2->version == VOP_VERSION_RK3576)
3150bb7ec356SDamon Ding vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK,
3151bb7ec356SDamon Ding ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false);
315263cb669fSSandy Huang }
315363cb669fSSandy Huang
3154ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568)
315563cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0);
315663cb669fSSandy Huang
3157a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) {
3158a552a69cSDamon Ding vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq");
3159a552a69cSDamon Ding
3160dad2c246SSandy Huang /* Default use rkiommu 2.0 for axi0 */
3161dad2c246SSandy Huang vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 1, true);
3162a552a69cSDamon Ding
3163a552a69cSDamon Ding /* Init frc2.0 config */
3164a552a69cSDamon Ding vop2_writel(vop2, 0xca0, 0xc8);
3165a552a69cSDamon Ding vop2_writel(vop2, 0xca4, 0x01000100);
3166a552a69cSDamon Ding vop2_writel(vop2, 0xca8, 0x03ff0100);
3167a552a69cSDamon Ding vop2_writel(vop2, 0xda0, 0xc8);
3168a552a69cSDamon Ding vop2_writel(vop2, 0xda4, 0x01000100);
3169a552a69cSDamon Ding vop2_writel(vop2, 0xda8, 0x03ff0100);
3170a552a69cSDamon Ding
3171a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true)
3172a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK,
3173a552a69cSDamon Ding VP_INTR_MERGE_EN_SHIFT, 1, true);
3174a552a69cSDamon Ding
3175a552a69cSDamon Ding /* Set reg done every field for interlace */
3176a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK,
3177a552a69cSDamon Ding INTERLACE_FRM_REG_DONE_SHIFT, 0, false);
3178a552a69cSDamon Ding }
3179a552a69cSDamon Ding
318063cb669fSSandy Huang vop2->global_init = true;
3181d0408543SAndy Yan }
3182d0408543SAndy Yan
rockchip_vop2_sharp_init(struct vop2 * vop2,struct display_state * state)3183344e932aSDamon Ding static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state)
3184344e932aSDamon Ding {
3185344e932aSDamon Ding struct crtc_state *cstate = &state->crtc_state;
3186344e932aSDamon Ding const struct vop2_data *vop2_data = vop2->data;
3187344e932aSDamon Ding const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
318845ec9215SDamon Ding struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
3189344e932aSDamon Ding struct resource sharp_regs;
3190344e932aSDamon Ding int ret;
3191344e932aSDamon Ding
319245ec9215SDamon Ding if (!(vp_data->feature & VOP_FEATURE_POST_SHARP) || !vp->sharp_en)
3193344e932aSDamon Ding return;
3194344e932aSDamon Ding
3195344e932aSDamon Ding ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs);
3196344e932aSDamon Ding if (ret) {
3197344e932aSDamon Ding printf("failed to get sharp regs\n");
3198344e932aSDamon Ding return;
3199344e932aSDamon Ding }
320045ec9215SDamon Ding vop2->sharp_res = (void *)sharp_regs.start;
3201344e932aSDamon Ding
3202344e932aSDamon Ding /*
3203344e932aSDamon Ding * After vop initialization, keep sw_sharp_enable always on.
3204344e932aSDamon Ding * Only enable/disable sharp submodule to avoid black screen.
3205344e932aSDamon Ding */
320645ec9215SDamon Ding writel(true << SW_SHARP_ENABLE_SHIFT, vop2->sharp_res + RK3576_SHARP_CTRL);
3207344e932aSDamon Ding }
3208344e932aSDamon Ding
rockchip_vop2_acm_init(struct vop2 * vop2,struct display_state * state)3209c54cc5d2SAlgea Cao static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state)
3210c54cc5d2SAlgea Cao {
3211c54cc5d2SAlgea Cao struct crtc_state *cstate = &state->crtc_state;
3212c54cc5d2SAlgea Cao const struct vop2_data *vop2_data = vop2->data;
3213c54cc5d2SAlgea Cao const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id];
3214c54cc5d2SAlgea Cao struct resource acm_regs;
3215c54cc5d2SAlgea Cao u32 *acm_reg_base;
3216c54cc5d2SAlgea Cao u32 vp_offset = (cstate->crtc_id * 0x100);
3217c54cc5d2SAlgea Cao int ret;
3218c54cc5d2SAlgea Cao
3219c54cc5d2SAlgea Cao if (!(vp_data->feature & VOP_FEATURE_POST_ACM))
3220c54cc5d2SAlgea Cao return;
3221c54cc5d2SAlgea Cao
3222c54cc5d2SAlgea Cao ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs);
3223c54cc5d2SAlgea Cao if (ret) {
3224c54cc5d2SAlgea Cao printf("failed to get acm regs\n");
3225c54cc5d2SAlgea Cao return;
3226c54cc5d2SAlgea Cao }
3227c54cc5d2SAlgea Cao acm_reg_base = (u32 *)acm_regs.start;
3228c54cc5d2SAlgea Cao
3229c54cc5d2SAlgea Cao /*
3230c54cc5d2SAlgea Cao * Black screen is displayed when acm bypass switched
3231c54cc5d2SAlgea Cao * between enable and disable. Therefore, disable acm
3232c54cc5d2SAlgea Cao * bypass by default after system boot.
3233c54cc5d2SAlgea Cao */
3234c54cc5d2SAlgea Cao vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset,
3235c54cc5d2SAlgea Cao POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false);
3236c54cc5d2SAlgea Cao
3237e1946cbdSAlgea Cao writel(0, acm_reg_base + 0);
3238c54cc5d2SAlgea Cao }
3239c54cc5d2SAlgea Cao
rockchip_vop2_of_get_gamma_lut(struct display_state * state,struct device_node * dsp_lut_node)32400669ab1fSDamon Ding static int rockchip_vop2_of_get_gamma_lut(struct display_state *state,
32410669ab1fSDamon Ding struct device_node *dsp_lut_node)
32420669ab1fSDamon Ding {
32430669ab1fSDamon Ding struct crtc_state *cstate = &state->crtc_state;
32440669ab1fSDamon Ding struct resource gamma_res;
32450669ab1fSDamon Ding fdt_size_t lut_size;
32460669ab1fSDamon Ding u32 *lut_regs;
32470669ab1fSDamon Ding u32 *lut;
32480669ab1fSDamon Ding u32 r, g, b;
32490669ab1fSDamon Ding int lut_len;
32500669ab1fSDamon Ding int length;
32510669ab1fSDamon Ding int i, j;
32520669ab1fSDamon Ding int ret = 0;
32530669ab1fSDamon Ding
32540669ab1fSDamon Ding of_get_property(dsp_lut_node, "gamma-lut", &length);
32550669ab1fSDamon Ding if (!length)
32560669ab1fSDamon Ding return -EINVAL;
32570669ab1fSDamon Ding
32580669ab1fSDamon Ding ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res);
32590669ab1fSDamon Ding if (ret)
32600669ab1fSDamon Ding printf("failed to get gamma lut res\n");
32610669ab1fSDamon Ding lut_regs = (u32 *)gamma_res.start;
32620669ab1fSDamon Ding lut_size = gamma_res.end - gamma_res.start + 1;
32630669ab1fSDamon Ding if (lut_regs == (u32 *)FDT_ADDR_T_NONE) {
32640669ab1fSDamon Ding printf("failed to get gamma lut register\n");
32650669ab1fSDamon Ding return -EINVAL;
32660669ab1fSDamon Ding }
32670669ab1fSDamon Ding lut_len = lut_size / 4;
32680669ab1fSDamon Ding
32690669ab1fSDamon Ding cstate->lut_val = (u32 *)calloc(1, lut_size);
32700669ab1fSDamon Ding if (!cstate->lut_val)
32710669ab1fSDamon Ding return -ENOMEM;
32720669ab1fSDamon Ding
32730669ab1fSDamon Ding length >>= 2;
32740669ab1fSDamon Ding if (length != lut_len) {
32750669ab1fSDamon Ding lut = (u32 *)calloc(1, lut_len);
32760669ab1fSDamon Ding if (!lut) {
32770669ab1fSDamon Ding free(cstate->lut_val);
32780669ab1fSDamon Ding return -ENOMEM;
32790669ab1fSDamon Ding }
32800669ab1fSDamon Ding
32810669ab1fSDamon Ding ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length);
32820669ab1fSDamon Ding if (ret) {
32830669ab1fSDamon Ding printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id);
32840669ab1fSDamon Ding free(cstate->lut_val);
32850669ab1fSDamon Ding free(lut);
32860669ab1fSDamon Ding return -EINVAL;
32870669ab1fSDamon Ding }
32880669ab1fSDamon Ding
32890669ab1fSDamon Ding /*
32900669ab1fSDamon Ding * In order to achieve the same gamma correction effect in different
32910669ab1fSDamon Ding * platforms, the following conversion helps to translate from 8bit
32920669ab1fSDamon Ding * gamma table with 256 parameters to 10bit gamma with 1024 parameters.
32930669ab1fSDamon Ding */
32940669ab1fSDamon Ding for (i = 0; i < lut_len; i++) {
32950669ab1fSDamon Ding j = i * length / lut_len;
32960669ab1fSDamon Ding r = lut[j] / length / length * lut_len / length;
32970669ab1fSDamon Ding g = lut[j] / length % length * lut_len / length;
32980669ab1fSDamon Ding b = lut[j] % length * lut_len / length;
32990669ab1fSDamon Ding
33000669ab1fSDamon Ding cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b;
33010669ab1fSDamon Ding }
33020669ab1fSDamon Ding free(lut);
33030669ab1fSDamon Ding } else {
33040669ab1fSDamon Ding of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len);
33050669ab1fSDamon Ding }
33060669ab1fSDamon Ding
33070669ab1fSDamon Ding return 0;
33080669ab1fSDamon Ding }
33090669ab1fSDamon Ding
rockchip_vop2_of_get_dsp_lut(struct vop2 * vop2,struct display_state * state)33100669ab1fSDamon Ding static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state)
33110669ab1fSDamon Ding {
33120669ab1fSDamon Ding struct crtc_state *cstate = &state->crtc_state;
33130669ab1fSDamon Ding struct device_node *dsp_lut_node;
33140669ab1fSDamon Ding int phandle;
33150669ab1fSDamon Ding int ret = 0;
33160669ab1fSDamon Ding
33170669ab1fSDamon Ding phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1);
33180669ab1fSDamon Ding if (phandle < 0)
33190669ab1fSDamon Ding return;
33200669ab1fSDamon Ding
33210669ab1fSDamon Ding dsp_lut_node = of_find_node_by_phandle(phandle);
33220669ab1fSDamon Ding if (!dsp_lut_node)
33230669ab1fSDamon Ding return;
33240669ab1fSDamon Ding
33250669ab1fSDamon Ding ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node);
33260669ab1fSDamon Ding if (ret)
33270669ab1fSDamon Ding printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id);
33280669ab1fSDamon Ding }
33290669ab1fSDamon Ding
vop2_initial(struct vop2 * vop2,struct display_state * state)3330d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state)
3331d0408543SAndy Yan {
33320669ab1fSDamon Ding rockchip_vop2_of_get_dsp_lut(vop2, state);
33330669ab1fSDamon Ding
33341147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state);
33356414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state);
3336344e932aSDamon Ding rockchip_vop2_sharp_init(vop2, state);
3337c54cc5d2SAlgea Cao rockchip_vop2_acm_init(vop2, state);
3338d0408543SAndy Yan
3339d0408543SAndy Yan return 0;
3340d0408543SAndy Yan }
3341d0408543SAndy Yan
3342d0408543SAndy Yan /*
3343d0408543SAndy Yan * VOP2 have multi video ports.
3344d0408543SAndy Yan * video port ------- crtc
3345d0408543SAndy Yan */
rockchip_vop2_preinit(struct display_state * state)3346d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state)
3347d0408543SAndy Yan {
3348d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state;
3349d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data;
3350734a0ce6SDamon Ding struct regmap *map;
3351789e70ecSFinley Xiao #if defined(CONFIG_MOS_SUPPORT) && !defined(CONFIG_SPL_BUILD)
3352789e70ecSFinley Xiao struct power_domain pwrdom;
3353789e70ecSFinley Xiao struct clk_bulk clks;
3354789e70ecSFinley Xiao #endif
33550686a6a6SZhang Yubing char dclk_name[16];
33560686a6a6SZhang Yubing int ret;
3357d0408543SAndy Yan
3358d0408543SAndy Yan if (!rockchip_vop2) {
33590d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2));
3360d0408543SAndy Yan if (!rockchip_vop2)
3361d0408543SAndy Yan return -ENOMEM;
3362d8e7f4a5SSandy Huang memset(rockchip_vop2, 0, sizeof(struct vop2));
3363d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG);
3364d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG;
3365d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD
3366d8e7f4a5SSandy Huang rockchip_vop2->regs = (void *)RK3528_VOP_BASE;
3367d8e7f4a5SSandy Huang #else
3368d8e7f4a5SSandy Huang rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev);
3369734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf");
3370734a0ce6SDamon Ding rockchip_vop2->grf = regmap_get_range(map, 0);
3371d0408543SAndy Yan if (rockchip_vop2->grf <= 0)
337263cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf);
3373d8e7f4a5SSandy Huang #endif
3374d0408543SAndy Yan rockchip_vop2->version = vop2_data->version;
3375d0408543SAndy Yan rockchip_vop2->data = vop2_data;
3376ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) {
3377734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf");
3378734a0ce6SDamon Ding rockchip_vop2->vop_grf = regmap_get_range(map, 0);
3379ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0)
3380a552a69cSDamon Ding printf("%s: Get syscon vop_grf failed (ret=%p)\n",
3381a552a69cSDamon Ding __func__, rockchip_vop2->vop_grf);
3382b890760eSAlgea Cao map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf");
3383b890760eSAlgea Cao rockchip_vop2->vo1_grf = regmap_get_range(map, 0);
3384ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0)
3385a552a69cSDamon Ding printf("%s: Get syscon vo1_grf failed (ret=%p)\n",
3386a552a69cSDamon Ding __func__, rockchip_vop2->vo1_grf);
3387734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3388734a0ce6SDamon Ding rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3389b890760eSAlgea Cao if (rockchip_vop2->sys_pmu <= 0)
3390a552a69cSDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3391a552a69cSDamon Ding __func__, rockchip_vop2->sys_pmu);
3392a552a69cSDamon Ding } else if (rockchip_vop2->version == VOP_VERSION_RK3576) {
3393a552a69cSDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf");
3394a552a69cSDamon Ding rockchip_vop2->ioc_grf = regmap_get_range(map, 0);
3395a552a69cSDamon Ding if (rockchip_vop2->ioc_grf <= 0)
3396a552a69cSDamon Ding printf("%s: Get syscon ioc_grf failed (ret=%p)\n",
3397a552a69cSDamon Ding __func__, rockchip_vop2->ioc_grf);
3398a552a69cSDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu");
3399a552a69cSDamon Ding rockchip_vop2->sys_pmu = regmap_get_range(map, 0);
3400a552a69cSDamon Ding if (rockchip_vop2->sys_pmu <= 0)
3401a552a69cSDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n",
3402a552a69cSDamon Ding __func__, rockchip_vop2->sys_pmu);
3403ecc31b6eSAndy Yan }
3404789e70ecSFinley Xiao #if defined(CONFIG_MOS_SUPPORT) && !defined(CONFIG_SPL_BUILD)
3405789e70ecSFinley Xiao ret = power_domain_get(cstate->dev, &pwrdom);
3406789e70ecSFinley Xiao if (ret) {
3407789e70ecSFinley Xiao printf("failed to get pwrdom: %d\n", ret);
3408789e70ecSFinley Xiao return ret;
3409789e70ecSFinley Xiao }
3410789e70ecSFinley Xiao ret = power_domain_on(&pwrdom);
3411789e70ecSFinley Xiao if (ret) {
3412789e70ecSFinley Xiao printf("failed to power on pd: %d\n", ret);
3413789e70ecSFinley Xiao return ret;
3414789e70ecSFinley Xiao }
3415789e70ecSFinley Xiao ret = clk_get_bulk(cstate->dev, &clks);
3416789e70ecSFinley Xiao if (ret) {
3417789e70ecSFinley Xiao if (ret != -ENOSYS && ret != -ENOENT) {
3418789e70ecSFinley Xiao printf("failed to get clk: %d\n", ret);
3419789e70ecSFinley Xiao return ret;
3420789e70ecSFinley Xiao }
3421789e70ecSFinley Xiao }
3422789e70ecSFinley Xiao ret = clk_enable_bulk(&clks);
3423789e70ecSFinley Xiao if (ret) {
3424789e70ecSFinley Xiao printf("failed to enable clk: %d\n", ret);
3425789e70ecSFinley Xiao clk_release_bulk(&clks);
3426789e70ecSFinley Xiao return ret;
3427789e70ecSFinley Xiao }
3428789e70ecSFinley Xiao #endif
3429d0408543SAndy Yan }
3430d0408543SAndy Yan
34310686a6a6SZhang Yubing snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
3432a2ce7568SDamon Ding if (dev_read_stringlist_search(cstate->dev, "reset-names", dclk_name) > 0) {
34330686a6a6SZhang Yubing ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst);
34340686a6a6SZhang Yubing if (ret < 0) {
34350686a6a6SZhang Yubing printf("%s: failed to get dclk reset: %d\n", __func__, ret);
34360686a6a6SZhang Yubing cstate->dclk_rst.dev = NULL;
34370686a6a6SZhang Yubing }
3438a2ce7568SDamon Ding }
34390686a6a6SZhang Yubing
3440d0408543SAndy Yan cstate->private = rockchip_vop2;
344163cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output;
344263cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature;
3443d0408543SAndy Yan
344489912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state);
344589912f2dSSandy Huang
3446d0408543SAndy Yan return 0;
3447d0408543SAndy Yan }
3448d0408543SAndy Yan
3449ecc31b6eSAndy Yan /*
3450ecc31b6eSAndy Yan * calc the dclk on rk3588
3451ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4
3452ecc31b6eSAndy Yan *
3453ecc31b6eSAndy Yan */
vop2_calc_dclk(unsigned long child_clk,unsigned long max_dclk)3454ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
3455ecc31b6eSAndy Yan {
3456ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk)
3457ecc31b6eSAndy Yan return child_clk * 4;
3458ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk)
3459ecc31b6eSAndy Yan return child_clk * 2;
3460ecc31b6eSAndy Yan else if (child_clk <= max_dclk)
3461ecc31b6eSAndy Yan return child_clk;
3462ecc31b6eSAndy Yan else
3463ecc31b6eSAndy Yan return 0;
3464ecc31b6eSAndy Yan }
3465ecc31b6eSAndy Yan
3466ecc31b6eSAndy Yan /*
3467ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588
3468ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core
3469ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core
3470ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core
3471ecc31b6eSAndy Yan */
vop2_calc_cru_cfg(struct display_state * state,int * dclk_core_div,int * dclk_out_div,int * if_pixclk_div,int * if_dclk_div)3472ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state,
3473ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div,
3474ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div)
3475d0408543SAndy Yan {
3476d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state;
3477d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state;
3478d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode;
3479d0408543SAndy Yan struct vop2 *vop2 = cstate->private;
3480dd0d7bfeSDamon Ding unsigned long v_pixclk = mode->crtc_clock * 1000L;
3481ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2;
3482ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk;
3483ecc31b6eSAndy Yan unsigned long dclk_out_rate;
3484ecc31b6eSAndy Yan u64 if_dclk_rate;
3485ecc31b6eSAndy Yan u64 if_pixclk_rate;
3486ecc31b6eSAndy Yan int output_type = conn_state->type;
3487ecc31b6eSAndy Yan int output_mode = conn_state->output_mode;
3488ecc31b6eSAndy Yan int K = 1;
3489ecc31b6eSAndy Yan
34900a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE &&
34910a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) {
34920a1fb152SZhang Yubing printf("Dual channel and YUV420 can't work together\n");
34930a1fb152SZhang Yubing return -EINVAL;
34940a1fb152SZhang Yubing }
34950a1fb152SZhang Yubing
34960a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
34970a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420)
34980a1fb152SZhang Yubing K = 2;
34990a1fb152SZhang Yubing
3500ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) {
3501ecc31b6eSAndy Yan /*
3502ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
3503ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
3504ecc31b6eSAndy Yan */
35050a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
35060a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3507b890760eSAlgea Cao dclk_rate = dclk_rate >> 1;
3508ecc31b6eSAndy Yan K = 2;
3509b890760eSAlgea Cao }
351012ee5af0SDamon Ding if (cstate->dsc_enable) {
3511dd0d7bfeSDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate << 1;
3512dd0d7bfeSDamon Ding if_dclk_rate = cstate->dsc_cds_clk_rate;
3513ecc31b6eSAndy Yan } else {
3514ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K;
3515ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K;
3516ecc31b6eSAndy Yan }
3517ecc31b6eSAndy Yan
3518dd0d7bfeSDamon Ding if (v_pixclk > VOP2_MAX_DCLK_RATE * 1000L)
35194b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_core_rate,
3520dd0d7bfeSDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
3521631ee99aSZhang Yubing
3522ecc31b6eSAndy Yan if (!dclk_rate) {
3523dd0d7bfeSDamon Ding printf("HDMI if_pixclk_rate out of range(max_dclk: %ld HZ, dclk_core: %lld HZ)\n",
3524dd0d7bfeSDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, if_pixclk_rate);
3525ecc31b6eSAndy Yan return -EINVAL;
3526ecc31b6eSAndy Yan }
3527ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate;
3528ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate;
3529b890760eSAlgea Cao *dclk_core_div = dclk_rate / dclk_core_rate;
3530d86cb420SDamon Ding /* For HDMI DSC mode, the dclk_out_div should be the same as dclk_core_div */
3531d86cb420SDamon Ding if (cstate->dsc_enable)
3532d86cb420SDamon Ding *dclk_out_div = *dclk_core_div;
3533b890760eSAlgea Cao printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n",
3534b890760eSAlgea Cao dclk_rate, *if_pixclk_div, *if_dclk_div);
3535ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) {
3536ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */
3537ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K;
3538ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K;
3539ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K;
3540ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate;
3541ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate;
3542ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div;
3543ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) {
3544ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2;
35450a1fb152SZhang Yubing dclk_out_rate = dclk_out_rate / K;
3546ecc31b6eSAndy Yan
35474b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate,
3548dd0d7bfeSDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
3549ecc31b6eSAndy Yan if (!dclk_rate) {
3550dd0d7bfeSDamon Ding printf("DP dclk_core out of range(max_dclk: %ld HZ, dclk_core: %ld HZ)\n",
3551dd0d7bfeSDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_core_rate);
3552ecc31b6eSAndy Yan return -EINVAL;
3553ecc31b6eSAndy Yan }
3554ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate;
3555ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate;
3556ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) {
3557ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3558ecc31b6eSAndy Yan K = 2;
355912ee5af0SDamon Ding if (cstate->dsc_enable)
356012ee5af0SDamon Ding /* dsc output is 96bit, dsi input is 192 bit */
356112ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1;
3562ecc31b6eSAndy Yan else
3563ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K;
3564ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */
356512ee5af0SDamon Ding dclk_out_rate = dclk_core_rate / K;
3566ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */
35674b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate,
3568dd0d7bfeSDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L);
35699f076eccSZhang Yubing if (!dclk_rate) {
3570dd0d7bfeSDamon Ding printf("MIPI dclk out of range(max_dclk: %ld HZ, dclk_rate: %ld HZ)\n",
3571dd0d7bfeSDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_rate);
35729f076eccSZhang Yubing return -EINVAL;
35739f076eccSZhang Yubing }
357412ee5af0SDamon Ding
357512ee5af0SDamon Ding if (cstate->dsc_enable)
3576d57af898SDamon Ding dclk_rate /= cstate->dsc_slice_num;
357712ee5af0SDamon Ding
3578ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate;
3579ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate;
3580ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/
358112ee5af0SDamon Ding if (cstate->dsc_enable)
3582dd0d7bfeSDamon Ding *if_pixclk_div = dclk_out_rate / if_pixclk_rate;
3583ecc31b6eSAndy Yan
3584ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) {
3585ecc31b6eSAndy Yan dclk_rate = v_pixclk;
3586ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate;
3587ecc31b6eSAndy Yan }
3588ecc31b6eSAndy Yan
3589ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div);
3590ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div);
3591ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div);
3592d86cb420SDamon Ding /*
3593d86cb420SDamon Ding * For RK3588, dclk_out is designed for DP, MIPI(both DSC and non-DSC mode)
3594d86cb420SDamon Ding * and HDMI in DSC mode.
3595d86cb420SDamon Ding */
3596d86cb420SDamon Ding if (output_type == DRM_MODE_CONNECTOR_DisplayPort ||
3597d86cb420SDamon Ding output_type == DRM_MODE_CONNECTOR_DSI ||
3598d86cb420SDamon Ding (output_type == DRM_MODE_CONNECTOR_HDMIA && cstate->dsc_enable))
3599ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div);
3600d86cb420SDamon Ding else
3601d86cb420SDamon Ding *dclk_out_div = 0;
3602ecc31b6eSAndy Yan
3603ecc31b6eSAndy Yan return dclk_rate;
3604ecc31b6eSAndy Yan }
3605ecc31b6eSAndy Yan
vop2_calc_dsc_clk(struct display_state * state)360612ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state)
3607ecc31b6eSAndy Yan {
360812ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state;
3609ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode;
361012ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state;
36111ace1b6dSDamon Ding u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */
3612ecc31b6eSAndy Yan u8 k = 1;
3613ecc31b6eSAndy Yan
3614ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
3615ecc31b6eSAndy Yan k = 2;
3616ecc31b6eSAndy Yan
361712ee5af0SDamon Ding cstate->dsc_txp_clk_rate = v_pixclk;
361812ee5af0SDamon Ding do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k));
3619ecc31b6eSAndy Yan
362012ee5af0SDamon Ding cstate->dsc_pxl_clk_rate = v_pixclk;
362112ee5af0SDamon Ding do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k));
3622ecc31b6eSAndy Yan
3623ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel)
3624ecc31b6eSAndy Yan * cds_dat_width = 96;
3625ecc31b6eSAndy Yan * bits_per_pixel = [8-12];
3626b61227a3SDamon Ding * As cds clk is div from txp clk and only support 1/2/4 div,
3627b61227a3SDamon Ding * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4,
3628b61227a3SDamon Ding * otherwise dsc_cds = crtc_clock / 8;
3629ecc31b6eSAndy Yan */
3630b61227a3SDamon Ding cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8);
3631ecc31b6eSAndy Yan
3632ecc31b6eSAndy Yan return 0;
3633ecc31b6eSAndy Yan }
3634ecc31b6eSAndy Yan
rk3588_vop2_if_cfg(struct display_state * state)3635ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state)
3636ecc31b6eSAndy Yan {
3637ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state;
3638ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state;
3639ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode;
364012ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
3641ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private;
364252ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100);
3643ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay;
3644ecc31b6eSAndy Yan int output_if = conn_state->output_if;
3645ecc31b6eSAndy Yan int if_pixclk_div = 0;
3646ecc31b6eSAndy Yan int if_dclk_div = 0;
3647ecc31b6eSAndy Yan unsigned long dclk_rate;
36485d2768f7SDamon Ding bool dclk_inv, yc_swap = false;
3649d0408543SAndy Yan u32 val;
3650ecc31b6eSAndy Yan
36515d2768f7SDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3652b890760eSAlgea Cao if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
3653b890760eSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
3654b890760eSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
3655b890760eSAlgea Cao } else {
3656ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3657ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3658b890760eSAlgea Cao }
3659ecc31b6eSAndy Yan
366012ee5af0SDamon Ding if (cstate->dsc_enable) {
366112ee5af0SDamon Ding int k = 1;
366212ee5af0SDamon Ding
3663ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) {
366412ee5af0SDamon Ding printf("Unsupported DSC\n");
3665ecc31b6eSAndy Yan return 0;
3666ecc31b6eSAndy Yan }
366712ee5af0SDamon Ding
366812ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
366912ee5af0SDamon Ding k = 2;
367012ee5af0SDamon Ding
367112ee5af0SDamon Ding cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1;
367212ee5af0SDamon Ding cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k;
367312ee5af0SDamon Ding cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num;
367412ee5af0SDamon Ding
367512ee5af0SDamon Ding vop2_calc_dsc_clk(state);
367612ee5af0SDamon Ding printf("Enable DSC%d slice:%dx%d, slice num:%d\n",
367712ee5af0SDamon Ding cstate->dsc_id, dsc_sink_cap->slice_width,
367812ee5af0SDamon Ding dsc_sink_cap->slice_height, cstate->dsc_slice_num);
3679ecc31b6eSAndy Yan }
3680ecc31b6eSAndy Yan
3681b61227a3SDamon Ding dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div);
3682ecc31b6eSAndy Yan
3683ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) {
3684ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3685ecc31b6eSAndy Yan 4, false);
36865d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
36875d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
3688ecc31b6eSAndy Yan }
3689ecc31b6eSAndy Yan
3690ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) {
3691ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3692ecc31b6eSAndy Yan 3, false);
36935d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
36945d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
36955d2768f7SDamon Ding yc_swap = is_yc_swap(conn_state->bus_format);
36965d2768f7SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT,
36975d2768f7SDamon Ding yc_swap, false);
3698ecc31b6eSAndy Yan }
3699ecc31b6eSAndy Yan
3700ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) {
3701ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT,
3702ecc31b6eSAndy Yan 2, false);
37035d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK,
37045d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
37055d2768f7SDamon Ding yc_swap = is_yc_swap(conn_state->bus_format);
37065d2768f7SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT,
37075d2768f7SDamon Ding yc_swap, false);
3708ecc31b6eSAndy Yan }
3709ecc31b6eSAndy Yan
3710ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) {
3711ecc31b6eSAndy Yan if (cstate->crtc_id == 2)
3712ecc31b6eSAndy Yan val = 0;
3713ecc31b6eSAndy Yan else
3714ecc31b6eSAndy Yan val = 1;
371541874944SGuochun Huang
37163df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
371741874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
371841874944SGuochun Huang RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false);
371941874944SGuochun Huang
3720ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT,
3721ecc31b6eSAndy Yan 1, false);
3722ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false);
3723ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT,
3724ecc31b6eSAndy Yan if_pixclk_div, false);
372541874944SGuochun Huang
372641874944SGuochun Huang if (conn_state->hold_mode) {
372741874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
37288e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
372941874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
373041874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
373141874944SGuochun Huang }
3732ecc31b6eSAndy Yan }
3733ecc31b6eSAndy Yan
3734ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) {
3735ecc31b6eSAndy Yan if (cstate->crtc_id == 2)
3736ecc31b6eSAndy Yan val = 0;
3737ecc31b6eSAndy Yan else if (cstate->crtc_id == 3)
3738ecc31b6eSAndy Yan val = 1;
3739ecc31b6eSAndy Yan else
3740ecc31b6eSAndy Yan val = 3; /*VP1*/
37413df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
374241874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
374341874944SGuochun Huang RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false);
374441874944SGuochun Huang
3745ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT,
3746ecc31b6eSAndy Yan 1, false);
3747ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT,
3748ecc31b6eSAndy Yan val, false);
3749ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT,
3750ecc31b6eSAndy Yan if_pixclk_div, false);
375141874944SGuochun Huang
375241874944SGuochun Huang if (conn_state->hold_mode) {
375341874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
37548e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
375541874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
375641874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
375741874944SGuochun Huang }
3758ecc31b6eSAndy Yan }
3759ecc31b6eSAndy Yan
3760ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
37613df6e59eSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
37623df6e59eSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false);
3763ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
3764ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
3765ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1,
3766ecc31b6eSAndy Yan false);
37670a1fb152SZhang Yubing switch (conn_state->type) {
37680a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DisplayPort:
37690a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37700a1fb152SZhang Yubing RK3588_DP_DUAL_EN_SHIFT, 1, false);
37710a1fb152SZhang Yubing break;
37720a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_eDP:
37730a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37740a1fb152SZhang Yubing RK3588_EDP_DUAL_EN_SHIFT, 1, false);
37750a1fb152SZhang Yubing break;
37760a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_HDMIA:
37770a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37780a1fb152SZhang Yubing RK3588_HDMI_DUAL_EN_SHIFT, 1, false);
37790a1fb152SZhang Yubing break;
37800a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DSI:
37810a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
37820a1fb152SZhang Yubing RK3568_MIPI_DUAL_EN_SHIFT, 1, false);
37830a1fb152SZhang Yubing break;
37840a1fb152SZhang Yubing default:
37850a1fb152SZhang Yubing break;
37860a1fb152SZhang Yubing }
3787ecc31b6eSAndy Yan }
3788ecc31b6eSAndy Yan
3789ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) {
3790ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT,
3791ecc31b6eSAndy Yan 1, false);
3792ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3793ecc31b6eSAndy Yan cstate->crtc_id, false);
3794ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3795ecc31b6eSAndy Yan if_dclk_div, false);
3796ecc31b6eSAndy Yan
3797ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3798ecc31b6eSAndy Yan if_pixclk_div, false);
3799ecc31b6eSAndy Yan
3800ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3801ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1);
3802ecc31b6eSAndy Yan }
3803ecc31b6eSAndy Yan
3804ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) {
3805ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT,
3806ecc31b6eSAndy Yan 1, false);
3807ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3808ecc31b6eSAndy Yan cstate->crtc_id, false);
3809ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3810ecc31b6eSAndy Yan if_dclk_div, false);
3811ecc31b6eSAndy Yan
3812ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3813ecc31b6eSAndy Yan if_pixclk_div, false);
38141848455fSDamon Ding
38151848455fSDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
38161848455fSDamon Ding RK3588_GRF_EDP1_ENABLE_SHIFT, 1);
3817ecc31b6eSAndy Yan }
3818ecc31b6eSAndy Yan
3819ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) {
3820ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT,
3821ecc31b6eSAndy Yan 1, false);
3822ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT,
3823ecc31b6eSAndy Yan cstate->crtc_id, false);
3824ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT,
3825ecc31b6eSAndy Yan if_dclk_div, false);
3826ecc31b6eSAndy Yan
3827ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT,
3828ecc31b6eSAndy Yan if_pixclk_div, false);
3829b890760eSAlgea Cao
38302e42aca5SDamon Ding if (cstate->dsc_enable)
38312e42aca5SDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
38322e42aca5SDamon Ding RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT, 1);
38332e42aca5SDamon Ding
3834b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3835b890760eSAlgea Cao RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1);
3836b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3837b890760eSAlgea Cao HDMI_SYNC_POL_MASK,
3838b890760eSAlgea Cao HDMI0_SYNC_POL_SHIFT, val);
3839ecc31b6eSAndy Yan }
3840ecc31b6eSAndy Yan
3841ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) {
3842ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT,
3843ecc31b6eSAndy Yan 1, false);
3844ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT,
3845ecc31b6eSAndy Yan cstate->crtc_id, false);
3846ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT,
3847ecc31b6eSAndy Yan if_dclk_div, false);
3848ecc31b6eSAndy Yan
3849ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT,
3850ecc31b6eSAndy Yan if_pixclk_div, false);
3851b890760eSAlgea Cao
38522e42aca5SDamon Ding if (cstate->dsc_enable)
38532e42aca5SDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
38542e42aca5SDamon Ding RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT, 1);
38552e42aca5SDamon Ding
3856b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK,
3857b890760eSAlgea Cao RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1);
3858b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0,
3859b890760eSAlgea Cao HDMI_SYNC_POL_MASK,
3860b890760eSAlgea Cao HDMI1_SYNC_POL_SHIFT, val);
3861ecc31b6eSAndy Yan }
3862ecc31b6eSAndy Yan
3863ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) {
3864ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT,
3865ecc31b6eSAndy Yan cstate->crtc_id, false);
3866ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3867ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false);
3868ecc31b6eSAndy Yan }
3869ecc31b6eSAndy Yan
3870ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) {
3871ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT,
3872ecc31b6eSAndy Yan cstate->crtc_id, false);
3873ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK,
3874ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false);
3875ecc31b6eSAndy Yan }
3876ecc31b6eSAndy Yan
3877ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3878b61227a3SDamon Ding DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false);
3879ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3,
3880b61227a3SDamon Ding DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false);
3881ecc31b6eSAndy Yan
3882dd0d7bfeSDamon Ding return dclk_rate / 1000;
3883ecc31b6eSAndy Yan }
3884ecc31b6eSAndy Yan
rk3576_vop2_if_cfg(struct display_state * state)3885a552a69cSDamon Ding static unsigned long rk3576_vop2_if_cfg(struct display_state *state)
3886a552a69cSDamon Ding {
3887a552a69cSDamon Ding struct crtc_state *cstate = &state->crtc_state;
3888a552a69cSDamon Ding struct connector_state *conn_state = &state->conn_state;
3889a552a69cSDamon Ding struct drm_display_mode *mode = &conn_state->mode;
3890a552a69cSDamon Ding struct vop2 *vop2 = cstate->private;
3891a552a69cSDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100);
3892a552a69cSDamon Ding u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate;
3893a552a69cSDamon Ding int output_if = conn_state->output_if;
3894a552a69cSDamon Ding bool dclk_inv, yc_swap = false;
3895a552a69cSDamon Ding bool split_mode = !!(conn_state->output_flags &
3896a552a69cSDamon Ding ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE);
3897a552a69cSDamon Ding bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false;
3898a552a69cSDamon Ding bool interface_dclk_sel, interface_pix_clk_sel = false;
3899a552a69cSDamon Ding bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK ||
3900a552a69cSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656;
3901cce1f2abSDamon Ding unsigned long dclk_in_rate, dclk_core_rate;
3902a552a69cSDamon Ding u32 val;
3903a552a69cSDamon Ding
390445ec9215SDamon Ding if (split_mode) {
390545ec9215SDamon Ding printf("WARN: split is enabled, post-scaler shouldn't be set\n");
390645ec9215SDamon Ding conn_state->overscan.left_margin = 100;
390745ec9215SDamon Ding conn_state->overscan.right_margin = 100;
390845ec9215SDamon Ding conn_state->overscan.top_margin = 100;
390945ec9215SDamon Ding conn_state->overscan.bottom_margin = 100;
391045ec9215SDamon Ding
391145ec9215SDamon Ding /*
391245ec9215SDamon Ding * VOP split and sharp use the same line buffer. If enable
391345ec9215SDamon Ding * split, sharp must be disabled completely.
391445ec9215SDamon Ding */
391545ec9215SDamon Ding if (vop2->data->vp_data[cstate->crtc_id].feature & VOP_FEATURE_POST_SHARP)
391645ec9215SDamon Ding writel(false << SW_SHARP_ENABLE_SHIFT,
391745ec9215SDamon Ding vop2->sharp_res + RK3576_SHARP_CTRL);
391845ec9215SDamon Ding }
391945ec9215SDamon Ding
3920a552a69cSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
3921a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_MIPI0) {
3922a552a69cSDamon Ding /*
3923a552a69cSDamon Ding * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
3924a552a69cSDamon Ding * so set VOP hsync/vsync polarity as positive by default.
3925a552a69cSDamon Ding */
3926a552a69cSDamon Ding val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
3927a552a69cSDamon Ding } else {
3928a552a69cSDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
3929a552a69cSDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
3930a552a69cSDamon Ding }
3931a552a69cSDamon Ding
3932cce1f2abSDamon Ding if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 ||
3933cce1f2abSDamon Ding mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode))
3934a552a69cSDamon Ding cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */
3935a552a69cSDamon Ding else
3936cce1f2abSDamon Ding cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */
3937cce1f2abSDamon Ding dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div;
3938cce1f2abSDamon Ding
3939cce1f2abSDamon Ding if (double_pixel)
3940cce1f2abSDamon Ding dclk_core_rate = mode->crtc_clock / 2;
3941cce1f2abSDamon Ding else
3942cce1f2abSDamon Ding dclk_core_rate = mode->crtc_clock / port_pix_rate;
3943cce1f2abSDamon Ding post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */
3944a552a69cSDamon Ding
3945a552a69cSDamon Ding if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
3946a552a69cSDamon Ding pix_half_rate = true;
3947a552a69cSDamon Ding post_dclk_out_sel = true;
3948a552a69cSDamon Ding }
3949a552a69cSDamon Ding
3950a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_RGB) {
3951a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3952a552a69cSDamon Ding /*
3953a552a69cSDamon Ding * RGB interface_pix_clk_sel will auto config according
3954a552a69cSDamon Ding * to rgb_en/bt1120_en/bt656_en.
3955a552a69cSDamon Ding */
3956a552a69cSDamon Ding } else if (output_if & VOP_OUTPUT_IF_eDP0) {
3957a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3958a552a69cSDamon Ding interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0;
3959a552a69cSDamon Ding } else {
3960a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0;
3961a552a69cSDamon Ding interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0;
3962a552a69cSDamon Ding }
3963a552a69cSDamon Ding
3964a552a69cSDamon Ding /* dclk_core */
3965a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3966a552a69cSDamon Ding RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false);
3967a552a69cSDamon Ding /* dclk_out */
3968a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK,
3969a552a69cSDamon Ding RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false);
3970a552a69cSDamon Ding
3971a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_RGB) {
3972a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */
3973a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3974a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3975a552a69cSDamon Ding
3976a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3977a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3978a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3979a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3980a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3981a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false);
3982a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
3983a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
3984a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK,
3985a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false);
3986a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
3987a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv);
3988a552a69cSDamon Ding }
3989a552a69cSDamon Ding
3990a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_BT1120) {
3991a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */
3992a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
3993a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
3994a552a69cSDamon Ding
3995a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3996a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
3997a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
3998a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
3999a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4000a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false);
4001a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4002a552a69cSDamon Ding RK3576_BT1120_OUT_EN_SHIFT, 1, false);
4003a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4004a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4005a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
4006a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
4007a552a69cSDamon Ding yc_swap = is_yc_swap(conn_state->bus_format);
4008a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4009a552a69cSDamon Ding RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false);
4010a552a69cSDamon Ding }
4011a552a69cSDamon Ding
4012a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_BT656) {
4013a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */
4014a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4015a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4016a552a69cSDamon Ding
4017a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4018a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4019a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4020a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4021a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4022a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false);
4023a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4024a552a69cSDamon Ding RK3576_BT656_OUT_EN_SHIFT, 1, false);
4025a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4026a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4027a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK,
4028a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv);
4029a552a69cSDamon Ding yc_swap = is_yc_swap(conn_state->bus_format);
4030a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK,
4031a552a69cSDamon Ding RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false);
4032a552a69cSDamon Ding }
4033a552a69cSDamon Ding
4034a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_MIPI0) {
4035a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4036a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4037a552a69cSDamon Ding /* 0: div2, 1: div4 */
4038a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4039a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4040a552a69cSDamon Ding
4041a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4042a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4043a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4044a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4045a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4046a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false);
4047a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4048a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4049a552a69cSDamon Ding /*
4050a552a69cSDamon Ding * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update,
4051a552a69cSDamon Ding * so set VOP hsync/vsync polarity as positive by default.
4052a552a69cSDamon Ding */
4053a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576)
4054a552a69cSDamon Ding val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE);
4055a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4056a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false);
4057a552a69cSDamon Ding
4058a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE)
4059a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4060a552a69cSDamon Ding RK3576_MIPI_CMD_MODE_SHIFT, 1, false);
4061a552a69cSDamon Ding
4062a552a69cSDamon Ding if (conn_state->hold_mode) {
4063a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4064a552a69cSDamon Ding EDPI_TE_EN, !cstate->soft_te, false);
4065a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4066a552a69cSDamon Ding EDPI_WMS_HOLD_EN, 1, false);
4067a552a69cSDamon Ding }
4068a552a69cSDamon Ding }
4069a552a69cSDamon Ding
4070a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
4071a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4072a552a69cSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false);
4073a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
4074a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4075a552a69cSDamon Ding MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
4076a552a69cSDamon Ding switch (conn_state->type) {
4077a552a69cSDamon Ding case DRM_MODE_CONNECTOR_DisplayPort:
4078a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4079a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4080a552a69cSDamon Ding break;
4081a552a69cSDamon Ding case DRM_MODE_CONNECTOR_eDP:
4082a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4083a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4084a552a69cSDamon Ding break;
4085a552a69cSDamon Ding case DRM_MODE_CONNECTOR_HDMIA:
4086a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4087a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4088a552a69cSDamon Ding break;
4089a552a69cSDamon Ding case DRM_MODE_CONNECTOR_DSI:
4090a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK,
4091a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false);
4092a552a69cSDamon Ding break;
4093a552a69cSDamon Ding default:
4094a552a69cSDamon Ding break;
4095a552a69cSDamon Ding }
4096a552a69cSDamon Ding }
4097a552a69cSDamon Ding
4098a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_eDP0) {
4099a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4100a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4101a552a69cSDamon Ding /* 0: dclk, 1: port0_dclk */
4102a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4103a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4104a552a69cSDamon Ding
4105a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4106a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4107a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4108a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4109a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK,
4110a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false);
4111a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4112a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4113a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4114a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false);
4115a552a69cSDamon Ding }
4116a552a69cSDamon Ding
4117a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_HDMI0) {
4118a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4119a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4120a552a69cSDamon Ding /* 0: div2, 1: div4 */
4121a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4122a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4123a552a69cSDamon Ding
4124a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4125a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4126a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4127a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4128a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK,
4129a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false);
4130a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4131a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4132a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4133a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false);
4134a552a69cSDamon Ding }
4135a552a69cSDamon Ding
4136a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP0) {
4137a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4138a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4139a552a69cSDamon Ding /* 0: no div, 1: div2 */
4140a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4141a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4142a552a69cSDamon Ding
4143a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4144a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4145a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
4146a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4147a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4148a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4149a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4150a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false);
4151a552a69cSDamon Ding }
4152a552a69cSDamon Ding
4153a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP1) {
4154a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4155a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4156a552a69cSDamon Ding /* 0: no div, 1: div2 */
4157a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4158a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4159a552a69cSDamon Ding
4160a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
4161a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4162a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
4163a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4164a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4165a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4166a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4167a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false);
4168a552a69cSDamon Ding }
4169a552a69cSDamon Ding
4170a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP2) {
4171a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK,
4172a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false);
4173a552a69cSDamon Ding /* 0: no div, 1: div2 */
4174a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK,
4175a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false);
4176a552a69cSDamon Ding
4177a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
4178a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false);
4179a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
4180a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false);
4181a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK,
4182a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false);
4183a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK,
4184a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false);
4185a552a69cSDamon Ding }
4186a552a69cSDamon Ding
4187a552a69cSDamon Ding return mode->crtc_clock;
4188a552a69cSDamon Ding }
4189a552a69cSDamon Ding
rk3568_vop2_setup_dual_channel_if(struct display_state * state)4190a2a16809SChaoyi Chen static void rk3568_vop2_setup_dual_channel_if(struct display_state *state)
4191a2a16809SChaoyi Chen {
4192a2a16809SChaoyi Chen struct crtc_state *cstate = &state->crtc_state;
4193a2a16809SChaoyi Chen struct connector_state *conn_state = &state->conn_state;
4194a2a16809SChaoyi Chen struct vop2 *vop2 = cstate->private;
4195a2a16809SChaoyi Chen u32 vp_offset = (cstate->crtc_id * 0x100);
4196a2a16809SChaoyi Chen
4197a2a16809SChaoyi Chen if (conn_state->output_flags &
4198a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) {
4199a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4200a2a16809SChaoyi Chen LVDS_DUAL_EN_SHIFT, 1, false);
4201a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4202a2a16809SChaoyi Chen LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false);
4203a2a16809SChaoyi Chen if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
4204a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4205a2a16809SChaoyi Chen LVDS_DUAL_SWAP_EN_SHIFT, 1, false);
4206a2a16809SChaoyi Chen
4207a2a16809SChaoyi Chen return;
4208a2a16809SChaoyi Chen }
4209a2a16809SChaoyi Chen
4210a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4211a2a16809SChaoyi Chen MIPI_DUAL_EN_SHIFT, 1, false);
4212a2a16809SChaoyi Chen if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) {
4213a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK,
4214a2a16809SChaoyi Chen MIPI_DUAL_SWAP_EN_SHIFT, 1, false);
4215a2a16809SChaoyi Chen }
4216a2a16809SChaoyi Chen
4217a2a16809SChaoyi Chen if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
4218a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4219a2a16809SChaoyi Chen LVDS_DUAL_EN_SHIFT, 1, false);
4220a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK,
4221a2a16809SChaoyi Chen LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false);
4222a2a16809SChaoyi Chen }
4223a2a16809SChaoyi Chen }
4224a2a16809SChaoyi Chen
rk3568_vop2_if_cfg(struct display_state * state)4225ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state)
4226ecc31b6eSAndy Yan {
4227ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state;
4228ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state;
4229ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode;
4230ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private;
4231d0408543SAndy Yan bool dclk_inv;
4232ecc31b6eSAndy Yan u32 val;
42338895aec1SSandy Huang
423413f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
423510ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
423610ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4237d0408543SAndy Yan
4238d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
4239d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
4240d0408543SAndy Yan 1, false);
4241d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4242d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false);
424315f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
424415f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4245ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
4246c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
4247d0408543SAndy Yan }
4248d0408543SAndy Yan
4249d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) {
425052ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
425152ee18acSSandy Huang 1, false);
4252d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK,
4253d0408543SAndy Yan BT1120_EN_SHIFT, 1, false);
4254d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4255d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false);
4256ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
425752ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv);
4258d0408543SAndy Yan }
4259d0408543SAndy Yan
4260d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4261d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4262d0408543SAndy Yan 1, false);
4263d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4264d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false);
4265ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK,
426652ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv);
4267d0408543SAndy Yan }
4268d0408543SAndy Yan
4269d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
4270d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
4271d0408543SAndy Yan 1, false);
4272d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4273d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false);
427415f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
427515f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
427611f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
427715f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4278d0408543SAndy Yan }
4279d0408543SAndy Yan
4280d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) {
4281d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT,
4282d0408543SAndy Yan 1, false);
4283d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4284d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false);
428515f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK,
428615f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
428711f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
428815f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4289d0408543SAndy Yan }
4290d0408543SAndy Yan
4291d0408543SAndy Yan
4292d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
4293d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
4294d0408543SAndy Yan 1, false);
4295d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4296d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false);
4297d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4298c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
4299de022775SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
4300de022775SGuochun Huang IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
4301d0408543SAndy Yan }
4302d0408543SAndy Yan
4303d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) {
4304d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT,
4305d0408543SAndy Yan 1, false);
4306d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4307d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false);
4308d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4309c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false);
4310de022775SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK,
4311de022775SGuochun Huang IF_CTRL_MIPI_PIN_POL_SHIFT, val, false);
4312d0408543SAndy Yan }
4313d0408543SAndy Yan
4314d0408543SAndy Yan if (conn_state->output_flags &
4315a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE ||
4316a2a16809SChaoyi Chen conn_state->output_flags &
4317a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)
4318a2a16809SChaoyi Chen rk3568_vop2_setup_dual_channel_if(state);
4319d0408543SAndy Yan
4320d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) {
4321d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT,
4322d0408543SAndy Yan 1, false);
4323d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4324d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false);
4325c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4326c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false);
43277bcdc6eeSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK,
43287bcdc6eeSDamon Ding IF_CTRL_EDP_PIN_POL_SHIFT, val, false);
4329d0408543SAndy Yan }
4330d0408543SAndy Yan
4331d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4332d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4333d0408543SAndy Yan 1, false);
4334d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4335d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false);
433610ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
433710ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
433810ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL,
433910ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK,
434010ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4341d0408543SAndy Yan }
434210ee9f5bSAlgea Cao
4343823146b6SDamon Ding return mode->crtc_clock;
4344ecc31b6eSAndy Yan }
4345ecc31b6eSAndy Yan
rk3562_vop2_if_cfg(struct display_state * state)4346452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state)
4347452afb13SDamon Ding {
4348452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state;
4349452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state;
4350452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode;
4351452afb13SDamon Ding struct vop2 *vop2 = cstate->private;
4352452afb13SDamon Ding bool dclk_inv;
4353606f72bdSDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100);
4354452afb13SDamon Ding u32 val;
4355452afb13SDamon Ding
435613f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
4357452afb13SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4358452afb13SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4359452afb13SDamon Ding
4360452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_RGB) {
4361452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT,
4362452afb13SDamon Ding 1, false);
4363452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4364452afb13SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false);
4365452afb13SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK,
4366452afb13SDamon Ding GRF_RGB_DCLK_INV_SHIFT, dclk_inv);
4367452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
436815f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4369452afb13SDamon Ding }
4370452afb13SDamon Ding
4371452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) {
4372452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT,
4373452afb13SDamon Ding 1, false);
4374452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4375452afb13SDamon Ding LVDS0_MUX_SHIFT, cstate->crtc_id, false);
4376452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
437715f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false);
4378452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
437915f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false);
4380452afb13SDamon Ding }
4381452afb13SDamon Ding
4382452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) {
4383452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT,
4384452afb13SDamon Ding 1, false);
4385452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4386452afb13SDamon Ding MIPI0_MUX_SHIFT, cstate->crtc_id, false);
4387452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4388452afb13SDamon Ding RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false);
4389452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK,
4390452afb13SDamon Ding RK3562_MIPI_PIN_POL_SHIFT, val, false);
4391606f72bdSDamon Ding
4392606f72bdSDamon Ding if (conn_state->hold_mode) {
4393606f72bdSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4394606f72bdSDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false);
4395606f72bdSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
4396606f72bdSDamon Ding EN_MASK, EDPI_WMS_HOLD_EN, 1, false);
4397606f72bdSDamon Ding }
4398452afb13SDamon Ding }
4399452afb13SDamon Ding
4400452afb13SDamon Ding return mode->crtc_clock;
4401452afb13SDamon Ding }
4402452afb13SDamon Ding
rk3528_vop2_if_cfg(struct display_state * state)4403a552a69cSDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state)
4404a552a69cSDamon Ding {
4405a552a69cSDamon Ding struct crtc_state *cstate = &state->crtc_state;
4406a552a69cSDamon Ding struct connector_state *conn_state = &state->conn_state;
4407a552a69cSDamon Ding struct drm_display_mode *mode = &conn_state->mode;
4408a552a69cSDamon Ding struct vop2 *vop2 = cstate->private;
4409a552a69cSDamon Ding u32 val;
4410a552a69cSDamon Ding
4411a552a69cSDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
4412a552a69cSDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
4413a552a69cSDamon Ding
4414a552a69cSDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_BT656) {
4415a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT,
4416a552a69cSDamon Ding 1, false);
4417a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4418a552a69cSDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false);
4419a552a69cSDamon Ding }
4420a552a69cSDamon Ding
4421a552a69cSDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) {
4422a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT,
4423a552a69cSDamon Ding 1, false);
4424a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK,
4425a552a69cSDamon Ding HDMI0_MUX_SHIFT, cstate->crtc_id, false);
4426a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK,
4427a552a69cSDamon Ding IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false);
4428a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL,
4429a552a69cSDamon Ding IF_CRTL_HDMI_PIN_POL_MASK,
4430a552a69cSDamon Ding IF_CRTL_HDMI_PIN_POL_SHIT, val, false);
4431a552a69cSDamon Ding }
4432a552a69cSDamon Ding
4433a552a69cSDamon Ding return mode->crtc_clock;
4434a552a69cSDamon Ding }
4435a552a69cSDamon Ding
vop2_post_color_swap(struct display_state * state)443665747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state)
443765747de7SDamon Ding {
443865747de7SDamon Ding struct crtc_state *cstate = &state->crtc_state;
443965747de7SDamon Ding struct connector_state *conn_state = &state->conn_state;
444065747de7SDamon Ding struct vop2 *vop2 = cstate->private;
444165747de7SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100);
444265747de7SDamon Ding u32 output_type = conn_state->type;
444365747de7SDamon Ding u32 data_swap = 0;
444465747de7SDamon Ding
4445c8820b76SDamon Ding if (is_uv_swap(state) || is_rb_swap(state))
444665747de7SDamon Ding data_swap = DSP_RB_SWAP;
444765747de7SDamon Ding
4448a552a69cSDamon Ding if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) {
4449a552a69cSDamon Ding if ((output_type == DRM_MODE_CONNECTOR_HDMIA ||
4450e6e4c154SDamon Ding output_type == DRM_MODE_CONNECTOR_DisplayPort) &&
445165747de7SDamon Ding (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
445265747de7SDamon Ding conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30))
445365747de7SDamon Ding data_swap |= DSP_RG_SWAP;
4454a552a69cSDamon Ding }
445565747de7SDamon Ding
445665747de7SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset,
445765747de7SDamon Ding DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false);
445865747de7SDamon Ding }
445965747de7SDamon Ding
vop2_clk_set_parent(struct clk * clk,struct clk * parent)4460b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent)
4461b890760eSAlgea Cao {
4462e1a1aa04SFinley Xiao #ifndef CONFIG_MOS_SUPPORT
4463b890760eSAlgea Cao int ret = 0;
4464b890760eSAlgea Cao
4465b890760eSAlgea Cao if (parent->dev)
4466b890760eSAlgea Cao ret = clk_set_parent(clk, parent);
4467b890760eSAlgea Cao if (ret < 0)
4468b890760eSAlgea Cao debug("failed to set %s as parent for %s\n",
4469b890760eSAlgea Cao parent->dev->name, clk->dev->name);
4470e1a1aa04SFinley Xiao #endif
4471b890760eSAlgea Cao }
4472b890760eSAlgea Cao
vop2_clk_set_rate(struct clk * clk,ulong rate)4473b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate)
4474b890760eSAlgea Cao {
4475b890760eSAlgea Cao int ret = 0;
4476b890760eSAlgea Cao
4477b890760eSAlgea Cao if (clk->dev)
4478b890760eSAlgea Cao ret = clk_set_rate(clk, rate);
4479b890760eSAlgea Cao if (ret < 0)
4480b890760eSAlgea Cao debug("failed to set %s rate %lu \n", clk->dev->name, rate);
4481b890760eSAlgea Cao
4482b890760eSAlgea Cao return ret;
4483b890760eSAlgea Cao }
4484b890760eSAlgea Cao
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)448512ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state,
448612ee5af0SDamon Ding int *dsc_txp_clk_div, int *dsc_pxl_clk_div,
448712ee5af0SDamon Ding int *dsc_cds_clk_div, u64 dclk_rate)
448812ee5af0SDamon Ding {
448912ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state;
449012ee5af0SDamon Ding
449112ee5af0SDamon Ding *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate;
449212ee5af0SDamon Ding *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate;
449312ee5af0SDamon Ding *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate;
449412ee5af0SDamon Ding
449512ee5af0SDamon Ding *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div);
449612ee5af0SDamon Ding *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div);
449712ee5af0SDamon Ding *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div);
449812ee5af0SDamon Ding }
449912ee5af0SDamon Ding
vop2_load_pps(struct display_state * state,struct vop2 * vop2,u8 dsc_id)450012ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id)
450112ee5af0SDamon Ding {
450212ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state;
450312ee5af0SDamon Ding struct drm_dsc_picture_parameter_set *pps = &cstate->pps;
450412ee5af0SDamon Ding struct drm_dsc_picture_parameter_set config_pps;
450512ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data;
450612ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
450712ee5af0SDamon Ding u32 *pps_val = (u32 *)&config_pps;
450812ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100);
450912ee5af0SDamon Ding int i = 0;
451012ee5af0SDamon Ding
451112ee5af0SDamon Ding memcpy(&config_pps, pps, sizeof(config_pps));
451212ee5af0SDamon Ding
451312ee5af0SDamon Ding if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) {
451412ee5af0SDamon Ding config_pps.pps_3 &= 0xf0;
451512ee5af0SDamon Ding config_pps.pps_3 |= dsc_data->max_linebuf_depth;
451612ee5af0SDamon Ding printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n",
451712ee5af0SDamon Ding dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf);
451812ee5af0SDamon Ding }
451912ee5af0SDamon Ding
452012ee5af0SDamon Ding for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
452112ee5af0SDamon Ding config_pps.rc_range_parameters[i] =
452212ee5af0SDamon Ding (pps->rc_range_parameters[i] >> 3 & 0x1f) |
452312ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) |
452412ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) |
452512ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10);
452612ee5af0SDamon Ding }
452712ee5af0SDamon Ding
452812ee5af0SDamon Ding for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++)
452912ee5af0SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++);
453012ee5af0SDamon Ding }
453112ee5af0SDamon Ding
vop2_dsc_enable(struct display_state * state,struct vop2 * vop2,u8 dsc_id,u64 dclk_rate)453212ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate)
453312ee5af0SDamon Ding {
453412ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state;
453512ee5af0SDamon Ding struct drm_display_mode *mode = &conn_state->mode;
453612ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state;
453712ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap;
453812ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data;
453912ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id];
454012ee5af0SDamon Ding bool mipi_ds_mode = false;
454112ee5af0SDamon Ding u8 dsc_interface_mode = 0;
454212ee5af0SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
454312ee5af0SDamon Ding u16 hdisplay = mode->crtc_hdisplay;
454412ee5af0SDamon Ding u16 htotal = mode->crtc_htotal;
454512ee5af0SDamon Ding u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
454612ee5af0SDamon Ding u16 vdisplay = mode->crtc_vdisplay;
454712ee5af0SDamon Ding u16 vtotal = mode->crtc_vtotal;
454812ee5af0SDamon Ding u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
454912ee5af0SDamon Ding u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
455012ee5af0SDamon Ding u16 vact_end = vact_st + vdisplay;
455112ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30);
455212ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100);
455312ee5af0SDamon Ding int dsc_txp_clk_div = 0;
455412ee5af0SDamon Ding int dsc_pxl_clk_div = 0;
455512ee5af0SDamon Ding int dsc_cds_clk_div = 0;
4556baf2c414SDamon Ding int val = 0;
455712ee5af0SDamon Ding
455812ee5af0SDamon Ding if (!vop2->data->nr_dscs) {
455912ee5af0SDamon Ding printf("Unsupported DSC\n");
456012ee5af0SDamon Ding return;
456112ee5af0SDamon Ding }
456212ee5af0SDamon Ding
456312ee5af0SDamon Ding if (cstate->dsc_slice_num > dsc_data->max_slice_num)
456412ee5af0SDamon Ding printf("DSC%d supported max slice is: %d, current is: %d\n",
456512ee5af0SDamon Ding dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num);
456612ee5af0SDamon Ding
456712ee5af0SDamon Ding if (dsc_data->pd_id) {
456812ee5af0SDamon Ding if (vop2_power_domain_on(vop2, dsc_data->pd_id))
456912ee5af0SDamon Ding printf("open dsc%d pd fail\n", dsc_id);
457012ee5af0SDamon Ding }
457112ee5af0SDamon Ding
457212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK,
457312ee5af0SDamon Ding SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false);
457412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK,
457512ee5af0SDamon Ding DSC_PORT_SEL_SHIFT, cstate->crtc_id, false);
457612ee5af0SDamon Ding if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
457712ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_HDMI;
457812ee5af0SDamon Ding } else {
457912ee5af0SDamon Ding mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE);
458012ee5af0SDamon Ding if (mipi_ds_mode)
458112ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE;
458212ee5af0SDamon Ding else
458312ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE;
458412ee5af0SDamon Ding }
458512ee5af0SDamon Ding
458612ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
458712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
458812ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 0, false);
458912ee5af0SDamon Ding else
459012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK,
459112ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 1, false);
459212ee5af0SDamon Ding
459312ee5af0SDamon Ding vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate);
459412ee5af0SDamon Ding
459512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK,
459612ee5af0SDamon Ding DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false);
459712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK,
459812ee5af0SDamon Ding DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false);
459912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK,
460012ee5af0SDamon Ding DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false);
460112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK,
460212ee5af0SDamon Ding DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false);
460312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
460412ee5af0SDamon Ding DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false);
460512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK,
460612ee5af0SDamon Ding DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false);
460712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK,
460812ee5af0SDamon Ding DSC_HALT_EN_SHIFT, mipi_ds_mode, false);
460912ee5af0SDamon Ding
461012ee5af0SDamon Ding if (!mipi_ds_mode) {
461112ee5af0SDamon Ding u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end;
461212ee5af0SDamon Ding u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16;
461312ee5af0SDamon Ding u64 dsc_cds_rate = cstate->dsc_cds_clk_rate;
461412ee5af0SDamon Ding u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */
461512ee5af0SDamon Ding u32 dly_num, dsc_cds_rate_mhz, val = 0;
4616b61227a3SDamon Ding int k = 1;
4617b61227a3SDamon Ding
4618b61227a3SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
4619b61227a3SDamon Ding k = 2;
462012ee5af0SDamon Ding
462112ee5af0SDamon Ding if (target_bpp >> 4 < dsc_data->min_bits_per_pixel)
462212ee5af0SDamon Ding printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel);
462312ee5af0SDamon Ding
462412ee5af0SDamon Ding /*
462512ee5af0SDamon Ding * dly_num = delay_line_num * T(one-line) / T (dsc_cds)
462612ee5af0SDamon Ding * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz
462712ee5af0SDamon Ding * T (dsc_cds) = 1 / dsc_cds_rate_mhz
46281ace1b6dSDamon Ding *
46291ace1b6dSDamon Ding * HDMI:
463012ee5af0SDamon Ding * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay
463112ee5af0SDamon Ding * delay_line_num = 4 - BPP / 8
463212ee5af0SDamon Ding * = (64 - target_bpp / 8) / 16
463312ee5af0SDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
46341ace1b6dSDamon Ding *
46351ace1b6dSDamon Ding * MIPI DSI[4320 and 9216 is buffer size for DSC]:
46361ace1b6dSDamon Ding * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size;
46371ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
46381ace1b6dSDamon Ding * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size;
46391ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
46401ace1b6dSDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num
464112ee5af0SDamon Ding */
464212ee5af0SDamon Ding do_div(dsc_cds_rate, 1000000); /* hz to Mhz */
464312ee5af0SDamon Ding dsc_cds_rate_mhz = dsc_cds_rate;
46441ace1b6dSDamon Ding dsc_hsync = hsync_len / 2;
46451ace1b6dSDamon Ding if (dsc_interface_mode == VOP_DSC_IF_HDMI) {
464612ee5af0SDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16;
46471ace1b6dSDamon Ding } else {
46481ace1b6dSDamon Ding int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2;
46491ace1b6dSDamon Ding int delay_line_num = dsc_buf_size / cstate->dsc_slice_num /
46501ace1b6dSDamon Ding be16_to_cpu(cstate->pps.chunk_size);
46511ace1b6dSDamon Ding
46521ace1b6dSDamon Ding delay_line_num = delay_line_num > 5 ? 5 : delay_line_num;
46531ace1b6dSDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num;
46541ace1b6dSDamon Ding
46551ace1b6dSDamon Ding /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */
46561ace1b6dSDamon Ding if (dsc_hsync < 8)
46571ace1b6dSDamon Ding dsc_hsync = 8;
46581ace1b6dSDamon Ding }
465912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK,
466012ee5af0SDamon Ding DSC_INIT_DLY_MODE_SHIFT, 0, false);
466112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK,
466212ee5af0SDamon Ding DSC_INIT_DLY_NUM_SHIFT, dly_num, false);
466312ee5af0SDamon Ding
4664b61227a3SDamon Ding /*
4665b61227a3SDamon Ding * htotal / dclk_core = dsc_htotal /cds_clk
4666b61227a3SDamon Ding *
4667b61227a3SDamon Ding * dclk_core = DCLK / (1 << dclk_core->div_val)
4668b61227a3SDamon Ding * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val)
4669b61227a3SDamon Ding * txp_clk = DCLK / (1 << dsc_txp_clk->div_val)
4670b61227a3SDamon Ding *
4671b61227a3SDamon Ding * dsc_htotal = htotal * (1 << dclk_core->div_val) /
4672b61227a3SDamon Ding * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val))
4673b61227a3SDamon Ding */
4674b61227a3SDamon Ding dsc_htotal = htotal * (1 << cstate->dclk_core_div) /
4675b61227a3SDamon Ding ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div));
467612ee5af0SDamon Ding val = dsc_htotal << 16 | dsc_hsync;
467712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK,
467812ee5af0SDamon Ding DSC_HTOTAL_PW_SHIFT, val, false);
467912ee5af0SDamon Ding
468012ee5af0SDamon Ding dsc_hact_st = hact_st / 2;
4681b61227a3SDamon Ding dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st;
468212ee5af0SDamon Ding val = dsc_hact_end << 16 | dsc_hact_st;
468312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK,
468412ee5af0SDamon Ding DSC_HACT_ST_END_SHIFT, val, false);
468512ee5af0SDamon Ding
468612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK,
468712ee5af0SDamon Ding DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false);
468812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK,
468912ee5af0SDamon Ding DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false);
469012ee5af0SDamon Ding }
469112ee5af0SDamon Ding
469212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK,
469312ee5af0SDamon Ding RST_DEASSERT_SHIFT, 1, false);
469412ee5af0SDamon Ding udelay(10);
469512ee5af0SDamon Ding
4696baf2c414SDamon Ding val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) |
4697baf2c414SDamon Ding ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT);
4698baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
4699baf2c414SDamon Ding
470012ee5af0SDamon Ding vop2_load_pps(state, vop2, dsc_id);
470112ee5af0SDamon Ding
4702baf2c414SDamon Ding val |= (1 << DSC_PPS_UPD_SHIFT);
4703baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val);
470412ee5af0SDamon Ding
470512ee5af0SDamon Ding printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n",
470612ee5af0SDamon Ding dsc_id,
470712ee5af0SDamon Ding cstate->dsc_txp_clk_rate, dsc_txp_clk_div,
470812ee5af0SDamon Ding cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div,
470912ee5af0SDamon Ding cstate->dsc_cds_clk_rate, dsc_cds_clk_div);
471012ee5af0SDamon Ding }
471112ee5af0SDamon Ding
is_extend_pll(struct display_state * state,struct udevice ** clk_dev)47125f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev)
47135f1357a2SZhang Yubing {
47145f1357a2SZhang Yubing struct crtc_state *cstate = &state->crtc_state;
47155f1357a2SZhang Yubing struct vop2 *vop2 = cstate->private;
47165f1357a2SZhang Yubing struct udevice *vp_dev, *dev;
47175f1357a2SZhang Yubing struct ofnode_phandle_args args;
47185f1357a2SZhang Yubing char vp_name[10];
47195f1357a2SZhang Yubing int ret;
47205f1357a2SZhang Yubing
4721a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576)
47225f1357a2SZhang Yubing return false;
47235f1357a2SZhang Yubing
47245f1357a2SZhang Yubing sprintf(vp_name, "port@%d", cstate->crtc_id);
47255f1357a2SZhang Yubing if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) {
47265e85f4a7SZhang Yubing debug("warn: can't get vp device\n");
47275f1357a2SZhang Yubing return false;
47285f1357a2SZhang Yubing }
47295f1357a2SZhang Yubing
47305f1357a2SZhang Yubing ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0,
47315f1357a2SZhang Yubing 0, &args);
47325f1357a2SZhang Yubing if (ret) {
47335e85f4a7SZhang Yubing debug("assigned-clock-parents's node not define\n");
47345f1357a2SZhang Yubing return false;
47355f1357a2SZhang Yubing }
47365f1357a2SZhang Yubing
47375f1357a2SZhang Yubing if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) {
47385e85f4a7SZhang Yubing debug("warn: can't get clk device\n");
47395f1357a2SZhang Yubing return false;
47405f1357a2SZhang Yubing }
47415f1357a2SZhang Yubing
47425f1357a2SZhang Yubing if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) {
47435f1357a2SZhang Yubing printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name);
47445f1357a2SZhang Yubing if (clk_dev)
47455f1357a2SZhang Yubing *clk_dev = dev;
47465f1357a2SZhang Yubing return true;
47475f1357a2SZhang Yubing }
47485f1357a2SZhang Yubing
47495f1357a2SZhang Yubing return false;
47505f1357a2SZhang Yubing }
47515f1357a2SZhang Yubing
vop3_mcu_mode_setup(struct display_state * state)47520675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state)
47530675a2a4SDamon Ding {
47540675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state;
47550675a2a4SDamon Ding struct vop2 *vop2 = cstate->private;
47560675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100);
47570675a2a4SDamon Ding
47580675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47590675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false);
47600675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47610675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false);
47620675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
47630675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false);
47640675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
47650675a2a4SDamon Ding MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false);
47660675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
47670675a2a4SDamon Ding MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false);
47680675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
47690675a2a4SDamon Ding MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false);
47700675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
47710675a2a4SDamon Ding MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false);
47720675a2a4SDamon Ding }
47730675a2a4SDamon Ding
vop3_mcu_bypass_mode_setup(struct display_state * state)47740675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state)
47750675a2a4SDamon Ding {
47760675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state;
47770675a2a4SDamon Ding struct vop2 *vop2 = cstate->private;
47780675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100);
47790675a2a4SDamon Ding
47800675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47810675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false);
47820675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
47830675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false);
47840675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK,
47850675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, 53, false);
47860675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK,
47870675a2a4SDamon Ding MCU_CS_PST_SHIFT, 6, false);
47880675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK,
47890675a2a4SDamon Ding MCU_CS_PEND_SHIFT, 48, false);
47900675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK,
47910675a2a4SDamon Ding MCU_RW_PST_SHIFT, 12, false);
47920675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK,
47930675a2a4SDamon Ding MCU_RW_PEND_SHIFT, 30, false);
47940675a2a4SDamon Ding }
47950675a2a4SDamon Ding
rockchip_vop2_send_mcu_cmd(struct display_state * state,u32 type,u32 value)47960675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value)
47970675a2a4SDamon Ding {
47980675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state;
47990675a2a4SDamon Ding struct connector_state *conn_state = &state->conn_state;
48000675a2a4SDamon Ding struct drm_display_mode *mode = &conn_state->mode;
48010675a2a4SDamon Ding struct vop2 *vop2 = cstate->private;
48020675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100);
48030675a2a4SDamon Ding
48040675a2a4SDamon Ding /*
480558cf1fa3SDamon Ding * 1.set mcu bypass mode timing.
480658cf1fa3SDamon Ding * 2.set dclk rate to 150M.
48070675a2a4SDamon Ding */
48080675a2a4SDamon Ding if (type == MCU_SETBYPASS && value) {
48090675a2a4SDamon Ding vop3_mcu_bypass_mode_setup(state);
48100675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, 150000000);
48110675a2a4SDamon Ding }
48120675a2a4SDamon Ding
48130675a2a4SDamon Ding switch (type) {
48140675a2a4SDamon Ding case MCU_WRCMD:
48150675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48160675a2a4SDamon Ding MCU_RS_SHIFT, 0, false);
48170675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
48180675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
48190675a2a4SDamon Ding value, false);
48200675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48210675a2a4SDamon Ding MCU_RS_SHIFT, 1, false);
48220675a2a4SDamon Ding break;
48230675a2a4SDamon Ding case MCU_WRDATA:
48240675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48250675a2a4SDamon Ding MCU_RS_SHIFT, 1, false);
48260675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset,
48270675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT,
48280675a2a4SDamon Ding value, false);
48290675a2a4SDamon Ding break;
48300675a2a4SDamon Ding case MCU_SETBYPASS:
48310675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
48320675a2a4SDamon Ding MCU_BYPASS_SHIFT, value ? 1 : 0, false);
48330675a2a4SDamon Ding break;
48340675a2a4SDamon Ding default:
48350675a2a4SDamon Ding break;
48360675a2a4SDamon Ding }
48370675a2a4SDamon Ding
48380675a2a4SDamon Ding /*
483958cf1fa3SDamon Ding * 1.restore mcu data mode timing.
484058cf1fa3SDamon Ding * 2.restore dclk rate to crtc_clock.
48410675a2a4SDamon Ding */
48420675a2a4SDamon Ding if (type == MCU_SETBYPASS && !value) {
48430675a2a4SDamon Ding vop3_mcu_mode_setup(state);
48440675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000);
48450675a2a4SDamon Ding }
48460675a2a4SDamon Ding
48470675a2a4SDamon Ding return 0;
48480675a2a4SDamon Ding }
48490675a2a4SDamon Ding
vop2_dither_setup(struct vop2 * vop2,int bus_format,int crtc_id)485034d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id)
485134d37ef0SDamon Ding {
4852a552a69cSDamon Ding const struct vop2_data *vop2_data = vop2->data;
4853a552a69cSDamon Ding const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id];
485434d37ef0SDamon Ding u32 vp_offset = crtc_id * 0x100;
485534d37ef0SDamon Ding bool pre_dither_down_en = false;
485634d37ef0SDamon Ding
485734d37ef0SDamon Ding switch (bus_format) {
485834d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB565_1X16:
485940608a7cSDamon Ding case MEDIA_BUS_FMT_RGB565_2X8_LE:
4860e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4861e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, true, false);
4862e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4863e2bdb3b3SDamon Ding DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false);
486434d37ef0SDamon Ding pre_dither_down_en = true;
486534d37ef0SDamon Ding break;
486634d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X18:
486734d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
486834d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
486940608a7cSDamon Ding case MEDIA_BUS_FMT_RGB666_3X6:
4870e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4871e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, true, false);
4872e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4873e2bdb3b3SDamon Ding DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false);
487434d37ef0SDamon Ding pre_dither_down_en = true;
487534d37ef0SDamon Ding break;
487634d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16:
487734d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV8_1X24:
487834d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
4879e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4880e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false);
488134d37ef0SDamon Ding pre_dither_down_en = true;
488234d37ef0SDamon Ding break;
488334d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV10_1X20:
488434d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV10_1X30:
488534d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
488634d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB101010_1X30:
4887e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4888e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false);
488934d37ef0SDamon Ding pre_dither_down_en = false;
489034d37ef0SDamon Ding break;
489134d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_3X8:
489234d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
489334d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X24:
489434d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
489534d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
489634d37ef0SDamon Ding default:
4897e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4898e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false);
489934d37ef0SDamon Ding pre_dither_down_en = true;
490034d37ef0SDamon Ding break;
490134d37ef0SDamon Ding }
490234d37ef0SDamon Ding
4903e2bdb3b3SDamon Ding if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0)
490434d37ef0SDamon Ding pre_dither_down_en = false;
490534d37ef0SDamon Ding
4906a552a69cSDamon Ding if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) {
4907481ef52dSDamon Ding if (vop2->version == VOP_VERSION_RK3576) {
4908481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000);
4909481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100);
4910481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100);
4911481ef52dSDamon Ding }
4912481ef52dSDamon Ding
4913a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4914a552a69cSDamon Ding PRE_DITHER_DOWN_EN_SHIFT, 0, false);
4915e2bdb3b3SDamon Ding /* enable frc2.0 do 10->8 */
4916a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
4917a552a69cSDamon Ding DITHER_DOWN_EN_SHIFT, 1, false);
4918e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4919e2bdb3b3SDamon Ding DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false);
4920a552a69cSDamon Ding } else {
492134d37ef0SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
492234d37ef0SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false);
4923e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK,
4924e2bdb3b3SDamon Ding DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false);
492534d37ef0SDamon Ding }
4926a552a69cSDamon Ding }
492734d37ef0SDamon Ding
rockchip_vop2_init(struct display_state * state)4928ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state)
4929ecc31b6eSAndy Yan {
4930ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state;
4931c2b1fe35SDamon Ding struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id];
4932ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state;
4933ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode;
4934ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private;
4935ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
4936ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay;
4937ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal;
4938ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
4939ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay;
4940ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay;
4941ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal;
4942ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
4943ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
4944ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay;
4945ecc31b6eSAndy Yan bool yuv_overlay = false;
4946ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100);
494766724b9cSDamon Ding u32 line_flag_offset = (cstate->crtc_id * 4);
494866724b9cSDamon Ding u32 val, act_end;
494958cf1fa3SDamon Ding u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
4950edfef528SDamon Ding u8 dclk_div_factor = 0;
4951a552a69cSDamon Ding u8 vp_dclk_div = 1;
4952ecc31b6eSAndy Yan char output_type_name[30] = {0};
4953d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
4954ecc31b6eSAndy Yan char dclk_name[9];
4955d8e7f4a5SSandy Huang #endif
4956b890760eSAlgea Cao struct clk hdmi0_phy_pll;
4957b890760eSAlgea Cao struct clk hdmi1_phy_pll;
49585f1357a2SZhang Yubing struct clk hdmi_phy_pll;
49593e05a7b8SZhang Yubing struct udevice *disp_dev;
49605fa6e665SDamon Ding unsigned long dclk_rate = 0;
4961ecc31b6eSAndy Yan int ret;
4962ecc31b6eSAndy Yan
4963ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n",
496471ac76f7SDamon Ding mode->crtc_hdisplay, mode->vdisplay,
4965ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
49664d64cedbSDamon Ding mode->vrefresh,
49672264c88bSDamon Ding rockchip_get_output_if_name(conn_state->output_if, output_type_name),
4968ecc31b6eSAndy Yan cstate->crtc_id);
4969ecc31b6eSAndy Yan
4970ee01dbb2SDamon Ding if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {
4971ee01dbb2SDamon Ding cstate->splice_mode = true;
4972ee01dbb2SDamon Ding cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id;
4973ee01dbb2SDamon Ding if (!cstate->splice_crtc_id) {
4974ee01dbb2SDamon Ding printf("%s: Splice mode is unsupported by vp%d\n",
4975ee01dbb2SDamon Ding __func__, cstate->crtc_id);
4976ee01dbb2SDamon Ding return -EINVAL;
4977ee01dbb2SDamon Ding }
4978b70b2d79SDamon Ding
4979b70b2d79SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK,
4980b70b2d79SDamon Ding PORT_MERGE_EN_SHIFT, 1, false);
4981ee01dbb2SDamon Ding }
4982ee01dbb2SDamon Ding
4983cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4984cd6c85a9SDamon Ding RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4985cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK,
4986cd6c85a9SDamon Ding RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false);
4987cd6c85a9SDamon Ding
498844b1b62cSDamon Ding if (vop2->data->vp_data[cstate->crtc_id].urgency) {
498944b1b62cSDamon Ding u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl;
499044b1b62cSDamon Ding u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh;
499144b1b62cSDamon Ding
499244b1b62cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK,
499344b1b62cSDamon Ding AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
499444b1b62cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK,
499544b1b62cSDamon Ding AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false);
499644b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK,
499744b1b62cSDamon Ding POST_URGENCY_EN_SHIFT, 1, false);
499844b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK,
499944b1b62cSDamon Ding POST_URGENCY_THL_SHIFT, urgen_thl, false);
500044b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK,
500144b1b62cSDamon Ding POST_URGENCY_THH_SHIFT, urgen_thh, false);
500244b1b62cSDamon Ding }
500344b1b62cSDamon Ding
5004ecc31b6eSAndy Yan vop2_initial(vop2, state);
5005ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588)
5006ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state);
5007a552a69cSDamon Ding else if (vop2->version == VOP_VERSION_RK3576)
5008a552a69cSDamon Ding dclk_rate = rk3576_vop2_if_cfg(state);
50095fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3568)
5010ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state);
5011452afb13SDamon Ding else if (vop2->version == VOP_VERSION_RK3562)
5012452afb13SDamon Ding dclk_rate = rk3562_vop2_if_cfg(state);
5013a552a69cSDamon Ding else if (vop2->version == VOP_VERSION_RK3528)
5014a552a69cSDamon Ding dclk_rate = rk3528_vop2_if_cfg(state);
5015ecc31b6eSAndy Yan
50165d2768f7SDamon Ding if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
50175d2768f7SDamon Ding !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
50185d2768f7SDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656)
50197bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
50207bdd0eb6SSandy Huang
5021bf7c1abfSDamon Ding if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
5022bf7c1abfSDamon Ding if (vop2->version == VOP_VERSION_RK3588 &&
5023bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
5024bf7c1abfSDamon Ding conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420;
5025bf7c1abfSDamon Ding } else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) {
5026bf7c1abfSDamon Ding if (vop2->version == VOP_VERSION_RK3576 &&
5027bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_eDP)
5028bf7c1abfSDamon Ding conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422;
5029bf7c1abfSDamon Ding else if (vop2->version == VOP_VERSION_RK3588 &&
5030bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_eDP)
5031bf7c1abfSDamon Ding conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422;
5032bf7c1abfSDamon Ding else if (vop2->version == VOP_VERSION_RK3576 &&
5033bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
5034bf7c1abfSDamon Ding conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422;
5035bf7c1abfSDamon Ding else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort)
5036bf7c1abfSDamon Ding conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422;
5037bf7c1abfSDamon Ding }
5038bf7c1abfSDamon Ding
503965747de7SDamon Ding vop2_post_color_swap(state);
504010ee9f5bSAlgea Cao
5041d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK,
5042d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false);
5043d0408543SAndy Yan
504434d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id);
504534d37ef0SDamon Ding if (cstate->splice_mode)
504634d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id);
5047d0408543SAndy Yan
5048d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0;
5049d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id,
5050d0408543SAndy Yan yuv_overlay, false);
5051d0408543SAndy Yan
5052d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay;
5053d0408543SAndy Yan
5054d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset,
5055d0408543SAndy Yan (htotal << 16) | hsync_len);
5056d0408543SAndy Yan val = hact_st << 16;
5057d0408543SAndy Yan val |= hact_end;
5058d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val);
5059d0408543SAndy Yan val = vact_st << 16;
5060d0408543SAndy Yan val |= vact_end;
5061d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val);
5062d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
5063d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1;
5064d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay;
5065d0408543SAndy Yan
5066d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1;
5067d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset,
5068d0408543SAndy Yan val);
5069d0408543SAndy Yan
5070d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len);
5071d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val);
5072d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5073d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false);
5074d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
50757a20be36SSandy Huang DSP_FILED_POL, 1, false);
50767a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5077d0408543SAndy Yan P2I_EN_SHIFT, 1, false);
5078d0408543SAndy Yan vtotal += vtotal + 1;
507966724b9cSDamon Ding act_end = vact_end_f1;
5080d0408543SAndy Yan } else {
5081d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5082d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false);
5083d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5084d0408543SAndy Yan P2I_EN_SHIFT, 0, false);
508566724b9cSDamon Ding act_end = vact_end;
5086d0408543SAndy Yan }
5087d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset,
5088d0408543SAndy Yan (vtotal << 16) | vsync_len);
508967be2ffcSDamon Ding
5090a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3528 ||
5091a552a69cSDamon Ding vop2->version == VOP_VERSION_RK3562 ||
5092a552a69cSDamon Ding vop2->version == VOP_VERSION_RK3568) {
509367be2ffcSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
509467be2ffcSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656)
5095d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
509667be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 1, false);
509767be2ffcSDamon Ding else
509867be2ffcSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
509967be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 0, false);
510010ee9f5bSAlgea Cao
510110ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420)
510263cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
510363cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false);
510410ee9f5bSAlgea Cao else
510563cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
510663cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false);
5107a552a69cSDamon Ding }
510810ee9f5bSAlgea Cao
5109ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
5110ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false);
5111ee01dbb2SDamon Ding
511210ee9f5bSAlgea Cao if (yuv_overlay)
511310ee9f5bSAlgea Cao val = 0x20010200;
511410ee9f5bSAlgea Cao else
511510ee9f5bSAlgea Cao val = 0;
511610ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val);
5117b70b2d79SDamon Ding if (cstate->splice_mode) {
5118ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK,
5119ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id,
5120ee01dbb2SDamon Ding yuv_overlay, false);
5121ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val);
5122ee01dbb2SDamon Ding }
512310ee9f5bSAlgea Cao
512410ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
512510ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false);
5126d0408543SAndy Yan
5127c2b1fe35SDamon Ding if (vp->xmirror_en)
5128c2b1fe35SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5129c2b1fe35SDamon Ding DSP_X_MIR_EN_SHIFT, 1, false);
5130c2b1fe35SDamon Ding
5131ac500a1fSSandy Huang vop2_tv_config_update(state, vop2);
5132d0408543SAndy Yan vop2_post_config(state, vop2);
51336027c871SZhang Yubing if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC))
51346027c871SZhang Yubing vop3_post_config(state, vop2);
5135d0408543SAndy Yan
513612ee5af0SDamon Ding if (cstate->dsc_enable) {
513712ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
51381ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL);
51391ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL);
514012ee5af0SDamon Ding } else {
51411ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL);
514212ee5af0SDamon Ding }
514312ee5af0SDamon Ding }
514412ee5af0SDamon Ding
5145d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
5146ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id);
51470675a2a4SDamon Ding ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk);
5148b890760eSAlgea Cao if (ret) {
5149b890760eSAlgea Cao printf("%s: Failed to get dclk ret=%d\n", __func__, ret);
5150b890760eSAlgea Cao return ret;
5151b890760eSAlgea Cao }
5152d8e7f4a5SSandy Huang #endif
5153b890760eSAlgea Cao
51543e05a7b8SZhang Yubing ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev);
51553e05a7b8SZhang Yubing if (!ret) {
51563e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll);
51573e05a7b8SZhang Yubing if (ret)
51585e85f4a7SZhang Yubing debug("%s: hdmi0_phy_pll may not define\n", __func__);
51593e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll);
51603e05a7b8SZhang Yubing if (ret)
51615e85f4a7SZhang Yubing debug("%s: hdmi1_phy_pll may not define\n", __func__);
51623e05a7b8SZhang Yubing } else {
5163b890760eSAlgea Cao hdmi0_phy_pll.dev = NULL;
5164545a0218SAlgea Cao hdmi1_phy_pll.dev = NULL;
51655e85f4a7SZhang Yubing debug("%s: Faile to find display-subsystem node\n", __func__);
5166b890760eSAlgea Cao }
5167b890760eSAlgea Cao
5168ebbd144cSAlgea Cao if (vop2->version == VOP_VERSION_RK3528) {
5169ebbd144cSAlgea Cao struct ofnode_phandle_args args;
5170ebbd144cSAlgea Cao
5171ebbd144cSAlgea Cao ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents",
5172ebbd144cSAlgea Cao "#clock-cells", 0, 0, &args);
5173ebbd144cSAlgea Cao if (!ret) {
5174ebbd144cSAlgea Cao ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev);
5175ebbd144cSAlgea Cao if (ret) {
5176ebbd144cSAlgea Cao debug("warn: can't get clk device\n");
5177ebbd144cSAlgea Cao return ret;
5178ebbd144cSAlgea Cao }
5179ebbd144cSAlgea Cao } else {
5180ebbd144cSAlgea Cao debug("assigned-clock-parents's node not define\n");
5181ebbd144cSAlgea Cao }
5182ebbd144cSAlgea Cao }
5183ebbd144cSAlgea Cao
5184cce1f2abSDamon Ding if (vop2->version == VOP_VERSION_RK3576)
5185cce1f2abSDamon Ding vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div;
5186cce1f2abSDamon Ding
51870a1fb152SZhang Yubing if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) {
5188b890760eSAlgea Cao if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0)
51890675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll);
5190b890760eSAlgea Cao else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1)
51910675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll);
5192b890760eSAlgea Cao
5193b890760eSAlgea Cao /*
5194b890760eSAlgea Cao * uboot clk driver won't set dclk parent's rate when use
5195b890760eSAlgea Cao * hdmi phypll as dclk source.
5196b890760eSAlgea Cao * So set dclk rate is meaningless. Set hdmi phypll rate
5197b890760eSAlgea Cao * directly.
5198b890760eSAlgea Cao */
51995f1357a2SZhang Yubing if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) {
5200cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000);
52015f1357a2SZhang Yubing } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) {
5202cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000);
52035f1357a2SZhang Yubing } else {
52047efea85dSDamon Ding if (is_extend_pll(state, &hdmi_phy_pll.dev)) {
5205cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi_phy_pll,
5206cce1f2abSDamon Ding dclk_rate / vp_dclk_div * 1000);
52077efea85dSDamon Ding } else {
5208d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
5209a552a69cSDamon Ding ret = vop2_clk_set_rate(&cstate->dclk,
5210a552a69cSDamon Ding dclk_rate / vp_dclk_div * 1000);
5211d8e7f4a5SSandy Huang #else
5212d8e7f4a5SSandy Huang if (vop2->version == VOP_VERSION_RK3528) {
5213d8e7f4a5SSandy Huang void *cru_base = (void *)RK3528_CRU_BASE;
5214d8e7f4a5SSandy Huang
5215d8e7f4a5SSandy Huang /* dclk src switch to hdmiphy pll */
5216d8e7f4a5SSandy Huang writel((BIT(0) << 16) | BIT(0), cru_base + 0x450);
5217d8e7f4a5SSandy Huang rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000);
5218d8e7f4a5SSandy Huang ret = dclk_rate * 1000;
5219d8e7f4a5SSandy Huang }
5220d8e7f4a5SSandy Huang #endif
52215f1357a2SZhang Yubing }
52227efea85dSDamon Ding }
5223631ee99aSZhang Yubing } else {
52245f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev))
5225cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000);
52265f1357a2SZhang Yubing else
5227cce1f2abSDamon Ding ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000);
5228edfef528SDamon Ding }
522963638f32SDamon Ding
523063638f32SDamon Ding if (IS_ERR_VALUE(ret)) {
523163638f32SDamon Ding printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n",
523263638f32SDamon Ding __func__, cstate->crtc_id, dclk_rate, ret);
523363638f32SDamon Ding return ret;
523463638f32SDamon Ding } else {
52354d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total) {
52364d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) / 1000;
52374d64cedbSDamon Ding } else {
52389655ad2fSDamon Ding dclk_div_factor = mode->crtc_clock / dclk_rate;
52394d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000;
52404d64cedbSDamon Ding }
5241edfef528SDamon Ding printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock);
5242631ee99aSZhang Yubing }
5243ecc31b6eSAndy Yan
524466724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
5245e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false);
524666724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK,
5247e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false);
524866724b9cSDamon Ding
524958cf1fa3SDamon Ding if (cstate->mcu_timing.mcu_pix_total) {
525058cf1fa3SDamon Ding vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
525158cf1fa3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
525258cf1fa3SDamon Ding STANDBY_EN_SHIFT, 0, false);
52530675a2a4SDamon Ding vop3_mcu_mode_setup(state);
525458cf1fa3SDamon Ding }
52550675a2a4SDamon Ding
5256d0408543SAndy Yan return 0;
5257d0408543SAndy Yan }
5258d0408543SAndy Yan
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)5259ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win,
52603e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w,
52613e39a5a1SSandy Huang uint32_t dst_h)
52623e39a5a1SSandy Huang {
52633e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
52643e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode;
52655fa6e665SDamon Ding uint8_t xgt2 = 0, xgt4 = 0;
52665fa6e665SDamon Ding uint8_t ygt2 = 0, ygt4 = 0;
52673e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0;
5268ecc31b6eSAndy Yan u32 win_offset = win->reg_offset;
52695fa6e665SDamon Ding bool xgt_en = false;
52705fa6e665SDamon Ding bool xavg_en = false;
52713e39a5a1SSandy Huang
52725fa6e665SDamon Ding if (is_vop3(vop2)) {
5273a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) {
5274a552a69cSDamon Ding if (src_w >= (8 * dst_w)) {
5275a552a69cSDamon Ding xgt4 = 1;
5276a552a69cSDamon Ding src_w >>= 2;
5277a552a69cSDamon Ding } else if (src_w >= (4 * dst_w)) {
5278a552a69cSDamon Ding xgt2 = 1;
5279a552a69cSDamon Ding src_w >>= 1;
5280a552a69cSDamon Ding }
5281a552a69cSDamon Ding } else {
52825fa6e665SDamon Ding if (src_w >= (4 * dst_w)) {
52835fa6e665SDamon Ding xgt4 = 1;
52845fa6e665SDamon Ding src_w >>= 2;
52855fa6e665SDamon Ding } else if (src_w >= (2 * dst_w)) {
52865fa6e665SDamon Ding xgt2 = 1;
52875fa6e665SDamon Ding src_w >>= 1;
52885fa6e665SDamon Ding }
52895fa6e665SDamon Ding }
5290a552a69cSDamon Ding }
52913e39a5a1SSandy Huang
5292183eb252SDamon Ding /**
5293183eb252SDamon Ding * The rk3528 is processed as 2 pixel/cycle,
5294183eb252SDamon Ding * so ygt2/ygt4 needs to be triggered in advance to improve performance
5295183eb252SDamon Ding * when src_w is bigger than 1920.
5296183eb252SDamon Ding * dst_h / src_h is at [1, 0.65) ygt2=0; ygt4=0;
5297183eb252SDamon Ding * dst_h / src_h is at [0.65, 0.35) ygt2=1; ygt4=0;
5298183eb252SDamon Ding * dst_h / src_h is at [0.35, 0) ygt2=0; ygt4=1;
5299183eb252SDamon Ding */
5300183eb252SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) {
5301183eb252SDamon Ding if (src_h >= (100 * dst_h / 35)) {
5302183eb252SDamon Ding ygt4 = 1;
5303183eb252SDamon Ding src_h >>= 2;
5304183eb252SDamon Ding } else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) {
5305183eb252SDamon Ding ygt2 = 1;
5306183eb252SDamon Ding src_h >>= 1;
5307183eb252SDamon Ding }
5308183eb252SDamon Ding } else {
5309a552a69cSDamon Ding if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) {
5310a552a69cSDamon Ding if (src_h >= (8 * dst_h)) {
5311a552a69cSDamon Ding ygt4 = 1;
5312a552a69cSDamon Ding src_h >>= 2;
5313a552a69cSDamon Ding } else if (src_h >= (4 * dst_h)) {
5314a552a69cSDamon Ding ygt2 = 1;
5315a552a69cSDamon Ding src_h >>= 1;
5316a552a69cSDamon Ding }
5317a552a69cSDamon Ding } else {
53185fa6e665SDamon Ding if (src_h >= (4 * dst_h)) {
53195fa6e665SDamon Ding ygt4 = 1;
53203e39a5a1SSandy Huang src_h >>= 2;
53215fa6e665SDamon Ding } else if (src_h >= (2 * dst_h)) {
53225fa6e665SDamon Ding ygt2 = 1;
53233e39a5a1SSandy Huang src_h >>= 1;
53245fa6e665SDamon Ding }
5325183eb252SDamon Ding }
5326a552a69cSDamon Ding }
53273e39a5a1SSandy Huang
53283e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
53293e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
53303e39a5a1SSandy Huang
53313e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP)
53325fa6e665SDamon Ding hscl_filter_mode = win->hsu_filter_mode;
53333e39a5a1SSandy Huang else
53345fa6e665SDamon Ding hscl_filter_mode = win->hsd_filter_mode;
53353e39a5a1SSandy Huang
53363e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP)
53375fa6e665SDamon Ding vscl_filter_mode = win->vsu_filter_mode;
53383e39a5a1SSandy Huang else
53395fa6e665SDamon Ding vscl_filter_mode = win->vsd_filter_mode;
53403e39a5a1SSandy Huang
53413e39a5a1SSandy Huang /*
53423e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel
53433e39a5a1SSandy Huang * at scale down mode
53443e39a5a1SSandy Huang */
53455fa6e665SDamon Ding if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) {
53463e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w);
53473e39a5a1SSandy Huang dst_w += 1;
53483e39a5a1SSandy Huang }
53493e39a5a1SSandy Huang
53505fa6e665SDamon Ding if (is_vop3(vop2)) {
53515fa6e665SDamon Ding xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true);
53525fa6e665SDamon Ding yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false);
53535fa6e665SDamon Ding
53545fa6e665SDamon Ding if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG)
53555fa6e665SDamon Ding xavg_en = xgt2 || xgt4;
53565fa6e665SDamon Ding else
53575fa6e665SDamon Ding xgt_en = xgt2 || xgt4;
5358a552a69cSDamon Ding
5359a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) {
5360a552a69cSDamon Ding bool zme_dering_en = false;
5361a552a69cSDamon Ding
5362a552a69cSDamon Ding if ((yrgb_hor_scl_mode == SCALE_UP &&
5363a552a69cSDamon Ding hscl_filter_mode == VOP2_SCALE_UP_ZME) ||
5364a552a69cSDamon Ding (yrgb_ver_scl_mode == SCALE_UP &&
5365a552a69cSDamon Ding vscl_filter_mode == VOP2_SCALE_UP_ZME))
5366a552a69cSDamon Ding zme_dering_en = true;
5367a552a69cSDamon Ding
5368a552a69cSDamon Ding /* Recommended configuration from the algorithm */
5369a552a69cSDamon Ding vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset,
5370a552a69cSDamon Ding 0x04100d10);
5371a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset,
5372a552a69cSDamon Ding EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false);
5373a552a69cSDamon Ding }
53745fa6e665SDamon Ding } else {
53753e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w);
53763e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h);
53775fa6e665SDamon Ding }
5378ecc31b6eSAndy Yan
5379ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) {
5380ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset,
5381ecc31b6eSAndy Yan yfac << 16 | xfac);
5382ecc31b6eSAndy Yan
53835fa6e665SDamon Ding if (is_vop3(vop2)) {
5384ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53855fa6e665SDamon Ding EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false);
5386ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53875fa6e665SDamon Ding EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false);
53885fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53895fa6e665SDamon Ding XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
5390ecc31b6eSAndy Yan
5391ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53925fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT,
53935fa6e665SDamon Ding yrgb_hor_scl_mode, false);
5394ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53955fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT,
53965fa6e665SDamon Ding yrgb_ver_scl_mode, false);
53975fa6e665SDamon Ding } else {
53985fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
53995fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT,
54005fa6e665SDamon Ding yrgb_hor_scl_mode, false);
54015fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54025fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT,
54035fa6e665SDamon Ding yrgb_ver_scl_mode, false);
54045fa6e665SDamon Ding }
5405ecc31b6eSAndy Yan
54065fa6e665SDamon Ding if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) {
54075fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54085fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false);
54095fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54105fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false);
54115fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54125fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false);
54135fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54145fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false);
54155fa6e665SDamon Ding } else {
54165fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54175fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false);
54185fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54195fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false);
54205fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54215fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false);
54225fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset,
54235fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false);
54245fa6e665SDamon Ding }
5425ecc31b6eSAndy Yan } else {
54263e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset,
54273e39a5a1SSandy Huang yfac << 16 | xfac);
54283e39a5a1SSandy Huang
54295fa6e665SDamon Ding if (is_vop3(vop2)) {
543034a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54315fa6e665SDamon Ding EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false);
543234a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54335fa6e665SDamon Ding EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false);
54345fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54355fa6e665SDamon Ding XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false);
54365fa6e665SDamon Ding }
54375fa6e665SDamon Ding
54385fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54395fa6e665SDamon Ding YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false);
54405fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
54415fa6e665SDamon Ding YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false);
54423e39a5a1SSandy Huang
54433e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54443e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false);
54453e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54463e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false);
54473e39a5a1SSandy Huang
54483e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54493e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT,
54503e39a5a1SSandy Huang hscl_filter_mode, false);
54513e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset,
54523e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT,
54533e39a5a1SSandy Huang vscl_filter_mode, false);
54543e39a5a1SSandy Huang }
5455ecc31b6eSAndy Yan }
54563e39a5a1SSandy Huang
vop2_axi_config(struct vop2 * vop2,struct vop2_win_data * win)5457a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win)
5458a33b790fSDamon Ding {
5459a33b790fSDamon Ding u32 win_offset = win->reg_offset;
5460a33b790fSDamon Ding
5461a33b790fSDamon Ding if (win->type == CLUSTER_LAYER) {
5462a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK,
5463a33b790fSDamon Ding CLUSTER_AXI_ID_SHIFT, win->axi_id, false);
5464a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK,
5465a33b790fSDamon Ding CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5466a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK,
5467a33b790fSDamon Ding CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5468a33b790fSDamon Ding } else {
5469a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK,
5470a33b790fSDamon Ding ESMART_AXI_ID_SHIFT, win->axi_id, false);
5471a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK,
5472a33b790fSDamon Ding ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false);
5473a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK,
5474a33b790fSDamon Ding ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false);
5475a33b790fSDamon Ding }
5476a33b790fSDamon Ding }
5477a33b790fSDamon Ding
vop2_win_dither_up(uint32_t format)5478840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format)
5479840bf541SDamon Ding {
5480840bf541SDamon Ding switch (format) {
5481840bf541SDamon Ding case ROCKCHIP_FMT_RGB565:
5482840bf541SDamon Ding return true;
5483840bf541SDamon Ding default:
5484840bf541SDamon Ding return false;
5485840bf541SDamon Ding }
5486840bf541SDamon Ding }
5487840bf541SDamon Ding
vop2_is_mirror_win(struct vop2_win_data * win)54881c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win)
54891c9572c7SDamon Ding {
54901c9572c7SDamon Ding return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR);
54911c9572c7SDamon Ding }
54921c9572c7SDamon Ding
vop2_set_cluster_win(struct display_state * state,struct vop2_win_data * win)54931c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win)
5494d0408543SAndy Yan {
5495d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state;
5496d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state;
5497d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode;
5498d0408543SAndy Yan struct vop2 *vop2 = cstate->private;
54999c7848c3SDamon Ding const struct vop2_data *vop2_data = vop2->data;
55009c7848c3SDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops;
5501ee01dbb2SDamon Ding int src_w = cstate->src_rect.w;
5502ee01dbb2SDamon Ding int src_h = cstate->src_rect.h;
5503ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x;
5504ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y;
5505ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w;
5506ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h;
5507d0408543SAndy Yan int xvir = cstate->xvir;
5508d0408543SAndy Yan int y_mirror = 0;
550910ee9f5bSAlgea Cao int csc_mode;
5510ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5511ee01dbb2SDamon Ding /* offset of the right window in splice mode */
5512ee01dbb2SDamon Ding u32 splice_pixel_offset = 0;
5513ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0;
5514ecc31b6eSAndy Yan u32 win_offset = win->reg_offset;
5515840bf541SDamon Ding bool dither_up;
5516d0408543SAndy Yan
5517ee01dbb2SDamon Ding if (win->splice_mode_right) {
5518ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w;
5519ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h;
5520ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x;
5521ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y;
5522ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w;
5523ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h;
5524ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5525ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5526ee01dbb2SDamon Ding }
5527ee01dbb2SDamon Ding
5528ecc31b6eSAndy Yan act_info = (src_h - 1) << 16;
5529ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff;
5530ecc31b6eSAndy Yan
5531ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16;
5532ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff;
5533ecc31b6eSAndy Yan
5534ecc31b6eSAndy Yan dsp_stx = crtc_x;
5535ecc31b6eSAndy Yan dsp_sty = crtc_y;
5536ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5537ecc31b6eSAndy Yan
5538ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5539ecc31b6eSAndy Yan y_mirror = 1;
5540ecc31b6eSAndy Yan else
5541ecc31b6eSAndy Yan y_mirror = 0;
5542ecc31b6eSAndy Yan
5543ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
5544ecc31b6eSAndy Yan
5545a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3568)
5546a33b790fSDamon Ding vop2_axi_config(vop2, win);
5547a33b790fSDamon Ding
5548ecc31b6eSAndy Yan if (y_mirror)
5549ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n");
5550ecc31b6eSAndy Yan
55519c7848c3SDamon Ding if (is_vop3(vop2)) {
5552a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset,
55534751aa64SDamon Ding CLUSTER_PORT_SEL_MASK, CLUSTER_PORT_SEL_SHIFT,
5554a552a69cSDamon Ding cstate->crtc_id, false);
5555b888dbc8SSandy Huang vop2_ops->setup_win_dly(state, cstate->crtc_id, win->phys_id);
55569c7848c3SDamon Ding }
5557a552a69cSDamon Ding
5558e84ccd9bSDamon Ding /*
5559e84ccd9bSDamon Ding * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode.
5560e84ccd9bSDamon Ding */
5561e84ccd9bSDamon Ding if (vop2->version >= VOP_VERSION_RK3588)
5562a59754e1SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset,
5563a59754e1SDamon Ding EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false);
5564a59754e1SDamon Ding
5565ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
5566ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5567ecc31b6eSAndy Yan false);
55681615d939SSandy Huang vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset,
55691615d939SSandy Huang 0x1, CLUSTER_RB_SWAP_SHIFT, cstate->rb_swap, false);
5570ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir);
5571ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset,
5572ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset);
5573ecc31b6eSAndy Yan
5574ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info);
5575ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info);
5576ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st);
5577ecc31b6eSAndy Yan
5578df0a5c43SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5579df0a5c43SDamon Ding CSC_10BIT_DEPTH);
5580ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5581ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT,
5582ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false);
5583ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK,
5584ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false);
5585840bf541SDamon Ding
5586840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format);
5587840bf541SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK,
5588840bf541SDamon Ding CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false);
5589840bf541SDamon Ding
5590dd579ec5SSandy Huang vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false);
5591ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false);
5592ecc31b6eSAndy Yan
55931c9572c7SDamon Ding return 0;
5594d0408543SAndy Yan }
5595d0408543SAndy Yan
vop2_set_smart_win(struct display_state * state,struct vop2_win_data * win)55961c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win)
5597ecc31b6eSAndy Yan {
5598ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state;
5599ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state;
5600ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode;
5601ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private;
56029c7848c3SDamon Ding const struct vop2_data *vop2_data = vop2->data;
56039c7848c3SDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops;
5604ee01dbb2SDamon Ding int src_w = cstate->src_rect.w;
5605ee01dbb2SDamon Ding int src_h = cstate->src_rect.h;
5606ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x;
5607ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y;
5608ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w;
5609ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h;
5610ecc31b6eSAndy Yan int xvir = cstate->xvir;
5611ecc31b6eSAndy Yan int y_mirror = 0;
5612ecc31b6eSAndy Yan int csc_mode;
5613ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty;
5614ee01dbb2SDamon Ding /* offset of the right window in splice mode */
5615ee01dbb2SDamon Ding u32 splice_pixel_offset = 0;
5616ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0;
5617ecc31b6eSAndy Yan u32 win_offset = win->reg_offset;
56181c9572c7SDamon Ding u32 val;
5619840bf541SDamon Ding bool dither_up;
5620ecc31b6eSAndy Yan
56211c9572c7SDamon Ding if (vop2_is_mirror_win(win)) {
56221c9572c7SDamon Ding struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id);
56231c9572c7SDamon Ding
56241c9572c7SDamon Ding if (!source_win) {
56251c9572c7SDamon Ding printf("invalid source win id %d\n", win->source_win_id);
56261c9572c7SDamon Ding return -ENODEV;
56271c9572c7SDamon Ding }
56281c9572c7SDamon Ding
56291c9572c7SDamon Ding val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset);
56301c9572c7SDamon Ding if (!(val & BIT(WIN_EN_SHIFT))) {
56311c9572c7SDamon Ding printf("WARN: the source win should be enabled before mirror win\n");
56321c9572c7SDamon Ding return -EAGAIN;
56331c9572c7SDamon Ding }
56341c9572c7SDamon Ding }
56351c9572c7SDamon Ding
5636ee01dbb2SDamon Ding if (win->splice_mode_right) {
5637ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w;
5638ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h;
5639ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x;
5640ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y;
5641ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w;
5642ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h;
5643ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x;
5644ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3);
5645ee01dbb2SDamon Ding }
5646ee01dbb2SDamon Ding
564774bd8269SSandy Huang /*
564874bd8269SSandy Huang * This is workaround solution for IC design:
564974bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1.
565074bd8269SSandy Huang */
565174bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) {
565274bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w);
565374bd8269SSandy Huang src_w -= 1;
565474bd8269SSandy Huang }
565574bd8269SSandy Huang
5656d0408543SAndy Yan act_info = (src_h - 1) << 16;
5657d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff;
5658d0408543SAndy Yan
5659d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16;
5660d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff;
5661d0408543SAndy Yan
5662d0408543SAndy Yan dsp_stx = crtc_x;
5663d0408543SAndy Yan dsp_sty = crtc_y;
5664d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
5665d0408543SAndy Yan
5666d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR)
5667d0408543SAndy Yan y_mirror = 1;
5668d0408543SAndy Yan else
5669d0408543SAndy Yan y_mirror = 0;
5670d0408543SAndy Yan
5671a552a69cSDamon Ding if (is_vop3(vop2)) {
5672a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset,
5673a552a69cSDamon Ding ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT,
5674a552a69cSDamon Ding win->scale_engine_num, false);
5675a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5676a552a69cSDamon Ding ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5677a552a69cSDamon Ding cstate->crtc_id, false);
5678b888dbc8SSandy Huang vop2_ops->setup_win_dly(state, cstate->crtc_id, win->phys_id);
5679a552a69cSDamon Ding
5680a552a69cSDamon Ding /* Merge esmart1/3 from vp1 post to vp0 */
5681a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 &&
5682a552a69cSDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 ||
5683a552a69cSDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART3))
5684a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset,
5685a552a69cSDamon Ding ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT,
5686a552a69cSDamon Ding 1, false);
5687a552a69cSDamon Ding }
56885fa6e665SDamon Ding
5689ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h);
56903e39a5a1SSandy Huang
5691a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3568)
5692a33b790fSDamon Ding vop2_axi_config(vop2, win);
5693a33b790fSDamon Ding
5694d0408543SAndy Yan if (y_mirror)
5695d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4;
5696d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK,
5697d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false);
5698d0408543SAndy Yan
5699d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
5700d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format,
5701d0408543SAndy Yan false);
5702a552a69cSDamon Ding
57031615d939SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset,
57041615d939SSandy Huang 0x1, REGION0_RB_SWAP_SHIFT, cstate->rb_swap, false);
57051615d939SSandy Huang
5706a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576)
5707a552a69cSDamon Ding vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00);
5708a552a69cSDamon Ding
5709d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir);
5710d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset,
5711ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset);
5712d0408543SAndy Yan
5713d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset,
5714d0408543SAndy Yan act_info);
5715d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset,
5716d0408543SAndy Yan dsp_info);
5717d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st);
5718d0408543SAndy Yan
5719df0a5c43SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range,
5720df0a5c43SDamon Ding CSC_10BIT_DEPTH);
572110ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK,
572210ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT,
572310ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false);
572410ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK,
572510ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false);
572610ee9f5bSAlgea Cao
5727840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format);
5728840bf541SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5729840bf541SDamon Ding REGION0_DITHER_UP_EN_SHIFT, dither_up, false);
5730840bf541SDamon Ding
5731dd579ec5SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK,
5732dd579ec5SSandy Huang WIN_EN_SHIFT, 1, false);
57331c9572c7SDamon Ding
57341c9572c7SDamon Ding return 0;
5735ecc31b6eSAndy Yan }
5736ecc31b6eSAndy Yan
vop2_calc_display_rect_for_splice(struct display_state * state)5737ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state)
5738ee01dbb2SDamon Ding {
5739ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state;
5740ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state;
5741ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode;
5742ee01dbb2SDamon Ding struct display_rect *src_rect = &cstate->src_rect;
5743ee01dbb2SDamon Ding struct display_rect *dst_rect = &cstate->crtc_rect;
5744ee01dbb2SDamon Ding struct display_rect left_src, left_dst, right_src, right_dst;
5745ee01dbb2SDamon Ding u16 half_hdisplay = mode->crtc_hdisplay >> 1;
5746ee01dbb2SDamon Ding int left_src_w, left_dst_w, right_dst_w;
5747ee01dbb2SDamon Ding
5748ee01dbb2SDamon Ding left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x;
5749ee01dbb2SDamon Ding if (left_dst_w < 0)
5750ee01dbb2SDamon Ding left_dst_w = 0;
5751ee01dbb2SDamon Ding right_dst_w = dst_rect->w - left_dst_w;
5752ee01dbb2SDamon Ding
5753ee01dbb2SDamon Ding if (!right_dst_w)
5754ee01dbb2SDamon Ding left_src_w = src_rect->w;
5755ee01dbb2SDamon Ding else
57560df0fd39SSandy Huang left_src_w = src_rect->x + src_rect->w - src_rect->w / 2;
5757ee01dbb2SDamon Ding
5758ee01dbb2SDamon Ding left_src.x = src_rect->x;
5759ee01dbb2SDamon Ding left_src.w = left_src_w;
5760ee01dbb2SDamon Ding left_dst.x = dst_rect->x;
5761ee01dbb2SDamon Ding left_dst.w = left_dst_w;
5762ee01dbb2SDamon Ding right_src.x = left_src.x + left_src.w;
5763ee01dbb2SDamon Ding right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w;
5764ee01dbb2SDamon Ding right_dst.x = dst_rect->x + left_dst_w - half_hdisplay;
5765ee01dbb2SDamon Ding right_dst.w = right_dst_w;
5766ee01dbb2SDamon Ding
5767ee01dbb2SDamon Ding left_src.y = src_rect->y;
5768ee01dbb2SDamon Ding left_src.h = src_rect->h;
5769ee01dbb2SDamon Ding left_dst.y = dst_rect->y;
5770ee01dbb2SDamon Ding left_dst.h = dst_rect->h;
5771ee01dbb2SDamon Ding right_src.y = src_rect->y;
5772ee01dbb2SDamon Ding right_src.h = src_rect->h;
5773ee01dbb2SDamon Ding right_dst.y = dst_rect->y;
5774ee01dbb2SDamon Ding right_dst.h = dst_rect->h;
5775ee01dbb2SDamon Ding
5776ee01dbb2SDamon Ding memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect));
5777ee01dbb2SDamon Ding memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect));
5778ee01dbb2SDamon Ding memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect));
5779ee01dbb2SDamon Ding memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect));
5780ee01dbb2SDamon Ding }
5781ee01dbb2SDamon Ding
rockchip_vop2_set_plane(struct display_state * state)5782ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state)
5783ecc31b6eSAndy Yan {
5784ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state;
5785ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private;
5786ecc31b6eSAndy Yan struct vop2_win_data *win_data;
5787ee01dbb2SDamon Ding struct vop2_win_data *splice_win_data;
5788ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
57891c9572c7SDamon Ding int ret;
5790ecc31b6eSAndy Yan
5791ee01dbb2SDamon Ding if (cstate->crtc_rect.w > cstate->max_output.width) {
5792ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n",
5793ee01dbb2SDamon Ding cstate->crtc_rect.w, cstate->max_output.width);
5794ecc31b6eSAndy Yan return -EINVAL;
5795ecc31b6eSAndy Yan }
5796ecc31b6eSAndy Yan
5797ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
5798ecc31b6eSAndy Yan if (!win_data) {
5799ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id);
5800ecc31b6eSAndy Yan return -ENODEV;
5801ecc31b6eSAndy Yan }
5802ecc31b6eSAndy Yan
58035fa6e665SDamon Ding /* ignore some plane register according vop3 esmart lb mode */
58045fa6e665SDamon Ding if (vop3_ignore_plane(vop2, win_data))
58055fa6e665SDamon Ding return -EACCES;
58065fa6e665SDamon Ding
5807a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) {
5808b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, win_data->pd_id))
5809b6ba80b4SDamon Ding printf("open vp%d plane pd fail\n", cstate->crtc_id);
5810b6ba80b4SDamon Ding }
5811b6ba80b4SDamon Ding
5812ee01dbb2SDamon Ding if (cstate->splice_mode) {
5813ee01dbb2SDamon Ding if (win_data->splice_win_id) {
5814ee01dbb2SDamon Ding splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id);
5815ee01dbb2SDamon Ding splice_win_data->splice_mode_right = true;
5816b6ba80b4SDamon Ding
5817b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, splice_win_data->pd_id))
5818b6ba80b4SDamon Ding printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id);
5819b6ba80b4SDamon Ding
5820ee01dbb2SDamon Ding vop2_calc_display_rect_for_splice(state);
5821ee01dbb2SDamon Ding if (win_data->type == CLUSTER_LAYER)
5822ee01dbb2SDamon Ding vop2_set_cluster_win(state, splice_win_data);
5823ee01dbb2SDamon Ding else
5824ee01dbb2SDamon Ding vop2_set_smart_win(state, splice_win_data);
5825ee01dbb2SDamon Ding } else {
5826ee01dbb2SDamon Ding printf("ERROR: splice mode is unsupported by plane %s\n",
5827a7cb29b7SDamon Ding vop2_plane_phys_id_to_string(primary_plane_id));
5828ee01dbb2SDamon Ding return -EINVAL;
5829ee01dbb2SDamon Ding }
5830ee01dbb2SDamon Ding }
5831ee01dbb2SDamon Ding
5832ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER)
58331c9572c7SDamon Ding ret = vop2_set_cluster_win(state, win_data);
5834ecc31b6eSAndy Yan else
58351c9572c7SDamon Ding ret = vop2_set_smart_win(state, win_data);
58361c9572c7SDamon Ding if (ret)
58371c9572c7SDamon Ding return ret;
58388895aec1SSandy Huang
58398895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n",
5840a7cb29b7SDamon Ding cstate->crtc_id, vop2_plane_phys_id_to_string(primary_plane_id),
5841ee01dbb2SDamon Ding cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h,
5842ee01dbb2SDamon Ding cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format,
58438895aec1SSandy Huang cstate->dma_addr);
58448895aec1SSandy Huang
5845d0408543SAndy Yan return 0;
5846d0408543SAndy Yan }
5847d0408543SAndy Yan
rockchip_vop2_prepare(struct display_state * state)5848d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state)
5849d0408543SAndy Yan {
5850d0408543SAndy Yan return 0;
5851d0408543SAndy Yan }
5852d0408543SAndy Yan
vop2_dsc_cfg_done(struct display_state * state)585312ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state)
585412ee5af0SDamon Ding {
585512ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state;
585612ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state;
585712ee5af0SDamon Ding struct vop2 *vop2 = cstate->private;
585812ee5af0SDamon Ding u8 dsc_id = cstate->dsc_id;
585912ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30);
586012ee5af0SDamon Ding
586112ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
586212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK,
586312ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false);
586412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK,
586512ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false);
586612ee5af0SDamon Ding } else {
586712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK,
586812ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false);
586912ee5af0SDamon Ding }
587012ee5af0SDamon Ding }
587112ee5af0SDamon Ding
rockchip_vop2_enable(struct display_state * state)5872d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state)
5873d0408543SAndy Yan {
5874d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state;
5875d0408543SAndy Yan struct vop2 *vop2 = cstate->private;
587652ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100);
5877ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5878d0408543SAndy Yan
5879d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5880d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false);
5881ee01dbb2SDamon Ding
5882ee01dbb2SDamon Ding if (cstate->splice_mode)
5883ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5884ee01dbb2SDamon Ding
5885d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5886d0408543SAndy Yan
588712ee5af0SDamon Ding if (cstate->dsc_enable)
588812ee5af0SDamon Ding vop2_dsc_cfg_done(state);
588912ee5af0SDamon Ding
58900675a2a4SDamon Ding if (cstate->mcu_timing.mcu_pix_total)
58910675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK,
58920675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 0, false);
58930675a2a4SDamon Ding
5894d0408543SAndy Yan return 0;
5895d0408543SAndy Yan }
5896d0408543SAndy Yan
rk3588_vop2_post_enable(struct display_state * state)5897efa01fe4SZhang Yubing static int rk3588_vop2_post_enable(struct display_state *state)
5898efa01fe4SZhang Yubing {
5899efa01fe4SZhang Yubing struct connector_state *conn_state = &state->conn_state;
5900efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state;
5901efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private;
5902efa01fe4SZhang Yubing int output_if = conn_state->output_if;
5903efa01fe4SZhang Yubing u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5904efa01fe4SZhang Yubing int ret, val;
5905efa01fe4SZhang Yubing
5906efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP0)
5907efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT,
5908efa01fe4SZhang Yubing 1, false);
5909efa01fe4SZhang Yubing
5910efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP1)
5911efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT,
5912efa01fe4SZhang Yubing 1, false);
5913efa01fe4SZhang Yubing
5914efa01fe4SZhang Yubing if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) {
5915efa01fe4SZhang Yubing vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5916efa01fe4SZhang Yubing ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5917efa01fe4SZhang Yubing val & BIT(cstate->crtc_id), 50 * 1000);
5918efa01fe4SZhang Yubing if (ret)
5919efa01fe4SZhang Yubing printf("%s wait cfg done timeout\n", __func__);
59200686a6a6SZhang Yubing
59210686a6a6SZhang Yubing if (cstate->dclk_rst.dev) {
59220686a6a6SZhang Yubing reset_assert(&cstate->dclk_rst);
59230686a6a6SZhang Yubing udelay(20);
59240686a6a6SZhang Yubing reset_deassert(&cstate->dclk_rst);
59250686a6a6SZhang Yubing }
5926efa01fe4SZhang Yubing }
5927efa01fe4SZhang Yubing
5928efa01fe4SZhang Yubing return 0;
5929efa01fe4SZhang Yubing }
5930efa01fe4SZhang Yubing
rk3576_vop2_post_enable(struct display_state * state)5931efa01fe4SZhang Yubing static int rk3576_vop2_post_enable(struct display_state *state)
5932efa01fe4SZhang Yubing {
5933efa01fe4SZhang Yubing struct connector_state *conn_state = &state->conn_state;
5934efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state;
5935efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private;
5936efa01fe4SZhang Yubing int output_if = conn_state->output_if;
5937efa01fe4SZhang Yubing u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5938efa01fe4SZhang Yubing int ret, val;
5939efa01fe4SZhang Yubing
5940efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP0)
5941efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK,
5942efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false);
5943efa01fe4SZhang Yubing
5944efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP1)
5945efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK,
5946efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false);
5947efa01fe4SZhang Yubing
5948efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP2)
5949efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK,
5950efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false);
5951efa01fe4SZhang Yubing
5952efa01fe4SZhang Yubing if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
5953efa01fe4SZhang Yubing vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5954efa01fe4SZhang Yubing ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val,
5955efa01fe4SZhang Yubing val & BIT(cstate->crtc_id), 50 * 1000);
5956efa01fe4SZhang Yubing if (ret)
5957efa01fe4SZhang Yubing printf("%s wait cfg done timeout\n", __func__);
59580686a6a6SZhang Yubing
59590686a6a6SZhang Yubing if (cstate->dclk_rst.dev) {
59600686a6a6SZhang Yubing reset_assert(&cstate->dclk_rst);
59610686a6a6SZhang Yubing udelay(20);
59620686a6a6SZhang Yubing reset_deassert(&cstate->dclk_rst);
59630686a6a6SZhang Yubing }
5964efa01fe4SZhang Yubing }
5965efa01fe4SZhang Yubing
5966efa01fe4SZhang Yubing return 0;
5967efa01fe4SZhang Yubing }
5968efa01fe4SZhang Yubing
rockchip_vop2_post_enable(struct display_state * state)5969efa01fe4SZhang Yubing static int rockchip_vop2_post_enable(struct display_state *state)
5970efa01fe4SZhang Yubing {
5971efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state;
5972efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private;
5973efa01fe4SZhang Yubing
5974efa01fe4SZhang Yubing if (vop2->version == VOP_VERSION_RK3588)
5975efa01fe4SZhang Yubing rk3588_vop2_post_enable(state);
5976efa01fe4SZhang Yubing else if (vop2->version == VOP_VERSION_RK3576)
5977efa01fe4SZhang Yubing rk3576_vop2_post_enable(state);
5978efa01fe4SZhang Yubing
5979efa01fe4SZhang Yubing return 0;
5980efa01fe4SZhang Yubing }
5981efa01fe4SZhang Yubing
rockchip_vop2_disable(struct display_state * state)5982d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state)
5983d0408543SAndy Yan {
5984d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state;
5985d0408543SAndy Yan struct vop2 *vop2 = cstate->private;
598652ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100);
5987ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16);
5988d0408543SAndy Yan
5989d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK,
5990d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false);
5991ee01dbb2SDamon Ding
5992ee01dbb2SDamon Ding if (cstate->splice_mode)
5993ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16);
5994ee01dbb2SDamon Ding
5995d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done);
5996d0408543SAndy Yan
5997d0408543SAndy Yan return 0;
5998d0408543SAndy Yan }
5999d0408543SAndy Yan
rockchip_vop2_fixup_dts(struct display_state * state,void * blob)6000b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob)
6001b0989546SSandy Huang {
6002b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state;
6003b0989546SSandy Huang struct vop2 *vop2 = cstate->private;
6004b0989546SSandy Huang ofnode vp_node;
6005b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node;
6006b0989546SSandy Huang static bool vop_fix_dts;
6007b0989546SSandy Huang const char *path;
6008b0989546SSandy Huang u32 plane_mask = 0;
6009b0989546SSandy Huang int vp_id = 0;
6010b0989546SSandy Huang
60116fea745cSDamon Ding /*
60126fea745cSDamon Ding * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in
60136fea745cSDamon Ding * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched
60146fea745cSDamon Ding * between different CRTCs flexibly and the userspace do not need
60156fea745cSDamon Ding * the plane_mask to restrict the binding between the crtc and plane.
60166fea745cSDamon Ding * We just find a expected plane for logo display.
60176fea745cSDamon Ding */
60186fea745cSDamon Ding if (vop_fix_dts || is_vop3(vop2))
6019b0989546SSandy Huang return 0;
6020b0989546SSandy Huang
6021b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
6022b0989546SSandy Huang path = vp_node.np->full_name;
6023b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask;
6024b0989546SSandy Huang
60258b1fe597SSandy Huang if (cstate->crtc->assign_plane)
60268b1fe597SSandy Huang continue;
6027b4fa21deSDamon Ding
6028ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n",
6029b0989546SSandy Huang vp_id, plane_mask,
6030ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id,
6031b4fa21deSDamon Ding vop2->vp_plane_mask[vp_id].cursor_plane_id);
6032b0989546SSandy Huang
6033b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask",
6034b0989546SSandy Huang plane_mask, 1);
6035b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane",
6036b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1);
6037b4fa21deSDamon Ding if (vop2->vp_plane_mask[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID)
6038ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id",
6039b4fa21deSDamon Ding vop2->vp_plane_mask[vp_id].cursor_plane_id, 1);
6040b0989546SSandy Huang vp_id++;
6041b0989546SSandy Huang }
6042b0989546SSandy Huang
6043b0989546SSandy Huang vop_fix_dts = true;
6044b0989546SSandy Huang
6045b0989546SSandy Huang return 0;
6046b0989546SSandy Huang }
6047b0989546SSandy Huang
rockchip_vop2_check(struct display_state * state)6048820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state)
6049820a5c17SDamon Ding {
6050820a5c17SDamon Ding struct crtc_state *cstate = &state->crtc_state;
6051820a5c17SDamon Ding struct rockchip_crtc *crtc = cstate->crtc;
6052820a5c17SDamon Ding
6053820a5c17SDamon Ding if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) {
6054820a5c17SDamon Ding printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id);
6055820a5c17SDamon Ding return -ENOTSUPP;
6056820a5c17SDamon Ding }
6057820a5c17SDamon Ding
6058820a5c17SDamon Ding if (cstate->splice_mode) {
6059820a5c17SDamon Ding crtc->splice_mode = true;
6060820a5c17SDamon Ding crtc->splice_crtc_id = cstate->splice_crtc_id;
6061820a5c17SDamon Ding }
6062820a5c17SDamon Ding
6063820a5c17SDamon Ding return 0;
6064820a5c17SDamon Ding }
6065820a5c17SDamon Ding
rockchip_vop2_mode_valid(struct display_state * state)606622007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state)
606722007755SDamon Ding {
606822007755SDamon Ding struct connector_state *conn_state = &state->conn_state;
606922007755SDamon Ding struct crtc_state *cstate = &state->crtc_state;
607022007755SDamon Ding struct drm_display_mode *mode = &conn_state->mode;
607122007755SDamon Ding struct videomode vm;
607222007755SDamon Ding
607322007755SDamon Ding drm_display_mode_to_videomode(mode, &vm);
607422007755SDamon Ding
607522007755SDamon Ding if (vm.hactive < 32 || vm.vactive < 32 ||
607622007755SDamon Ding (vm.hfront_porch * vm.hsync_len * vm.hback_porch *
607722007755SDamon Ding vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) {
607822007755SDamon Ding printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id);
607922007755SDamon Ding return -EINVAL;
608022007755SDamon Ding }
608122007755SDamon Ding
608222007755SDamon Ding return 0;
608322007755SDamon Ding }
608422007755SDamon Ding
rockchip_vop2_mode_fixup(struct display_state * state)6085b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state)
6086b02eb70bSDamon Ding {
6087b02eb70bSDamon Ding struct connector_state *conn_state = &state->conn_state;
60880e19fecdSDamon Ding struct rockchip_connector *conn = conn_state->connector;
6089b02eb70bSDamon Ding struct drm_display_mode *mode = &conn_state->mode;
6090b02eb70bSDamon Ding struct crtc_state *cstate = &state->crtc_state;
6091b02eb70bSDamon Ding struct vop2 *vop2 = cstate->private;
6092b02eb70bSDamon Ding
60930e19fecdSDamon Ding if (conn_state->secondary) {
60940e19fecdSDamon Ding if (!(conn->dual_channel_mode &&
60950e19fecdSDamon Ding conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) &&
60962b992d78SDamon Ding conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS)
60972b992d78SDamon Ding drm_mode_convert_to_split_mode(mode);
60980e19fecdSDamon Ding }
60992b992d78SDamon Ding
61001b5811e7SDamon Ding drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
6101b02eb70bSDamon Ding
6102243f0077SDamon Ding /*
6103640211a0SDamon Ding * For RK3568 and RK3588, the hactive of video timing must
6104640211a0SDamon Ding * be 4-pixel aligned.
6105640211a0SDamon Ding */
6106640211a0SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) {
6107640211a0SDamon Ding if (mode->crtc_hdisplay % 4) {
6108640211a0SDamon Ding int old_hdisplay = mode->crtc_hdisplay;
6109640211a0SDamon Ding int align = 4 - (mode->crtc_hdisplay % 4);
6110640211a0SDamon Ding
6111640211a0SDamon Ding mode->crtc_hdisplay += align;
6112640211a0SDamon Ding mode->crtc_hsync_start += align;
6113640211a0SDamon Ding mode->crtc_hsync_end += align;
6114640211a0SDamon Ding mode->crtc_htotal += align;
6115640211a0SDamon Ding
6116640211a0SDamon Ding printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n",
6117640211a0SDamon Ding old_hdisplay, mode->hdisplay);
6118640211a0SDamon Ding }
6119640211a0SDamon Ding }
6120640211a0SDamon Ding
61214a9e4766SAlgea Cao /*
61224a9e4766SAlgea Cao * When the dsc bpp is less than 9, hdmi output will flash on TV.
61234a9e4766SAlgea Cao * It is speculated that the reason is that pixel rate of sink
61244a9e4766SAlgea Cao * decoding is not enough.
61254a9e4766SAlgea Cao * Taking 8bpp as an example, dsc clk needs to be 1/3 of the input
61264a9e4766SAlgea Cao * clk. the theoretical calculation of DEN compression 1/3, at this
61274a9e4766SAlgea Cao * time, the clk of vop dsc to hdmi tx can be reduced to about 260M
61284a9e4766SAlgea Cao * to meet the 8bpp transmission.
61294a9e4766SAlgea Cao * RK3588 dsc clk only supports 1/2 frequency division, so dsc clk
61304a9e4766SAlgea Cao * is 1/2 input clk, which needs to increase blank, which is
61314a9e4766SAlgea Cao * equivalent to compressing the absolute DEN time. TV is likely to
61324a9e4766SAlgea Cao * decode at a decoding rate of around 260M. DEN absolute time
61334a9e4766SAlgea Cao * shortening results in abnormal TV decoding.
61344a9e4766SAlgea Cao * So the value of hblank needs to be reduced when bpp is below 9.
61354a9e4766SAlgea Cao * The measurement can be displayed normally on TV, but reducing
61364a9e4766SAlgea Cao * the hblank will result in non-standard timing of the hdmi output.
61374a9e4766SAlgea Cao * This may cause compatibility issues and hdmi cts certification
61384a9e4766SAlgea Cao * may fail.
61394a9e4766SAlgea Cao */
61404a9e4766SAlgea Cao if (vop2->version == VOP_VERSION_RK3588) {
61414a9e4766SAlgea Cao if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) {
61424a9e4766SAlgea Cao if (cstate->dsc_sink_cap.target_bits_per_pixel_x16 < 0x90 &&
61434a9e4766SAlgea Cao cstate->dsc_enable) {
61444a9e4766SAlgea Cao u8 vrefresh = drm_mode_vrefresh(mode);
61454a9e4766SAlgea Cao
61464a9e4766SAlgea Cao mode->crtc_hsync_start = mode->hdisplay + 10;
61474a9e4766SAlgea Cao mode->crtc_hsync_end = mode->crtc_hsync_start + 10;
61484a9e4766SAlgea Cao mode->crtc_htotal = mode->crtc_hsync_end + 10;
61494a9e4766SAlgea Cao mode->crtc_clock = (u32)mode->crtc_htotal * mode->crtc_vtotal *
61504a9e4766SAlgea Cao vrefresh / 1000;
61514a9e4766SAlgea Cao }
61524a9e4766SAlgea Cao }
61534a9e4766SAlgea Cao }
61544a9e4766SAlgea Cao
615521198dbdSZhang Yubing if (vop2->version == VOP_VERSION_RK3576) {
6156640211a0SDamon Ding /*
6157243f0077SDamon Ding * For RK3576 YUV420 output, hden signal introduce one cycle delay,
6158243f0077SDamon Ding * so we need to adjust hfp and hbp to compatible with this design.
6159243f0077SDamon Ding */
616021198dbdSZhang Yubing if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
6161243f0077SDamon Ding mode->crtc_hsync_start += 2;
6162243f0077SDamon Ding mode->crtc_hsync_end += 2;
6163243f0077SDamon Ding }
616421198dbdSZhang Yubing /*
616521198dbdSZhang Yubing * For RK3576 DP output, vp send 2 pixels 1 cycle. So the hactive,
616621198dbdSZhang Yubing * hfp, hsync, hbp should be 2-pixel aligned.
616721198dbdSZhang Yubing */
616821198dbdSZhang Yubing if (conn_state->output_if &
616921198dbdSZhang Yubing (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) {
617021198dbdSZhang Yubing mode->crtc_hdisplay += mode->crtc_hdisplay % 2;
617121198dbdSZhang Yubing mode->crtc_hsync_start += mode->crtc_hsync_start % 2;
617221198dbdSZhang Yubing mode->crtc_hsync_end += mode->crtc_hsync_end % 2;
617321198dbdSZhang Yubing mode->crtc_htotal += mode->crtc_htotal % 2;
617421198dbdSZhang Yubing }
617521198dbdSZhang Yubing }
6176243f0077SDamon Ding
6177b02eb70bSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656)
6178b02eb70bSDamon Ding mode->crtc_clock *= 2;
6179b02eb70bSDamon Ding
6180b02eb70bSDamon Ding /*
6181b02eb70bSDamon Ding * For RK3528, the path of CVBS output is like:
6182b02eb70bSDamon Ding * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC
6183b02eb70bSDamon Ding * The vop2 dclk should be four times crtc_clock for CVBS sampling
6184b02eb70bSDamon Ding * clock needs.
6185b02eb70bSDamon Ding */
6186b02eb70bSDamon Ding if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656)
6187b02eb70bSDamon Ding mode->crtc_clock *= 4;
6188b02eb70bSDamon Ding
61894d64cedbSDamon Ding mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format);
61904d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total)
61914d64cedbSDamon Ding mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1;
61920675a2a4SDamon Ding
6193b02eb70bSDamon Ding return 0;
6194b02eb70bSDamon Ding }
6195b02eb70bSDamon Ding
61964c765862SDamon Ding #define FRAC_16_16(mult, div) (((mult) << 16) / (div))
61974c765862SDamon Ding
rockchip_vop2_plane_check(struct display_state * state)61984c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state)
61994c765862SDamon Ding {
62004c765862SDamon Ding struct crtc_state *cstate = &state->crtc_state;
62014c765862SDamon Ding struct vop2 *vop2 = cstate->private;
62024c765862SDamon Ding struct display_rect *src = &cstate->src_rect;
62034c765862SDamon Ding struct display_rect *dst = &cstate->crtc_rect;
62044c765862SDamon Ding struct vop2_win_data *win_data;
62054c765862SDamon Ding int min_scale, max_scale;
62064c765862SDamon Ding int hscale, vscale;
62074c765862SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id;
62084c765862SDamon Ding
62094c765862SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id);
62104c765862SDamon Ding if (!win_data) {
62114c765862SDamon Ding printf("ERROR: invalid win id %d\n", primary_plane_id);
62124c765862SDamon Ding return -ENODEV;
62134c765862SDamon Ding }
62144c765862SDamon Ding
62154c765862SDamon Ding min_scale = FRAC_16_16(1, win_data->max_downscale_factor);
62164c765862SDamon Ding max_scale = FRAC_16_16(win_data->max_upscale_factor, 1);
62174c765862SDamon Ding
62184c765862SDamon Ding hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale);
62194c765862SDamon Ding vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale);
62204c765862SDamon Ding if (hscale < 0 || vscale < 0) {
62214c765862SDamon Ding printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name);
62224c765862SDamon Ding return -ERANGE;
62234c765862SDamon Ding }
62244c765862SDamon Ding
62254c765862SDamon Ding return 0;
62264c765862SDamon Ding }
6227337d1c13SDamon Ding
rockchip_vop2_apply_soft_te(struct display_state * state)62288e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state)
62298e7ef808SDamon Ding {
6230d8e7f4a5SSandy Huang __maybe_unused struct connector_state *conn_state = &state->conn_state;
62318e7ef808SDamon Ding struct crtc_state *cstate = &state->crtc_state;
62328e7ef808SDamon Ding struct vop2 *vop2 = cstate->private;
62338e7ef808SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100);
62348e7ef808SDamon Ding int val = 0;
62358e7ef808SDamon Ding int ret = 0;
62368e7ef808SDamon Ding
62378e7ef808SDamon Ding ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val,
62388e7ef808SDamon Ding (val >> EDPI_WMS_FS) & 0x1, 50 * 1000);
62398e7ef808SDamon Ding if (!ret) {
6240d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD
62418e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
62428e7ef808SDamon Ding !val, 50 * 1000);
62438e7ef808SDamon Ding if (!ret) {
62448e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val,
62458e7ef808SDamon Ding val, 50 * 1000);
62468e7ef808SDamon Ding if (!ret) {
62478e7ef808SDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset,
62488e7ef808SDamon Ding EN_MASK, EDPI_WMS_FS, 1, false);
62498e7ef808SDamon Ding } else {
62508e7ef808SDamon Ding printf("ERROR: vp%d wait for active TE signal timeout\n",
62518e7ef808SDamon Ding cstate->crtc_id);
62528e7ef808SDamon Ding return ret;
62538e7ef808SDamon Ding }
62548e7ef808SDamon Ding } else {
62558e7ef808SDamon Ding printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id);
62568e7ef808SDamon Ding return ret;
62578e7ef808SDamon Ding }
6258d8e7f4a5SSandy Huang #endif
62598e7ef808SDamon Ding } else {
62608e7ef808SDamon Ding printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id);
62618e7ef808SDamon Ding return ret;
62628e7ef808SDamon Ding }
62638e7ef808SDamon Ding
62648e7ef808SDamon Ding return 0;
62658e7ef808SDamon Ding }
62668e7ef808SDamon Ding
rockchip_vop2_regs_dump(struct display_state * state)626772388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state)
626872388c26SDamon Ding {
626972388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state;
627072388c26SDamon Ding struct vop2 *vop2 = cstate->private;
627172388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data;
627272388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs;
6273a552a69cSDamon Ding u32 len = 128;
627472388c26SDamon Ding u32 n, i, j;
627572388c26SDamon Ding u32 base;
627672388c26SDamon Ding
627772388c26SDamon Ding if (!cstate->crtc->active)
627872388c26SDamon Ding return -EINVAL;
627972388c26SDamon Ding
628072388c26SDamon Ding n = vop2_data->dump_regs_size;
628172388c26SDamon Ding for (i = 0; i < n; i++) {
628272388c26SDamon Ding base = regs[i].offset;
6283a552a69cSDamon Ding len = 128;
6284a552a69cSDamon Ding if (regs[i].size)
6285a552a69cSDamon Ding len = min(len, regs[i].size >> 2);
628672388c26SDamon Ding printf("\n%s:\n", regs[i].name);
6287a552a69cSDamon Ding for (j = 0; j < len;) {
628872388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
628972388c26SDamon Ding vop2_readl(vop2, base + (4 * j)),
629072388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))),
629172388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))),
629272388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3))));
629372388c26SDamon Ding j += 4;
629472388c26SDamon Ding }
629572388c26SDamon Ding }
629672388c26SDamon Ding
629772388c26SDamon Ding return 0;
629872388c26SDamon Ding }
629972388c26SDamon Ding
rockchip_vop2_active_regs_dump(struct display_state * state)630072388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state)
630172388c26SDamon Ding {
630272388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state;
630372388c26SDamon Ding struct vop2 *vop2 = cstate->private;
630472388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data;
630572388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs;
6306a552a69cSDamon Ding u32 len = 128;
630772388c26SDamon Ding u32 n, i, j;
630872388c26SDamon Ding u32 base;
630972388c26SDamon Ding bool enable_state;
631072388c26SDamon Ding
631172388c26SDamon Ding if (!cstate->crtc->active)
631272388c26SDamon Ding return -EINVAL;
631372388c26SDamon Ding
631472388c26SDamon Ding n = vop2_data->dump_regs_size;
631572388c26SDamon Ding for (i = 0; i < n; i++) {
631672388c26SDamon Ding if (regs[i].state_mask) {
631772388c26SDamon Ding enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) &
631872388c26SDamon Ding regs[i].state_mask;
631972388c26SDamon Ding if (enable_state != regs[i].enable_state)
632072388c26SDamon Ding continue;
632172388c26SDamon Ding }
632272388c26SDamon Ding
632372388c26SDamon Ding base = regs[i].offset;
6324a552a69cSDamon Ding len = 128;
6325a552a69cSDamon Ding if (regs[i].size)
6326a552a69cSDamon Ding len = min(len, regs[i].size >> 2);
632772388c26SDamon Ding printf("\n%s:\n", regs[i].name);
6328a552a69cSDamon Ding for (j = 0; j < len;) {
632972388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4,
633072388c26SDamon Ding vop2_readl(vop2, base + (4 * j)),
633172388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))),
633272388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))),
633372388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3))));
633472388c26SDamon Ding j += 4;
633572388c26SDamon Ding }
633672388c26SDamon Ding }
633772388c26SDamon Ding
633872388c26SDamon Ding return 0;
633972388c26SDamon Ding }
634072388c26SDamon Ding
rk3528_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6341b888dbc8SSandy Huang static void rk3528_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
63429c7848c3SDamon Ding {
63439c7848c3SDamon Ding struct crtc_state *cstate = &state->crtc_state;
63449c7848c3SDamon Ding struct vop2 *vop2 = cstate->private;
63459c7848c3SDamon Ding uint32_t dly = 0; /* For vop3, the default window delay is 0 */
63469c7848c3SDamon Ding
6347b888dbc8SSandy Huang switch (plane_phy_id) {
63489c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER0:
63499c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_CLUSTER0_CTRL, CLUSTER_DLY_NUM_MASK,
63509c7848c3SDamon Ding CLUSTER_DLY_NUM_SHIFT, dly, false);
63519c7848c3SDamon Ding break;
63529c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART0:
63539c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL, ESMART_DLY_NUM_MASK,
63549c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
63559c7848c3SDamon Ding break;
63569c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART1:
63579c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART1_CTRL, ESMART_DLY_NUM_MASK,
63589c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
63599c7848c3SDamon Ding break;
63609c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART2:
63619c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART2_CTRL, ESMART_DLY_NUM_MASK,
63629c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
63639c7848c3SDamon Ding break;
63649c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART3:
63659c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART3_CTRL, ESMART_DLY_NUM_MASK,
63669c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
63679c7848c3SDamon Ding break;
63689c7848c3SDamon Ding }
63699c7848c3SDamon Ding }
63709c7848c3SDamon Ding
rk3528_setup_overlay(struct display_state * state)6371b7195f56SDamon Ding static void rk3528_setup_overlay(struct display_state *state)
6372b7195f56SDamon Ding {
6373b7195f56SDamon Ding struct crtc_state *cstate = &state->crtc_state;
6374b7195f56SDamon Ding struct vop2 *vop2 = cstate->private;
6375b7195f56SDamon Ding struct vop2_win_data *win_data;
6376b7195f56SDamon Ding int i;
6377b7195f56SDamon Ding u32 offset = 0;
6378b7195f56SDamon Ding u8 shift = 0;
6379b7195f56SDamon Ding
6380b7195f56SDamon Ding /* init the layer sel value to 0xff(Disable layer) */
6381b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
6382b7195f56SDamon Ding offset = 0x100 * i;
6383b7195f56SDamon Ding vop2_writel(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 0xffffffff);
6384b7195f56SDamon Ding }
6385b7195f56SDamon Ding
6386b7195f56SDamon Ding /* layer sel win id */
6387b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
6388b7195f56SDamon Ding if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6389b7195f56SDamon Ding offset = 0x100 * i;
6390b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6391b7195f56SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset,
6392b7195f56SDamon Ding LAYER_SEL_MASK, 0, win_data->layer_sel_win_id[i], false);
6393b7195f56SDamon Ding }
6394b7195f56SDamon Ding }
6395b7195f56SDamon Ding
6396b7195f56SDamon Ding /* win sel port */
6397b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
6398b7195f56SDamon Ding if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6399b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6400b7195f56SDamon Ding shift = win_data->win_sel_port_offset * 2;
6401b7195f56SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL,
6402b7195f56SDamon Ding LAYER_SEL_PORT_MASK, shift, i, false);
6403b7195f56SDamon Ding }
6404b7195f56SDamon Ding }
6405b7195f56SDamon Ding }
6406b7195f56SDamon Ding
rk3568_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6407b888dbc8SSandy Huang static void rk3568_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
64089c7848c3SDamon Ding {
64099c7848c3SDamon Ding struct crtc_state *cstate = &state->crtc_state;
64109c7848c3SDamon Ding struct vop2 *vop2 = cstate->private;
64119c7848c3SDamon Ding struct vop2_win_data *win_data;
64129c7848c3SDamon Ding uint32_t dly;
64139c7848c3SDamon Ding
6414b888dbc8SSandy Huang win_data = vop2_find_win_by_phys_id(vop2, plane_phy_id);
64159c7848c3SDamon Ding dly = win_data->dly[VOP2_DLY_MODE_DEFAULT];
64169c7848c3SDamon Ding if (win_data->type == CLUSTER_LAYER)
64179c7848c3SDamon Ding dly |= dly << 8;
64189c7848c3SDamon Ding
6419b888dbc8SSandy Huang switch (plane_phy_id) {
64209c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER0:
64219c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
64229c7848c3SDamon Ding CLUSTER0_DLY_NUM_SHIFT, dly, false);
64239c7848c3SDamon Ding break;
64249c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER1:
64259c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK,
64269c7848c3SDamon Ding CLUSTER1_DLY_NUM_SHIFT, dly, false);
64279c7848c3SDamon Ding break;
64289c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER2:
64299c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
64309c7848c3SDamon Ding CLUSTER0_DLY_NUM_SHIFT, dly, false);
64319c7848c3SDamon Ding break;
64329c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER3:
64339c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK,
64349c7848c3SDamon Ding CLUSTER1_DLY_NUM_SHIFT, dly, false);
64359c7848c3SDamon Ding break;
64369c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART0:
64379c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64389c7848c3SDamon Ding ESMART0_DLY_NUM_SHIFT, dly, false);
64399c7848c3SDamon Ding break;
64409c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART1:
64419c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64429c7848c3SDamon Ding ESMART1_DLY_NUM_SHIFT, dly, false);
64439c7848c3SDamon Ding break;
64449c7848c3SDamon Ding case ROCKCHIP_VOP2_SMART0:
64459c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART2:
64469c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64479c7848c3SDamon Ding SMART0_DLY_NUM_SHIFT, dly, false);
64489c7848c3SDamon Ding break;
64499c7848c3SDamon Ding case ROCKCHIP_VOP2_SMART1:
64509c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART3:
64519c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK,
64529c7848c3SDamon Ding SMART1_DLY_NUM_SHIFT, dly, false);
64539c7848c3SDamon Ding break;
64549c7848c3SDamon Ding }
64559c7848c3SDamon Ding }
64569c7848c3SDamon Ding
rk3568_setup_overlay(struct display_state * state)6457b7195f56SDamon Ding static void rk3568_setup_overlay(struct display_state *state)
6458b7195f56SDamon Ding {
6459b7195f56SDamon Ding struct crtc_state *cstate = &state->crtc_state;
6460b7195f56SDamon Ding struct vop2 *vop2 = cstate->private;
6461b7195f56SDamon Ding struct vop2_win_data *win_data;
6462b7195f56SDamon Ding int layer_phy_id = 0;
6463b7195f56SDamon Ding int total_used_layer = 0;
6464b7195f56SDamon Ding int port_mux = 0;
6465b7195f56SDamon Ding int i, j;
6466b7195f56SDamon Ding u32 layer_nr = 0;
6467b7195f56SDamon Ding u8 shift = 0;
6468b7195f56SDamon Ding
6469b7195f56SDamon Ding /* layer sel win id */
6470b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
6471b7195f56SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6472b7195f56SDamon Ding for (j = 0; j < layer_nr; j++) {
6473b7195f56SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6474b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6475b7195f56SDamon Ding vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK,
6476b7195f56SDamon Ding shift, win_data->layer_sel_win_id[i], false);
6477b7195f56SDamon Ding shift += 4;
6478b7195f56SDamon Ding }
6479b7195f56SDamon Ding }
6480b7195f56SDamon Ding
6481b7195f56SDamon Ding /* win sel port */
6482b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
6483b7195f56SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr;
6484b7195f56SDamon Ding for (j = 0; j < layer_nr; j++) {
6485b7195f56SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j])
6486b7195f56SDamon Ding continue;
6487b7195f56SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j];
6488b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id);
6489b7195f56SDamon Ding shift = win_data->win_sel_port_offset * 2;
6490b7195f56SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK,
6491b7195f56SDamon Ding LAYER_SEL_PORT_SHIFT + shift, i, false);
6492b7195f56SDamon Ding }
6493b7195f56SDamon Ding }
6494b7195f56SDamon Ding
6495b7195f56SDamon Ding /**
6496b7195f56SDamon Ding * port mux config
6497b7195f56SDamon Ding */
6498b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
6499b7195f56SDamon Ding shift = i * 4;
6500b7195f56SDamon Ding if (vop2->vp_plane_mask[i].attached_layers_nr) {
6501b7195f56SDamon Ding total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr;
6502b7195f56SDamon Ding port_mux = total_used_layer - 1;
6503b7195f56SDamon Ding } else {
6504b7195f56SDamon Ding port_mux = 8;
6505b7195f56SDamon Ding }
6506b7195f56SDamon Ding
6507b7195f56SDamon Ding if (i == vop2->data->nr_vps - 1)
6508b7195f56SDamon Ding port_mux = vop2->data->nr_mixers;
6509b7195f56SDamon Ding
6510b7195f56SDamon Ding cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1;
6511b7195f56SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK,
6512b7195f56SDamon Ding PORT_MUX_SHIFT + shift, port_mux, false);
6513b7195f56SDamon Ding }
6514b7195f56SDamon Ding }
6515b7195f56SDamon Ding
rk3576_setup_win_dly(struct display_state * state,int crtc_id,u8 plane_phy_id)6516b888dbc8SSandy Huang static void rk3576_setup_win_dly(struct display_state *state, int crtc_id, u8 plane_phy_id)
65179c7848c3SDamon Ding {
65189c7848c3SDamon Ding struct crtc_state *cstate = &state->crtc_state;
65199c7848c3SDamon Ding struct vop2 *vop2 = cstate->private;
65209c7848c3SDamon Ding uint32_t dly = 0; /* For vop3, the default window delay is 0 */
65219c7848c3SDamon Ding
6522b888dbc8SSandy Huang switch (plane_phy_id) {
65239c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER0:
65249c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_DLY_NUM, CLUSTER_DLY_NUM_MASK,
65259c7848c3SDamon Ding CLUSTER_DLY_NUM_SHIFT, dly, false);
65269c7848c3SDamon Ding break;
65279c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER1:
65289c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER1_DLY_NUM, CLUSTER_DLY_NUM_MASK,
65299c7848c3SDamon Ding CLUSTER_DLY_NUM_SHIFT, dly, false);
65309c7848c3SDamon Ding break;
65319c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART0:
65329c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM, ESMART_DLY_NUM_MASK,
65339c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
65349c7848c3SDamon Ding break;
65359c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART1:
65369c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART1_DLY_NUM, ESMART_DLY_NUM_MASK,
65379c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
65389c7848c3SDamon Ding break;
65399c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART2:
65409c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART2_DLY_NUM, ESMART_DLY_NUM_MASK,
65419c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
65429c7848c3SDamon Ding break;
65439c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART3:
65449c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART3_DLY_NUM, ESMART_DLY_NUM_MASK,
65459c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false);
65469c7848c3SDamon Ding break;
65479c7848c3SDamon Ding }
65489c7848c3SDamon Ding }
65499c7848c3SDamon Ding
rk3576_setup_overlay(struct display_state * state)6550b7195f56SDamon Ding static void rk3576_setup_overlay(struct display_state *state)
6551b7195f56SDamon Ding {
6552b7195f56SDamon Ding struct crtc_state *cstate = &state->crtc_state;
6553b7195f56SDamon Ding struct vop2 *vop2 = cstate->private;
6554b7195f56SDamon Ding struct vop2_win_data *win_data;
6555b7195f56SDamon Ding int i;
6556b7195f56SDamon Ding u32 offset = 0;
6557b7195f56SDamon Ding
6558b7195f56SDamon Ding /* layer sel win id */
6559b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) {
6560b7195f56SDamon Ding if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) {
6561b7195f56SDamon Ding offset = 0x100 * i;
6562b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id);
6563b7195f56SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, LAYER_SEL_MASK,
6564b7195f56SDamon Ding 0, win_data->layer_sel_win_id[i], false);
6565b7195f56SDamon Ding }
6566b7195f56SDamon Ding }
6567b7195f56SDamon Ding }
6568b7195f56SDamon Ding
6569*60e6e79dSSandy Huang #ifdef CONFIG_MOS_SECONDARY
vop2_cluster_disable(void * regs,u32 offset)6570*60e6e79dSSandy Huang static void vop2_cluster_disable(void *regs, u32 offset)
6571*60e6e79dSSandy Huang {
6572*60e6e79dSSandy Huang writel(0x0, regs + RK3568_CLUSTER0_WIN0_CTRL0 + offset);
6573*60e6e79dSSandy Huang writel(0x0, regs + RK3568_CLUSTER0_WIN1_CTRL0 + offset);
6574*60e6e79dSSandy Huang writel(0x0, regs + RK3568_CLUSTER0_CTRL + offset);
6575*60e6e79dSSandy Huang }
6576*60e6e79dSSandy Huang
vop2_esmart_disable(void * regs,u32 offset)6577*60e6e79dSSandy Huang static void vop2_esmart_disable(void *regs, u32 offset)
6578*60e6e79dSSandy Huang {
6579*60e6e79dSSandy Huang writel(0x0, regs + RK3568_ESMART0_REGION0_CTRL + offset);
6580*60e6e79dSSandy Huang writel(0x0, regs + RK3568_ESMART0_REGION1_CTRL + offset);
6581*60e6e79dSSandy Huang writel(0x0, regs + RK3568_ESMART0_REGION2_CTRL + offset);
6582*60e6e79dSSandy Huang writel(0x0, regs + RK3568_ESMART0_REGION3_CTRL + offset);
6583*60e6e79dSSandy Huang }
6584*60e6e79dSSandy Huang
vop2_vp_irqs_disable(void * regs,u32 vp_id)6585*60e6e79dSSandy Huang static void vop2_vp_irqs_disable(void *regs, u32 vp_id)
6586*60e6e79dSSandy Huang {
6587*60e6e79dSSandy Huang u32 offset = 0x10 * vp_id;
6588*60e6e79dSSandy Huang
6589*60e6e79dSSandy Huang writel(0xffff0000, regs + RK3568_VP0_INT_EN + offset);
6590*60e6e79dSSandy Huang writel(0xffffffff, regs + RK3568_VP0_INT_CLR + offset);
6591*60e6e79dSSandy Huang }
6592*60e6e79dSSandy Huang
vop2_axi_irqs_disable(void * regs,u32 axi_id)6593*60e6e79dSSandy Huang static void vop2_axi_irqs_disable(void *regs, u32 axi_id)
6594*60e6e79dSSandy Huang {
6595*60e6e79dSSandy Huang u32 offset = 0x10 * axi_id;
6596*60e6e79dSSandy Huang
6597*60e6e79dSSandy Huang writel(0xffff0000, regs + RK3568_VP0_INT_EN + offset);
6598*60e6e79dSSandy Huang writel(0xffffffff, regs + RK3568_VP0_INT_CLR + offset);
6599*60e6e79dSSandy Huang }
6600*60e6e79dSSandy Huang
vop2_vp_in_standby(void * regs,u32 vp_id)6601*60e6e79dSSandy Huang static bool vop2_vp_in_standby(void *regs, u32 vp_id)
6602*60e6e79dSSandy Huang {
6603*60e6e79dSSandy Huang u32 offset = vp_id * 0x100;
6604*60e6e79dSSandy Huang
6605*60e6e79dSSandy Huang return !!(readl(regs + RK3568_VP0_DSP_CTRL + offset) & BIT(STANDBY_EN_SHIFT));
6606*60e6e79dSSandy Huang }
6607*60e6e79dSSandy Huang
vop2_vp_standby(void * regs,u32 vp_id)6608*60e6e79dSSandy Huang static void vop2_vp_standby(void *regs, u32 vp_id)
6609*60e6e79dSSandy Huang {
6610*60e6e79dSSandy Huang u32 offset = vp_id * 0x100;
6611*60e6e79dSSandy Huang
6612*60e6e79dSSandy Huang writel(BIT(STANDBY_EN_SHIFT), regs + RK3568_VP0_DSP_CTRL + offset);
6613*60e6e79dSSandy Huang }
6614*60e6e79dSSandy Huang
vop2_vp_config_done(void * regs,u32 vp_id)6615*60e6e79dSSandy Huang static void vop2_vp_config_done(void *regs, u32 vp_id)
6616*60e6e79dSSandy Huang {
6617*60e6e79dSSandy Huang u32 cfg_done = CFG_DONE_EN | BIT(vp_id) | (BIT(vp_id) << 16);
6618*60e6e79dSSandy Huang u32 offset = vp_id * 0x100;
6619*60e6e79dSSandy Huang
6620*60e6e79dSSandy Huang writel(cfg_done, regs + RK3568_REG_CFG_DONE + offset);
6621*60e6e79dSSandy Huang }
6622*60e6e79dSSandy Huang
vop2_iommu_disable(void * regs,u32 axi_id)6623*60e6e79dSSandy Huang static void vop2_iommu_disable(void *regs, u32 axi_id)
6624*60e6e79dSSandy Huang {
6625*60e6e79dSSandy Huang u32 val = readl(regs + RK3568_IOMMU0_STATUS);
6626*60e6e79dSSandy Huang bool pagefault = val & MMU_PAGE_FAULT_ACTIVE;
6627*60e6e79dSSandy Huang u32 offset = axi_id * 0x100;
6628*60e6e79dSSandy Huang
6629*60e6e79dSSandy Huang writel(MMU_DISABLE_PAGING, regs + RK3568_IOMMU0_COMMAND + offset);
6630*60e6e79dSSandy Huang
6631*60e6e79dSSandy Huang if (pagefault) {
6632*60e6e79dSSandy Huang printf("iommu%d status:0x%x, pagefault addr: 0x%x\n",
6633*60e6e79dSSandy Huang axi_id, val, readl(regs + RK3568_IOMMU0_PAGEFAULT_ADDR + offset));
6634*60e6e79dSSandy Huang writel(MMU_FORCE_RESET, regs + RK3568_IOMMU0_COMMAND + offset);
6635*60e6e79dSSandy Huang }
6636*60e6e79dSSandy Huang }
6637*60e6e79dSSandy Huang
rockchip_vop2_reset(struct udevice * dev,u32 axi,u32 vp_mask,u32 plane_mask)6638*60e6e79dSSandy Huang static int rockchip_vop2_reset(struct udevice *dev, u32 axi, u32 vp_mask, u32 plane_mask)
6639*60e6e79dSSandy Huang {
6640*60e6e79dSSandy Huang void *regs = dev_read_addr_ptr(dev);
6641*60e6e79dSSandy Huang struct rockchip_crtc *crtc = (struct rockchip_crtc *)dev_get_driver_data(dev);
6642*60e6e79dSSandy Huang const struct vop2_data *vop2_data = crtc->data;
6643*60e6e79dSSandy Huang u32 enabled_vp_mask = 0;
6644*60e6e79dSSandy Huang int i = 0;
6645*60e6e79dSSandy Huang
6646*60e6e79dSSandy Huang for (i = 0; i < vop2_data->nr_vps; i++) {
6647*60e6e79dSSandy Huang if (BIT(i) & vp_mask) {
6648*60e6e79dSSandy Huang if (!vop2_vp_in_standby(regs,i)) {
6649*60e6e79dSSandy Huang enabled_vp_mask |= BIT(i);
6650*60e6e79dSSandy Huang }
6651*60e6e79dSSandy Huang }
6652*60e6e79dSSandy Huang }
6653*60e6e79dSSandy Huang
6654*60e6e79dSSandy Huang if (enabled_vp_mask == 0)
6655*60e6e79dSSandy Huang return 0;
6656*60e6e79dSSandy Huang
6657*60e6e79dSSandy Huang for (i = 0; i < vop2_data->nr_layers; i++) {
6658*60e6e79dSSandy Huang if (BIT(vop2_data->win_data[i].phys_id) & plane_mask) {
6659*60e6e79dSSandy Huang if (vop2_data->win_data[i].type == CLUSTER_LAYER)
6660*60e6e79dSSandy Huang vop2_cluster_disable(regs, vop2_data->win_data[i].reg_offset);
6661*60e6e79dSSandy Huang else
6662*60e6e79dSSandy Huang vop2_esmart_disable(regs, vop2_data->win_data[i].reg_offset);
6663*60e6e79dSSandy Huang }
6664*60e6e79dSSandy Huang }
6665*60e6e79dSSandy Huang
6666*60e6e79dSSandy Huang for (i = 0; i < vop2_data->nr_vps; i++) {
6667*60e6e79dSSandy Huang if (BIT(i) & vp_mask)
6668*60e6e79dSSandy Huang vop2_vp_config_done(regs, i);
6669*60e6e79dSSandy Huang }
6670*60e6e79dSSandy Huang mdelay(50);
6671*60e6e79dSSandy Huang vop2_iommu_disable(regs, axi);
6672*60e6e79dSSandy Huang vop2_axi_irqs_disable(regs, axi);
6673*60e6e79dSSandy Huang
6674*60e6e79dSSandy Huang for (i = 0; i < vop2_data->nr_vps; i++) {
6675*60e6e79dSSandy Huang if (BIT(i) & vp_mask) {
6676*60e6e79dSSandy Huang vop2_vp_irqs_disable(regs, i);
6677*60e6e79dSSandy Huang vop2_vp_standby(regs, i);
6678*60e6e79dSSandy Huang }
6679*60e6e79dSSandy Huang }
6680*60e6e79dSSandy Huang printf("Reset vop success\n");
6681*60e6e79dSSandy Huang
6682*60e6e79dSSandy Huang return 0;
6683*60e6e79dSSandy Huang }
6684*60e6e79dSSandy Huang #else
rockchip_vop2_reset(struct udevice * dev,u32 axi,u32 vp_mask,u32 plane_mask)6685*60e6e79dSSandy Huang static int rockchip_vop2_reset(struct udevice *dev, u32 axi, u32 vp_mask, u32 plane_mask)
6686*60e6e79dSSandy Huang {
6687*60e6e79dSSandy Huang return 0;
6688*60e6e79dSSandy Huang }
6689*60e6e79dSSandy Huang #endif
6690*60e6e79dSSandy Huang
669172388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = {
669272388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
669372388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
669472388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
669572388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
669672388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
669772388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
669872388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
669972388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
670072388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
670172388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
670272388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
670372388c26SDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
670472388c26SDamon Ding { RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1},
670572388c26SDamon Ding };
670672388c26SDamon Ding
67076fea745cSDamon Ding #define RK3528_PLANE_MASK_BASE \
67086fea745cSDamon Ding (BIT(ROCKCHIP_VOP2_CLUSTER0) | \
67096fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
67106fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
67115fa6e665SDamon Ding
67125fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = {
67135fa6e665SDamon Ding {
67145fa6e665SDamon Ding .name = "Esmart0",
67155fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0,
67165fa6e665SDamon Ding .type = ESMART_LAYER,
67176fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
67185fa6e665SDamon Ding .win_sel_port_offset = 8,
67195fa6e665SDamon Ding .layer_sel_win_id = { 1, 0xff, 0xff, 0xff },
67205fa6e665SDamon Ding .reg_offset = 0,
67215fa6e665SDamon Ding .axi_id = 0,
67225fa6e665SDamon Ding .axi_yrgb_id = 0x06,
67235fa6e665SDamon Ding .axi_uv_id = 0x07,
67245fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
67255fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67265fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
67275fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67285fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
67295fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
673013bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0),
67315fa6e665SDamon Ding .max_upscale_factor = 8,
67325fa6e665SDamon Ding .max_downscale_factor = 8,
67335fa6e665SDamon Ding },
67345fa6e665SDamon Ding
67355fa6e665SDamon Ding {
67365fa6e665SDamon Ding .name = "Esmart1",
67375fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1,
67385fa6e665SDamon Ding .type = ESMART_LAYER,
67396fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
67405fa6e665SDamon Ding .win_sel_port_offset = 10,
67415fa6e665SDamon Ding .layer_sel_win_id = { 2, 0xff, 0xff, 0xff },
67425fa6e665SDamon Ding .reg_offset = 0x200,
67435fa6e665SDamon Ding .axi_id = 0,
67445fa6e665SDamon Ding .axi_yrgb_id = 0x08,
67455fa6e665SDamon Ding .axi_uv_id = 0x09,
67465fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
67475fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67485fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
67495fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67505fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
67515fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
675213bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0),
67535fa6e665SDamon Ding .max_upscale_factor = 8,
67545fa6e665SDamon Ding .max_downscale_factor = 8,
67555fa6e665SDamon Ding },
67565fa6e665SDamon Ding
67575fa6e665SDamon Ding {
67585fa6e665SDamon Ding .name = "Esmart2",
67595fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2,
67605fa6e665SDamon Ding .type = ESMART_LAYER,
67616fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_CURSOR,
67625fa6e665SDamon Ding .win_sel_port_offset = 12,
67635fa6e665SDamon Ding .layer_sel_win_id = { 3, 0, 0xff, 0xff },
67645fa6e665SDamon Ding .reg_offset = 0x400,
67655fa6e665SDamon Ding .axi_id = 0,
67665fa6e665SDamon Ding .axi_yrgb_id = 0x0a,
67675fa6e665SDamon Ding .axi_uv_id = 0x0b,
67685fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
67695fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67705fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
67715fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67725fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
67735fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
677413bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
67755fa6e665SDamon Ding .max_upscale_factor = 8,
67765fa6e665SDamon Ding .max_downscale_factor = 8,
67775fa6e665SDamon Ding },
67785fa6e665SDamon Ding
67795fa6e665SDamon Ding {
67805fa6e665SDamon Ding .name = "Esmart3",
67815fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3,
67825fa6e665SDamon Ding .type = ESMART_LAYER,
67836fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
67845fa6e665SDamon Ding .win_sel_port_offset = 14,
67855fa6e665SDamon Ding .layer_sel_win_id = { 0xff, 1, 0xff, 0xff },
67865fa6e665SDamon Ding .reg_offset = 0x600,
67875fa6e665SDamon Ding .axi_id = 0,
67885fa6e665SDamon Ding .axi_yrgb_id = 0x0c,
67895fa6e665SDamon Ding .axi_uv_id = 0x0d,
67905fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
67915fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67925fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
67935fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
67945fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
67955fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */
679613bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP1),
67975fa6e665SDamon Ding .max_upscale_factor = 8,
67985fa6e665SDamon Ding .max_downscale_factor = 8,
67995fa6e665SDamon Ding },
68005fa6e665SDamon Ding
68015fa6e665SDamon Ding {
68025fa6e665SDamon Ding .name = "Cluster0",
68035fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0,
68045fa6e665SDamon Ding .type = CLUSTER_LAYER,
68056fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
68065fa6e665SDamon Ding .win_sel_port_offset = 0,
68075fa6e665SDamon Ding .layer_sel_win_id = { 0, 0xff, 0xff, 0xff },
68085fa6e665SDamon Ding .reg_offset = 0,
68095fa6e665SDamon Ding .axi_id = 0,
68105fa6e665SDamon Ding .axi_yrgb_id = 0x02,
68115fa6e665SDamon Ding .axi_uv_id = 0x03,
68125fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
68135fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
68145fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
68155fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
68165fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
68175fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */
681813bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0),
68195fa6e665SDamon Ding .max_upscale_factor = 8,
68205fa6e665SDamon Ding .max_downscale_factor = 8,
68215fa6e665SDamon Ding },
68225fa6e665SDamon Ding };
68235fa6e665SDamon Ding
68245fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = {
68255fa6e665SDamon Ding {
68266027c871SZhang Yubing .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM |
68276027c871SZhang Yubing VOP_FEATURE_POST_CSC,
68285fa6e665SDamon Ding .max_output = {4096, 4096},
6829b05105abSDamon Ding .layer_mix_dly = 6,
6830b05105abSDamon Ding .hdr_mix_dly = 2,
6831b05105abSDamon Ding .win_dly = 8,
68325fa6e665SDamon Ding },
68335fa6e665SDamon Ding {
68345fa6e665SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
68355fa6e665SDamon Ding .max_output = {1920, 1080},
6836b05105abSDamon Ding .layer_mix_dly = 2,
6837b05105abSDamon Ding .hdr_mix_dly = 0,
6838b05105abSDamon Ding .win_dly = 8,
68395fa6e665SDamon Ding },
68405fa6e665SDamon Ding };
68415fa6e665SDamon Ding
68429c7848c3SDamon Ding static const struct vop2_ops rk3528_vop_ops = {
68439c7848c3SDamon Ding .setup_win_dly = rk3528_setup_win_dly,
6844b7195f56SDamon Ding .setup_overlay = rk3528_setup_overlay,
6845ef0607a7SDamon Ding .assign_plane_mask = rk3528_assign_plane_mask,
68469c7848c3SDamon Ding };
68479c7848c3SDamon Ding
68485fa6e665SDamon Ding const struct vop2_data rk3528_vop = {
68495fa6e665SDamon Ding .version = VOP_VERSION_RK3528,
68505fa6e665SDamon Ding .nr_vps = 2,
68515fa6e665SDamon Ding .vp_data = rk3528_vp_data,
68525fa6e665SDamon Ding .win_data = rk3528_win_data,
68536fea745cSDamon Ding .plane_mask_base = RK3528_PLANE_MASK_BASE,
68545fa6e665SDamon Ding .nr_layers = 5,
68555fa6e665SDamon Ding .nr_mixers = 3,
68565fa6e665SDamon Ding .nr_gammas = 2,
68575fa6e665SDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE,
685872388c26SDamon Ding .dump_regs = rk3528_dump_regs,
685972388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3528_dump_regs),
68609c7848c3SDamon Ding .ops = &rk3528_vop_ops,
68619c7848c3SDamon Ding
686272388c26SDamon Ding };
686372388c26SDamon Ding
686472388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = {
686572388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
686672388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 },
686772388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
686872388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
686972388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
687072388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
687172388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
687272388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
687372388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 },
687472388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 },
68755fa6e665SDamon Ding };
68765fa6e665SDamon Ding
68776fea745cSDamon Ding #define RK3562_PLANE_MASK_BASE \
68786fea745cSDamon Ding (BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
68796fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
6880452afb13SDamon Ding
6881452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = {
6882452afb13SDamon Ding {
6883452afb13SDamon Ding .name = "Esmart0",
6884452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0,
6885452afb13SDamon Ding .type = ESMART_LAYER,
68866fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
6887452afb13SDamon Ding .win_sel_port_offset = 8,
6888452afb13SDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff },
6889452afb13SDamon Ding .reg_offset = 0,
6890452afb13SDamon Ding .axi_id = 0,
6891452afb13SDamon Ding .axi_yrgb_id = 0x02,
6892452afb13SDamon Ding .axi_uv_id = 0x03,
6893452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6894452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6895452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6896452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
689713bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0),
6898452afb13SDamon Ding .max_upscale_factor = 8,
6899452afb13SDamon Ding .max_downscale_factor = 8,
6900452afb13SDamon Ding },
6901452afb13SDamon Ding
6902452afb13SDamon Ding {
6903452afb13SDamon Ding .name = "Esmart1",
6904452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1,
6905452afb13SDamon Ding .type = ESMART_LAYER,
69066fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
6907452afb13SDamon Ding .win_sel_port_offset = 10,
6908452afb13SDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff },
6909452afb13SDamon Ding .reg_offset = 0x200,
6910452afb13SDamon Ding .axi_id = 0,
6911452afb13SDamon Ding .axi_yrgb_id = 0x04,
6912452afb13SDamon Ding .axi_uv_id = 0x05,
6913452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6914452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6915452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6916452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
691713bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0),
6918452afb13SDamon Ding .max_upscale_factor = 8,
6919452afb13SDamon Ding .max_downscale_factor = 8,
6920452afb13SDamon Ding },
6921452afb13SDamon Ding
6922452afb13SDamon Ding {
6923452afb13SDamon Ding .name = "Esmart2",
6924452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2,
6925452afb13SDamon Ding .type = ESMART_LAYER,
69266fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
6927452afb13SDamon Ding .win_sel_port_offset = 12,
6928452afb13SDamon Ding .layer_sel_win_id = { 2, 2, 0xff, 0xff },
6929452afb13SDamon Ding .reg_offset = 0x400,
6930452afb13SDamon Ding .axi_id = 0,
6931452afb13SDamon Ding .axi_yrgb_id = 0x06,
6932452afb13SDamon Ding .axi_uv_id = 0x07,
6933452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6934452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6935452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6936452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
693713bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0),
6938452afb13SDamon Ding .max_upscale_factor = 8,
6939452afb13SDamon Ding .max_downscale_factor = 8,
6940452afb13SDamon Ding },
6941452afb13SDamon Ding
6942452afb13SDamon Ding {
6943452afb13SDamon Ding .name = "Esmart3",
6944452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3,
6945452afb13SDamon Ding .type = ESMART_LAYER,
69466fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
6947452afb13SDamon Ding .win_sel_port_offset = 14,
6948452afb13SDamon Ding .layer_sel_win_id = { 3, 3, 0xff, 0xff },
6949452afb13SDamon Ding .reg_offset = 0x600,
6950452afb13SDamon Ding .axi_id = 0,
6951452afb13SDamon Ding .axi_yrgb_id = 0x08,
6952452afb13SDamon Ding .axi_uv_id = 0x0d,
6953452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
6954452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
6955452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
6956452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
695713bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0),
6958452afb13SDamon Ding .max_upscale_factor = 8,
6959452afb13SDamon Ding .max_downscale_factor = 8,
6960452afb13SDamon Ding },
6961452afb13SDamon Ding };
6962452afb13SDamon Ding
6963452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = {
6964452afb13SDamon Ding {
6965452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6966452afb13SDamon Ding .max_output = {2048, 4096},
696753d536adSDamon Ding .win_dly = 6,
6968452afb13SDamon Ding .layer_mix_dly = 8,
6969452afb13SDamon Ding },
6970452afb13SDamon Ding {
6971452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
6972452afb13SDamon Ding .max_output = {2048, 1080},
6973452afb13SDamon Ding .win_dly = 8,
6974452afb13SDamon Ding .layer_mix_dly = 8,
6975452afb13SDamon Ding },
6976452afb13SDamon Ding };
6977452afb13SDamon Ding
69789c7848c3SDamon Ding static const struct vop2_ops rk3562_vop_ops = {
69799c7848c3SDamon Ding .setup_win_dly = rk3528_setup_win_dly,
6980b7195f56SDamon Ding .setup_overlay = rk3528_setup_overlay,
6981ef0607a7SDamon Ding .assign_plane_mask = rk3528_assign_plane_mask,
69829c7848c3SDamon Ding };
69839c7848c3SDamon Ding
6984452afb13SDamon Ding const struct vop2_data rk3562_vop = {
6985452afb13SDamon Ding .version = VOP_VERSION_RK3562,
6986452afb13SDamon Ding .nr_vps = 2,
6987452afb13SDamon Ding .vp_data = rk3562_vp_data,
6988452afb13SDamon Ding .win_data = rk3562_win_data,
69896fea745cSDamon Ding .plane_mask_base = RK3562_PLANE_MASK_BASE,
6990452afb13SDamon Ding .nr_layers = 4,
6991452afb13SDamon Ding .nr_mixers = 3,
6992452afb13SDamon Ding .nr_gammas = 2,
6993452afb13SDamon Ding .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE,
699472388c26SDamon Ding .dump_regs = rk3562_dump_regs,
699572388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3562_dump_regs),
69969c7848c3SDamon Ding .ops = &rk3562_vop_ops,
699772388c26SDamon Ding };
699872388c26SDamon Ding
699972388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = {
700072388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
700172388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
700272388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
700372388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
700472388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
700572388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
700672388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
700772388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
700872388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
700972388c26SDamon Ding { RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
701072388c26SDamon Ding { RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
701172388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
7012452afb13SDamon Ding };
7013452afb13SDamon Ding
7014b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
7015b0989546SSandy Huang { /* one display policy */
7016b0989546SSandy Huang {/* main display */
7017b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0,
7018b0989546SSandy Huang .attached_layers_nr = 6,
7019b0989546SSandy Huang .attached_layers = {
7020b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
7021b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
7022b0989546SSandy Huang },
70232d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7024b0989546SSandy Huang },
7025b0989546SSandy Huang {/* second display */},
7026b0989546SSandy Huang {/* third display */},
7027b0989546SSandy Huang {/* fourth display */},
7028b0989546SSandy Huang },
7029b0989546SSandy Huang
7030b0989546SSandy Huang { /* two display policy */
7031b0989546SSandy Huang {/* main display */
7032b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0,
7033b0989546SSandy Huang .attached_layers_nr = 3,
7034b0989546SSandy Huang .attached_layers = {
7035b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
7036b0989546SSandy Huang },
70372d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7038b0989546SSandy Huang },
7039b0989546SSandy Huang
7040b0989546SSandy Huang {/* second display */
7041b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1,
7042b0989546SSandy Huang .attached_layers_nr = 3,
7043b0989546SSandy Huang .attached_layers = {
7044b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1
7045b0989546SSandy Huang },
70462d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7047b0989546SSandy Huang },
7048b0989546SSandy Huang {/* third display */},
7049b0989546SSandy Huang {/* fourth display */},
7050b0989546SSandy Huang },
7051b0989546SSandy Huang
7052b0989546SSandy Huang { /* three display policy */
7053b0989546SSandy Huang {/* main display */
7054b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0,
7055b0989546SSandy Huang .attached_layers_nr = 3,
7056b0989546SSandy Huang .attached_layers = {
7057b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0
7058b0989546SSandy Huang },
70592d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7060b0989546SSandy Huang },
7061b0989546SSandy Huang
7062b0989546SSandy Huang {/* second display */
7063b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1,
7064b0989546SSandy Huang .attached_layers_nr = 2,
7065b0989546SSandy Huang .attached_layers = {
7066b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1
7067b0989546SSandy Huang },
70682d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7069b0989546SSandy Huang },
7070b0989546SSandy Huang
7071b0989546SSandy Huang {/* third display */
7072b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7073b0989546SSandy Huang .attached_layers_nr = 1,
7074b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 },
70752d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7076b0989546SSandy Huang },
7077b0989546SSandy Huang
7078b0989546SSandy Huang {/* fourth display */},
7079b0989546SSandy Huang },
7080b0989546SSandy Huang
7081b0989546SSandy Huang {/* reserved for four display policy */},
7082b0989546SSandy Huang };
7083b0989546SSandy Huang
70846fea745cSDamon Ding #define RK3568_PLANE_MASK_BASE \
70856fea745cSDamon Ding (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
70866fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
70876fea745cSDamon Ding BIT(ROCKCHIP_VOP2_SMART0) | BIT(ROCKCHIP_VOP2_SMART1))
70886fea745cSDamon Ding
7089b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = {
7090b0989546SSandy Huang {
7091b0989546SSandy Huang .name = "Cluster0",
7092b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0,
7093ecc31b6eSAndy Yan .type = CLUSTER_LAYER,
70946fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7095b0989546SSandy Huang .win_sel_port_offset = 0,
70965fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0xff },
7097b0989546SSandy Huang .reg_offset = 0,
70985fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
70995fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71005fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
71015fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
710213bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71034c765862SDamon Ding .max_upscale_factor = 4,
71044c765862SDamon Ding .max_downscale_factor = 4,
71059c7848c3SDamon Ding .dly = { 0, 27, 21 },
7106b0989546SSandy Huang },
7107b0989546SSandy Huang
7108b0989546SSandy Huang {
7109b0989546SSandy Huang .name = "Cluster1",
7110b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1,
7111ecc31b6eSAndy Yan .type = CLUSTER_LAYER,
71126fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7113b0989546SSandy Huang .win_sel_port_offset = 1,
71145fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 0xff },
7115b0989546SSandy Huang .reg_offset = 0x200,
71165fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
71175fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71185fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
71195fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
712013bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71214c765862SDamon Ding .max_upscale_factor = 4,
71224c765862SDamon Ding .max_downscale_factor = 4,
71231c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_CLUSTER0,
71241c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR,
71259c7848c3SDamon Ding .dly = { 0, 27, 21 },
7126b0989546SSandy Huang },
7127b0989546SSandy Huang
7128b0989546SSandy Huang {
7129b0989546SSandy Huang .name = "Esmart0",
7130b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0,
7131ecc31b6eSAndy Yan .type = ESMART_LAYER,
71326fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7133b0989546SSandy Huang .win_sel_port_offset = 4,
71345fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 0xff },
7135b0989546SSandy Huang .reg_offset = 0,
71365fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
71375fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71385fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
71395fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
714013bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71414c765862SDamon Ding .max_upscale_factor = 8,
71424c765862SDamon Ding .max_downscale_factor = 8,
71439c7848c3SDamon Ding .dly = { 20, 47, 41 },
7144b0989546SSandy Huang },
7145b0989546SSandy Huang
7146b0989546SSandy Huang {
7147b0989546SSandy Huang .name = "Esmart1",
7148b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1,
7149ecc31b6eSAndy Yan .type = ESMART_LAYER,
71506fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7151b0989546SSandy Huang .win_sel_port_offset = 5,
71525fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 0xff },
7153b0989546SSandy Huang .reg_offset = 0x200,
71545fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
71555fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71565fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
71575fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
715813bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71594c765862SDamon Ding .max_upscale_factor = 8,
71604c765862SDamon Ding .max_downscale_factor = 8,
71619c7848c3SDamon Ding .dly = { 20, 47, 41 },
71621c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_ESMART0,
71631c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR,
7164b0989546SSandy Huang },
7165b0989546SSandy Huang
7166b0989546SSandy Huang {
7167b0989546SSandy Huang .name = "Smart0",
7168b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0,
7169ecc31b6eSAndy Yan .type = SMART_LAYER,
71706fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7171b0989546SSandy Huang .win_sel_port_offset = 6,
71725fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 0xff },
7173b0989546SSandy Huang .reg_offset = 0x400,
71745fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
71755fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71765fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
71775fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
717813bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71794c765862SDamon Ding .max_upscale_factor = 8,
71804c765862SDamon Ding .max_downscale_factor = 8,
71819c7848c3SDamon Ding .dly = { 20, 47, 41 },
7182b0989546SSandy Huang },
7183b0989546SSandy Huang
7184b0989546SSandy Huang {
7185b0989546SSandy Huang .name = "Smart1",
7186b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1,
7187ecc31b6eSAndy Yan .type = SMART_LAYER,
71886fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7189b0989546SSandy Huang .win_sel_port_offset = 7,
71905fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 0xff },
7191b0989546SSandy Huang .reg_offset = 0x600,
71925fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
71935fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
71945fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
71955fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
719613bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2),
71974c765862SDamon Ding .max_upscale_factor = 8,
71984c765862SDamon Ding .max_downscale_factor = 8,
71999c7848c3SDamon Ding .dly = { 20, 47, 41 },
72001c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_SMART0,
72011c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR,
7202b0989546SSandy Huang },
7203b0989546SSandy Huang };
7204b0989546SSandy Huang
720563cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = {
720663cb669fSSandy Huang {
720763cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT,
720863cb669fSSandy Huang .pre_scan_max_dly = 42,
720963cb669fSSandy Huang .max_output = {4096, 2304},
7210d0408543SAndy Yan },
721163cb669fSSandy Huang {
721263cb669fSSandy Huang .feature = 0,
721363cb669fSSandy Huang .pre_scan_max_dly = 40,
721463cb669fSSandy Huang .max_output = {2048, 1536},
721563cb669fSSandy Huang },
721663cb669fSSandy Huang {
721763cb669fSSandy Huang .feature = 0,
721863cb669fSSandy Huang .pre_scan_max_dly = 40,
721963cb669fSSandy Huang .max_output = {1920, 1080},
722063cb669fSSandy Huang },
722163cb669fSSandy Huang };
7222d0408543SAndy Yan
72239c7848c3SDamon Ding static const struct vop2_ops rk3568_vop_ops = {
72249c7848c3SDamon Ding .setup_win_dly = rk3568_setup_win_dly,
7225b7195f56SDamon Ding .setup_overlay = rk3568_setup_overlay,
7226ef0607a7SDamon Ding .assign_plane_mask = rk3568_assign_plane_mask,
72279c7848c3SDamon Ding };
72289c7848c3SDamon Ding
722963cb669fSSandy Huang const struct vop2_data rk3568_vop = {
7230ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568,
723163cb669fSSandy Huang .nr_vps = 3,
723263cb669fSSandy Huang .vp_data = rk3568_vp_data,
7233b0989546SSandy Huang .win_data = rk3568_win_data,
7234b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0],
72356fea745cSDamon Ding .plane_mask_base = RK3568_PLANE_MASK_BASE,
7236d0408543SAndy Yan .nr_layers = 6,
723763cb669fSSandy Huang .nr_mixers = 5,
72381147facaSSandy Huang .nr_gammas = 1,
723972388c26SDamon Ding .dump_regs = rk3568_dump_regs,
724072388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs),
72419c7848c3SDamon Ding .ops = &rk3568_vop_ops,
7242d0408543SAndy Yan };
7243d0408543SAndy Yan
72446fea745cSDamon Ding #define RK3576_PLANE_MASK_BASE \
72456fea745cSDamon Ding (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
72466fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
72476fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
7248a552a69cSDamon Ding
7249a552a69cSDamon Ding static struct vop2_dump_regs rk3576_dump_regs[] = {
7250a552a69cSDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 },
7251a552a69cSDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 },
7252a552a69cSDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 },
7253a552a69cSDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 },
7254a552a69cSDamon Ding { RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 },
7255a552a69cSDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7256a552a69cSDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7257a552a69cSDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 },
7258a552a69cSDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
7259a552a69cSDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 },
7260a552a69cSDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 },
7261a552a69cSDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 },
7262a552a69cSDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 },
7263a552a69cSDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 },
7264a552a69cSDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 },
7265a552a69cSDamon Ding };
7266a552a69cSDamon Ding
7267a552a69cSDamon Ding /*
7268a552a69cSDamon Ding * RK3576 VOP with 2 Cluster win and 4 Esmart win.
7269a552a69cSDamon Ding * Every Esmart win support 4 multi-region.
7270a552a69cSDamon Ding * VP0 can use Cluster0/1 and Esmart0/2
7271a552a69cSDamon Ding * VP1 can use Cluster0/1 and Esmart1/3
7272a552a69cSDamon Ding * VP2 can use Esmart0/1/2/3
7273a552a69cSDamon Ding *
7274a552a69cSDamon Ding * Scale filter mode:
7275a552a69cSDamon Ding *
7276a552a69cSDamon Ding * * Cluster:
7277a552a69cSDamon Ding * * Support prescale down:
7278a552a69cSDamon Ding * * H/V: gt2/avg2 or gt4/avg4
7279a552a69cSDamon Ding * * After prescale down:
7280a552a69cSDamon Ding * * nearest-neighbor/bilinear/multi-phase filter for scale up
7281a552a69cSDamon Ding * * nearest-neighbor/bilinear/multi-phase filter for scale down
7282a552a69cSDamon Ding *
7283a552a69cSDamon Ding * * Esmart:
7284a552a69cSDamon Ding * * Support prescale down:
7285a552a69cSDamon Ding * * H: gt2/avg2 or gt4/avg4
7286a552a69cSDamon Ding * * V: gt2 or gt4
7287a552a69cSDamon Ding * * After prescale down:
7288a552a69cSDamon Ding * * nearest-neighbor/bilinear/bicubic for scale up
7289a552a69cSDamon Ding * * nearest-neighbor/bilinear for scale down
7290cc517d73SDamon Ding *
7291cc517d73SDamon Ding * AXI config::
7292cc517d73SDamon Ding *
7293cc517d73SDamon Ding * * Cluster0 win0: 0xa, 0xb [AXI0]
7294cc517d73SDamon Ding * * Cluster0 win1: 0xc, 0xd [AXI0]
7295cc517d73SDamon Ding * * Cluster1 win0: 0x6, 0x7 [AXI0]
7296cc517d73SDamon Ding * * Cluster1 win1: 0x8, 0x9 [AXI0]
7297cc517d73SDamon Ding * * Esmart0: 0x10, 0x11 [AXI0]
7298cc517d73SDamon Ding * * Esmart1: 0x12, 0x13 [AXI0]
7299cc517d73SDamon Ding * * Esmart2: 0xa, 0xb [AXI1]
7300cc517d73SDamon Ding * * Esmart3: 0xc, 0xd [AXI1]
7301cc517d73SDamon Ding * * Lut dma rid: 0x1, 0x2, 0x3 [AXI0]
7302cc517d73SDamon Ding * * DCI dma rid: 0x4 [AXI0]
7303cc517d73SDamon Ding * * Metadata rid: 0x5 [AXI0]
7304cc517d73SDamon Ding *
7305cc517d73SDamon Ding * * Limit:
7306cc517d73SDamon Ding * * (1) 0x0 and 0xf can't be used;
7307cc517d73SDamon Ding * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf,
7308cc517d73SDamon Ding * * VOP will dead at the system bandwidth very terrible scene.
7309a552a69cSDamon Ding */
7310a552a69cSDamon Ding static struct vop2_win_data rk3576_win_data[6] = {
7311a552a69cSDamon Ding {
7312a552a69cSDamon Ding .name = "Esmart0",
7313a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0,
7314a552a69cSDamon Ding .type = ESMART_LAYER,
73156fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7316a552a69cSDamon Ding .layer_sel_win_id = { 2, 0xff, 0, 0xff },
7317a552a69cSDamon Ding .reg_offset = 0x0,
7318a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y,
7319a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7320a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7321a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7322a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7323a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7324a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7325a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART,
7326a552a69cSDamon Ding .axi_id = 0,
7327cc517d73SDamon Ding .axi_yrgb_id = 0x10,
7328cc517d73SDamon Ding .axi_uv_id = 0x11,
732913bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
7330a552a69cSDamon Ding .max_upscale_factor = 8,
7331a552a69cSDamon Ding .max_downscale_factor = 8,
7332a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH,
7333a552a69cSDamon Ding },
7334a552a69cSDamon Ding {
7335a552a69cSDamon Ding .name = "Esmart1",
7336a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1,
7337a552a69cSDamon Ding .type = ESMART_LAYER,
73386fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7339a552a69cSDamon Ding .layer_sel_win_id = { 0xff, 2, 1, 0xff },
7340a552a69cSDamon Ding .reg_offset = 0x200,
7341a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y,
7342a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7343a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7344a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7345a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7346a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7347a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7348a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART,
7349a552a69cSDamon Ding .axi_id = 0,
7350cc517d73SDamon Ding .axi_yrgb_id = 0x12,
7351cc517d73SDamon Ding .axi_uv_id = 0x13,
735213bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
7353a552a69cSDamon Ding .max_upscale_factor = 8,
7354a552a69cSDamon Ding .max_downscale_factor = 8,
7355a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA,
7356a552a69cSDamon Ding },
7357a552a69cSDamon Ding
7358a552a69cSDamon Ding {
7359a552a69cSDamon Ding .name = "Esmart2",
7360a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2,
7361a552a69cSDamon Ding .type = ESMART_LAYER,
73626fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7363a552a69cSDamon Ding .layer_sel_win_id = { 3, 0xff, 2, 0xff },
7364a552a69cSDamon Ding .reg_offset = 0x400,
7365a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y,
7366a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7367a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7368a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7369a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7370a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7371a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7372a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART,
7373a552a69cSDamon Ding .axi_id = 1,
7374a552a69cSDamon Ding .axi_yrgb_id = 0x0a,
7375a552a69cSDamon Ding .axi_uv_id = 0x0b,
737613bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2),
7377a552a69cSDamon Ding .max_upscale_factor = 8,
7378a552a69cSDamon Ding .max_downscale_factor = 8,
7379a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA,
7380a552a69cSDamon Ding },
7381a552a69cSDamon Ding
7382a552a69cSDamon Ding {
7383a552a69cSDamon Ding .name = "Esmart3",
7384a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3,
7385a552a69cSDamon Ding .type = ESMART_LAYER,
73866fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7387a552a69cSDamon Ding .layer_sel_win_id = { 0xff, 3, 3, 0xff },
7388a552a69cSDamon Ding .reg_offset = 0x600,
7389a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y,
7390a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
7391a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7392a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7393a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7394a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7395a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */
7396a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART,
7397a552a69cSDamon Ding .axi_id = 1,
7398a552a69cSDamon Ding .axi_yrgb_id = 0x0c,
7399a552a69cSDamon Ding .axi_uv_id = 0x0d,
740013bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2),
7401a552a69cSDamon Ding .max_upscale_factor = 8,
7402a552a69cSDamon Ding .max_downscale_factor = 8,
7403a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA,
7404a552a69cSDamon Ding },
7405a552a69cSDamon Ding
7406a552a69cSDamon Ding {
7407a552a69cSDamon Ding .name = "Cluster0",
7408a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0,
7409a552a69cSDamon Ding .type = CLUSTER_LAYER,
74106fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7411a552a69cSDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff },
7412a552a69cSDamon Ding .reg_offset = 0x0,
7413a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
7414a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIL,
7415a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7416a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7417a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7418a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7419a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7420a552a69cSDamon Ding .pd_id = VOP2_PD_CLUSTER,
7421cc517d73SDamon Ding .axi_yrgb_id = 0x0a,
7422cc517d73SDamon Ding .axi_uv_id = 0x0b,
742313bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
7424a552a69cSDamon Ding .max_upscale_factor = 8,
7425a552a69cSDamon Ding .max_downscale_factor = 8,
7426a552a69cSDamon Ding .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
7427a552a69cSDamon Ding WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI,
7428a552a69cSDamon Ding },
7429a552a69cSDamon Ding
7430a552a69cSDamon Ding {
7431a552a69cSDamon Ding .name = "Cluster1",
7432a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER1,
7433a552a69cSDamon Ding .type = CLUSTER_LAYER,
74346fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7435a552a69cSDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff },
7436a552a69cSDamon Ding .reg_offset = 0x200,
7437a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
7438a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIL,
7439a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7440a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
7441a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
7442a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7443a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */
7444a552a69cSDamon Ding .pd_id = VOP2_PD_CLUSTER,
7445a552a69cSDamon Ding .axi_yrgb_id = 0x06,
7446a552a69cSDamon Ding .axi_uv_id = 0x07,
744713bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1),
7448a552a69cSDamon Ding .max_upscale_factor = 8,
7449a552a69cSDamon Ding .max_downscale_factor = 8,
7450a552a69cSDamon Ding .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN |
7451a552a69cSDamon Ding WIN_FEATURE_Y2R_13BIT_DEPTH,
7452a552a69cSDamon Ding },
7453a552a69cSDamon Ding };
7454a552a69cSDamon Ding
745544b1b62cSDamon Ding /*
745644b1b62cSDamon Ding * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4,
745744b1b62cSDamon Ding * the urgency signal will be set to 1, when full post line buffer is over 6, the
745844b1b62cSDamon Ding * urgency signal will be set to 0.
745944b1b62cSDamon Ding */
746044b1b62cSDamon Ding static struct vop_urgency rk3576_vp0_urgency = {
746144b1b62cSDamon Ding .urgen_thl = 4,
746244b1b62cSDamon Ding .urgen_thh = 6,
746344b1b62cSDamon Ding };
746444b1b62cSDamon Ding
7465a552a69cSDamon Ding static struct vop2_vp_data rk3576_vp_data[3] = {
7466a552a69cSDamon Ding {
7467a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR |
7468a552a69cSDamon Ding VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT |
7469a552a69cSDamon Ding VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP,
7470a552a69cSDamon Ding .max_output = { 4096, 4096 },
7471a552a69cSDamon Ding .hdrvivid_dly = 21,
7472a552a69cSDamon Ding .sdr2hdr_dly = 21,
7473a552a69cSDamon Ding .layer_mix_dly = 8,
7474a552a69cSDamon Ding .hdr_mix_dly = 2,
7475a552a69cSDamon Ding .win_dly = 10,
7476a552a69cSDamon Ding .pixel_rate = 2,
747744b1b62cSDamon Ding .urgency = &rk3576_vp0_urgency,
7478a552a69cSDamon Ding },
7479a552a69cSDamon Ding {
7480a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN |
7481a552a69cSDamon Ding VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2,
7482a552a69cSDamon Ding .max_output = { 2560, 2560 },
7483a552a69cSDamon Ding .hdrvivid_dly = 0,
7484a552a69cSDamon Ding .sdr2hdr_dly = 0,
7485a552a69cSDamon Ding .layer_mix_dly = 6,
7486a552a69cSDamon Ding .hdr_mix_dly = 0,
7487a552a69cSDamon Ding .win_dly = 10,
7488a552a69cSDamon Ding .pixel_rate = 1,
7489a552a69cSDamon Ding },
7490a552a69cSDamon Ding {
7491a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN,
7492a552a69cSDamon Ding .max_output = { 1920, 1920 },
7493a552a69cSDamon Ding .hdrvivid_dly = 0,
7494a552a69cSDamon Ding .sdr2hdr_dly = 0,
7495a552a69cSDamon Ding .layer_mix_dly = 6,
7496a552a69cSDamon Ding .hdr_mix_dly = 0,
7497a552a69cSDamon Ding .win_dly = 10,
7498a552a69cSDamon Ding .pixel_rate = 1,
7499a552a69cSDamon Ding },
7500a552a69cSDamon Ding };
7501a552a69cSDamon Ding
7502a552a69cSDamon Ding static struct vop2_power_domain_data rk3576_vop_pd_data[] = {
7503a552a69cSDamon Ding {
7504a552a69cSDamon Ding .id = VOP2_PD_CLUSTER,
7505a552a69cSDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1),
7506a552a69cSDamon Ding },
7507a552a69cSDamon Ding {
7508a552a69cSDamon Ding .id = VOP2_PD_ESMART,
7509a552a69cSDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) |
7510a552a69cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3),
7511a552a69cSDamon Ding },
7512a552a69cSDamon Ding };
7513a552a69cSDamon Ding
7514a552a69cSDamon Ding static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = {
7515a552a69cSDamon Ding {VOP3_ESMART_4K_4K_4K_MODE, 2},
7516a552a69cSDamon Ding {VOP3_ESMART_4K_4K_2K_2K_MODE, 3}
7517a552a69cSDamon Ding };
7518a552a69cSDamon Ding
75199c7848c3SDamon Ding static const struct vop2_ops rk3576_vop_ops = {
75209c7848c3SDamon Ding .setup_win_dly = rk3576_setup_win_dly,
7521b7195f56SDamon Ding .setup_overlay = rk3576_setup_overlay,
7522ef0607a7SDamon Ding .assign_plane_mask = rk3528_assign_plane_mask,
75239c7848c3SDamon Ding };
75249c7848c3SDamon Ding
7525a552a69cSDamon Ding const struct vop2_data rk3576_vop = {
7526a552a69cSDamon Ding .version = VOP_VERSION_RK3576,
7527a552a69cSDamon Ding .nr_vps = 3,
7528a552a69cSDamon Ding .nr_mixers = 4,
7529a552a69cSDamon Ding .nr_layers = 6,
7530a552a69cSDamon Ding .nr_gammas = 3,
7531a552a69cSDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE,
7532a552a69cSDamon Ding .esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map),
7533a552a69cSDamon Ding .esmart_lb_mode_map = rk3576_esmart_lb_mode_map,
7534a552a69cSDamon Ding .vp_data = rk3576_vp_data,
7535a552a69cSDamon Ding .win_data = rk3576_win_data,
75366fea745cSDamon Ding .plane_mask_base = RK3576_PLANE_MASK_BASE,
7537a552a69cSDamon Ding .pd = rk3576_vop_pd_data,
7538a552a69cSDamon Ding .nr_pd = ARRAY_SIZE(rk3576_vop_pd_data),
7539a552a69cSDamon Ding .dump_regs = rk3576_dump_regs,
7540a552a69cSDamon Ding .dump_regs_size = ARRAY_SIZE(rk3576_dump_regs),
75419c7848c3SDamon Ding .ops = &rk3576_vop_ops,
7542a552a69cSDamon Ding };
7543a552a69cSDamon Ding
754472388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = {
754572388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 },
754672388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 },
754772388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 },
754872388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 },
754972388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 },
755072388c26SDamon Ding { RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 },
755172388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 },
755272388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 },
755372388c26SDamon Ding { RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 },
755472388c26SDamon Ding { RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 },
755572388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 },
755672388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 },
755772388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 },
755872388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 },
755972388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 },
756072388c26SDamon Ding };
756172388c26SDamon Ding
7562ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = {
7563ecc31b6eSAndy Yan { /* one display policy */
7564ecc31b6eSAndy Yan {/* main display */
7565608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
756683d6b087SDamon Ding .attached_layers_nr = 4,
7567ecc31b6eSAndy Yan .attached_layers = {
756883d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
756983d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7570ecc31b6eSAndy Yan },
75712d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7572ecc31b6eSAndy Yan },
757383d6b087SDamon Ding
757483d6b087SDamon Ding {/* planes for the splice mode */
757583d6b087SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
757683d6b087SDamon Ding .attached_layers_nr = 4,
757783d6b087SDamon Ding .attached_layers = {
757883d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
757983d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
758083d6b087SDamon Ding },
75812d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
758283d6b087SDamon Ding },
7583ecc31b6eSAndy Yan {/* third display */},
7584ecc31b6eSAndy Yan {/* fourth display */},
7585ecc31b6eSAndy Yan },
7586ecc31b6eSAndy Yan
7587ecc31b6eSAndy Yan { /* two display policy */
7588ecc31b6eSAndy Yan {/* main display */
7589608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7590ecc31b6eSAndy Yan .attached_layers_nr = 4,
7591ecc31b6eSAndy Yan .attached_layers = {
7592ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0,
759383d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2
7594ecc31b6eSAndy Yan },
75952d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7596ecc31b6eSAndy Yan },
7597ecc31b6eSAndy Yan
7598ecc31b6eSAndy Yan {/* second display */
759983d6b087SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7600ecc31b6eSAndy Yan .attached_layers_nr = 4,
7601ecc31b6eSAndy Yan .attached_layers = {
760283d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1,
7603ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3
7604ecc31b6eSAndy Yan },
76052d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7606ecc31b6eSAndy Yan },
7607ecc31b6eSAndy Yan {/* third display */},
7608ecc31b6eSAndy Yan {/* fourth display */},
7609ecc31b6eSAndy Yan },
7610ecc31b6eSAndy Yan
7611ecc31b6eSAndy Yan { /* three display policy */
7612ecc31b6eSAndy Yan {/* main display */
7613608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7614ecc31b6eSAndy Yan .attached_layers_nr = 3,
7615ecc31b6eSAndy Yan .attached_layers = {
761683d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER2,
761783d6b087SDamon Ding ROCKCHIP_VOP2_ESMART0
7618ecc31b6eSAndy Yan },
76192d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7620ecc31b6eSAndy Yan },
7621ecc31b6eSAndy Yan
7622ecc31b6eSAndy Yan {/* second display */
7623608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7624ecc31b6eSAndy Yan .attached_layers_nr = 3,
7625ecc31b6eSAndy Yan .attached_layers = {
762683d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_CLUSTER3,
762783d6b087SDamon Ding ROCKCHIP_VOP2_ESMART1
7628ecc31b6eSAndy Yan },
76292d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7630ecc31b6eSAndy Yan },
7631ecc31b6eSAndy Yan
7632ecc31b6eSAndy Yan {/* third display */
7633ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7634ecc31b6eSAndy Yan .attached_layers_nr = 2,
7635ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 },
76362d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7637ecc31b6eSAndy Yan },
7638ecc31b6eSAndy Yan
7639ecc31b6eSAndy Yan {/* fourth display */},
7640ecc31b6eSAndy Yan },
7641ecc31b6eSAndy Yan
7642ecc31b6eSAndy Yan { /* four display policy */
7643ecc31b6eSAndy Yan {/* main display */
7644608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0,
7645ecc31b6eSAndy Yan .attached_layers_nr = 2,
7646ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 },
76472d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7648ecc31b6eSAndy Yan },
7649ecc31b6eSAndy Yan
7650ecc31b6eSAndy Yan {/* second display */
7651608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1,
7652ecc31b6eSAndy Yan .attached_layers_nr = 2,
7653ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 },
76542d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7655ecc31b6eSAndy Yan },
7656ecc31b6eSAndy Yan
7657ecc31b6eSAndy Yan {/* third display */
7658608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2,
7659ecc31b6eSAndy Yan .attached_layers_nr = 2,
7660ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 },
76612d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7662ecc31b6eSAndy Yan },
7663ecc31b6eSAndy Yan
7664ecc31b6eSAndy Yan {/* fourth display */
7665608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3,
7666ecc31b6eSAndy Yan .attached_layers_nr = 2,
7667ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 },
76682d3a2f01SDamon Ding .cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID,
7669ecc31b6eSAndy Yan },
7670ecc31b6eSAndy Yan },
7671ecc31b6eSAndy Yan
7672ecc31b6eSAndy Yan };
7673ecc31b6eSAndy Yan
76746fea745cSDamon Ding #define RK3588_PLANE_MASK_BASE \
76756fea745cSDamon Ding (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \
76766fea745cSDamon Ding BIT(ROCKCHIP_VOP2_CLUSTER2) | BIT(ROCKCHIP_VOP2_CLUSTER3) | \
76776fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \
76786fea745cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3))
76796fea745cSDamon Ding
7680ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = {
7681ecc31b6eSAndy Yan {
7682ecc31b6eSAndy Yan .name = "Cluster0",
7683ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0,
7684ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER1,
7685ecc31b6eSAndy Yan .type = CLUSTER_LAYER,
76866fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7687ecc31b6eSAndy Yan .win_sel_port_offset = 0,
76885fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0 },
7689ecc31b6eSAndy Yan .reg_offset = 0,
7690a33b790fSDamon Ding .axi_id = 0,
7691a33b790fSDamon Ding .axi_yrgb_id = 2,
7692a33b790fSDamon Ding .axi_uv_id = 3,
7693b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER0,
76945fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
76955fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
76965fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
76975fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
769813bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
76994c765862SDamon Ding .max_upscale_factor = 4,
77004c765862SDamon Ding .max_downscale_factor = 4,
77019c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 },
7702ecc31b6eSAndy Yan },
7703ecc31b6eSAndy Yan
7704ecc31b6eSAndy Yan {
7705ecc31b6eSAndy Yan .name = "Cluster1",
7706ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1,
7707ecc31b6eSAndy Yan .type = CLUSTER_LAYER,
77086fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7709ecc31b6eSAndy Yan .win_sel_port_offset = 1,
77105fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 1 },
7711ecc31b6eSAndy Yan .reg_offset = 0x200,
7712a33b790fSDamon Ding .axi_id = 0,
7713a33b790fSDamon Ding .axi_yrgb_id = 6,
7714a33b790fSDamon Ding .axi_uv_id = 7,
7715b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER1,
77165fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
77175fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77185fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
77195fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
772013bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77214c765862SDamon Ding .max_upscale_factor = 4,
77224c765862SDamon Ding .max_downscale_factor = 4,
77239c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 },
7724ecc31b6eSAndy Yan },
7725ecc31b6eSAndy Yan
7726ecc31b6eSAndy Yan {
7727ecc31b6eSAndy Yan .name = "Cluster2",
7728ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2,
7729ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER3,
7730ecc31b6eSAndy Yan .type = CLUSTER_LAYER,
77316fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7732ecc31b6eSAndy Yan .win_sel_port_offset = 2,
77335fa6e665SDamon Ding .layer_sel_win_id = { 4, 4, 4, 4 },
7734ecc31b6eSAndy Yan .reg_offset = 0x400,
7735a33b790fSDamon Ding .axi_id = 1,
7736a33b790fSDamon Ding .axi_yrgb_id = 2,
7737a33b790fSDamon Ding .axi_uv_id = 3,
7738b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER2,
77395fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
77405fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77415fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
77425fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
774313bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77444c765862SDamon Ding .max_upscale_factor = 4,
77454c765862SDamon Ding .max_downscale_factor = 4,
77469c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 },
7747ecc31b6eSAndy Yan },
7748ecc31b6eSAndy Yan
7749ecc31b6eSAndy Yan {
7750ecc31b6eSAndy Yan .name = "Cluster3",
7751ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3,
7752ecc31b6eSAndy Yan .type = CLUSTER_LAYER,
77536fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_OVERLAY,
7754ecc31b6eSAndy Yan .win_sel_port_offset = 3,
77555fa6e665SDamon Ding .layer_sel_win_id = { 5, 5, 5, 5 },
7756ecc31b6eSAndy Yan .reg_offset = 0x600,
7757a33b790fSDamon Ding .axi_id = 1,
7758a33b790fSDamon Ding .axi_yrgb_id = 6,
7759a33b790fSDamon Ding .axi_uv_id = 7,
7760b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER3,
77615fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
77625fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77635fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
77645fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
776513bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77664c765862SDamon Ding .max_upscale_factor = 4,
77674c765862SDamon Ding .max_downscale_factor = 4,
77689c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 },
7769ecc31b6eSAndy Yan },
7770ecc31b6eSAndy Yan
7771ecc31b6eSAndy Yan {
7772ecc31b6eSAndy Yan .name = "Esmart0",
7773ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0,
7774ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART1,
7775ecc31b6eSAndy Yan .type = ESMART_LAYER,
77766fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7777ecc31b6eSAndy Yan .win_sel_port_offset = 4,
77785fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 2 },
7779ecc31b6eSAndy Yan .reg_offset = 0,
7780a33b790fSDamon Ding .axi_id = 0,
7781a33b790fSDamon Ding .axi_yrgb_id = 0x0a,
7782a33b790fSDamon Ding .axi_uv_id = 0x0b,
77835fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
77845fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
77855fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
77865fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
778713bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
77884c765862SDamon Ding .max_upscale_factor = 8,
77894c765862SDamon Ding .max_downscale_factor = 8,
77909c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 },
7791ecc31b6eSAndy Yan },
7792ecc31b6eSAndy Yan
7793ecc31b6eSAndy Yan {
7794ecc31b6eSAndy Yan .name = "Esmart1",
7795ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1,
7796ecc31b6eSAndy Yan .type = ESMART_LAYER,
77976fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7798ecc31b6eSAndy Yan .win_sel_port_offset = 5,
77995fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 3 },
7800ecc31b6eSAndy Yan .reg_offset = 0x200,
7801a33b790fSDamon Ding .axi_id = 0,
7802a33b790fSDamon Ding .axi_yrgb_id = 0x0c,
7803a33b790fSDamon Ding .axi_uv_id = 0x0d,
7804b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART,
78055fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
78065fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
78075fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
78085fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
780913bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
78104c765862SDamon Ding .max_upscale_factor = 8,
78114c765862SDamon Ding .max_downscale_factor = 8,
78129c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 },
7813ecc31b6eSAndy Yan },
7814ecc31b6eSAndy Yan
7815ecc31b6eSAndy Yan {
7816ecc31b6eSAndy Yan .name = "Esmart2",
7817ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2,
7818ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART3,
7819ecc31b6eSAndy Yan .type = ESMART_LAYER,
78206fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7821ecc31b6eSAndy Yan .win_sel_port_offset = 6,
78225fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 6 },
7823ecc31b6eSAndy Yan .reg_offset = 0x400,
7824a33b790fSDamon Ding .axi_id = 1,
7825a33b790fSDamon Ding .axi_yrgb_id = 0x0a,
7826a33b790fSDamon Ding .axi_uv_id = 0x0b,
7827b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART,
78285fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
78295fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
78305fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
78315fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
783213bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
78334c765862SDamon Ding .max_upscale_factor = 8,
78344c765862SDamon Ding .max_downscale_factor = 8,
78359c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 },
7836ecc31b6eSAndy Yan },
7837ecc31b6eSAndy Yan
7838ecc31b6eSAndy Yan {
7839ecc31b6eSAndy Yan .name = "Esmart3",
7840ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3,
7841ecc31b6eSAndy Yan .type = ESMART_LAYER,
78426fea745cSDamon Ding .plane_type = VOP2_PLANE_TYPE_PRIMARY,
7843ecc31b6eSAndy Yan .win_sel_port_offset = 7,
78445fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 7 },
7845ecc31b6eSAndy Yan .reg_offset = 0x600,
7846a33b790fSDamon Ding .axi_id = 1,
7847a33b790fSDamon Ding .axi_yrgb_id = 0x0c,
7848a33b790fSDamon Ding .axi_uv_id = 0x0d,
7849b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART,
78505fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC,
78515fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
78525fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL,
78535fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
785413bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3),
78554c765862SDamon Ding .max_upscale_factor = 8,
78564c765862SDamon Ding .max_downscale_factor = 8,
78579c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 },
7858ecc31b6eSAndy Yan },
7859ecc31b6eSAndy Yan };
7860ecc31b6eSAndy Yan
786112ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = {
786212ee5af0SDamon Ding {0x00000000, "no error detected by DSC encoder"},
786312ee5af0SDamon Ding {0x0030ffff, "bits per component error"},
786412ee5af0SDamon Ding {0x0040ffff, "multiple mode error"},
786512ee5af0SDamon Ding {0x0050ffff, "line buffer depth error"},
786612ee5af0SDamon Ding {0x0060ffff, "minor version error"},
786712ee5af0SDamon Ding {0x0070ffff, "picture height error"},
786812ee5af0SDamon Ding {0x0080ffff, "picture width error"},
786912ee5af0SDamon Ding {0x0090ffff, "number of slices error"},
787012ee5af0SDamon Ding {0x00c0ffff, "slice height Error "},
787112ee5af0SDamon Ding {0x00d0ffff, "slice width error"},
787212ee5af0SDamon Ding {0x00e0ffff, "second line BPG offset error"},
787312ee5af0SDamon Ding {0x00f0ffff, "non second line BPG offset error"},
787412ee5af0SDamon Ding {0x0100ffff, "PPS ID error"},
787512ee5af0SDamon Ding {0x0110ffff, "bits per pixel (BPP) Error"},
787612ee5af0SDamon Ding {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */
787712ee5af0SDamon Ding
787812ee5af0SDamon Ding {0x01510001, "slice 0 RC buffer model overflow error"},
787912ee5af0SDamon Ding {0x01510002, "slice 1 RC buffer model overflow error"},
788012ee5af0SDamon Ding {0x01510004, "slice 2 RC buffer model overflow error"},
788112ee5af0SDamon Ding {0x01510008, "slice 3 RC buffer model overflow error"},
788212ee5af0SDamon Ding {0x01510010, "slice 4 RC buffer model overflow error"},
788312ee5af0SDamon Ding {0x01510020, "slice 5 RC buffer model overflow error"},
788412ee5af0SDamon Ding {0x01510040, "slice 6 RC buffer model overflow error"},
788512ee5af0SDamon Ding {0x01510080, "slice 7 RC buffer model overflow error"},
788612ee5af0SDamon Ding
788712ee5af0SDamon Ding {0x01610001, "slice 0 RC buffer model underflow error"},
788812ee5af0SDamon Ding {0x01610002, "slice 1 RC buffer model underflow error"},
788912ee5af0SDamon Ding {0x01610004, "slice 2 RC buffer model underflow error"},
789012ee5af0SDamon Ding {0x01610008, "slice 3 RC buffer model underflow error"},
789112ee5af0SDamon Ding {0x01610010, "slice 4 RC buffer model underflow error"},
789212ee5af0SDamon Ding {0x01610020, "slice 5 RC buffer model underflow error"},
789312ee5af0SDamon Ding {0x01610040, "slice 6 RC buffer model underflow error"},
789412ee5af0SDamon Ding {0x01610080, "slice 7 RC buffer model underflow error"},
789512ee5af0SDamon Ding
789612ee5af0SDamon Ding {0xffffffff, "unsuccessful RESET cycle status"},
789712ee5af0SDamon Ding {0x00a0ffff, "ICH full error precision settings error"},
789812ee5af0SDamon Ding {0x0020ffff, "native mode"},
789912ee5af0SDamon Ding };
790012ee5af0SDamon Ding
790112ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = {
790212ee5af0SDamon Ding {0x00000000, "rate buffer status"},
790312ee5af0SDamon Ding {0x00000001, "line buffer status"},
790412ee5af0SDamon Ding {0x00000002, "decoder model status"},
790512ee5af0SDamon Ding {0x00000003, "pixel buffer status"},
790612ee5af0SDamon Ding {0x00000004, "balance fifo buffer status"},
790712ee5af0SDamon Ding {0x00000005, "syntax element fifo status"},
790812ee5af0SDamon Ding };
790912ee5af0SDamon Ding
791012ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = {
791112ee5af0SDamon Ding {
791212ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_8K,
791312ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_8K,
791412ee5af0SDamon Ding .max_slice_num = 8,
791512ee5af0SDamon Ding .max_linebuf_depth = 11,
7916b61227a3SDamon Ding .min_bits_per_pixel = 8,
791712ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src",
791812ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_8k_txp_clk",
791912ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_8k_pxl_clk",
792012ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_8k_cds_clk",
792112ee5af0SDamon Ding },
792212ee5af0SDamon Ding
792312ee5af0SDamon Ding {
792412ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_4K,
792512ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_4K,
792612ee5af0SDamon Ding .max_slice_num = 2,
792712ee5af0SDamon Ding .max_linebuf_depth = 11,
7928b61227a3SDamon Ding .min_bits_per_pixel = 8,
792912ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src",
793012ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_4k_txp_clk",
793112ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_4k_pxl_clk",
793212ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_4k_cds_clk",
793312ee5af0SDamon Ding },
793412ee5af0SDamon Ding };
793512ee5af0SDamon Ding
7936ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = {
7937ecc31b6eSAndy Yan {
7938ee01dbb2SDamon Ding .splice_vp_id = 1,
7939ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT,
7940b890760eSAlgea Cao .pre_scan_max_dly = 54,
7941ecc31b6eSAndy Yan .max_dclk = 600000,
7942ecc31b6eSAndy Yan .max_output = {7680, 4320},
7943ecc31b6eSAndy Yan },
7944ecc31b6eSAndy Yan {
7945ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT,
7946ee01dbb2SDamon Ding .pre_scan_max_dly = 54,
7947ecc31b6eSAndy Yan .max_dclk = 600000,
7948ecc31b6eSAndy Yan .max_output = {4096, 2304},
7949ecc31b6eSAndy Yan },
7950ecc31b6eSAndy Yan {
7951ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT,
7952ecc31b6eSAndy Yan .pre_scan_max_dly = 52,
7953ecc31b6eSAndy Yan .max_dclk = 600000,
7954ecc31b6eSAndy Yan .max_output = {4096, 2304},
7955ecc31b6eSAndy Yan },
7956ecc31b6eSAndy Yan {
7957ecc31b6eSAndy Yan .feature = 0,
7958ecc31b6eSAndy Yan .pre_scan_max_dly = 52,
7959ecc31b6eSAndy Yan .max_dclk = 200000,
7960ecc31b6eSAndy Yan .max_output = {1920, 1080},
7961ecc31b6eSAndy Yan },
7962ecc31b6eSAndy Yan };
7963ecc31b6eSAndy Yan
7964b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = {
7965b6ba80b4SDamon Ding {
7966b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER0,
7967b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0),
7968b6ba80b4SDamon Ding },
7969b6ba80b4SDamon Ding {
7970b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER1,
7971b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1),
7972b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0,
7973b6ba80b4SDamon Ding },
7974b6ba80b4SDamon Ding {
7975b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER2,
7976b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2),
7977b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0,
7978b6ba80b4SDamon Ding },
7979b6ba80b4SDamon Ding {
7980b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER3,
7981b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3),
7982b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0,
7983b6ba80b4SDamon Ding },
7984b6ba80b4SDamon Ding {
7985b6ba80b4SDamon Ding .id = VOP2_PD_ESMART,
7986b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) |
7987b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) |
7988b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART3),
7989b6ba80b4SDamon Ding },
7990b6ba80b4SDamon Ding {
7991b6ba80b4SDamon Ding .id = VOP2_PD_DSC_8K,
7992b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K),
7993b6ba80b4SDamon Ding },
7994b6ba80b4SDamon Ding {
7995b6ba80b4SDamon Ding .id = VOP2_PD_DSC_4K,
7996b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K),
7997b6ba80b4SDamon Ding },
7998b6ba80b4SDamon Ding };
7999b6ba80b4SDamon Ding
80009c7848c3SDamon Ding static const struct vop2_ops rk3588_vop_ops = {
80019c7848c3SDamon Ding .setup_win_dly = rk3568_setup_win_dly,
8002b7195f56SDamon Ding .setup_overlay = rk3568_setup_overlay,
8003ef0607a7SDamon Ding .assign_plane_mask = rk3568_assign_plane_mask,
80049c7848c3SDamon Ding };
80059c7848c3SDamon Ding
8006ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = {
8007ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588,
8008ecc31b6eSAndy Yan .nr_vps = 4,
8009ecc31b6eSAndy Yan .vp_data = rk3588_vp_data,
8010ecc31b6eSAndy Yan .win_data = rk3588_win_data,
8011ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0],
80126fea745cSDamon Ding .plane_mask_base = RK3588_PLANE_MASK_BASE,
8013b6ba80b4SDamon Ding .pd = rk3588_vop_pd_data,
801412ee5af0SDamon Ding .dsc = rk3588_dsc_data,
801512ee5af0SDamon Ding .dsc_error_ecw = dsc_ecw,
801612ee5af0SDamon Ding .dsc_error_buffer_flow = dsc_buffer_flow,
8017ecc31b6eSAndy Yan .nr_layers = 8,
8018ecc31b6eSAndy Yan .nr_mixers = 7,
8019ecc31b6eSAndy Yan .nr_gammas = 4,
8020b6ba80b4SDamon Ding .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data),
802112ee5af0SDamon Ding .nr_dscs = 2,
802212ee5af0SDamon Ding .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw),
802312ee5af0SDamon Ding .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow),
802472388c26SDamon Ding .dump_regs = rk3588_dump_regs,
802572388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs),
80269c7848c3SDamon Ding .ops = &rk3588_vop_ops,
8027ecc31b6eSAndy Yan };
8028ecc31b6eSAndy Yan
8029d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = {
8030*60e6e79dSSandy Huang .reset = rockchip_vop2_reset,
8031d0408543SAndy Yan .preinit = rockchip_vop2_preinit,
8032d0408543SAndy Yan .prepare = rockchip_vop2_prepare,
8033d0408543SAndy Yan .init = rockchip_vop2_init,
8034d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane,
8035d0408543SAndy Yan .enable = rockchip_vop2_enable,
8036efa01fe4SZhang Yubing .post_enable = rockchip_vop2_post_enable,
8037d0408543SAndy Yan .disable = rockchip_vop2_disable,
8038b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts,
80390675a2a4SDamon Ding .send_mcu_cmd = rockchip_vop2_send_mcu_cmd,
8040820a5c17SDamon Ding .check = rockchip_vop2_check,
804122007755SDamon Ding .mode_valid = rockchip_vop2_mode_valid,
8042b02eb70bSDamon Ding .mode_fixup = rockchip_vop2_mode_fixup,
80434c765862SDamon Ding .plane_check = rockchip_vop2_plane_check,
804472388c26SDamon Ding .regs_dump = rockchip_vop2_regs_dump,
804572388c26SDamon Ding .active_regs_dump = rockchip_vop2_active_regs_dump,
80468e7ef808SDamon Ding .apply_soft_te = rockchip_vop2_apply_soft_te,
8047d0408543SAndy Yan };
8048