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 <clk.h> 21d0408543SAndy Yan #include <asm/arch/clock.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> 26ac500a1fSSandy Huang #include <fixp-arith.h> 27d0408543SAndy Yan #include <syscon.h> 2860e469f5SDamon Ding #include <linux/iopoll.h> 295f1357a2SZhang Yubing #include <dm/uclass-internal.h> 30d0408543SAndy Yan 31d0408543SAndy Yan #include "rockchip_display.h" 32d0408543SAndy Yan #include "rockchip_crtc.h" 33d0408543SAndy Yan #include "rockchip_connector.h" 34d0408543SAndy Yan 35d0408543SAndy Yan /* System registers definition */ 36d0408543SAndy Yan #define RK3568_REG_CFG_DONE 0x000 37d0408543SAndy Yan #define CFG_DONE_EN BIT(15) 38d0408543SAndy Yan 39d0408543SAndy Yan #define RK3568_VERSION_INFO 0x004 40d0408543SAndy Yan #define EN_MASK 1 41d0408543SAndy Yan 4263cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL 0x008 4363cb669fSSandy Huang 446414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL 0x024 456414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT 0 466414e3bcSSandy Huang 47d0408543SAndy Yan #define RK3568_DSP_IF_EN 0x028 48d0408543SAndy Yan #define RGB_EN_SHIFT 0 49ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT 0 50ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT 1 51ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT 8 52d0408543SAndy Yan #define HDMI0_EN_SHIFT 1 53d0408543SAndy Yan #define EDP0_EN_SHIFT 3 54ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT 2 55ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT 3 56d0408543SAndy Yan #define MIPI0_EN_SHIFT 4 57ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT 4 58ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT 5 59ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT 6 60d0408543SAndy Yan #define MIPI1_EN_SHIFT 20 61ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT 7 62d0408543SAndy Yan #define LVDS0_EN_SHIFT 5 63d0408543SAndy Yan #define LVDS1_EN_SHIFT 24 64d0408543SAndy Yan #define BT1120_EN_SHIFT 6 65d0408543SAndy Yan #define BT656_EN_SHIFT 7 66d0408543SAndy Yan #define IF_MUX_MASK 3 67d0408543SAndy Yan #define RGB_MUX_SHIFT 8 68d0408543SAndy Yan #define HDMI0_MUX_SHIFT 10 69ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT 12 70ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT 14 71d0408543SAndy Yan #define EDP0_MUX_SHIFT 14 72ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT 16 73ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT 18 74d0408543SAndy Yan #define MIPI0_MUX_SHIFT 16 75ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT 20 76d0408543SAndy Yan #define MIPI1_MUX_SHIFT 21 7711f53190SSandy Huang #define LVDS0_MUX_SHIFT 18 78d0408543SAndy Yan #define LVDS1_MUX_SHIFT 25 79d0408543SAndy Yan 80d0408543SAndy Yan #define RK3568_DSP_IF_CTRL 0x02c 81d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT 0 82d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 83d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT 2 8441874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT 10 8541874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11 8641874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12 8741874944SGuochun Huang 88d0408543SAndy Yan #define RK3568_DSP_IF_POL 0x030 89d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_MASK 1 90d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT 28 91d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 92d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT 15 93d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 9410ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 9510ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT 4 96ecc31b6eSAndy Yan 97ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT 8 98ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT 12 99ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK 0x7 100ecc31b6eSAndy Yan 101d0408543SAndy Yan #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT 3 102ecc31b6eSAndy Yan 103ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT 16 104ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 105ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT 20 106ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 107ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT 24 108ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT 26 109ecc31b6eSAndy Yan 110feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN 0x50 111feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT 0 1121147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL 0x58 1131147facaSSandy Huang #define GAMMA_PORT_SEL_MASK 0x3 1141147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT 0 115ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT 16 1161147facaSSandy Huang 117ecc31b6eSAndy Yan #define RK3568_SYS_PD_CTRL 0x034 118d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG 0x70 119d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG 0x74 120d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG 0x78 121d0408543SAndy Yan #define RK3568_SYS0_INT_EN 0x80 122d0408543SAndy Yan #define RK3568_SYS0_INT_CLR 0x84 123d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS 0x88 124d0408543SAndy Yan #define RK3568_SYS1_INT_EN 0x90 125d0408543SAndy Yan #define RK3568_SYS1_INT_CLR 0x94 126d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS 0x98 127d0408543SAndy Yan #define RK3568_VP0_INT_EN 0xA0 128d0408543SAndy Yan #define RK3568_VP0_INT_CLR 0xA4 129d0408543SAndy Yan #define RK3568_VP0_INT_STATUS 0xA8 130d0408543SAndy Yan #define RK3568_VP1_INT_EN 0xB0 131d0408543SAndy Yan #define RK3568_VP1_INT_CLR 0xB4 132d0408543SAndy Yan #define RK3568_VP1_INT_STATUS 0xB8 133d0408543SAndy Yan #define RK3568_VP2_INT_EN 0xC0 134d0408543SAndy Yan #define RK3568_VP2_INT_CLR 0xC4 135d0408543SAndy Yan #define RK3568_VP2_INT_STATUS 0xC8 13660e469f5SDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT 0 13760e469f5SDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT 1 13860e469f5SDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT 2 13960e469f5SDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT 3 140b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT 5 141b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT 6 14260e469f5SDamon Ding #define RK3588_ESMART_PD_EN_SHIFT 7 14360e469f5SDamon Ding 14460e469f5SDamon Ding #define RK3568_SYS_STATUS0 0x60 14560e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8 14660e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9 14760e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10 14860e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11 149b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT 13 150b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT 14 15160e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT 15 152d0408543SAndy Yan 15366724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0 0x70 15466724b9cSDamon Ding #define LINE_FLAG_NUM_MASK 0x1fff 15566724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0 15666724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16 15766724b9cSDamon Ding 15812ee5af0SDamon Ding /* DSC CTRL registers definition */ 15912ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL 0x200 16012ee5af0SDamon Ding #define DSC_PORT_SEL_MASK 0x3 16112ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT 0 16212ee5af0SDamon Ding #define DSC_MAN_MODE_MASK 0x1 16312ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT 2 16412ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK 0x3 16512ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT 4 16612ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK 0x3 16712ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT 6 16812ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK 0x1 16912ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT 8 17012ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK 0x3 17112ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT 12 17212ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK 0x3 17312ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT 14 17412ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK 0x1 17512ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT 16 17612ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT 17 17712ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT 18 17812ee5af0SDamon Ding 17912ee5af0SDamon Ding #define RK3588_DSC_8K_RST 0x204 18012ee5af0SDamon Ding #define RST_DEASSERT_MASK 0x1 18112ee5af0SDamon Ding #define RST_DEASSERT_SHIFT 0 18212ee5af0SDamon Ding 18312ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE 0x208 18412ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT 0 18512ee5af0SDamon Ding 18612ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY 0x20C 18712ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK 0xffff 18812ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT 0 18912ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16 19012ee5af0SDamon Ding 19112ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END 0x210 19212ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK 0xffffffff 19312ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT 0 19412ee5af0SDamon Ding 19512ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END 0x214 19612ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK 0xffffffff 19712ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT 0 19812ee5af0SDamon Ding 19912ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END 0x218 20012ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK 0xffffffff 20112ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT 0 20212ee5af0SDamon Ding 20312ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END 0x21C 20412ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK 0xffffffff 20512ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT 0 20612ee5af0SDamon Ding 20712ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS 0x220 20812ee5af0SDamon Ding 20963cb669fSSandy Huang /* Overlay registers definition */ 21063cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600 211ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK 0x1 212ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT 0 21363cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 21463cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604 21563cb669fSSandy Huang #define LAYER_SEL_MASK 0xf 21663cb669fSSandy Huang 21763cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608 21863cb669fSSandy Huang #define PORT_MUX_MASK 0xf 21963cb669fSSandy Huang #define PORT_MUX_SHIFT 0 22063cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3 22163cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16 22263cb669fSSandy Huang 22363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 22463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 22563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 22663cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 22763cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 22863cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654 22963cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 23063cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 23163cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 23263cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 23363cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 23463cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 23563cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0 23663cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff 23763cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24 23863cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4 23963cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8 24063cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0 24163cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8 24263cb669fSSandy Huang 243d0408543SAndy Yan /* Video Port registers definition */ 244d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00 245d0408543SAndy Yan #define OUT_MODE_MASK 0xf 246d0408543SAndy Yan #define OUT_MODE_SHIFT 0 24710ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f 24810ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8 24965747de7SDamon Ding #define DSP_BG_SWAP 0x1 25065747de7SDamon Ding #define DSP_RB_SWAP 0x2 25165747de7SDamon Ding #define DSP_RG_SWAP 0x4 25265747de7SDamon Ding #define DSP_DELTA_SWAP 0x8 25310ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4 254d0408543SAndy Yan #define P2I_EN_SHIFT 5 2557a20be36SSandy Huang #define DSP_FILED_POL 6 256d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7 25710ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15 258d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16 259d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17 2601147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28 2611147facaSSandy Huang 262d0408543SAndy Yan #define STANDBY_EN_SHIFT 31 263d0408543SAndy Yan 264d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04 26510ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4 26610ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3 267d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20 268d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21 26941874944SGuochun Huang #define EDPI_TE_EN 28 27041874944SGuochun Huang #define EDPI_WMS_HOLD_EN 30 27141874944SGuochun Huang #define EDPI_WMS_FS 31 27241874944SGuochun Huang 273d0408543SAndy Yan 274d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 2756414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10 2766414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0 2776414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2 2786414e3bcSSandy Huang 279ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C 280ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0 281ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2 282ecc31b6eSAndy Yan 2836414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20 2846414e3bcSSandy Huang 285d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C 286d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 287d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 288d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 289d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 290d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40 291d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 292d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 293d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 294d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 295d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54 296d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 297d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 298d0408543SAndy Yan 299ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60 300ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0 301ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1 302ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 303ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 304ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4 305ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1 306ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 307ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 308ac500a1fSSandy Huang 309ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64 310ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0 311ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF 312ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8 313ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF 314ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20 315ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF 316ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30 317ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3 318ac500a1fSSandy Huang 319ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68 320ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0 321ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF 322ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16 323ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF 324ac500a1fSSandy Huang 325ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C 326ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31 327ac500a1fSSandy Huang #define BCSH_EN_MASK 1 328ac500a1fSSandy Huang 329d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00 330d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04 331d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 332d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 333d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 334d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 335d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 336d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40 337d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34 338d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38 339d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 340d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 341d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 342d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 343d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54 344d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 345d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 346d0408543SAndy Yan 347d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00 348d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04 349d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 350d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 351d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 352d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 353d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 354d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40 355d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34 356d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38 357d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 358d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 359d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 360d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 361d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54 362d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 363d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 364d0408543SAndy Yan 365d0408543SAndy Yan /* Cluster0 register definition */ 366d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 367ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8 368ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9 369ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10 370ecc31b6eSAndy Yan #define CLUSTER_YRGB_XSCL_MODE_SHIFT 12 371ecc31b6eSAndy Yan #define CLUSTER_YRGB_YSCL_MODE_SHIFT 14 372d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 373ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28 374ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29 375a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008 376a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK 0x1f 377a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT 0 378a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK 0x1f 379a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT 5 380a33b790fSDamon Ding 381d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 382d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 383d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018 384d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 385d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 386d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 387d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 388d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 389d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 390d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 391d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 392d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 393d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 394d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 395d0408543SAndy Yan 396d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 397d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 398d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 399d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 400d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098 401d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 402d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 403d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 404d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 405d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 406d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 407d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 408d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 409d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 410d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 411d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 412d0408543SAndy Yan 413d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100 414ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0 415a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK 0x1 416a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT 13 417d0408543SAndy Yan 418d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 419d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 420d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 421d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 422d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218 423d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 424d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 425d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 426d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 427d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 428d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 429d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 430d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 431d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 432d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 433d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 434d0408543SAndy Yan 435d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 436d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 437d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 438d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 439d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298 440d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 441d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 442d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 443d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 444d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 445d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 446d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 447d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 448d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 449d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 450d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 451d0408543SAndy Yan 452d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300 453d0408543SAndy Yan 454d0408543SAndy Yan /* Esmart register definition */ 455d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800 45610ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1 45710ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2 45810ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3 459d0408543SAndy Yan 460d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804 461a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK 0x1f 462a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT 4 463a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK 0x1f 464a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT 12 465d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31 466a33b790fSDamon Ding 467a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL 0x1808 468a33b790fSDamon Ding #define ESMART_AXI_ID_MASK 0x1 469a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT 1 470a33b790fSDamon Ding 471d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810 47210ee9f5bSAlgea Cao #define REGION0_RB_SWAP_SHIFT 14 473d0408543SAndy Yan #define WIN_EN_SHIFT 0 474d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f 475d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1 476d0408543SAndy Yan 477d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 478d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 479d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C 480d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 481d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 482d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 483d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 4843e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3 4853e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0 4863e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3 4873e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2 4883e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3 4893e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4 4903e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3 4913e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6 4923e39a5a1SSandy Huang 493d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 494d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 495d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 496d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840 4973e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1 4983e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8 4993e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1 5003e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9 5013e39a5a1SSandy Huang 502d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 503d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 504d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C 505d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 506d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 507d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 508d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 509d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 510d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 511d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 512d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870 513d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 514d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 515d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C 516d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 517d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 518d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 519d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 520d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 521d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 522d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 523d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0 524d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 525d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 526d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC 527d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 528d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 529d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 530d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 531d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 532d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 533d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 534d0408543SAndy Yan 535d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00 536d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04 537d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10 538d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 539d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 540d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C 541d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 542d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 543d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 544d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 545d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 546d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 547d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 548d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40 549d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 550d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 551d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C 552d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 553d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 554d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 555d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 556d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 557d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 558d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 559d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70 560d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 561d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 562d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C 563d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 564d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 565d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 566d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 567d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 568d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 569d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 570d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 571d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 572d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 573d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC 574d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 575d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 576d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 577d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 578d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 579d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 580d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 581d0408543SAndy Yan 582d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00 583d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04 584d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10 585d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 586d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 587d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C 588d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 589d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 590d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 591d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 592d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 593d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 594d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 595d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40 596d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 597d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 598d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C 599d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 600d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 601d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 602d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 603d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 604d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 605d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 606d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70 607d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 608d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 609d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C 610d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 611d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 612d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 613d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 614d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 615d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 616d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 617d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0 618d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 619d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 620d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC 621d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 622d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 623d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 624d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 625d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 626d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 627d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 628d0408543SAndy Yan 629d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00 630d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04 631d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10 632d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 633d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 634d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C 635d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 636d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 637d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 638d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 639d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 640d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 641d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 642d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40 643d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 644d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 645d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C 646d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 647d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 648d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 649d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 650d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 651d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 652d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 653d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70 654d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 655d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 656d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C 657d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 658d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 659d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 660d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 661d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 662d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 663d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 664d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0 665d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 666d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 667d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC 668d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 669d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 670d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 671d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 672d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 673d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 674d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 675d0408543SAndy Yan 67612ee5af0SDamon Ding /* DSC 8K/4K register definition */ 67712ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3 0x4000 67812ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0 0x40A0 67912ee5af0SDamon Ding #define DSC_EN_SHIFT 0 68012ee5af0SDamon Ding #define DSC_RBIT_SHIFT 2 68112ee5af0SDamon Ding #define DSC_RBYT_SHIFT 3 68212ee5af0SDamon Ding #define DSC_FLAL_SHIFT 4 68312ee5af0SDamon Ding #define DSC_MER_SHIFT 5 68412ee5af0SDamon Ding #define DSC_EPB_SHIFT 6 68512ee5af0SDamon Ding #define DSC_EPL_SHIFT 7 68612ee5af0SDamon Ding #define DSC_NSLC_SHIFT 16 68712ee5af0SDamon Ding #define DSC_SBO_SHIFT 28 68812ee5af0SDamon Ding #define DSC_IFEP_SHIFT 29 68912ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT 31 69012ee5af0SDamon Ding 69112ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1 0x40A4 69212ee5af0SDamon Ding #define RK3588_DSC_8K_STS0 0x40A8 69312ee5af0SDamon Ding #define RK3588_DSC_8K_ERS 0x40C4 69412ee5af0SDamon Ding 69512ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3 0x4100 69612ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0 0x41A0 69712ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1 0x41A4 69812ee5af0SDamon Ding #define RK3588_DSC_4K_STS0 0x41A8 69912ee5af0SDamon Ding #define RK3588_DSC_4K_ERS 0x41C4 70012ee5af0SDamon Ding 701d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0 702d0408543SAndy Yan 70352ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364 70452ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1 70552ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2 70652ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3 70752ee18acSSandy Huang 708ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008 709ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 710ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 711ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 712ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 713ecc31b6eSAndy Yan 714b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0 0x0000 715b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK 0x3 716b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT 5 717b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT 7 718b890760eSAlgea Cao 71960e469f5SDamon Ding #define RK3588_PMU_BISR_CON3 0x20C 72060e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 72160e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 72260e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 72360e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 724b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13 725b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14 72660e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 72760e469f5SDamon Ding 72860e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5 0x294 72960e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 73060e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 73160e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 73260e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 733b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13 734b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14 73560e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 73660e469f5SDamon Ding 737d0408543SAndy Yan #define VOP2_LAYER_MAX 8 73863cb669fSSandy Huang 739ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH 4096 740ee01dbb2SDamon Ding 74163cb669fSSandy Huang #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 742d0408543SAndy Yan 743631ee99aSZhang Yubing /* KHz */ 744631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE 600000 745631ee99aSZhang Yubing 746b6ba80b4SDamon Ding /* 747b6ba80b4SDamon Ding * vop2 dsc id 748b6ba80b4SDamon Ding */ 749b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K 0 750b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K 1 751b6ba80b4SDamon Ding 752b6ba80b4SDamon Ding /* 753b6ba80b4SDamon Ding * vop2 internal power domain id, 754b6ba80b4SDamon Ding * should be all none zero, 0 will be 755b6ba80b4SDamon Ding * treat as invalid; 756b6ba80b4SDamon Ding */ 757b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0 BIT(0) 758b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1 BIT(1) 759b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2 BIT(2) 760b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3 BIT(3) 761b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K BIT(5) 762b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K BIT(6) 763b6ba80b4SDamon Ding #define VOP2_PD_ESMART BIT(7) 764b6ba80b4SDamon Ding 76510ee9f5bSAlgea Cao enum vop2_csc_format { 76610ee9f5bSAlgea Cao CSC_BT601L, 76710ee9f5bSAlgea Cao CSC_BT709L, 76810ee9f5bSAlgea Cao CSC_BT601F, 76910ee9f5bSAlgea Cao CSC_BT2020, 77010ee9f5bSAlgea Cao }; 77110ee9f5bSAlgea Cao 77210ee9f5bSAlgea Cao enum vop2_pol { 77310ee9f5bSAlgea Cao HSYNC_POSITIVE = 0, 77410ee9f5bSAlgea Cao VSYNC_POSITIVE = 1, 77510ee9f5bSAlgea Cao DEN_NEGATIVE = 2, 77610ee9f5bSAlgea Cao DCLK_INVERT = 3 77710ee9f5bSAlgea Cao }; 77810ee9f5bSAlgea Cao 779ac500a1fSSandy Huang enum vop2_bcsh_out_mode { 780ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK, 781ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE, 782ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR, 783ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, 784ac500a1fSSandy Huang }; 785ac500a1fSSandy Huang 786d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \ 787d0408543SAndy Yan { \ 788d0408543SAndy Yan .offset = off, \ 789d0408543SAndy Yan .mask = _mask, \ 790d0408543SAndy Yan .shift = _shift, \ 791d0408543SAndy Yan .write_mask = _write_mask, \ 792d0408543SAndy Yan } 793d0408543SAndy Yan 794d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \ 795d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false) 796d0408543SAndy Yan enum dither_down_mode { 797d0408543SAndy Yan RGB888_TO_RGB565 = 0x0, 798d0408543SAndy Yan RGB888_TO_RGB666 = 0x1 799d0408543SAndy Yan }; 800d0408543SAndy Yan 801d0408543SAndy Yan enum vop2_video_ports_id { 802d0408543SAndy Yan VOP2_VP0, 803d0408543SAndy Yan VOP2_VP1, 804d0408543SAndy Yan VOP2_VP2, 805d0408543SAndy Yan VOP2_VP3, 806d0408543SAndy Yan VOP2_VP_MAX, 807d0408543SAndy Yan }; 808d0408543SAndy Yan 809ee008497SSandy Huang enum vop2_layer_type { 810ee008497SSandy Huang CLUSTER_LAYER = 0, 811ee008497SSandy Huang ESMART_LAYER = 1, 812ee008497SSandy Huang SMART_LAYER = 2, 813ee008497SSandy Huang }; 814ee008497SSandy Huang 815b0989546SSandy Huang /* This define must same with kernel win phy id */ 816b0989546SSandy Huang enum vop2_layer_phy_id { 817b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0, 818b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, 819b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0, 820b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 821b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 822b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 823b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2, 824b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3, 825b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2, 826b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3, 827ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX, 828d0408543SAndy Yan }; 829d0408543SAndy Yan 8303e39a5a1SSandy Huang enum vop2_scale_up_mode { 8313e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR, 8323e39a5a1SSandy Huang VOP2_SCALE_UP_BIL, 8333e39a5a1SSandy Huang VOP2_SCALE_UP_BIC, 8343e39a5a1SSandy Huang }; 8353e39a5a1SSandy Huang 8363e39a5a1SSandy Huang enum vop2_scale_down_mode { 8373e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR, 8383e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL, 8393e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG, 8403e39a5a1SSandy Huang }; 8413e39a5a1SSandy Huang 8423e39a5a1SSandy Huang enum scale_mode { 8433e39a5a1SSandy Huang SCALE_NONE = 0x0, 8443e39a5a1SSandy Huang SCALE_UP = 0x1, 8453e39a5a1SSandy Huang SCALE_DOWN = 0x2 8463e39a5a1SSandy Huang }; 8473e39a5a1SSandy Huang 84812ee5af0SDamon Ding enum vop_dsc_interface_mode { 84912ee5af0SDamon Ding VOP_DSC_IF_DISABLE = 0, 85012ee5af0SDamon Ding VOP_DSC_IF_HDMI = 1, 85112ee5af0SDamon Ding VOP_DSC_IF_MIPI_DS_MODE = 2, 85212ee5af0SDamon Ding VOP_DSC_IF_MIPI_VIDEO_MODE = 3, 85312ee5af0SDamon Ding }; 85412ee5af0SDamon Ding 8553e39a5a1SSandy Huang struct vop2_layer { 8563e39a5a1SSandy Huang u8 id; 8573e39a5a1SSandy Huang /** 8583e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected. 8593e39a5a1SSandy Huang * Every layer must make sure to select different 8603e39a5a1SSandy Huang * windows of others. 8613e39a5a1SSandy Huang */ 8623e39a5a1SSandy Huang u8 win_phys_id; 8633e39a5a1SSandy Huang }; 8643e39a5a1SSandy Huang 86560e469f5SDamon Ding struct vop2_power_domain_data { 866b6ba80b4SDamon Ding u8 id; 867b6ba80b4SDamon Ding u8 parent_id; 868b6ba80b4SDamon Ding /* 869b6ba80b4SDamon Ding * @module_id_mask: module id of which module this power domain is belongs to. 870b6ba80b4SDamon Ding * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 871b6ba80b4SDamon Ding */ 872b6ba80b4SDamon Ding u32 module_id_mask; 87360e469f5SDamon Ding }; 87460e469f5SDamon Ding 875b0989546SSandy Huang struct vop2_win_data { 876b0989546SSandy Huang char *name; 87763cb669fSSandy Huang u8 phys_id; 878ecc31b6eSAndy Yan enum vop2_layer_type type; 879b0989546SSandy Huang u8 win_sel_port_offset; 880b0989546SSandy Huang u8 layer_sel_win_id; 881a33b790fSDamon Ding u8 axi_id; 882a33b790fSDamon Ding u8 axi_uv_id; 883a33b790fSDamon Ding u8 axi_yrgb_id; 884ee01dbb2SDamon Ding u8 splice_win_id; 885b6ba80b4SDamon Ding u8 pd_id; 886b0989546SSandy Huang u32 reg_offset; 887ee01dbb2SDamon Ding bool splice_mode_right; 88863cb669fSSandy Huang }; 88963cb669fSSandy Huang 89063cb669fSSandy Huang struct vop2_vp_data { 89163cb669fSSandy Huang u32 feature; 89263cb669fSSandy Huang u8 pre_scan_max_dly; 893ee01dbb2SDamon Ding u8 splice_vp_id; 89463cb669fSSandy Huang struct vop_rect max_output; 895ecc31b6eSAndy Yan u32 max_dclk; 896d0408543SAndy Yan }; 897d0408543SAndy Yan 898ee008497SSandy Huang struct vop2_plane_table { 899ee008497SSandy Huang enum vop2_layer_phy_id plane_id; 900ee008497SSandy Huang enum vop2_layer_type plane_type; 901ee008497SSandy Huang }; 902ee008497SSandy Huang 903b0989546SSandy Huang struct vop2_vp_plane_mask { 904b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */ 905b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */ 906b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 907b0989546SSandy Huang u32 plane_mask; 908ee008497SSandy Huang int cursor_plane_id; 909b0989546SSandy Huang }; 910b0989546SSandy Huang 91112ee5af0SDamon Ding struct vop2_dsc_data { 91212ee5af0SDamon Ding u8 id; 91312ee5af0SDamon Ding u8 pd_id; 91412ee5af0SDamon Ding u8 max_slice_num; 91512ee5af0SDamon Ding u8 max_linebuf_depth; /* used to generate the bitstream */ 91612ee5af0SDamon Ding u8 min_bits_per_pixel; /* bit num after encoder compress */ 91712ee5af0SDamon Ding const char *dsc_txp_clk_src_name; 91812ee5af0SDamon Ding const char *dsc_txp_clk_name; 91912ee5af0SDamon Ding const char *dsc_pxl_clk_name; 92012ee5af0SDamon Ding const char *dsc_cds_clk_name; 92112ee5af0SDamon Ding }; 92212ee5af0SDamon Ding 92312ee5af0SDamon Ding struct dsc_error_info { 92412ee5af0SDamon Ding u32 dsc_error_val; 92512ee5af0SDamon Ding char dsc_error_info[50]; 92612ee5af0SDamon Ding }; 92712ee5af0SDamon Ding 928d0408543SAndy Yan struct vop2_data { 92952ee18acSSandy Huang u32 version; 93063cb669fSSandy Huang struct vop2_vp_data *vp_data; 931b0989546SSandy Huang struct vop2_win_data *win_data; 932b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 933ee008497SSandy Huang struct vop2_plane_table *plane_table; 934b6ba80b4SDamon Ding struct vop2_power_domain_data *pd; 93512ee5af0SDamon Ding struct vop2_dsc_data *dsc; 93612ee5af0SDamon Ding struct dsc_error_info *dsc_error_ecw; 93712ee5af0SDamon Ding struct dsc_error_info *dsc_error_buffer_flow; 93863cb669fSSandy Huang u8 nr_vps; 93963cb669fSSandy Huang u8 nr_layers; 94063cb669fSSandy Huang u8 nr_mixers; 9411147facaSSandy Huang u8 nr_gammas; 942b6ba80b4SDamon Ding u8 nr_pd; 94312ee5af0SDamon Ding u8 nr_dscs; 94412ee5af0SDamon Ding u8 nr_dsc_ecw; 94512ee5af0SDamon Ding u8 nr_dsc_buffer_flow; 946ecc31b6eSAndy Yan u32 reg_len; 947d0408543SAndy Yan }; 948d0408543SAndy Yan 949d0408543SAndy Yan struct vop2 { 950d0408543SAndy Yan u32 *regsbak; 951d0408543SAndy Yan void *regs; 952d0408543SAndy Yan void *grf; 953ecc31b6eSAndy Yan void *vop_grf; 954ecc31b6eSAndy Yan void *vo1_grf; 95560e469f5SDamon Ding void *sys_pmu; 95652ee18acSSandy Huang u32 reg_len; 95752ee18acSSandy Huang u32 version; 95863cb669fSSandy Huang bool global_init; 959d0408543SAndy Yan const struct vop2_data *data; 960b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 961d0408543SAndy Yan }; 962d0408543SAndy Yan 963d0408543SAndy Yan static struct vop2 *rockchip_vop2; 9643e39a5a1SSandy Huang /* 9653e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12; 9663e39a5a1SSandy Huang * avg_sd_factor: 9673e39a5a1SSandy Huang * bli_su_factor: 9683e39a5a1SSandy Huang * bic_su_factor: 9693e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16; 9703e39a5a1SSandy Huang * 9713e39a5a1SSandy Huang * gt2 enable: dst get one line from two line of the src 9723e39a5a1SSandy Huang * gt4 enable: dst get one line from four line of the src. 9733e39a5a1SSandy Huang * 9743e39a5a1SSandy Huang */ 9753e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 9763e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 9773e39a5a1SSandy Huang 9783e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 9793e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1)) 9803e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 9813e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1)) 9823e39a5a1SSandy Huang 9833e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode, 9843e39a5a1SSandy Huang int32_t filter_mode, 9853e39a5a1SSandy Huang uint32_t src, uint32_t dst) 9863e39a5a1SSandy Huang { 9873e39a5a1SSandy Huang uint32_t fac = 0; 9883e39a5a1SSandy Huang int i = 0; 9893e39a5a1SSandy Huang 9903e39a5a1SSandy Huang if (mode == SCALE_NONE) 9913e39a5a1SSandy Huang return 0; 9923e39a5a1SSandy Huang 9933e39a5a1SSandy Huang /* 9943e39a5a1SSandy Huang * A workaround to avoid zero div. 9953e39a5a1SSandy Huang */ 9963e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) { 9973e39a5a1SSandy Huang dst = dst + 1; 9983e39a5a1SSandy Huang src = src + 1; 9993e39a5a1SSandy Huang } 10003e39a5a1SSandy Huang 10013e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 10023e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst); 10033e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 10043e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 10053e39a5a1SSandy Huang break; 10063e39a5a1SSandy Huang fac -= 1; 10073e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 10083e39a5a1SSandy Huang } 10093e39a5a1SSandy Huang } else { 10103e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst); 10113e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 10123e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 10133e39a5a1SSandy Huang break; 10143e39a5a1SSandy Huang fac -= 1; 10153e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 10163e39a5a1SSandy Huang } 10173e39a5a1SSandy Huang } 10183e39a5a1SSandy Huang 10193e39a5a1SSandy Huang return fac; 10203e39a5a1SSandy Huang } 10213e39a5a1SSandy Huang 10223e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst) 10233e39a5a1SSandy Huang { 10243e39a5a1SSandy Huang if (src < dst) 10253e39a5a1SSandy Huang return SCALE_UP; 10263e39a5a1SSandy Huang else if (src > dst) 10273e39a5a1SSandy Huang return SCALE_DOWN; 10283e39a5a1SSandy Huang 10293e39a5a1SSandy Huang return SCALE_NONE; 10303e39a5a1SSandy Huang } 1031d0408543SAndy Yan 1032ecc31b6eSAndy Yan static u8 rk3588_vop2_vp_primary_plane_order[VOP2_VP_MAX] = { 1033ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART0, 1034ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART1, 1035ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART2, 1036ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART3, 1037ecc31b6eSAndy Yan }; 1038ecc31b6eSAndy Yan 1039ecc31b6eSAndy Yan static u8 rk3568_vop2_vp_primary_plane_order[VOP2_VP_MAX] = { 1040b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 1041b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 1042b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 1043b0989546SSandy Huang }; 1044b0989546SSandy Huang 1045ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x) 1046ac500a1fSSandy Huang { 1047ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 1048ac500a1fSSandy Huang } 1049ac500a1fSSandy Huang 1050b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 1051b0989546SSandy Huang { 1052b0989546SSandy Huang int i = 0; 1053ecc31b6eSAndy Yan u8 *vop2_vp_primary_plane_order; 1054ecc31b6eSAndy Yan u8 default_primary_plane; 1055ecc31b6eSAndy Yan 1056ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) { 1057ecc31b6eSAndy Yan vop2_vp_primary_plane_order = rk3588_vop2_vp_primary_plane_order; 1058ecc31b6eSAndy Yan default_primary_plane = ROCKCHIP_VOP2_ESMART0; 1059ecc31b6eSAndy Yan } else { 1060ecc31b6eSAndy Yan vop2_vp_primary_plane_order = rk3568_vop2_vp_primary_plane_order; 1061ecc31b6eSAndy Yan default_primary_plane = ROCKCHIP_VOP2_SMART0; 1062ecc31b6eSAndy Yan } 1063b0989546SSandy Huang 1064b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1065b0989546SSandy Huang if (plane_mask & BIT(vop2_vp_primary_plane_order[i])) 1066b0989546SSandy Huang return vop2_vp_primary_plane_order[i]; 1067b0989546SSandy Huang } 1068b0989546SSandy Huang 1069ecc31b6eSAndy Yan return default_primary_plane; 1070b0989546SSandy Huang } 1071b0989546SSandy Huang 107263cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift) 1073d0408543SAndy Yan { 1074d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 1075d0408543SAndy Yan } 1076d0408543SAndy Yan 107763cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst) 1078d0408543SAndy Yan { 1079d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1); 1080d0408543SAndy Yan } 1081d0408543SAndy Yan 108252ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 1083d0408543SAndy Yan { 1084d0408543SAndy Yan writel(v, vop2->regs + offset); 1085d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1086d0408543SAndy Yan } 1087d0408543SAndy Yan 108852ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 1089d0408543SAndy Yan { 1090d0408543SAndy Yan return readl(vop2->regs + offset); 1091d0408543SAndy Yan } 1092d0408543SAndy Yan 109352ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 109452ee18acSSandy Huang u32 mask, u32 shift, u32 v, 1095d0408543SAndy Yan bool write_mask) 1096d0408543SAndy Yan { 1097d0408543SAndy Yan if (!mask) 1098d0408543SAndy Yan return; 1099d0408543SAndy Yan 1100d0408543SAndy Yan if (write_mask) { 1101d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16)); 1102d0408543SAndy Yan } else { 110352ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2]; 1104d0408543SAndy Yan 1105d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 1106d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1107d0408543SAndy Yan } 1108d0408543SAndy Yan 1109d0408543SAndy Yan writel(v, vop2->regs + offset); 1110d0408543SAndy Yan } 1111d0408543SAndy Yan 1112ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 111352ee18acSSandy Huang u32 mask, u32 shift, u32 v) 111452ee18acSSandy Huang { 111552ee18acSSandy Huang u32 val = 0; 111652ee18acSSandy Huang 111752ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16)); 1118ecc31b6eSAndy Yan writel(val, grf_base + offset); 111952ee18acSSandy Huang } 112052ee18acSSandy Huang 112160e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 112260e469f5SDamon Ding u32 mask, u32 shift) 112360e469f5SDamon Ding { 112460e469f5SDamon Ding return (readl(grf_base + offset) >> shift) & mask; 112560e469f5SDamon Ding } 112660e469f5SDamon Ding 11278895aec1SSandy Huang static char* get_output_if_name(u32 output_if, char *name) 11288895aec1SSandy Huang { 11298895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_RGB) 11308895aec1SSandy Huang strcat(name, " RGB"); 11318895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT1120) 11328895aec1SSandy Huang strcat(name, " BT1120"); 11338895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT656) 11348895aec1SSandy Huang strcat(name, " BT656"); 11358895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS0) 11368895aec1SSandy Huang strcat(name, " LVDS0"); 11378895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS1) 11388895aec1SSandy Huang strcat(name, " LVDS1"); 11398895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI0) 11408895aec1SSandy Huang strcat(name, " MIPI0"); 11418895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI1) 11428895aec1SSandy Huang strcat(name, " MIPI1"); 11438895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP0) 11448895aec1SSandy Huang strcat(name, " eDP0"); 11458895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP1) 11468895aec1SSandy Huang strcat(name, " eDP1"); 11478895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP0) 11488895aec1SSandy Huang strcat(name, " DP0"); 11498895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP1) 11508895aec1SSandy Huang strcat(name, " DP1"); 11518895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI0) 11528895aec1SSandy Huang strcat(name, " HDMI0"); 11538895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI1) 11548895aec1SSandy Huang strcat(name, " HDMI1"); 11558895aec1SSandy Huang 11568895aec1SSandy Huang return name; 11578895aec1SSandy Huang } 11588895aec1SSandy Huang 11598895aec1SSandy Huang static char *get_plane_name(int plane_id, char *name) 11608895aec1SSandy Huang { 11618895aec1SSandy Huang switch (plane_id) { 11628895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER0: 11638895aec1SSandy Huang strcat(name, "Cluster0"); 11648895aec1SSandy Huang break; 11658895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER1: 11668895aec1SSandy Huang strcat(name, "Cluster1"); 11678895aec1SSandy Huang break; 11688895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART0: 11698895aec1SSandy Huang strcat(name, "Esmart0"); 11708895aec1SSandy Huang break; 11718895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART1: 11728895aec1SSandy Huang strcat(name, "Esmart1"); 11738895aec1SSandy Huang break; 11748895aec1SSandy Huang case ROCKCHIP_VOP2_SMART0: 11758895aec1SSandy Huang strcat(name, "Smart0"); 11768895aec1SSandy Huang break; 11778895aec1SSandy Huang case ROCKCHIP_VOP2_SMART1: 11788895aec1SSandy Huang strcat(name, "Smart1"); 11798895aec1SSandy Huang break; 11808895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER2: 11818895aec1SSandy Huang strcat(name, "Cluster2"); 11828895aec1SSandy Huang break; 11838895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER3: 11848895aec1SSandy Huang strcat(name, "Cluster3"); 11858895aec1SSandy Huang break; 11868895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART2: 11878895aec1SSandy Huang strcat(name, "Esmart2"); 11888895aec1SSandy Huang break; 11898895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART3: 11908895aec1SSandy Huang strcat(name, "Esmart3"); 11918895aec1SSandy Huang break; 11928895aec1SSandy Huang } 11938895aec1SSandy Huang 11948895aec1SSandy Huang return name; 11958895aec1SSandy Huang } 11968895aec1SSandy Huang 119752ee18acSSandy Huang static bool is_yuv_output(u32 bus_format) 1198d0408543SAndy Yan { 1199d0408543SAndy Yan switch (bus_format) { 1200d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 1201d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 1202d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1203d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1204a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 1205a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 1206a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8: 1207a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8: 1208a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 1209a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 1210a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16: 1211a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16: 1212d0408543SAndy Yan return true; 1213d0408543SAndy Yan default: 1214d0408543SAndy Yan return false; 1215d0408543SAndy Yan } 1216d0408543SAndy Yan } 1217d0408543SAndy Yan 121810ee9f5bSAlgea Cao static int vop2_convert_csc_mode(int csc_mode) 121910ee9f5bSAlgea Cao { 122010ee9f5bSAlgea Cao switch (csc_mode) { 122110ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE170M: 122210ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_M: 122310ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_BG: 122410ee9f5bSAlgea Cao return CSC_BT601L; 122510ee9f5bSAlgea Cao case V4L2_COLORSPACE_REC709: 122610ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE240M: 122710ee9f5bSAlgea Cao case V4L2_COLORSPACE_DEFAULT: 122810ee9f5bSAlgea Cao return CSC_BT709L; 122910ee9f5bSAlgea Cao case V4L2_COLORSPACE_JPEG: 123010ee9f5bSAlgea Cao return CSC_BT601F; 123110ee9f5bSAlgea Cao case V4L2_COLORSPACE_BT2020: 123210ee9f5bSAlgea Cao return CSC_BT2020; 123310ee9f5bSAlgea Cao default: 123410ee9f5bSAlgea Cao return CSC_BT709L; 123510ee9f5bSAlgea Cao } 123610ee9f5bSAlgea Cao } 123710ee9f5bSAlgea Cao 1238b0989546SSandy Huang static bool is_uv_swap(u32 bus_format, u32 output_mode) 1239d0408543SAndy Yan { 1240d0408543SAndy Yan /* 1241d0408543SAndy Yan * FIXME: 1242d0408543SAndy Yan * 1243d0408543SAndy Yan * There is no media type for YUV444 output, 1244d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on 1245d0408543SAndy Yan * yuv format. 1246d0408543SAndy Yan * 1247d0408543SAndy Yan * From H/W testing, YUV444 mode need a rb swap. 1248d0408543SAndy Yan */ 12493e59c137SSandy Huang if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || 12503e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || 12513e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || 12523e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || 12533e59c137SSandy Huang ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1254d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1255d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA || 12563e59c137SSandy Huang output_mode == ROCKCHIP_OUT_MODE_P888))) 1257d0408543SAndy Yan return true; 1258d0408543SAndy Yan else 1259d0408543SAndy Yan return false; 1260d0408543SAndy Yan } 1261d0408543SAndy Yan 1262b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type) 126363cb669fSSandy Huang { 1264b0989546SSandy Huang switch (output_type) { 1265b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA: 1266b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB: 1267b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV: 1268b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort: 1269b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA: 1270b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown: 1271b0989546SSandy Huang return true; 1272b0989546SSandy Huang default: 1273b0989546SSandy Huang return false; 127463cb669fSSandy Huang } 127563cb669fSSandy Huang } 127663cb669fSSandy Huang 1277ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1278ecc31b6eSAndy Yan { 1279ecc31b6eSAndy Yan int i = 0; 1280ecc31b6eSAndy Yan 1281ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) { 1282ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id) 1283ecc31b6eSAndy Yan return &vop2->data->win_data[i]; 1284ecc31b6eSAndy Yan } 1285ecc31b6eSAndy Yan 1286ecc31b6eSAndy Yan return NULL; 1287ecc31b6eSAndy Yan } 1288ecc31b6eSAndy Yan 1289b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id) 1290b6ba80b4SDamon Ding { 1291b6ba80b4SDamon Ding int i = 0; 1292b6ba80b4SDamon Ding 1293b6ba80b4SDamon Ding for (i = 0; i < vop2->data->nr_pd; i++) { 1294b6ba80b4SDamon Ding if (vop2->data->pd[i].id == pd_id) 1295b6ba80b4SDamon Ding return &vop2->data->pd[i]; 1296b6ba80b4SDamon Ding } 1297b6ba80b4SDamon Ding 1298b6ba80b4SDamon Ding return NULL; 1299b6ba80b4SDamon Ding } 1300b6ba80b4SDamon Ding 13011147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1302d0408543SAndy Yan struct display_state *state) 1303d0408543SAndy Yan { 13041147facaSSandy Huang struct connector_state *conn_state = &state->conn_state; 13051147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state; 13061147facaSSandy Huang struct resource gamma_res; 13071147facaSSandy Huang fdt_size_t lut_size; 13081147facaSSandy Huang int i, lut_len, ret = 0; 13091147facaSSandy Huang u32 *lut_regs; 13101147facaSSandy Huang u32 *lut_val; 13111147facaSSandy Huang u32 r, g, b; 13121147facaSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 13131147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 13141147facaSSandy Huang static int gamma_lut_en_num = 1; 13151147facaSSandy Huang 13161147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) { 13171147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 13181147facaSSandy Huang return 0; 13191147facaSSandy Huang } 13201147facaSSandy Huang 13211147facaSSandy Huang if (!disp_info) 13221147facaSSandy Huang return 0; 13231147facaSSandy Huang 13241147facaSSandy Huang if (!disp_info->gamma_lut_data.size) 13251147facaSSandy Huang return 0; 13261147facaSSandy Huang 13271147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 13281147facaSSandy Huang if (ret) 13291147facaSSandy Huang printf("failed to get gamma lut res\n"); 13301147facaSSandy Huang lut_regs = (u32 *)gamma_res.start; 13311147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1; 13321147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 13331147facaSSandy Huang printf("failed to get gamma lut register\n"); 13341147facaSSandy Huang return 0; 13351147facaSSandy Huang } 13361147facaSSandy Huang lut_len = lut_size / 4; 13371147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) { 13381147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 13391147facaSSandy Huang return 0; 13401147facaSSandy Huang } 13411147facaSSandy Huang lut_val = (u32 *)calloc(1, lut_size); 13421147facaSSandy Huang for (i = 0; i < lut_len; i++) { 13431147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 13441147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 13451147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 13461147facaSSandy Huang 13471147facaSSandy Huang lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 13481147facaSSandy Huang } 13491147facaSSandy Huang 13501147facaSSandy Huang for (i = 0; i < lut_len; i++) 13511147facaSSandy Huang writel(lut_val[i], lut_regs + i); 13521147facaSSandy Huang 13531147facaSSandy Huang vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 13541147facaSSandy Huang GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 13551147facaSSandy Huang cstate->crtc_id , false); 13561147facaSSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 13571147facaSSandy Huang EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 13581147facaSSandy Huang gamma_lut_en_num++; 13591147facaSSandy Huang 1360d0408543SAndy Yan return 0; 1361d0408543SAndy Yan } 1362d0408543SAndy Yan 13636414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 13646414e3bcSSandy Huang struct display_state *state) 13656414e3bcSSandy Huang { 13666414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state; 13676414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state; 13686414e3bcSSandy Huang int i, cubic_lut_len; 13696414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 13706414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 13716414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 13726414e3bcSSandy Huang u32 *cubic_lut_addr; 13736414e3bcSSandy Huang 13746414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 13756414e3bcSSandy Huang return 0; 13766414e3bcSSandy Huang 13776414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size) 13786414e3bcSSandy Huang return 0; 13796414e3bcSSandy Huang 13806414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 13816414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size; 13826414e3bcSSandy Huang 13836414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) { 13846414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 13856414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 13866414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 13876414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 13886414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) + 13896414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 13906414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28); 13916414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 13926414e3bcSSandy Huang *cubic_lut_addr++ = 0; 13936414e3bcSSandy Huang } 13946414e3bcSSandy Huang 13956414e3bcSSandy Huang if (cubic_lut_len % 2) { 13966414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 13976414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 13986414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 13996414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 14006414e3bcSSandy Huang *cubic_lut_addr++ = 0; 14016414e3bcSSandy Huang *cubic_lut_addr = 0; 14026414e3bcSSandy Huang } 14036414e3bcSSandy Huang 14046414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 14056414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id)); 14066414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 14076414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 14086414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 14096414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 14106414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 14116414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 14126414e3bcSSandy Huang 14136414e3bcSSandy Huang return 0; 14146414e3bcSSandy Huang } 14156414e3bcSSandy Huang 1416ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2, 1417ee01dbb2SDamon Ding struct bcsh_state *bcsh_state, int crtc_id) 1418ee01dbb2SDamon Ding { 1419ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1420ee01dbb2SDamon Ding u32 vp_offset = crtc_id * 0x100; 1421ee01dbb2SDamon Ding 1422ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 1423ee01dbb2SDamon Ding BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false); 1424ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 1425ee01dbb2SDamon Ding BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false); 1426ee01dbb2SDamon Ding 1427ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 1428ee01dbb2SDamon Ding BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1429ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 1430ee01dbb2SDamon Ding BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1431ee01dbb2SDamon Ding 1432ee01dbb2SDamon Ding if (!cstate->bcsh_en) { 1433ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1434ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 1435ee01dbb2SDamon Ding return; 1436ee01dbb2SDamon Ding } 1437ee01dbb2SDamon Ding 1438ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1439ee01dbb2SDamon Ding BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 1440ee01dbb2SDamon Ding bcsh_state->brightness, false); 1441ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1442ee01dbb2SDamon Ding BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false); 1443ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1444ee01dbb2SDamon Ding BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 1445ee01dbb2SDamon Ding bcsh_state->saturation * bcsh_state->contrast / 0x100, false); 1446ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1447ee01dbb2SDamon Ding BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false); 1448ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1449ee01dbb2SDamon Ding BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false); 1450ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1451ee01dbb2SDamon Ding BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 1452ee01dbb2SDamon Ding BCSH_OUT_MODE_NORMAL_VIDEO, false); 1453ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1454ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 1455ee01dbb2SDamon Ding } 1456ee01dbb2SDamon Ding 1457ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 1458ac500a1fSSandy Huang { 1459ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state; 1460ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info; 1461ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state; 1462ee01dbb2SDamon Ding struct bcsh_state bcsh_state; 1463ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue; 1464ac500a1fSSandy Huang 1465ac500a1fSSandy Huang if (!conn_state->disp_info) 1466ac500a1fSSandy Huang return; 1467ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info; 1468ac500a1fSSandy Huang if (!bcsh_info) 1469ac500a1fSSandy Huang return; 1470ac500a1fSSandy Huang 1471ac500a1fSSandy Huang if (bcsh_info->brightness != 50 || 1472ac500a1fSSandy Huang bcsh_info->contrast != 50 || 1473ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50) 1474ee01dbb2SDamon Ding cstate->bcsh_en = true; 1475ac500a1fSSandy Huang 1476ee01dbb2SDamon Ding if (cstate->bcsh_en) { 1477ac500a1fSSandy Huang if (!cstate->yuv_overlay) 1478ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1479ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format)) 1480ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1481ac500a1fSSandy Huang } else { 1482ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 1483ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1484ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 1485ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1486ac500a1fSSandy Huang } 1487ac500a1fSSandy Huang 1488ee01dbb2SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space); 1489ac500a1fSSandy Huang 1490ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 1491ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127, 1492ac500a1fSSandy Huang bcsh_info->brightness); 1493ac500a1fSSandy Huang else 1494ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31, 1495ac500a1fSSandy Huang bcsh_info->brightness); 1496ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 1497ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 1498ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 1499ac500a1fSSandy Huang 1500ac500a1fSSandy Huang 1501ac500a1fSSandy Huang /* 1502ac500a1fSSandy Huang * a:[-30~0): 1503ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256; 1504ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1505ac500a1fSSandy Huang * a:[0~30] 1506ac500a1fSSandy Huang * sin_hue = sin(a)*256; 1507ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1508ac500a1fSSandy Huang */ 1509ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23; 1510ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23; 1511ac500a1fSSandy Huang 1512ee01dbb2SDamon Ding bcsh_state.brightness = brightness; 1513ee01dbb2SDamon Ding bcsh_state.contrast = contrast; 1514ee01dbb2SDamon Ding bcsh_state.saturation = saturation; 1515ee01dbb2SDamon Ding bcsh_state.sin_hue = sin_hue; 1516ee01dbb2SDamon Ding bcsh_state.cos_hue = cos_hue; 1517ee01dbb2SDamon Ding 1518ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id); 1519ee01dbb2SDamon Ding if (cstate->splice_mode) 1520ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id); 1521ee01dbb2SDamon Ding } 1522ee01dbb2SDamon Ding 1523ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id) 1524ee01dbb2SDamon Ding { 1525ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 1526ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 1527ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1528ee01dbb2SDamon Ding u32 bg_ovl_dly, bg_dly, pre_scan_dly; 1529ee01dbb2SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 1530ee01dbb2SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1531ee01dbb2SDamon Ding 1532ee01dbb2SDamon Ding bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly; 1533ee01dbb2SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly; 1534ee01dbb2SDamon Ding bg_dly -= bg_ovl_dly; 1535ee01dbb2SDamon Ding 1536ee01dbb2SDamon Ding if (cstate->splice_mode) 1537ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 2) - 1; 1538ee01dbb2SDamon Ding else 1539ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1540ee01dbb2SDamon Ding 1541ee01dbb2SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 1542ee01dbb2SDamon Ding hsync_len = 8; 1543ee01dbb2SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1544ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4, 1545ee01dbb2SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1546ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 1547ac500a1fSSandy Huang } 1548ac500a1fSSandy Huang 1549d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 1550d0408543SAndy Yan { 1551d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 1552d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 155352ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state; 155452ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 1555d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal; 1556d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 1557d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 1558d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay; 1559d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay; 1560d0408543SAndy Yan u16 hsize = 1561d0408543SAndy Yan hdisplay * (conn_state->overscan.left_margin + 1562d0408543SAndy Yan conn_state->overscan.right_margin) / 200; 1563d0408543SAndy Yan u16 vsize = 1564d0408543SAndy Yan vdisplay * (conn_state->overscan.top_margin + 1565d0408543SAndy Yan conn_state->overscan.bottom_margin) / 200; 1566d0408543SAndy Yan u16 hact_end, vact_end; 1567d0408543SAndy Yan u32 val; 1568d0408543SAndy Yan 156974bd8269SSandy Huang hsize = round_down(hsize, 2); 1570d0408543SAndy Yan vsize = round_down(vsize, 2); 1571d0408543SAndy Yan 1572d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 1573d0408543SAndy Yan hact_end = hact_st + hsize; 1574d0408543SAndy Yan val = hact_st << 16; 1575d0408543SAndy Yan val |= hact_end; 1576d0408543SAndy Yan 157752ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 1578d0408543SAndy Yan vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 1579d0408543SAndy Yan vact_end = vact_st + vsize; 1580d0408543SAndy Yan val = vact_st << 16; 1581d0408543SAndy Yan val |= vact_end; 158252ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 1583d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16; 1584d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize); 158552ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 1586d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 1587d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 158852ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 1589d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 1590d0408543SAndy Yan POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 1591d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1592d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 1593d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize; 1594d0408543SAndy Yan 1595d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 159652ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 1597d0408543SAndy Yan } 1598d0408543SAndy Yan 1599ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id); 1600ee01dbb2SDamon Ding if (cstate->splice_mode) 1601ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id); 1602d0408543SAndy Yan } 1603d0408543SAndy Yan 1604d2e91fdcSDamon Ding /* 1605d2e91fdcSDamon Ding * Read VOP internal power domain on/off status. 1606d2e91fdcSDamon Ding * We should query BISR_STS register in PMU for 1607d2e91fdcSDamon Ding * power up/down status when memory repair is enabled. 1608d2e91fdcSDamon Ding * Return value: 1 for power on, 0 for power off; 1609d2e91fdcSDamon Ding */ 161060e469f5SDamon Ding static int vop2_wait_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 161160e469f5SDamon Ding { 161260e469f5SDamon Ding int val = 0; 161360e469f5SDamon Ding int shift = 0; 1614b6ba80b4SDamon Ding int shift_factor = 0; 161560e469f5SDamon Ding bool is_bisr_en = false; 161660e469f5SDamon Ding 1617b6ba80b4SDamon Ding /* 1618b6ba80b4SDamon Ding * The order of pd status bits in BISR_STS register 1619b6ba80b4SDamon Ding * is different from that in VOP SYS_STS register. 1620b6ba80b4SDamon Ding */ 1621b6ba80b4SDamon Ding if (pd_data->id == VOP2_PD_DSC_8K || 1622b6ba80b4SDamon Ding pd_data->id == VOP2_PD_DSC_4K || 1623b6ba80b4SDamon Ding pd_data->id == VOP2_PD_ESMART) 1624b6ba80b4SDamon Ding shift_factor = 1; 1625b6ba80b4SDamon Ding 1626b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor; 1627b6ba80b4SDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift); 162860e469f5SDamon Ding if (is_bisr_en) { 1629b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor; 1630b6ba80b4SDamon Ding 163160e469f5SDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 1632d2e91fdcSDamon Ding ((val >> shift) & 0x1), 50 * 1000); 163360e469f5SDamon Ding } else { 1634b6ba80b4SDamon Ding shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1; 1635b6ba80b4SDamon Ding 163660e469f5SDamon Ding return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 163760e469f5SDamon Ding !((val >> shift) & 0x1), 50 * 1000); 163860e469f5SDamon Ding } 163960e469f5SDamon Ding } 164060e469f5SDamon Ding 1641b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id) 164260e469f5SDamon Ding { 164360e469f5SDamon Ding struct vop2_power_domain_data *pd_data; 164460e469f5SDamon Ding int ret = 0; 164560e469f5SDamon Ding 1646b6ba80b4SDamon Ding if (!pd_id) 1647b6ba80b4SDamon Ding return 0; 1648b6ba80b4SDamon Ding 1649b6ba80b4SDamon Ding pd_data = vop2_find_pd_data_by_id(vop2, pd_id); 1650b6ba80b4SDamon Ding if (!pd_data) { 1651b6ba80b4SDamon Ding printf("can't find pd_data by id\n"); 165260e469f5SDamon Ding return -EINVAL; 165360e469f5SDamon Ding } 16542c66af11SDamon Ding 1655b6ba80b4SDamon Ding if (pd_data->parent_id) { 1656b6ba80b4SDamon Ding ret = vop2_power_domain_on(vop2, pd_data->parent_id); 165760e469f5SDamon Ding if (ret) { 165860e469f5SDamon Ding printf("can't open parent power domain\n"); 165960e469f5SDamon Ding return -EINVAL; 166060e469f5SDamon Ding } 166160e469f5SDamon Ding } 166260e469f5SDamon Ding 1663b6ba80b4SDamon Ding vop2_mask_write(vop2, RK3568_SYS_PD_CTRL, EN_MASK, 1664b6ba80b4SDamon Ding RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_id) - 1, 0, false); 166560e469f5SDamon Ding ret = vop2_wait_power_domain_on(vop2, pd_data); 166660e469f5SDamon Ding if (ret) { 166760e469f5SDamon Ding printf("wait vop2 power domain timeout\n"); 166860e469f5SDamon Ding return ret; 166960e469f5SDamon Ding } 167060e469f5SDamon Ding 167160e469f5SDamon Ding return 0; 167260e469f5SDamon Ding } 167360e469f5SDamon Ding 1674ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2) 1675ecc31b6eSAndy Yan { 1676ecc31b6eSAndy Yan u32 *base = vop2->regs; 1677ecc31b6eSAndy Yan int i = 0; 1678ecc31b6eSAndy Yan 1679ecc31b6eSAndy Yan /* 1680ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 1681ecc31b6eSAndy Yan */ 1682ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++) 1683ecc31b6eSAndy Yan vop2->regsbak[i] = base[i]; 1684ecc31b6eSAndy Yan } 1685ecc31b6eSAndy Yan 1686b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 1687d0408543SAndy Yan { 1688b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 1689b0989546SSandy Huang int i, j, port_mux = 0, total_used_layer = 0; 169063cb669fSSandy Huang u8 shift = 0; 1691b0989546SSandy Huang int layer_phy_id = 0; 1692b0989546SSandy Huang u32 layer_nr = 0; 1693b0989546SSandy Huang struct vop2_win_data *win_data; 1694b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 1695d0408543SAndy Yan 169663cb669fSSandy Huang if (vop2->global_init) 1697d0408543SAndy Yan return; 169863cb669fSSandy Huang 1699b0989546SSandy Huang /* OTP must enable at the first time, otherwise mirror layer register is error */ 170063cb669fSSandy Huang if (soc_is_rk3566()) 170163cb669fSSandy Huang vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 170263cb669fSSandy Huang OTP_WIN_EN_SHIFT, 1, false); 1703b0989546SSandy Huang 1704b0989546SSandy Huang if (cstate->crtc->assign_plane) {/* dts assign plane */ 1705b0989546SSandy Huang u32 plane_mask; 1706b0989546SSandy Huang int primary_plane_id; 1707b0989546SSandy Huang 1708b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1709b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask; 1710b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 1711b0989546SSandy Huang layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 1712b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 17135fc2b656SDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 17145fc2b656SDamon Ding if (primary_plane_id < 0) 1715b0989546SSandy Huang primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 1716b0989546SSandy Huang vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 1717b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 1718b0989546SSandy Huang 1719b0989546SSandy Huang /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 1720b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1721b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 1722b0989546SSandy Huang plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 172363cb669fSSandy Huang } 1724b0989546SSandy Huang } 1725b0989546SSandy Huang } else {/* need soft assign plane mask */ 1726b0989546SSandy Huang /* find the first unplug devices and set it as main display */ 1727b0989546SSandy Huang int main_vp_index = -1; 1728b0989546SSandy Huang int active_vp_num = 0; 1729b0989546SSandy Huang 1730b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1731b0989546SSandy Huang if (cstate->crtc->vps[i].enable) 1732b0989546SSandy Huang active_vp_num++; 1733b0989546SSandy Huang } 1734b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num); 1735b0989546SSandy Huang 1736b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2) 1737b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n"); 1738b0989546SSandy Huang plane_mask = vop2->data->plane_mask; 1739b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 1740b0989546SSandy Huang 1741b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1742b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 1743b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/ 1744b0989546SSandy Huang main_vp_index = i; 1745e007876dSSandy Huang break; 1746b0989546SSandy Huang } 1747b0989546SSandy Huang } 1748b0989546SSandy Huang 1749b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */ 1750b0989546SSandy Huang if (main_vp_index < 0) { 1751b0989546SSandy Huang main_vp_index = 0; 1752b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0]; 1753b0989546SSandy Huang } 1754b0989546SSandy Huang 1755b0989546SSandy Huang j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */ 1756b0989546SSandy Huang 1757b0989546SSandy Huang /* init other display except main display */ 1758b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1759b0989546SSandy Huang if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */ 1760b0989546SSandy Huang continue; 1761b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++]; 1762b0989546SSandy Huang } 1763b0989546SSandy Huang 1764b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */ 1765b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1766b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1767b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1768b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1769b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 1770b0989546SSandy Huang } 1771b0989546SSandy Huang } 1772b0989546SSandy Huang } 1773b0989546SSandy Huang 177460e469f5SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 177560e469f5SDamon Ding rk3588_vop2_regsbak(vop2); 177660e469f5SDamon Ding else 177760e469f5SDamon Ding memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 177860e469f5SDamon Ding 177960e469f5SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 178060e469f5SDamon Ding OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 178160e469f5SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 178260e469f5SDamon Ding IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 178360e469f5SDamon Ding 1784b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1785b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 1786b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 1787b0989546SSandy Huang printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]); 1788b0989546SSandy Huang printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id); 1789b0989546SSandy Huang } 1790b0989546SSandy Huang 1791b0989546SSandy Huang shift = 0; 1792b0989546SSandy Huang /* layer sel win id */ 1793b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1794b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1795b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1796b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1797ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 1798b0989546SSandy Huang vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 1799b0989546SSandy Huang shift, win_data->layer_sel_win_id, false); 1800b0989546SSandy Huang shift += 4; 1801b0989546SSandy Huang } 1802b0989546SSandy Huang } 1803b0989546SSandy Huang 1804b0989546SSandy Huang /* win sel port */ 1805b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1806b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1807b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1808ecc31b6eSAndy Yan if (!vop2->vp_plane_mask[i].attached_layers[j]) 1809b0989546SSandy Huang continue; 1810b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1811ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 1812b0989546SSandy Huang shift = win_data->win_sel_port_offset * 2; 1813b0989546SSandy Huang vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 1814b0989546SSandy Huang LAYER_SEL_PORT_SHIFT + shift, i, false); 1815b0989546SSandy Huang } 1816b0989546SSandy Huang } 1817b0989546SSandy Huang 181863cb669fSSandy Huang /** 181963cb669fSSandy Huang * port mux config 182063cb669fSSandy Huang */ 1821b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 182263cb669fSSandy Huang shift = i * 4; 1823ecc31b6eSAndy Yan if (vop2->vp_plane_mask[i].attached_layers_nr) { 1824b0989546SSandy Huang total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 182563cb669fSSandy Huang port_mux = total_used_layer - 1; 182663cb669fSSandy Huang } else { 182763cb669fSSandy Huang port_mux = 8; 1828d0408543SAndy Yan } 1829d0408543SAndy Yan 1830b0989546SSandy Huang if (i == vop2->data->nr_vps - 1) 183163cb669fSSandy Huang port_mux = vop2->data->nr_mixers; 183263cb669fSSandy Huang 183363cb669fSSandy Huang cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 183463cb669fSSandy Huang vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 183563cb669fSSandy Huang PORT_MUX_SHIFT + shift, port_mux, false); 183663cb669fSSandy Huang } 183763cb669fSSandy Huang 1838ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568) 183963cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 184063cb669fSSandy Huang 184163cb669fSSandy Huang vop2->global_init = true; 1842d0408543SAndy Yan } 1843d0408543SAndy Yan 1844d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state) 1845d0408543SAndy Yan { 1846d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 184763cb669fSSandy Huang int ret; 1848d0408543SAndy Yan 1849d0408543SAndy Yan /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1850d0408543SAndy Yan ret = clk_set_defaults(cstate->dev); 1851d0408543SAndy Yan if (ret) 1852d0408543SAndy Yan debug("%s clk_set_defaults failed %d\n", __func__, ret); 1853d0408543SAndy Yan 18541147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state); 18556414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state); 1856d0408543SAndy Yan 1857d0408543SAndy Yan return 0; 1858d0408543SAndy Yan } 1859d0408543SAndy Yan 1860d0408543SAndy Yan /* 1861d0408543SAndy Yan * VOP2 have multi video ports. 1862d0408543SAndy Yan * video port ------- crtc 1863d0408543SAndy Yan */ 1864d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state) 1865d0408543SAndy Yan { 1866d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 1867d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data; 1868d0408543SAndy Yan 1869d0408543SAndy Yan if (!rockchip_vop2) { 18700d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2)); 1871d0408543SAndy Yan if (!rockchip_vop2) 1872d0408543SAndy Yan return -ENOMEM; 1873d0408543SAndy Yan rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 1874d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 1875d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG; 187663cb669fSSandy Huang rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 1877d0408543SAndy Yan if (rockchip_vop2->grf <= 0) 187863cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 1879d0408543SAndy Yan rockchip_vop2->version = vop2_data->version; 1880d0408543SAndy Yan rockchip_vop2->data = vop2_data; 1881ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) { 1882b890760eSAlgea Cao struct regmap *map; 1883b890760eSAlgea Cao 1884ecc31b6eSAndy Yan rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF); 1885ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0) 1886ecc31b6eSAndy Yan printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf); 1887b890760eSAlgea Cao map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); 1888b890760eSAlgea Cao rockchip_vop2->vo1_grf = regmap_get_range(map, 0); 1889ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0) 1890ecc31b6eSAndy Yan printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf); 189160e469f5SDamon Ding rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); 1892b890760eSAlgea Cao if (rockchip_vop2->sys_pmu <= 0) 189360e469f5SDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu); 1894ecc31b6eSAndy Yan } 1895d0408543SAndy Yan } 1896d0408543SAndy Yan 1897d0408543SAndy Yan cstate->private = rockchip_vop2; 189863cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 189963cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 1900d0408543SAndy Yan 190189912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state); 190289912f2dSSandy Huang 1903d0408543SAndy Yan return 0; 1904d0408543SAndy Yan } 1905d0408543SAndy Yan 1906ecc31b6eSAndy Yan /* 1907ecc31b6eSAndy Yan * calc the dclk on rk3588 1908ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4 1909ecc31b6eSAndy Yan * 1910ecc31b6eSAndy Yan */ 1911ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 1912ecc31b6eSAndy Yan { 1913ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk) 1914ecc31b6eSAndy Yan return child_clk * 4; 1915ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk) 1916ecc31b6eSAndy Yan return child_clk * 2; 1917ecc31b6eSAndy Yan else if (child_clk <= max_dclk) 1918ecc31b6eSAndy Yan return child_clk; 1919ecc31b6eSAndy Yan else 1920ecc31b6eSAndy Yan return 0; 1921ecc31b6eSAndy Yan } 1922ecc31b6eSAndy Yan 1923ecc31b6eSAndy Yan /* 1924ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588 1925ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core 1926ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core 1927ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core 1928ecc31b6eSAndy Yan */ 1929ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state, 1930ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div, 1931ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div) 1932d0408543SAndy Yan { 1933d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 1934d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 1935d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 1936d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 1937ecc31b6eSAndy Yan unsigned long v_pixclk = mode->clock; 1938ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2; 1939ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk; 1940ecc31b6eSAndy Yan unsigned long dclk_out_rate; 1941ecc31b6eSAndy Yan u64 if_dclk_rate; 1942ecc31b6eSAndy Yan u64 if_pixclk_rate; 1943ecc31b6eSAndy Yan int output_type = conn_state->type; 1944ecc31b6eSAndy Yan int output_mode = conn_state->output_mode; 1945ecc31b6eSAndy Yan int K = 1; 1946ecc31b6eSAndy Yan 1947ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 1948ecc31b6eSAndy Yan /* 1949ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 1950ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 1951ecc31b6eSAndy Yan */ 1952b890760eSAlgea Cao if (output_mode == ROCKCHIP_OUT_MODE_YUV420) { 1953b890760eSAlgea Cao dclk_rate = dclk_rate >> 1; 1954ecc31b6eSAndy Yan K = 2; 1955b890760eSAlgea Cao } 195612ee5af0SDamon Ding if (cstate->dsc_enable) { 195712ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate << 1; 195812ee5af0SDamon Ding if_dclk_rate = cstate->dsc_cds_clk_rate; 1959ecc31b6eSAndy Yan } else { 1960ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K; 1961ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K; 1962ecc31b6eSAndy Yan } 1963ecc31b6eSAndy Yan 1964631ee99aSZhang Yubing if (v_pixclk > VOP2_MAX_DCLK_RATE) 1965631ee99aSZhang Yubing dclk_rate = vop2_calc_dclk(dclk_core_rate, vop2->data->vp_data->max_dclk); 1966631ee99aSZhang Yubing 1967ecc31b6eSAndy Yan if (!dclk_rate) { 1968ecc31b6eSAndy Yan printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 1969ecc31b6eSAndy Yan vop2->data->vp_data->max_dclk, if_pixclk_rate); 1970ecc31b6eSAndy Yan return -EINVAL; 1971ecc31b6eSAndy Yan } 1972ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 1973ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate; 1974b890760eSAlgea Cao *dclk_core_div = dclk_rate / dclk_core_rate; 1975b890760eSAlgea Cao printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n", 1976b890760eSAlgea Cao dclk_rate, *if_pixclk_div, *if_dclk_div); 1977ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 1978ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */ 1979ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K; 1980ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K; 1981ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K; 1982ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 1983ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 1984ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div; 1985ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 1986ecc31b6eSAndy Yan if (output_mode == ROCKCHIP_OUT_MODE_YUV420) 1987ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 3; 1988ecc31b6eSAndy Yan else 1989ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2; 1990ecc31b6eSAndy Yan 19916b2bd269SZhang Yubing dclk_rate = vop2_calc_dclk(dclk_out_rate, vop2->data->vp_data->max_dclk); 1992ecc31b6eSAndy Yan if (!dclk_rate) { 1993ecc31b6eSAndy Yan printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 1994ecc31b6eSAndy Yan vop2->data->vp_data->max_dclk, dclk_core_rate); 1995ecc31b6eSAndy Yan return -EINVAL; 1996ecc31b6eSAndy Yan } 1997ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 1998ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 1999ecc31b6eSAndy Yan 2000ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 2001ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2002ecc31b6eSAndy Yan K = 2; 200312ee5af0SDamon Ding if (cstate->dsc_enable) 200412ee5af0SDamon Ding /* dsc output is 96bit, dsi input is 192 bit */ 200512ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1; 2006ecc31b6eSAndy Yan else 2007ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K; 2008ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 200912ee5af0SDamon Ding dclk_out_rate = dclk_core_rate / K; 2010ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 20119f076eccSZhang Yubing dclk_rate = vop2_calc_dclk(dclk_out_rate, vop2->data->vp_data->max_dclk); 20129f076eccSZhang Yubing if (!dclk_rate) { 20139f076eccSZhang Yubing printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n", 20149f076eccSZhang Yubing vop2->data->vp_data->max_dclk, dclk_rate); 20159f076eccSZhang Yubing return -EINVAL; 20169f076eccSZhang Yubing } 201712ee5af0SDamon Ding 201812ee5af0SDamon Ding if (cstate->dsc_enable) 201912ee5af0SDamon Ding dclk_rate = dclk_rate >> 1; 202012ee5af0SDamon Ding 2021ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 2022ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2023ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 202412ee5af0SDamon Ding if (cstate->dsc_enable) 202512ee5af0SDamon Ding *if_pixclk_div = dclk_out_rate / if_pixclk_rate; 2026ecc31b6eSAndy Yan 2027ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 2028ecc31b6eSAndy Yan dclk_rate = v_pixclk; 2029ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2030ecc31b6eSAndy Yan } 2031ecc31b6eSAndy Yan 2032ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div); 2033ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div); 2034ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div); 2035ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div); 2036ecc31b6eSAndy Yan 2037ecc31b6eSAndy Yan return dclk_rate; 2038ecc31b6eSAndy Yan } 2039ecc31b6eSAndy Yan 204012ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state) 2041ecc31b6eSAndy Yan { 204212ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 2043ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 204412ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 204512ee5af0SDamon Ding u64 v_pixclk = mode->clock; /* video timing pixclk */ 2046ecc31b6eSAndy Yan u8 k = 1; 2047ecc31b6eSAndy Yan 2048ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2049ecc31b6eSAndy Yan k = 2; 2050ecc31b6eSAndy Yan 205112ee5af0SDamon Ding cstate->dsc_txp_clk_rate = v_pixclk; 205212ee5af0SDamon Ding do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k)); 2053ecc31b6eSAndy Yan 205412ee5af0SDamon Ding cstate->dsc_pxl_clk_rate = v_pixclk; 205512ee5af0SDamon Ding do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k)); 2056ecc31b6eSAndy Yan 2057ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 2058ecc31b6eSAndy Yan * cds_dat_width = 96; 2059ecc31b6eSAndy Yan * bits_per_pixel = [8-12]; 2060b61227a3SDamon Ding * As cds clk is div from txp clk and only support 1/2/4 div, 2061b61227a3SDamon Ding * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4, 2062b61227a3SDamon Ding * otherwise dsc_cds = crtc_clock / 8; 2063ecc31b6eSAndy Yan */ 2064b61227a3SDamon Ding cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8); 2065ecc31b6eSAndy Yan 2066ecc31b6eSAndy Yan return 0; 2067ecc31b6eSAndy Yan } 2068ecc31b6eSAndy Yan 2069ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 2070ecc31b6eSAndy Yan { 2071ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2072ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2073ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 207412ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 2075ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 207652ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2077ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2078ecc31b6eSAndy Yan int output_if = conn_state->output_if; 2079ecc31b6eSAndy Yan int if_pixclk_div = 0; 2080ecc31b6eSAndy Yan int if_dclk_div = 0; 2081ecc31b6eSAndy Yan unsigned long dclk_rate; 2082d0408543SAndy Yan u32 val; 2083ecc31b6eSAndy Yan 2084b890760eSAlgea Cao if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 2085b890760eSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 2086b890760eSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 2087b890760eSAlgea Cao } else { 2088ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 2089ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2090b890760eSAlgea Cao } 2091ecc31b6eSAndy Yan 209212ee5af0SDamon Ding if (cstate->dsc_enable) { 209312ee5af0SDamon Ding int k = 1; 209412ee5af0SDamon Ding 2095ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) { 209612ee5af0SDamon Ding printf("Unsupported DSC\n"); 2097ecc31b6eSAndy Yan return 0; 2098ecc31b6eSAndy Yan } 209912ee5af0SDamon Ding 210012ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 210112ee5af0SDamon Ding k = 2; 210212ee5af0SDamon Ding 210312ee5af0SDamon Ding cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 210412ee5af0SDamon Ding cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k; 210512ee5af0SDamon Ding cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num; 210612ee5af0SDamon Ding 210712ee5af0SDamon Ding vop2_calc_dsc_clk(state); 210812ee5af0SDamon Ding printf("Enable DSC%d slice:%dx%d, slice num:%d\n", 210912ee5af0SDamon Ding cstate->dsc_id, dsc_sink_cap->slice_width, 211012ee5af0SDamon Ding dsc_sink_cap->slice_height, cstate->dsc_slice_num); 2111ecc31b6eSAndy Yan } 2112ecc31b6eSAndy Yan 2113b61227a3SDamon Ding dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div); 2114ecc31b6eSAndy Yan 2115ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) { 2116ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2117ecc31b6eSAndy Yan 4, false); 2118ecc31b6eSAndy Yan } 2119ecc31b6eSAndy Yan 2120ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) { 2121ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2122ecc31b6eSAndy Yan 3, false); 2123ecc31b6eSAndy Yan } 2124ecc31b6eSAndy Yan 2125ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) { 2126ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2127ecc31b6eSAndy Yan 2, false); 2128ecc31b6eSAndy Yan } 2129ecc31b6eSAndy Yan 2130ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) { 2131ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2132ecc31b6eSAndy Yan val = 0; 2133ecc31b6eSAndy Yan else 2134ecc31b6eSAndy Yan val = 1; 213541874944SGuochun Huang 21363df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 213741874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 213841874944SGuochun Huang RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 213941874944SGuochun Huang 2140ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 2141ecc31b6eSAndy Yan 1, false); 2142ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 2143ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 2144ecc31b6eSAndy Yan if_pixclk_div, false); 214541874944SGuochun Huang 214641874944SGuochun Huang if (conn_state->hold_mode) { 214741874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 214841874944SGuochun Huang EN_MASK, EDPI_TE_EN, 1, false); 214941874944SGuochun Huang 215041874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 215141874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 215241874944SGuochun Huang } 2153ecc31b6eSAndy Yan } 2154ecc31b6eSAndy Yan 2155ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) { 2156ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2157ecc31b6eSAndy Yan val = 0; 2158ecc31b6eSAndy Yan else if (cstate->crtc_id == 3) 2159ecc31b6eSAndy Yan val = 1; 2160ecc31b6eSAndy Yan else 2161ecc31b6eSAndy Yan val = 3; /*VP1*/ 21623df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 216341874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 216441874944SGuochun Huang RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 216541874944SGuochun Huang 2166ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 2167ecc31b6eSAndy Yan 1, false); 2168ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 2169ecc31b6eSAndy Yan val, false); 2170ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 2171ecc31b6eSAndy Yan if_pixclk_div, false); 217241874944SGuochun Huang 217341874944SGuochun Huang if (conn_state->hold_mode) { 217441874944SGuochun Huang /* UNDO: RK3588 VP1->DSC1->DSI1 only can support soft TE mode */ 217541874944SGuochun Huang if (vop2->version == VOP_VERSION_RK3588 && val == 3) 217641874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 217741874944SGuochun Huang EN_MASK, EDPI_TE_EN, 0, false); 217841874944SGuochun Huang else 217941874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 218041874944SGuochun Huang EN_MASK, EDPI_TE_EN, 1, false); 218141874944SGuochun Huang 218241874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 218341874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 218441874944SGuochun Huang } 2185ecc31b6eSAndy Yan } 2186ecc31b6eSAndy Yan 2187ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 2188ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2189ecc31b6eSAndy Yan RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 21903df6e59eSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 21913df6e59eSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 2192ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2193ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2194ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 2195ecc31b6eSAndy Yan false); 2196ecc31b6eSAndy Yan } 2197ecc31b6eSAndy Yan 2198ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) { 2199ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 2200ecc31b6eSAndy Yan 1, false); 2201ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2202ecc31b6eSAndy Yan cstate->crtc_id, false); 2203ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2204ecc31b6eSAndy Yan if_dclk_div, false); 2205ecc31b6eSAndy Yan 2206ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2207ecc31b6eSAndy Yan if_pixclk_div, false); 2208ecc31b6eSAndy Yan 2209ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2210ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 2211ecc31b6eSAndy Yan } 2212ecc31b6eSAndy Yan 2213ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) { 2214ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 2215ecc31b6eSAndy Yan 1, false); 2216ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2217ecc31b6eSAndy Yan cstate->crtc_id, false); 2218ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2219ecc31b6eSAndy Yan if_dclk_div, false); 2220ecc31b6eSAndy Yan 2221ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2222ecc31b6eSAndy Yan if_pixclk_div, false); 22231848455fSDamon Ding 22241848455fSDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 22251848455fSDamon Ding RK3588_GRF_EDP1_ENABLE_SHIFT, 1); 2226ecc31b6eSAndy Yan } 2227ecc31b6eSAndy Yan 2228ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) { 2229ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 2230ecc31b6eSAndy Yan 1, false); 2231ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2232ecc31b6eSAndy Yan cstate->crtc_id, false); 2233ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2234ecc31b6eSAndy Yan if_dclk_div, false); 2235ecc31b6eSAndy Yan 2236ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2237ecc31b6eSAndy Yan if_pixclk_div, false); 2238b890760eSAlgea Cao 2239b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2240b890760eSAlgea Cao RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1); 2241b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2242b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2243b890760eSAlgea Cao HDMI0_SYNC_POL_SHIFT, val); 2244ecc31b6eSAndy Yan } 2245ecc31b6eSAndy Yan 2246ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) { 2247ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 2248ecc31b6eSAndy Yan 1, false); 2249ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2250ecc31b6eSAndy Yan cstate->crtc_id, false); 2251ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2252ecc31b6eSAndy Yan if_dclk_div, false); 2253ecc31b6eSAndy Yan 2254ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2255ecc31b6eSAndy Yan if_pixclk_div, false); 2256b890760eSAlgea Cao 2257b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2258b890760eSAlgea Cao RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1); 2259b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2260b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2261b890760eSAlgea Cao HDMI1_SYNC_POL_SHIFT, val); 2262ecc31b6eSAndy Yan } 2263ecc31b6eSAndy Yan 2264ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) { 2265ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 2266ecc31b6eSAndy Yan 1, false); 2267ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 2268ecc31b6eSAndy Yan cstate->crtc_id, false); 2269ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2270ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false); 2271ecc31b6eSAndy Yan } 2272ecc31b6eSAndy Yan 2273ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) { 2274108c5f8bSZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT, 2275ecc31b6eSAndy Yan 1, false); 2276ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 2277ecc31b6eSAndy Yan cstate->crtc_id, false); 2278ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2279ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false); 2280ecc31b6eSAndy Yan } 2281ecc31b6eSAndy Yan 2282ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2283b61227a3SDamon Ding DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false); 2284ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2285b61227a3SDamon Ding DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false); 2286ecc31b6eSAndy Yan 2287ecc31b6eSAndy Yan return dclk_rate; 2288ecc31b6eSAndy Yan } 2289ecc31b6eSAndy Yan 2290ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 2291ecc31b6eSAndy Yan { 2292ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2293ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2294ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2295ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2296ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 2297d0408543SAndy Yan bool dclk_inv; 2298ecc31b6eSAndy Yan u32 val; 22998895aec1SSandy Huang 2300d0408543SAndy Yan dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 230110ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 230210ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2303d0408543SAndy Yan 2304d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 2305d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 2306d0408543SAndy Yan 1, false); 2307d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2308d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 2309ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 2310c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 2311d0408543SAndy Yan } 2312d0408543SAndy Yan 2313d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 231452ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 231552ee18acSSandy Huang 1, false); 2316d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 2317d0408543SAndy Yan BT1120_EN_SHIFT, 1, false); 2318d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2319d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 2320ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 232152ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 2322d0408543SAndy Yan } 2323d0408543SAndy Yan 2324d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 2325d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 2326d0408543SAndy Yan 1, false); 2327d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2328d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 2329ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 233052ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 2331d0408543SAndy Yan } 2332d0408543SAndy Yan 2333d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 2334d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 2335d0408543SAndy Yan 1, false); 2336d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2337d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false); 233811f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 233911f53190SSandy Huang IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 2340d0408543SAndy Yan } 2341d0408543SAndy Yan 2342d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 2343d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 2344d0408543SAndy Yan 1, false); 2345d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2346d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false); 234711f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 234811f53190SSandy Huang IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 2349d0408543SAndy Yan } 2350d0408543SAndy Yan 2351d0408543SAndy Yan if (conn_state->output_flags & 2352d0408543SAndy Yan (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 2353d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 2354d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2355d0408543SAndy Yan LVDS_DUAL_EN_SHIFT, 1, false); 2356d0408543SAndy Yan if (conn_state->output_flags & 2357d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2358d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2359d0408543SAndy Yan LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 2360d0408543SAndy Yan false); 2361d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2362d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2363d0408543SAndy Yan LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 2364d0408543SAndy Yan } 2365d0408543SAndy Yan 2366d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 2367d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 2368d0408543SAndy Yan 1, false); 2369d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2370d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false); 2371d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2372c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 2373d0408543SAndy Yan } 2374d0408543SAndy Yan 2375d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 2376d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 2377d0408543SAndy Yan 1, false); 2378d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2379d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false); 2380d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2381c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 2382d0408543SAndy Yan } 2383d0408543SAndy Yan 2384d0408543SAndy Yan if (conn_state->output_flags & 2385d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 2386d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 2387d0408543SAndy Yan MIPI_DUAL_EN_SHIFT, 1, false); 2388d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2389d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2390d0408543SAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 2391d0408543SAndy Yan false); 2392d0408543SAndy Yan } 2393d0408543SAndy Yan 2394d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 2395d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 2396d0408543SAndy Yan 1, false); 2397d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2398d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false); 2399c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2400c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 2401d0408543SAndy Yan } 2402d0408543SAndy Yan 2403d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 2404d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 2405d0408543SAndy Yan 1, false); 2406d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2407d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false); 240810ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 240910ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 241010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, 241110ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK, 241210ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 2413d0408543SAndy Yan } 241410ee9f5bSAlgea Cao 2415ecc31b6eSAndy Yan return mode->clock; 2416ecc31b6eSAndy Yan } 2417ecc31b6eSAndy Yan 241865747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state) 241965747de7SDamon Ding { 242065747de7SDamon Ding struct crtc_state *cstate = &state->crtc_state; 242165747de7SDamon Ding struct connector_state *conn_state = &state->conn_state; 242265747de7SDamon Ding struct vop2 *vop2 = cstate->private; 242365747de7SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 242465747de7SDamon Ding u32 output_type = conn_state->type; 242565747de7SDamon Ding u32 data_swap = 0; 242665747de7SDamon Ding 242765747de7SDamon Ding if (is_uv_swap(conn_state->bus_format, conn_state->output_mode)) 242865747de7SDamon Ding data_swap = DSP_RB_SWAP; 242965747de7SDamon Ding 243065747de7SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && 243165747de7SDamon Ding (output_type == DRM_MODE_CONNECTOR_HDMIA || 243265747de7SDamon Ding output_type == DRM_MODE_CONNECTOR_eDP) && 243365747de7SDamon Ding (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 243465747de7SDamon Ding conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 243565747de7SDamon Ding data_swap |= DSP_RG_SWAP; 243665747de7SDamon Ding 243765747de7SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 243865747de7SDamon Ding DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 243965747de7SDamon Ding } 244065747de7SDamon Ding 2441b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent) 2442b890760eSAlgea Cao { 2443b890760eSAlgea Cao int ret = 0; 2444b890760eSAlgea Cao 2445b890760eSAlgea Cao if (parent->dev) 2446b890760eSAlgea Cao ret = clk_set_parent(clk, parent); 2447b890760eSAlgea Cao if (ret < 0) 2448b890760eSAlgea Cao debug("failed to set %s as parent for %s\n", 2449b890760eSAlgea Cao parent->dev->name, clk->dev->name); 2450b890760eSAlgea Cao } 2451b890760eSAlgea Cao 2452b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate) 2453b890760eSAlgea Cao { 2454b890760eSAlgea Cao int ret = 0; 2455b890760eSAlgea Cao 2456b890760eSAlgea Cao if (clk->dev) 2457b890760eSAlgea Cao ret = clk_set_rate(clk, rate); 2458b890760eSAlgea Cao if (ret < 0) 2459b890760eSAlgea Cao debug("failed to set %s rate %lu \n", clk->dev->name, rate); 2460b890760eSAlgea Cao 2461b890760eSAlgea Cao return ret; 2462b890760eSAlgea Cao } 2463b890760eSAlgea Cao 246412ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state, 246512ee5af0SDamon Ding int *dsc_txp_clk_div, int *dsc_pxl_clk_div, 246612ee5af0SDamon Ding int *dsc_cds_clk_div, u64 dclk_rate) 246712ee5af0SDamon Ding { 246812ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 246912ee5af0SDamon Ding 247012ee5af0SDamon Ding *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate; 247112ee5af0SDamon Ding *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate; 247212ee5af0SDamon Ding *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate; 247312ee5af0SDamon Ding 247412ee5af0SDamon Ding *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div); 247512ee5af0SDamon Ding *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div); 247612ee5af0SDamon Ding *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div); 247712ee5af0SDamon Ding } 247812ee5af0SDamon Ding 247912ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id) 248012ee5af0SDamon Ding { 248112ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 248212ee5af0SDamon Ding struct drm_dsc_picture_parameter_set *pps = &cstate->pps; 248312ee5af0SDamon Ding struct drm_dsc_picture_parameter_set config_pps; 248412ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 248512ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 248612ee5af0SDamon Ding u32 *pps_val = (u32 *)&config_pps; 248712ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 248812ee5af0SDamon Ding int i = 0; 248912ee5af0SDamon Ding 249012ee5af0SDamon Ding memcpy(&config_pps, pps, sizeof(config_pps)); 249112ee5af0SDamon Ding 249212ee5af0SDamon Ding if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) { 249312ee5af0SDamon Ding config_pps.pps_3 &= 0xf0; 249412ee5af0SDamon Ding config_pps.pps_3 |= dsc_data->max_linebuf_depth; 249512ee5af0SDamon Ding printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n", 249612ee5af0SDamon Ding dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf); 249712ee5af0SDamon Ding } 249812ee5af0SDamon Ding 249912ee5af0SDamon Ding for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 250012ee5af0SDamon Ding config_pps.rc_range_parameters[i] = 250112ee5af0SDamon Ding (pps->rc_range_parameters[i] >> 3 & 0x1f) | 250212ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) | 250312ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) | 250412ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10); 250512ee5af0SDamon Ding } 250612ee5af0SDamon Ding 250712ee5af0SDamon Ding for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++) 250812ee5af0SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++); 250912ee5af0SDamon Ding } 251012ee5af0SDamon Ding 251112ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate) 251212ee5af0SDamon Ding { 251312ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 251412ee5af0SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 251512ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 251612ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 251712ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 251812ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 251912ee5af0SDamon Ding bool mipi_ds_mode = false; 252012ee5af0SDamon Ding u8 dsc_interface_mode = 0; 252112ee5af0SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 252212ee5af0SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 252312ee5af0SDamon Ding u16 htotal = mode->crtc_htotal; 252412ee5af0SDamon Ding u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 252512ee5af0SDamon Ding u16 vdisplay = mode->crtc_vdisplay; 252612ee5af0SDamon Ding u16 vtotal = mode->crtc_vtotal; 252712ee5af0SDamon Ding u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 252812ee5af0SDamon Ding u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 252912ee5af0SDamon Ding u16 vact_end = vact_st + vdisplay; 253012ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 253112ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 253212ee5af0SDamon Ding u32 backup_regs_offset = 0; 253312ee5af0SDamon Ding int dsc_txp_clk_div = 0; 253412ee5af0SDamon Ding int dsc_pxl_clk_div = 0; 253512ee5af0SDamon Ding int dsc_cds_clk_div = 0; 253612ee5af0SDamon Ding 253712ee5af0SDamon Ding if (!vop2->data->nr_dscs) { 253812ee5af0SDamon Ding printf("Unsupported DSC\n"); 253912ee5af0SDamon Ding return; 254012ee5af0SDamon Ding } 254112ee5af0SDamon Ding 254212ee5af0SDamon Ding if (cstate->dsc_slice_num > dsc_data->max_slice_num) 254312ee5af0SDamon Ding printf("DSC%d supported max slice is: %d, current is: %d\n", 254412ee5af0SDamon Ding dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num); 254512ee5af0SDamon Ding 254612ee5af0SDamon Ding if (dsc_data->pd_id) { 254712ee5af0SDamon Ding if (vop2_power_domain_on(vop2, dsc_data->pd_id)) 254812ee5af0SDamon Ding printf("open dsc%d pd fail\n", dsc_id); 254912ee5af0SDamon Ding } 255012ee5af0SDamon Ding 255112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK, 255212ee5af0SDamon Ding SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false); 255312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK, 255412ee5af0SDamon Ding DSC_PORT_SEL_SHIFT, cstate->crtc_id, false); 255512ee5af0SDamon Ding if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 255612ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_HDMI; 255712ee5af0SDamon Ding } else { 255812ee5af0SDamon Ding mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE); 255912ee5af0SDamon Ding if (mipi_ds_mode) 256012ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE; 256112ee5af0SDamon Ding else 256212ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE; 256312ee5af0SDamon Ding } 256412ee5af0SDamon Ding 256512ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 256612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 256712ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 0, false); 256812ee5af0SDamon Ding else 256912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 257012ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 1, false); 257112ee5af0SDamon Ding 257212ee5af0SDamon Ding vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate); 257312ee5af0SDamon Ding 257412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK, 257512ee5af0SDamon Ding DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false); 257612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK, 257712ee5af0SDamon Ding DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false); 257812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK, 257912ee5af0SDamon Ding DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false); 258012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK, 258112ee5af0SDamon Ding DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false); 258212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 258312ee5af0SDamon Ding DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false); 258412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK, 258512ee5af0SDamon Ding DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false); 258612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 258712ee5af0SDamon Ding DSC_HALT_EN_SHIFT, mipi_ds_mode, false); 258812ee5af0SDamon Ding 258912ee5af0SDamon Ding if (!mipi_ds_mode) { 259012ee5af0SDamon Ding u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end; 259112ee5af0SDamon Ding u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16; 259212ee5af0SDamon Ding u64 dsc_cds_rate = cstate->dsc_cds_clk_rate; 259312ee5af0SDamon Ding u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */ 259412ee5af0SDamon Ding u32 dly_num, dsc_cds_rate_mhz, val = 0; 2595b61227a3SDamon Ding int k = 1; 2596b61227a3SDamon Ding 2597b61227a3SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2598b61227a3SDamon Ding k = 2; 259912ee5af0SDamon Ding 260012ee5af0SDamon Ding if (target_bpp >> 4 < dsc_data->min_bits_per_pixel) 260112ee5af0SDamon Ding printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel); 260212ee5af0SDamon Ding 260312ee5af0SDamon Ding /* 260412ee5af0SDamon Ding * dly_num = delay_line_num * T(one-line) / T (dsc_cds) 260512ee5af0SDamon Ding * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz 260612ee5af0SDamon Ding * T (dsc_cds) = 1 / dsc_cds_rate_mhz 260712ee5af0SDamon Ding * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay 260812ee5af0SDamon Ding * delay_line_num = 4 - BPP / 8 260912ee5af0SDamon Ding * = (64 - target_bpp / 8) / 16 261012ee5af0SDamon Ding * 261112ee5af0SDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 261212ee5af0SDamon Ding */ 261312ee5af0SDamon Ding do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ 261412ee5af0SDamon Ding dsc_cds_rate_mhz = dsc_cds_rate; 261512ee5af0SDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 261612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK, 261712ee5af0SDamon Ding DSC_INIT_DLY_MODE_SHIFT, 0, false); 261812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK, 261912ee5af0SDamon Ding DSC_INIT_DLY_NUM_SHIFT, dly_num, false); 262012ee5af0SDamon Ding 262112ee5af0SDamon Ding dsc_hsync = hsync_len / 2; 2622b61227a3SDamon Ding /* 2623b61227a3SDamon Ding * htotal / dclk_core = dsc_htotal /cds_clk 2624b61227a3SDamon Ding * 2625b61227a3SDamon Ding * dclk_core = DCLK / (1 << dclk_core->div_val) 2626b61227a3SDamon Ding * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val) 2627b61227a3SDamon Ding * txp_clk = DCLK / (1 << dsc_txp_clk->div_val) 2628b61227a3SDamon Ding * 2629b61227a3SDamon Ding * dsc_htotal = htotal * (1 << dclk_core->div_val) / 2630b61227a3SDamon Ding * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val)) 2631b61227a3SDamon Ding */ 2632b61227a3SDamon Ding dsc_htotal = htotal * (1 << cstate->dclk_core_div) / 2633b61227a3SDamon Ding ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div)); 263412ee5af0SDamon Ding val = dsc_htotal << 16 | dsc_hsync; 263512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK, 263612ee5af0SDamon Ding DSC_HTOTAL_PW_SHIFT, val, false); 263712ee5af0SDamon Ding 263812ee5af0SDamon Ding dsc_hact_st = hact_st / 2; 2639b61227a3SDamon Ding dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st; 264012ee5af0SDamon Ding val = dsc_hact_end << 16 | dsc_hact_st; 264112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK, 264212ee5af0SDamon Ding DSC_HACT_ST_END_SHIFT, val, false); 264312ee5af0SDamon Ding 264412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK, 264512ee5af0SDamon Ding DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false); 264612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK, 264712ee5af0SDamon Ding DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false); 264812ee5af0SDamon Ding } 264912ee5af0SDamon Ding 265012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK, 265112ee5af0SDamon Ding RST_DEASSERT_SHIFT, 1, false); 265212ee5af0SDamon Ding udelay(10); 265312ee5af0SDamon Ding /* read current dsc core register and backup to regsbak */ 265412ee5af0SDamon Ding backup_regs_offset = RK3588_DSC_8K_CTRL0; 265512ee5af0SDamon Ding vop2->regsbak[backup_regs_offset >> 2] = vop2_readl(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset); 265612ee5af0SDamon Ding 265712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 265812ee5af0SDamon Ding DSC_EN_SHIFT, 1, false); 265912ee5af0SDamon Ding vop2_load_pps(state, vop2, dsc_id); 266012ee5af0SDamon Ding 266112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 266212ee5af0SDamon Ding DSC_RBIT_SHIFT, 1, false); 266312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 266412ee5af0SDamon Ding DSC_RBYT_SHIFT, 0, false); 266512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 266612ee5af0SDamon Ding DSC_FLAL_SHIFT, 1, false); 266712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 266812ee5af0SDamon Ding DSC_MER_SHIFT, 1, false); 266912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 267012ee5af0SDamon Ding DSC_EPB_SHIFT, 0, false); 267112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 267212ee5af0SDamon Ding DSC_EPL_SHIFT, 1, false); 267312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 267412ee5af0SDamon Ding DSC_NSLC_SHIFT, ilog2(cstate->dsc_slice_num), false); 267512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 267612ee5af0SDamon Ding DSC_SBO_SHIFT, 1, false); 267712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 267812ee5af0SDamon Ding DSC_IFEP_SHIFT, dsc_sink_cap->version_minor == 2 ? 1 : 0, false); 267912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, EN_MASK, 268012ee5af0SDamon Ding DSC_PPS_UPD_SHIFT, 1, false); 268112ee5af0SDamon Ding 268212ee5af0SDamon Ding printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n", 268312ee5af0SDamon Ding dsc_id, 268412ee5af0SDamon Ding cstate->dsc_txp_clk_rate, dsc_txp_clk_div, 268512ee5af0SDamon Ding cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div, 268612ee5af0SDamon Ding cstate->dsc_cds_clk_rate, dsc_cds_clk_div); 268712ee5af0SDamon Ding } 268812ee5af0SDamon Ding 26895f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev) 26905f1357a2SZhang Yubing { 26915f1357a2SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 26925f1357a2SZhang Yubing struct vop2 *vop2 = cstate->private; 26935f1357a2SZhang Yubing struct udevice *vp_dev, *dev; 26945f1357a2SZhang Yubing struct ofnode_phandle_args args; 26955f1357a2SZhang Yubing char vp_name[10]; 26965f1357a2SZhang Yubing int ret; 26975f1357a2SZhang Yubing 26985f1357a2SZhang Yubing if (vop2->version != VOP_VERSION_RK3588) 26995f1357a2SZhang Yubing return false; 27005f1357a2SZhang Yubing 27015f1357a2SZhang Yubing sprintf(vp_name, "port@%d", cstate->crtc_id); 27025f1357a2SZhang Yubing if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) { 27035f1357a2SZhang Yubing printf("warn: can't get vp device\n"); 27045f1357a2SZhang Yubing return false; 27055f1357a2SZhang Yubing } 27065f1357a2SZhang Yubing 27075f1357a2SZhang Yubing ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0, 27085f1357a2SZhang Yubing 0, &args); 27095f1357a2SZhang Yubing if (ret) { 2710c0545157SZhang Yubing printf("assigned-clock-parents's node not define\n"); 27115f1357a2SZhang Yubing return false; 27125f1357a2SZhang Yubing } 27135f1357a2SZhang Yubing 27145f1357a2SZhang Yubing if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) { 27155f1357a2SZhang Yubing printf("warn: can't get clk device\n"); 27165f1357a2SZhang Yubing return false; 27175f1357a2SZhang Yubing } 27185f1357a2SZhang Yubing 27195f1357a2SZhang Yubing if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) { 27205f1357a2SZhang Yubing printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name); 27215f1357a2SZhang Yubing if (clk_dev) 27225f1357a2SZhang Yubing *clk_dev = dev; 27235f1357a2SZhang Yubing return true; 27245f1357a2SZhang Yubing } 27255f1357a2SZhang Yubing 27265f1357a2SZhang Yubing return false; 27275f1357a2SZhang Yubing } 27285f1357a2SZhang Yubing 2729ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state) 2730ecc31b6eSAndy Yan { 2731ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2732ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2733ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2734ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2735ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2736ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2737ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal; 2738ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 2739ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay; 2740ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay; 2741ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal; 2742ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 2743ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 2744ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay; 2745ecc31b6eSAndy Yan bool yuv_overlay = false; 2746ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 274766724b9cSDamon Ding u32 line_flag_offset = (cstate->crtc_id * 4); 274866724b9cSDamon Ding u32 val, act_end; 2749ecc31b6eSAndy Yan u8 dither_down_en = 0; 2750ecc31b6eSAndy Yan u8 pre_dither_down_en = 0; 2751edfef528SDamon Ding u8 dclk_div_factor = 0; 2752ecc31b6eSAndy Yan char output_type_name[30] = {0}; 2753ecc31b6eSAndy Yan char dclk_name[9]; 2754ecc31b6eSAndy Yan struct clk dclk; 2755b890760eSAlgea Cao struct clk hdmi0_phy_pll; 2756b890760eSAlgea Cao struct clk hdmi1_phy_pll; 27575f1357a2SZhang Yubing struct clk hdmi_phy_pll; 27583e05a7b8SZhang Yubing struct udevice *disp_dev; 2759ecc31b6eSAndy Yan unsigned long dclk_rate; 2760ecc31b6eSAndy Yan int ret; 2761ecc31b6eSAndy Yan 2762ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 2763ecc31b6eSAndy Yan mode->hdisplay, mode->vdisplay, 2764ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 2765ecc31b6eSAndy Yan mode->vscan, 2766ecc31b6eSAndy Yan get_output_if_name(conn_state->output_if, output_type_name), 2767ecc31b6eSAndy Yan cstate->crtc_id); 2768ecc31b6eSAndy Yan 2769ee01dbb2SDamon Ding if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { 2770ee01dbb2SDamon Ding cstate->splice_mode = true; 2771ee01dbb2SDamon Ding cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id; 2772ee01dbb2SDamon Ding if (!cstate->splice_crtc_id) { 2773ee01dbb2SDamon Ding printf("%s: Splice mode is unsupported by vp%d\n", 2774ee01dbb2SDamon Ding __func__, cstate->crtc_id); 2775ee01dbb2SDamon Ding return -EINVAL; 2776ee01dbb2SDamon Ding } 2777*b70b2d79SDamon Ding 2778*b70b2d79SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK, 2779*b70b2d79SDamon Ding PORT_MERGE_EN_SHIFT, 1, false); 2780ee01dbb2SDamon Ding } 2781ee01dbb2SDamon Ding 2782ecc31b6eSAndy Yan vop2_initial(vop2, state); 2783ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 2784ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state); 2785ecc31b6eSAndy Yan else 2786ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state); 2787ecc31b6eSAndy Yan 278863cb669fSSandy Huang if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 278963cb669fSSandy Huang !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) 27907bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 27917bdd0eb6SSandy Huang 279265747de7SDamon Ding vop2_post_color_swap(state); 279310ee9f5bSAlgea Cao 2794d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 2795d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false); 2796d0408543SAndy Yan 2797d0408543SAndy Yan switch (conn_state->bus_format) { 2798d0408543SAndy Yan case MEDIA_BUS_FMT_RGB565_1X16: 2799d0408543SAndy Yan dither_down_en = 1; 2800d0408543SAndy Yan break; 2801d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X18: 2802d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 2803d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 2804d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: 2805d0408543SAndy Yan dither_down_en = 1; 2806d0408543SAndy Yan break; 2807d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 2808d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 2809d0408543SAndy Yan dither_down_en = 0; 2810d0408543SAndy Yan pre_dither_down_en = 1; 2811d0408543SAndy Yan break; 2812d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 2813d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 2814d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X24: 2815d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 2816d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 2817d0408543SAndy Yan default: 2818d0408543SAndy Yan dither_down_en = 0; 2819d0408543SAndy Yan pre_dither_down_en = 0; 2820d0408543SAndy Yan break; 2821d0408543SAndy Yan } 2822d0408543SAndy Yan 2823d0408543SAndy Yan if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA) 2824d0408543SAndy Yan pre_dither_down_en = 0; 2825d0408543SAndy Yan else 2826d0408543SAndy Yan pre_dither_down_en = 1; 2827d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2828d0408543SAndy Yan DITHER_DOWN_EN_SHIFT, dither_down_en, false); 2829d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2830d0408543SAndy Yan PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 2831d0408543SAndy Yan 2832d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 2833d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 2834d0408543SAndy Yan yuv_overlay, false); 2835d0408543SAndy Yan 2836d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay; 2837d0408543SAndy Yan 2838d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 2839d0408543SAndy Yan (htotal << 16) | hsync_len); 2840d0408543SAndy Yan val = hact_st << 16; 2841d0408543SAndy Yan val |= hact_end; 2842d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 2843d0408543SAndy Yan val = vact_st << 16; 2844d0408543SAndy Yan val |= vact_end; 2845d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 2846d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 2847d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 2848d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay; 2849d0408543SAndy Yan 2850d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 2851d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 2852d0408543SAndy Yan val); 2853d0408543SAndy Yan 2854d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len); 2855d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 2856d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2857d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false); 2858d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 28597a20be36SSandy Huang DSP_FILED_POL, 1, false); 28607a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2861d0408543SAndy Yan P2I_EN_SHIFT, 1, false); 2862d0408543SAndy Yan vtotal += vtotal + 1; 286366724b9cSDamon Ding act_end = vact_end_f1; 2864d0408543SAndy Yan } else { 2865d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2866d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false); 2867d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2868d0408543SAndy Yan P2I_EN_SHIFT, 0, false); 286966724b9cSDamon Ding act_end = vact_end; 2870d0408543SAndy Yan } 2871d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 2872d0408543SAndy Yan (vtotal << 16) | vsync_len); 287367be2ffcSDamon Ding 287467be2ffcSDamon Ding if (vop2->version == VOP_VERSION_RK3568) { 287567be2ffcSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || 287667be2ffcSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 2877d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 287867be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 1, false); 287967be2ffcSDamon Ding else 288067be2ffcSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 288167be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 0, false); 288267be2ffcSDamon Ding } 288310ee9f5bSAlgea Cao 288410ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 288563cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 288663cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 288710ee9f5bSAlgea Cao else 288863cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 288963cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 289010ee9f5bSAlgea Cao 2891ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 2892ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false); 2893ee01dbb2SDamon Ding 289410ee9f5bSAlgea Cao if (yuv_overlay) 289510ee9f5bSAlgea Cao val = 0x20010200; 289610ee9f5bSAlgea Cao else 289710ee9f5bSAlgea Cao val = 0; 289810ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 2899*b70b2d79SDamon Ding if (cstate->splice_mode) { 2900ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 2901ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id, 2902ee01dbb2SDamon Ding yuv_overlay, false); 2903ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val); 2904ee01dbb2SDamon Ding } 290510ee9f5bSAlgea Cao 290610ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 290710ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 2908d0408543SAndy Yan 2909ac500a1fSSandy Huang vop2_tv_config_update(state, vop2); 2910d0408543SAndy Yan vop2_post_config(state, vop2); 2911d0408543SAndy Yan 291212ee5af0SDamon Ding if (cstate->dsc_enable) { 291312ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 291412ee5af0SDamon Ding vop2_dsc_enable(state, vop2, 0, dclk_rate); 291512ee5af0SDamon Ding vop2_dsc_enable(state, vop2, 1, dclk_rate); 291612ee5af0SDamon Ding } else { 291712ee5af0SDamon Ding vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate); 291812ee5af0SDamon Ding } 291912ee5af0SDamon Ding } 292012ee5af0SDamon Ding 2921ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 2922ecc31b6eSAndy Yan ret = clk_get_by_name(cstate->dev, dclk_name, &dclk); 2923b890760eSAlgea Cao if (ret) { 2924b890760eSAlgea Cao printf("%s: Failed to get dclk ret=%d\n", __func__, ret); 2925b890760eSAlgea Cao return ret; 2926b890760eSAlgea Cao } 2927b890760eSAlgea Cao 29283e05a7b8SZhang Yubing ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev); 29293e05a7b8SZhang Yubing if (!ret) { 29303e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll); 29313e05a7b8SZhang Yubing if (ret) 2932c0545157SZhang Yubing printf("%s: hdmi0_phy_pll may not define\n", __func__); 29333e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll); 29343e05a7b8SZhang Yubing if (ret) 2935c0545157SZhang Yubing printf("%s: hdmi1_phy_pll may not define\n", __func__); 29363e05a7b8SZhang Yubing } else { 2937b890760eSAlgea Cao hdmi0_phy_pll.dev = NULL; 2938545a0218SAlgea Cao hdmi1_phy_pll.dev = NULL; 29393e05a7b8SZhang Yubing printf("%s: Faile to find display-subsystem node\n", __func__); 2940b890760eSAlgea Cao } 2941b890760eSAlgea Cao 2942631ee99aSZhang Yubing if (mode->clock < VOP2_MAX_DCLK_RATE) { 2943b890760eSAlgea Cao if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) 2944b890760eSAlgea Cao vop2_clk_set_parent(&dclk, &hdmi0_phy_pll); 2945b890760eSAlgea Cao else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1) 2946b890760eSAlgea Cao vop2_clk_set_parent(&dclk, &hdmi1_phy_pll); 2947b890760eSAlgea Cao 2948b890760eSAlgea Cao /* 2949b890760eSAlgea Cao * uboot clk driver won't set dclk parent's rate when use 2950b890760eSAlgea Cao * hdmi phypll as dclk source. 2951b890760eSAlgea Cao * So set dclk rate is meaningless. Set hdmi phypll rate 2952b890760eSAlgea Cao * directly. 2953b890760eSAlgea Cao */ 29545f1357a2SZhang Yubing if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) { 2955b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate * 1000); 29565f1357a2SZhang Yubing } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) { 2957b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate * 1000); 29585f1357a2SZhang Yubing } else { 29595f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev)) 29605f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 2961b890760eSAlgea Cao else 2962b890760eSAlgea Cao ret = vop2_clk_set_rate(&dclk, dclk_rate * 1000); 29635f1357a2SZhang Yubing } 2964631ee99aSZhang Yubing } else { 29655f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev)) 29665f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 29675f1357a2SZhang Yubing else 2968631ee99aSZhang Yubing ret = vop2_clk_set_rate(&dclk, dclk_rate * 1000); 2969edfef528SDamon Ding } 297063638f32SDamon Ding 297163638f32SDamon Ding if (IS_ERR_VALUE(ret)) { 297263638f32SDamon Ding printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 297363638f32SDamon Ding __func__, cstate->crtc_id, dclk_rate, ret); 297463638f32SDamon Ding return ret; 297563638f32SDamon Ding } else { 2976edfef528SDamon Ding dclk_div_factor = mode->clock / dclk_rate; 2977edfef528SDamon Ding mode->crtc_clock = ret * dclk_div_factor / 1000; 2978edfef528SDamon Ding printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); 2979631ee99aSZhang Yubing } 2980ecc31b6eSAndy Yan 298166724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 2982e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false); 298366724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 2984e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false); 298566724b9cSDamon Ding 2986d0408543SAndy Yan return 0; 2987d0408543SAndy Yan } 2988d0408543SAndy Yan 2989ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 29903e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w, 29913e39a5a1SSandy Huang uint32_t dst_h) 29923e39a5a1SSandy Huang { 29933e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 29943e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode; 29953e39a5a1SSandy Huang uint8_t gt2 = 0, gt4 = 0; 29963e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0; 29973e39a5a1SSandy Huang uint16_t hsu_filter_mode = VOP2_SCALE_UP_BIC; 29983e39a5a1SSandy Huang uint16_t hsd_filter_mode = VOP2_SCALE_DOWN_BIL; 29993e39a5a1SSandy Huang uint16_t vsu_filter_mode = VOP2_SCALE_UP_BIL; 30003e39a5a1SSandy Huang uint16_t vsd_filter_mode = VOP2_SCALE_DOWN_BIL; 3001ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 30023e39a5a1SSandy Huang 30033e39a5a1SSandy Huang if (src_h >= (4 * dst_h)) 30043e39a5a1SSandy Huang gt4 = 1; 30053e39a5a1SSandy Huang else if (src_h >= (2 * dst_h)) 30063e39a5a1SSandy Huang gt2 = 1; 30073e39a5a1SSandy Huang 30083e39a5a1SSandy Huang if (gt4) 30093e39a5a1SSandy Huang src_h >>= 2; 30103e39a5a1SSandy Huang else if (gt2) 30113e39a5a1SSandy Huang src_h >>= 1; 30123e39a5a1SSandy Huang 30133e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 30143e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 30153e39a5a1SSandy Huang 30163e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP) 30173e39a5a1SSandy Huang hscl_filter_mode = hsu_filter_mode; 30183e39a5a1SSandy Huang else 30193e39a5a1SSandy Huang hscl_filter_mode = hsd_filter_mode; 30203e39a5a1SSandy Huang 30213e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP) 30223e39a5a1SSandy Huang vscl_filter_mode = vsu_filter_mode; 30233e39a5a1SSandy Huang else 30243e39a5a1SSandy Huang vscl_filter_mode = vsd_filter_mode; 30253e39a5a1SSandy Huang 30263e39a5a1SSandy Huang /* 30273e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel 30283e39a5a1SSandy Huang * at scale down mode 30293e39a5a1SSandy Huang */ 30303e39a5a1SSandy Huang if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) { 30313e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 30323e39a5a1SSandy Huang dst_w += 1; 30333e39a5a1SSandy Huang } 30343e39a5a1SSandy Huang 30353e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 30363e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 3037ecc31b6eSAndy Yan 3038ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) { 3039ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 3040ecc31b6eSAndy Yan yfac << 16 | xfac); 3041ecc31b6eSAndy Yan 3042ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 3043ecc31b6eSAndy Yan YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, gt2, false); 3044ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 3045ecc31b6eSAndy Yan YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, gt4, false); 3046ecc31b6eSAndy Yan 3047ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 3048ecc31b6eSAndy Yan YRGB_XSCL_MODE_MASK, CLUSTER_YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 3049ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 3050ecc31b6eSAndy Yan YRGB_YSCL_MODE_MASK, CLUSTER_YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 3051ecc31b6eSAndy Yan 3052ecc31b6eSAndy Yan } else { 30533e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 30543e39a5a1SSandy Huang yfac << 16 | xfac); 30553e39a5a1SSandy Huang 305634a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 30573e39a5a1SSandy Huang YRGB_GT2_MASK, YRGB_GT2_SHIFT, gt2, false); 305834a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 30593e39a5a1SSandy Huang YRGB_GT4_MASK, YRGB_GT4_SHIFT, gt4, false); 30603e39a5a1SSandy Huang 30613e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 30623e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 30633e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 30643e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 30653e39a5a1SSandy Huang 30663e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 30673e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 30683e39a5a1SSandy Huang hscl_filter_mode, false); 30693e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 30703e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 30713e39a5a1SSandy Huang vscl_filter_mode, false); 30723e39a5a1SSandy Huang } 3073ecc31b6eSAndy Yan } 30743e39a5a1SSandy Huang 3075a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win) 3076a33b790fSDamon Ding { 3077a33b790fSDamon Ding u32 win_offset = win->reg_offset; 3078a33b790fSDamon Ding 3079a33b790fSDamon Ding if (win->type == CLUSTER_LAYER) { 3080a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK, 3081a33b790fSDamon Ding CLUSTER_AXI_ID_SHIFT, win->axi_id, false); 3082a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK, 3083a33b790fSDamon Ding CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 3084a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK, 3085a33b790fSDamon Ding CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 3086a33b790fSDamon Ding } else { 3087a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK, 3088a33b790fSDamon Ding ESMART_AXI_ID_SHIFT, win->axi_id, false); 3089a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK, 3090a33b790fSDamon Ding ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 3091a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK, 3092a33b790fSDamon Ding ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 3093a33b790fSDamon Ding } 3094a33b790fSDamon Ding } 3095a33b790fSDamon Ding 3096ecc31b6eSAndy Yan static void vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 3097d0408543SAndy Yan { 3098d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3099d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 3100d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3101d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 3102ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 3103ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 3104ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 3105ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 3106ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 3107ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 3108d0408543SAndy Yan int xvir = cstate->xvir; 3109d0408543SAndy Yan int y_mirror = 0; 311010ee9f5bSAlgea Cao int csc_mode; 3111ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 3112ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 3113ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 3114ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 3115ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 3116ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 3117d0408543SAndy Yan 3118ee01dbb2SDamon Ding if (win->splice_mode_right) { 3119ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 3120ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 3121ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 3122ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 3123ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 3124ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 3125ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 3126ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 3127ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 3128ee01dbb2SDamon Ding } 3129ee01dbb2SDamon Ding 3130ecc31b6eSAndy Yan act_info = (src_h - 1) << 16; 3131ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff; 3132ecc31b6eSAndy Yan 3133ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16; 3134ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 3135ecc31b6eSAndy Yan 3136ecc31b6eSAndy Yan dsp_stx = crtc_x; 3137ecc31b6eSAndy Yan dsp_sty = crtc_y; 3138ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 3139ecc31b6eSAndy Yan 3140ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 3141ecc31b6eSAndy Yan y_mirror = 1; 3142ecc31b6eSAndy Yan else 3143ecc31b6eSAndy Yan y_mirror = 0; 3144ecc31b6eSAndy Yan 3145ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 3146ecc31b6eSAndy Yan 3147a33b790fSDamon Ding if (vop2->version == VOP_VERSION_RK3588) 3148a33b790fSDamon Ding vop2_axi_config(vop2, win); 3149a33b790fSDamon Ding 3150ecc31b6eSAndy Yan if (y_mirror) 3151ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n"); 3152ecc31b6eSAndy Yan 3153ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 3154ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 3155ecc31b6eSAndy Yan false); 3156ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 3157ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, 3158ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 3159ecc31b6eSAndy Yan 3160ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 3161ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 3162ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 3163ecc31b6eSAndy Yan 3164ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 3165ecc31b6eSAndy Yan 3166ecc31b6eSAndy Yan csc_mode = vop2_convert_csc_mode(conn_state->color_space); 3167ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 3168ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT, 3169ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false); 3170ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 3171ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 3172ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 3173ecc31b6eSAndy Yan 3174ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 3175d0408543SAndy Yan } 3176d0408543SAndy Yan 3177ecc31b6eSAndy Yan static void vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 3178ecc31b6eSAndy Yan { 3179ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3180ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3181ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3182ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 3183ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 3184ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 3185ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 3186ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 3187ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 3188ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 3189ecc31b6eSAndy Yan int xvir = cstate->xvir; 3190ecc31b6eSAndy Yan int y_mirror = 0; 3191ecc31b6eSAndy Yan int csc_mode; 3192ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 3193ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 3194ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 3195ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 3196ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 3197ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 3198ecc31b6eSAndy Yan 3199ee01dbb2SDamon Ding if (win->splice_mode_right) { 3200ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 3201ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 3202ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 3203ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 3204ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 3205ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 3206ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 3207ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 3208ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 3209ee01dbb2SDamon Ding } 3210ee01dbb2SDamon Ding 321174bd8269SSandy Huang /* 321274bd8269SSandy Huang * This is workaround solution for IC design: 321374bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1. 321474bd8269SSandy Huang */ 321574bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) { 321674bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 321774bd8269SSandy Huang src_w -= 1; 321874bd8269SSandy Huang } 321974bd8269SSandy Huang 3220d0408543SAndy Yan act_info = (src_h - 1) << 16; 3221d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff; 3222d0408543SAndy Yan 3223d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16; 3224d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 3225d0408543SAndy Yan 3226d0408543SAndy Yan dsp_stx = crtc_x; 3227d0408543SAndy Yan dsp_sty = crtc_y; 3228d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 3229d0408543SAndy Yan 3230d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 3231d0408543SAndy Yan y_mirror = 1; 3232d0408543SAndy Yan else 3233d0408543SAndy Yan y_mirror = 0; 3234d0408543SAndy Yan 3235ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 32363e39a5a1SSandy Huang 3237a33b790fSDamon Ding if (vop2->version == VOP_VERSION_RK3588) 3238a33b790fSDamon Ding vop2_axi_config(vop2, win); 3239a33b790fSDamon Ding 3240d0408543SAndy Yan if (y_mirror) 3241d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4; 3242d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 3243d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false); 3244d0408543SAndy Yan 3245d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 3246d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 3247d0408543SAndy Yan false); 3248d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 3249d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 3250ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 3251d0408543SAndy Yan 3252d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 3253d0408543SAndy Yan act_info); 3254d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 3255d0408543SAndy Yan dsp_info); 3256d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 3257d0408543SAndy Yan 3258d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 3259d0408543SAndy Yan WIN_EN_SHIFT, 1, false); 3260d0408543SAndy Yan 326110ee9f5bSAlgea Cao csc_mode = vop2_convert_csc_mode(conn_state->color_space); 326210ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 326310ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT, 326410ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false); 326510ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 326610ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false); 326710ee9f5bSAlgea Cao 3268d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 3269ecc31b6eSAndy Yan } 3270ecc31b6eSAndy Yan 3271ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state) 3272ee01dbb2SDamon Ding { 3273ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 3274ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 3275ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3276ee01dbb2SDamon Ding struct display_rect *src_rect = &cstate->src_rect; 3277ee01dbb2SDamon Ding struct display_rect *dst_rect = &cstate->crtc_rect; 3278ee01dbb2SDamon Ding struct display_rect left_src, left_dst, right_src, right_dst; 3279ee01dbb2SDamon Ding u16 half_hdisplay = mode->crtc_hdisplay >> 1; 3280ee01dbb2SDamon Ding int left_src_w, left_dst_w, right_dst_w; 3281ee01dbb2SDamon Ding 3282ee01dbb2SDamon Ding left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x; 3283ee01dbb2SDamon Ding if (left_dst_w < 0) 3284ee01dbb2SDamon Ding left_dst_w = 0; 3285ee01dbb2SDamon Ding right_dst_w = dst_rect->w - left_dst_w; 3286ee01dbb2SDamon Ding 3287ee01dbb2SDamon Ding if (!right_dst_w) 3288ee01dbb2SDamon Ding left_src_w = src_rect->w; 3289ee01dbb2SDamon Ding else 32900df0fd39SSandy Huang left_src_w = src_rect->x + src_rect->w - src_rect->w / 2; 3291ee01dbb2SDamon Ding 3292ee01dbb2SDamon Ding left_src.x = src_rect->x; 3293ee01dbb2SDamon Ding left_src.w = left_src_w; 3294ee01dbb2SDamon Ding left_dst.x = dst_rect->x; 3295ee01dbb2SDamon Ding left_dst.w = left_dst_w; 3296ee01dbb2SDamon Ding right_src.x = left_src.x + left_src.w; 3297ee01dbb2SDamon Ding right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w; 3298ee01dbb2SDamon Ding right_dst.x = dst_rect->x + left_dst_w - half_hdisplay; 3299ee01dbb2SDamon Ding right_dst.w = right_dst_w; 3300ee01dbb2SDamon Ding 3301ee01dbb2SDamon Ding left_src.y = src_rect->y; 3302ee01dbb2SDamon Ding left_src.h = src_rect->h; 3303ee01dbb2SDamon Ding left_dst.y = dst_rect->y; 3304ee01dbb2SDamon Ding left_dst.h = dst_rect->h; 3305ee01dbb2SDamon Ding right_src.y = src_rect->y; 3306ee01dbb2SDamon Ding right_src.h = src_rect->h; 3307ee01dbb2SDamon Ding right_dst.y = dst_rect->y; 3308ee01dbb2SDamon Ding right_dst.h = dst_rect->h; 3309ee01dbb2SDamon Ding 3310ee01dbb2SDamon Ding memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect)); 3311ee01dbb2SDamon Ding memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect)); 3312ee01dbb2SDamon Ding memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect)); 3313ee01dbb2SDamon Ding memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect)); 3314ee01dbb2SDamon Ding } 3315ee01dbb2SDamon Ding 3316ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state) 3317ecc31b6eSAndy Yan { 3318ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3319ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 3320ecc31b6eSAndy Yan struct vop2_win_data *win_data; 3321ee01dbb2SDamon Ding struct vop2_win_data *splice_win_data; 3322ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 3323ecc31b6eSAndy Yan char plane_name[10] = {0}; 3324ecc31b6eSAndy Yan 3325ee01dbb2SDamon Ding if (cstate->crtc_rect.w > cstate->max_output.width) { 3326ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n", 3327ee01dbb2SDamon Ding cstate->crtc_rect.w, cstate->max_output.width); 3328ecc31b6eSAndy Yan return -EINVAL; 3329ecc31b6eSAndy Yan } 3330ecc31b6eSAndy Yan 3331ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 3332ecc31b6eSAndy Yan if (!win_data) { 3333ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id); 3334ecc31b6eSAndy Yan return -ENODEV; 3335ecc31b6eSAndy Yan } 3336ecc31b6eSAndy Yan 3337b6ba80b4SDamon Ding if (vop2->version == VOP_VERSION_RK3588) { 3338b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, win_data->pd_id)) 3339b6ba80b4SDamon Ding printf("open vp%d plane pd fail\n", cstate->crtc_id); 3340b6ba80b4SDamon Ding } 3341b6ba80b4SDamon Ding 3342ee01dbb2SDamon Ding if (cstate->splice_mode) { 3343ee01dbb2SDamon Ding if (win_data->splice_win_id) { 3344ee01dbb2SDamon Ding splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id); 3345ee01dbb2SDamon Ding splice_win_data->splice_mode_right = true; 3346b6ba80b4SDamon Ding 3347b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, splice_win_data->pd_id)) 3348b6ba80b4SDamon Ding printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id); 3349b6ba80b4SDamon Ding 3350ee01dbb2SDamon Ding vop2_calc_display_rect_for_splice(state); 3351ee01dbb2SDamon Ding if (win_data->type == CLUSTER_LAYER) 3352ee01dbb2SDamon Ding vop2_set_cluster_win(state, splice_win_data); 3353ee01dbb2SDamon Ding else 3354ee01dbb2SDamon Ding vop2_set_smart_win(state, splice_win_data); 3355ee01dbb2SDamon Ding } else { 3356ee01dbb2SDamon Ding printf("ERROR: splice mode is unsupported by plane %s\n", 3357ee01dbb2SDamon Ding get_plane_name(primary_plane_id, plane_name)); 3358ee01dbb2SDamon Ding return -EINVAL; 3359ee01dbb2SDamon Ding } 3360ee01dbb2SDamon Ding } 3361ee01dbb2SDamon Ding 3362ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER) 3363ecc31b6eSAndy Yan vop2_set_cluster_win(state, win_data); 3364ecc31b6eSAndy Yan else 3365ecc31b6eSAndy Yan vop2_set_smart_win(state, win_data); 33668895aec1SSandy Huang 33678895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 33688895aec1SSandy Huang cstate->crtc_id, get_plane_name(primary_plane_id, plane_name), 3369ee01dbb2SDamon Ding cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h, 3370ee01dbb2SDamon Ding cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format, 33718895aec1SSandy Huang cstate->dma_addr); 33728895aec1SSandy Huang 3373d0408543SAndy Yan return 0; 3374d0408543SAndy Yan } 3375d0408543SAndy Yan 3376d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state) 3377d0408543SAndy Yan { 3378d0408543SAndy Yan return 0; 3379d0408543SAndy Yan } 3380d0408543SAndy Yan 338112ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state) 338212ee5af0SDamon Ding { 338312ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 338412ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 338512ee5af0SDamon Ding struct vop2 *vop2 = cstate->private; 338612ee5af0SDamon Ding u8 dsc_id = cstate->dsc_id; 338712ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 338812ee5af0SDamon Ding 338912ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 339012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK, 339112ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 339212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK, 339312ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 339412ee5af0SDamon Ding } else { 339512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK, 339612ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 339712ee5af0SDamon Ding } 339812ee5af0SDamon Ding } 339912ee5af0SDamon Ding 3400d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state) 3401d0408543SAndy Yan { 3402d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3403d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 340452ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 3405ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 3406d0408543SAndy Yan 3407d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3408d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false); 3409ee01dbb2SDamon Ding 3410ee01dbb2SDamon Ding if (cstate->splice_mode) 3411ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 3412ee01dbb2SDamon Ding 3413d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 3414d0408543SAndy Yan 341512ee5af0SDamon Ding if (cstate->dsc_enable) 341612ee5af0SDamon Ding vop2_dsc_cfg_done(state); 341712ee5af0SDamon Ding 3418d0408543SAndy Yan return 0; 3419d0408543SAndy Yan } 3420d0408543SAndy Yan 3421d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state) 3422d0408543SAndy Yan { 3423d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3424d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 342552ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 3426ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 3427d0408543SAndy Yan 3428d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3429d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false); 3430ee01dbb2SDamon Ding 3431ee01dbb2SDamon Ding if (cstate->splice_mode) 3432ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 3433ee01dbb2SDamon Ding 3434d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 3435d0408543SAndy Yan 3436d0408543SAndy Yan return 0; 3437d0408543SAndy Yan } 3438d0408543SAndy Yan 3439ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 3440ee008497SSandy Huang { 3441ee008497SSandy Huang struct crtc_state *cstate = &state->crtc_state; 3442ee008497SSandy Huang struct vop2 *vop2 = cstate->private; 3443ee008497SSandy Huang int i = 0; 3444ee008497SSandy Huang int correct_cursor_plane = -1; 3445ee008497SSandy Huang int plane_type = -1; 3446ee008497SSandy Huang 3447ee008497SSandy Huang if (cursor_plane < 0) 3448ee008497SSandy Huang return -1; 3449ee008497SSandy Huang 3450ee008497SSandy Huang if (plane_mask & (1 << cursor_plane)) 3451ee008497SSandy Huang return cursor_plane; 3452ee008497SSandy Huang 3453ee008497SSandy Huang /* Get current cursor plane type */ 3454ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 3455ee008497SSandy Huang if (vop2->data->plane_table[i].plane_id == cursor_plane) { 3456ee008497SSandy Huang plane_type = vop2->data->plane_table[i].plane_type; 3457ee008497SSandy Huang break; 3458ee008497SSandy Huang } 3459ee008497SSandy Huang } 3460ee008497SSandy Huang 3461ee008497SSandy Huang /* Get the other same plane type plane id */ 3462ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 3463ee008497SSandy Huang if (vop2->data->plane_table[i].plane_type == plane_type && 3464ee008497SSandy Huang vop2->data->plane_table[i].plane_id != cursor_plane) { 3465ee008497SSandy Huang correct_cursor_plane = vop2->data->plane_table[i].plane_id; 3466ee008497SSandy Huang break; 3467ee008497SSandy Huang } 3468ee008497SSandy Huang } 3469ee008497SSandy Huang 3470ee008497SSandy Huang /* To check whether the new correct_cursor_plane is attach to current vp */ 3471ee008497SSandy Huang if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 3472ee008497SSandy Huang printf("error: faild to find correct plane as cursor plane\n"); 3473ee008497SSandy Huang return -1; 3474ee008497SSandy Huang } 3475ee008497SSandy Huang 3476ee008497SSandy Huang printf("vp%d adjust cursor plane from %d to %d\n", 3477ee008497SSandy Huang cstate->crtc_id, cursor_plane, correct_cursor_plane); 3478ee008497SSandy Huang 3479ee008497SSandy Huang return correct_cursor_plane; 3480ee008497SSandy Huang } 3481ee008497SSandy Huang 3482b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 3483b0989546SSandy Huang { 3484b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 3485b0989546SSandy Huang struct vop2 *vop2 = cstate->private; 3486b0989546SSandy Huang ofnode vp_node; 3487b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node; 3488b0989546SSandy Huang static bool vop_fix_dts; 3489b0989546SSandy Huang const char *path; 3490b0989546SSandy Huang u32 plane_mask = 0; 3491b0989546SSandy Huang int vp_id = 0; 3492ee008497SSandy Huang int cursor_plane_id = -1; 3493b0989546SSandy Huang 3494b0989546SSandy Huang if (vop_fix_dts) 3495b0989546SSandy Huang return 0; 3496b0989546SSandy Huang 3497b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 3498b0989546SSandy Huang path = vp_node.np->full_name; 3499b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 3500b0989546SSandy Huang 35018b1fe597SSandy Huang if (cstate->crtc->assign_plane) 35028b1fe597SSandy Huang continue; 3503ee008497SSandy Huang cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 3504ee008497SSandy Huang cstate->crtc->vps[vp_id].cursor_plane); 3505ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 3506b0989546SSandy Huang vp_id, plane_mask, 3507ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 3508ee008497SSandy Huang cursor_plane_id); 3509b0989546SSandy Huang 3510b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 3511b0989546SSandy Huang plane_mask, 1); 3512b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 3513b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 3514ee008497SSandy Huang if (cursor_plane_id >= 0) 3515ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id", 3516ee008497SSandy Huang cursor_plane_id, 1); 3517b0989546SSandy Huang vp_id++; 3518b0989546SSandy Huang } 3519b0989546SSandy Huang 3520b0989546SSandy Huang vop_fix_dts = true; 3521b0989546SSandy Huang 3522b0989546SSandy Huang return 0; 3523b0989546SSandy Huang } 3524b0989546SSandy Huang 3525ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 3526ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 3527ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 3528ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 3529ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 3530ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 3531ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 3532ee008497SSandy Huang }; 3533ee008497SSandy Huang 3534b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 3535b0989546SSandy Huang { /* one display policy */ 3536b0989546SSandy Huang {/* main display */ 3537b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 3538b0989546SSandy Huang .attached_layers_nr = 6, 3539b0989546SSandy Huang .attached_layers = { 3540b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 3541b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 3542b0989546SSandy Huang }, 3543b0989546SSandy Huang }, 3544b0989546SSandy Huang {/* second display */}, 3545b0989546SSandy Huang {/* third display */}, 3546b0989546SSandy Huang {/* fourth display */}, 3547b0989546SSandy Huang }, 3548b0989546SSandy Huang 3549b0989546SSandy Huang { /* two display policy */ 3550b0989546SSandy Huang {/* main display */ 3551b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 3552b0989546SSandy Huang .attached_layers_nr = 3, 3553b0989546SSandy Huang .attached_layers = { 3554b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 3555b0989546SSandy Huang }, 3556b0989546SSandy Huang }, 3557b0989546SSandy Huang 3558b0989546SSandy Huang {/* second display */ 3559b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 3560b0989546SSandy Huang .attached_layers_nr = 3, 3561b0989546SSandy Huang .attached_layers = { 3562b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 3563b0989546SSandy Huang }, 3564b0989546SSandy Huang }, 3565b0989546SSandy Huang {/* third display */}, 3566b0989546SSandy Huang {/* fourth display */}, 3567b0989546SSandy Huang }, 3568b0989546SSandy Huang 3569b0989546SSandy Huang { /* three display policy */ 3570b0989546SSandy Huang {/* main display */ 3571b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 3572b0989546SSandy Huang .attached_layers_nr = 3, 3573b0989546SSandy Huang .attached_layers = { 3574b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 3575b0989546SSandy Huang }, 3576b0989546SSandy Huang }, 3577b0989546SSandy Huang 3578b0989546SSandy Huang {/* second display */ 3579b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 3580b0989546SSandy Huang .attached_layers_nr = 2, 3581b0989546SSandy Huang .attached_layers = { 3582b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 3583b0989546SSandy Huang }, 3584b0989546SSandy Huang }, 3585b0989546SSandy Huang 3586b0989546SSandy Huang {/* third display */ 3587b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 3588b0989546SSandy Huang .attached_layers_nr = 1, 3589b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 3590b0989546SSandy Huang }, 3591b0989546SSandy Huang 3592b0989546SSandy Huang {/* fourth display */}, 3593b0989546SSandy Huang }, 3594b0989546SSandy Huang 3595b0989546SSandy Huang {/* reserved for four display policy */}, 3596b0989546SSandy Huang }; 3597b0989546SSandy Huang 3598b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = { 3599b0989546SSandy Huang { 3600b0989546SSandy Huang .name = "Cluster0", 3601b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0, 3602ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 3603b0989546SSandy Huang .win_sel_port_offset = 0, 3604b0989546SSandy Huang .layer_sel_win_id = 0, 3605b0989546SSandy Huang .reg_offset = 0, 3606b0989546SSandy Huang }, 3607b0989546SSandy Huang 3608b0989546SSandy Huang { 3609b0989546SSandy Huang .name = "Cluster1", 3610b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1, 3611ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 3612b0989546SSandy Huang .win_sel_port_offset = 1, 3613b0989546SSandy Huang .layer_sel_win_id = 1, 3614b0989546SSandy Huang .reg_offset = 0x200, 3615b0989546SSandy Huang }, 3616b0989546SSandy Huang 3617b0989546SSandy Huang { 3618b0989546SSandy Huang .name = "Esmart0", 3619b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0, 3620ecc31b6eSAndy Yan .type = ESMART_LAYER, 3621b0989546SSandy Huang .win_sel_port_offset = 4, 3622b0989546SSandy Huang .layer_sel_win_id = 2, 3623b0989546SSandy Huang .reg_offset = 0, 3624b0989546SSandy Huang }, 3625b0989546SSandy Huang 3626b0989546SSandy Huang { 3627b0989546SSandy Huang .name = "Esmart1", 3628b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1, 3629ecc31b6eSAndy Yan .type = ESMART_LAYER, 3630b0989546SSandy Huang .win_sel_port_offset = 5, 3631b0989546SSandy Huang .layer_sel_win_id = 6, 3632b0989546SSandy Huang .reg_offset = 0x200, 3633b0989546SSandy Huang }, 3634b0989546SSandy Huang 3635b0989546SSandy Huang { 3636b0989546SSandy Huang .name = "Smart0", 3637b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0, 3638ecc31b6eSAndy Yan .type = SMART_LAYER, 3639b0989546SSandy Huang .win_sel_port_offset = 6, 3640b0989546SSandy Huang .layer_sel_win_id = 3, 3641b0989546SSandy Huang .reg_offset = 0x400, 3642b0989546SSandy Huang }, 3643b0989546SSandy Huang 3644b0989546SSandy Huang { 3645b0989546SSandy Huang .name = "Smart1", 3646b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1, 3647ecc31b6eSAndy Yan .type = SMART_LAYER, 3648b0989546SSandy Huang .win_sel_port_offset = 7, 3649b0989546SSandy Huang .layer_sel_win_id = 7, 3650b0989546SSandy Huang .reg_offset = 0x600, 3651b0989546SSandy Huang }, 3652b0989546SSandy Huang }; 3653b0989546SSandy Huang 365463cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = { 365563cb669fSSandy Huang { 365663cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT, 365763cb669fSSandy Huang .pre_scan_max_dly = 42, 365863cb669fSSandy Huang .max_output = {4096, 2304}, 3659d0408543SAndy Yan }, 366063cb669fSSandy Huang { 366163cb669fSSandy Huang .feature = 0, 366263cb669fSSandy Huang .pre_scan_max_dly = 40, 366363cb669fSSandy Huang .max_output = {2048, 1536}, 366463cb669fSSandy Huang }, 366563cb669fSSandy Huang { 366663cb669fSSandy Huang .feature = 0, 366763cb669fSSandy Huang .pre_scan_max_dly = 40, 366863cb669fSSandy Huang .max_output = {1920, 1080}, 366963cb669fSSandy Huang }, 367063cb669fSSandy Huang }; 3671d0408543SAndy Yan 367263cb669fSSandy Huang const struct vop2_data rk3568_vop = { 3673ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568, 367463cb669fSSandy Huang .nr_vps = 3, 367563cb669fSSandy Huang .vp_data = rk3568_vp_data, 3676b0989546SSandy Huang .win_data = rk3568_win_data, 3677b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0], 3678ee008497SSandy Huang .plane_table = rk356x_plane_table, 3679d0408543SAndy Yan .nr_layers = 6, 368063cb669fSSandy Huang .nr_mixers = 5, 36811147facaSSandy Huang .nr_gammas = 1, 3682d0408543SAndy Yan }; 3683d0408543SAndy Yan 3684ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 3685ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 3686ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 3687ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 3688ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 3689ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 3690ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 3691ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 3692ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 3693ecc31b6eSAndy Yan }; 3694ecc31b6eSAndy Yan 3695ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 3696ecc31b6eSAndy Yan { /* one display policy */ 3697ecc31b6eSAndy Yan {/* main display */ 3698ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 3699ecc31b6eSAndy Yan .attached_layers_nr = 8, 3700ecc31b6eSAndy Yan .attached_layers = { 3701ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, 3702ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, 3703ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 3704ecc31b6eSAndy Yan }, 3705ecc31b6eSAndy Yan }, 3706ecc31b6eSAndy Yan {/* second display */}, 3707ecc31b6eSAndy Yan {/* third display */}, 3708ecc31b6eSAndy Yan {/* fourth display */}, 3709ecc31b6eSAndy Yan }, 3710ecc31b6eSAndy Yan 3711ecc31b6eSAndy Yan { /* two display policy */ 3712ecc31b6eSAndy Yan {/* main display */ 3713ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 3714ecc31b6eSAndy Yan .attached_layers_nr = 4, 3715ecc31b6eSAndy Yan .attached_layers = { 3716ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 3717ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 3718ecc31b6eSAndy Yan }, 3719ecc31b6eSAndy Yan }, 3720ecc31b6eSAndy Yan 3721ecc31b6eSAndy Yan {/* second display */ 3722ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 3723ecc31b6eSAndy Yan .attached_layers_nr = 4, 3724ecc31b6eSAndy Yan .attached_layers = { 3725ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, 3726ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 3727ecc31b6eSAndy Yan }, 3728ecc31b6eSAndy Yan }, 3729ecc31b6eSAndy Yan {/* third display */}, 3730ecc31b6eSAndy Yan {/* fourth display */}, 3731ecc31b6eSAndy Yan }, 3732ecc31b6eSAndy Yan 3733ecc31b6eSAndy Yan { /* three display policy */ 3734ecc31b6eSAndy Yan {/* main display */ 3735ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 3736ecc31b6eSAndy Yan .attached_layers_nr = 3, 3737ecc31b6eSAndy Yan .attached_layers = { 3738ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 3739ecc31b6eSAndy Yan }, 3740ecc31b6eSAndy Yan }, 3741ecc31b6eSAndy Yan 3742ecc31b6eSAndy Yan {/* second display */ 3743ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 3744ecc31b6eSAndy Yan .attached_layers_nr = 3, 3745ecc31b6eSAndy Yan .attached_layers = { 3746ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 3747ecc31b6eSAndy Yan }, 3748ecc31b6eSAndy Yan }, 3749ecc31b6eSAndy Yan 3750ecc31b6eSAndy Yan {/* third display */ 3751ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 3752ecc31b6eSAndy Yan .attached_layers_nr = 2, 3753ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 3754ecc31b6eSAndy Yan }, 3755ecc31b6eSAndy Yan 3756ecc31b6eSAndy Yan {/* fourth display */}, 3757ecc31b6eSAndy Yan }, 3758ecc31b6eSAndy Yan 3759ecc31b6eSAndy Yan { /* four display policy */ 3760ecc31b6eSAndy Yan {/* main display */ 3761ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 3762ecc31b6eSAndy Yan .attached_layers_nr = 2, 3763ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 3764ecc31b6eSAndy Yan }, 3765ecc31b6eSAndy Yan 3766ecc31b6eSAndy Yan {/* second display */ 3767ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER1, 3768ecc31b6eSAndy Yan .attached_layers_nr = 2, 3769ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 3770ecc31b6eSAndy Yan }, 3771ecc31b6eSAndy Yan 3772ecc31b6eSAndy Yan {/* third display */ 3773ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 3774ecc31b6eSAndy Yan .attached_layers_nr = 2, 3775ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 3776ecc31b6eSAndy Yan }, 3777ecc31b6eSAndy Yan 3778ecc31b6eSAndy Yan {/* fourth display */ 3779ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER3, 3780ecc31b6eSAndy Yan .attached_layers_nr = 2, 3781ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 3782ecc31b6eSAndy Yan }, 3783ecc31b6eSAndy Yan }, 3784ecc31b6eSAndy Yan 3785ecc31b6eSAndy Yan }; 3786ecc31b6eSAndy Yan 3787ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = { 3788ecc31b6eSAndy Yan { 3789ecc31b6eSAndy Yan .name = "Cluster0", 3790ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0, 3791ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER1, 3792ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 3793ecc31b6eSAndy Yan .win_sel_port_offset = 0, 3794ecc31b6eSAndy Yan .layer_sel_win_id = 0, 3795ecc31b6eSAndy Yan .reg_offset = 0, 3796a33b790fSDamon Ding .axi_id = 0, 3797a33b790fSDamon Ding .axi_yrgb_id = 2, 3798a33b790fSDamon Ding .axi_uv_id = 3, 3799b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER0, 3800ecc31b6eSAndy Yan }, 3801ecc31b6eSAndy Yan 3802ecc31b6eSAndy Yan { 3803ecc31b6eSAndy Yan .name = "Cluster1", 3804ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1, 3805ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 3806ecc31b6eSAndy Yan .win_sel_port_offset = 1, 3807ecc31b6eSAndy Yan .layer_sel_win_id = 1, 3808ecc31b6eSAndy Yan .reg_offset = 0x200, 3809a33b790fSDamon Ding .axi_id = 0, 3810a33b790fSDamon Ding .axi_yrgb_id = 6, 3811a33b790fSDamon Ding .axi_uv_id = 7, 3812b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER1, 3813ecc31b6eSAndy Yan }, 3814ecc31b6eSAndy Yan 3815ecc31b6eSAndy Yan { 3816ecc31b6eSAndy Yan .name = "Cluster2", 3817ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2, 3818ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER3, 3819ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 3820ecc31b6eSAndy Yan .win_sel_port_offset = 2, 3821ecc31b6eSAndy Yan .layer_sel_win_id = 4, 3822ecc31b6eSAndy Yan .reg_offset = 0x400, 3823a33b790fSDamon Ding .axi_id = 1, 3824a33b790fSDamon Ding .axi_yrgb_id = 2, 3825a33b790fSDamon Ding .axi_uv_id = 3, 3826b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER2, 3827ecc31b6eSAndy Yan }, 3828ecc31b6eSAndy Yan 3829ecc31b6eSAndy Yan { 3830ecc31b6eSAndy Yan .name = "Cluster3", 3831ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3, 3832ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 3833ecc31b6eSAndy Yan .win_sel_port_offset = 3, 3834ecc31b6eSAndy Yan .layer_sel_win_id = 5, 3835ecc31b6eSAndy Yan .reg_offset = 0x600, 3836a33b790fSDamon Ding .axi_id = 1, 3837a33b790fSDamon Ding .axi_yrgb_id = 6, 3838a33b790fSDamon Ding .axi_uv_id = 7, 3839b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER3, 3840ecc31b6eSAndy Yan }, 3841ecc31b6eSAndy Yan 3842ecc31b6eSAndy Yan { 3843ecc31b6eSAndy Yan .name = "Esmart0", 3844ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0, 3845ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART1, 3846ecc31b6eSAndy Yan .type = ESMART_LAYER, 3847ecc31b6eSAndy Yan .win_sel_port_offset = 4, 3848ecc31b6eSAndy Yan .layer_sel_win_id = 2, 3849ecc31b6eSAndy Yan .reg_offset = 0, 3850a33b790fSDamon Ding .axi_id = 0, 3851a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 3852a33b790fSDamon Ding .axi_uv_id = 0x0b, 3853ecc31b6eSAndy Yan }, 3854ecc31b6eSAndy Yan 3855ecc31b6eSAndy Yan { 3856ecc31b6eSAndy Yan .name = "Esmart1", 3857ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1, 3858ecc31b6eSAndy Yan .type = ESMART_LAYER, 3859ecc31b6eSAndy Yan .win_sel_port_offset = 5, 3860ecc31b6eSAndy Yan .layer_sel_win_id = 3, 3861ecc31b6eSAndy Yan .reg_offset = 0x200, 3862a33b790fSDamon Ding .axi_id = 0, 3863a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 3864a33b790fSDamon Ding .axi_uv_id = 0x0d, 3865b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 3866ecc31b6eSAndy Yan }, 3867ecc31b6eSAndy Yan 3868ecc31b6eSAndy Yan { 3869ecc31b6eSAndy Yan .name = "Esmart2", 3870ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2, 3871ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART3, 3872ecc31b6eSAndy Yan .type = ESMART_LAYER, 3873ecc31b6eSAndy Yan .win_sel_port_offset = 6, 3874ecc31b6eSAndy Yan .layer_sel_win_id = 6, 3875ecc31b6eSAndy Yan .reg_offset = 0x400, 3876a33b790fSDamon Ding .axi_id = 1, 3877a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 3878a33b790fSDamon Ding .axi_uv_id = 0x0b, 3879b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 3880ecc31b6eSAndy Yan }, 3881ecc31b6eSAndy Yan 3882ecc31b6eSAndy Yan { 3883ecc31b6eSAndy Yan .name = "Esmart3", 3884ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3, 3885ecc31b6eSAndy Yan .type = ESMART_LAYER, 3886ecc31b6eSAndy Yan .win_sel_port_offset = 7, 3887ecc31b6eSAndy Yan .layer_sel_win_id = 7, 3888ecc31b6eSAndy Yan .reg_offset = 0x600, 3889a33b790fSDamon Ding .axi_id = 1, 3890a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 3891a33b790fSDamon Ding .axi_uv_id = 0x0d, 3892b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 3893ecc31b6eSAndy Yan }, 3894ecc31b6eSAndy Yan }; 3895ecc31b6eSAndy Yan 389612ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = { 389712ee5af0SDamon Ding {0x00000000, "no error detected by DSC encoder"}, 389812ee5af0SDamon Ding {0x0030ffff, "bits per component error"}, 389912ee5af0SDamon Ding {0x0040ffff, "multiple mode error"}, 390012ee5af0SDamon Ding {0x0050ffff, "line buffer depth error"}, 390112ee5af0SDamon Ding {0x0060ffff, "minor version error"}, 390212ee5af0SDamon Ding {0x0070ffff, "picture height error"}, 390312ee5af0SDamon Ding {0x0080ffff, "picture width error"}, 390412ee5af0SDamon Ding {0x0090ffff, "number of slices error"}, 390512ee5af0SDamon Ding {0x00c0ffff, "slice height Error "}, 390612ee5af0SDamon Ding {0x00d0ffff, "slice width error"}, 390712ee5af0SDamon Ding {0x00e0ffff, "second line BPG offset error"}, 390812ee5af0SDamon Ding {0x00f0ffff, "non second line BPG offset error"}, 390912ee5af0SDamon Ding {0x0100ffff, "PPS ID error"}, 391012ee5af0SDamon Ding {0x0110ffff, "bits per pixel (BPP) Error"}, 391112ee5af0SDamon Ding {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */ 391212ee5af0SDamon Ding 391312ee5af0SDamon Ding {0x01510001, "slice 0 RC buffer model overflow error"}, 391412ee5af0SDamon Ding {0x01510002, "slice 1 RC buffer model overflow error"}, 391512ee5af0SDamon Ding {0x01510004, "slice 2 RC buffer model overflow error"}, 391612ee5af0SDamon Ding {0x01510008, "slice 3 RC buffer model overflow error"}, 391712ee5af0SDamon Ding {0x01510010, "slice 4 RC buffer model overflow error"}, 391812ee5af0SDamon Ding {0x01510020, "slice 5 RC buffer model overflow error"}, 391912ee5af0SDamon Ding {0x01510040, "slice 6 RC buffer model overflow error"}, 392012ee5af0SDamon Ding {0x01510080, "slice 7 RC buffer model overflow error"}, 392112ee5af0SDamon Ding 392212ee5af0SDamon Ding {0x01610001, "slice 0 RC buffer model underflow error"}, 392312ee5af0SDamon Ding {0x01610002, "slice 1 RC buffer model underflow error"}, 392412ee5af0SDamon Ding {0x01610004, "slice 2 RC buffer model underflow error"}, 392512ee5af0SDamon Ding {0x01610008, "slice 3 RC buffer model underflow error"}, 392612ee5af0SDamon Ding {0x01610010, "slice 4 RC buffer model underflow error"}, 392712ee5af0SDamon Ding {0x01610020, "slice 5 RC buffer model underflow error"}, 392812ee5af0SDamon Ding {0x01610040, "slice 6 RC buffer model underflow error"}, 392912ee5af0SDamon Ding {0x01610080, "slice 7 RC buffer model underflow error"}, 393012ee5af0SDamon Ding 393112ee5af0SDamon Ding {0xffffffff, "unsuccessful RESET cycle status"}, 393212ee5af0SDamon Ding {0x00a0ffff, "ICH full error precision settings error"}, 393312ee5af0SDamon Ding {0x0020ffff, "native mode"}, 393412ee5af0SDamon Ding }; 393512ee5af0SDamon Ding 393612ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = { 393712ee5af0SDamon Ding {0x00000000, "rate buffer status"}, 393812ee5af0SDamon Ding {0x00000001, "line buffer status"}, 393912ee5af0SDamon Ding {0x00000002, "decoder model status"}, 394012ee5af0SDamon Ding {0x00000003, "pixel buffer status"}, 394112ee5af0SDamon Ding {0x00000004, "balance fifo buffer status"}, 394212ee5af0SDamon Ding {0x00000005, "syntax element fifo status"}, 394312ee5af0SDamon Ding }; 394412ee5af0SDamon Ding 394512ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = { 394612ee5af0SDamon Ding { 394712ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_8K, 394812ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_8K, 394912ee5af0SDamon Ding .max_slice_num = 8, 395012ee5af0SDamon Ding .max_linebuf_depth = 11, 3951b61227a3SDamon Ding .min_bits_per_pixel = 8, 395212ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src", 395312ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_8k_txp_clk", 395412ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_8k_pxl_clk", 395512ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_8k_cds_clk", 395612ee5af0SDamon Ding }, 395712ee5af0SDamon Ding 395812ee5af0SDamon Ding { 395912ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_4K, 396012ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_4K, 396112ee5af0SDamon Ding .max_slice_num = 2, 396212ee5af0SDamon Ding .max_linebuf_depth = 11, 3963b61227a3SDamon Ding .min_bits_per_pixel = 8, 396412ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src", 396512ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_4k_txp_clk", 396612ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_4k_pxl_clk", 396712ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_4k_cds_clk", 396812ee5af0SDamon Ding }, 396912ee5af0SDamon Ding }; 397012ee5af0SDamon Ding 3971ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = { 3972ecc31b6eSAndy Yan { 3973ee01dbb2SDamon Ding .splice_vp_id = 1, 3974ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 3975b890760eSAlgea Cao .pre_scan_max_dly = 54, 3976ecc31b6eSAndy Yan .max_dclk = 600000, 3977ecc31b6eSAndy Yan .max_output = {7680, 4320}, 3978ecc31b6eSAndy Yan }, 3979ecc31b6eSAndy Yan { 3980ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 3981ee01dbb2SDamon Ding .pre_scan_max_dly = 54, 3982ecc31b6eSAndy Yan .max_dclk = 600000, 3983ecc31b6eSAndy Yan .max_output = {4096, 2304}, 3984ecc31b6eSAndy Yan }, 3985ecc31b6eSAndy Yan { 3986ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 3987ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 3988ecc31b6eSAndy Yan .max_dclk = 600000, 3989ecc31b6eSAndy Yan .max_output = {4096, 2304}, 3990ecc31b6eSAndy Yan }, 3991ecc31b6eSAndy Yan { 3992ecc31b6eSAndy Yan .feature = 0, 3993ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 3994ecc31b6eSAndy Yan .max_dclk = 200000, 3995ecc31b6eSAndy Yan .max_output = {1920, 1080}, 3996ecc31b6eSAndy Yan }, 3997ecc31b6eSAndy Yan }; 3998ecc31b6eSAndy Yan 3999b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = { 4000b6ba80b4SDamon Ding { 4001b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER0, 4002b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0), 4003b6ba80b4SDamon Ding }, 4004b6ba80b4SDamon Ding { 4005b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER1, 4006b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1), 4007b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 4008b6ba80b4SDamon Ding }, 4009b6ba80b4SDamon Ding { 4010b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER2, 4011b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2), 4012b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 4013b6ba80b4SDamon Ding }, 4014b6ba80b4SDamon Ding { 4015b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER3, 4016b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3), 4017b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 4018b6ba80b4SDamon Ding }, 4019b6ba80b4SDamon Ding { 4020b6ba80b4SDamon Ding .id = VOP2_PD_ESMART, 4021b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) | 4022b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | 4023b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART3), 4024b6ba80b4SDamon Ding }, 4025b6ba80b4SDamon Ding { 4026b6ba80b4SDamon Ding .id = VOP2_PD_DSC_8K, 4027b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K), 4028b6ba80b4SDamon Ding }, 4029b6ba80b4SDamon Ding { 4030b6ba80b4SDamon Ding .id = VOP2_PD_DSC_4K, 4031b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K), 4032b6ba80b4SDamon Ding }, 4033b6ba80b4SDamon Ding }; 4034b6ba80b4SDamon Ding 4035ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = { 4036ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588, 4037ecc31b6eSAndy Yan .nr_vps = 4, 4038ecc31b6eSAndy Yan .vp_data = rk3588_vp_data, 4039ecc31b6eSAndy Yan .win_data = rk3588_win_data, 4040ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0], 4041ecc31b6eSAndy Yan .plane_table = rk3588_plane_table, 4042b6ba80b4SDamon Ding .pd = rk3588_vop_pd_data, 404312ee5af0SDamon Ding .dsc = rk3588_dsc_data, 404412ee5af0SDamon Ding .dsc_error_ecw = dsc_ecw, 404512ee5af0SDamon Ding .dsc_error_buffer_flow = dsc_buffer_flow, 4046ecc31b6eSAndy Yan .nr_layers = 8, 4047ecc31b6eSAndy Yan .nr_mixers = 7, 4048ecc31b6eSAndy Yan .nr_gammas = 4, 4049b6ba80b4SDamon Ding .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data), 405012ee5af0SDamon Ding .nr_dscs = 2, 405112ee5af0SDamon Ding .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw), 405212ee5af0SDamon Ding .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow), 4053ecc31b6eSAndy Yan }; 4054ecc31b6eSAndy Yan 4055d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 4056d0408543SAndy Yan .preinit = rockchip_vop2_preinit, 4057d0408543SAndy Yan .prepare = rockchip_vop2_prepare, 4058d0408543SAndy Yan .init = rockchip_vop2_init, 4059d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane, 4060d0408543SAndy Yan .enable = rockchip_vop2_enable, 4061d0408543SAndy Yan .disable = rockchip_vop2_disable, 4062b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts, 4063d0408543SAndy Yan }; 4064