1d0408543SAndy Yan // SPDX-License-Identifier: GPL-2.0-only 2d0408543SAndy Yan /* 3d0408543SAndy Yan * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 4d0408543SAndy Yan * 5d0408543SAndy Yan */ 6d0408543SAndy Yan 7d0408543SAndy Yan #include <config.h> 8d0408543SAndy Yan #include <common.h> 9d0408543SAndy Yan #include <errno.h> 10d0408543SAndy Yan #include <malloc.h> 11d0408543SAndy Yan #include <fdtdec.h> 12d0408543SAndy Yan #include <fdt_support.h> 13b890760eSAlgea Cao #include <regmap.h> 14feffd38eSSandy Huang #include <asm/arch/cpu.h> 15d0408543SAndy Yan #include <asm/unaligned.h> 16d0408543SAndy Yan #include <asm/io.h> 17d0408543SAndy Yan #include <linux/list.h> 18ecc31b6eSAndy Yan #include <linux/log2.h> 19d0408543SAndy Yan #include <linux/media-bus-format.h> 20d0408543SAndy Yan #include <asm/arch/clock.h> 218e7ef808SDamon Ding #include <asm/gpio.h> 22d0408543SAndy Yan #include <linux/err.h> 231147facaSSandy Huang #include <linux/ioport.h> 24d0408543SAndy Yan #include <dm/device.h> 25d0408543SAndy Yan #include <dm/read.h> 265fa6e665SDamon Ding #include <dm/ofnode.h> 27ac500a1fSSandy Huang #include <fixp-arith.h> 28d0408543SAndy Yan #include <syscon.h> 2960e469f5SDamon Ding #include <linux/iopoll.h> 305f1357a2SZhang Yubing #include <dm/uclass-internal.h> 31452afb13SDamon Ding #include <stdlib.h> 320669ab1fSDamon Ding #include <dm/of_access.h> 33d0408543SAndy Yan 34d0408543SAndy Yan #include "rockchip_display.h" 35d0408543SAndy Yan #include "rockchip_crtc.h" 36d0408543SAndy Yan #include "rockchip_connector.h" 37d8e7f4a5SSandy Huang #include "rockchip_phy.h" 386027c871SZhang Yubing #include "rockchip_post_csc.h" 39d0408543SAndy Yan 40d0408543SAndy Yan /* System registers definition */ 41d0408543SAndy Yan #define RK3568_REG_CFG_DONE 0x000 42d0408543SAndy Yan #define CFG_DONE_EN BIT(15) 43d0408543SAndy Yan 44d0408543SAndy Yan #define RK3568_VERSION_INFO 0x004 45d0408543SAndy Yan #define EN_MASK 1 46d0408543SAndy Yan 4763cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL 0x008 480675a2a4SDamon Ding #define AUTO_GATING_EN_SHIFT 31 490675a2a4SDamon Ding #define PORT_DCLK_AUTO_GATING_EN_SHIFT 14 50bb7ec356SDamon Ding #define ACLK_PRE_AUTO_GATING_EN_SHIFT 7 5163cb669fSSandy Huang 5244b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL0_IMD 0x014 5344b1b62cSDamon Ding #define AXI0_PORT_URGENCY_EN_SHIFT 24 5444b1b62cSDamon Ding 5544b1b62cSDamon Ding #define RK3576_SYS_AXI_HURRY_CTRL1_IMD 0x018 5644b1b62cSDamon Ding #define AXI1_PORT_URGENCY_EN_SHIFT 24 5744b1b62cSDamon Ding 58a552a69cSDamon Ding #define RK3576_SYS_MMU_CTRL 0x020 59a552a69cSDamon Ding #define RKMMU_V2_EN_SHIFT 0 60a552a69cSDamon Ding #define RKMMU_V2_SEL_AXI_SHIFT 1 61a552a69cSDamon Ding 626414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL 0x024 636414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT 0 64aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT 16 656414e3bcSSandy Huang 66d0408543SAndy Yan #define RK3568_DSP_IF_EN 0x028 67d0408543SAndy Yan #define RGB_EN_SHIFT 0 68ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT 0 69ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT 1 70ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT 8 71d0408543SAndy Yan #define HDMI0_EN_SHIFT 1 72d0408543SAndy Yan #define EDP0_EN_SHIFT 3 73ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT 2 74ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT 3 75d0408543SAndy Yan #define MIPI0_EN_SHIFT 4 76ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT 4 77ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT 5 78ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT 6 79d0408543SAndy Yan #define MIPI1_EN_SHIFT 20 80ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT 7 81d0408543SAndy Yan #define LVDS0_EN_SHIFT 5 82d0408543SAndy Yan #define LVDS1_EN_SHIFT 24 83d0408543SAndy Yan #define BT1120_EN_SHIFT 6 84d0408543SAndy Yan #define BT656_EN_SHIFT 7 85d0408543SAndy Yan #define IF_MUX_MASK 3 86d0408543SAndy Yan #define RGB_MUX_SHIFT 8 87d0408543SAndy Yan #define HDMI0_MUX_SHIFT 10 88ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT 12 89ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT 14 90d0408543SAndy Yan #define EDP0_MUX_SHIFT 14 91ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT 16 92ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT 18 93d0408543SAndy Yan #define MIPI0_MUX_SHIFT 16 94ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT 20 95d0408543SAndy Yan #define MIPI1_MUX_SHIFT 21 9611f53190SSandy Huang #define LVDS0_MUX_SHIFT 18 97d0408543SAndy Yan #define LVDS1_MUX_SHIFT 25 98d0408543SAndy Yan 99a552a69cSDamon Ding #define RK3576_SYS_PORT_CTRL 0x028 100a552a69cSDamon Ding #define VP_INTR_MERGE_EN_SHIFT 14 10112ee4de7SDamon Ding #define RK3576_DSP_VS_T_SEL_SHIFT 4 102a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_MASK 0x7 103a552a69cSDamon Ding #define INTERLACE_FRM_REG_DONE_SHIFT 0 104a552a69cSDamon Ding 105d0408543SAndy Yan #define RK3568_DSP_IF_CTRL 0x02c 106d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT 0 1075d2768f7SDamon Ding #define RK3588_BT656_UV_SWAP_SHIFT 0 108d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 1095d2768f7SDamon Ding #define RK3588_BT656_YC_SWAP_SHIFT 1 110d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT 2 1115fa6e665SDamon Ding #define BT656_UV_SWAP 4 1125d2768f7SDamon Ding #define RK3588_BT1120_UV_SWAP_SHIFT 4 1135fa6e665SDamon Ding #define BT656_YC_SWAP 5 1145d2768f7SDamon Ding #define RK3588_BT1120_YC_SWAP_SHIFT 5 1155fa6e665SDamon Ding #define BT656_DCLK_POL 6 1160a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT 8 1170a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT 8 1180a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT 9 11941874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT 10 12041874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11 12141874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12 12241874944SGuochun Huang 123d0408543SAndy Yan #define RK3568_DSP_IF_POL 0x030 124d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT 28 125d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 126de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_MASK 0x7 127de022775SGuochun Huang #define IF_CTRL_MIPI_PIN_POL_SHIFT 16 128d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT 15 1297bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_MASK 0x7 1307bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_SHIFT 12 131d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 13210ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 13310ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT 4 13415f69071SDamon Ding #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT 3 13515f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_MASK 0x7 13615f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT 0 137ecc31b6eSAndy Yan 138452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT 15 139452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT 12 140452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK 0x7 141452afb13SDamon Ding 142ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT 8 143ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT 12 144ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK 0x7 145ecc31b6eSAndy Yan 146ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT 16 147ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 148ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT 20 149ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 150ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT 24 151ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT 26 152ecc31b6eSAndy Yan 153a552a69cSDamon Ding #define RK3576_SYS_CLUSTER_PD_CTRL 0x030 154a552a69cSDamon Ding #define RK3576_CLUSTER_PD_EN_SHIFT 0 155a552a69cSDamon Ding 156a552a69cSDamon Ding #define RK3588_SYS_PD_CTRL 0x034 157a552a69cSDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT 0 158a552a69cSDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT 1 159a552a69cSDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT 2 160a552a69cSDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT 3 161a552a69cSDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT 5 162a552a69cSDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT 6 163a552a69cSDamon Ding #define RK3588_ESMART_PD_EN_SHIFT 7 164a552a69cSDamon Ding 165a552a69cSDamon Ding #define RK3576_SYS_ESMART_PD_CTRL 0x034 166a552a69cSDamon Ding #define RK3576_ESMART_PD_EN_SHIFT 0 167a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_SHIFT 6 168a552a69cSDamon Ding #define RK3576_ESMART_LB_MODE_SEL_MASK 0x3 169a552a69cSDamon Ding 170feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN 0x50 171feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT 0 1721147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL 0x58 1731147facaSSandy Huang #define GAMMA_PORT_SEL_MASK 0x3 1741147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT 0 175db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK 0x3 176db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT 12 177ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT 16 1785fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK 0x3 1795fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT 26 1801147facaSSandy Huang 181d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG 0x70 182d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG 0x74 183d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG 0x78 184d0408543SAndy Yan #define RK3568_SYS0_INT_EN 0x80 185d0408543SAndy Yan #define RK3568_SYS0_INT_CLR 0x84 186d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS 0x88 187d0408543SAndy Yan #define RK3568_SYS1_INT_EN 0x90 188d0408543SAndy Yan #define RK3568_SYS1_INT_CLR 0x94 189d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS 0x98 190d0408543SAndy Yan #define RK3568_VP0_INT_EN 0xA0 191d0408543SAndy Yan #define RK3568_VP0_INT_CLR 0xA4 192d0408543SAndy Yan #define RK3568_VP0_INT_STATUS 0xA8 193d0408543SAndy Yan #define RK3568_VP1_INT_EN 0xB0 194d0408543SAndy Yan #define RK3568_VP1_INT_CLR 0xB4 195d0408543SAndy Yan #define RK3568_VP1_INT_STATUS 0xB8 196d0408543SAndy Yan #define RK3568_VP2_INT_EN 0xC0 197d0408543SAndy Yan #define RK3568_VP2_INT_CLR 0xC4 198d0408543SAndy Yan #define RK3568_VP2_INT_STATUS 0xC8 199a552a69cSDamon Ding #define RK3568_VP2_INT_RAW_STATUS 0xCC 200a552a69cSDamon Ding #define RK3588_VP3_INT_EN 0xD0 201a552a69cSDamon Ding #define RK3588_VP3_INT_CLR 0xD4 202a552a69cSDamon Ding #define RK3588_VP3_INT_STATUS 0xD8 203a552a69cSDamon Ding #define RK3576_WB_CTRL 0x100 204a552a69cSDamon Ding #define RK3576_WB_XSCAL_FACTOR 0x104 205a552a69cSDamon Ding #define RK3576_WB_YRGB_MST 0x108 206a552a69cSDamon Ding #define RK3576_WB_CBR_MST 0x10C 207a552a69cSDamon Ding #define RK3576_WB_VIR_STRIDE 0x110 208a552a69cSDamon Ding #define RK3576_WB_TIMEOUT_CTRL 0x114 209a552a69cSDamon Ding #define RK3576_MIPI0_IF_CTRL 0x180 210a552a69cSDamon Ding #define RK3576_IF_OUT_EN_SHIFT 0 211a552a69cSDamon Ding #define RK3576_IF_CLK_OUT_EN_SHIFT 1 212a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_SHIFT 2 213a552a69cSDamon Ding #define RK3576_IF_PORT_SEL_MASK 0x3 214a552a69cSDamon Ding #define RK3576_IF_PIN_POL_SHIFT 4 215a552a69cSDamon Ding #define RK3576_IF_PIN_POL_MASK 0x7 216a552a69cSDamon Ding #define RK3576_IF_SPLIT_EN_SHIFT 8 217a552a69cSDamon Ding #define RK3576_IF_DATA1_SEL_SHIFT 9 218a552a69cSDamon Ding #define RK3576_MIPI_CMD_MODE_SHIFT 11 219a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_SHIFT 21 220a552a69cSDamon Ding #define RK3576_IF_DCLK_SEL_MASK 0x1 221a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_SHIFT 20 222a552a69cSDamon Ding #define RK3576_IF_PIX_CLK_SEL_MASK 0x1 223a552a69cSDamon Ding #define RK3576_IF_REGDONE_IMD_EN_SHIFT 31 224a552a69cSDamon Ding #define RK3576_HDMI0_IF_CTRL 0x184 225a552a69cSDamon Ding #define RK3576_EDP0_IF_CTRL 0x188 226a552a69cSDamon Ding #define RK3576_DP0_IF_CTRL 0x18C 227a552a69cSDamon Ding #define RK3576_RGB_IF_CTRL 0x194 228a552a69cSDamon Ding #define RK3576_BT656_OUT_EN_SHIFT 12 229a552a69cSDamon Ding #define RK3576_BT656_UV_SWAP_SHIFT 13 230a552a69cSDamon Ding #define RK3576_BT656_YC_SWAP_SHIFT 14 231a552a69cSDamon Ding #define RK3576_BT1120_OUT_EN_SHIFT 16 232a552a69cSDamon Ding #define RK3576_BT1120_UV_SWAP_SHIFT 17 233a552a69cSDamon Ding #define RK3576_BT1120_YC_SWAP_SHIFT 18 234a552a69cSDamon Ding #define RK3576_DP1_IF_CTRL 0x1A4 235a552a69cSDamon Ding #define RK3576_DP2_IF_CTRL 0x1B0 23660e469f5SDamon Ding 237cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL 0x038 238cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT 20 239cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT 24 240cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT 28 241cd6c85a9SDamon Ding 24260e469f5SDamon Ding #define RK3568_SYS_STATUS0 0x60 24360e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8 24460e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9 24560e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10 24660e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11 247b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT 13 248b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT 14 24960e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT 15 250d0408543SAndy Yan 25166724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0 0x70 25266724b9cSDamon Ding #define LINE_FLAG_NUM_MASK 0x1fff 25366724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0 25466724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16 25566724b9cSDamon Ding 25612ee5af0SDamon Ding /* DSC CTRL registers definition */ 25712ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL 0x200 25812ee5af0SDamon Ding #define DSC_PORT_SEL_MASK 0x3 25912ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT 0 26012ee5af0SDamon Ding #define DSC_MAN_MODE_MASK 0x1 26112ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT 2 26212ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK 0x3 26312ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT 4 26412ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK 0x3 26512ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT 6 26612ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK 0x1 26712ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT 8 26812ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK 0x3 26912ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT 12 27012ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK 0x3 27112ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT 14 27212ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK 0x1 27312ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT 16 27412ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT 17 27512ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT 18 27612ee5af0SDamon Ding 27712ee5af0SDamon Ding #define RK3588_DSC_8K_RST 0x204 27812ee5af0SDamon Ding #define RST_DEASSERT_MASK 0x1 27912ee5af0SDamon Ding #define RST_DEASSERT_SHIFT 0 28012ee5af0SDamon Ding 28112ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE 0x208 28212ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT 0 28312ee5af0SDamon Ding 28412ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY 0x20C 28512ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK 0xffff 28612ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT 0 28712ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16 28812ee5af0SDamon Ding 28912ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END 0x210 29012ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK 0xffffffff 29112ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT 0 29212ee5af0SDamon Ding 29312ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END 0x214 29412ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK 0xffffffff 29512ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT 0 29612ee5af0SDamon Ding 29712ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END 0x218 29812ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK 0xffffffff 29912ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT 0 30012ee5af0SDamon Ding 30112ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END 0x21C 30212ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK 0xffffffff 30312ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT 0 30412ee5af0SDamon Ding 30512ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS 0x220 30612ee5af0SDamon Ding 30763cb669fSSandy Huang /* Overlay registers definition */ 3085fa6e665SDamon Ding #define RK3528_OVL_SYS 0x500 309a552a69cSDamon Ding #define RK3528_OVL_SYS_PORT_SEL 0x504 310a552a69cSDamon Ding #define RK3528_OVL_SYS_GATING_EN 0x508 3115fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL 0x510 3129c7848c3SDamon Ding #define CLUSTER_DLY_NUM_SHIFT 0 3135fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL 0x520 314452afb13SDamon Ding #define ESMART_DLY_NUM_MASK 0xff 315452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT 0 3165fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL 0x524 3175fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL 0x528 3185fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C 3195fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530 3205fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 3215fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 3225fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c 323a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540 324a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544 325a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548 326a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c 3275fa6e665SDamon Ding 3285fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL 0x600 32963cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600 330ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK 0x1 331ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT 0 33263cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 3335fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL 0x604 33463cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604 33563cb669fSSandy Huang #define LAYER_SEL_MASK 0xf 33663cb669fSSandy Huang 33763cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608 33863cb669fSSandy Huang #define PORT_MUX_MASK 0xf 33963cb669fSSandy Huang #define PORT_MUX_SHIFT 0 34063cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3 34163cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16 34263cb669fSSandy Huang 34363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 34463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 34563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 34663cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 3475fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620 3485fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624 3495fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628 3505fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C 3515fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630 3525fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634 3535fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638 3545fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C 3555fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640 3565fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644 3575fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648 3585fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C 35963cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 36063cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654 36163cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 36263cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 363a552a69cSDamon Ding #define RK3576_EXTRA_SRC_COLOR_CTRL 0x650 364a552a69cSDamon Ding #define RK3576_EXTRA_DST_COLOR_CTRL 0x654 365a552a69cSDamon Ding #define RK3576_EXTRA_SRC_ALPHA_CTRL 0x658 366a552a69cSDamon Ding #define RK3576_EXTRA_DST_ALPHA_CTRL 0x65C 3675fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL 0x660 3685fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL 0x664 3695fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL 0x668 3705fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL 0x66C 3715fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670 37263cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 37363cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 37463cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 37563cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 37663cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0 37763cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff 37863cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24 37963cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4 38063cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8 38163cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0 3829c7848c3SDamon Ding #define RK3568_CLUSTER_DLY_NUM1 0x6F4 3839c7848c3SDamon Ding #define CLUSTER_DLY_NUM_MASK 0xffff 3849c7848c3SDamon Ding #define CLUSTER0_DLY_NUM_SHIFT 0 3859c7848c3SDamon Ding #define CLUSTER1_DLY_NUM_SHIFT 16 38663cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8 3879c7848c3SDamon Ding #define SMART_DLY_NUM_MASK 0xff 3889c7848c3SDamon Ding #define ESMART0_DLY_NUM_SHIFT 0 3899c7848c3SDamon Ding #define ESMART1_DLY_NUM_SHIFT 8 3909c7848c3SDamon Ding #define SMART0_DLY_NUM_SHIFT 16 3919c7848c3SDamon Ding #define SMART1_DLY_NUM_SHIFT 24 39263cb669fSSandy Huang 3935fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL 0x700 3945fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL 0x704 3955fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720 3965fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724 3975fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728 3985fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C 3995fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730 4005fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734 4015fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738 4025fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C 4035fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740 4045fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744 4055fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748 4065fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C 4075fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770 408a552a69cSDamon Ding #define RK3576_OVL_PORT2_CTRL 0x800 409a552a69cSDamon Ding #define RK3576_OVL_PORT2_LAYER_SEL 0x804 410a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL 0x820 411a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL 0x824 412a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL 0x828 413a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL 0x82C 414a552a69cSDamon Ding #define RK3576_OVL_PORT2_BG_MIX_CTRL 0x870 4155fa6e665SDamon Ding 416d0408543SAndy Yan /* Video Port registers definition */ 417d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00 418d0408543SAndy Yan #define OUT_MODE_MASK 0xf 419d0408543SAndy Yan #define OUT_MODE_SHIFT 0 42010ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f 42110ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8 42265747de7SDamon Ding #define DSP_BG_SWAP 0x1 42365747de7SDamon Ding #define DSP_RB_SWAP 0x2 42465747de7SDamon Ding #define DSP_RG_SWAP 0x4 42565747de7SDamon Ding #define DSP_DELTA_SWAP 0x8 42610ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4 427d0408543SAndy Yan #define P2I_EN_SHIFT 5 4287a20be36SSandy Huang #define DSP_FILED_POL 6 429d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7 430c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT 13 43110ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15 432d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16 433d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17 434e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_SHIFT 18 435e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_MASK 0x3 436452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT 20 437db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT 22 4381147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28 4391147facaSSandy Huang 440d0408543SAndy Yan #define STANDBY_EN_SHIFT 31 441d0408543SAndy Yan 442d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04 44310ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4 44410ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3 445d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20 446d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21 44741874944SGuochun Huang #define EDPI_TE_EN 28 44841874944SGuochun Huang #define EDPI_WMS_HOLD_EN 30 44941874944SGuochun Huang #define EDPI_WMS_FS 31 45041874944SGuochun Huang 451d0408543SAndy Yan 452d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 45344b1b62cSDamon Ding #define POST_URGENCY_EN_SHIFT 8 45444b1b62cSDamon Ding #define POST_URGENCY_THL_SHIFT 16 45544b1b62cSDamon Ding #define POST_URGENCY_THL_MASK 0xf 45644b1b62cSDamon Ding #define POST_URGENCY_THH_SHIFT 20 45744b1b62cSDamon Ding #define POST_URGENCY_THH_MASK 0xf 4585fa6e665SDamon Ding 4595fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL 0xC0C 460a552a69cSDamon Ding #define RK3576_DCLK_CORE_SEL_SHIFT 0 461a552a69cSDamon Ding #define RK3576_DCLK_OUT_SEL_SHIFT 2 4625fa6e665SDamon Ding 4636414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10 4646414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0 4656414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2 4666414e3bcSSandy Huang 467ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C 468ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0 469ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2 470ecc31b6eSAndy Yan 4716414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20 4726414e3bcSSandy Huang 473d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C 474d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 475d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 476d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 477d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 478d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40 4797504507fSSandy Huang #define RK3568_VP0_POST_SCALE_MASK 0x3 4807504507fSSandy Huang #define RK3568_VP0_POST_SCALE_SHIFT 0 481d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 482d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 483d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 484d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 485d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54 486d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 487d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 488d0408543SAndy Yan 489ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60 490ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0 491ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1 492ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 493ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 494ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4 495ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1 496ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 497ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 498ac500a1fSSandy Huang 499ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64 500ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0 501ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF 502ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8 503ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF 504ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20 505ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF 506ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30 507ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3 508ac500a1fSSandy Huang 509ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68 510ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0 511ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF 512ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16 513ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF 514ac500a1fSSandy Huang 515ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C 516ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31 517ac500a1fSSandy Huang #define BCSH_EN_MASK 1 518ac500a1fSSandy Huang 519a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_0 0xCA0 520a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_1 0xCA4 521a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_2 0xCA8 522a552a69cSDamon Ding 5236027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL 0xCD0 5246027c871SZhang Yubing #define POST_CSC_COE00_MASK 0xFFFF 5256027c871SZhang Yubing #define POST_CSC_COE00_SHIFT 16 5266027c871SZhang Yubing #define POST_R2Y_MODE_MASK 0x7 5276027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT 8 5286027c871SZhang Yubing #define POST_CSC_MODE_MASK 0x7 5296027c871SZhang Yubing #define POST_CSC_MODE_SHIFT 3 5306027c871SZhang Yubing #define POST_R2Y_EN_MASK 0x1 5316027c871SZhang Yubing #define POST_R2Y_EN_SHIFT 2 5326027c871SZhang Yubing #define POST_CSC_EN_MASK 0x1 5336027c871SZhang Yubing #define POST_CSC_EN_SHIFT 1 5346027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK 0x1 5356027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT 0 5366027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02 0xCD4 5376027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11 0xCD8 5386027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20 0xCDC 5396027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22 0xCE0 5406027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0 0xCE4 5416027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1 0xCE8 5426027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2 0xCEC 5436027c871SZhang Yubing 5440675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL 0xCF8 5450675a2a4SDamon Ding #define MCU_TYPE_SHIFT 31 5460675a2a4SDamon Ding #define MCU_BYPASS_SHIFT 30 5470675a2a4SDamon Ding #define MCU_RS_SHIFT 29 5480675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT 28 5490675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT 27 5500675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT 26 5510675a2a4SDamon Ding #define MCU_CLK_SEL_MASK 0x1 5520675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT 20 5530675a2a4SDamon Ding #define MCU_RW_PEND_MASK 0x3F 5540675a2a4SDamon Ding #define MCU_RW_PST_SHIFT 16 5550675a2a4SDamon Ding #define MCU_RW_PST_MASK 0xF 5560675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT 10 5570675a2a4SDamon Ding #define MCU_CS_PEND_MASK 0x3F 5580675a2a4SDamon Ding #define MCU_CS_PST_SHIFT 6 5590675a2a4SDamon Ding #define MCU_CS_PST_MASK 0xF 5600675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT 0 5610675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK 0x3F 5620675a2a4SDamon Ding 5630675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT 0xCFC 5640675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT 0 5650675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK 0xFFFFFFFF 5660675a2a4SDamon Ding 567d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00 568d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04 569d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 570d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 571d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 572d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 573d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 574d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40 575d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34 576d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38 577d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 578d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 579d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 580d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 581d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54 582d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 583d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 584d0408543SAndy Yan 585d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00 586d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04 587d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 588d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 589d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 590d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 591d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 592d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40 593d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34 594d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38 595d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 596d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 597d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 598d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 599d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54 600d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 601d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 602a552a69cSDamon Ding #define RK3568_VP2_BCSH_CTRL 0xE60 603a552a69cSDamon Ding #define RK3568_VP2_BCSH_BCS 0xE64 604a552a69cSDamon Ding #define RK3568_VP2_BCSH_H 0xE68 605a552a69cSDamon Ding #define RK3568_VP2_BCSH_COLOR_BAR 0xE6C 606a552a69cSDamon Ding #define RK3576_VP2_MCU_CTRL 0xEF8 607a552a69cSDamon Ding #define RK3576_VP2_MCU_RW_BYPASS_PORT 0xEFC 608d0408543SAndy Yan 609d0408543SAndy Yan /* Cluster0 register definition */ 610d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 611ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8 612ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9 613ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10 614840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT 18 615d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 6165fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12 6175fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 6185fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 6195fa6e665SDamon Ding #define AVG2_MASK 0x1 6205fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT 18 6215fa6e665SDamon Ding #define AVG4_MASK 0x1 6225fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT 19 6235fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22 6245fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT 24 6255fa6e665SDamon Ding #define XGT_MODE_MASK 0x3 6265fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT 25 6275fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT 27 628ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28 629ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29 630a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008 631a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK 0x1f 632a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT 0 633a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK 0x1f 634a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT 5 635a33b790fSDamon Ding 636d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 637d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 638d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018 639d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 640d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 641d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 642d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 643a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_CTRL 0x1040 644a552a69cSDamon Ding #define WIN0_ZME_DERING_EN_SHIFT 3 645a552a69cSDamon Ding #define WIN0_ZME_GATING_EN_SHIFT 31 646a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA 0x1044 647d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 648d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 649d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 650d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 651d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 652d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 653d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 654a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT 7 655a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET 0x1078 656a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE 0x107C 657d0408543SAndy Yan 658d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 659d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 660d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 661d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 662d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098 663d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 664d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 665d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 666d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 667d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 668d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 669d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 670d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 671d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 672d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 673d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 674a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET 0x10F8 675a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE 0x10FC 676d0408543SAndy Yan 677d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100 678ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0 679a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK 0x1 680a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT 13 681a552a69cSDamon Ding #define RK3576_CLUSTER0_PORT_SEL 0x11F4 682a552a69cSDamon Ding #define CLUSTER_PORT_SEL_SHIFT 0 683a552a69cSDamon Ding #define CLUSTER_PORT_SEL_MASK 0x3 684a552a69cSDamon Ding #define RK3576_CLUSTER0_DLY_NUM 0x11F8 685a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_SHIFT 0 686a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_MASK 0xff 687a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_SHIFT 0 688a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_MASK 0xff 689d0408543SAndy Yan 690d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 691d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 692d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 693d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 694d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218 695d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 696d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 697d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 698d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 699a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_CTRL 0x1240 700a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA 0x1244 701d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 702d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 703d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 704d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 705d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 706d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 707d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 708a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET 0x1278 709a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE 0x127C 710d0408543SAndy Yan 711d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 712d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 713d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 714d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 715d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298 716d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 717d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 718d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 719d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 720d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 721d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 722d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 723d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 724d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 725d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 726d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 727a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET 0x12F8 728a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE 0x12FC 729d0408543SAndy Yan 730d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300 731a552a69cSDamon Ding #define RK3576_CLUSTER1_PORT_SEL 0x13F4 732a552a69cSDamon Ding #define RK3576_CLUSTER1_DLY_NUM 0x13F8 733d0408543SAndy Yan 734d0408543SAndy Yan /* Esmart register definition */ 735d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800 73610ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1 73710ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2 73810ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3 7395fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT 12 7405fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK 0x3 741d0408543SAndy Yan 742d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804 743a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK 0x1f 744a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT 4 745a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK 0x1f 746a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT 12 747d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31 748a33b790fSDamon Ding 749a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL 0x1808 750a33b790fSDamon Ding #define ESMART_AXI_ID_MASK 0x1 751a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT 1 752a33b790fSDamon Ding 753d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810 754d0408543SAndy Yan #define WIN_EN_SHIFT 0 755d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f 756d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1 757840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT 12 7585fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT 14 7595fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT 20 7605fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT 21 7615fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT 22 762d0408543SAndy Yan 763d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 764d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 765d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C 766d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 767d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 768d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 769d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 7703e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3 7713e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0 7723e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3 7733e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2 7743e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3 7753e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4 7763e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3 7773e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6 7783e39a5a1SSandy Huang 779d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 780d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 781d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 782d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840 7833e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1 7843e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8 7853e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1 7863e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9 7873e39a5a1SSandy Huang 788d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 789d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 790d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C 791d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 792d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 793d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 794d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 795d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 796d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 797d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 798d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870 799d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 800d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 801d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C 802d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 803d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 804d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 805d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 806d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 807d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 808d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 809d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0 810d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 811d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 812d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC 813d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 814d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 815d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 816d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 817d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 818d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 819d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 820a552a69cSDamon Ding #define RK3568_ESMART0_COLOR_KEY_CTRL 0x18D0 821a552a69cSDamon Ding #define RK3576_ESMART0_ALPHA_MAP 0x18D8 822a552a69cSDamon Ding #define RK3576_ESMART0_PORT_SEL 0x18F4 823a552a69cSDamon Ding #define ESMART_PORT_SEL_SHIFT 0 824a552a69cSDamon Ding #define ESMART_PORT_SEL_MASK 0x3 825a552a69cSDamon Ding #define RK3576_ESMART0_DLY_NUM 0x18F8 826d0408543SAndy Yan 827d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00 828d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04 829d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10 830d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 831d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 832d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C 833d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 834d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 835d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 836d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 837d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 838d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 839d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 840d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40 841d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 842d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 843d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C 844d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 845d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 846d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 847d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 848d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 849d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 850d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 851d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70 852d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 853d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 854d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C 855d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 856d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 857d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 858d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 859d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 860d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 861d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 862d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 863d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 864d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 865d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC 866d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 867d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 868d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 869d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 870d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 871d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 872d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 873a552a69cSDamon Ding #define RK3576_ESMART1_ALPHA_MAP 0x1AD8 874a552a69cSDamon Ding #define RK3576_ESMART1_PORT_SEL 0x1AF4 875a552a69cSDamon Ding #define RK3576_ESMART1_DLY_NUM 0x1AF8 876d0408543SAndy Yan 877d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00 878d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04 879d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10 880d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 881d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 882d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C 883d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 884d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 885d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 886d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 887d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 888d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 889d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 890d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40 891d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 892d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 893d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C 894d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 895d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 896d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 897d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 898d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 899d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 900d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 901d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70 902d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 903d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 904d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C 905d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 906d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 907d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 908d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 909d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 910d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 911d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 912d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0 913d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 914d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 915d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC 916d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 917d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 918d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 919d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 920d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 921d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 922d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 923a552a69cSDamon Ding #define RK3576_ESMART2_ALPHA_MAP 0x1CD8 924a552a69cSDamon Ding #define RK3576_ESMART2_PORT_SEL 0x1CF4 925a552a69cSDamon Ding #define RK3576_ESMART2_DLY_NUM 0x1CF8 926d0408543SAndy Yan 927d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00 928d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04 929d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10 930d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 931d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 932d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C 933d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 934d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 935d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 936d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 937d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 938d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 939d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 940d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40 941d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 942d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 943d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C 944d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 945d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 946d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 947d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 948d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 949d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 950d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 951d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70 952d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 953d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 954d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C 955d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 956d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 957d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 958d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 959d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 960d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 961d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 962d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0 963d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 964d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 965d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC 966d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 967d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 968d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 969d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 970d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 971d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 972d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 973a552a69cSDamon Ding #define RK3576_ESMART3_ALPHA_MAP 0x1ED8 974a552a69cSDamon Ding #define RK3576_ESMART3_PORT_SEL 0x1EF4 975a552a69cSDamon Ding #define RK3576_ESMART3_DLY_NUM 0x1EF8 976d0408543SAndy Yan 97772388c26SDamon Ding /* HDR register definition */ 97872388c26SDamon Ding #define RK3568_HDR_LUT_CTRL 0x2000 97972388c26SDamon Ding 98072388c26SDamon Ding #define RK3588_VP3_DSP_CTRL 0xF00 98172388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400 98272388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0 0x1600 98372388c26SDamon Ding 98412ee5af0SDamon Ding /* DSC 8K/4K register definition */ 98512ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3 0x4000 98612ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0 0x40A0 98712ee5af0SDamon Ding #define DSC_EN_SHIFT 0 98812ee5af0SDamon Ding #define DSC_RBIT_SHIFT 2 98912ee5af0SDamon Ding #define DSC_RBYT_SHIFT 3 99012ee5af0SDamon Ding #define DSC_FLAL_SHIFT 4 99112ee5af0SDamon Ding #define DSC_MER_SHIFT 5 99212ee5af0SDamon Ding #define DSC_EPB_SHIFT 6 99312ee5af0SDamon Ding #define DSC_EPL_SHIFT 7 9941ace1b6dSDamon Ding #define DSC_NSLC_MASK 0x7 99512ee5af0SDamon Ding #define DSC_NSLC_SHIFT 16 99612ee5af0SDamon Ding #define DSC_SBO_SHIFT 28 99712ee5af0SDamon Ding #define DSC_IFEP_SHIFT 29 99812ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT 31 999baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \ 1000baf2c414SDamon Ding (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \ 1001baf2c414SDamon Ding (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT)) 100212ee5af0SDamon Ding 100312ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1 0x40A4 100412ee5af0SDamon Ding #define RK3588_DSC_8K_STS0 0x40A8 100512ee5af0SDamon Ding #define RK3588_DSC_8K_ERS 0x40C4 100612ee5af0SDamon Ding 100712ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3 0x4100 100812ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0 0x41A0 100912ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1 0x41A4 101012ee5af0SDamon Ding #define RK3588_DSC_4K_STS0 0x41A8 101112ee5af0SDamon Ding #define RK3588_DSC_4K_ERS 0x41C4 101212ee5af0SDamon Ding 101372388c26SDamon Ding /* RK3528 HDR register definition */ 101472388c26SDamon Ding #define RK3528_HDR_LUT_CTRL 0x2000 101572388c26SDamon Ding 10166027c871SZhang Yubing /* RK3528 ACM register definition */ 10176027c871SZhang Yubing #define RK3528_ACM_CTRL 0x6400 10186027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE 0x6404 10196027c871SZhang Yubing #define RK3528_ACM_FETCH_START 0x6408 10206027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE 0x6420 10216027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500 10226027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760 10236027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764 10246027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4 10256027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8 10266027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8 10276027c871SZhang Yubing 1028d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0 1029d0408543SAndy Yan 1030452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON 0x10500 103152ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364 103252ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1 103352ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2 103452ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3 103552ee18acSSandy Huang 1036a552a69cSDamon Ding /* Base SYS_GRF: 0x2600a000*/ 1037a552a69cSDamon Ding #define RK3576_SYS_GRF_MEMFAULT_STATUS0 0x0148 1038a552a69cSDamon Ding 1039a552a69cSDamon Ding /* Base IOC_GRF: 0x26040000 */ 1040a552a69cSDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8 0x6420 1041a552a69cSDamon Ding #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT 9 1042a552a69cSDamon Ding #define RK3576_IOC_VOPLITE_SEL_SHIFT 11 1043a552a69cSDamon Ding 1044a552a69cSDamon Ding /* Base PMU2: 0x27380000 */ 1045a552a69cSDamon Ding #define RK3576_PMU_PWR_GATE_STS 0x0230 1046a552a69cSDamon Ding #define PD_VOP_ESMART_DWN_STAT 12 1047a552a69cSDamon Ding #define PD_VOP_CLUSTER_DWN_STAT 13 1048a552a69cSDamon Ding #define RK3576_PMU_BISR_PDGEN_CON0 0x0510 1049a552a69cSDamon Ding #define PD_VOP_ESMART_REPAIR_ENA_SHIFT 12 1050a552a69cSDamon Ding #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT 13 1051a552a69cSDamon Ding #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0 0x0570 1052a552a69cSDamon Ding #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT 12 1053a552a69cSDamon Ding #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT 13 1054a552a69cSDamon Ding 10555d2768f7SDamon Ding #define RK3588_GRF_SOC_CON1 0x0304 10565d2768f7SDamon Ding #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT 14 10575d2768f7SDamon Ding 1058ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008 1059ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 1060ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 1061ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 1062ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 1063ecc31b6eSAndy Yan 1064b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0 0x0000 1065b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK 0x3 1066b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT 5 1067b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT 7 1068b890760eSAlgea Cao 106960e469f5SDamon Ding #define RK3588_PMU_BISR_CON3 0x20C 107060e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 107160e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 107260e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 107360e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 1074b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13 1075b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14 107660e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 107760e469f5SDamon Ding 107860e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5 0x294 107960e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 108060e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 108160e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 108260e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 1083b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13 1084b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14 108560e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 108660e469f5SDamon Ding 1087d0408543SAndy Yan #define VOP2_LAYER_MAX 8 108863cb669fSSandy Huang 1089ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH 4096 1090ee01dbb2SDamon Ding 1091631ee99aSZhang Yubing /* KHz */ 1092631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE 600000 1093631ee99aSZhang Yubing 1094b6ba80b4SDamon Ding /* 1095b6ba80b4SDamon Ding * vop2 dsc id 1096b6ba80b4SDamon Ding */ 1097b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K 0 1098b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K 1 1099b6ba80b4SDamon Ding 1100b6ba80b4SDamon Ding /* 1101b6ba80b4SDamon Ding * vop2 internal power domain id, 1102b6ba80b4SDamon Ding * should be all none zero, 0 will be 1103b6ba80b4SDamon Ding * treat as invalid; 1104b6ba80b4SDamon Ding */ 1105b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0 BIT(0) 1106b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1 BIT(1) 1107b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2 BIT(2) 1108b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3 BIT(3) 1109b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K BIT(5) 1110b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K BIT(6) 1111b6ba80b4SDamon Ding #define VOP2_PD_ESMART BIT(7) 1112a552a69cSDamon Ding #define VOP2_PD_CLUSTER BIT(8) 1113b6ba80b4SDamon Ding 11144c765862SDamon Ding #define VOP2_PLANE_NO_SCALING BIT(16) 11154c765862SDamon Ding 11165fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 11175fa6e665SDamon Ding #define VOP_FEATURE_AFBDC BIT(1) 11185fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE BIT(2) 11195fa6e665SDamon Ding #define VOP_FEATURE_HDR10 BIT(3) 11205fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR BIT(4) 11215fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */ 11225fa6e665SDamon Ding #define VOP_FEATURE_SPLICE BIT(5) 11235fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN BIT(6) 11246027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR BIT(7) 11256027c871SZhang Yubing #define VOP_FEATURE_POST_ACM BIT(8) 11266027c871SZhang Yubing #define VOP_FEATURE_POST_CSC BIT(9) 1127a552a69cSDamon Ding #define VOP_FEATURE_POST_FRC_V2 BIT(10) 1128a552a69cSDamon Ding #define VOP_FEATURE_POST_SHARP BIT(11) 11295fa6e665SDamon Ding 11305fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR BIT(0) 11315fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR BIT(1) 11325fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY BIT(2) 11335fa6e665SDamon Ding #define WIN_FEATURE_AFBDC BIT(3) 11345fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN BIT(4) 11355fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB BIT(5) 11365fa6e665SDamon Ding /* a mirror win can only get fb address 11375fa6e665SDamon Ding * from source win: 11385fa6e665SDamon Ding * Cluster1---->Cluster0 11395fa6e665SDamon Ding * Esmart1 ---->Esmart0 11405fa6e665SDamon Ding * Smart1 ---->Smart0 11415fa6e665SDamon Ding * This is a feather on rk3566 11425fa6e665SDamon Ding */ 11435fa6e665SDamon Ding #define WIN_FEATURE_MIRROR BIT(6) 11445fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA BIT(7) 11455fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8) 1146a552a69cSDamon Ding #define WIN_FEATURE_DCI BIT(9) 11475fa6e665SDamon Ding 11485fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F 0xfe 11495fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F 0xff 11505fa6e665SDamon Ding 11515fa6e665SDamon Ding enum vop_csc_format { 115210ee9f5bSAlgea Cao CSC_BT601L, 115310ee9f5bSAlgea Cao CSC_BT709L, 115410ee9f5bSAlgea Cao CSC_BT601F, 1155df0a5c43SDamon Ding CSC_BT2020L, 11565fa6e665SDamon Ding CSC_BT709L_13BIT, 11575fa6e665SDamon Ding CSC_BT709F_13BIT, 11585fa6e665SDamon Ding CSC_BT2020L_13BIT, 11595fa6e665SDamon Ding CSC_BT2020F_13BIT, 11605fa6e665SDamon Ding }; 11615fa6e665SDamon Ding 11625fa6e665SDamon Ding enum vop_csc_bit_depth { 11635fa6e665SDamon Ding CSC_10BIT_DEPTH, 11645fa6e665SDamon Ding CSC_13BIT_DEPTH, 116510ee9f5bSAlgea Cao }; 116610ee9f5bSAlgea Cao 116710ee9f5bSAlgea Cao enum vop2_pol { 116810ee9f5bSAlgea Cao HSYNC_POSITIVE = 0, 116910ee9f5bSAlgea Cao VSYNC_POSITIVE = 1, 117010ee9f5bSAlgea Cao DEN_NEGATIVE = 2, 117110ee9f5bSAlgea Cao DCLK_INVERT = 3 117210ee9f5bSAlgea Cao }; 117310ee9f5bSAlgea Cao 1174ac500a1fSSandy Huang enum vop2_bcsh_out_mode { 1175ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK, 1176ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE, 1177ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR, 1178ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, 1179ac500a1fSSandy Huang }; 1180ac500a1fSSandy Huang 1181d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \ 1182d0408543SAndy Yan { \ 1183d0408543SAndy Yan .offset = off, \ 1184d0408543SAndy Yan .mask = _mask, \ 1185d0408543SAndy Yan .shift = _shift, \ 1186d0408543SAndy Yan .write_mask = _write_mask, \ 1187d0408543SAndy Yan } 1188d0408543SAndy Yan 1189d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \ 1190d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false) 1191d0408543SAndy Yan enum dither_down_mode { 1192d0408543SAndy Yan RGB888_TO_RGB565 = 0x0, 1193d0408543SAndy Yan RGB888_TO_RGB666 = 0x1 1194d0408543SAndy Yan }; 1195d0408543SAndy Yan 1196a552a69cSDamon Ding enum dither_down_mode_sel { 1197a552a69cSDamon Ding DITHER_DOWN_ALLEGRO = 0x0, 1198a552a69cSDamon Ding DITHER_DOWN_FRC = 0x1 1199a552a69cSDamon Ding }; 1200a552a69cSDamon Ding 1201d0408543SAndy Yan enum vop2_video_ports_id { 1202d0408543SAndy Yan VOP2_VP0, 1203d0408543SAndy Yan VOP2_VP1, 1204d0408543SAndy Yan VOP2_VP2, 1205d0408543SAndy Yan VOP2_VP3, 1206d0408543SAndy Yan VOP2_VP_MAX, 1207d0408543SAndy Yan }; 1208d0408543SAndy Yan 1209ee008497SSandy Huang enum vop2_layer_type { 1210ee008497SSandy Huang CLUSTER_LAYER = 0, 1211ee008497SSandy Huang ESMART_LAYER = 1, 1212ee008497SSandy Huang SMART_LAYER = 2, 1213ee008497SSandy Huang }; 1214ee008497SSandy Huang 1215b0989546SSandy Huang /* This define must same with kernel win phy id */ 1216b0989546SSandy Huang enum vop2_layer_phy_id { 1217b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0, 1218b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, 1219b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0, 1220b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 1221b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 1222b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 1223b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2, 1224b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3, 1225b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2, 1226b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3, 1227ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX, 122827cec8e2SDamon Ding ROCKCHIP_VOP2_PHY_ID_INVALID = -1, 1229d0408543SAndy Yan }; 1230d0408543SAndy Yan 12313e39a5a1SSandy Huang enum vop2_scale_up_mode { 12323e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR, 12333e39a5a1SSandy Huang VOP2_SCALE_UP_BIL, 12343e39a5a1SSandy Huang VOP2_SCALE_UP_BIC, 1235a552a69cSDamon Ding VOP2_SCALE_UP_ZME, 12363e39a5a1SSandy Huang }; 12373e39a5a1SSandy Huang 12383e39a5a1SSandy Huang enum vop2_scale_down_mode { 12393e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR, 12403e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL, 12413e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG, 1242a552a69cSDamon Ding VOP2_SCALE_DOWN_ZME, 12433e39a5a1SSandy Huang }; 12443e39a5a1SSandy Huang 12453e39a5a1SSandy Huang enum scale_mode { 12463e39a5a1SSandy Huang SCALE_NONE = 0x0, 12473e39a5a1SSandy Huang SCALE_UP = 0x1, 12483e39a5a1SSandy Huang SCALE_DOWN = 0x2 12493e39a5a1SSandy Huang }; 12503e39a5a1SSandy Huang 125112ee5af0SDamon Ding enum vop_dsc_interface_mode { 125212ee5af0SDamon Ding VOP_DSC_IF_DISABLE = 0, 125312ee5af0SDamon Ding VOP_DSC_IF_HDMI = 1, 125412ee5af0SDamon Ding VOP_DSC_IF_MIPI_DS_MODE = 2, 125512ee5af0SDamon Ding VOP_DSC_IF_MIPI_VIDEO_MODE = 3, 125612ee5af0SDamon Ding }; 125712ee5af0SDamon Ding 12585fa6e665SDamon Ding enum vop3_pre_scale_down_mode { 12595fa6e665SDamon Ding VOP3_PRE_SCALE_UNSPPORT, 12605fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_GT, 12615fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_AVG, 12625fa6e665SDamon Ding }; 12635fa6e665SDamon Ding 12649c7848c3SDamon Ding /* 12659c7848c3SDamon Ding * the delay number of a window in different mode. 12669c7848c3SDamon Ding */ 12679c7848c3SDamon Ding enum vop2_win_dly_mode { 12689c7848c3SDamon Ding VOP2_DLY_MODE_DEFAULT, /* default mode */ 12699c7848c3SDamon Ding VOP2_DLY_MODE_HISO_S, /* HDR in SDR out mode, as a SDR window */ 12709c7848c3SDamon Ding VOP2_DLY_MODE_HIHO_H, /* HDR in HDR out mode, as a HDR window */ 12719c7848c3SDamon Ding VOP2_DLY_MODE_DOVI_IN_CORE1, /* dovi video input, as dovi core1 */ 12729c7848c3SDamon Ding VOP2_DLY_MODE_DOVI_IN_CORE2, /* dovi video input, as dovi core2 */ 12739c7848c3SDamon Ding VOP2_DLY_MODE_NONDOVI_IN_CORE1, /* ndovi video input, as dovi core1 */ 12749c7848c3SDamon Ding VOP2_DLY_MODE_NONDOVI_IN_CORE2, /* ndovi video input, as dovi core2 */ 12759c7848c3SDamon Ding VOP2_DLY_MODE_MAX, 12769c7848c3SDamon Ding }; 12779c7848c3SDamon Ding 12785fa6e665SDamon Ding enum vop3_esmart_lb_mode { 12795fa6e665SDamon Ding VOP3_ESMART_8K_MODE, 12805fa6e665SDamon Ding VOP3_ESMART_4K_4K_MODE, 12815fa6e665SDamon Ding VOP3_ESMART_4K_2K_2K_MODE, 12825fa6e665SDamon Ding VOP3_ESMART_2K_2K_2K_2K_MODE, 1283a552a69cSDamon Ding VOP3_ESMART_4K_4K_4K_MODE, 1284a552a69cSDamon Ding VOP3_ESMART_4K_4K_2K_2K_MODE, 12855fa6e665SDamon Ding }; 12865fa6e665SDamon Ding 12873e39a5a1SSandy Huang struct vop2_layer { 12883e39a5a1SSandy Huang u8 id; 12893e39a5a1SSandy Huang /** 12903e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected. 12913e39a5a1SSandy Huang * Every layer must make sure to select different 12923e39a5a1SSandy Huang * windows of others. 12933e39a5a1SSandy Huang */ 12943e39a5a1SSandy Huang u8 win_phys_id; 12953e39a5a1SSandy Huang }; 12963e39a5a1SSandy Huang 129760e469f5SDamon Ding struct vop2_power_domain_data { 1298a552a69cSDamon Ding u16 id; 1299a552a69cSDamon Ding u16 parent_id; 1300b6ba80b4SDamon Ding /* 1301b6ba80b4SDamon Ding * @module_id_mask: module id of which module this power domain is belongs to. 1302b6ba80b4SDamon Ding * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 1303b6ba80b4SDamon Ding */ 1304b6ba80b4SDamon Ding u32 module_id_mask; 130560e469f5SDamon Ding }; 130660e469f5SDamon Ding 1307b0989546SSandy Huang struct vop2_win_data { 1308b0989546SSandy Huang char *name; 130963cb669fSSandy Huang u8 phys_id; 1310ecc31b6eSAndy Yan enum vop2_layer_type type; 1311b0989546SSandy Huang u8 win_sel_port_offset; 13125fa6e665SDamon Ding u8 layer_sel_win_id[VOP2_VP_MAX]; 1313a33b790fSDamon Ding u8 axi_id; 1314a33b790fSDamon Ding u8 axi_uv_id; 1315a33b790fSDamon Ding u8 axi_yrgb_id; 1316ee01dbb2SDamon Ding u8 splice_win_id; 13175fa6e665SDamon Ding u8 hsu_filter_mode; 13185fa6e665SDamon Ding u8 hsd_filter_mode; 13195fa6e665SDamon Ding u8 vsu_filter_mode; 13205fa6e665SDamon Ding u8 vsd_filter_mode; 13215fa6e665SDamon Ding u8 hsd_pre_filter_mode; 13225fa6e665SDamon Ding u8 vsd_pre_filter_mode; 13235fa6e665SDamon Ding u8 scale_engine_num; 13241c9572c7SDamon Ding u8 source_win_id; 1325*13bc92e8SDamon Ding u8 possible_vp_mask; 13269c7848c3SDamon Ding u8 dly[VOP2_DLY_MODE_MAX]; 1327a552a69cSDamon Ding u16 pd_id; 1328b0989546SSandy Huang u32 reg_offset; 13294c765862SDamon Ding u32 max_upscale_factor; 13304c765862SDamon Ding u32 max_downscale_factor; 13311c9572c7SDamon Ding u32 feature; 1332a552a69cSDamon Ding u32 supported_rotations; 1333ee01dbb2SDamon Ding bool splice_mode_right; 133463cb669fSSandy Huang }; 133563cb669fSSandy Huang 133663cb669fSSandy Huang struct vop2_vp_data { 133763cb669fSSandy Huang u32 feature; 133844b1b62cSDamon Ding u32 max_dclk; 133963cb669fSSandy Huang u8 pre_scan_max_dly; 1340452afb13SDamon Ding u8 layer_mix_dly; 1341a552a69cSDamon Ding u8 hdrvivid_dly; 1342a552a69cSDamon Ding u8 sdr2hdr_dly; 1343452afb13SDamon Ding u8 hdr_mix_dly; 1344452afb13SDamon Ding u8 win_dly; 1345ee01dbb2SDamon Ding u8 splice_vp_id; 1346a552a69cSDamon Ding u8 pixel_rate; 134763cb669fSSandy Huang struct vop_rect max_output; 134844b1b62cSDamon Ding struct vop_urgency *urgency; 1349d0408543SAndy Yan }; 1350d0408543SAndy Yan 1351ee008497SSandy Huang struct vop2_plane_table { 1352ee008497SSandy Huang enum vop2_layer_phy_id plane_id; 1353ee008497SSandy Huang enum vop2_layer_type plane_type; 1354ee008497SSandy Huang }; 1355ee008497SSandy Huang 1356b0989546SSandy Huang struct vop2_vp_plane_mask { 1357b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */ 1358b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */ 1359b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 1360b0989546SSandy Huang u32 plane_mask; 1361ee008497SSandy Huang int cursor_plane_id; 1362b0989546SSandy Huang }; 1363b0989546SSandy Huang 136412ee5af0SDamon Ding struct vop2_dsc_data { 136512ee5af0SDamon Ding u8 id; 136612ee5af0SDamon Ding u8 max_slice_num; 136712ee5af0SDamon Ding u8 max_linebuf_depth; /* used to generate the bitstream */ 136812ee5af0SDamon Ding u8 min_bits_per_pixel; /* bit num after encoder compress */ 1369a552a69cSDamon Ding u16 pd_id; 137012ee5af0SDamon Ding const char *dsc_txp_clk_src_name; 137112ee5af0SDamon Ding const char *dsc_txp_clk_name; 137212ee5af0SDamon Ding const char *dsc_pxl_clk_name; 137312ee5af0SDamon Ding const char *dsc_cds_clk_name; 137412ee5af0SDamon Ding }; 137512ee5af0SDamon Ding 137612ee5af0SDamon Ding struct dsc_error_info { 137712ee5af0SDamon Ding u32 dsc_error_val; 137812ee5af0SDamon Ding char dsc_error_info[50]; 137912ee5af0SDamon Ding }; 138012ee5af0SDamon Ding 138172388c26SDamon Ding struct vop2_dump_regs { 138272388c26SDamon Ding u32 offset; 138372388c26SDamon Ding const char *name; 138472388c26SDamon Ding u32 state_base; 138572388c26SDamon Ding u32 state_mask; 138672388c26SDamon Ding u32 state_shift; 138772388c26SDamon Ding bool enable_state; 1388a552a69cSDamon Ding u32 size; 1389a552a69cSDamon Ding }; 1390a552a69cSDamon Ding 1391a552a69cSDamon Ding struct vop2_esmart_lb_map { 1392a552a69cSDamon Ding u8 lb_mode; 1393a552a69cSDamon Ding u8 lb_map_value; 139472388c26SDamon Ding }; 139572388c26SDamon Ding 13969c7848c3SDamon Ding /** 13979c7848c3SDamon Ding * struct vop2_ops - helper operations for vop2 hardware 13989c7848c3SDamon Ding * 13999c7848c3SDamon Ding * These hooks are used by the common part of the vop2 driver to 14009c7848c3SDamon Ding * implement the proper behaviour of different variants. 14019c7848c3SDamon Ding */ 14029c7848c3SDamon Ding struct vop2_ops { 14039c7848c3SDamon Ding void (*setup_win_dly)(struct display_state *state, int crtc_id); 1404b7195f56SDamon Ding void (*setup_overlay)(struct display_state *state); 14059c7848c3SDamon Ding }; 14069c7848c3SDamon Ding 1407d0408543SAndy Yan struct vop2_data { 140852ee18acSSandy Huang u32 version; 14095fa6e665SDamon Ding u32 esmart_lb_mode; 141063cb669fSSandy Huang struct vop2_vp_data *vp_data; 1411b0989546SSandy Huang struct vop2_win_data *win_data; 1412b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 1413ee008497SSandy Huang struct vop2_plane_table *plane_table; 1414b6ba80b4SDamon Ding struct vop2_power_domain_data *pd; 141512ee5af0SDamon Ding struct vop2_dsc_data *dsc; 141612ee5af0SDamon Ding struct dsc_error_info *dsc_error_ecw; 141712ee5af0SDamon Ding struct dsc_error_info *dsc_error_buffer_flow; 141872388c26SDamon Ding struct vop2_dump_regs *dump_regs; 1419a552a69cSDamon Ding const struct vop2_esmart_lb_map *esmart_lb_mode_map; 14209c7848c3SDamon Ding const struct vop2_ops *ops; 1421337d1c13SDamon Ding u8 *vp_primary_plane_order; 1422a552a69cSDamon Ding u8 *vp_default_primary_plane; 142363cb669fSSandy Huang u8 nr_vps; 142463cb669fSSandy Huang u8 nr_layers; 142563cb669fSSandy Huang u8 nr_mixers; 14261147facaSSandy Huang u8 nr_gammas; 1427b6ba80b4SDamon Ding u8 nr_pd; 142812ee5af0SDamon Ding u8 nr_dscs; 142912ee5af0SDamon Ding u8 nr_dsc_ecw; 143012ee5af0SDamon Ding u8 nr_dsc_buffer_flow; 1431a552a69cSDamon Ding u8 esmart_lb_mode_num; 1432ecc31b6eSAndy Yan u32 reg_len; 143372388c26SDamon Ding u32 dump_regs_size; 1434d0408543SAndy Yan }; 1435d0408543SAndy Yan 1436d0408543SAndy Yan struct vop2 { 1437d0408543SAndy Yan u32 *regsbak; 1438d0408543SAndy Yan void *regs; 1439d0408543SAndy Yan void *grf; 1440ecc31b6eSAndy Yan void *vop_grf; 1441ecc31b6eSAndy Yan void *vo1_grf; 144260e469f5SDamon Ding void *sys_pmu; 1443a552a69cSDamon Ding void *ioc_grf; 144452ee18acSSandy Huang u32 reg_len; 144552ee18acSSandy Huang u32 version; 14465fa6e665SDamon Ding u32 esmart_lb_mode; 144763cb669fSSandy Huang bool global_init; 1448a552a69cSDamon Ding bool merge_irq; 1449d0408543SAndy Yan const struct vop2_data *data; 1450b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 1451d0408543SAndy Yan }; 1452d0408543SAndy Yan 1453d0408543SAndy Yan static struct vop2 *rockchip_vop2; 14545fa6e665SDamon Ding 145527cec8e2SDamon Ding /* vop2_layer_phy_id */ 145627cec8e2SDamon Ding static const char *const vop2_layer_name_list[] = { 145727cec8e2SDamon Ding "Cluster0", 145827cec8e2SDamon Ding "Cluster1", 145927cec8e2SDamon Ding "Esmart0", 146027cec8e2SDamon Ding "Esmart1", 146127cec8e2SDamon Ding "Smart0", 146227cec8e2SDamon Ding "Smart1", 146327cec8e2SDamon Ding "Cluster2", 146427cec8e2SDamon Ding "Cluster3", 146527cec8e2SDamon Ding "Esmart2", 146627cec8e2SDamon Ding "Esmart3", 146727cec8e2SDamon Ding }; 146827cec8e2SDamon Ding 146927cec8e2SDamon Ding static inline const char *vop2_plane_id_to_string(unsigned long phy) 147027cec8e2SDamon Ding { 147127cec8e2SDamon Ding if (phy == ROCKCHIP_VOP2_PHY_ID_INVALID) 147227cec8e2SDamon Ding return "INVALID"; 147327cec8e2SDamon Ding 147427cec8e2SDamon Ding if (WARN_ON(phy >= ARRAY_SIZE(vop2_layer_name_list))) 147527cec8e2SDamon Ding return NULL; 147627cec8e2SDamon Ding 147727cec8e2SDamon Ding return vop2_layer_name_list[phy]; 147827cec8e2SDamon Ding } 147927cec8e2SDamon Ding 14805fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2) 14815fa6e665SDamon Ding { 14825fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) 14835fa6e665SDamon Ding return false; 14845fa6e665SDamon Ding else 14855fa6e665SDamon Ding return true; 14865fa6e665SDamon Ding } 14875fa6e665SDamon Ding 14883e39a5a1SSandy Huang /* 14893e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12; 14903e39a5a1SSandy Huang * avg_sd_factor: 14913e39a5a1SSandy Huang * bli_su_factor: 14923e39a5a1SSandy Huang * bic_su_factor: 14933e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16; 14943e39a5a1SSandy Huang * 14955fa6e665SDamon Ding * ygt2 enable: dst get one line from two line of the src 14965fa6e665SDamon Ding * ygt4 enable: dst get one line from four line of the src. 14973e39a5a1SSandy Huang * 14983e39a5a1SSandy Huang */ 14993e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 15003e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 15013e39a5a1SSandy Huang 15023e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 15033e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1)) 15043e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 15053e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1)) 15065fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \ 15075fa6e665SDamon Ding (fac * (dst - 1) >> 16 < (src - 1)) 15083e39a5a1SSandy Huang 15093e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode, 15103e39a5a1SSandy Huang int32_t filter_mode, 15113e39a5a1SSandy Huang uint32_t src, uint32_t dst) 15123e39a5a1SSandy Huang { 15133e39a5a1SSandy Huang uint32_t fac = 0; 15143e39a5a1SSandy Huang int i = 0; 15153e39a5a1SSandy Huang 15163e39a5a1SSandy Huang if (mode == SCALE_NONE) 15173e39a5a1SSandy Huang return 0; 15183e39a5a1SSandy Huang 15193e39a5a1SSandy Huang /* 15203e39a5a1SSandy Huang * A workaround to avoid zero div. 15213e39a5a1SSandy Huang */ 15223e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) { 15233e39a5a1SSandy Huang dst = dst + 1; 15243e39a5a1SSandy Huang src = src + 1; 15253e39a5a1SSandy Huang } 15263e39a5a1SSandy Huang 15273e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 15283e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst); 15293e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 15303e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 15313e39a5a1SSandy Huang break; 15323e39a5a1SSandy Huang fac -= 1; 15333e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 15343e39a5a1SSandy Huang } 15353e39a5a1SSandy Huang } else { 15363e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst); 15373e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 15383e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 15393e39a5a1SSandy Huang break; 15403e39a5a1SSandy Huang fac -= 1; 15413e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 15423e39a5a1SSandy Huang } 15433e39a5a1SSandy Huang } 15443e39a5a1SSandy Huang 15453e39a5a1SSandy Huang return fac; 15463e39a5a1SSandy Huang } 15473e39a5a1SSandy Huang 15485fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor) 15495fa6e665SDamon Ding { 15505fa6e665SDamon Ding if (is_hor) 15515fa6e665SDamon Ding return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac); 15525fa6e665SDamon Ding return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac); 15535fa6e665SDamon Ding } 15545fa6e665SDamon Ding 15555fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode, 15565fa6e665SDamon Ding uint32_t src, uint32_t dst, bool is_hor) 15575fa6e665SDamon Ding { 15585fa6e665SDamon Ding uint32_t fac = 0; 15595fa6e665SDamon Ding int i = 0; 15605fa6e665SDamon Ding 15615fa6e665SDamon Ding if (mode == SCALE_NONE) 15625fa6e665SDamon Ding return 0; 15635fa6e665SDamon Ding 15645fa6e665SDamon Ding /* 15655fa6e665SDamon Ding * A workaround to avoid zero div. 15665fa6e665SDamon Ding */ 15675fa6e665SDamon Ding if ((dst == 1) || (src == 1)) { 15685fa6e665SDamon Ding dst = dst + 1; 15695fa6e665SDamon Ding src = src + 1; 15705fa6e665SDamon Ding } 15715fa6e665SDamon Ding 15725fa6e665SDamon Ding if (mode == SCALE_DOWN) { 15735fa6e665SDamon Ding fac = VOP2_BILI_SCL_DN(src, dst); 15745fa6e665SDamon Ding for (i = 0; i < 100; i++) { 15755fa6e665SDamon Ding if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 15765fa6e665SDamon Ding break; 15775fa6e665SDamon Ding fac -= 1; 15785fa6e665SDamon Ding printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 15795fa6e665SDamon Ding } 15805fa6e665SDamon Ding } else { 15815fa6e665SDamon Ding fac = VOP2_COMMON_SCL(src, dst); 15825fa6e665SDamon Ding for (i = 0; i < 100; i++) { 15835fa6e665SDamon Ding if (vop3_scale_up_fac_check(src, dst, fac, is_hor)) 15845fa6e665SDamon Ding break; 15855fa6e665SDamon Ding fac -= 1; 15865fa6e665SDamon Ding printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 15875fa6e665SDamon Ding } 15885fa6e665SDamon Ding } 15895fa6e665SDamon Ding 15905fa6e665SDamon Ding return fac; 15915fa6e665SDamon Ding } 15925fa6e665SDamon Ding 15933e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst) 15943e39a5a1SSandy Huang { 15953e39a5a1SSandy Huang if (src < dst) 15963e39a5a1SSandy Huang return SCALE_UP; 15973e39a5a1SSandy Huang else if (src > dst) 15983e39a5a1SSandy Huang return SCALE_DOWN; 15993e39a5a1SSandy Huang 16003e39a5a1SSandy Huang return SCALE_NONE; 16013e39a5a1SSandy Huang } 1602d0408543SAndy Yan 1603ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x) 1604ac500a1fSSandy Huang { 1605ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 1606ac500a1fSSandy Huang } 1607ac500a1fSSandy Huang 1608b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 1609b0989546SSandy Huang { 1610b0989546SSandy Huang int i = 0; 1611ecc31b6eSAndy Yan 1612337d1c13SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 1613337d1c13SDamon Ding if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i])) 1614337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[i]; 1615ecc31b6eSAndy Yan } 1616b0989546SSandy Huang 1617337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[0]; 1618b0989546SSandy Huang } 1619b0989546SSandy Huang 162063cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift) 1621d0408543SAndy Yan { 1622d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 1623d0408543SAndy Yan } 1624d0408543SAndy Yan 162563cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst) 1626d0408543SAndy Yan { 1627d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1); 1628d0408543SAndy Yan } 1629d0408543SAndy Yan 163052ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 1631d0408543SAndy Yan { 1632d0408543SAndy Yan writel(v, vop2->regs + offset); 1633d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1634d0408543SAndy Yan } 1635d0408543SAndy Yan 163652ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 1637d0408543SAndy Yan { 1638d0408543SAndy Yan return readl(vop2->regs + offset); 1639d0408543SAndy Yan } 1640d0408543SAndy Yan 164152ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 164252ee18acSSandy Huang u32 mask, u32 shift, u32 v, 1643d0408543SAndy Yan bool write_mask) 1644d0408543SAndy Yan { 1645d0408543SAndy Yan if (!mask) 1646d0408543SAndy Yan return; 1647d0408543SAndy Yan 1648d0408543SAndy Yan if (write_mask) { 1649d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16)); 1650d0408543SAndy Yan } else { 165152ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2]; 1652d0408543SAndy Yan 1653d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 1654d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1655d0408543SAndy Yan } 1656d0408543SAndy Yan 1657d0408543SAndy Yan writel(v, vop2->regs + offset); 1658d0408543SAndy Yan } 1659d0408543SAndy Yan 1660ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 166152ee18acSSandy Huang u32 mask, u32 shift, u32 v) 166252ee18acSSandy Huang { 166352ee18acSSandy Huang u32 val = 0; 166452ee18acSSandy Huang 166552ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16)); 1666ecc31b6eSAndy Yan writel(val, grf_base + offset); 166752ee18acSSandy Huang } 166852ee18acSSandy Huang 166960e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 167060e469f5SDamon Ding u32 mask, u32 shift) 167160e469f5SDamon Ding { 167260e469f5SDamon Ding return (readl(grf_base + offset) >> shift) & mask; 167360e469f5SDamon Ding } 167460e469f5SDamon Ding 167552ee18acSSandy Huang static bool is_yuv_output(u32 bus_format) 1676d0408543SAndy Yan { 1677d0408543SAndy Yan switch (bus_format) { 1678d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 1679d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 1680034a46b5SAlgea Cao case MEDIA_BUS_FMT_YUYV10_1X20: 1681d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1682d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1683a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 1684a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 1685a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8: 1686a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8: 1687a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 1688a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 1689a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16: 1690a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16: 1691d0408543SAndy Yan return true; 1692d0408543SAndy Yan default: 1693d0408543SAndy Yan return false; 1694d0408543SAndy Yan } 1695d0408543SAndy Yan } 1696d0408543SAndy Yan 1697df0a5c43SDamon Ding static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding, 1698df0a5c43SDamon Ding enum drm_color_range color_range, 1699df0a5c43SDamon Ding int bit_depth) 170010ee9f5bSAlgea Cao { 1701df0a5c43SDamon Ding bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; 1702df0a5c43SDamon Ding enum vop_csc_format csc_mode = CSC_BT709L; 1703df0a5c43SDamon Ding 1704df0a5c43SDamon Ding 1705df0a5c43SDamon Ding switch (color_encoding) { 1706df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT601: 1707df0a5c43SDamon Ding if (full_range) 1708df0a5c43SDamon Ding csc_mode = CSC_BT601F; 17095fa6e665SDamon Ding else 1710df0a5c43SDamon Ding csc_mode = CSC_BT601L; 1711df0a5c43SDamon Ding break; 1712df0a5c43SDamon Ding 1713df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT709: 1714df0a5c43SDamon Ding if (full_range) { 1715df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F; 1716df0a5c43SDamon Ding if (bit_depth != CSC_13BIT_DEPTH) 1717df0a5c43SDamon Ding printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n"); 17185fa6e665SDamon Ding } else { 1719df0a5c43SDamon Ding csc_mode = CSC_BT709L; 17205fa6e665SDamon Ding } 1721df0a5c43SDamon Ding break; 1722df0a5c43SDamon Ding 1723df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT2020: 1724df0a5c43SDamon Ding if (full_range) { 1725df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F; 1726df0a5c43SDamon Ding if (bit_depth != CSC_13BIT_DEPTH) 1727df0a5c43SDamon Ding printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n"); 17285fa6e665SDamon Ding } else { 1729df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L; 17305fa6e665SDamon Ding } 1731df0a5c43SDamon Ding break; 1732df0a5c43SDamon Ding 173310ee9f5bSAlgea Cao default: 1734df0a5c43SDamon Ding printf("Unsuport color_encoding:%d\n", color_encoding); 173510ee9f5bSAlgea Cao } 1736df0a5c43SDamon Ding 1737df0a5c43SDamon Ding return csc_mode; 173810ee9f5bSAlgea Cao } 173910ee9f5bSAlgea Cao 1740c8820b76SDamon Ding static bool is_uv_swap(struct display_state *state) 1741d0408543SAndy Yan { 1742c8820b76SDamon Ding struct connector_state *conn_state = &state->conn_state; 1743c8820b76SDamon Ding u32 bus_format = conn_state->bus_format; 1744c8820b76SDamon Ding u32 output_mode = conn_state->output_mode; 1745c8820b76SDamon Ding u32 output_type = conn_state->type; 1746c8820b76SDamon Ding 1747d0408543SAndy Yan /* 1748d0408543SAndy Yan * FIXME: 1749d0408543SAndy Yan * 1750d0408543SAndy Yan * There is no media type for YUV444 output, 1751d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on 1752d0408543SAndy Yan * yuv format. 1753d0408543SAndy Yan * 1754c8820b76SDamon Ding * From H/W testing, YUV444 mode need a rb swap except eDP. 1755d0408543SAndy Yan */ 17563e59c137SSandy Huang if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || 17573e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || 17583e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || 17593e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || 17603e59c137SSandy Huang ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1761d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1762d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA || 1763c8820b76SDamon Ding output_mode == ROCKCHIP_OUT_MODE_P888) && 1764c8820b76SDamon Ding !(output_type == DRM_MODE_CONNECTOR_eDP))) 1765d0408543SAndy Yan return true; 1766d0408543SAndy Yan else 1767d0408543SAndy Yan return false; 1768d0408543SAndy Yan } 1769d0408543SAndy Yan 1770c8820b76SDamon Ding static bool is_rb_swap(struct display_state *state) 17710675a2a4SDamon Ding { 1772c8820b76SDamon Ding struct connector_state *conn_state = &state->conn_state; 1773c8820b76SDamon Ding u32 bus_format = conn_state->bus_format; 1774c8820b76SDamon Ding 17750675a2a4SDamon Ding /* 17760675a2a4SDamon Ding * The default component order of serial rgb3x8 formats 17770675a2a4SDamon Ding * is BGR. So it is needed to enable RB swap. 17780675a2a4SDamon Ding */ 1779b7b383ebSDamon Ding if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 || 1780b7b383ebSDamon Ding bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8) 17810675a2a4SDamon Ding return true; 17820675a2a4SDamon Ding else 17830675a2a4SDamon Ding return false; 17840675a2a4SDamon Ding } 17850675a2a4SDamon Ding 17865d2768f7SDamon Ding static bool is_yc_swap(u32 bus_format) 17875d2768f7SDamon Ding { 17885d2768f7SDamon Ding switch (bus_format) { 17895d2768f7SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 17905d2768f7SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 17915d2768f7SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 17925d2768f7SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 17935d2768f7SDamon Ding return true; 17945d2768f7SDamon Ding default: 17955d2768f7SDamon Ding return false; 17965d2768f7SDamon Ding } 17975d2768f7SDamon Ding } 17985d2768f7SDamon Ding 1799b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type) 180063cb669fSSandy Huang { 1801b0989546SSandy Huang switch (output_type) { 1802b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA: 1803b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB: 1804b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV: 1805b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort: 1806b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA: 1807b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown: 1808b0989546SSandy Huang return true; 1809b0989546SSandy Huang default: 1810b0989546SSandy Huang return false; 181163cb669fSSandy Huang } 181263cb669fSSandy Huang } 181363cb669fSSandy Huang 1814ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1815ecc31b6eSAndy Yan { 1816ecc31b6eSAndy Yan int i = 0; 1817ecc31b6eSAndy Yan 1818ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) { 1819ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id) 1820ecc31b6eSAndy Yan return &vop2->data->win_data[i]; 1821ecc31b6eSAndy Yan } 1822ecc31b6eSAndy Yan 1823ecc31b6eSAndy Yan return NULL; 1824ecc31b6eSAndy Yan } 1825ecc31b6eSAndy Yan 1826b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id) 1827b6ba80b4SDamon Ding { 1828b6ba80b4SDamon Ding int i = 0; 1829b6ba80b4SDamon Ding 1830b6ba80b4SDamon Ding for (i = 0; i < vop2->data->nr_pd; i++) { 1831b6ba80b4SDamon Ding if (vop2->data->pd[i].id == pd_id) 1832b6ba80b4SDamon Ding return &vop2->data->pd[i]; 1833b6ba80b4SDamon Ding } 1834b6ba80b4SDamon Ding 1835b6ba80b4SDamon Ding return NULL; 1836b6ba80b4SDamon Ding } 1837b6ba80b4SDamon Ding 1838db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1839db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1840db328a0dSDamon Ding { 1841db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1842db328a0dSDamon Ding int i; 1843db328a0dSDamon Ding 1844db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1845db328a0dSDamon Ding GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 1846db328a0dSDamon Ding crtc_id, false); 1847db328a0dSDamon Ding 1848db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1849db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1850db328a0dSDamon Ding 1851db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1852db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1853db328a0dSDamon Ding } 1854db328a0dSDamon Ding 1855db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1856db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1857db328a0dSDamon Ding { 1858db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1859db328a0dSDamon Ding int i; 1860db328a0dSDamon Ding 1861db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1862db328a0dSDamon Ding GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT, 1863db328a0dSDamon Ding crtc_id, false); 1864db328a0dSDamon Ding 1865db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1866db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1867db328a0dSDamon Ding 1868db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1869db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1870db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1871db328a0dSDamon Ding EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false); 1872db328a0dSDamon Ding } 1873db328a0dSDamon Ding 18741147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1875d0408543SAndy Yan struct display_state *state) 1876d0408543SAndy Yan { 18771147facaSSandy Huang struct connector_state *conn_state = &state->conn_state; 18781147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state; 18791147facaSSandy Huang struct resource gamma_res; 18801147facaSSandy Huang fdt_size_t lut_size; 18811147facaSSandy Huang int i, lut_len, ret = 0; 18821147facaSSandy Huang u32 *lut_regs; 18831147facaSSandy Huang u32 r, g, b; 18841147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 18851147facaSSandy Huang static int gamma_lut_en_num = 1; 18861147facaSSandy Huang 18871147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) { 18881147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 18891147facaSSandy Huang return 0; 18901147facaSSandy Huang } 18911147facaSSandy Huang 18921147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 18931147facaSSandy Huang if (ret) 18941147facaSSandy Huang printf("failed to get gamma lut res\n"); 18951147facaSSandy Huang lut_regs = (u32 *)gamma_res.start; 18961147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1; 18971147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 18981147facaSSandy Huang printf("failed to get gamma lut register\n"); 18991147facaSSandy Huang return 0; 19001147facaSSandy Huang } 19011147facaSSandy Huang lut_len = lut_size / 4; 19021147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) { 19031147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 19041147facaSSandy Huang return 0; 19051147facaSSandy Huang } 19060669ab1fSDamon Ding 19070669ab1fSDamon Ding if (!cstate->lut_val) { 19080669ab1fSDamon Ding if (!disp_info) 19090669ab1fSDamon Ding return 0; 19100669ab1fSDamon Ding 19110669ab1fSDamon Ding if (!disp_info->gamma_lut_data.size) 19120669ab1fSDamon Ding return 0; 19130669ab1fSDamon Ding 19140669ab1fSDamon Ding cstate->lut_val = (u32 *)calloc(1, lut_size); 19151147facaSSandy Huang for (i = 0; i < lut_len; i++) { 19161147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 19171147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 19181147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 19191147facaSSandy Huang 19200669ab1fSDamon Ding cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 19210669ab1fSDamon Ding } 19221147facaSSandy Huang } 19231147facaSSandy Huang 1924db328a0dSDamon Ding if (vop2->version == VOP_VERSION_RK3568) { 19250669ab1fSDamon Ding rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, 19260669ab1fSDamon Ding cstate->lut_val, lut_len); 19271147facaSSandy Huang gamma_lut_en_num++; 192818d9b8adSDamon Ding } else { 19290669ab1fSDamon Ding rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, 19300669ab1fSDamon Ding cstate->lut_val, lut_len); 1931db328a0dSDamon Ding if (cstate->splice_mode) { 19320669ab1fSDamon Ding rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, 19330669ab1fSDamon Ding cstate->lut_val, lut_len); 1934db328a0dSDamon Ding gamma_lut_en_num++; 1935db328a0dSDamon Ding } 1936db328a0dSDamon Ding gamma_lut_en_num++; 1937db328a0dSDamon Ding } 19381147facaSSandy Huang 19390669ab1fSDamon Ding free(cstate->lut_val); 19400669ab1fSDamon Ding 1941d0408543SAndy Yan return 0; 1942d0408543SAndy Yan } 1943d0408543SAndy Yan 19446414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 19456414e3bcSSandy Huang struct display_state *state) 19466414e3bcSSandy Huang { 19476414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state; 19486414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state; 19496414e3bcSSandy Huang int i, cubic_lut_len; 19506414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 19516414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 19526414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 19536414e3bcSSandy Huang u32 *cubic_lut_addr; 19546414e3bcSSandy Huang 19556414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 19566414e3bcSSandy Huang return 0; 19576414e3bcSSandy Huang 19586414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size) 19596414e3bcSSandy Huang return 0; 19606414e3bcSSandy Huang 19616414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 19626414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size; 19636414e3bcSSandy Huang 19646414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) { 19656414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 19666414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 19676414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 19686414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 19696414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) + 19706414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 19716414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28); 19726414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 19736414e3bcSSandy Huang *cubic_lut_addr++ = 0; 19746414e3bcSSandy Huang } 19756414e3bcSSandy Huang 19766414e3bcSSandy Huang if (cubic_lut_len % 2) { 19776414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 19786414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 19796414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 19806414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 19816414e3bcSSandy Huang *cubic_lut_addr++ = 0; 19826414e3bcSSandy Huang *cubic_lut_addr = 0; 19836414e3bcSSandy Huang } 19846414e3bcSSandy Huang 19856414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 19866414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id)); 19876414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 19886414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 19896414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 19906414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 19916414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 19926414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 19936414e3bcSSandy Huang 19946414e3bcSSandy Huang return 0; 19956414e3bcSSandy Huang } 19966414e3bcSSandy Huang 1997ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2, 1998ee01dbb2SDamon Ding struct bcsh_state *bcsh_state, int crtc_id) 1999ee01dbb2SDamon Ding { 2000ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 2001ee01dbb2SDamon Ding u32 vp_offset = crtc_id * 0x100; 2002ee01dbb2SDamon Ding 2003ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 2004ee01dbb2SDamon Ding BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false); 2005ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 2006ee01dbb2SDamon Ding BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false); 2007ee01dbb2SDamon Ding 2008ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 2009ee01dbb2SDamon Ding BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 2010ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 2011ee01dbb2SDamon Ding BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 2012ee01dbb2SDamon Ding 2013ee01dbb2SDamon Ding if (!cstate->bcsh_en) { 2014ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 2015ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 2016ee01dbb2SDamon Ding return; 2017ee01dbb2SDamon Ding } 2018ee01dbb2SDamon Ding 2019ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2020ee01dbb2SDamon Ding BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 2021ee01dbb2SDamon Ding bcsh_state->brightness, false); 2022ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2023ee01dbb2SDamon Ding BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false); 2024ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2025ee01dbb2SDamon Ding BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 2026ee01dbb2SDamon Ding bcsh_state->saturation * bcsh_state->contrast / 0x100, false); 2027ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 2028ee01dbb2SDamon Ding BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false); 2029ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 2030ee01dbb2SDamon Ding BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false); 2031ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2032ee01dbb2SDamon Ding BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 2033ee01dbb2SDamon Ding BCSH_OUT_MODE_NORMAL_VIDEO, false); 2034ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 2035ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 2036ee01dbb2SDamon Ding } 2037ee01dbb2SDamon Ding 2038ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 2039ac500a1fSSandy Huang { 2040ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state; 2041ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info; 2042ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state; 2043ee01dbb2SDamon Ding struct bcsh_state bcsh_state; 2044ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue; 2045ac500a1fSSandy Huang 2046ac500a1fSSandy Huang if (!conn_state->disp_info) 2047ac500a1fSSandy Huang return; 2048ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info; 2049ac500a1fSSandy Huang if (!bcsh_info) 2050ac500a1fSSandy Huang return; 2051ac500a1fSSandy Huang 2052ac500a1fSSandy Huang if (bcsh_info->brightness != 50 || 2053ac500a1fSSandy Huang bcsh_info->contrast != 50 || 2054ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50) 2055ee01dbb2SDamon Ding cstate->bcsh_en = true; 2056ac500a1fSSandy Huang 2057ee01dbb2SDamon Ding if (cstate->bcsh_en) { 2058ac500a1fSSandy Huang if (!cstate->yuv_overlay) 2059ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 2060ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format)) 2061ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 2062ac500a1fSSandy Huang } else { 2063ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 2064ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 2065ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 2066ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 2067ac500a1fSSandy Huang } 2068ac500a1fSSandy Huang 2069df0a5c43SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, 2070df0a5c43SDamon Ding conn_state->color_range, 2071df0a5c43SDamon Ding CSC_10BIT_DEPTH); 2072ac500a1fSSandy Huang 2073ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 2074ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127, 2075ac500a1fSSandy Huang bcsh_info->brightness); 2076ac500a1fSSandy Huang else 2077ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31, 2078ac500a1fSSandy Huang bcsh_info->brightness); 2079ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 2080ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 2081ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 2082ac500a1fSSandy Huang 2083ac500a1fSSandy Huang 2084ac500a1fSSandy Huang /* 2085ac500a1fSSandy Huang * a:[-30~0): 2086ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256; 2087ac500a1fSSandy Huang * cos_hue = cos(a)*256; 2088ac500a1fSSandy Huang * a:[0~30] 2089ac500a1fSSandy Huang * sin_hue = sin(a)*256; 2090ac500a1fSSandy Huang * cos_hue = cos(a)*256; 2091ac500a1fSSandy Huang */ 2092ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23; 2093ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23; 2094ac500a1fSSandy Huang 2095ee01dbb2SDamon Ding bcsh_state.brightness = brightness; 2096ee01dbb2SDamon Ding bcsh_state.contrast = contrast; 2097ee01dbb2SDamon Ding bcsh_state.saturation = saturation; 2098ee01dbb2SDamon Ding bcsh_state.sin_hue = sin_hue; 2099ee01dbb2SDamon Ding bcsh_state.cos_hue = cos_hue; 2100ee01dbb2SDamon Ding 2101ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id); 2102ee01dbb2SDamon Ding if (cstate->splice_mode) 2103ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id); 2104ee01dbb2SDamon Ding } 2105ee01dbb2SDamon Ding 2106ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id) 2107ee01dbb2SDamon Ding { 2108ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 2109ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 2110ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 2111ee01dbb2SDamon Ding u32 bg_ovl_dly, bg_dly, pre_scan_dly; 2112ee01dbb2SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 2113ee01dbb2SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2114ee01dbb2SDamon Ding 2115ee01dbb2SDamon Ding bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly; 2116ee01dbb2SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly; 2117ee01dbb2SDamon Ding bg_dly -= bg_ovl_dly; 2118ee01dbb2SDamon Ding 2119a552a69cSDamon Ding /* 2120a552a69cSDamon Ding * splice mode: hdisplay must roundup as 4 pixel, 2121a552a69cSDamon Ding * no splice mode: hdisplay must roundup as 2 pixel. 2122a552a69cSDamon Ding */ 2123ee01dbb2SDamon Ding if (cstate->splice_mode) 2124a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1; 2125ee01dbb2SDamon Ding else 2126a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1; 2127ee01dbb2SDamon Ding 2128ee01dbb2SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 2129ee01dbb2SDamon Ding hsync_len = 8; 2130ee01dbb2SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 2131ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4, 2132ee01dbb2SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 2133ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 2134ac500a1fSSandy Huang } 2135ac500a1fSSandy Huang 2136452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id) 2137452afb13SDamon Ding { 2138452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 2139452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 2140452afb13SDamon Ding u32 bg_dly, pre_scan_dly; 2141452afb13SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 2142452afb13SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2143452afb13SDamon Ding 2144452afb13SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].win_dly + 2145452afb13SDamon Ding vop2->data->vp_data[crtc_id].layer_mix_dly + 2146452afb13SDamon Ding vop2->data->vp_data[crtc_id].hdr_mix_dly; 2147a552a69cSDamon Ding /* hdisplay must roundup as 2 pixel */ 2148a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1; 2149a552a69cSDamon Ding /** 2150a552a69cSDamon Ding * pre_scan_hblank minimum value is 8, otherwise the win reset signal will 2151a552a69cSDamon Ding * lead to first line data be zero. 2152a552a69cSDamon Ding */ 2153a552a69cSDamon Ding pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len); 2154452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100, 2155452afb13SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 2156452afb13SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 2157452afb13SDamon Ding } 2158452afb13SDamon Ding 2159d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 2160d0408543SAndy Yan { 2161d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 2162d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 216352ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state; 21649c7848c3SDamon Ding const struct vop2_data *vop2_data = vop2->data; 21659c7848c3SDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops; 216652ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2167d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal; 2168d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 2169d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 2170d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2171d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay; 2172d0408543SAndy Yan u16 hsize = 2173d0408543SAndy Yan hdisplay * (conn_state->overscan.left_margin + 2174d0408543SAndy Yan conn_state->overscan.right_margin) / 200; 2175d0408543SAndy Yan u16 vsize = 2176d0408543SAndy Yan vdisplay * (conn_state->overscan.top_margin + 2177d0408543SAndy Yan conn_state->overscan.bottom_margin) / 200; 2178d0408543SAndy Yan u16 hact_end, vact_end; 2179d0408543SAndy Yan u32 val; 2180d0408543SAndy Yan 218174bd8269SSandy Huang hsize = round_down(hsize, 2); 2182d0408543SAndy Yan vsize = round_down(vsize, 2); 2183d0408543SAndy Yan 2184d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 2185d0408543SAndy Yan hact_end = hact_st + hsize; 2186d0408543SAndy Yan val = hact_st << 16; 2187d0408543SAndy Yan val |= hact_end; 2188d0408543SAndy Yan 218952ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 2190d0408543SAndy Yan vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 2191d0408543SAndy Yan vact_end = vact_st + vsize; 2192d0408543SAndy Yan val = vact_st << 16; 2193d0408543SAndy Yan val |= vact_end; 219452ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 2195d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16; 2196d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize); 219752ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 2198d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 2199d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 22007504507fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 22017504507fSSandy Huang RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT, 2202d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 22037504507fSSandy Huang POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false); 2204d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 2205d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 2206d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize; 2207d0408543SAndy Yan 2208d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 220952ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 2210d0408543SAndy Yan } 2211d0408543SAndy Yan 2212452afb13SDamon Ding if (is_vop3(vop2)) { 2213452afb13SDamon Ding vop3_setup_pipe_dly(state, vop2, cstate->crtc_id); 2214452afb13SDamon Ding } else { 2215ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id); 22169c7848c3SDamon Ding vop2_ops->setup_win_dly(state, cstate->crtc_id); 22179c7848c3SDamon Ding if (cstate->splice_mode) { 2218ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id); 22199c7848c3SDamon Ding vop2_ops->setup_win_dly(state, cstate->splice_crtc_id); 22209c7848c3SDamon Ding } 2221d0408543SAndy Yan } 2222452afb13SDamon Ding } 2223d0408543SAndy Yan 22246027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2) 22256027c871SZhang Yubing { 22266027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 22276027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 22286027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 22296027c871SZhang Yubing struct drm_display_mode *mode = &conn_state->mode; 22306027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 22316027c871SZhang Yubing s16 *lut_y; 22326027c871SZhang Yubing s16 *lut_h; 22336027c871SZhang Yubing s16 *lut_s; 22346027c871SZhang Yubing u32 value; 22356027c871SZhang Yubing int i; 22366027c871SZhang Yubing 22376027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2238b8db91d0SZhang Yubing POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 2239b8db91d0SZhang Yubing if (!acm->acm_enable) { 2240b8db91d0SZhang Yubing writel(0, vop2->regs + RK3528_ACM_CTRL); 22416027c871SZhang Yubing return; 22426027c871SZhang Yubing } 22436027c871SZhang Yubing 22446027c871SZhang Yubing printf("post acm enable\n"); 22456027c871SZhang Yubing 22466027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_START); 22476027c871SZhang Yubing 22486027c871SZhang Yubing value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) + 22496027c871SZhang Yubing ((mode->vdisplay & 0xfff) << 20); 22506027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_CTRL); 22516027c871SZhang Yubing 22526027c871SZhang Yubing value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + 22536027c871SZhang Yubing ((acm->s_gain << 20) & 0x3ff00000); 22546027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE); 22556027c871SZhang Yubing 22566027c871SZhang Yubing lut_y = &acm->gain_lut_hy[0]; 22576027c871SZhang Yubing lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH]; 22586027c871SZhang Yubing lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2]; 22596027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) { 22606027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 22616027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 22626027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2)); 22636027c871SZhang Yubing } 22646027c871SZhang Yubing 22656027c871SZhang Yubing lut_y = &acm->gain_lut_hs[0]; 22666027c871SZhang Yubing lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH]; 22676027c871SZhang Yubing lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2]; 22686027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) { 22696027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 22706027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 22716027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2)); 22726027c871SZhang Yubing } 22736027c871SZhang Yubing 22746027c871SZhang Yubing lut_y = &acm->delta_lut_h[0]; 22756027c871SZhang Yubing lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH]; 22766027c871SZhang Yubing lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2]; 22776027c871SZhang Yubing for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) { 22786027c871SZhang Yubing value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) + 22796027c871SZhang Yubing ((lut_s[i] << 20) & 0x3ff00000); 22806027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2)); 22816027c871SZhang Yubing } 22826027c871SZhang Yubing 22836027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_DONE); 22846027c871SZhang Yubing } 22856027c871SZhang Yubing 22866027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2) 22876027c871SZhang Yubing { 22886027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 22896027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 22906027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 22916027c871SZhang Yubing struct csc_info *csc = &conn_state->disp_info->csc_info; 22926027c871SZhang Yubing struct post_csc_coef csc_coef; 22936027c871SZhang Yubing bool is_input_yuv = false; 22946027c871SZhang Yubing bool is_output_yuv = false; 22956027c871SZhang Yubing bool post_r2y_en = false; 22966027c871SZhang Yubing bool post_csc_en = false; 22976027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 22986027c871SZhang Yubing u32 value; 22996027c871SZhang Yubing int range_type; 23006027c871SZhang Yubing 23016027c871SZhang Yubing printf("post csc enable\n"); 23026027c871SZhang Yubing 23036027c871SZhang Yubing if (acm->acm_enable) { 23046027c871SZhang Yubing if (!cstate->yuv_overlay) 23056027c871SZhang Yubing post_r2y_en = true; 23066027c871SZhang Yubing 23076027c871SZhang Yubing /* do y2r in csc module */ 23086027c871SZhang Yubing if (!is_yuv_output(conn_state->bus_format)) 23096027c871SZhang Yubing post_csc_en = true; 23106027c871SZhang Yubing } else { 23116027c871SZhang Yubing if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 23126027c871SZhang Yubing post_r2y_en = true; 23136027c871SZhang Yubing 23146027c871SZhang Yubing /* do y2r in csc module */ 23156027c871SZhang Yubing if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 23166027c871SZhang Yubing post_csc_en = true; 23176027c871SZhang Yubing } 23186027c871SZhang Yubing 23196027c871SZhang Yubing if (csc->csc_enable) 23206027c871SZhang Yubing post_csc_en = true; 23216027c871SZhang Yubing 23226027c871SZhang Yubing if (cstate->yuv_overlay || post_r2y_en) 23236027c871SZhang Yubing is_input_yuv = true; 23246027c871SZhang Yubing 23256027c871SZhang Yubing if (is_yuv_output(conn_state->bus_format)) 23266027c871SZhang Yubing is_output_yuv = true; 23276027c871SZhang Yubing 2328df0a5c43SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, 2329df0a5c43SDamon Ding conn_state->color_range, 2330df0a5c43SDamon Ding CSC_13BIT_DEPTH); 23316027c871SZhang Yubing 23326027c871SZhang Yubing if (post_csc_en) { 23336027c871SZhang Yubing rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv, 23346027c871SZhang Yubing is_output_yuv); 23356027c871SZhang Yubing 23366027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23376027c871SZhang Yubing POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT, 23386027c871SZhang Yubing csc_coef.csc_coef00, false); 23395743c73eSZhang Yubing value = csc_coef.csc_coef01 & 0xffff; 23405743c73eSZhang Yubing value |= (csc_coef.csc_coef02 << 16) & 0xffff0000; 23416027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02); 23425743c73eSZhang Yubing value = csc_coef.csc_coef10 & 0xffff; 23435743c73eSZhang Yubing value |= (csc_coef.csc_coef11 << 16) & 0xffff0000; 23446027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11); 23455743c73eSZhang Yubing value = csc_coef.csc_coef12 & 0xffff; 23465743c73eSZhang Yubing value |= (csc_coef.csc_coef20 << 16) & 0xffff0000; 23476027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20); 23485743c73eSZhang Yubing value = csc_coef.csc_coef21 & 0xffff; 23495743c73eSZhang Yubing value |= (csc_coef.csc_coef22 << 16) & 0xffff0000; 23506027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22); 23516027c871SZhang Yubing writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0); 23526027c871SZhang Yubing writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1); 23536027c871SZhang Yubing writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2); 23546027c871SZhang Yubing 23556027c871SZhang Yubing range_type = csc_coef.range_type ? 0 : 1; 23566027c871SZhang Yubing range_type <<= is_input_yuv ? 0 : 1; 23576027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23586027c871SZhang Yubing POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false); 23596027c871SZhang Yubing } 23606027c871SZhang Yubing 23616027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23625743c73eSZhang Yubing POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false); 23636027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23646027c871SZhang Yubing POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false); 23656027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23666027c871SZhang Yubing POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false); 23676027c871SZhang Yubing } 23686027c871SZhang Yubing 23696027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2) 23706027c871SZhang Yubing { 23716027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 23726027c871SZhang Yubing struct base2_disp_info *disp_info = conn_state->disp_info; 23736027c871SZhang Yubing const char *enable_flag; 23746027c871SZhang Yubing if (!disp_info) { 23756027c871SZhang Yubing printf("disp_info is empty\n"); 23766027c871SZhang Yubing return; 23776027c871SZhang Yubing } 23786027c871SZhang Yubing 23796027c871SZhang Yubing enable_flag = (const char *)&disp_info->cacm_header; 23806027c871SZhang Yubing if (strncasecmp(enable_flag, "CACM", 4)) { 23816027c871SZhang Yubing printf("acm and csc is not support\n"); 23826027c871SZhang Yubing return; 23836027c871SZhang Yubing } 23846027c871SZhang Yubing 23856027c871SZhang Yubing vop3_post_acm_config(state, vop2); 23866027c871SZhang Yubing vop3_post_csc_config(state, vop2); 23876027c871SZhang Yubing } 23886027c871SZhang Yubing 2389a552a69cSDamon Ding static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2, 2390a552a69cSDamon Ding struct vop2_power_domain_data *pd_data) 2391a552a69cSDamon Ding { 2392a552a69cSDamon Ding int val = 0; 2393a552a69cSDamon Ding bool is_bisr_en, is_otp_bisr_en; 2394a552a69cSDamon Ding 2395a552a69cSDamon Ding if (pd_data->id == VOP2_PD_CLUSTER) { 2396a552a69cSDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0, 2397a552a69cSDamon Ding EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT); 2398a552a69cSDamon Ding is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0, 2399a552a69cSDamon Ding EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT); 2400a552a69cSDamon Ding if (is_bisr_en && is_otp_bisr_en) 2401a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 2402a552a69cSDamon Ding val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1), 2403a552a69cSDamon Ding 50 * 1000); 2404a552a69cSDamon Ding else 2405a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS, 24060e0a0ff9SDamon Ding val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1), 2407a552a69cSDamon Ding 50 * 1000); 2408a552a69cSDamon Ding } else { 2409a552a69cSDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0, 2410a552a69cSDamon Ding EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT); 2411a552a69cSDamon Ding is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0, 2412a552a69cSDamon Ding EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT); 2413a552a69cSDamon Ding if (is_bisr_en && is_otp_bisr_en) 2414a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 2415a552a69cSDamon Ding val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1), 2416a552a69cSDamon Ding 50 * 1000); 2417a552a69cSDamon Ding else 2418a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS, 2419a552a69cSDamon Ding val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1), 2420a552a69cSDamon Ding 50 * 1000); 2421a552a69cSDamon Ding } 2422a552a69cSDamon Ding } 2423a552a69cSDamon Ding 2424a552a69cSDamon Ding static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 2425a552a69cSDamon Ding { 2426a552a69cSDamon Ding int ret = 0; 2427a552a69cSDamon Ding 2428a552a69cSDamon Ding if (pd_data->id == VOP2_PD_CLUSTER) 2429a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK, 2430a552a69cSDamon Ding RK3576_CLUSTER_PD_EN_SHIFT, 0, true); 2431a552a69cSDamon Ding else 2432a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK, 2433a552a69cSDamon Ding RK3576_ESMART_PD_EN_SHIFT, 0, true); 2434a552a69cSDamon Ding ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data); 2435a552a69cSDamon Ding if (ret) { 2436a552a69cSDamon Ding printf("wait vop2 power domain timeout\n"); 2437a552a69cSDamon Ding return ret; 2438a552a69cSDamon Ding } 2439a552a69cSDamon Ding 2440a552a69cSDamon Ding return 0; 2441a552a69cSDamon Ding } 2442a552a69cSDamon Ding 2443a552a69cSDamon Ding static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2, 2444a552a69cSDamon Ding struct vop2_power_domain_data *pd_data) 244560e469f5SDamon Ding { 244660e469f5SDamon Ding int val = 0; 244760e469f5SDamon Ding int shift = 0; 2448b6ba80b4SDamon Ding int shift_factor = 0; 244960e469f5SDamon Ding bool is_bisr_en = false; 245060e469f5SDamon Ding 2451b6ba80b4SDamon Ding /* 2452b6ba80b4SDamon Ding * The order of pd status bits in BISR_STS register 2453b6ba80b4SDamon Ding * is different from that in VOP SYS_STS register. 2454b6ba80b4SDamon Ding */ 2455b6ba80b4SDamon Ding if (pd_data->id == VOP2_PD_DSC_8K || 2456b6ba80b4SDamon Ding pd_data->id == VOP2_PD_DSC_4K || 2457b6ba80b4SDamon Ding pd_data->id == VOP2_PD_ESMART) 2458b6ba80b4SDamon Ding shift_factor = 1; 2459b6ba80b4SDamon Ding 2460b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor; 2461b6ba80b4SDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift); 246260e469f5SDamon Ding if (is_bisr_en) { 2463b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor; 2464b6ba80b4SDamon Ding 246560e469f5SDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 2466d2e91fdcSDamon Ding ((val >> shift) & 0x1), 50 * 1000); 246760e469f5SDamon Ding } else { 2468b6ba80b4SDamon Ding shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1; 2469b6ba80b4SDamon Ding 247060e469f5SDamon Ding return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 247160e469f5SDamon Ding !((val >> shift) & 0x1), 50 * 1000); 247260e469f5SDamon Ding } 247360e469f5SDamon Ding } 247460e469f5SDamon Ding 2475a552a69cSDamon Ding static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 2476a552a69cSDamon Ding { 2477a552a69cSDamon Ding int ret = 0; 2478a552a69cSDamon Ding 2479a552a69cSDamon Ding vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK, 2480a552a69cSDamon Ding RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false); 2481a552a69cSDamon Ding ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data); 2482a552a69cSDamon Ding if (ret) { 2483a552a69cSDamon Ding printf("wait vop2 power domain timeout\n"); 2484a552a69cSDamon Ding return ret; 2485a552a69cSDamon Ding } 2486a552a69cSDamon Ding 2487a552a69cSDamon Ding return 0; 2488a552a69cSDamon Ding } 2489a552a69cSDamon Ding 2490b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id) 249160e469f5SDamon Ding { 249260e469f5SDamon Ding struct vop2_power_domain_data *pd_data; 249360e469f5SDamon Ding int ret = 0; 249460e469f5SDamon Ding 2495b6ba80b4SDamon Ding if (!pd_id) 2496b6ba80b4SDamon Ding return 0; 2497b6ba80b4SDamon Ding 2498b6ba80b4SDamon Ding pd_data = vop2_find_pd_data_by_id(vop2, pd_id); 2499b6ba80b4SDamon Ding if (!pd_data) { 2500b6ba80b4SDamon Ding printf("can't find pd_data by id\n"); 250160e469f5SDamon Ding return -EINVAL; 250260e469f5SDamon Ding } 25032c66af11SDamon Ding 2504b6ba80b4SDamon Ding if (pd_data->parent_id) { 2505b6ba80b4SDamon Ding ret = vop2_power_domain_on(vop2, pd_data->parent_id); 250660e469f5SDamon Ding if (ret) { 250760e469f5SDamon Ding printf("can't open parent power domain\n"); 250860e469f5SDamon Ding return -EINVAL; 250960e469f5SDamon Ding } 251060e469f5SDamon Ding } 251160e469f5SDamon Ding 2512a552a69cSDamon Ding /* 2513a552a69cSDamon Ding * Read VOP internal power domain on/off status. 2514a552a69cSDamon Ding * We should query BISR_STS register in PMU for 2515a552a69cSDamon Ding * power up/down status when memory repair is enabled. 2516a552a69cSDamon Ding * Return value: 1 for power on, 0 for power off; 2517a552a69cSDamon Ding */ 2518a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 2519a552a69cSDamon Ding ret = rk3576_vop2_power_domain_on(vop2, pd_data); 2520a552a69cSDamon Ding else 2521a552a69cSDamon Ding ret = rk3588_vop2_power_domain_on(vop2, pd_data); 252260e469f5SDamon Ding 2523a552a69cSDamon Ding return ret; 252460e469f5SDamon Ding } 252560e469f5SDamon Ding 2526ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2) 2527ecc31b6eSAndy Yan { 2528ecc31b6eSAndy Yan u32 *base = vop2->regs; 2529ecc31b6eSAndy Yan int i = 0; 2530ecc31b6eSAndy Yan 2531ecc31b6eSAndy Yan /* 2532ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 2533ecc31b6eSAndy Yan */ 2534ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++) 2535ecc31b6eSAndy Yan vop2->regsbak[i] = base[i]; 2536ecc31b6eSAndy Yan } 2537ecc31b6eSAndy Yan 25385fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win) 25395fa6e665SDamon Ding { 25405fa6e665SDamon Ding if (!is_vop3(vop2)) 25415fa6e665SDamon Ding return false; 25425fa6e665SDamon Ding 25435fa6e665SDamon Ding if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE && 25445fa6e665SDamon Ding win->phys_id != ROCKCHIP_VOP2_ESMART0) 25455fa6e665SDamon Ding return true; 25465fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE && 25475fa6e665SDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) 25485fa6e665SDamon Ding return true; 25495fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && 25505fa6e665SDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART1) 25515fa6e665SDamon Ding return true; 2552a552a69cSDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE && 2553a552a69cSDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART3) 2554a552a69cSDamon Ding return true; 25555fa6e665SDamon Ding else 25565fa6e665SDamon Ding return false; 25575fa6e665SDamon Ding } 25585fa6e665SDamon Ding 25595fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2) 25605fa6e665SDamon Ding { 25615fa6e665SDamon Ding struct vop2_win_data *win_data; 2562fa4ecc32SDamon Ding int i; 25635fa6e665SDamon Ding u8 scale_engine_num = 0; 25645fa6e665SDamon Ding 25655fa6e665SDamon Ding /* store plane mask for vop2_fixup_dts */ 2566fa4ecc32SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 2567fa4ecc32SDamon Ding win_data = &vop2->data->win_data[i]; 25685fa6e665SDamon Ding if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data)) 25695fa6e665SDamon Ding continue; 25705fa6e665SDamon Ding 25715fa6e665SDamon Ding win_data->scale_engine_num = scale_engine_num++; 25725fa6e665SDamon Ding } 25735fa6e665SDamon Ding } 25745fa6e665SDamon Ding 2575a552a69cSDamon Ding static int vop3_get_esmart_lb_mode(struct vop2 *vop2) 2576a552a69cSDamon Ding { 2577a552a69cSDamon Ding const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map; 2578a552a69cSDamon Ding int i; 2579a552a69cSDamon Ding 2580a552a69cSDamon Ding if (!esmart_lb_mode_map) 2581a552a69cSDamon Ding return vop2->esmart_lb_mode; 2582a552a69cSDamon Ding 2583a552a69cSDamon Ding for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) { 2584a552a69cSDamon Ding if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode) 2585a552a69cSDamon Ding return esmart_lb_mode_map->lb_map_value; 2586a552a69cSDamon Ding esmart_lb_mode_map++; 2587a552a69cSDamon Ding } 2588a552a69cSDamon Ding 2589a552a69cSDamon Ding if (i == vop2->data->esmart_lb_mode_num) 2590a552a69cSDamon Ding printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode); 2591a552a69cSDamon Ding 2592a552a69cSDamon Ding return vop2->data->esmart_lb_mode_map[0].lb_map_value; 2593a552a69cSDamon Ding } 2594a552a69cSDamon Ding 2595b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 2596d0408543SAndy Yan { 2597b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 2598b7195f56SDamon Ding const struct vop2_data *vop2_data = vop2->data; 2599b7195f56SDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops; 2600b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 2601a552a69cSDamon Ding int active_vp_num = 0; 26025fa6e665SDamon Ding int layer_phy_id = 0; 26035fa6e665SDamon Ding int i, j; 26045fa6e665SDamon Ding u32 layer_nr = 0; 260551e1509eSDamon Ding const u8 *tmp; 2606d0408543SAndy Yan 260763cb669fSSandy Huang if (vop2->global_init) 2608d0408543SAndy Yan return; 260963cb669fSSandy Huang 2610b0989546SSandy Huang /* OTP must enable at the first time, otherwise mirror layer register is error */ 261163cb669fSSandy Huang if (soc_is_rk3566()) 261263cb669fSSandy Huang vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 261363cb669fSSandy Huang OTP_WIN_EN_SHIFT, 1, false); 2614b0989546SSandy Huang 2615b0989546SSandy Huang if (cstate->crtc->assign_plane) {/* dts assign plane */ 2616b0989546SSandy Huang u32 plane_mask; 2617b0989546SSandy Huang int primary_plane_id; 2618b0989546SSandy Huang 2619b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2620b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask; 2621b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2622b0989546SSandy Huang layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 2623b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 26245fc2b656SDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 2625337d1c13SDamon Ding if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX) 2626b0989546SSandy Huang primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 2627b0989546SSandy Huang vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 2628b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2629b0989546SSandy Huang 2630b0989546SSandy Huang /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 2631b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2632b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 2633b0989546SSandy Huang plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 263463cb669fSSandy Huang } 2635b0989546SSandy Huang } 2636b0989546SSandy Huang } else {/* need soft assign plane mask */ 2637a552a69cSDamon Ding printf("Assign plane mask automatically\n"); 2638a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 2639a552a69cSDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 2640a552a69cSDamon Ding if (cstate->crtc->vps[i].enable) { 2641a552a69cSDamon Ding vop2->vp_plane_mask[i].attached_layers_nr = 1; 2642a552a69cSDamon Ding vop2->vp_plane_mask[i].primary_plane_id = 2643a552a69cSDamon Ding vop2->data->vp_default_primary_plane[i]; 2644a552a69cSDamon Ding vop2->vp_plane_mask[i].attached_layers[0] = 2645a552a69cSDamon Ding vop2->data->vp_default_primary_plane[i]; 2646a552a69cSDamon Ding vop2->vp_plane_mask[i].plane_mask |= 2647a552a69cSDamon Ding BIT(vop2->data->vp_default_primary_plane[i]); 2648a552a69cSDamon Ding active_vp_num++; 2649a552a69cSDamon Ding } 2650a552a69cSDamon Ding } 2651a552a69cSDamon Ding printf("VOP have %d active VP\n", active_vp_num); 2652a552a69cSDamon Ding } else { 2653b0989546SSandy Huang /* find the first unplug devices and set it as main display */ 2654b0989546SSandy Huang int main_vp_index = -1; 2655b0989546SSandy Huang 2656b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2657b0989546SSandy Huang if (cstate->crtc->vps[i].enable) 2658b0989546SSandy Huang active_vp_num++; 2659b0989546SSandy Huang } 2660b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num); 2661b0989546SSandy Huang 2662b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2) 2663b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n"); 2664b0989546SSandy Huang plane_mask = vop2->data->plane_mask; 2665b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 26665fa6e665SDamon Ding /* 2667a552a69cSDamon Ding * For rk3528, one display policy for hdmi store in plane_mask[0], and 2668a552a69cSDamon Ding * the other for cvbs store in plane_mask[2]. 26695fa6e665SDamon Ding */ 26705fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 && 26715fa6e665SDamon Ding cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV) 26725fa6e665SDamon Ding plane_mask += 2 * VOP2_VP_MAX; 2673b0989546SSandy Huang 26745fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528) { 26755fa6e665SDamon Ding /* 2676a552a69cSDamon Ding * For rk3528, the plane mask of vp is limited, only esmart2 can 2677a552a69cSDamon Ding * be selected by both vp0 and vp1. 26785fa6e665SDamon Ding */ 26795fa6e665SDamon Ding j = 0; 26805fa6e665SDamon Ding } else { 2681b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2682b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 2683a552a69cSDamon Ding /* the first store main display plane mask */ 2684a552a69cSDamon Ding vop2->vp_plane_mask[i] = plane_mask[0]; 2685b0989546SSandy Huang main_vp_index = i; 2686e007876dSSandy Huang break; 2687b0989546SSandy Huang } 2688b0989546SSandy Huang } 2689b0989546SSandy Huang 2690b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */ 2691b0989546SSandy Huang if (main_vp_index < 0) { 2692b0989546SSandy Huang main_vp_index = 0; 2693b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0]; 2694b0989546SSandy Huang } 2695b0989546SSandy Huang 2696a552a69cSDamon Ding /* plane_mask[0] store main display, so we from plane_mask[1] */ 2697a552a69cSDamon Ding j = 1; 26985fa6e665SDamon Ding } 2699b0989546SSandy Huang 2700b0989546SSandy Huang /* init other display except main display */ 2701b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2702a552a69cSDamon Ding /* main display or no connect devices */ 2703a552a69cSDamon Ding if (i == main_vp_index || !cstate->crtc->vps[i].enable) 2704b0989546SSandy Huang continue; 2705b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++]; 270683d6b087SDamon Ding /* 270783d6b087SDamon Ding * For rk3588, the main window should attach to the VP0 while 270883d6b087SDamon Ding * the splice window should attach to the VP1 when the display 270983d6b087SDamon Ding * mode is over 4k. 271083d6b087SDamon Ding * If only one VP is enabled and the plane mask is not assigned 271183d6b087SDamon Ding * in DTS, all main windows will be assigned to the enabled VPx, 271283d6b087SDamon Ding * and all splice windows will be assigned to the VPx+1, in order 271383d6b087SDamon Ding * to ensure that the splice mode work well. 271483d6b087SDamon Ding */ 271583d6b087SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && active_vp_num == 1) 271683d6b087SDamon Ding vop2->vp_plane_mask[(i + 1) % vop2->data->nr_vps] = plane_mask[j++]; 2717b0989546SSandy Huang } 2718a552a69cSDamon Ding } 2719b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */ 2720b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2721b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 2722b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2723b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 2724b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 2725b0989546SSandy Huang } 2726b0989546SSandy Huang } 2727b0989546SSandy Huang } 2728b0989546SSandy Huang 272960e469f5SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 273060e469f5SDamon Ding rk3588_vop2_regsbak(vop2); 273160e469f5SDamon Ding else 273260e469f5SDamon Ding memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 273360e469f5SDamon Ding 273460e469f5SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 273560e469f5SDamon Ding OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 273660e469f5SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 273760e469f5SDamon Ding IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 273860e469f5SDamon Ding 2739b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2740b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 2741b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 274227cec8e2SDamon Ding printf("%s ", 274327cec8e2SDamon Ding vop2_plane_id_to_string(vop2->vp_plane_mask[i].attached_layers[j])); 274427cec8e2SDamon Ding printf("], primary plane: %s\n", 274527cec8e2SDamon Ding vop2_plane_id_to_string(vop2->vp_plane_mask[i].primary_plane_id)); 2746b0989546SSandy Huang } 2747b0989546SSandy Huang 2748b7195f56SDamon Ding vop2_ops->setup_overlay(state); 2749b0989546SSandy Huang 27505fa6e665SDamon Ding if (is_vop3(vop2)) { 27515fa6e665SDamon Ding /* 27525fa6e665SDamon Ding * you can rewrite at dts vop node: 27535fa6e665SDamon Ding * 27545fa6e665SDamon Ding * VOP3_ESMART_8K_MODE = 0, 27555fa6e665SDamon Ding * VOP3_ESMART_4K_4K_MODE = 1, 27565fa6e665SDamon Ding * VOP3_ESMART_4K_2K_2K_MODE = 2, 27575fa6e665SDamon Ding * VOP3_ESMART_2K_2K_2K_2K_MODE = 3, 27585fa6e665SDamon Ding * 27595fa6e665SDamon Ding * &vop { 27605fa6e665SDamon Ding * esmart_lb_mode = /bits/ 8 <2>; 27615fa6e665SDamon Ding * }; 276263cb669fSSandy Huang */ 276351e1509eSDamon Ding tmp = dev_read_u8_array_ptr(cstate->dev, "esmart_lb_mode", 1); 276451e1509eSDamon Ding if (tmp) 276551e1509eSDamon Ding vop2->esmart_lb_mode = *tmp; 276651e1509eSDamon Ding else 27675fa6e665SDamon Ding vop2->esmart_lb_mode = vop2->data->esmart_lb_mode; 2768a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 2769a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, 2770a552a69cSDamon Ding RK3576_ESMART_LB_MODE_SEL_MASK, 2771a552a69cSDamon Ding RK3576_ESMART_LB_MODE_SEL_SHIFT, 2772a552a69cSDamon Ding vop3_get_esmart_lb_mode(vop2), true); 2773a552a69cSDamon Ding else 2774a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 2775a552a69cSDamon Ding ESMART_LB_MODE_SEL_MASK, 2776a552a69cSDamon Ding ESMART_LB_MODE_SEL_SHIFT, 2777f6e9a2a3SDamon Ding vop3_get_esmart_lb_mode(vop2), false); 2778d0408543SAndy Yan 27795fa6e665SDamon Ding vop3_init_esmart_scale_engine(vop2); 2780aa670293SDamon Ding 278112ee4de7SDamon Ding if (vop2->version == VOP_VERSION_RK3576) 278212ee4de7SDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK, 278312ee4de7SDamon Ding RK3576_DSP_VS_T_SEL_SHIFT, 0, true); 278412ee4de7SDamon Ding else 2785aa670293SDamon Ding vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK, 2786aa670293SDamon Ding DSP_VS_T_SEL_SHIFT, 0, false); 2787bb7ec356SDamon Ding 2788bb7ec356SDamon Ding /* 2789bb7ec356SDamon Ding * This is a workaround for RK3528/RK3562/RK3576: 2790bb7ec356SDamon Ding * 2791bb7ec356SDamon Ding * The aclk pre auto gating function may disable the aclk 2792bb7ec356SDamon Ding * in some unexpected cases, which detected by hardware 2793bb7ec356SDamon Ding * automatically. 2794bb7ec356SDamon Ding * 2795bb7ec356SDamon Ding * For example, if the above function is enabled, the post 2796bb7ec356SDamon Ding * scale function will be affected, resulting in abnormal 2797bb7ec356SDamon Ding * display. 2798bb7ec356SDamon Ding */ 2799bb7ec356SDamon Ding if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 || 2800bb7ec356SDamon Ding vop2->version == VOP_VERSION_RK3576) 2801bb7ec356SDamon Ding vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK, 2802bb7ec356SDamon Ding ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false); 280363cb669fSSandy Huang } 280463cb669fSSandy Huang 2805ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568) 280663cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 280763cb669fSSandy Huang 2808a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 2809a552a69cSDamon Ding vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq"); 2810a552a69cSDamon Ding 2811f67105fbSSandy Huang /* Default use rkiommu 1.0 for axi0 */ 2812f67105fbSSandy Huang vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 0, true); 2813a552a69cSDamon Ding 2814a552a69cSDamon Ding /* Init frc2.0 config */ 2815a552a69cSDamon Ding vop2_writel(vop2, 0xca0, 0xc8); 2816a552a69cSDamon Ding vop2_writel(vop2, 0xca4, 0x01000100); 2817a552a69cSDamon Ding vop2_writel(vop2, 0xca8, 0x03ff0100); 2818a552a69cSDamon Ding vop2_writel(vop2, 0xda0, 0xc8); 2819a552a69cSDamon Ding vop2_writel(vop2, 0xda4, 0x01000100); 2820a552a69cSDamon Ding vop2_writel(vop2, 0xda8, 0x03ff0100); 2821a552a69cSDamon Ding 2822a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true) 2823a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK, 2824a552a69cSDamon Ding VP_INTR_MERGE_EN_SHIFT, 1, true); 2825a552a69cSDamon Ding 2826a552a69cSDamon Ding /* Set reg done every field for interlace */ 2827a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK, 2828a552a69cSDamon Ding INTERLACE_FRM_REG_DONE_SHIFT, 0, false); 2829a552a69cSDamon Ding } 2830a552a69cSDamon Ding 283163cb669fSSandy Huang vop2->global_init = true; 2832d0408543SAndy Yan } 2833d0408543SAndy Yan 2834344e932aSDamon Ding static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state) 2835344e932aSDamon Ding { 2836344e932aSDamon Ding struct crtc_state *cstate = &state->crtc_state; 2837344e932aSDamon Ding const struct vop2_data *vop2_data = vop2->data; 2838344e932aSDamon Ding const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id]; 2839344e932aSDamon Ding struct resource sharp_regs; 2840344e932aSDamon Ding u32 *sharp_reg_base; 2841344e932aSDamon Ding int ret; 2842344e932aSDamon Ding 2843344e932aSDamon Ding if (!(vp_data->feature & VOP_FEATURE_POST_SHARP)) 2844344e932aSDamon Ding return; 2845344e932aSDamon Ding 2846344e932aSDamon Ding ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs); 2847344e932aSDamon Ding if (ret) { 2848344e932aSDamon Ding printf("failed to get sharp regs\n"); 2849344e932aSDamon Ding return; 2850344e932aSDamon Ding } 2851344e932aSDamon Ding sharp_reg_base = (u32 *)sharp_regs.start; 2852344e932aSDamon Ding 2853344e932aSDamon Ding /* 2854344e932aSDamon Ding * After vop initialization, keep sw_sharp_enable always on. 2855344e932aSDamon Ding * Only enable/disable sharp submodule to avoid black screen. 2856344e932aSDamon Ding */ 2857344e932aSDamon Ding writel(0x1, sharp_reg_base); 2858344e932aSDamon Ding } 2859344e932aSDamon Ding 2860c54cc5d2SAlgea Cao static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state) 2861c54cc5d2SAlgea Cao { 2862c54cc5d2SAlgea Cao struct crtc_state *cstate = &state->crtc_state; 2863c54cc5d2SAlgea Cao const struct vop2_data *vop2_data = vop2->data; 2864c54cc5d2SAlgea Cao const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id]; 2865c54cc5d2SAlgea Cao struct resource acm_regs; 2866c54cc5d2SAlgea Cao u32 *acm_reg_base; 2867c54cc5d2SAlgea Cao u32 vp_offset = (cstate->crtc_id * 0x100); 2868c54cc5d2SAlgea Cao int ret; 2869c54cc5d2SAlgea Cao 2870c54cc5d2SAlgea Cao if (!(vp_data->feature & VOP_FEATURE_POST_ACM)) 2871c54cc5d2SAlgea Cao return; 2872c54cc5d2SAlgea Cao 2873c54cc5d2SAlgea Cao ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs); 2874c54cc5d2SAlgea Cao if (ret) { 2875c54cc5d2SAlgea Cao printf("failed to get acm regs\n"); 2876c54cc5d2SAlgea Cao return; 2877c54cc5d2SAlgea Cao } 2878c54cc5d2SAlgea Cao acm_reg_base = (u32 *)acm_regs.start; 2879c54cc5d2SAlgea Cao 2880c54cc5d2SAlgea Cao /* 2881c54cc5d2SAlgea Cao * Black screen is displayed when acm bypass switched 2882c54cc5d2SAlgea Cao * between enable and disable. Therefore, disable acm 2883c54cc5d2SAlgea Cao * bypass by default after system boot. 2884c54cc5d2SAlgea Cao */ 2885c54cc5d2SAlgea Cao vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2886c54cc5d2SAlgea Cao POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 2887c54cc5d2SAlgea Cao 2888e1946cbdSAlgea Cao writel(0, acm_reg_base + 0); 2889c54cc5d2SAlgea Cao } 2890c54cc5d2SAlgea Cao 28910669ab1fSDamon Ding static int rockchip_vop2_of_get_gamma_lut(struct display_state *state, 28920669ab1fSDamon Ding struct device_node *dsp_lut_node) 28930669ab1fSDamon Ding { 28940669ab1fSDamon Ding struct crtc_state *cstate = &state->crtc_state; 28950669ab1fSDamon Ding struct resource gamma_res; 28960669ab1fSDamon Ding fdt_size_t lut_size; 28970669ab1fSDamon Ding u32 *lut_regs; 28980669ab1fSDamon Ding u32 *lut; 28990669ab1fSDamon Ding u32 r, g, b; 29000669ab1fSDamon Ding int lut_len; 29010669ab1fSDamon Ding int length; 29020669ab1fSDamon Ding int i, j; 29030669ab1fSDamon Ding int ret = 0; 29040669ab1fSDamon Ding 29050669ab1fSDamon Ding of_get_property(dsp_lut_node, "gamma-lut", &length); 29060669ab1fSDamon Ding if (!length) 29070669ab1fSDamon Ding return -EINVAL; 29080669ab1fSDamon Ding 29090669ab1fSDamon Ding ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 29100669ab1fSDamon Ding if (ret) 29110669ab1fSDamon Ding printf("failed to get gamma lut res\n"); 29120669ab1fSDamon Ding lut_regs = (u32 *)gamma_res.start; 29130669ab1fSDamon Ding lut_size = gamma_res.end - gamma_res.start + 1; 29140669ab1fSDamon Ding if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 29150669ab1fSDamon Ding printf("failed to get gamma lut register\n"); 29160669ab1fSDamon Ding return -EINVAL; 29170669ab1fSDamon Ding } 29180669ab1fSDamon Ding lut_len = lut_size / 4; 29190669ab1fSDamon Ding 29200669ab1fSDamon Ding cstate->lut_val = (u32 *)calloc(1, lut_size); 29210669ab1fSDamon Ding if (!cstate->lut_val) 29220669ab1fSDamon Ding return -ENOMEM; 29230669ab1fSDamon Ding 29240669ab1fSDamon Ding length >>= 2; 29250669ab1fSDamon Ding if (length != lut_len) { 29260669ab1fSDamon Ding lut = (u32 *)calloc(1, lut_len); 29270669ab1fSDamon Ding if (!lut) { 29280669ab1fSDamon Ding free(cstate->lut_val); 29290669ab1fSDamon Ding return -ENOMEM; 29300669ab1fSDamon Ding } 29310669ab1fSDamon Ding 29320669ab1fSDamon Ding ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length); 29330669ab1fSDamon Ding if (ret) { 29340669ab1fSDamon Ding printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id); 29350669ab1fSDamon Ding free(cstate->lut_val); 29360669ab1fSDamon Ding free(lut); 29370669ab1fSDamon Ding return -EINVAL; 29380669ab1fSDamon Ding } 29390669ab1fSDamon Ding 29400669ab1fSDamon Ding /* 29410669ab1fSDamon Ding * In order to achieve the same gamma correction effect in different 29420669ab1fSDamon Ding * platforms, the following conversion helps to translate from 8bit 29430669ab1fSDamon Ding * gamma table with 256 parameters to 10bit gamma with 1024 parameters. 29440669ab1fSDamon Ding */ 29450669ab1fSDamon Ding for (i = 0; i < lut_len; i++) { 29460669ab1fSDamon Ding j = i * length / lut_len; 29470669ab1fSDamon Ding r = lut[j] / length / length * lut_len / length; 29480669ab1fSDamon Ding g = lut[j] / length % length * lut_len / length; 29490669ab1fSDamon Ding b = lut[j] % length * lut_len / length; 29500669ab1fSDamon Ding 29510669ab1fSDamon Ding cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b; 29520669ab1fSDamon Ding } 29530669ab1fSDamon Ding free(lut); 29540669ab1fSDamon Ding } else { 29550669ab1fSDamon Ding of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len); 29560669ab1fSDamon Ding } 29570669ab1fSDamon Ding 29580669ab1fSDamon Ding return 0; 29590669ab1fSDamon Ding } 29600669ab1fSDamon Ding 29610669ab1fSDamon Ding static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state) 29620669ab1fSDamon Ding { 29630669ab1fSDamon Ding struct crtc_state *cstate = &state->crtc_state; 29640669ab1fSDamon Ding struct device_node *dsp_lut_node; 29650669ab1fSDamon Ding int phandle; 29660669ab1fSDamon Ding int ret = 0; 29670669ab1fSDamon Ding 29680669ab1fSDamon Ding phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1); 29690669ab1fSDamon Ding if (phandle < 0) 29700669ab1fSDamon Ding return; 29710669ab1fSDamon Ding 29720669ab1fSDamon Ding dsp_lut_node = of_find_node_by_phandle(phandle); 29730669ab1fSDamon Ding if (!dsp_lut_node) 29740669ab1fSDamon Ding return; 29750669ab1fSDamon Ding 29760669ab1fSDamon Ding ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node); 29770669ab1fSDamon Ding if (ret) 29780669ab1fSDamon Ding printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id); 29790669ab1fSDamon Ding } 29800669ab1fSDamon Ding 2981d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state) 2982d0408543SAndy Yan { 29830669ab1fSDamon Ding rockchip_vop2_of_get_dsp_lut(vop2, state); 29840669ab1fSDamon Ding 29851147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state); 29866414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state); 2987344e932aSDamon Ding rockchip_vop2_sharp_init(vop2, state); 2988c54cc5d2SAlgea Cao rockchip_vop2_acm_init(vop2, state); 2989d0408543SAndy Yan 2990d0408543SAndy Yan return 0; 2991d0408543SAndy Yan } 2992d0408543SAndy Yan 2993d0408543SAndy Yan /* 2994d0408543SAndy Yan * VOP2 have multi video ports. 2995d0408543SAndy Yan * video port ------- crtc 2996d0408543SAndy Yan */ 2997d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state) 2998d0408543SAndy Yan { 2999d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3000d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data; 3001734a0ce6SDamon Ding struct regmap *map; 30020686a6a6SZhang Yubing char dclk_name[16]; 30030686a6a6SZhang Yubing int ret; 3004d0408543SAndy Yan 3005d0408543SAndy Yan if (!rockchip_vop2) { 30060d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2)); 3007d0408543SAndy Yan if (!rockchip_vop2) 3008d0408543SAndy Yan return -ENOMEM; 3009d8e7f4a5SSandy Huang memset(rockchip_vop2, 0, sizeof(struct vop2)); 3010d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 3011d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG; 3012d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD 3013d8e7f4a5SSandy Huang rockchip_vop2->regs = (void *)RK3528_VOP_BASE; 3014d8e7f4a5SSandy Huang #else 3015d8e7f4a5SSandy Huang rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 3016734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf"); 3017734a0ce6SDamon Ding rockchip_vop2->grf = regmap_get_range(map, 0); 3018d0408543SAndy Yan if (rockchip_vop2->grf <= 0) 301963cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 3020d8e7f4a5SSandy Huang #endif 3021d0408543SAndy Yan rockchip_vop2->version = vop2_data->version; 3022d0408543SAndy Yan rockchip_vop2->data = vop2_data; 3023ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) { 3024734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf"); 3025734a0ce6SDamon Ding rockchip_vop2->vop_grf = regmap_get_range(map, 0); 3026ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0) 3027a552a69cSDamon Ding printf("%s: Get syscon vop_grf failed (ret=%p)\n", 3028a552a69cSDamon Ding __func__, rockchip_vop2->vop_grf); 3029b890760eSAlgea Cao map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); 3030b890760eSAlgea Cao rockchip_vop2->vo1_grf = regmap_get_range(map, 0); 3031ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0) 3032a552a69cSDamon Ding printf("%s: Get syscon vo1_grf failed (ret=%p)\n", 3033a552a69cSDamon Ding __func__, rockchip_vop2->vo1_grf); 3034734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu"); 3035734a0ce6SDamon Ding rockchip_vop2->sys_pmu = regmap_get_range(map, 0); 3036b890760eSAlgea Cao if (rockchip_vop2->sys_pmu <= 0) 3037a552a69cSDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", 3038a552a69cSDamon Ding __func__, rockchip_vop2->sys_pmu); 3039a552a69cSDamon Ding } else if (rockchip_vop2->version == VOP_VERSION_RK3576) { 3040a552a69cSDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf"); 3041a552a69cSDamon Ding rockchip_vop2->ioc_grf = regmap_get_range(map, 0); 3042a552a69cSDamon Ding if (rockchip_vop2->ioc_grf <= 0) 3043a552a69cSDamon Ding printf("%s: Get syscon ioc_grf failed (ret=%p)\n", 3044a552a69cSDamon Ding __func__, rockchip_vop2->ioc_grf); 3045a552a69cSDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu"); 3046a552a69cSDamon Ding rockchip_vop2->sys_pmu = regmap_get_range(map, 0); 3047a552a69cSDamon Ding if (rockchip_vop2->sys_pmu <= 0) 3048a552a69cSDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", 3049a552a69cSDamon Ding __func__, rockchip_vop2->sys_pmu); 3050ecc31b6eSAndy Yan } 3051d0408543SAndy Yan } 3052d0408543SAndy Yan 30530686a6a6SZhang Yubing snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 3054a2ce7568SDamon Ding if (dev_read_stringlist_search(cstate->dev, "reset-names", dclk_name) > 0) { 30550686a6a6SZhang Yubing ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst); 30560686a6a6SZhang Yubing if (ret < 0) { 30570686a6a6SZhang Yubing printf("%s: failed to get dclk reset: %d\n", __func__, ret); 30580686a6a6SZhang Yubing cstate->dclk_rst.dev = NULL; 30590686a6a6SZhang Yubing } 3060a2ce7568SDamon Ding } 30610686a6a6SZhang Yubing 3062d0408543SAndy Yan cstate->private = rockchip_vop2; 306363cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 306463cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 3065d0408543SAndy Yan 306689912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state); 306789912f2dSSandy Huang 3068d0408543SAndy Yan return 0; 3069d0408543SAndy Yan } 3070d0408543SAndy Yan 3071ecc31b6eSAndy Yan /* 3072ecc31b6eSAndy Yan * calc the dclk on rk3588 3073ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4 3074ecc31b6eSAndy Yan * 3075ecc31b6eSAndy Yan */ 3076ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 3077ecc31b6eSAndy Yan { 3078ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk) 3079ecc31b6eSAndy Yan return child_clk * 4; 3080ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk) 3081ecc31b6eSAndy Yan return child_clk * 2; 3082ecc31b6eSAndy Yan else if (child_clk <= max_dclk) 3083ecc31b6eSAndy Yan return child_clk; 3084ecc31b6eSAndy Yan else 3085ecc31b6eSAndy Yan return 0; 3086ecc31b6eSAndy Yan } 3087ecc31b6eSAndy Yan 3088ecc31b6eSAndy Yan /* 3089ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588 3090ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core 3091ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core 3092ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core 3093ecc31b6eSAndy Yan */ 3094ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state, 3095ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div, 3096ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div) 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; 31020a1fb152SZhang Yubing unsigned long v_pixclk = mode->crtc_clock; 3103ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2; 3104ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk; 3105ecc31b6eSAndy Yan unsigned long dclk_out_rate; 3106ecc31b6eSAndy Yan u64 if_dclk_rate; 3107ecc31b6eSAndy Yan u64 if_pixclk_rate; 3108ecc31b6eSAndy Yan int output_type = conn_state->type; 3109ecc31b6eSAndy Yan int output_mode = conn_state->output_mode; 3110ecc31b6eSAndy Yan int K = 1; 3111ecc31b6eSAndy Yan 31120a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE && 31130a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 31140a1fb152SZhang Yubing printf("Dual channel and YUV420 can't work together\n"); 31150a1fb152SZhang Yubing return -EINVAL; 31160a1fb152SZhang Yubing } 31170a1fb152SZhang Yubing 31180a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 31190a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) 31200a1fb152SZhang Yubing K = 2; 31210a1fb152SZhang Yubing 3122ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 3123ecc31b6eSAndy Yan /* 3124ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 3125ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 3126ecc31b6eSAndy Yan */ 31270a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 31280a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 3129b890760eSAlgea Cao dclk_rate = dclk_rate >> 1; 3130ecc31b6eSAndy Yan K = 2; 3131b890760eSAlgea Cao } 313212ee5af0SDamon Ding if (cstate->dsc_enable) { 313312ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate << 1; 313412ee5af0SDamon Ding if_dclk_rate = cstate->dsc_cds_clk_rate; 3135ecc31b6eSAndy Yan } else { 3136ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K; 3137ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K; 3138ecc31b6eSAndy Yan } 3139ecc31b6eSAndy Yan 3140631ee99aSZhang Yubing if (v_pixclk > VOP2_MAX_DCLK_RATE) 31414b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_core_rate, 31424b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 3143631ee99aSZhang Yubing 3144ecc31b6eSAndy Yan if (!dclk_rate) { 3145ecc31b6eSAndy Yan printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 31464b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate); 3147ecc31b6eSAndy Yan return -EINVAL; 3148ecc31b6eSAndy Yan } 3149ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 3150ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate; 3151b890760eSAlgea Cao *dclk_core_div = dclk_rate / dclk_core_rate; 3152b890760eSAlgea Cao printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n", 3153b890760eSAlgea Cao dclk_rate, *if_pixclk_div, *if_dclk_div); 3154ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 3155ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */ 3156ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K; 3157ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K; 3158ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K; 3159ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3160ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 3161ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div; 3162ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 3163ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2; 31640a1fb152SZhang Yubing dclk_out_rate = dclk_out_rate / K; 3165ecc31b6eSAndy Yan 31664b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 31674b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 3168ecc31b6eSAndy Yan if (!dclk_rate) { 3169ecc31b6eSAndy Yan printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 31704b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate); 3171ecc31b6eSAndy Yan return -EINVAL; 3172ecc31b6eSAndy Yan } 3173ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 3174ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3175ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 3176ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3177ecc31b6eSAndy Yan K = 2; 317812ee5af0SDamon Ding if (cstate->dsc_enable) 317912ee5af0SDamon Ding /* dsc output is 96bit, dsi input is 192 bit */ 318012ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1; 3181ecc31b6eSAndy Yan else 3182ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K; 3183ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 318412ee5af0SDamon Ding dclk_out_rate = dclk_core_rate / K; 3185ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 31864b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 31874b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 31889f076eccSZhang Yubing if (!dclk_rate) { 31899f076eccSZhang Yubing printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n", 31904b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate); 31919f076eccSZhang Yubing return -EINVAL; 31929f076eccSZhang Yubing } 319312ee5af0SDamon Ding 319412ee5af0SDamon Ding if (cstate->dsc_enable) 3195d57af898SDamon Ding dclk_rate /= cstate->dsc_slice_num; 319612ee5af0SDamon Ding 3197ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 3198ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3199ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 320012ee5af0SDamon Ding if (cstate->dsc_enable) 32011ace1b6dSDamon Ding *if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate; 3202ecc31b6eSAndy Yan 3203ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 3204ecc31b6eSAndy Yan dclk_rate = v_pixclk; 3205ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3206ecc31b6eSAndy Yan } 3207ecc31b6eSAndy Yan 3208ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div); 3209ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div); 3210ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div); 3211ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div); 3212ecc31b6eSAndy Yan 3213ecc31b6eSAndy Yan return dclk_rate; 3214ecc31b6eSAndy Yan } 3215ecc31b6eSAndy Yan 321612ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state) 3217ecc31b6eSAndy Yan { 321812ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 3219ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 322012ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 32211ace1b6dSDamon Ding u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */ 3222ecc31b6eSAndy Yan u8 k = 1; 3223ecc31b6eSAndy Yan 3224ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3225ecc31b6eSAndy Yan k = 2; 3226ecc31b6eSAndy Yan 322712ee5af0SDamon Ding cstate->dsc_txp_clk_rate = v_pixclk; 322812ee5af0SDamon Ding do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k)); 3229ecc31b6eSAndy Yan 323012ee5af0SDamon Ding cstate->dsc_pxl_clk_rate = v_pixclk; 323112ee5af0SDamon Ding do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k)); 3232ecc31b6eSAndy Yan 3233ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 3234ecc31b6eSAndy Yan * cds_dat_width = 96; 3235ecc31b6eSAndy Yan * bits_per_pixel = [8-12]; 3236b61227a3SDamon Ding * As cds clk is div from txp clk and only support 1/2/4 div, 3237b61227a3SDamon Ding * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4, 3238b61227a3SDamon Ding * otherwise dsc_cds = crtc_clock / 8; 3239ecc31b6eSAndy Yan */ 3240b61227a3SDamon Ding cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8); 3241ecc31b6eSAndy Yan 3242ecc31b6eSAndy Yan return 0; 3243ecc31b6eSAndy Yan } 3244ecc31b6eSAndy Yan 3245ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 3246ecc31b6eSAndy Yan { 3247ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3248ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3249ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 325012ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 3251ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 325252ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 3253ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 3254ecc31b6eSAndy Yan int output_if = conn_state->output_if; 3255ecc31b6eSAndy Yan int if_pixclk_div = 0; 3256ecc31b6eSAndy Yan int if_dclk_div = 0; 3257ecc31b6eSAndy Yan unsigned long dclk_rate; 32585d2768f7SDamon Ding bool dclk_inv, yc_swap = false; 3259d0408543SAndy Yan u32 val; 3260ecc31b6eSAndy Yan 32615d2768f7SDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3262b890760eSAlgea Cao if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 3263b890760eSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 3264b890760eSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 3265b890760eSAlgea Cao } else { 3266ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3267ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3268b890760eSAlgea Cao } 3269ecc31b6eSAndy Yan 327012ee5af0SDamon Ding if (cstate->dsc_enable) { 327112ee5af0SDamon Ding int k = 1; 327212ee5af0SDamon Ding 3273ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) { 327412ee5af0SDamon Ding printf("Unsupported DSC\n"); 3275ecc31b6eSAndy Yan return 0; 3276ecc31b6eSAndy Yan } 327712ee5af0SDamon Ding 327812ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 327912ee5af0SDamon Ding k = 2; 328012ee5af0SDamon Ding 328112ee5af0SDamon Ding cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 328212ee5af0SDamon Ding cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k; 328312ee5af0SDamon Ding cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num; 328412ee5af0SDamon Ding 328512ee5af0SDamon Ding vop2_calc_dsc_clk(state); 328612ee5af0SDamon Ding printf("Enable DSC%d slice:%dx%d, slice num:%d\n", 328712ee5af0SDamon Ding cstate->dsc_id, dsc_sink_cap->slice_width, 328812ee5af0SDamon Ding dsc_sink_cap->slice_height, cstate->dsc_slice_num); 3289ecc31b6eSAndy Yan } 3290ecc31b6eSAndy Yan 3291b61227a3SDamon Ding dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div); 3292ecc31b6eSAndy Yan 3293ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) { 3294ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3295ecc31b6eSAndy Yan 4, false); 32965d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 32975d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3298ecc31b6eSAndy Yan } 3299ecc31b6eSAndy Yan 3300ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) { 3301ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3302ecc31b6eSAndy Yan 3, false); 33035d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 33045d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 33055d2768f7SDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 33065d2768f7SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT, 33075d2768f7SDamon Ding yc_swap, false); 3308ecc31b6eSAndy Yan } 3309ecc31b6eSAndy Yan 3310ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) { 3311ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3312ecc31b6eSAndy Yan 2, false); 33135d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 33145d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 33155d2768f7SDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 33165d2768f7SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT, 33175d2768f7SDamon Ding yc_swap, false); 3318ecc31b6eSAndy Yan } 3319ecc31b6eSAndy Yan 3320ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) { 3321ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 3322ecc31b6eSAndy Yan val = 0; 3323ecc31b6eSAndy Yan else 3324ecc31b6eSAndy Yan val = 1; 332541874944SGuochun Huang 33263df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 332741874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 332841874944SGuochun Huang RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 332941874944SGuochun Huang 3330ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 3331ecc31b6eSAndy Yan 1, false); 3332ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 3333ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 3334ecc31b6eSAndy Yan if_pixclk_div, false); 333541874944SGuochun Huang 333641874944SGuochun Huang if (conn_state->hold_mode) { 333741874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 33388e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 333941874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 334041874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 334141874944SGuochun Huang } 3342ecc31b6eSAndy Yan } 3343ecc31b6eSAndy Yan 3344ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) { 3345ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 3346ecc31b6eSAndy Yan val = 0; 3347ecc31b6eSAndy Yan else if (cstate->crtc_id == 3) 3348ecc31b6eSAndy Yan val = 1; 3349ecc31b6eSAndy Yan else 3350ecc31b6eSAndy Yan val = 3; /*VP1*/ 33513df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 335241874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 335341874944SGuochun Huang RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 335441874944SGuochun Huang 3355ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 3356ecc31b6eSAndy Yan 1, false); 3357ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 3358ecc31b6eSAndy Yan val, false); 3359ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 3360ecc31b6eSAndy Yan if_pixclk_div, false); 336141874944SGuochun Huang 336241874944SGuochun Huang if (conn_state->hold_mode) { 336341874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 33648e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 336541874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 336641874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 336741874944SGuochun Huang } 3368ecc31b6eSAndy Yan } 3369ecc31b6eSAndy Yan 3370ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 33713df6e59eSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 33723df6e59eSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 3373ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3374ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3375ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 3376ecc31b6eSAndy Yan false); 33770a1fb152SZhang Yubing switch (conn_state->type) { 33780a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DisplayPort: 33790a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 33800a1fb152SZhang Yubing RK3588_DP_DUAL_EN_SHIFT, 1, false); 33810a1fb152SZhang Yubing break; 33820a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_eDP: 33830a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 33840a1fb152SZhang Yubing RK3588_EDP_DUAL_EN_SHIFT, 1, false); 33850a1fb152SZhang Yubing break; 33860a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_HDMIA: 33870a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 33880a1fb152SZhang Yubing RK3588_HDMI_DUAL_EN_SHIFT, 1, false); 33890a1fb152SZhang Yubing break; 33900a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DSI: 33910a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 33920a1fb152SZhang Yubing RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 33930a1fb152SZhang Yubing break; 33940a1fb152SZhang Yubing default: 33950a1fb152SZhang Yubing break; 33960a1fb152SZhang Yubing } 3397ecc31b6eSAndy Yan } 3398ecc31b6eSAndy Yan 3399ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) { 3400ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 3401ecc31b6eSAndy Yan 1, false); 3402ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 3403ecc31b6eSAndy Yan cstate->crtc_id, false); 3404ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 3405ecc31b6eSAndy Yan if_dclk_div, false); 3406ecc31b6eSAndy Yan 3407ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 3408ecc31b6eSAndy Yan if_pixclk_div, false); 3409ecc31b6eSAndy Yan 3410ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3411ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 3412ecc31b6eSAndy Yan } 3413ecc31b6eSAndy Yan 3414ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) { 3415ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 3416ecc31b6eSAndy Yan 1, false); 3417ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 3418ecc31b6eSAndy Yan cstate->crtc_id, false); 3419ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 3420ecc31b6eSAndy Yan if_dclk_div, false); 3421ecc31b6eSAndy Yan 3422ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 3423ecc31b6eSAndy Yan if_pixclk_div, false); 34241848455fSDamon Ding 34251848455fSDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 34261848455fSDamon Ding RK3588_GRF_EDP1_ENABLE_SHIFT, 1); 3427ecc31b6eSAndy Yan } 3428ecc31b6eSAndy Yan 3429ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) { 3430ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 3431ecc31b6eSAndy Yan 1, false); 3432ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 3433ecc31b6eSAndy Yan cstate->crtc_id, false); 3434ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 3435ecc31b6eSAndy Yan if_dclk_div, false); 3436ecc31b6eSAndy Yan 3437ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 3438ecc31b6eSAndy Yan if_pixclk_div, false); 3439b890760eSAlgea Cao 3440b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3441b890760eSAlgea Cao RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1); 3442b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 3443b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 3444b890760eSAlgea Cao HDMI0_SYNC_POL_SHIFT, val); 3445ecc31b6eSAndy Yan } 3446ecc31b6eSAndy Yan 3447ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) { 3448ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 3449ecc31b6eSAndy Yan 1, false); 3450ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 3451ecc31b6eSAndy Yan cstate->crtc_id, false); 3452ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 3453ecc31b6eSAndy Yan if_dclk_div, false); 3454ecc31b6eSAndy Yan 3455ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 3456ecc31b6eSAndy Yan if_pixclk_div, false); 3457b890760eSAlgea Cao 3458b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3459b890760eSAlgea Cao RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1); 3460b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 3461b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 3462b890760eSAlgea Cao HDMI1_SYNC_POL_SHIFT, val); 3463ecc31b6eSAndy Yan } 3464ecc31b6eSAndy Yan 3465ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) { 3466ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 3467ecc31b6eSAndy Yan cstate->crtc_id, false); 3468ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 3469ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false); 3470ecc31b6eSAndy Yan } 3471ecc31b6eSAndy Yan 3472ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) { 3473ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 3474ecc31b6eSAndy Yan cstate->crtc_id, false); 3475ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 3476ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false); 3477ecc31b6eSAndy Yan } 3478ecc31b6eSAndy Yan 3479ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 3480b61227a3SDamon Ding DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false); 3481ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 3482b61227a3SDamon Ding DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false); 3483ecc31b6eSAndy Yan 3484ecc31b6eSAndy Yan return dclk_rate; 3485ecc31b6eSAndy Yan } 3486ecc31b6eSAndy Yan 3487a552a69cSDamon Ding static unsigned long rk3576_vop2_if_cfg(struct display_state *state) 3488a552a69cSDamon Ding { 3489a552a69cSDamon Ding struct crtc_state *cstate = &state->crtc_state; 3490a552a69cSDamon Ding struct connector_state *conn_state = &state->conn_state; 3491a552a69cSDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3492a552a69cSDamon Ding struct vop2 *vop2 = cstate->private; 3493a552a69cSDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 3494a552a69cSDamon Ding u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate; 3495a552a69cSDamon Ding int output_if = conn_state->output_if; 3496a552a69cSDamon Ding bool dclk_inv, yc_swap = false; 3497a552a69cSDamon Ding bool split_mode = !!(conn_state->output_flags & 3498a552a69cSDamon Ding ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE); 3499a552a69cSDamon Ding bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false; 3500a552a69cSDamon Ding bool interface_dclk_sel, interface_pix_clk_sel = false; 3501a552a69cSDamon Ding bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK || 3502a552a69cSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656; 3503cce1f2abSDamon Ding unsigned long dclk_in_rate, dclk_core_rate; 3504a552a69cSDamon Ding u32 val; 3505a552a69cSDamon Ding 3506a552a69cSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3507a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_MIPI0) { 3508a552a69cSDamon Ding /* 3509a552a69cSDamon Ding * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update, 3510a552a69cSDamon Ding * so set VOP hsync/vsync polarity as positive by default. 3511a552a69cSDamon Ding */ 3512a552a69cSDamon Ding val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE); 3513a552a69cSDamon Ding } else { 3514a552a69cSDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3515a552a69cSDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3516a552a69cSDamon Ding } 3517a552a69cSDamon Ding 3518cce1f2abSDamon Ding if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 || 3519cce1f2abSDamon Ding mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode)) 3520a552a69cSDamon Ding cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */ 3521a552a69cSDamon Ding else 3522cce1f2abSDamon Ding cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */ 3523cce1f2abSDamon Ding dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div; 3524cce1f2abSDamon Ding 3525cce1f2abSDamon Ding if (double_pixel) 3526cce1f2abSDamon Ding dclk_core_rate = mode->crtc_clock / 2; 3527cce1f2abSDamon Ding else 3528cce1f2abSDamon Ding dclk_core_rate = mode->crtc_clock / port_pix_rate; 3529cce1f2abSDamon Ding post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */ 3530a552a69cSDamon Ding 3531a552a69cSDamon Ding if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 3532a552a69cSDamon Ding pix_half_rate = true; 3533a552a69cSDamon Ding post_dclk_out_sel = true; 3534a552a69cSDamon Ding } 3535a552a69cSDamon Ding 3536a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_RGB) { 3537a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3538a552a69cSDamon Ding /* 3539a552a69cSDamon Ding * RGB interface_pix_clk_sel will auto config according 3540a552a69cSDamon Ding * to rgb_en/bt1120_en/bt656_en. 3541a552a69cSDamon Ding */ 3542a552a69cSDamon Ding } else if (output_if & VOP_OUTPUT_IF_eDP0) { 3543a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3544a552a69cSDamon Ding interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0; 3545a552a69cSDamon Ding } else { 3546a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3547a552a69cSDamon Ding interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0; 3548a552a69cSDamon Ding } 3549a552a69cSDamon Ding 3550a552a69cSDamon Ding /* dclk_core */ 3551a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK, 3552a552a69cSDamon Ding RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false); 3553a552a69cSDamon Ding /* dclk_out */ 3554a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK, 3555a552a69cSDamon Ding RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false); 3556a552a69cSDamon Ding 3557a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_RGB) { 3558a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */ 3559a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3560a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3561a552a69cSDamon Ding 3562a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3563a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3564a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3565a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3566a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3567a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3568a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3569a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3570a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3571a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3572a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3573a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv); 3574a552a69cSDamon Ding } 3575a552a69cSDamon Ding 3576a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_BT1120) { 3577a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */ 3578a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3579a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3580a552a69cSDamon Ding 3581a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3582a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3583a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3584a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3585a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3586a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3587a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3588a552a69cSDamon Ding RK3576_BT1120_OUT_EN_SHIFT, 1, false); 3589a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3590a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3591a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3592a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3593a552a69cSDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 3594a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3595a552a69cSDamon Ding RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false); 3596a552a69cSDamon Ding } 3597a552a69cSDamon Ding 3598a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_BT656) { 3599a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */ 3600a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3601a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3602a552a69cSDamon Ding 3603a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3604a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3605a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3606a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3607a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3608a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3609a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3610a552a69cSDamon Ding RK3576_BT656_OUT_EN_SHIFT, 1, false); 3611a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3612a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3613a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3614a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3615a552a69cSDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 3616a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3617a552a69cSDamon Ding RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false); 3618a552a69cSDamon Ding } 3619a552a69cSDamon Ding 3620a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_MIPI0) { 3621a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3622a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3623a552a69cSDamon Ding /* 0: div2, 1: div4 */ 3624a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3625a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3626a552a69cSDamon Ding 3627a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3628a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3629a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3630a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3631a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3632a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3633a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3634a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3635a552a69cSDamon Ding /* 3636a552a69cSDamon Ding * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update, 3637a552a69cSDamon Ding * so set VOP hsync/vsync polarity as positive by default. 3638a552a69cSDamon Ding */ 3639a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 3640a552a69cSDamon Ding val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE); 3641a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3642a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3643a552a69cSDamon Ding 3644a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 3645a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3646a552a69cSDamon Ding RK3576_MIPI_CMD_MODE_SHIFT, 1, false); 3647a552a69cSDamon Ding 3648a552a69cSDamon Ding if (conn_state->hold_mode) { 3649a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3650a552a69cSDamon Ding EDPI_TE_EN, !cstate->soft_te, false); 3651a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3652a552a69cSDamon Ding EDPI_WMS_HOLD_EN, 1, false); 3653a552a69cSDamon Ding } 3654a552a69cSDamon Ding } 3655a552a69cSDamon Ding 3656a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 3657a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3658a552a69cSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 3659a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3660a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3661a552a69cSDamon Ding MIPI_DUAL_SWAP_EN_SHIFT, 1, false); 3662a552a69cSDamon Ding switch (conn_state->type) { 3663a552a69cSDamon Ding case DRM_MODE_CONNECTOR_DisplayPort: 3664a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 3665a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3666a552a69cSDamon Ding break; 3667a552a69cSDamon Ding case DRM_MODE_CONNECTOR_eDP: 3668a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3669a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3670a552a69cSDamon Ding break; 3671a552a69cSDamon Ding case DRM_MODE_CONNECTOR_HDMIA: 3672a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3673a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3674a552a69cSDamon Ding break; 3675a552a69cSDamon Ding case DRM_MODE_CONNECTOR_DSI: 3676a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3677a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3678a552a69cSDamon Ding break; 3679a552a69cSDamon Ding default: 3680a552a69cSDamon Ding break; 3681a552a69cSDamon Ding } 3682a552a69cSDamon Ding } 3683a552a69cSDamon Ding 3684a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_eDP0) { 3685a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3686a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3687a552a69cSDamon Ding /* 0: dclk, 1: port0_dclk */ 3688a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3689a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3690a552a69cSDamon Ding 3691a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3692a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3693a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3694a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3695a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3696a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3697a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3698a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3699a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3700a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3701a552a69cSDamon Ding } 3702a552a69cSDamon Ding 3703a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_HDMI0) { 3704a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3705a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3706a552a69cSDamon Ding /* 0: div2, 1: div4 */ 3707a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3708a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3709a552a69cSDamon Ding 3710a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3711a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3712a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3713a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3714a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3715a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3716a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3717a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3718a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3719a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3720a552a69cSDamon Ding } 3721a552a69cSDamon Ding 3722a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP0) { 3723a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3724a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3725a552a69cSDamon Ding /* 0: no div, 1: div2 */ 3726a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3727a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3728a552a69cSDamon Ding 3729a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 3730a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3731a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 3732a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3733a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3734a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3735a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3736a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3737a552a69cSDamon Ding } 3738a552a69cSDamon Ding 3739a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP1) { 3740a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3741a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3742a552a69cSDamon Ding /* 0: no div, 1: div2 */ 3743a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3744a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3745a552a69cSDamon Ding 3746a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 3747a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3748a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 3749a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3750a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3751a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3752a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3753a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3754a552a69cSDamon Ding } 3755a552a69cSDamon Ding 3756a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP2) { 3757a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3758a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3759a552a69cSDamon Ding /* 0: no div, 1: div2 */ 3760a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3761a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3762a552a69cSDamon Ding 3763a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 3764a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3765a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 3766a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3767a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3768a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3769a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3770a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3771a552a69cSDamon Ding } 3772a552a69cSDamon Ding 3773a552a69cSDamon Ding return mode->crtc_clock; 3774a552a69cSDamon Ding } 3775a552a69cSDamon Ding 3776a2a16809SChaoyi Chen static void rk3568_vop2_setup_dual_channel_if(struct display_state *state) 3777a2a16809SChaoyi Chen { 3778a2a16809SChaoyi Chen struct crtc_state *cstate = &state->crtc_state; 3779a2a16809SChaoyi Chen struct connector_state *conn_state = &state->conn_state; 3780a2a16809SChaoyi Chen struct vop2 *vop2 = cstate->private; 3781a2a16809SChaoyi Chen u32 vp_offset = (cstate->crtc_id * 0x100); 3782a2a16809SChaoyi Chen 3783a2a16809SChaoyi Chen if (conn_state->output_flags & 3784a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) { 3785a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3786a2a16809SChaoyi Chen LVDS_DUAL_EN_SHIFT, 1, false); 3787a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3788a2a16809SChaoyi Chen LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false); 3789a2a16809SChaoyi Chen if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3790a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3791a2a16809SChaoyi Chen LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 3792a2a16809SChaoyi Chen 3793a2a16809SChaoyi Chen return; 3794a2a16809SChaoyi Chen } 3795a2a16809SChaoyi Chen 3796a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3797a2a16809SChaoyi Chen MIPI_DUAL_EN_SHIFT, 1, false); 3798a2a16809SChaoyi Chen if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) { 3799a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3800a2a16809SChaoyi Chen MIPI_DUAL_SWAP_EN_SHIFT, 1, false); 3801a2a16809SChaoyi Chen } 3802a2a16809SChaoyi Chen 3803a2a16809SChaoyi Chen if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 3804a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3805a2a16809SChaoyi Chen LVDS_DUAL_EN_SHIFT, 1, false); 3806a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3807a2a16809SChaoyi Chen LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false); 3808a2a16809SChaoyi Chen } 3809a2a16809SChaoyi Chen } 3810a2a16809SChaoyi Chen 3811ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 3812ecc31b6eSAndy Yan { 3813ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3814ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3815ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3816ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 3817d0408543SAndy Yan bool dclk_inv; 3818ecc31b6eSAndy Yan u32 val; 38198895aec1SSandy Huang 382013f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 382110ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 382210ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3823d0408543SAndy Yan 3824d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3825d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3826d0408543SAndy Yan 1, false); 3827d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3828d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 382915f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 383015f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3831ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 3832c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 3833d0408543SAndy Yan } 3834d0408543SAndy Yan 3835d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 383652ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 383752ee18acSSandy Huang 1, false); 3838d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 3839d0408543SAndy Yan BT1120_EN_SHIFT, 1, false); 3840d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3841d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 3842ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 384352ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 3844d0408543SAndy Yan } 3845d0408543SAndy Yan 3846d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 3847d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 3848d0408543SAndy Yan 1, false); 3849d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3850d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 3851ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 385252ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 3853d0408543SAndy Yan } 3854d0408543SAndy Yan 3855d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3856d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3857d0408543SAndy Yan 1, false); 3858d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3859d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false); 386015f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 386115f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 386211f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 386315f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3864d0408543SAndy Yan } 3865d0408543SAndy Yan 3866d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 3867d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 3868d0408543SAndy Yan 1, false); 3869d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3870d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false); 387115f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 387215f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 387311f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 387415f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3875d0408543SAndy Yan } 3876d0408543SAndy Yan 3877d0408543SAndy Yan 3878d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3879d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3880d0408543SAndy Yan 1, false); 3881d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3882d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3883d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3884c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3885de022775SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK, 3886de022775SGuochun Huang IF_CTRL_MIPI_PIN_POL_SHIFT, val, false); 3887d0408543SAndy Yan } 3888d0408543SAndy Yan 3889d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 3890d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 3891d0408543SAndy Yan 1, false); 3892d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3893d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false); 3894d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3895c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3896de022775SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK, 3897de022775SGuochun Huang IF_CTRL_MIPI_PIN_POL_SHIFT, val, false); 3898d0408543SAndy Yan } 3899d0408543SAndy Yan 3900d0408543SAndy Yan if (conn_state->output_flags & 3901a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 3902a2a16809SChaoyi Chen conn_state->output_flags & 3903a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) 3904a2a16809SChaoyi Chen rk3568_vop2_setup_dual_channel_if(state); 3905d0408543SAndy Yan 3906d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 3907d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 3908d0408543SAndy Yan 1, false); 3909d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3910d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false); 3911c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3912c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 39137bcdc6eeSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK, 39147bcdc6eeSDamon Ding IF_CTRL_EDP_PIN_POL_SHIFT, val, false); 3915d0408543SAndy Yan } 3916d0408543SAndy Yan 3917d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 3918d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 3919d0408543SAndy Yan 1, false); 3920d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3921d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false); 392210ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 392310ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 392410ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, 392510ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK, 392610ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 3927d0408543SAndy Yan } 392810ee9f5bSAlgea Cao 3929823146b6SDamon Ding return mode->crtc_clock; 3930ecc31b6eSAndy Yan } 3931ecc31b6eSAndy Yan 3932452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state) 3933452afb13SDamon Ding { 3934452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 3935452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 3936452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3937452afb13SDamon Ding struct vop2 *vop2 = cstate->private; 3938452afb13SDamon Ding bool dclk_inv; 3939606f72bdSDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 3940452afb13SDamon Ding u32 val; 3941452afb13SDamon Ding 394213f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3943452afb13SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3944452afb13SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3945452afb13SDamon Ding 3946452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3947452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3948452afb13SDamon Ding 1, false); 3949452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3950452afb13SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 3951452afb13SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK, 3952452afb13SDamon Ding GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 3953452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 395415f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3955452afb13SDamon Ding } 3956452afb13SDamon Ding 3957452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3958452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3959452afb13SDamon Ding 1, false); 3960452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3961452afb13SDamon Ding LVDS0_MUX_SHIFT, cstate->crtc_id, false); 3962452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 396315f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3964452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 396515f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3966452afb13SDamon Ding } 3967452afb13SDamon Ding 3968452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3969452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3970452afb13SDamon Ding 1, false); 3971452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3972452afb13SDamon Ding MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3973452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3974452afb13SDamon Ding RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false); 3975452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 3976452afb13SDamon Ding RK3562_MIPI_PIN_POL_SHIFT, val, false); 3977606f72bdSDamon Ding 3978606f72bdSDamon Ding if (conn_state->hold_mode) { 3979606f72bdSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3980606f72bdSDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 3981606f72bdSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3982606f72bdSDamon Ding EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 3983606f72bdSDamon Ding } 3984452afb13SDamon Ding } 3985452afb13SDamon Ding 3986452afb13SDamon Ding return mode->crtc_clock; 3987452afb13SDamon Ding } 3988452afb13SDamon Ding 3989a552a69cSDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state) 3990a552a69cSDamon Ding { 3991a552a69cSDamon Ding struct crtc_state *cstate = &state->crtc_state; 3992a552a69cSDamon Ding struct connector_state *conn_state = &state->conn_state; 3993a552a69cSDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3994a552a69cSDamon Ding struct vop2 *vop2 = cstate->private; 3995a552a69cSDamon Ding u32 val; 3996a552a69cSDamon Ding 3997a552a69cSDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3998a552a69cSDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3999a552a69cSDamon Ding 4000a552a69cSDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 4001a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 4002a552a69cSDamon Ding 1, false); 4003a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4004a552a69cSDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 4005a552a69cSDamon Ding } 4006a552a69cSDamon Ding 4007a552a69cSDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 4008a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 4009a552a69cSDamon Ding 1, false); 4010a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4011a552a69cSDamon Ding HDMI0_MUX_SHIFT, cstate->crtc_id, false); 4012a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4013a552a69cSDamon Ding IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 4014a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, 4015a552a69cSDamon Ding IF_CRTL_HDMI_PIN_POL_MASK, 4016a552a69cSDamon Ding IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 4017a552a69cSDamon Ding } 4018a552a69cSDamon Ding 4019a552a69cSDamon Ding return mode->crtc_clock; 4020a552a69cSDamon Ding } 4021a552a69cSDamon Ding 402265747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state) 402365747de7SDamon Ding { 402465747de7SDamon Ding struct crtc_state *cstate = &state->crtc_state; 402565747de7SDamon Ding struct connector_state *conn_state = &state->conn_state; 402665747de7SDamon Ding struct vop2 *vop2 = cstate->private; 402765747de7SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 402865747de7SDamon Ding u32 output_type = conn_state->type; 402965747de7SDamon Ding u32 data_swap = 0; 403065747de7SDamon Ding 4031c8820b76SDamon Ding if (is_uv_swap(state) || is_rb_swap(state)) 403265747de7SDamon Ding data_swap = DSP_RB_SWAP; 403365747de7SDamon Ding 4034a552a69cSDamon Ding if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) { 4035a552a69cSDamon Ding if ((output_type == DRM_MODE_CONNECTOR_HDMIA || 4036e6e4c154SDamon Ding output_type == DRM_MODE_CONNECTOR_DisplayPort) && 403765747de7SDamon Ding (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 403865747de7SDamon Ding conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 403965747de7SDamon Ding data_swap |= DSP_RG_SWAP; 4040a552a69cSDamon Ding } 404165747de7SDamon Ding 404265747de7SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 404365747de7SDamon Ding DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 404465747de7SDamon Ding } 404565747de7SDamon Ding 4046b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent) 4047b890760eSAlgea Cao { 4048b890760eSAlgea Cao int ret = 0; 4049b890760eSAlgea Cao 4050b890760eSAlgea Cao if (parent->dev) 4051b890760eSAlgea Cao ret = clk_set_parent(clk, parent); 4052b890760eSAlgea Cao if (ret < 0) 4053b890760eSAlgea Cao debug("failed to set %s as parent for %s\n", 4054b890760eSAlgea Cao parent->dev->name, clk->dev->name); 4055b890760eSAlgea Cao } 4056b890760eSAlgea Cao 4057b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate) 4058b890760eSAlgea Cao { 4059b890760eSAlgea Cao int ret = 0; 4060b890760eSAlgea Cao 4061b890760eSAlgea Cao if (clk->dev) 4062b890760eSAlgea Cao ret = clk_set_rate(clk, rate); 4063b890760eSAlgea Cao if (ret < 0) 4064b890760eSAlgea Cao debug("failed to set %s rate %lu \n", clk->dev->name, rate); 4065b890760eSAlgea Cao 4066b890760eSAlgea Cao return ret; 4067b890760eSAlgea Cao } 4068b890760eSAlgea Cao 406912ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state, 407012ee5af0SDamon Ding int *dsc_txp_clk_div, int *dsc_pxl_clk_div, 407112ee5af0SDamon Ding int *dsc_cds_clk_div, u64 dclk_rate) 407212ee5af0SDamon Ding { 407312ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 407412ee5af0SDamon Ding 407512ee5af0SDamon Ding *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate; 407612ee5af0SDamon Ding *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate; 407712ee5af0SDamon Ding *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate; 407812ee5af0SDamon Ding 407912ee5af0SDamon Ding *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div); 408012ee5af0SDamon Ding *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div); 408112ee5af0SDamon Ding *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div); 408212ee5af0SDamon Ding } 408312ee5af0SDamon Ding 408412ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id) 408512ee5af0SDamon Ding { 408612ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 408712ee5af0SDamon Ding struct drm_dsc_picture_parameter_set *pps = &cstate->pps; 408812ee5af0SDamon Ding struct drm_dsc_picture_parameter_set config_pps; 408912ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 409012ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 409112ee5af0SDamon Ding u32 *pps_val = (u32 *)&config_pps; 409212ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 409312ee5af0SDamon Ding int i = 0; 409412ee5af0SDamon Ding 409512ee5af0SDamon Ding memcpy(&config_pps, pps, sizeof(config_pps)); 409612ee5af0SDamon Ding 409712ee5af0SDamon Ding if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) { 409812ee5af0SDamon Ding config_pps.pps_3 &= 0xf0; 409912ee5af0SDamon Ding config_pps.pps_3 |= dsc_data->max_linebuf_depth; 410012ee5af0SDamon Ding printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n", 410112ee5af0SDamon Ding dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf); 410212ee5af0SDamon Ding } 410312ee5af0SDamon Ding 410412ee5af0SDamon Ding for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 410512ee5af0SDamon Ding config_pps.rc_range_parameters[i] = 410612ee5af0SDamon Ding (pps->rc_range_parameters[i] >> 3 & 0x1f) | 410712ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) | 410812ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) | 410912ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10); 411012ee5af0SDamon Ding } 411112ee5af0SDamon Ding 411212ee5af0SDamon Ding for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++) 411312ee5af0SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++); 411412ee5af0SDamon Ding } 411512ee5af0SDamon Ding 411612ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate) 411712ee5af0SDamon Ding { 411812ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 411912ee5af0SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 412012ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 412112ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 412212ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 412312ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 412412ee5af0SDamon Ding bool mipi_ds_mode = false; 412512ee5af0SDamon Ding u8 dsc_interface_mode = 0; 412612ee5af0SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 412712ee5af0SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 412812ee5af0SDamon Ding u16 htotal = mode->crtc_htotal; 412912ee5af0SDamon Ding u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 413012ee5af0SDamon Ding u16 vdisplay = mode->crtc_vdisplay; 413112ee5af0SDamon Ding u16 vtotal = mode->crtc_vtotal; 413212ee5af0SDamon Ding u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 413312ee5af0SDamon Ding u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 413412ee5af0SDamon Ding u16 vact_end = vact_st + vdisplay; 413512ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 413612ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 413712ee5af0SDamon Ding int dsc_txp_clk_div = 0; 413812ee5af0SDamon Ding int dsc_pxl_clk_div = 0; 413912ee5af0SDamon Ding int dsc_cds_clk_div = 0; 4140baf2c414SDamon Ding int val = 0; 414112ee5af0SDamon Ding 414212ee5af0SDamon Ding if (!vop2->data->nr_dscs) { 414312ee5af0SDamon Ding printf("Unsupported DSC\n"); 414412ee5af0SDamon Ding return; 414512ee5af0SDamon Ding } 414612ee5af0SDamon Ding 414712ee5af0SDamon Ding if (cstate->dsc_slice_num > dsc_data->max_slice_num) 414812ee5af0SDamon Ding printf("DSC%d supported max slice is: %d, current is: %d\n", 414912ee5af0SDamon Ding dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num); 415012ee5af0SDamon Ding 415112ee5af0SDamon Ding if (dsc_data->pd_id) { 415212ee5af0SDamon Ding if (vop2_power_domain_on(vop2, dsc_data->pd_id)) 415312ee5af0SDamon Ding printf("open dsc%d pd fail\n", dsc_id); 415412ee5af0SDamon Ding } 415512ee5af0SDamon Ding 415612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK, 415712ee5af0SDamon Ding SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false); 415812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK, 415912ee5af0SDamon Ding DSC_PORT_SEL_SHIFT, cstate->crtc_id, false); 416012ee5af0SDamon Ding if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 416112ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_HDMI; 416212ee5af0SDamon Ding } else { 416312ee5af0SDamon Ding mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE); 416412ee5af0SDamon Ding if (mipi_ds_mode) 416512ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE; 416612ee5af0SDamon Ding else 416712ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE; 416812ee5af0SDamon Ding } 416912ee5af0SDamon Ding 417012ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 417112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 417212ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 0, false); 417312ee5af0SDamon Ding else 417412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 417512ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 1, false); 417612ee5af0SDamon Ding 417712ee5af0SDamon Ding vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate); 417812ee5af0SDamon Ding 417912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK, 418012ee5af0SDamon Ding DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false); 418112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK, 418212ee5af0SDamon Ding DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false); 418312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK, 418412ee5af0SDamon Ding DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false); 418512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK, 418612ee5af0SDamon Ding DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false); 418712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 418812ee5af0SDamon Ding DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false); 418912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK, 419012ee5af0SDamon Ding DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false); 419112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 419212ee5af0SDamon Ding DSC_HALT_EN_SHIFT, mipi_ds_mode, false); 419312ee5af0SDamon Ding 419412ee5af0SDamon Ding if (!mipi_ds_mode) { 419512ee5af0SDamon Ding u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end; 419612ee5af0SDamon Ding u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16; 419712ee5af0SDamon Ding u64 dsc_cds_rate = cstate->dsc_cds_clk_rate; 419812ee5af0SDamon Ding u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */ 419912ee5af0SDamon Ding u32 dly_num, dsc_cds_rate_mhz, val = 0; 4200b61227a3SDamon Ding int k = 1; 4201b61227a3SDamon Ding 4202b61227a3SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 4203b61227a3SDamon Ding k = 2; 420412ee5af0SDamon Ding 420512ee5af0SDamon Ding if (target_bpp >> 4 < dsc_data->min_bits_per_pixel) 420612ee5af0SDamon Ding printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel); 420712ee5af0SDamon Ding 420812ee5af0SDamon Ding /* 420912ee5af0SDamon Ding * dly_num = delay_line_num * T(one-line) / T (dsc_cds) 421012ee5af0SDamon Ding * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz 421112ee5af0SDamon Ding * T (dsc_cds) = 1 / dsc_cds_rate_mhz 42121ace1b6dSDamon Ding * 42131ace1b6dSDamon Ding * HDMI: 421412ee5af0SDamon Ding * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay 421512ee5af0SDamon Ding * delay_line_num = 4 - BPP / 8 421612ee5af0SDamon Ding * = (64 - target_bpp / 8) / 16 421712ee5af0SDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 42181ace1b6dSDamon Ding * 42191ace1b6dSDamon Ding * MIPI DSI[4320 and 9216 is buffer size for DSC]: 42201ace1b6dSDamon Ding * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size; 42211ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 42221ace1b6dSDamon Ding * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size; 42231ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 42241ace1b6dSDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num 422512ee5af0SDamon Ding */ 422612ee5af0SDamon Ding do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ 422712ee5af0SDamon Ding dsc_cds_rate_mhz = dsc_cds_rate; 42281ace1b6dSDamon Ding dsc_hsync = hsync_len / 2; 42291ace1b6dSDamon Ding if (dsc_interface_mode == VOP_DSC_IF_HDMI) { 423012ee5af0SDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 42311ace1b6dSDamon Ding } else { 42321ace1b6dSDamon Ding int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2; 42331ace1b6dSDamon Ding int delay_line_num = dsc_buf_size / cstate->dsc_slice_num / 42341ace1b6dSDamon Ding be16_to_cpu(cstate->pps.chunk_size); 42351ace1b6dSDamon Ding 42361ace1b6dSDamon Ding delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 42371ace1b6dSDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num; 42381ace1b6dSDamon Ding 42391ace1b6dSDamon Ding /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */ 42401ace1b6dSDamon Ding if (dsc_hsync < 8) 42411ace1b6dSDamon Ding dsc_hsync = 8; 42421ace1b6dSDamon Ding } 424312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK, 424412ee5af0SDamon Ding DSC_INIT_DLY_MODE_SHIFT, 0, false); 424512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK, 424612ee5af0SDamon Ding DSC_INIT_DLY_NUM_SHIFT, dly_num, false); 424712ee5af0SDamon Ding 4248b61227a3SDamon Ding /* 4249b61227a3SDamon Ding * htotal / dclk_core = dsc_htotal /cds_clk 4250b61227a3SDamon Ding * 4251b61227a3SDamon Ding * dclk_core = DCLK / (1 << dclk_core->div_val) 4252b61227a3SDamon Ding * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val) 4253b61227a3SDamon Ding * txp_clk = DCLK / (1 << dsc_txp_clk->div_val) 4254b61227a3SDamon Ding * 4255b61227a3SDamon Ding * dsc_htotal = htotal * (1 << dclk_core->div_val) / 4256b61227a3SDamon Ding * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val)) 4257b61227a3SDamon Ding */ 4258b61227a3SDamon Ding dsc_htotal = htotal * (1 << cstate->dclk_core_div) / 4259b61227a3SDamon Ding ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div)); 426012ee5af0SDamon Ding val = dsc_htotal << 16 | dsc_hsync; 426112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK, 426212ee5af0SDamon Ding DSC_HTOTAL_PW_SHIFT, val, false); 426312ee5af0SDamon Ding 426412ee5af0SDamon Ding dsc_hact_st = hact_st / 2; 4265b61227a3SDamon Ding dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st; 426612ee5af0SDamon Ding val = dsc_hact_end << 16 | dsc_hact_st; 426712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK, 426812ee5af0SDamon Ding DSC_HACT_ST_END_SHIFT, val, false); 426912ee5af0SDamon Ding 427012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK, 427112ee5af0SDamon Ding DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false); 427212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK, 427312ee5af0SDamon Ding DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false); 427412ee5af0SDamon Ding } 427512ee5af0SDamon Ding 427612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK, 427712ee5af0SDamon Ding RST_DEASSERT_SHIFT, 1, false); 427812ee5af0SDamon Ding udelay(10); 427912ee5af0SDamon Ding 4280baf2c414SDamon Ding val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) | 4281baf2c414SDamon Ding ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT); 4282baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 4283baf2c414SDamon Ding 428412ee5af0SDamon Ding vop2_load_pps(state, vop2, dsc_id); 428512ee5af0SDamon Ding 4286baf2c414SDamon Ding val |= (1 << DSC_PPS_UPD_SHIFT); 4287baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 428812ee5af0SDamon Ding 428912ee5af0SDamon Ding printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n", 429012ee5af0SDamon Ding dsc_id, 429112ee5af0SDamon Ding cstate->dsc_txp_clk_rate, dsc_txp_clk_div, 429212ee5af0SDamon Ding cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div, 429312ee5af0SDamon Ding cstate->dsc_cds_clk_rate, dsc_cds_clk_div); 429412ee5af0SDamon Ding } 429512ee5af0SDamon Ding 42965f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev) 42975f1357a2SZhang Yubing { 42985f1357a2SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 42995f1357a2SZhang Yubing struct vop2 *vop2 = cstate->private; 43005f1357a2SZhang Yubing struct udevice *vp_dev, *dev; 43015f1357a2SZhang Yubing struct ofnode_phandle_args args; 43025f1357a2SZhang Yubing char vp_name[10]; 43035f1357a2SZhang Yubing int ret; 43045f1357a2SZhang Yubing 4305a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576) 43065f1357a2SZhang Yubing return false; 43075f1357a2SZhang Yubing 43085f1357a2SZhang Yubing sprintf(vp_name, "port@%d", cstate->crtc_id); 43095f1357a2SZhang Yubing if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) { 43105e85f4a7SZhang Yubing debug("warn: can't get vp device\n"); 43115f1357a2SZhang Yubing return false; 43125f1357a2SZhang Yubing } 43135f1357a2SZhang Yubing 43145f1357a2SZhang Yubing ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0, 43155f1357a2SZhang Yubing 0, &args); 43165f1357a2SZhang Yubing if (ret) { 43175e85f4a7SZhang Yubing debug("assigned-clock-parents's node not define\n"); 43185f1357a2SZhang Yubing return false; 43195f1357a2SZhang Yubing } 43205f1357a2SZhang Yubing 43215f1357a2SZhang Yubing if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) { 43225e85f4a7SZhang Yubing debug("warn: can't get clk device\n"); 43235f1357a2SZhang Yubing return false; 43245f1357a2SZhang Yubing } 43255f1357a2SZhang Yubing 43265f1357a2SZhang Yubing if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) { 43275f1357a2SZhang Yubing printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name); 43285f1357a2SZhang Yubing if (clk_dev) 43295f1357a2SZhang Yubing *clk_dev = dev; 43305f1357a2SZhang Yubing return true; 43315f1357a2SZhang Yubing } 43325f1357a2SZhang Yubing 43335f1357a2SZhang Yubing return false; 43345f1357a2SZhang Yubing } 43355f1357a2SZhang Yubing 43360675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state) 43370675a2a4SDamon Ding { 43380675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 43390675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 43400675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 43410675a2a4SDamon Ding 43420675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 43430675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false); 43440675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 43450675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false); 43460675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 43470675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false); 43480675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 43490675a2a4SDamon Ding MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false); 43500675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 43510675a2a4SDamon Ding MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false); 43520675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 43530675a2a4SDamon Ding MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false); 43540675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 43550675a2a4SDamon Ding MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false); 43560675a2a4SDamon Ding } 43570675a2a4SDamon Ding 43580675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state) 43590675a2a4SDamon Ding { 43600675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 43610675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 43620675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 43630675a2a4SDamon Ding 43640675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 43650675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false); 43660675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 43670675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false); 43680675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 43690675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, 53, false); 43700675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 43710675a2a4SDamon Ding MCU_CS_PST_SHIFT, 6, false); 43720675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 43730675a2a4SDamon Ding MCU_CS_PEND_SHIFT, 48, false); 43740675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 43750675a2a4SDamon Ding MCU_RW_PST_SHIFT, 12, false); 43760675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 43770675a2a4SDamon Ding MCU_RW_PEND_SHIFT, 30, false); 43780675a2a4SDamon Ding } 43790675a2a4SDamon Ding 43800675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value) 43810675a2a4SDamon Ding { 43820675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 43830675a2a4SDamon Ding struct connector_state *conn_state = &state->conn_state; 43840675a2a4SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 43850675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 43860675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 43870675a2a4SDamon Ding 43880675a2a4SDamon Ding /* 438958cf1fa3SDamon Ding * 1.set mcu bypass mode timing. 439058cf1fa3SDamon Ding * 2.set dclk rate to 150M. 43910675a2a4SDamon Ding */ 43920675a2a4SDamon Ding if (type == MCU_SETBYPASS && value) { 43930675a2a4SDamon Ding vop3_mcu_bypass_mode_setup(state); 43940675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, 150000000); 43950675a2a4SDamon Ding } 43960675a2a4SDamon Ding 43970675a2a4SDamon Ding switch (type) { 43980675a2a4SDamon Ding case MCU_WRCMD: 43990675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44000675a2a4SDamon Ding MCU_RS_SHIFT, 0, false); 44010675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 44020675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 44030675a2a4SDamon Ding value, false); 44040675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44050675a2a4SDamon Ding MCU_RS_SHIFT, 1, false); 44060675a2a4SDamon Ding break; 44070675a2a4SDamon Ding case MCU_WRDATA: 44080675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44090675a2a4SDamon Ding MCU_RS_SHIFT, 1, false); 44100675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 44110675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 44120675a2a4SDamon Ding value, false); 44130675a2a4SDamon Ding break; 44140675a2a4SDamon Ding case MCU_SETBYPASS: 44150675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44160675a2a4SDamon Ding MCU_BYPASS_SHIFT, value ? 1 : 0, false); 44170675a2a4SDamon Ding break; 44180675a2a4SDamon Ding default: 44190675a2a4SDamon Ding break; 44200675a2a4SDamon Ding } 44210675a2a4SDamon Ding 44220675a2a4SDamon Ding /* 442358cf1fa3SDamon Ding * 1.restore mcu data mode timing. 442458cf1fa3SDamon Ding * 2.restore dclk rate to crtc_clock. 44250675a2a4SDamon Ding */ 44260675a2a4SDamon Ding if (type == MCU_SETBYPASS && !value) { 44270675a2a4SDamon Ding vop3_mcu_mode_setup(state); 44280675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000); 44290675a2a4SDamon Ding } 44300675a2a4SDamon Ding 44310675a2a4SDamon Ding return 0; 44320675a2a4SDamon Ding } 44330675a2a4SDamon Ding 443434d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id) 443534d37ef0SDamon Ding { 4436a552a69cSDamon Ding const struct vop2_data *vop2_data = vop2->data; 4437a552a69cSDamon Ding const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id]; 443834d37ef0SDamon Ding u32 vp_offset = crtc_id * 0x100; 443934d37ef0SDamon Ding bool pre_dither_down_en = false; 444034d37ef0SDamon Ding 444134d37ef0SDamon Ding switch (bus_format) { 444234d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB565_1X16: 444340608a7cSDamon Ding case MEDIA_BUS_FMT_RGB565_2X8_LE: 4444e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4445e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, true, false); 4446e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4447e2bdb3b3SDamon Ding DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false); 444834d37ef0SDamon Ding pre_dither_down_en = true; 444934d37ef0SDamon Ding break; 445034d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X18: 445134d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 445234d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 445340608a7cSDamon Ding case MEDIA_BUS_FMT_RGB666_3X6: 4454e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4455e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, true, false); 4456e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4457e2bdb3b3SDamon Ding DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false); 445834d37ef0SDamon Ding pre_dither_down_en = true; 445934d37ef0SDamon Ding break; 446034d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 446134d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV8_1X24: 446234d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 4463e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4464e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false); 446534d37ef0SDamon Ding pre_dither_down_en = true; 446634d37ef0SDamon Ding break; 446734d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV10_1X20: 446834d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV10_1X30: 446934d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 447034d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB101010_1X30: 4471e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4472e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false); 447334d37ef0SDamon Ding pre_dither_down_en = false; 447434d37ef0SDamon Ding break; 447534d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_3X8: 447634d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: 447734d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X24: 447834d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 447934d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 448034d37ef0SDamon Ding default: 4481e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4482e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false); 448334d37ef0SDamon Ding pre_dither_down_en = true; 448434d37ef0SDamon Ding break; 448534d37ef0SDamon Ding } 448634d37ef0SDamon Ding 4487e2bdb3b3SDamon Ding if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0) 448834d37ef0SDamon Ding pre_dither_down_en = false; 448934d37ef0SDamon Ding 4490a552a69cSDamon Ding if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) { 4491481ef52dSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 4492481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000); 4493481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100); 4494481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100); 4495481ef52dSDamon Ding } 4496481ef52dSDamon Ding 4497a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4498a552a69cSDamon Ding PRE_DITHER_DOWN_EN_SHIFT, 0, false); 4499e2bdb3b3SDamon Ding /* enable frc2.0 do 10->8 */ 4500a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4501a552a69cSDamon Ding DITHER_DOWN_EN_SHIFT, 1, false); 4502e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK, 4503e2bdb3b3SDamon Ding DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false); 4504a552a69cSDamon Ding } else { 450534d37ef0SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 450634d37ef0SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 4507e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK, 4508e2bdb3b3SDamon Ding DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false); 450934d37ef0SDamon Ding } 4510a552a69cSDamon Ding } 451134d37ef0SDamon Ding 4512ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state) 4513ecc31b6eSAndy Yan { 4514ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4515c2b1fe35SDamon Ding struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id]; 4516ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 4517ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 4518ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4519ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 4520ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 4521ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal; 4522ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 4523ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay; 4524ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay; 4525ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal; 4526ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 4527ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 4528ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay; 4529ecc31b6eSAndy Yan bool yuv_overlay = false; 4530ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 453166724b9cSDamon Ding u32 line_flag_offset = (cstate->crtc_id * 4); 453266724b9cSDamon Ding u32 val, act_end; 453358cf1fa3SDamon Ding u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4534edfef528SDamon Ding u8 dclk_div_factor = 0; 4535a552a69cSDamon Ding u8 vp_dclk_div = 1; 4536ecc31b6eSAndy Yan char output_type_name[30] = {0}; 4537d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 4538ecc31b6eSAndy Yan char dclk_name[9]; 4539d8e7f4a5SSandy Huang #endif 4540b890760eSAlgea Cao struct clk hdmi0_phy_pll; 4541b890760eSAlgea Cao struct clk hdmi1_phy_pll; 45425f1357a2SZhang Yubing struct clk hdmi_phy_pll; 45433e05a7b8SZhang Yubing struct udevice *disp_dev; 45445fa6e665SDamon Ding unsigned long dclk_rate = 0; 4545ecc31b6eSAndy Yan int ret; 4546ecc31b6eSAndy Yan 4547ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 454871ac76f7SDamon Ding mode->crtc_hdisplay, mode->vdisplay, 4549ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 45504d64cedbSDamon Ding mode->vrefresh, 45512264c88bSDamon Ding rockchip_get_output_if_name(conn_state->output_if, output_type_name), 4552ecc31b6eSAndy Yan cstate->crtc_id); 4553ecc31b6eSAndy Yan 4554ee01dbb2SDamon Ding if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { 4555ee01dbb2SDamon Ding cstate->splice_mode = true; 4556ee01dbb2SDamon Ding cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id; 4557ee01dbb2SDamon Ding if (!cstate->splice_crtc_id) { 4558ee01dbb2SDamon Ding printf("%s: Splice mode is unsupported by vp%d\n", 4559ee01dbb2SDamon Ding __func__, cstate->crtc_id); 4560ee01dbb2SDamon Ding return -EINVAL; 4561ee01dbb2SDamon Ding } 4562b70b2d79SDamon Ding 4563b70b2d79SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK, 4564b70b2d79SDamon Ding PORT_MERGE_EN_SHIFT, 1, false); 4565ee01dbb2SDamon Ding } 4566ee01dbb2SDamon Ding 4567cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 4568cd6c85a9SDamon Ding RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false); 4569cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 4570cd6c85a9SDamon Ding RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false); 4571cd6c85a9SDamon Ding 457244b1b62cSDamon Ding if (vop2->data->vp_data[cstate->crtc_id].urgency) { 457344b1b62cSDamon Ding u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl; 457444b1b62cSDamon Ding u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh; 457544b1b62cSDamon Ding 457644b1b62cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK, 457744b1b62cSDamon Ding AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false); 457844b1b62cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK, 457944b1b62cSDamon Ding AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false); 458044b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK, 458144b1b62cSDamon Ding POST_URGENCY_EN_SHIFT, 1, false); 458244b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK, 458344b1b62cSDamon Ding POST_URGENCY_THL_SHIFT, urgen_thl, false); 458444b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK, 458544b1b62cSDamon Ding POST_URGENCY_THH_SHIFT, urgen_thh, false); 458644b1b62cSDamon Ding } 458744b1b62cSDamon Ding 4588ecc31b6eSAndy Yan vop2_initial(vop2, state); 4589ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 4590ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state); 4591a552a69cSDamon Ding else if (vop2->version == VOP_VERSION_RK3576) 4592a552a69cSDamon Ding dclk_rate = rk3576_vop2_if_cfg(state); 45935fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3568) 4594ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state); 4595452afb13SDamon Ding else if (vop2->version == VOP_VERSION_RK3562) 4596452afb13SDamon Ding dclk_rate = rk3562_vop2_if_cfg(state); 4597a552a69cSDamon Ding else if (vop2->version == VOP_VERSION_RK3528) 4598a552a69cSDamon Ding dclk_rate = rk3528_vop2_if_cfg(state); 4599ecc31b6eSAndy Yan 46005d2768f7SDamon Ding if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 46015d2768f7SDamon Ding !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) || 46025d2768f7SDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 46037bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 46047bdd0eb6SSandy Huang 4605bf7c1abfSDamon Ding if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 4606bf7c1abfSDamon Ding if (vop2->version == VOP_VERSION_RK3588 && 4607bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_DisplayPort) 4608bf7c1abfSDamon Ding conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420; 4609bf7c1abfSDamon Ding } else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) { 4610bf7c1abfSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && 4611bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_eDP) 4612bf7c1abfSDamon Ding conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422; 4613bf7c1abfSDamon Ding else if (vop2->version == VOP_VERSION_RK3588 && 4614bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_eDP) 4615bf7c1abfSDamon Ding conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422; 4616bf7c1abfSDamon Ding else if (vop2->version == VOP_VERSION_RK3576 && 4617bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_HDMIA) 4618bf7c1abfSDamon Ding conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422; 4619bf7c1abfSDamon Ding else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort) 4620bf7c1abfSDamon Ding conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422; 4621bf7c1abfSDamon Ding } 4622bf7c1abfSDamon Ding 462365747de7SDamon Ding vop2_post_color_swap(state); 462410ee9f5bSAlgea Cao 4625d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 4626d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false); 4627d0408543SAndy Yan 462834d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id); 462934d37ef0SDamon Ding if (cstate->splice_mode) 463034d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id); 4631d0408543SAndy Yan 4632d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 4633d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 4634d0408543SAndy Yan yuv_overlay, false); 4635d0408543SAndy Yan 4636d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay; 4637d0408543SAndy Yan 4638d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 4639d0408543SAndy Yan (htotal << 16) | hsync_len); 4640d0408543SAndy Yan val = hact_st << 16; 4641d0408543SAndy Yan val |= hact_end; 4642d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 4643d0408543SAndy Yan val = vact_st << 16; 4644d0408543SAndy Yan val |= vact_end; 4645d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 4646d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 4647d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 4648d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay; 4649d0408543SAndy Yan 4650d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 4651d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 4652d0408543SAndy Yan val); 4653d0408543SAndy Yan 4654d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len); 4655d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 4656d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4657d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false); 4658d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 46597a20be36SSandy Huang DSP_FILED_POL, 1, false); 46607a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4661d0408543SAndy Yan P2I_EN_SHIFT, 1, false); 4662d0408543SAndy Yan vtotal += vtotal + 1; 466366724b9cSDamon Ding act_end = vact_end_f1; 4664d0408543SAndy Yan } else { 4665d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4666d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false); 4667d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4668d0408543SAndy Yan P2I_EN_SHIFT, 0, false); 466966724b9cSDamon Ding act_end = vact_end; 4670d0408543SAndy Yan } 4671d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 4672d0408543SAndy Yan (vtotal << 16) | vsync_len); 467367be2ffcSDamon Ding 4674a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3528 || 4675a552a69cSDamon Ding vop2->version == VOP_VERSION_RK3562 || 4676a552a69cSDamon Ding vop2->version == VOP_VERSION_RK3568) { 467767be2ffcSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || 467867be2ffcSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 4679d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 468067be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 1, false); 468167be2ffcSDamon Ding else 468267be2ffcSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 468367be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 0, false); 468410ee9f5bSAlgea Cao 468510ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 468663cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 468763cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 468810ee9f5bSAlgea Cao else 468963cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 469063cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 4691a552a69cSDamon Ding } 469210ee9f5bSAlgea Cao 4693ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 4694ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false); 4695ee01dbb2SDamon Ding 469610ee9f5bSAlgea Cao if (yuv_overlay) 469710ee9f5bSAlgea Cao val = 0x20010200; 469810ee9f5bSAlgea Cao else 469910ee9f5bSAlgea Cao val = 0; 470010ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 4701b70b2d79SDamon Ding if (cstate->splice_mode) { 4702ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 4703ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id, 4704ee01dbb2SDamon Ding yuv_overlay, false); 4705ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val); 4706ee01dbb2SDamon Ding } 470710ee9f5bSAlgea Cao 470810ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 470910ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 4710d0408543SAndy Yan 4711c2b1fe35SDamon Ding if (vp->xmirror_en) 4712c2b1fe35SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4713c2b1fe35SDamon Ding DSP_X_MIR_EN_SHIFT, 1, false); 4714c2b1fe35SDamon Ding 4715ac500a1fSSandy Huang vop2_tv_config_update(state, vop2); 4716d0408543SAndy Yan vop2_post_config(state, vop2); 47176027c871SZhang Yubing if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) 47186027c871SZhang Yubing vop3_post_config(state, vop2); 4719d0408543SAndy Yan 472012ee5af0SDamon Ding if (cstate->dsc_enable) { 472112ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 47221ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL); 47231ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL); 472412ee5af0SDamon Ding } else { 47251ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL); 472612ee5af0SDamon Ding } 472712ee5af0SDamon Ding } 472812ee5af0SDamon Ding 4729d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 4730ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 47310675a2a4SDamon Ding ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk); 4732b890760eSAlgea Cao if (ret) { 4733b890760eSAlgea Cao printf("%s: Failed to get dclk ret=%d\n", __func__, ret); 4734b890760eSAlgea Cao return ret; 4735b890760eSAlgea Cao } 4736d8e7f4a5SSandy Huang #endif 4737b890760eSAlgea Cao 47383e05a7b8SZhang Yubing ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev); 47393e05a7b8SZhang Yubing if (!ret) { 47403e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll); 47413e05a7b8SZhang Yubing if (ret) 47425e85f4a7SZhang Yubing debug("%s: hdmi0_phy_pll may not define\n", __func__); 47433e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll); 47443e05a7b8SZhang Yubing if (ret) 47455e85f4a7SZhang Yubing debug("%s: hdmi1_phy_pll may not define\n", __func__); 47463e05a7b8SZhang Yubing } else { 4747b890760eSAlgea Cao hdmi0_phy_pll.dev = NULL; 4748545a0218SAlgea Cao hdmi1_phy_pll.dev = NULL; 47495e85f4a7SZhang Yubing debug("%s: Faile to find display-subsystem node\n", __func__); 4750b890760eSAlgea Cao } 4751b890760eSAlgea Cao 4752ebbd144cSAlgea Cao if (vop2->version == VOP_VERSION_RK3528) { 4753ebbd144cSAlgea Cao struct ofnode_phandle_args args; 4754ebbd144cSAlgea Cao 4755ebbd144cSAlgea Cao ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents", 4756ebbd144cSAlgea Cao "#clock-cells", 0, 0, &args); 4757ebbd144cSAlgea Cao if (!ret) { 4758ebbd144cSAlgea Cao ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev); 4759ebbd144cSAlgea Cao if (ret) { 4760ebbd144cSAlgea Cao debug("warn: can't get clk device\n"); 4761ebbd144cSAlgea Cao return ret; 4762ebbd144cSAlgea Cao } 4763ebbd144cSAlgea Cao } else { 4764ebbd144cSAlgea Cao debug("assigned-clock-parents's node not define\n"); 4765ebbd144cSAlgea Cao } 4766ebbd144cSAlgea Cao } 4767ebbd144cSAlgea Cao 4768cce1f2abSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 4769cce1f2abSDamon Ding vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div; 4770cce1f2abSDamon Ding 47710a1fb152SZhang Yubing if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) { 4772b890760eSAlgea Cao if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) 47730675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll); 4774b890760eSAlgea Cao else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1) 47750675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll); 4776b890760eSAlgea Cao 4777b890760eSAlgea Cao /* 4778b890760eSAlgea Cao * uboot clk driver won't set dclk parent's rate when use 4779b890760eSAlgea Cao * hdmi phypll as dclk source. 4780b890760eSAlgea Cao * So set dclk rate is meaningless. Set hdmi phypll rate 4781b890760eSAlgea Cao * directly. 4782b890760eSAlgea Cao */ 47835f1357a2SZhang Yubing if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) { 4784cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000); 47855f1357a2SZhang Yubing } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) { 4786cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000); 47875f1357a2SZhang Yubing } else { 47887efea85dSDamon Ding if (is_extend_pll(state, &hdmi_phy_pll.dev)) { 4789cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi_phy_pll, 4790cce1f2abSDamon Ding dclk_rate / vp_dclk_div * 1000); 47917efea85dSDamon Ding } else { 4792d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 4793a552a69cSDamon Ding ret = vop2_clk_set_rate(&cstate->dclk, 4794a552a69cSDamon Ding dclk_rate / vp_dclk_div * 1000); 4795d8e7f4a5SSandy Huang #else 4796d8e7f4a5SSandy Huang if (vop2->version == VOP_VERSION_RK3528) { 4797d8e7f4a5SSandy Huang void *cru_base = (void *)RK3528_CRU_BASE; 4798d8e7f4a5SSandy Huang 4799d8e7f4a5SSandy Huang /* dclk src switch to hdmiphy pll */ 4800d8e7f4a5SSandy Huang writel((BIT(0) << 16) | BIT(0), cru_base + 0x450); 4801d8e7f4a5SSandy Huang rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000); 4802d8e7f4a5SSandy Huang ret = dclk_rate * 1000; 4803d8e7f4a5SSandy Huang } 4804d8e7f4a5SSandy Huang #endif 48055f1357a2SZhang Yubing } 48067efea85dSDamon Ding } 4807631ee99aSZhang Yubing } else { 48085f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev)) 4809cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000); 48105f1357a2SZhang Yubing else 4811cce1f2abSDamon Ding ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000); 4812edfef528SDamon Ding } 481363638f32SDamon Ding 481463638f32SDamon Ding if (IS_ERR_VALUE(ret)) { 481563638f32SDamon Ding printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 481663638f32SDamon Ding __func__, cstate->crtc_id, dclk_rate, ret); 481763638f32SDamon Ding return ret; 481863638f32SDamon Ding } else { 48194d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total) { 48204d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) / 1000; 48214d64cedbSDamon Ding } else { 48229655ad2fSDamon Ding dclk_div_factor = mode->crtc_clock / dclk_rate; 48234d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000; 48244d64cedbSDamon Ding } 4825edfef528SDamon Ding printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); 4826631ee99aSZhang Yubing } 4827ecc31b6eSAndy Yan 482866724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 4829e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false); 483066724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 4831e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false); 483266724b9cSDamon Ding 483358cf1fa3SDamon Ding if (cstate->mcu_timing.mcu_pix_total) { 483458cf1fa3SDamon Ding vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 483558cf1fa3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 483658cf1fa3SDamon Ding STANDBY_EN_SHIFT, 0, false); 48370675a2a4SDamon Ding vop3_mcu_mode_setup(state); 483858cf1fa3SDamon Ding } 48390675a2a4SDamon Ding 4840d0408543SAndy Yan return 0; 4841d0408543SAndy Yan } 4842d0408543SAndy Yan 4843ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 48443e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w, 48453e39a5a1SSandy Huang uint32_t dst_h) 48463e39a5a1SSandy Huang { 48473e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 48483e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode; 48495fa6e665SDamon Ding uint8_t xgt2 = 0, xgt4 = 0; 48505fa6e665SDamon Ding uint8_t ygt2 = 0, ygt4 = 0; 48513e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0; 4852ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 48535fa6e665SDamon Ding bool xgt_en = false; 48545fa6e665SDamon Ding bool xavg_en = false; 48553e39a5a1SSandy Huang 48565fa6e665SDamon Ding if (is_vop3(vop2)) { 4857a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) { 4858a552a69cSDamon Ding if (src_w >= (8 * dst_w)) { 4859a552a69cSDamon Ding xgt4 = 1; 4860a552a69cSDamon Ding src_w >>= 2; 4861a552a69cSDamon Ding } else if (src_w >= (4 * dst_w)) { 4862a552a69cSDamon Ding xgt2 = 1; 4863a552a69cSDamon Ding src_w >>= 1; 4864a552a69cSDamon Ding } 4865a552a69cSDamon Ding } else { 48665fa6e665SDamon Ding if (src_w >= (4 * dst_w)) { 48675fa6e665SDamon Ding xgt4 = 1; 48685fa6e665SDamon Ding src_w >>= 2; 48695fa6e665SDamon Ding } else if (src_w >= (2 * dst_w)) { 48705fa6e665SDamon Ding xgt2 = 1; 48715fa6e665SDamon Ding src_w >>= 1; 48725fa6e665SDamon Ding } 48735fa6e665SDamon Ding } 4874a552a69cSDamon Ding } 48753e39a5a1SSandy Huang 4876183eb252SDamon Ding /** 4877183eb252SDamon Ding * The rk3528 is processed as 2 pixel/cycle, 4878183eb252SDamon Ding * so ygt2/ygt4 needs to be triggered in advance to improve performance 4879183eb252SDamon Ding * when src_w is bigger than 1920. 4880183eb252SDamon Ding * dst_h / src_h is at [1, 0.65) ygt2=0; ygt4=0; 4881183eb252SDamon Ding * dst_h / src_h is at [0.65, 0.35) ygt2=1; ygt4=0; 4882183eb252SDamon Ding * dst_h / src_h is at [0.35, 0) ygt2=0; ygt4=1; 4883183eb252SDamon Ding */ 4884183eb252SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) { 4885183eb252SDamon Ding if (src_h >= (100 * dst_h / 35)) { 4886183eb252SDamon Ding ygt4 = 1; 4887183eb252SDamon Ding src_h >>= 2; 4888183eb252SDamon Ding } else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) { 4889183eb252SDamon Ding ygt2 = 1; 4890183eb252SDamon Ding src_h >>= 1; 4891183eb252SDamon Ding } 4892183eb252SDamon Ding } else { 4893a552a69cSDamon Ding if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { 4894a552a69cSDamon Ding if (src_h >= (8 * dst_h)) { 4895a552a69cSDamon Ding ygt4 = 1; 4896a552a69cSDamon Ding src_h >>= 2; 4897a552a69cSDamon Ding } else if (src_h >= (4 * dst_h)) { 4898a552a69cSDamon Ding ygt2 = 1; 4899a552a69cSDamon Ding src_h >>= 1; 4900a552a69cSDamon Ding } 4901a552a69cSDamon Ding } else { 49025fa6e665SDamon Ding if (src_h >= (4 * dst_h)) { 49035fa6e665SDamon Ding ygt4 = 1; 49043e39a5a1SSandy Huang src_h >>= 2; 49055fa6e665SDamon Ding } else if (src_h >= (2 * dst_h)) { 49065fa6e665SDamon Ding ygt2 = 1; 49073e39a5a1SSandy Huang src_h >>= 1; 49085fa6e665SDamon Ding } 4909183eb252SDamon Ding } 4910a552a69cSDamon Ding } 49113e39a5a1SSandy Huang 49123e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 49133e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 49143e39a5a1SSandy Huang 49153e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP) 49165fa6e665SDamon Ding hscl_filter_mode = win->hsu_filter_mode; 49173e39a5a1SSandy Huang else 49185fa6e665SDamon Ding hscl_filter_mode = win->hsd_filter_mode; 49193e39a5a1SSandy Huang 49203e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP) 49215fa6e665SDamon Ding vscl_filter_mode = win->vsu_filter_mode; 49223e39a5a1SSandy Huang else 49235fa6e665SDamon Ding vscl_filter_mode = win->vsd_filter_mode; 49243e39a5a1SSandy Huang 49253e39a5a1SSandy Huang /* 49263e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel 49273e39a5a1SSandy Huang * at scale down mode 49283e39a5a1SSandy Huang */ 49295fa6e665SDamon Ding if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) { 49303e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 49313e39a5a1SSandy Huang dst_w += 1; 49323e39a5a1SSandy Huang } 49333e39a5a1SSandy Huang 49345fa6e665SDamon Ding if (is_vop3(vop2)) { 49355fa6e665SDamon Ding xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true); 49365fa6e665SDamon Ding yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false); 49375fa6e665SDamon Ding 49385fa6e665SDamon Ding if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG) 49395fa6e665SDamon Ding xavg_en = xgt2 || xgt4; 49405fa6e665SDamon Ding else 49415fa6e665SDamon Ding xgt_en = xgt2 || xgt4; 4942a552a69cSDamon Ding 4943a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 4944a552a69cSDamon Ding bool zme_dering_en = false; 4945a552a69cSDamon Ding 4946a552a69cSDamon Ding if ((yrgb_hor_scl_mode == SCALE_UP && 4947a552a69cSDamon Ding hscl_filter_mode == VOP2_SCALE_UP_ZME) || 4948a552a69cSDamon Ding (yrgb_ver_scl_mode == SCALE_UP && 4949a552a69cSDamon Ding vscl_filter_mode == VOP2_SCALE_UP_ZME)) 4950a552a69cSDamon Ding zme_dering_en = true; 4951a552a69cSDamon Ding 4952a552a69cSDamon Ding /* Recommended configuration from the algorithm */ 4953a552a69cSDamon Ding vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset, 4954a552a69cSDamon Ding 0x04100d10); 4955a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset, 4956a552a69cSDamon Ding EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false); 4957a552a69cSDamon Ding } 49585fa6e665SDamon Ding } else { 49593e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 49603e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 49615fa6e665SDamon Ding } 4962ecc31b6eSAndy Yan 4963ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) { 4964ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 4965ecc31b6eSAndy Yan yfac << 16 | xfac); 4966ecc31b6eSAndy Yan 49675fa6e665SDamon Ding if (is_vop3(vop2)) { 4968ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49695fa6e665SDamon Ding EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false); 4970ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49715fa6e665SDamon Ding EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false); 49725fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49735fa6e665SDamon Ding XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 4974ecc31b6eSAndy Yan 4975ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49765fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT, 49775fa6e665SDamon Ding yrgb_hor_scl_mode, false); 4978ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49795fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT, 49805fa6e665SDamon Ding yrgb_ver_scl_mode, false); 49815fa6e665SDamon Ding } else { 49825fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49835fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT, 49845fa6e665SDamon Ding yrgb_hor_scl_mode, false); 49855fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49865fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT, 49875fa6e665SDamon Ding yrgb_ver_scl_mode, false); 49885fa6e665SDamon Ding } 4989ecc31b6eSAndy Yan 49905fa6e665SDamon Ding if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) { 49915fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49925fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false); 49935fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49945fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false); 49955fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49965fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false); 49975fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 49985fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false); 49995fa6e665SDamon Ding } else { 50005fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50015fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false); 50025fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50035fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false); 50045fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50055fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false); 50065fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50075fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false); 50085fa6e665SDamon Ding } 5009ecc31b6eSAndy Yan } else { 50103e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 50113e39a5a1SSandy Huang yfac << 16 | xfac); 50123e39a5a1SSandy Huang 50135fa6e665SDamon Ding if (is_vop3(vop2)) { 501434a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50155fa6e665SDamon Ding EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false); 501634a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50175fa6e665SDamon Ding EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false); 50185fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50195fa6e665SDamon Ding XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 50205fa6e665SDamon Ding } 50215fa6e665SDamon Ding 50225fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50235fa6e665SDamon Ding YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false); 50245fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50255fa6e665SDamon Ding YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false); 50263e39a5a1SSandy Huang 50273e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50283e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 50293e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50303e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 50313e39a5a1SSandy Huang 50323e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50333e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 50343e39a5a1SSandy Huang hscl_filter_mode, false); 50353e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50363e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 50373e39a5a1SSandy Huang vscl_filter_mode, false); 50383e39a5a1SSandy Huang } 5039ecc31b6eSAndy Yan } 50403e39a5a1SSandy Huang 5041a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win) 5042a33b790fSDamon Ding { 5043a33b790fSDamon Ding u32 win_offset = win->reg_offset; 5044a33b790fSDamon Ding 5045a33b790fSDamon Ding if (win->type == CLUSTER_LAYER) { 5046a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK, 5047a33b790fSDamon Ding CLUSTER_AXI_ID_SHIFT, win->axi_id, false); 5048a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK, 5049a33b790fSDamon Ding CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 5050a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK, 5051a33b790fSDamon Ding CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 5052a33b790fSDamon Ding } else { 5053a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK, 5054a33b790fSDamon Ding ESMART_AXI_ID_SHIFT, win->axi_id, false); 5055a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK, 5056a33b790fSDamon Ding ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 5057a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK, 5058a33b790fSDamon Ding ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 5059a33b790fSDamon Ding } 5060a33b790fSDamon Ding } 5061a33b790fSDamon Ding 5062840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format) 5063840bf541SDamon Ding { 5064840bf541SDamon Ding switch (format) { 5065840bf541SDamon Ding case ROCKCHIP_FMT_RGB565: 5066840bf541SDamon Ding return true; 5067840bf541SDamon Ding default: 5068840bf541SDamon Ding return false; 5069840bf541SDamon Ding } 5070840bf541SDamon Ding } 5071840bf541SDamon Ding 50721c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win) 50731c9572c7SDamon Ding { 50741c9572c7SDamon Ding return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR); 50751c9572c7SDamon Ding } 50761c9572c7SDamon Ding 50771c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 5078d0408543SAndy Yan { 5079d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 5080d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 5081d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 5082d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 50839c7848c3SDamon Ding const struct vop2_data *vop2_data = vop2->data; 50849c7848c3SDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops; 5085ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 5086ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 5087ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 5088ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 5089ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 5090ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 5091d0408543SAndy Yan int xvir = cstate->xvir; 5092d0408543SAndy Yan int y_mirror = 0; 509310ee9f5bSAlgea Cao int csc_mode; 5094ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 5095ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 5096ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 5097ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 5098ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 5099ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5100840bf541SDamon Ding bool dither_up; 5101d0408543SAndy Yan 5102ee01dbb2SDamon Ding if (win->splice_mode_right) { 5103ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 5104ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 5105ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 5106ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 5107ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 5108ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 5109ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 5110ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 5111ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5112ee01dbb2SDamon Ding } 5113ee01dbb2SDamon Ding 5114ecc31b6eSAndy Yan act_info = (src_h - 1) << 16; 5115ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff; 5116ecc31b6eSAndy Yan 5117ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16; 5118ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 5119ecc31b6eSAndy Yan 5120ecc31b6eSAndy Yan dsp_stx = crtc_x; 5121ecc31b6eSAndy Yan dsp_sty = crtc_y; 5122ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 5123ecc31b6eSAndy Yan 5124ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 5125ecc31b6eSAndy Yan y_mirror = 1; 5126ecc31b6eSAndy Yan else 5127ecc31b6eSAndy Yan y_mirror = 0; 5128ecc31b6eSAndy Yan 5129ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 5130ecc31b6eSAndy Yan 5131a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3568) 5132a33b790fSDamon Ding vop2_axi_config(vop2, win); 5133a33b790fSDamon Ding 5134ecc31b6eSAndy Yan if (y_mirror) 5135ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n"); 5136ecc31b6eSAndy Yan 51379c7848c3SDamon Ding if (is_vop3(vop2)) { 5138a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset, 51394751aa64SDamon Ding CLUSTER_PORT_SEL_MASK, CLUSTER_PORT_SEL_SHIFT, 5140a552a69cSDamon Ding cstate->crtc_id, false); 51419c7848c3SDamon Ding vop2_ops->setup_win_dly(state, cstate->crtc_id); 51429c7848c3SDamon Ding } 5143a552a69cSDamon Ding 5144e84ccd9bSDamon Ding /* 5145e84ccd9bSDamon Ding * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode. 5146e84ccd9bSDamon Ding */ 5147e84ccd9bSDamon Ding if (vop2->version >= VOP_VERSION_RK3588) 5148a59754e1SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset, 5149a59754e1SDamon Ding EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false); 5150a59754e1SDamon Ding 5151ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 5152ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 5153ecc31b6eSAndy Yan false); 5154ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 5155ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, 5156ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 5157ecc31b6eSAndy Yan 5158ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 5159ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 5160ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 5161ecc31b6eSAndy Yan 5162ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 5163ecc31b6eSAndy Yan 5164df0a5c43SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range, 5165df0a5c43SDamon Ding CSC_10BIT_DEPTH); 5166ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 5167ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT, 5168ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false); 5169ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 5170ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 5171840bf541SDamon Ding 5172840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format); 5173840bf541SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 5174840bf541SDamon Ding CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false); 5175840bf541SDamon Ding 5176ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 5177ecc31b6eSAndy Yan 5178ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 51791c9572c7SDamon Ding 51801c9572c7SDamon Ding return 0; 5181d0408543SAndy Yan } 5182d0408543SAndy Yan 51831c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 5184ecc31b6eSAndy Yan { 5185ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 5186ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 5187ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 5188ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 51899c7848c3SDamon Ding const struct vop2_data *vop2_data = vop2->data; 51909c7848c3SDamon Ding const struct vop2_ops *vop2_ops = vop2_data->ops; 5191ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 5192ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 5193ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 5194ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 5195ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 5196ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 5197ecc31b6eSAndy Yan int xvir = cstate->xvir; 5198ecc31b6eSAndy Yan int y_mirror = 0; 5199ecc31b6eSAndy Yan int csc_mode; 5200ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 5201ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 5202ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 5203ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 5204ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 5205ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 52061c9572c7SDamon Ding u32 val; 5207840bf541SDamon Ding bool dither_up; 5208ecc31b6eSAndy Yan 52091c9572c7SDamon Ding if (vop2_is_mirror_win(win)) { 52101c9572c7SDamon Ding struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id); 52111c9572c7SDamon Ding 52121c9572c7SDamon Ding if (!source_win) { 52131c9572c7SDamon Ding printf("invalid source win id %d\n", win->source_win_id); 52141c9572c7SDamon Ding return -ENODEV; 52151c9572c7SDamon Ding } 52161c9572c7SDamon Ding 52171c9572c7SDamon Ding val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset); 52181c9572c7SDamon Ding if (!(val & BIT(WIN_EN_SHIFT))) { 52191c9572c7SDamon Ding printf("WARN: the source win should be enabled before mirror win\n"); 52201c9572c7SDamon Ding return -EAGAIN; 52211c9572c7SDamon Ding } 52221c9572c7SDamon Ding } 52231c9572c7SDamon Ding 5224ee01dbb2SDamon Ding if (win->splice_mode_right) { 5225ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 5226ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 5227ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 5228ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 5229ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 5230ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 5231ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 5232ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 5233ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5234ee01dbb2SDamon Ding } 5235ee01dbb2SDamon Ding 523674bd8269SSandy Huang /* 523774bd8269SSandy Huang * This is workaround solution for IC design: 523874bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1. 523974bd8269SSandy Huang */ 524074bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) { 524174bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 524274bd8269SSandy Huang src_w -= 1; 524374bd8269SSandy Huang } 524474bd8269SSandy Huang 5245d0408543SAndy Yan act_info = (src_h - 1) << 16; 5246d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff; 5247d0408543SAndy Yan 5248d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16; 5249d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 5250d0408543SAndy Yan 5251d0408543SAndy Yan dsp_stx = crtc_x; 5252d0408543SAndy Yan dsp_sty = crtc_y; 5253d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 5254d0408543SAndy Yan 5255d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 5256d0408543SAndy Yan y_mirror = 1; 5257d0408543SAndy Yan else 5258d0408543SAndy Yan y_mirror = 0; 5259d0408543SAndy Yan 5260a552a69cSDamon Ding if (is_vop3(vop2)) { 5261a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, 5262a552a69cSDamon Ding ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT, 5263a552a69cSDamon Ding win->scale_engine_num, false); 5264a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset, 5265a552a69cSDamon Ding ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT, 5266a552a69cSDamon Ding cstate->crtc_id, false); 52679c7848c3SDamon Ding vop2_ops->setup_win_dly(state, cstate->crtc_id); 5268a552a69cSDamon Ding 5269a552a69cSDamon Ding /* Merge esmart1/3 from vp1 post to vp0 */ 5270a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 && 5271a552a69cSDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || 5272a552a69cSDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART3)) 5273a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset, 5274a552a69cSDamon Ding ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT, 5275a552a69cSDamon Ding 1, false); 5276a552a69cSDamon Ding } 52775fa6e665SDamon Ding 5278ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 52793e39a5a1SSandy Huang 5280a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3568) 5281a33b790fSDamon Ding vop2_axi_config(vop2, win); 5282a33b790fSDamon Ding 5283d0408543SAndy Yan if (y_mirror) 5284d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4; 5285d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 5286d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false); 5287d0408543SAndy Yan 5288d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5289d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 5290d0408543SAndy Yan false); 5291a552a69cSDamon Ding 5292a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 5293a552a69cSDamon Ding vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00); 5294a552a69cSDamon Ding 5295d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 5296d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 5297ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 5298d0408543SAndy Yan 5299d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 5300d0408543SAndy Yan act_info); 5301d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 5302d0408543SAndy Yan dsp_info); 5303d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 5304d0408543SAndy Yan 5305d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 5306d0408543SAndy Yan WIN_EN_SHIFT, 1, false); 5307d0408543SAndy Yan 5308df0a5c43SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range, 5309df0a5c43SDamon Ding CSC_10BIT_DEPTH); 531010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 531110ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT, 531210ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false); 531310ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 531410ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false); 531510ee9f5bSAlgea Cao 5316840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format); 5317840bf541SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 5318840bf541SDamon Ding REGION0_DITHER_UP_EN_SHIFT, dither_up, false); 5319840bf541SDamon Ding 5320d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 53211c9572c7SDamon Ding 53221c9572c7SDamon Ding return 0; 5323ecc31b6eSAndy Yan } 5324ecc31b6eSAndy Yan 5325ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state) 5326ee01dbb2SDamon Ding { 5327ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 5328ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 5329ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 5330ee01dbb2SDamon Ding struct display_rect *src_rect = &cstate->src_rect; 5331ee01dbb2SDamon Ding struct display_rect *dst_rect = &cstate->crtc_rect; 5332ee01dbb2SDamon Ding struct display_rect left_src, left_dst, right_src, right_dst; 5333ee01dbb2SDamon Ding u16 half_hdisplay = mode->crtc_hdisplay >> 1; 5334ee01dbb2SDamon Ding int left_src_w, left_dst_w, right_dst_w; 5335ee01dbb2SDamon Ding 5336ee01dbb2SDamon Ding left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x; 5337ee01dbb2SDamon Ding if (left_dst_w < 0) 5338ee01dbb2SDamon Ding left_dst_w = 0; 5339ee01dbb2SDamon Ding right_dst_w = dst_rect->w - left_dst_w; 5340ee01dbb2SDamon Ding 5341ee01dbb2SDamon Ding if (!right_dst_w) 5342ee01dbb2SDamon Ding left_src_w = src_rect->w; 5343ee01dbb2SDamon Ding else 53440df0fd39SSandy Huang left_src_w = src_rect->x + src_rect->w - src_rect->w / 2; 5345ee01dbb2SDamon Ding 5346ee01dbb2SDamon Ding left_src.x = src_rect->x; 5347ee01dbb2SDamon Ding left_src.w = left_src_w; 5348ee01dbb2SDamon Ding left_dst.x = dst_rect->x; 5349ee01dbb2SDamon Ding left_dst.w = left_dst_w; 5350ee01dbb2SDamon Ding right_src.x = left_src.x + left_src.w; 5351ee01dbb2SDamon Ding right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w; 5352ee01dbb2SDamon Ding right_dst.x = dst_rect->x + left_dst_w - half_hdisplay; 5353ee01dbb2SDamon Ding right_dst.w = right_dst_w; 5354ee01dbb2SDamon Ding 5355ee01dbb2SDamon Ding left_src.y = src_rect->y; 5356ee01dbb2SDamon Ding left_src.h = src_rect->h; 5357ee01dbb2SDamon Ding left_dst.y = dst_rect->y; 5358ee01dbb2SDamon Ding left_dst.h = dst_rect->h; 5359ee01dbb2SDamon Ding right_src.y = src_rect->y; 5360ee01dbb2SDamon Ding right_src.h = src_rect->h; 5361ee01dbb2SDamon Ding right_dst.y = dst_rect->y; 5362ee01dbb2SDamon Ding right_dst.h = dst_rect->h; 5363ee01dbb2SDamon Ding 5364ee01dbb2SDamon Ding memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect)); 5365ee01dbb2SDamon Ding memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect)); 5366ee01dbb2SDamon Ding memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect)); 5367ee01dbb2SDamon Ding memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect)); 5368ee01dbb2SDamon Ding } 5369ee01dbb2SDamon Ding 5370ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state) 5371ecc31b6eSAndy Yan { 5372ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 5373ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 5374ecc31b6eSAndy Yan struct vop2_win_data *win_data; 5375ee01dbb2SDamon Ding struct vop2_win_data *splice_win_data; 5376ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 53771c9572c7SDamon Ding int ret; 5378ecc31b6eSAndy Yan 5379ee01dbb2SDamon Ding if (cstate->crtc_rect.w > cstate->max_output.width) { 5380ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n", 5381ee01dbb2SDamon Ding cstate->crtc_rect.w, cstate->max_output.width); 5382ecc31b6eSAndy Yan return -EINVAL; 5383ecc31b6eSAndy Yan } 5384ecc31b6eSAndy Yan 5385ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 5386ecc31b6eSAndy Yan if (!win_data) { 5387ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id); 5388ecc31b6eSAndy Yan return -ENODEV; 5389ecc31b6eSAndy Yan } 5390ecc31b6eSAndy Yan 53915fa6e665SDamon Ding /* ignore some plane register according vop3 esmart lb mode */ 53925fa6e665SDamon Ding if (vop3_ignore_plane(vop2, win_data)) 53935fa6e665SDamon Ding return -EACCES; 53945fa6e665SDamon Ding 5395a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) { 5396b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, win_data->pd_id)) 5397b6ba80b4SDamon Ding printf("open vp%d plane pd fail\n", cstate->crtc_id); 5398b6ba80b4SDamon Ding } 5399b6ba80b4SDamon Ding 5400ee01dbb2SDamon Ding if (cstate->splice_mode) { 5401ee01dbb2SDamon Ding if (win_data->splice_win_id) { 5402ee01dbb2SDamon Ding splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id); 5403ee01dbb2SDamon Ding splice_win_data->splice_mode_right = true; 5404b6ba80b4SDamon Ding 5405b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, splice_win_data->pd_id)) 5406b6ba80b4SDamon Ding printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id); 5407b6ba80b4SDamon Ding 5408ee01dbb2SDamon Ding vop2_calc_display_rect_for_splice(state); 5409ee01dbb2SDamon Ding if (win_data->type == CLUSTER_LAYER) 5410ee01dbb2SDamon Ding vop2_set_cluster_win(state, splice_win_data); 5411ee01dbb2SDamon Ding else 5412ee01dbb2SDamon Ding vop2_set_smart_win(state, splice_win_data); 5413ee01dbb2SDamon Ding } else { 5414ee01dbb2SDamon Ding printf("ERROR: splice mode is unsupported by plane %s\n", 541527cec8e2SDamon Ding vop2_plane_id_to_string(primary_plane_id)); 5416ee01dbb2SDamon Ding return -EINVAL; 5417ee01dbb2SDamon Ding } 5418ee01dbb2SDamon Ding } 5419ee01dbb2SDamon Ding 5420ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER) 54211c9572c7SDamon Ding ret = vop2_set_cluster_win(state, win_data); 5422ecc31b6eSAndy Yan else 54231c9572c7SDamon Ding ret = vop2_set_smart_win(state, win_data); 54241c9572c7SDamon Ding if (ret) 54251c9572c7SDamon Ding return ret; 54268895aec1SSandy Huang 54278895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 542827cec8e2SDamon Ding cstate->crtc_id, vop2_plane_id_to_string(primary_plane_id), 5429ee01dbb2SDamon Ding cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h, 5430ee01dbb2SDamon Ding cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format, 54318895aec1SSandy Huang cstate->dma_addr); 54328895aec1SSandy Huang 5433d0408543SAndy Yan return 0; 5434d0408543SAndy Yan } 5435d0408543SAndy Yan 5436d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state) 5437d0408543SAndy Yan { 5438d0408543SAndy Yan return 0; 5439d0408543SAndy Yan } 5440d0408543SAndy Yan 544112ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state) 544212ee5af0SDamon Ding { 544312ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 544412ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 544512ee5af0SDamon Ding struct vop2 *vop2 = cstate->private; 544612ee5af0SDamon Ding u8 dsc_id = cstate->dsc_id; 544712ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 544812ee5af0SDamon Ding 544912ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 545012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK, 545112ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 545212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK, 545312ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 545412ee5af0SDamon Ding } else { 545512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK, 545612ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 545712ee5af0SDamon Ding } 545812ee5af0SDamon Ding } 545912ee5af0SDamon Ding 5460d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state) 5461d0408543SAndy Yan { 5462d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 5463d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 546452ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 5465ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5466d0408543SAndy Yan 5467d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5468d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false); 5469ee01dbb2SDamon Ding 5470ee01dbb2SDamon Ding if (cstate->splice_mode) 5471ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5472ee01dbb2SDamon Ding 5473d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5474d0408543SAndy Yan 547512ee5af0SDamon Ding if (cstate->dsc_enable) 547612ee5af0SDamon Ding vop2_dsc_cfg_done(state); 547712ee5af0SDamon Ding 54780675a2a4SDamon Ding if (cstate->mcu_timing.mcu_pix_total) 54790675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 54800675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 0, false); 54810675a2a4SDamon Ding 5482d0408543SAndy Yan return 0; 5483d0408543SAndy Yan } 5484d0408543SAndy Yan 5485efa01fe4SZhang Yubing static int rk3588_vop2_post_enable(struct display_state *state) 5486efa01fe4SZhang Yubing { 5487efa01fe4SZhang Yubing struct connector_state *conn_state = &state->conn_state; 5488efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 5489efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private; 5490efa01fe4SZhang Yubing int output_if = conn_state->output_if; 5491efa01fe4SZhang Yubing u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5492efa01fe4SZhang Yubing int ret, val; 5493efa01fe4SZhang Yubing 5494efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP0) 5495efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 5496efa01fe4SZhang Yubing 1, false); 5497efa01fe4SZhang Yubing 5498efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP1) 5499efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT, 5500efa01fe4SZhang Yubing 1, false); 5501efa01fe4SZhang Yubing 5502efa01fe4SZhang Yubing if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) { 5503efa01fe4SZhang Yubing vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5504efa01fe4SZhang Yubing ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val, 5505efa01fe4SZhang Yubing val & BIT(cstate->crtc_id), 50 * 1000); 5506efa01fe4SZhang Yubing if (ret) 5507efa01fe4SZhang Yubing printf("%s wait cfg done timeout\n", __func__); 55080686a6a6SZhang Yubing 55090686a6a6SZhang Yubing if (cstate->dclk_rst.dev) { 55100686a6a6SZhang Yubing reset_assert(&cstate->dclk_rst); 55110686a6a6SZhang Yubing udelay(20); 55120686a6a6SZhang Yubing reset_deassert(&cstate->dclk_rst); 55130686a6a6SZhang Yubing } 5514efa01fe4SZhang Yubing } 5515efa01fe4SZhang Yubing 5516efa01fe4SZhang Yubing return 0; 5517efa01fe4SZhang Yubing } 5518efa01fe4SZhang Yubing 5519efa01fe4SZhang Yubing static int rk3576_vop2_post_enable(struct display_state *state) 5520efa01fe4SZhang Yubing { 5521efa01fe4SZhang Yubing struct connector_state *conn_state = &state->conn_state; 5522efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 5523efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private; 5524efa01fe4SZhang Yubing int output_if = conn_state->output_if; 5525efa01fe4SZhang Yubing u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5526efa01fe4SZhang Yubing int ret, val; 5527efa01fe4SZhang Yubing 5528efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP0) 5529efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 5530efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false); 5531efa01fe4SZhang Yubing 5532efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP1) 5533efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 5534efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false); 5535efa01fe4SZhang Yubing 5536efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP2) 5537efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 5538efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false); 5539efa01fe4SZhang Yubing 5540efa01fe4SZhang Yubing if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) { 5541efa01fe4SZhang Yubing vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5542efa01fe4SZhang Yubing ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val, 5543efa01fe4SZhang Yubing val & BIT(cstate->crtc_id), 50 * 1000); 5544efa01fe4SZhang Yubing if (ret) 5545efa01fe4SZhang Yubing printf("%s wait cfg done timeout\n", __func__); 55460686a6a6SZhang Yubing 55470686a6a6SZhang Yubing if (cstate->dclk_rst.dev) { 55480686a6a6SZhang Yubing reset_assert(&cstate->dclk_rst); 55490686a6a6SZhang Yubing udelay(20); 55500686a6a6SZhang Yubing reset_deassert(&cstate->dclk_rst); 55510686a6a6SZhang Yubing } 5552efa01fe4SZhang Yubing } 5553efa01fe4SZhang Yubing 5554efa01fe4SZhang Yubing return 0; 5555efa01fe4SZhang Yubing } 5556efa01fe4SZhang Yubing 5557efa01fe4SZhang Yubing static int rockchip_vop2_post_enable(struct display_state *state) 5558efa01fe4SZhang Yubing { 5559efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 5560efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private; 5561efa01fe4SZhang Yubing 5562efa01fe4SZhang Yubing if (vop2->version == VOP_VERSION_RK3588) 5563efa01fe4SZhang Yubing rk3588_vop2_post_enable(state); 5564efa01fe4SZhang Yubing else if (vop2->version == VOP_VERSION_RK3576) 5565efa01fe4SZhang Yubing rk3576_vop2_post_enable(state); 5566efa01fe4SZhang Yubing 5567efa01fe4SZhang Yubing return 0; 5568efa01fe4SZhang Yubing } 5569efa01fe4SZhang Yubing 5570d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state) 5571d0408543SAndy Yan { 5572d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 5573d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 557452ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 5575ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5576d0408543SAndy Yan 5577d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5578d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false); 5579ee01dbb2SDamon Ding 5580ee01dbb2SDamon Ding if (cstate->splice_mode) 5581ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5582ee01dbb2SDamon Ding 5583d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5584d0408543SAndy Yan 5585d0408543SAndy Yan return 0; 5586d0408543SAndy Yan } 5587d0408543SAndy Yan 5588ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 5589ee008497SSandy Huang { 5590ee008497SSandy Huang struct crtc_state *cstate = &state->crtc_state; 5591ee008497SSandy Huang struct vop2 *vop2 = cstate->private; 5592ee008497SSandy Huang int i = 0; 5593ee008497SSandy Huang int correct_cursor_plane = -1; 5594ee008497SSandy Huang int plane_type = -1; 5595ee008497SSandy Huang 5596ee008497SSandy Huang if (cursor_plane < 0) 5597ee008497SSandy Huang return -1; 5598ee008497SSandy Huang 5599ee008497SSandy Huang if (plane_mask & (1 << cursor_plane)) 5600ee008497SSandy Huang return cursor_plane; 5601ee008497SSandy Huang 5602ee008497SSandy Huang /* Get current cursor plane type */ 5603ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 5604ee008497SSandy Huang if (vop2->data->plane_table[i].plane_id == cursor_plane) { 5605ee008497SSandy Huang plane_type = vop2->data->plane_table[i].plane_type; 5606ee008497SSandy Huang break; 5607ee008497SSandy Huang } 5608ee008497SSandy Huang } 5609ee008497SSandy Huang 5610ee008497SSandy Huang /* Get the other same plane type plane id */ 5611ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 5612ee008497SSandy Huang if (vop2->data->plane_table[i].plane_type == plane_type && 5613ee008497SSandy Huang vop2->data->plane_table[i].plane_id != cursor_plane) { 5614ee008497SSandy Huang correct_cursor_plane = vop2->data->plane_table[i].plane_id; 5615ee008497SSandy Huang break; 5616ee008497SSandy Huang } 5617ee008497SSandy Huang } 5618ee008497SSandy Huang 5619ee008497SSandy Huang /* To check whether the new correct_cursor_plane is attach to current vp */ 5620ee008497SSandy Huang if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 5621ee008497SSandy Huang printf("error: faild to find correct plane as cursor plane\n"); 5622ee008497SSandy Huang return -1; 5623ee008497SSandy Huang } 5624ee008497SSandy Huang 5625ee008497SSandy Huang printf("vp%d adjust cursor plane from %d to %d\n", 5626ee008497SSandy Huang cstate->crtc_id, cursor_plane, correct_cursor_plane); 5627ee008497SSandy Huang 5628ee008497SSandy Huang return correct_cursor_plane; 5629ee008497SSandy Huang } 5630ee008497SSandy Huang 5631b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 5632b0989546SSandy Huang { 5633b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 5634b0989546SSandy Huang struct vop2 *vop2 = cstate->private; 5635b0989546SSandy Huang ofnode vp_node; 5636b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node; 5637b0989546SSandy Huang static bool vop_fix_dts; 5638b0989546SSandy Huang const char *path; 5639b0989546SSandy Huang u32 plane_mask = 0; 5640b0989546SSandy Huang int vp_id = 0; 5641ee008497SSandy Huang int cursor_plane_id = -1; 5642b0989546SSandy Huang 56435fa6e665SDamon Ding if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528) 5644b0989546SSandy Huang return 0; 5645b0989546SSandy Huang 5646b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 5647b0989546SSandy Huang path = vp_node.np->full_name; 5648b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 5649b0989546SSandy Huang 56508b1fe597SSandy Huang if (cstate->crtc->assign_plane) 56518b1fe597SSandy Huang continue; 5652ee008497SSandy Huang cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 5653ee008497SSandy Huang cstate->crtc->vps[vp_id].cursor_plane); 5654ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 5655b0989546SSandy Huang vp_id, plane_mask, 5656ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 5657ee008497SSandy Huang cursor_plane_id); 5658b0989546SSandy Huang 5659b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 5660b0989546SSandy Huang plane_mask, 1); 5661b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 5662b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 5663ee008497SSandy Huang if (cursor_plane_id >= 0) 5664ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id", 5665ee008497SSandy Huang cursor_plane_id, 1); 5666b0989546SSandy Huang vp_id++; 5667b0989546SSandy Huang } 5668b0989546SSandy Huang 5669b0989546SSandy Huang vop_fix_dts = true; 5670b0989546SSandy Huang 5671b0989546SSandy Huang return 0; 5672b0989546SSandy Huang } 5673b0989546SSandy Huang 5674820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state) 5675820a5c17SDamon Ding { 5676820a5c17SDamon Ding struct crtc_state *cstate = &state->crtc_state; 5677820a5c17SDamon Ding struct rockchip_crtc *crtc = cstate->crtc; 5678820a5c17SDamon Ding 5679820a5c17SDamon Ding if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) { 5680820a5c17SDamon Ding printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id); 5681820a5c17SDamon Ding return -ENOTSUPP; 5682820a5c17SDamon Ding } 5683820a5c17SDamon Ding 5684820a5c17SDamon Ding if (cstate->splice_mode) { 5685820a5c17SDamon Ding crtc->splice_mode = true; 5686820a5c17SDamon Ding crtc->splice_crtc_id = cstate->splice_crtc_id; 5687820a5c17SDamon Ding } 5688820a5c17SDamon Ding 5689820a5c17SDamon Ding return 0; 5690820a5c17SDamon Ding } 5691820a5c17SDamon Ding 569222007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state) 569322007755SDamon Ding { 569422007755SDamon Ding struct connector_state *conn_state = &state->conn_state; 569522007755SDamon Ding struct crtc_state *cstate = &state->crtc_state; 569622007755SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 569722007755SDamon Ding struct videomode vm; 569822007755SDamon Ding 569922007755SDamon Ding drm_display_mode_to_videomode(mode, &vm); 570022007755SDamon Ding 570122007755SDamon Ding if (vm.hactive < 32 || vm.vactive < 32 || 570222007755SDamon Ding (vm.hfront_porch * vm.hsync_len * vm.hback_porch * 570322007755SDamon Ding vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) { 570422007755SDamon Ding printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id); 570522007755SDamon Ding return -EINVAL; 570622007755SDamon Ding } 570722007755SDamon Ding 570822007755SDamon Ding return 0; 570922007755SDamon Ding } 571022007755SDamon Ding 5711b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state) 5712b02eb70bSDamon Ding { 5713b02eb70bSDamon Ding struct connector_state *conn_state = &state->conn_state; 57140e19fecdSDamon Ding struct rockchip_connector *conn = conn_state->connector; 5715b02eb70bSDamon Ding struct drm_display_mode *mode = &conn_state->mode; 5716b02eb70bSDamon Ding struct crtc_state *cstate = &state->crtc_state; 5717b02eb70bSDamon Ding struct vop2 *vop2 = cstate->private; 5718b02eb70bSDamon Ding 57190e19fecdSDamon Ding if (conn_state->secondary) { 57200e19fecdSDamon Ding if (!(conn->dual_channel_mode && 57210e19fecdSDamon Ding conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) && 57222b992d78SDamon Ding conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS) 57232b992d78SDamon Ding drm_mode_convert_to_split_mode(mode); 57240e19fecdSDamon Ding } 57252b992d78SDamon Ding 57261b5811e7SDamon Ding drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE); 5727b02eb70bSDamon Ding 5728243f0077SDamon Ding /* 5729640211a0SDamon Ding * For RK3568 and RK3588, the hactive of video timing must 5730640211a0SDamon Ding * be 4-pixel aligned. 5731640211a0SDamon Ding */ 5732640211a0SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) { 5733640211a0SDamon Ding if (mode->crtc_hdisplay % 4) { 5734640211a0SDamon Ding int old_hdisplay = mode->crtc_hdisplay; 5735640211a0SDamon Ding int align = 4 - (mode->crtc_hdisplay % 4); 5736640211a0SDamon Ding 5737640211a0SDamon Ding mode->crtc_hdisplay += align; 5738640211a0SDamon Ding mode->crtc_hsync_start += align; 5739640211a0SDamon Ding mode->crtc_hsync_end += align; 5740640211a0SDamon Ding mode->crtc_htotal += align; 5741640211a0SDamon Ding 5742640211a0SDamon Ding printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n", 5743640211a0SDamon Ding old_hdisplay, mode->hdisplay); 5744640211a0SDamon Ding } 5745640211a0SDamon Ding } 5746640211a0SDamon Ding 5747640211a0SDamon Ding /* 5748243f0077SDamon Ding * For RK3576 YUV420 output, hden signal introduce one cycle delay, 5749243f0077SDamon Ding * so we need to adjust hfp and hbp to compatible with this design. 5750243f0077SDamon Ding */ 5751243f0077SDamon Ding if (vop2->version == VOP_VERSION_RK3576 && 5752243f0077SDamon Ding conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 5753243f0077SDamon Ding mode->crtc_hsync_start += 2; 5754243f0077SDamon Ding mode->crtc_hsync_end += 2; 5755243f0077SDamon Ding } 5756243f0077SDamon Ding 5757b02eb70bSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656) 5758b02eb70bSDamon Ding mode->crtc_clock *= 2; 5759b02eb70bSDamon Ding 5760b02eb70bSDamon Ding /* 5761b02eb70bSDamon Ding * For RK3528, the path of CVBS output is like: 5762b02eb70bSDamon Ding * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC 5763b02eb70bSDamon Ding * The vop2 dclk should be four times crtc_clock for CVBS sampling 5764b02eb70bSDamon Ding * clock needs. 5765b02eb70bSDamon Ding */ 5766b02eb70bSDamon Ding if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656) 5767b02eb70bSDamon Ding mode->crtc_clock *= 4; 5768b02eb70bSDamon Ding 57694d64cedbSDamon Ding mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format); 57704d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total) 57714d64cedbSDamon Ding mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1; 57720675a2a4SDamon Ding 5773b02eb70bSDamon Ding return 0; 5774b02eb70bSDamon Ding } 5775b02eb70bSDamon Ding 57764c765862SDamon Ding #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) 57774c765862SDamon Ding 57784c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state) 57794c765862SDamon Ding { 57804c765862SDamon Ding struct crtc_state *cstate = &state->crtc_state; 57814c765862SDamon Ding struct vop2 *vop2 = cstate->private; 57824c765862SDamon Ding struct display_rect *src = &cstate->src_rect; 57834c765862SDamon Ding struct display_rect *dst = &cstate->crtc_rect; 57844c765862SDamon Ding struct vop2_win_data *win_data; 57854c765862SDamon Ding int min_scale, max_scale; 57864c765862SDamon Ding int hscale, vscale; 57874c765862SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 57884c765862SDamon Ding 57894c765862SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 57904c765862SDamon Ding if (!win_data) { 57914c765862SDamon Ding printf("ERROR: invalid win id %d\n", primary_plane_id); 57924c765862SDamon Ding return -ENODEV; 57934c765862SDamon Ding } 57944c765862SDamon Ding 57954c765862SDamon Ding min_scale = FRAC_16_16(1, win_data->max_downscale_factor); 57964c765862SDamon Ding max_scale = FRAC_16_16(win_data->max_upscale_factor, 1); 57974c765862SDamon Ding 57984c765862SDamon Ding hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale); 57994c765862SDamon Ding vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale); 58004c765862SDamon Ding if (hscale < 0 || vscale < 0) { 58014c765862SDamon Ding printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name); 58024c765862SDamon Ding return -ERANGE; 58034c765862SDamon Ding } 58044c765862SDamon Ding 58054c765862SDamon Ding return 0; 58064c765862SDamon Ding } 5807337d1c13SDamon Ding 58088e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state) 58098e7ef808SDamon Ding { 5810d8e7f4a5SSandy Huang __maybe_unused struct connector_state *conn_state = &state->conn_state; 58118e7ef808SDamon Ding struct crtc_state *cstate = &state->crtc_state; 58128e7ef808SDamon Ding struct vop2 *vop2 = cstate->private; 58138e7ef808SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 58148e7ef808SDamon Ding int val = 0; 58158e7ef808SDamon Ding int ret = 0; 58168e7ef808SDamon Ding 58178e7ef808SDamon Ding ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val, 58188e7ef808SDamon Ding (val >> EDPI_WMS_FS) & 0x1, 50 * 1000); 58198e7ef808SDamon Ding if (!ret) { 5820d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 58218e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 58228e7ef808SDamon Ding !val, 50 * 1000); 58238e7ef808SDamon Ding if (!ret) { 58248e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 58258e7ef808SDamon Ding val, 50 * 1000); 58268e7ef808SDamon Ding if (!ret) { 58278e7ef808SDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 58288e7ef808SDamon Ding EN_MASK, EDPI_WMS_FS, 1, false); 58298e7ef808SDamon Ding } else { 58308e7ef808SDamon Ding printf("ERROR: vp%d wait for active TE signal timeout\n", 58318e7ef808SDamon Ding cstate->crtc_id); 58328e7ef808SDamon Ding return ret; 58338e7ef808SDamon Ding } 58348e7ef808SDamon Ding } else { 58358e7ef808SDamon Ding printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id); 58368e7ef808SDamon Ding return ret; 58378e7ef808SDamon Ding } 5838d8e7f4a5SSandy Huang #endif 58398e7ef808SDamon Ding } else { 58408e7ef808SDamon Ding printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id); 58418e7ef808SDamon Ding return ret; 58428e7ef808SDamon Ding } 58438e7ef808SDamon Ding 58448e7ef808SDamon Ding return 0; 58458e7ef808SDamon Ding } 58468e7ef808SDamon Ding 584772388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state) 584872388c26SDamon Ding { 584972388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 585072388c26SDamon Ding struct vop2 *vop2 = cstate->private; 585172388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 585272388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 5853a552a69cSDamon Ding u32 len = 128; 585472388c26SDamon Ding u32 n, i, j; 585572388c26SDamon Ding u32 base; 585672388c26SDamon Ding 585772388c26SDamon Ding if (!cstate->crtc->active) 585872388c26SDamon Ding return -EINVAL; 585972388c26SDamon Ding 586072388c26SDamon Ding n = vop2_data->dump_regs_size; 586172388c26SDamon Ding for (i = 0; i < n; i++) { 586272388c26SDamon Ding base = regs[i].offset; 5863a552a69cSDamon Ding len = 128; 5864a552a69cSDamon Ding if (regs[i].size) 5865a552a69cSDamon Ding len = min(len, regs[i].size >> 2); 586672388c26SDamon Ding printf("\n%s:\n", regs[i].name); 5867a552a69cSDamon Ding for (j = 0; j < len;) { 586872388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 586972388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 587072388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 587172388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 587272388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 587372388c26SDamon Ding j += 4; 587472388c26SDamon Ding } 587572388c26SDamon Ding } 587672388c26SDamon Ding 587772388c26SDamon Ding return 0; 587872388c26SDamon Ding } 587972388c26SDamon Ding 588072388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state) 588172388c26SDamon Ding { 588272388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 588372388c26SDamon Ding struct vop2 *vop2 = cstate->private; 588472388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 588572388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 5886a552a69cSDamon Ding u32 len = 128; 588772388c26SDamon Ding u32 n, i, j; 588872388c26SDamon Ding u32 base; 588972388c26SDamon Ding bool enable_state; 589072388c26SDamon Ding 589172388c26SDamon Ding if (!cstate->crtc->active) 589272388c26SDamon Ding return -EINVAL; 589372388c26SDamon Ding 589472388c26SDamon Ding n = vop2_data->dump_regs_size; 589572388c26SDamon Ding for (i = 0; i < n; i++) { 589672388c26SDamon Ding if (regs[i].state_mask) { 589772388c26SDamon Ding enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) & 589872388c26SDamon Ding regs[i].state_mask; 589972388c26SDamon Ding if (enable_state != regs[i].enable_state) 590072388c26SDamon Ding continue; 590172388c26SDamon Ding } 590272388c26SDamon Ding 590372388c26SDamon Ding base = regs[i].offset; 5904a552a69cSDamon Ding len = 128; 5905a552a69cSDamon Ding if (regs[i].size) 5906a552a69cSDamon Ding len = min(len, regs[i].size >> 2); 590772388c26SDamon Ding printf("\n%s:\n", regs[i].name); 5908a552a69cSDamon Ding for (j = 0; j < len;) { 590972388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 591072388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 591172388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 591272388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 591372388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 591472388c26SDamon Ding j += 4; 591572388c26SDamon Ding } 591672388c26SDamon Ding } 591772388c26SDamon Ding 591872388c26SDamon Ding return 0; 591972388c26SDamon Ding } 592072388c26SDamon Ding 59219c7848c3SDamon Ding static void rk3528_setup_win_dly(struct display_state *state, int crtc_id) 59229c7848c3SDamon Ding { 59239c7848c3SDamon Ding struct crtc_state *cstate = &state->crtc_state; 59249c7848c3SDamon Ding struct vop2 *vop2 = cstate->private; 59259c7848c3SDamon Ding struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id]; 59269c7848c3SDamon Ding uint32_t dly = 0; /* For vop3, the default window delay is 0 */ 59279c7848c3SDamon Ding 59289c7848c3SDamon Ding switch (plane_mask->primary_plane_id) { 59299c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER0: 59309c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_CLUSTER0_CTRL, CLUSTER_DLY_NUM_MASK, 59319c7848c3SDamon Ding CLUSTER_DLY_NUM_SHIFT, dly, false); 59329c7848c3SDamon Ding break; 59339c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART0: 59349c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL, ESMART_DLY_NUM_MASK, 59359c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 59369c7848c3SDamon Ding break; 59379c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART1: 59389c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART1_CTRL, ESMART_DLY_NUM_MASK, 59399c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 59409c7848c3SDamon Ding break; 59419c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART2: 59429c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART2_CTRL, ESMART_DLY_NUM_MASK, 59439c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 59449c7848c3SDamon Ding break; 59459c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART3: 59469c7848c3SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART3_CTRL, ESMART_DLY_NUM_MASK, 59479c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 59489c7848c3SDamon Ding break; 59499c7848c3SDamon Ding } 59509c7848c3SDamon Ding } 59519c7848c3SDamon Ding 5952b7195f56SDamon Ding static void rk3528_setup_overlay(struct display_state *state) 5953b7195f56SDamon Ding { 5954b7195f56SDamon Ding struct crtc_state *cstate = &state->crtc_state; 5955b7195f56SDamon Ding struct vop2 *vop2 = cstate->private; 5956b7195f56SDamon Ding struct vop2_win_data *win_data; 5957b7195f56SDamon Ding int i; 5958b7195f56SDamon Ding u32 offset = 0; 5959b7195f56SDamon Ding u8 shift = 0; 5960b7195f56SDamon Ding 5961b7195f56SDamon Ding /* init the layer sel value to 0xff(Disable layer) */ 5962b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 5963b7195f56SDamon Ding offset = 0x100 * i; 5964b7195f56SDamon Ding vop2_writel(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 0xffffffff); 5965b7195f56SDamon Ding } 5966b7195f56SDamon Ding 5967b7195f56SDamon Ding /* layer sel win id */ 5968b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 5969b7195f56SDamon Ding if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { 5970b7195f56SDamon Ding offset = 0x100 * i; 5971b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id); 5972b7195f56SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 5973b7195f56SDamon Ding LAYER_SEL_MASK, 0, win_data->layer_sel_win_id[i], false); 5974b7195f56SDamon Ding } 5975b7195f56SDamon Ding } 5976b7195f56SDamon Ding 5977b7195f56SDamon Ding /* win sel port */ 5978b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 5979b7195f56SDamon Ding if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { 5980b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id); 5981b7195f56SDamon Ding shift = win_data->win_sel_port_offset * 2; 5982b7195f56SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL, 5983b7195f56SDamon Ding LAYER_SEL_PORT_MASK, shift, i, false); 5984b7195f56SDamon Ding } 5985b7195f56SDamon Ding } 5986b7195f56SDamon Ding } 5987b7195f56SDamon Ding 59889c7848c3SDamon Ding static void rk3568_setup_win_dly(struct display_state *state, int crtc_id) 59899c7848c3SDamon Ding { 59909c7848c3SDamon Ding struct crtc_state *cstate = &state->crtc_state; 59919c7848c3SDamon Ding struct vop2 *vop2 = cstate->private; 59929c7848c3SDamon Ding struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id]; 59939c7848c3SDamon Ding struct vop2_win_data *win_data; 59949c7848c3SDamon Ding uint32_t dly; 59959c7848c3SDamon Ding 59969c7848c3SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, plane_mask->primary_plane_id); 59979c7848c3SDamon Ding dly = win_data->dly[VOP2_DLY_MODE_DEFAULT]; 59989c7848c3SDamon Ding if (win_data->type == CLUSTER_LAYER) 59999c7848c3SDamon Ding dly |= dly << 8; 60009c7848c3SDamon Ding 60019c7848c3SDamon Ding switch (plane_mask->primary_plane_id) { 60029c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER0: 60039c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK, 60049c7848c3SDamon Ding CLUSTER0_DLY_NUM_SHIFT, dly, false); 60059c7848c3SDamon Ding break; 60069c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER1: 60079c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK, 60089c7848c3SDamon Ding CLUSTER1_DLY_NUM_SHIFT, dly, false); 60099c7848c3SDamon Ding break; 60109c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER2: 60119c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK, 60129c7848c3SDamon Ding CLUSTER0_DLY_NUM_SHIFT, dly, false); 60139c7848c3SDamon Ding break; 60149c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER3: 60159c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK, 60169c7848c3SDamon Ding CLUSTER1_DLY_NUM_SHIFT, dly, false); 60179c7848c3SDamon Ding break; 60189c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART0: 60199c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 60209c7848c3SDamon Ding ESMART0_DLY_NUM_SHIFT, dly, false); 60219c7848c3SDamon Ding break; 60229c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART1: 60239c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 60249c7848c3SDamon Ding ESMART1_DLY_NUM_SHIFT, dly, false); 60259c7848c3SDamon Ding break; 60269c7848c3SDamon Ding case ROCKCHIP_VOP2_SMART0: 60279c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART2: 60289c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 60299c7848c3SDamon Ding SMART0_DLY_NUM_SHIFT, dly, false); 60309c7848c3SDamon Ding break; 60319c7848c3SDamon Ding case ROCKCHIP_VOP2_SMART1: 60329c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART3: 60339c7848c3SDamon Ding vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 60349c7848c3SDamon Ding SMART1_DLY_NUM_SHIFT, dly, false); 60359c7848c3SDamon Ding break; 60369c7848c3SDamon Ding } 60379c7848c3SDamon Ding } 60389c7848c3SDamon Ding 6039b7195f56SDamon Ding static void rk3568_setup_overlay(struct display_state *state) 6040b7195f56SDamon Ding { 6041b7195f56SDamon Ding struct crtc_state *cstate = &state->crtc_state; 6042b7195f56SDamon Ding struct vop2 *vop2 = cstate->private; 6043b7195f56SDamon Ding struct vop2_win_data *win_data; 6044b7195f56SDamon Ding int layer_phy_id = 0; 6045b7195f56SDamon Ding int total_used_layer = 0; 6046b7195f56SDamon Ding int port_mux = 0; 6047b7195f56SDamon Ding int i, j; 6048b7195f56SDamon Ding u32 layer_nr = 0; 6049b7195f56SDamon Ding u8 shift = 0; 6050b7195f56SDamon Ding 6051b7195f56SDamon Ding /* layer sel win id */ 6052b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 6053b7195f56SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 6054b7195f56SDamon Ding for (j = 0; j < layer_nr; j++) { 6055b7195f56SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 6056b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 6057b7195f56SDamon Ding vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 6058b7195f56SDamon Ding shift, win_data->layer_sel_win_id[i], false); 6059b7195f56SDamon Ding shift += 4; 6060b7195f56SDamon Ding } 6061b7195f56SDamon Ding } 6062b7195f56SDamon Ding 6063b7195f56SDamon Ding /* win sel port */ 6064b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 6065b7195f56SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 6066b7195f56SDamon Ding for (j = 0; j < layer_nr; j++) { 6067b7195f56SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 6068b7195f56SDamon Ding continue; 6069b7195f56SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 6070b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 6071b7195f56SDamon Ding shift = win_data->win_sel_port_offset * 2; 6072b7195f56SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 6073b7195f56SDamon Ding LAYER_SEL_PORT_SHIFT + shift, i, false); 6074b7195f56SDamon Ding } 6075b7195f56SDamon Ding } 6076b7195f56SDamon Ding 6077b7195f56SDamon Ding /** 6078b7195f56SDamon Ding * port mux config 6079b7195f56SDamon Ding */ 6080b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 6081b7195f56SDamon Ding shift = i * 4; 6082b7195f56SDamon Ding if (vop2->vp_plane_mask[i].attached_layers_nr) { 6083b7195f56SDamon Ding total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 6084b7195f56SDamon Ding port_mux = total_used_layer - 1; 6085b7195f56SDamon Ding } else { 6086b7195f56SDamon Ding port_mux = 8; 6087b7195f56SDamon Ding } 6088b7195f56SDamon Ding 6089b7195f56SDamon Ding if (i == vop2->data->nr_vps - 1) 6090b7195f56SDamon Ding port_mux = vop2->data->nr_mixers; 6091b7195f56SDamon Ding 6092b7195f56SDamon Ding cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 6093b7195f56SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 6094b7195f56SDamon Ding PORT_MUX_SHIFT + shift, port_mux, false); 6095b7195f56SDamon Ding } 6096b7195f56SDamon Ding } 6097b7195f56SDamon Ding 60989c7848c3SDamon Ding static void rk3576_setup_win_dly(struct display_state *state, int crtc_id) 60999c7848c3SDamon Ding { 61009c7848c3SDamon Ding struct crtc_state *cstate = &state->crtc_state; 61019c7848c3SDamon Ding struct vop2 *vop2 = cstate->private; 61029c7848c3SDamon Ding struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id]; 61039c7848c3SDamon Ding uint32_t dly = 0; /* For vop3, the default window delay is 0 */ 61049c7848c3SDamon Ding 61059c7848c3SDamon Ding switch (plane_mask->primary_plane_id) { 61069c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER0: 61079c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_DLY_NUM, CLUSTER_DLY_NUM_MASK, 61089c7848c3SDamon Ding CLUSTER_DLY_NUM_SHIFT, dly, false); 61099c7848c3SDamon Ding break; 61109c7848c3SDamon Ding case ROCKCHIP_VOP2_CLUSTER1: 61119c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER1_DLY_NUM, CLUSTER_DLY_NUM_MASK, 61129c7848c3SDamon Ding CLUSTER_DLY_NUM_SHIFT, dly, false); 61139c7848c3SDamon Ding break; 61149c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART0: 61159c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM, ESMART_DLY_NUM_MASK, 61169c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 61179c7848c3SDamon Ding break; 61189c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART1: 61199c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART1_DLY_NUM, ESMART_DLY_NUM_MASK, 61209c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 61219c7848c3SDamon Ding break; 61229c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART2: 61239c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART2_DLY_NUM, ESMART_DLY_NUM_MASK, 61249c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 61259c7848c3SDamon Ding break; 61269c7848c3SDamon Ding case ROCKCHIP_VOP2_ESMART3: 61279c7848c3SDamon Ding vop2_mask_write(vop2, RK3576_ESMART3_DLY_NUM, ESMART_DLY_NUM_MASK, 61289c7848c3SDamon Ding ESMART_DLY_NUM_SHIFT, dly, false); 61299c7848c3SDamon Ding break; 61309c7848c3SDamon Ding } 61319c7848c3SDamon Ding } 61329c7848c3SDamon Ding 6133b7195f56SDamon Ding static void rk3576_setup_overlay(struct display_state *state) 6134b7195f56SDamon Ding { 6135b7195f56SDamon Ding struct crtc_state *cstate = &state->crtc_state; 6136b7195f56SDamon Ding struct vop2 *vop2 = cstate->private; 6137b7195f56SDamon Ding struct vop2_win_data *win_data; 6138b7195f56SDamon Ding int i; 6139b7195f56SDamon Ding u32 offset = 0; 6140b7195f56SDamon Ding 6141b7195f56SDamon Ding /* layer sel win id */ 6142b7195f56SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 6143b7195f56SDamon Ding if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { 6144b7195f56SDamon Ding offset = 0x100 * i; 6145b7195f56SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id); 6146b7195f56SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, LAYER_SEL_MASK, 6147b7195f56SDamon Ding 0, win_data->layer_sel_win_id[i], false); 6148b7195f56SDamon Ding } 6149b7195f56SDamon Ding } 6150b7195f56SDamon Ding } 6151b7195f56SDamon Ding 615272388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = { 615372388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 615472388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 615572388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 615672388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 615772388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 615872388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 615972388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 616072388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 616172388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 616272388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 616372388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 616472388c26SDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 616572388c26SDamon Ding { RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1}, 616672388c26SDamon Ding }; 616772388c26SDamon Ding 61685fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 61695fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, 61705fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART1, 61715fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, 61725fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART3, 61735fa6e665SDamon Ding }; 61745fa6e665SDamon Ding 61755fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 61765fa6e665SDamon Ding {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 61775fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 61785fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 61795fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 61805fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 61815fa6e665SDamon Ding }; 61825fa6e665SDamon Ding 61835fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 61845fa6e665SDamon Ding { /* one display policy for hdmi */ 61855fa6e665SDamon Ding {/* main display */ 6186ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 61875fa6e665SDamon Ding .attached_layers_nr = 4, 61885fa6e665SDamon Ding .attached_layers = { 61895fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 61905fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2 61915fa6e665SDamon Ding }, 61925fa6e665SDamon Ding }, 61935fa6e665SDamon Ding {/* second display */}, 61945fa6e665SDamon Ding {/* third display */}, 61955fa6e665SDamon Ding {/* fourth display */}, 61965fa6e665SDamon Ding }, 61975fa6e665SDamon Ding 61985fa6e665SDamon Ding { /* two display policy */ 61995fa6e665SDamon Ding {/* main display */ 6200ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 62015fa6e665SDamon Ding .attached_layers_nr = 3, 62025fa6e665SDamon Ding .attached_layers = { 62035fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 62045fa6e665SDamon Ding }, 62055fa6e665SDamon Ding }, 62065fa6e665SDamon Ding 62075fa6e665SDamon Ding {/* second display */ 62085fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 62095fa6e665SDamon Ding .attached_layers_nr = 2, 62105fa6e665SDamon Ding .attached_layers = { 62115fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 62125fa6e665SDamon Ding }, 62135fa6e665SDamon Ding }, 62145fa6e665SDamon Ding {/* third display */}, 62155fa6e665SDamon Ding {/* fourth display */}, 62165fa6e665SDamon Ding }, 62175fa6e665SDamon Ding 62185fa6e665SDamon Ding { /* one display policy for cvbs */ 62195fa6e665SDamon Ding {/* main display */ 62205fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 62215fa6e665SDamon Ding .attached_layers_nr = 2, 62225fa6e665SDamon Ding .attached_layers = { 62235fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 62245fa6e665SDamon Ding }, 62255fa6e665SDamon Ding }, 62265fa6e665SDamon Ding {/* second display */}, 62275fa6e665SDamon Ding {/* third display */}, 62285fa6e665SDamon Ding {/* fourth display */}, 62295fa6e665SDamon Ding }, 62305fa6e665SDamon Ding 62315fa6e665SDamon Ding {/* reserved */}, 62325fa6e665SDamon Ding }; 62335fa6e665SDamon Ding 62345fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = { 62355fa6e665SDamon Ding { 62365fa6e665SDamon Ding .name = "Esmart0", 62375fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 62385fa6e665SDamon Ding .type = ESMART_LAYER, 62395fa6e665SDamon Ding .win_sel_port_offset = 8, 62405fa6e665SDamon Ding .layer_sel_win_id = { 1, 0xff, 0xff, 0xff }, 62415fa6e665SDamon Ding .reg_offset = 0, 62425fa6e665SDamon Ding .axi_id = 0, 62435fa6e665SDamon Ding .axi_yrgb_id = 0x06, 62445fa6e665SDamon Ding .axi_uv_id = 0x07, 62455fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 62465fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 62475fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 62485fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 62495fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 62505fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6251*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0), 62525fa6e665SDamon Ding .max_upscale_factor = 8, 62535fa6e665SDamon Ding .max_downscale_factor = 8, 62545fa6e665SDamon Ding }, 62555fa6e665SDamon Ding 62565fa6e665SDamon Ding { 62575fa6e665SDamon Ding .name = "Esmart1", 62585fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 62595fa6e665SDamon Ding .type = ESMART_LAYER, 62605fa6e665SDamon Ding .win_sel_port_offset = 10, 62615fa6e665SDamon Ding .layer_sel_win_id = { 2, 0xff, 0xff, 0xff }, 62625fa6e665SDamon Ding .reg_offset = 0x200, 62635fa6e665SDamon Ding .axi_id = 0, 62645fa6e665SDamon Ding .axi_yrgb_id = 0x08, 62655fa6e665SDamon Ding .axi_uv_id = 0x09, 62665fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 62675fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 62685fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 62695fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 62705fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 62715fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6272*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0), 62735fa6e665SDamon Ding .max_upscale_factor = 8, 62745fa6e665SDamon Ding .max_downscale_factor = 8, 62755fa6e665SDamon Ding }, 62765fa6e665SDamon Ding 62775fa6e665SDamon Ding { 62785fa6e665SDamon Ding .name = "Esmart2", 62795fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 62805fa6e665SDamon Ding .type = ESMART_LAYER, 62815fa6e665SDamon Ding .win_sel_port_offset = 12, 62825fa6e665SDamon Ding .layer_sel_win_id = { 3, 0, 0xff, 0xff }, 62835fa6e665SDamon Ding .reg_offset = 0x400, 62845fa6e665SDamon Ding .axi_id = 0, 62855fa6e665SDamon Ding .axi_yrgb_id = 0x0a, 62865fa6e665SDamon Ding .axi_uv_id = 0x0b, 62875fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 62885fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 62895fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 62905fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 62915fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 62925fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6293*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1), 62945fa6e665SDamon Ding .max_upscale_factor = 8, 62955fa6e665SDamon Ding .max_downscale_factor = 8, 62965fa6e665SDamon Ding }, 62975fa6e665SDamon Ding 62985fa6e665SDamon Ding { 62995fa6e665SDamon Ding .name = "Esmart3", 63005fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 63015fa6e665SDamon Ding .type = ESMART_LAYER, 63025fa6e665SDamon Ding .win_sel_port_offset = 14, 63035fa6e665SDamon Ding .layer_sel_win_id = { 0xff, 1, 0xff, 0xff }, 63045fa6e665SDamon Ding .reg_offset = 0x600, 63055fa6e665SDamon Ding .axi_id = 0, 63065fa6e665SDamon Ding .axi_yrgb_id = 0x0c, 63075fa6e665SDamon Ding .axi_uv_id = 0x0d, 63085fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 63095fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 63105fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 63115fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 63125fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 63135fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6314*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP1), 63155fa6e665SDamon Ding .max_upscale_factor = 8, 63165fa6e665SDamon Ding .max_downscale_factor = 8, 63175fa6e665SDamon Ding }, 63185fa6e665SDamon Ding 63195fa6e665SDamon Ding { 63205fa6e665SDamon Ding .name = "Cluster0", 63215fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0, 63225fa6e665SDamon Ding .type = CLUSTER_LAYER, 63235fa6e665SDamon Ding .win_sel_port_offset = 0, 63245fa6e665SDamon Ding .layer_sel_win_id = { 0, 0xff, 0xff, 0xff }, 63255fa6e665SDamon Ding .reg_offset = 0, 63265fa6e665SDamon Ding .axi_id = 0, 63275fa6e665SDamon Ding .axi_yrgb_id = 0x02, 63285fa6e665SDamon Ding .axi_uv_id = 0x03, 63295fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 63305fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 63315fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 63325fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 63335fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 63345fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 6335*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0), 63365fa6e665SDamon Ding .max_upscale_factor = 8, 63375fa6e665SDamon Ding .max_downscale_factor = 8, 63385fa6e665SDamon Ding }, 63395fa6e665SDamon Ding }; 63405fa6e665SDamon Ding 63415fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = { 63425fa6e665SDamon Ding { 63436027c871SZhang Yubing .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM | 63446027c871SZhang Yubing VOP_FEATURE_POST_CSC, 63455fa6e665SDamon Ding .max_output = {4096, 4096}, 6346b05105abSDamon Ding .layer_mix_dly = 6, 6347b05105abSDamon Ding .hdr_mix_dly = 2, 6348b05105abSDamon Ding .win_dly = 8, 63495fa6e665SDamon Ding }, 63505fa6e665SDamon Ding { 63515fa6e665SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 63525fa6e665SDamon Ding .max_output = {1920, 1080}, 6353b05105abSDamon Ding .layer_mix_dly = 2, 6354b05105abSDamon Ding .hdr_mix_dly = 0, 6355b05105abSDamon Ding .win_dly = 8, 63565fa6e665SDamon Ding }, 63575fa6e665SDamon Ding }; 63585fa6e665SDamon Ding 63599c7848c3SDamon Ding static const struct vop2_ops rk3528_vop_ops = { 63609c7848c3SDamon Ding .setup_win_dly = rk3528_setup_win_dly, 6361b7195f56SDamon Ding .setup_overlay = rk3528_setup_overlay, 63629c7848c3SDamon Ding }; 63639c7848c3SDamon Ding 63645fa6e665SDamon Ding const struct vop2_data rk3528_vop = { 63655fa6e665SDamon Ding .version = VOP_VERSION_RK3528, 63665fa6e665SDamon Ding .nr_vps = 2, 63675fa6e665SDamon Ding .vp_data = rk3528_vp_data, 63685fa6e665SDamon Ding .win_data = rk3528_win_data, 63695fa6e665SDamon Ding .plane_mask = rk3528_vp_plane_mask[0], 63705fa6e665SDamon Ding .plane_table = rk3528_plane_table, 63715fa6e665SDamon Ding .vp_primary_plane_order = rk3528_vp_primary_plane_order, 63725fa6e665SDamon Ding .nr_layers = 5, 63735fa6e665SDamon Ding .nr_mixers = 3, 63745fa6e665SDamon Ding .nr_gammas = 2, 63755fa6e665SDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE, 637672388c26SDamon Ding .dump_regs = rk3528_dump_regs, 637772388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3528_dump_regs), 63789c7848c3SDamon Ding .ops = &rk3528_vop_ops, 63799c7848c3SDamon Ding 638072388c26SDamon Ding }; 638172388c26SDamon Ding 638272388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = { 638372388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 638472388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 638572388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 638672388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 638772388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 638872388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 638972388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 639072388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 639172388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 639272388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 63935fa6e665SDamon Ding }; 63945fa6e665SDamon Ding 6395452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 6396452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, 6397452afb13SDamon Ding ROCKCHIP_VOP2_ESMART1, 6398452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, 6399452afb13SDamon Ding ROCKCHIP_VOP2_ESMART3, 6400452afb13SDamon Ding }; 6401452afb13SDamon Ding 6402452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 6403452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 6404452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 6405452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 6406452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 6407452afb13SDamon Ding }; 6408452afb13SDamon Ding 6409452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 6410452afb13SDamon Ding { /* one display policy for hdmi */ 6411452afb13SDamon Ding {/* main display */ 6412452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6413452afb13SDamon Ding .attached_layers_nr = 4, 6414452afb13SDamon Ding .attached_layers = { 6415452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, 6416452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 6417452afb13SDamon Ding }, 6418452afb13SDamon Ding }, 6419452afb13SDamon Ding {/* second display */}, 6420452afb13SDamon Ding {/* third display */}, 6421452afb13SDamon Ding {/* fourth display */}, 6422452afb13SDamon Ding }, 6423452afb13SDamon Ding 6424452afb13SDamon Ding { /* two display policy */ 6425452afb13SDamon Ding {/* main display */ 6426452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6427452afb13SDamon Ding .attached_layers_nr = 2, 6428452afb13SDamon Ding .attached_layers = { 6429452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 6430452afb13SDamon Ding }, 6431452afb13SDamon Ding }, 6432452afb13SDamon Ding 6433452afb13SDamon Ding {/* second display */ 6434452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 6435452afb13SDamon Ding .attached_layers_nr = 2, 6436452afb13SDamon Ding .attached_layers = { 6437452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 6438452afb13SDamon Ding }, 6439452afb13SDamon Ding }, 6440452afb13SDamon Ding {/* third display */}, 6441452afb13SDamon Ding {/* fourth display */}, 6442452afb13SDamon Ding }, 6443452afb13SDamon Ding 6444452afb13SDamon Ding {/* reserved */}, 6445452afb13SDamon Ding }; 6446452afb13SDamon Ding 6447452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = { 6448452afb13SDamon Ding { 6449452afb13SDamon Ding .name = "Esmart0", 6450452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 6451452afb13SDamon Ding .type = ESMART_LAYER, 6452452afb13SDamon Ding .win_sel_port_offset = 8, 6453452afb13SDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 6454452afb13SDamon Ding .reg_offset = 0, 6455452afb13SDamon Ding .axi_id = 0, 6456452afb13SDamon Ding .axi_yrgb_id = 0x02, 6457452afb13SDamon Ding .axi_uv_id = 0x03, 6458452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6459452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6460452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6461452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6462*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0), 6463452afb13SDamon Ding .max_upscale_factor = 8, 6464452afb13SDamon Ding .max_downscale_factor = 8, 6465452afb13SDamon Ding }, 6466452afb13SDamon Ding 6467452afb13SDamon Ding { 6468452afb13SDamon Ding .name = "Esmart1", 6469452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 6470452afb13SDamon Ding .type = ESMART_LAYER, 6471452afb13SDamon Ding .win_sel_port_offset = 10, 6472452afb13SDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 6473452afb13SDamon Ding .reg_offset = 0x200, 6474452afb13SDamon Ding .axi_id = 0, 6475452afb13SDamon Ding .axi_yrgb_id = 0x04, 6476452afb13SDamon Ding .axi_uv_id = 0x05, 6477452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6478452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6479452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6480452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6481*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0), 6482452afb13SDamon Ding .max_upscale_factor = 8, 6483452afb13SDamon Ding .max_downscale_factor = 8, 6484452afb13SDamon Ding }, 6485452afb13SDamon Ding 6486452afb13SDamon Ding { 6487452afb13SDamon Ding .name = "Esmart2", 6488452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 6489452afb13SDamon Ding .type = ESMART_LAYER, 6490452afb13SDamon Ding .win_sel_port_offset = 12, 6491452afb13SDamon Ding .layer_sel_win_id = { 2, 2, 0xff, 0xff }, 6492452afb13SDamon Ding .reg_offset = 0x400, 6493452afb13SDamon Ding .axi_id = 0, 6494452afb13SDamon Ding .axi_yrgb_id = 0x06, 6495452afb13SDamon Ding .axi_uv_id = 0x07, 6496452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6497452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6498452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6499452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6500*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0), 6501452afb13SDamon Ding .max_upscale_factor = 8, 6502452afb13SDamon Ding .max_downscale_factor = 8, 6503452afb13SDamon Ding }, 6504452afb13SDamon Ding 6505452afb13SDamon Ding { 6506452afb13SDamon Ding .name = "Esmart3", 6507452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 6508452afb13SDamon Ding .type = ESMART_LAYER, 6509452afb13SDamon Ding .win_sel_port_offset = 14, 6510452afb13SDamon Ding .layer_sel_win_id = { 3, 3, 0xff, 0xff }, 6511452afb13SDamon Ding .reg_offset = 0x600, 6512452afb13SDamon Ding .axi_id = 0, 6513452afb13SDamon Ding .axi_yrgb_id = 0x08, 6514452afb13SDamon Ding .axi_uv_id = 0x0d, 6515452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6516452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6517452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6518452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6519*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0), 6520452afb13SDamon Ding .max_upscale_factor = 8, 6521452afb13SDamon Ding .max_downscale_factor = 8, 6522452afb13SDamon Ding }, 6523452afb13SDamon Ding }; 6524452afb13SDamon Ding 6525452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = { 6526452afb13SDamon Ding { 6527452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6528452afb13SDamon Ding .max_output = {2048, 4096}, 652953d536adSDamon Ding .win_dly = 6, 6530452afb13SDamon Ding .layer_mix_dly = 8, 6531452afb13SDamon Ding }, 6532452afb13SDamon Ding { 6533452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6534452afb13SDamon Ding .max_output = {2048, 1080}, 6535452afb13SDamon Ding .win_dly = 8, 6536452afb13SDamon Ding .layer_mix_dly = 8, 6537452afb13SDamon Ding }, 6538452afb13SDamon Ding }; 6539452afb13SDamon Ding 65409c7848c3SDamon Ding static const struct vop2_ops rk3562_vop_ops = { 65419c7848c3SDamon Ding .setup_win_dly = rk3528_setup_win_dly, 6542b7195f56SDamon Ding .setup_overlay = rk3528_setup_overlay, 65439c7848c3SDamon Ding }; 65449c7848c3SDamon Ding 6545452afb13SDamon Ding const struct vop2_data rk3562_vop = { 6546452afb13SDamon Ding .version = VOP_VERSION_RK3562, 6547452afb13SDamon Ding .nr_vps = 2, 6548452afb13SDamon Ding .vp_data = rk3562_vp_data, 6549452afb13SDamon Ding .win_data = rk3562_win_data, 6550452afb13SDamon Ding .plane_mask = rk3562_vp_plane_mask[0], 6551452afb13SDamon Ding .plane_table = rk3562_plane_table, 6552452afb13SDamon Ding .vp_primary_plane_order = rk3562_vp_primary_plane_order, 6553452afb13SDamon Ding .nr_layers = 4, 6554452afb13SDamon Ding .nr_mixers = 3, 6555452afb13SDamon Ding .nr_gammas = 2, 6556452afb13SDamon Ding .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE, 655772388c26SDamon Ding .dump_regs = rk3562_dump_regs, 655872388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3562_dump_regs), 65599c7848c3SDamon Ding .ops = &rk3562_vop_ops, 656072388c26SDamon Ding }; 656172388c26SDamon Ding 656272388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = { 656372388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 656472388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 656572388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 656672388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 656772388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 656872388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 656972388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 657072388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 657172388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 657272388c26SDamon Ding { RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 657372388c26SDamon Ding { RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 657472388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 6575452afb13SDamon Ding }; 6576452afb13SDamon Ding 6577337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 6578337d1c13SDamon Ding ROCKCHIP_VOP2_SMART0, 6579337d1c13SDamon Ding ROCKCHIP_VOP2_SMART1, 6580337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 6581337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 6582337d1c13SDamon Ding }; 6583337d1c13SDamon Ding 6584ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 6585ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 6586ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 6587ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 6588ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 6589ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 6590ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 6591ee008497SSandy Huang }; 6592ee008497SSandy Huang 6593b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 6594b0989546SSandy Huang { /* one display policy */ 6595b0989546SSandy Huang {/* main display */ 6596b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6597b0989546SSandy Huang .attached_layers_nr = 6, 6598b0989546SSandy Huang .attached_layers = { 6599b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 6600b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 6601b0989546SSandy Huang }, 6602b0989546SSandy Huang }, 6603b0989546SSandy Huang {/* second display */}, 6604b0989546SSandy Huang {/* third display */}, 6605b0989546SSandy Huang {/* fourth display */}, 6606b0989546SSandy Huang }, 6607b0989546SSandy Huang 6608b0989546SSandy Huang { /* two display policy */ 6609b0989546SSandy Huang {/* main display */ 6610b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6611b0989546SSandy Huang .attached_layers_nr = 3, 6612b0989546SSandy Huang .attached_layers = { 6613b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 6614b0989546SSandy Huang }, 6615b0989546SSandy Huang }, 6616b0989546SSandy Huang 6617b0989546SSandy Huang {/* second display */ 6618b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 6619b0989546SSandy Huang .attached_layers_nr = 3, 6620b0989546SSandy Huang .attached_layers = { 6621b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 6622b0989546SSandy Huang }, 6623b0989546SSandy Huang }, 6624b0989546SSandy Huang {/* third display */}, 6625b0989546SSandy Huang {/* fourth display */}, 6626b0989546SSandy Huang }, 6627b0989546SSandy Huang 6628b0989546SSandy Huang { /* three display policy */ 6629b0989546SSandy Huang {/* main display */ 6630b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6631b0989546SSandy Huang .attached_layers_nr = 3, 6632b0989546SSandy Huang .attached_layers = { 6633b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 6634b0989546SSandy Huang }, 6635b0989546SSandy Huang }, 6636b0989546SSandy Huang 6637b0989546SSandy Huang {/* second display */ 6638b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 6639b0989546SSandy Huang .attached_layers_nr = 2, 6640b0989546SSandy Huang .attached_layers = { 6641b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 6642b0989546SSandy Huang }, 6643b0989546SSandy Huang }, 6644b0989546SSandy Huang 6645b0989546SSandy Huang {/* third display */ 6646b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 6647b0989546SSandy Huang .attached_layers_nr = 1, 6648b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 6649b0989546SSandy Huang }, 6650b0989546SSandy Huang 6651b0989546SSandy Huang {/* fourth display */}, 6652b0989546SSandy Huang }, 6653b0989546SSandy Huang 6654b0989546SSandy Huang {/* reserved for four display policy */}, 6655b0989546SSandy Huang }; 6656b0989546SSandy Huang 6657b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = { 6658b0989546SSandy Huang { 6659b0989546SSandy Huang .name = "Cluster0", 6660b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0, 6661ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 6662b0989546SSandy Huang .win_sel_port_offset = 0, 66635fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0xff }, 6664b0989546SSandy Huang .reg_offset = 0, 66655fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 66665fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 66675fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 66685fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6669*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 66704c765862SDamon Ding .max_upscale_factor = 4, 66714c765862SDamon Ding .max_downscale_factor = 4, 66729c7848c3SDamon Ding .dly = { 0, 27, 21 }, 6673b0989546SSandy Huang }, 6674b0989546SSandy Huang 6675b0989546SSandy Huang { 6676b0989546SSandy Huang .name = "Cluster1", 6677b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1, 6678ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 6679b0989546SSandy Huang .win_sel_port_offset = 1, 66805fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 0xff }, 6681b0989546SSandy Huang .reg_offset = 0x200, 66825fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 66835fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 66845fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 66855fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6686*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 66874c765862SDamon Ding .max_upscale_factor = 4, 66884c765862SDamon Ding .max_downscale_factor = 4, 66891c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_CLUSTER0, 66901c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 66919c7848c3SDamon Ding .dly = { 0, 27, 21 }, 6692b0989546SSandy Huang }, 6693b0989546SSandy Huang 6694b0989546SSandy Huang { 6695b0989546SSandy Huang .name = "Esmart0", 6696b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0, 6697ecc31b6eSAndy Yan .type = ESMART_LAYER, 6698b0989546SSandy Huang .win_sel_port_offset = 4, 66995fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 0xff }, 6700b0989546SSandy Huang .reg_offset = 0, 67015fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 67025fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 67035fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 67045fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6705*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 67064c765862SDamon Ding .max_upscale_factor = 8, 67074c765862SDamon Ding .max_downscale_factor = 8, 67089c7848c3SDamon Ding .dly = { 20, 47, 41 }, 6709b0989546SSandy Huang }, 6710b0989546SSandy Huang 6711b0989546SSandy Huang { 6712b0989546SSandy Huang .name = "Esmart1", 6713b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1, 6714ecc31b6eSAndy Yan .type = ESMART_LAYER, 6715b0989546SSandy Huang .win_sel_port_offset = 5, 67165fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 0xff }, 6717b0989546SSandy Huang .reg_offset = 0x200, 67185fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 67195fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 67205fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 67215fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6722*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 67234c765862SDamon Ding .max_upscale_factor = 8, 67244c765862SDamon Ding .max_downscale_factor = 8, 67259c7848c3SDamon Ding .dly = { 20, 47, 41 }, 67261c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_ESMART0, 67271c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 6728b0989546SSandy Huang }, 6729b0989546SSandy Huang 6730b0989546SSandy Huang { 6731b0989546SSandy Huang .name = "Smart0", 6732b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0, 6733ecc31b6eSAndy Yan .type = SMART_LAYER, 6734b0989546SSandy Huang .win_sel_port_offset = 6, 67355fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 0xff }, 6736b0989546SSandy Huang .reg_offset = 0x400, 67375fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 67385fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 67395fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 67405fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6741*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 67424c765862SDamon Ding .max_upscale_factor = 8, 67434c765862SDamon Ding .max_downscale_factor = 8, 67449c7848c3SDamon Ding .dly = { 20, 47, 41 }, 6745b0989546SSandy Huang }, 6746b0989546SSandy Huang 6747b0989546SSandy Huang { 6748b0989546SSandy Huang .name = "Smart1", 6749b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1, 6750ecc31b6eSAndy Yan .type = SMART_LAYER, 6751b0989546SSandy Huang .win_sel_port_offset = 7, 67525fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 0xff }, 6753b0989546SSandy Huang .reg_offset = 0x600, 67545fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 67555fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 67565fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 67575fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6758*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 67594c765862SDamon Ding .max_upscale_factor = 8, 67604c765862SDamon Ding .max_downscale_factor = 8, 67619c7848c3SDamon Ding .dly = { 20, 47, 41 }, 67621c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_SMART0, 67631c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 6764b0989546SSandy Huang }, 6765b0989546SSandy Huang }; 6766b0989546SSandy Huang 676763cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = { 676863cb669fSSandy Huang { 676963cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT, 677063cb669fSSandy Huang .pre_scan_max_dly = 42, 677163cb669fSSandy Huang .max_output = {4096, 2304}, 6772d0408543SAndy Yan }, 677363cb669fSSandy Huang { 677463cb669fSSandy Huang .feature = 0, 677563cb669fSSandy Huang .pre_scan_max_dly = 40, 677663cb669fSSandy Huang .max_output = {2048, 1536}, 677763cb669fSSandy Huang }, 677863cb669fSSandy Huang { 677963cb669fSSandy Huang .feature = 0, 678063cb669fSSandy Huang .pre_scan_max_dly = 40, 678163cb669fSSandy Huang .max_output = {1920, 1080}, 678263cb669fSSandy Huang }, 678363cb669fSSandy Huang }; 6784d0408543SAndy Yan 67859c7848c3SDamon Ding static const struct vop2_ops rk3568_vop_ops = { 67869c7848c3SDamon Ding .setup_win_dly = rk3568_setup_win_dly, 6787b7195f56SDamon Ding .setup_overlay = rk3568_setup_overlay, 67889c7848c3SDamon Ding }; 67899c7848c3SDamon Ding 679063cb669fSSandy Huang const struct vop2_data rk3568_vop = { 6791ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568, 679263cb669fSSandy Huang .nr_vps = 3, 679363cb669fSSandy Huang .vp_data = rk3568_vp_data, 6794b0989546SSandy Huang .win_data = rk3568_win_data, 6795b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0], 6796ee008497SSandy Huang .plane_table = rk356x_plane_table, 6797337d1c13SDamon Ding .vp_primary_plane_order = rk3568_vp_primary_plane_order, 6798d0408543SAndy Yan .nr_layers = 6, 679963cb669fSSandy Huang .nr_mixers = 5, 68001147facaSSandy Huang .nr_gammas = 1, 680172388c26SDamon Ding .dump_regs = rk3568_dump_regs, 680272388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs), 68039c7848c3SDamon Ding .ops = &rk3568_vop_ops, 6804d0408543SAndy Yan }; 6805d0408543SAndy Yan 6806a552a69cSDamon Ding static u8 rk3576_vp_default_primary_plane[VOP2_VP_MAX] = { 6807a552a69cSDamon Ding ROCKCHIP_VOP2_ESMART0, 6808a552a69cSDamon Ding ROCKCHIP_VOP2_ESMART1, 6809a552a69cSDamon Ding ROCKCHIP_VOP2_ESMART2, 6810a552a69cSDamon Ding }; 6811a552a69cSDamon Ding 6812a552a69cSDamon Ding static struct vop2_plane_table rk3576_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 6813a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 6814a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 6815a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 6816a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 6817a552a69cSDamon Ding {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 6818a552a69cSDamon Ding {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 6819a552a69cSDamon Ding }; 6820a552a69cSDamon Ding 6821a552a69cSDamon Ding static struct vop2_dump_regs rk3576_dump_regs[] = { 6822a552a69cSDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 }, 6823a552a69cSDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 }, 6824a552a69cSDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 }, 6825a552a69cSDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 }, 6826a552a69cSDamon Ding { RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 }, 6827a552a69cSDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 6828a552a69cSDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 6829a552a69cSDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 6830a552a69cSDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 }, 6831a552a69cSDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 }, 6832a552a69cSDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 }, 6833a552a69cSDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 }, 6834a552a69cSDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 }, 6835a552a69cSDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 }, 6836a552a69cSDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 }, 6837a552a69cSDamon Ding }; 6838a552a69cSDamon Ding 6839a552a69cSDamon Ding /* 6840a552a69cSDamon Ding * RK3576 VOP with 2 Cluster win and 4 Esmart win. 6841a552a69cSDamon Ding * Every Esmart win support 4 multi-region. 6842a552a69cSDamon Ding * VP0 can use Cluster0/1 and Esmart0/2 6843a552a69cSDamon Ding * VP1 can use Cluster0/1 and Esmart1/3 6844a552a69cSDamon Ding * VP2 can use Esmart0/1/2/3 6845a552a69cSDamon Ding * 6846a552a69cSDamon Ding * Scale filter mode: 6847a552a69cSDamon Ding * 6848a552a69cSDamon Ding * * Cluster: 6849a552a69cSDamon Ding * * Support prescale down: 6850a552a69cSDamon Ding * * H/V: gt2/avg2 or gt4/avg4 6851a552a69cSDamon Ding * * After prescale down: 6852a552a69cSDamon Ding * * nearest-neighbor/bilinear/multi-phase filter for scale up 6853a552a69cSDamon Ding * * nearest-neighbor/bilinear/multi-phase filter for scale down 6854a552a69cSDamon Ding * 6855a552a69cSDamon Ding * * Esmart: 6856a552a69cSDamon Ding * * Support prescale down: 6857a552a69cSDamon Ding * * H: gt2/avg2 or gt4/avg4 6858a552a69cSDamon Ding * * V: gt2 or gt4 6859a552a69cSDamon Ding * * After prescale down: 6860a552a69cSDamon Ding * * nearest-neighbor/bilinear/bicubic for scale up 6861a552a69cSDamon Ding * * nearest-neighbor/bilinear for scale down 6862cc517d73SDamon Ding * 6863cc517d73SDamon Ding * AXI config:: 6864cc517d73SDamon Ding * 6865cc517d73SDamon Ding * * Cluster0 win0: 0xa, 0xb [AXI0] 6866cc517d73SDamon Ding * * Cluster0 win1: 0xc, 0xd [AXI0] 6867cc517d73SDamon Ding * * Cluster1 win0: 0x6, 0x7 [AXI0] 6868cc517d73SDamon Ding * * Cluster1 win1: 0x8, 0x9 [AXI0] 6869cc517d73SDamon Ding * * Esmart0: 0x10, 0x11 [AXI0] 6870cc517d73SDamon Ding * * Esmart1: 0x12, 0x13 [AXI0] 6871cc517d73SDamon Ding * * Esmart2: 0xa, 0xb [AXI1] 6872cc517d73SDamon Ding * * Esmart3: 0xc, 0xd [AXI1] 6873cc517d73SDamon Ding * * Lut dma rid: 0x1, 0x2, 0x3 [AXI0] 6874cc517d73SDamon Ding * * DCI dma rid: 0x4 [AXI0] 6875cc517d73SDamon Ding * * Metadata rid: 0x5 [AXI0] 6876cc517d73SDamon Ding * 6877cc517d73SDamon Ding * * Limit: 6878cc517d73SDamon Ding * * (1) 0x0 and 0xf can't be used; 6879cc517d73SDamon Ding * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf, 6880cc517d73SDamon Ding * * VOP will dead at the system bandwidth very terrible scene. 6881a552a69cSDamon Ding */ 6882a552a69cSDamon Ding static struct vop2_win_data rk3576_win_data[6] = { 6883a552a69cSDamon Ding { 6884a552a69cSDamon Ding .name = "Esmart0", 6885a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 6886a552a69cSDamon Ding .type = ESMART_LAYER, 6887a552a69cSDamon Ding .layer_sel_win_id = { 2, 0xff, 0, 0xff }, 6888a552a69cSDamon Ding .reg_offset = 0x0, 6889a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6890a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6891a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6892a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6893a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6894a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6895a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6896a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6897a552a69cSDamon Ding .axi_id = 0, 6898cc517d73SDamon Ding .axi_yrgb_id = 0x10, 6899cc517d73SDamon Ding .axi_uv_id = 0x11, 6900*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2), 6901a552a69cSDamon Ding .max_upscale_factor = 8, 6902a552a69cSDamon Ding .max_downscale_factor = 8, 6903a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH, 6904a552a69cSDamon Ding }, 6905a552a69cSDamon Ding { 6906a552a69cSDamon Ding .name = "Esmart1", 6907a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 6908a552a69cSDamon Ding .type = ESMART_LAYER, 6909a552a69cSDamon Ding .layer_sel_win_id = { 0xff, 2, 1, 0xff }, 6910a552a69cSDamon Ding .reg_offset = 0x200, 6911a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6912a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6913a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6914a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6915a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6916a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6917a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6918a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6919a552a69cSDamon Ding .axi_id = 0, 6920cc517d73SDamon Ding .axi_yrgb_id = 0x12, 6921cc517d73SDamon Ding .axi_uv_id = 0x13, 6922*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2), 6923a552a69cSDamon Ding .max_upscale_factor = 8, 6924a552a69cSDamon Ding .max_downscale_factor = 8, 6925a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA, 6926a552a69cSDamon Ding }, 6927a552a69cSDamon Ding 6928a552a69cSDamon Ding { 6929a552a69cSDamon Ding .name = "Esmart2", 6930a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 6931a552a69cSDamon Ding .type = ESMART_LAYER, 6932a552a69cSDamon Ding .layer_sel_win_id = { 3, 0xff, 2, 0xff }, 6933a552a69cSDamon Ding .reg_offset = 0x400, 6934a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6935a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6936a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6937a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6938a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6939a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6940a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6941a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6942a552a69cSDamon Ding .axi_id = 1, 6943a552a69cSDamon Ding .axi_yrgb_id = 0x0a, 6944a552a69cSDamon Ding .axi_uv_id = 0x0b, 6945*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2), 6946a552a69cSDamon Ding .max_upscale_factor = 8, 6947a552a69cSDamon Ding .max_downscale_factor = 8, 6948a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA, 6949a552a69cSDamon Ding }, 6950a552a69cSDamon Ding 6951a552a69cSDamon Ding { 6952a552a69cSDamon Ding .name = "Esmart3", 6953a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 6954a552a69cSDamon Ding .type = ESMART_LAYER, 6955a552a69cSDamon Ding .layer_sel_win_id = { 0xff, 3, 3, 0xff }, 6956a552a69cSDamon Ding .reg_offset = 0x600, 6957a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6958a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6959a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6960a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6961a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6962a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6963a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6964a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6965a552a69cSDamon Ding .axi_id = 1, 6966a552a69cSDamon Ding .axi_yrgb_id = 0x0c, 6967a552a69cSDamon Ding .axi_uv_id = 0x0d, 6968*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2), 6969a552a69cSDamon Ding .max_upscale_factor = 8, 6970a552a69cSDamon Ding .max_downscale_factor = 8, 6971a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA, 6972a552a69cSDamon Ding }, 6973a552a69cSDamon Ding 6974a552a69cSDamon Ding { 6975a552a69cSDamon Ding .name = "Cluster0", 6976a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0, 6977a552a69cSDamon Ding .type = CLUSTER_LAYER, 6978a552a69cSDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 6979a552a69cSDamon Ding .reg_offset = 0x0, 6980a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, 6981a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIL, 6982a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6983a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6984a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6985a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6986a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6987a552a69cSDamon Ding .pd_id = VOP2_PD_CLUSTER, 6988cc517d73SDamon Ding .axi_yrgb_id = 0x0a, 6989cc517d73SDamon Ding .axi_uv_id = 0x0b, 6990*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1), 6991a552a69cSDamon Ding .max_upscale_factor = 8, 6992a552a69cSDamon Ding .max_downscale_factor = 8, 6993a552a69cSDamon Ding .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | 6994a552a69cSDamon Ding WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI, 6995a552a69cSDamon Ding }, 6996a552a69cSDamon Ding 6997a552a69cSDamon Ding { 6998a552a69cSDamon Ding .name = "Cluster1", 6999a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER1, 7000a552a69cSDamon Ding .type = CLUSTER_LAYER, 7001a552a69cSDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 7002a552a69cSDamon Ding .reg_offset = 0x200, 7003a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, 7004a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIL, 7005a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7006a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7007a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7008a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7009a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7010a552a69cSDamon Ding .pd_id = VOP2_PD_CLUSTER, 7011a552a69cSDamon Ding .axi_yrgb_id = 0x06, 7012a552a69cSDamon Ding .axi_uv_id = 0x07, 7013*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1), 7014a552a69cSDamon Ding .max_upscale_factor = 8, 7015a552a69cSDamon Ding .max_downscale_factor = 8, 7016a552a69cSDamon Ding .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | 7017a552a69cSDamon Ding WIN_FEATURE_Y2R_13BIT_DEPTH, 7018a552a69cSDamon Ding }, 7019a552a69cSDamon Ding }; 7020a552a69cSDamon Ding 702144b1b62cSDamon Ding /* 702244b1b62cSDamon Ding * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4, 702344b1b62cSDamon Ding * the urgency signal will be set to 1, when full post line buffer is over 6, the 702444b1b62cSDamon Ding * urgency signal will be set to 0. 702544b1b62cSDamon Ding */ 702644b1b62cSDamon Ding static struct vop_urgency rk3576_vp0_urgency = { 702744b1b62cSDamon Ding .urgen_thl = 4, 702844b1b62cSDamon Ding .urgen_thh = 6, 702944b1b62cSDamon Ding }; 703044b1b62cSDamon Ding 7031a552a69cSDamon Ding static struct vop2_vp_data rk3576_vp_data[3] = { 7032a552a69cSDamon Ding { 7033a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR | 7034a552a69cSDamon Ding VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT | 7035a552a69cSDamon Ding VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP, 7036a552a69cSDamon Ding .max_output = { 4096, 4096 }, 7037a552a69cSDamon Ding .hdrvivid_dly = 21, 7038a552a69cSDamon Ding .sdr2hdr_dly = 21, 7039a552a69cSDamon Ding .layer_mix_dly = 8, 7040a552a69cSDamon Ding .hdr_mix_dly = 2, 7041a552a69cSDamon Ding .win_dly = 10, 7042a552a69cSDamon Ding .pixel_rate = 2, 704344b1b62cSDamon Ding .urgency = &rk3576_vp0_urgency, 7044a552a69cSDamon Ding }, 7045a552a69cSDamon Ding { 7046a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | 7047a552a69cSDamon Ding VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2, 7048a552a69cSDamon Ding .max_output = { 2560, 2560 }, 7049a552a69cSDamon Ding .hdrvivid_dly = 0, 7050a552a69cSDamon Ding .sdr2hdr_dly = 0, 7051a552a69cSDamon Ding .layer_mix_dly = 6, 7052a552a69cSDamon Ding .hdr_mix_dly = 0, 7053a552a69cSDamon Ding .win_dly = 10, 7054a552a69cSDamon Ding .pixel_rate = 1, 7055a552a69cSDamon Ding }, 7056a552a69cSDamon Ding { 7057a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 7058a552a69cSDamon Ding .max_output = { 1920, 1920 }, 7059a552a69cSDamon Ding .hdrvivid_dly = 0, 7060a552a69cSDamon Ding .sdr2hdr_dly = 0, 7061a552a69cSDamon Ding .layer_mix_dly = 6, 7062a552a69cSDamon Ding .hdr_mix_dly = 0, 7063a552a69cSDamon Ding .win_dly = 10, 7064a552a69cSDamon Ding .pixel_rate = 1, 7065a552a69cSDamon Ding }, 7066a552a69cSDamon Ding }; 7067a552a69cSDamon Ding 7068a552a69cSDamon Ding static struct vop2_power_domain_data rk3576_vop_pd_data[] = { 7069a552a69cSDamon Ding { 7070a552a69cSDamon Ding .id = VOP2_PD_CLUSTER, 7071a552a69cSDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1), 7072a552a69cSDamon Ding }, 7073a552a69cSDamon Ding { 7074a552a69cSDamon Ding .id = VOP2_PD_ESMART, 7075a552a69cSDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | 7076a552a69cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3), 7077a552a69cSDamon Ding }, 7078a552a69cSDamon Ding }; 7079a552a69cSDamon Ding 7080a552a69cSDamon Ding static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = { 7081a552a69cSDamon Ding {VOP3_ESMART_4K_4K_4K_MODE, 2}, 7082a552a69cSDamon Ding {VOP3_ESMART_4K_4K_2K_2K_MODE, 3} 7083a552a69cSDamon Ding }; 7084a552a69cSDamon Ding 70859c7848c3SDamon Ding static const struct vop2_ops rk3576_vop_ops = { 70869c7848c3SDamon Ding .setup_win_dly = rk3576_setup_win_dly, 7087b7195f56SDamon Ding .setup_overlay = rk3576_setup_overlay, 70889c7848c3SDamon Ding }; 70899c7848c3SDamon Ding 7090a552a69cSDamon Ding const struct vop2_data rk3576_vop = { 7091a552a69cSDamon Ding .version = VOP_VERSION_RK3576, 7092a552a69cSDamon Ding .nr_vps = 3, 7093a552a69cSDamon Ding .nr_mixers = 4, 7094a552a69cSDamon Ding .nr_layers = 6, 7095a552a69cSDamon Ding .nr_gammas = 3, 7096a552a69cSDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE, 7097a552a69cSDamon Ding .esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map), 7098a552a69cSDamon Ding .esmart_lb_mode_map = rk3576_esmart_lb_mode_map, 7099a552a69cSDamon Ding .vp_data = rk3576_vp_data, 7100a552a69cSDamon Ding .win_data = rk3576_win_data, 7101a552a69cSDamon Ding .plane_table = rk3576_plane_table, 7102a552a69cSDamon Ding .pd = rk3576_vop_pd_data, 7103a552a69cSDamon Ding .vp_default_primary_plane = rk3576_vp_default_primary_plane, 7104a552a69cSDamon Ding .nr_pd = ARRAY_SIZE(rk3576_vop_pd_data), 7105a552a69cSDamon Ding .dump_regs = rk3576_dump_regs, 7106a552a69cSDamon Ding .dump_regs_size = ARRAY_SIZE(rk3576_dump_regs), 71079c7848c3SDamon Ding .ops = &rk3576_vop_ops, 7108a552a69cSDamon Ding }; 7109a552a69cSDamon Ding 7110337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 7111337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 7112337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 7113337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART2, 7114337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART3, 7115337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 7116337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER1, 7117337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER2, 7118337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER3, 7119337d1c13SDamon Ding }; 7120337d1c13SDamon Ding 7121ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 7122ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 7123ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 7124ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 7125ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 7126ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 7127ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 7128ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 7129ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 7130ecc31b6eSAndy Yan }; 7131ecc31b6eSAndy Yan 713272388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = { 713372388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 713472388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 713572388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 713672388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 713772388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 713872388c26SDamon Ding { RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 }, 713972388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 714072388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 714172388c26SDamon Ding { RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 }, 714272388c26SDamon Ding { RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 }, 714372388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 714472388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 714572388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 714672388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 714772388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 714872388c26SDamon Ding }; 714972388c26SDamon Ding 7150ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 7151ecc31b6eSAndy Yan { /* one display policy */ 7152ecc31b6eSAndy Yan {/* main display */ 7153608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 715483d6b087SDamon Ding .attached_layers_nr = 4, 7155ecc31b6eSAndy Yan .attached_layers = { 715683d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 715783d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 7158ecc31b6eSAndy Yan }, 7159ecc31b6eSAndy Yan }, 716083d6b087SDamon Ding 716183d6b087SDamon Ding {/* planes for the splice mode */ 716283d6b087SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 716383d6b087SDamon Ding .attached_layers_nr = 4, 716483d6b087SDamon Ding .attached_layers = { 716583d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, 716683d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 716783d6b087SDamon Ding }, 716883d6b087SDamon Ding }, 7169ecc31b6eSAndy Yan {/* third display */}, 7170ecc31b6eSAndy Yan {/* fourth display */}, 7171ecc31b6eSAndy Yan }, 7172ecc31b6eSAndy Yan 7173ecc31b6eSAndy Yan { /* two display policy */ 7174ecc31b6eSAndy Yan {/* main display */ 7175608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 7176ecc31b6eSAndy Yan .attached_layers_nr = 4, 7177ecc31b6eSAndy Yan .attached_layers = { 7178ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 717983d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 7180ecc31b6eSAndy Yan }, 7181ecc31b6eSAndy Yan }, 7182ecc31b6eSAndy Yan 7183ecc31b6eSAndy Yan {/* second display */ 718483d6b087SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 7185ecc31b6eSAndy Yan .attached_layers_nr = 4, 7186ecc31b6eSAndy Yan .attached_layers = { 718783d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, 7188ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 7189ecc31b6eSAndy Yan }, 7190ecc31b6eSAndy Yan }, 7191ecc31b6eSAndy Yan {/* third display */}, 7192ecc31b6eSAndy Yan {/* fourth display */}, 7193ecc31b6eSAndy Yan }, 7194ecc31b6eSAndy Yan 7195ecc31b6eSAndy Yan { /* three display policy */ 7196ecc31b6eSAndy Yan {/* main display */ 7197608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 7198ecc31b6eSAndy Yan .attached_layers_nr = 3, 7199ecc31b6eSAndy Yan .attached_layers = { 720083d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER2, 720183d6b087SDamon Ding ROCKCHIP_VOP2_ESMART0 7202ecc31b6eSAndy Yan }, 7203ecc31b6eSAndy Yan }, 7204ecc31b6eSAndy Yan 7205ecc31b6eSAndy Yan {/* second display */ 7206608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 7207ecc31b6eSAndy Yan .attached_layers_nr = 3, 7208ecc31b6eSAndy Yan .attached_layers = { 720983d6b087SDamon Ding ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_CLUSTER3, 721083d6b087SDamon Ding ROCKCHIP_VOP2_ESMART1 7211ecc31b6eSAndy Yan }, 7212ecc31b6eSAndy Yan }, 7213ecc31b6eSAndy Yan 7214ecc31b6eSAndy Yan {/* third display */ 7215ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 7216ecc31b6eSAndy Yan .attached_layers_nr = 2, 7217ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 7218ecc31b6eSAndy Yan }, 7219ecc31b6eSAndy Yan 7220ecc31b6eSAndy Yan {/* fourth display */}, 7221ecc31b6eSAndy Yan }, 7222ecc31b6eSAndy Yan 7223ecc31b6eSAndy Yan { /* four display policy */ 7224ecc31b6eSAndy Yan {/* main display */ 7225608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 7226ecc31b6eSAndy Yan .attached_layers_nr = 2, 7227ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 7228ecc31b6eSAndy Yan }, 7229ecc31b6eSAndy Yan 7230ecc31b6eSAndy Yan {/* second display */ 7231608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 7232ecc31b6eSAndy Yan .attached_layers_nr = 2, 7233ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 7234ecc31b6eSAndy Yan }, 7235ecc31b6eSAndy Yan 7236ecc31b6eSAndy Yan {/* third display */ 7237608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 7238ecc31b6eSAndy Yan .attached_layers_nr = 2, 7239ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 7240ecc31b6eSAndy Yan }, 7241ecc31b6eSAndy Yan 7242ecc31b6eSAndy Yan {/* fourth display */ 7243608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 7244ecc31b6eSAndy Yan .attached_layers_nr = 2, 7245ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 7246ecc31b6eSAndy Yan }, 7247ecc31b6eSAndy Yan }, 7248ecc31b6eSAndy Yan 7249ecc31b6eSAndy Yan }; 7250ecc31b6eSAndy Yan 7251ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = { 7252ecc31b6eSAndy Yan { 7253ecc31b6eSAndy Yan .name = "Cluster0", 7254ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0, 7255ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER1, 7256ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7257ecc31b6eSAndy Yan .win_sel_port_offset = 0, 72585fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0 }, 7259ecc31b6eSAndy Yan .reg_offset = 0, 7260a33b790fSDamon Ding .axi_id = 0, 7261a33b790fSDamon Ding .axi_yrgb_id = 2, 7262a33b790fSDamon Ding .axi_uv_id = 3, 7263b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER0, 72645fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 72655fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 72665fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 72675fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7268*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 72694c765862SDamon Ding .max_upscale_factor = 4, 72704c765862SDamon Ding .max_downscale_factor = 4, 72719c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7272ecc31b6eSAndy Yan }, 7273ecc31b6eSAndy Yan 7274ecc31b6eSAndy Yan { 7275ecc31b6eSAndy Yan .name = "Cluster1", 7276ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1, 7277ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7278ecc31b6eSAndy Yan .win_sel_port_offset = 1, 72795fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 1 }, 7280ecc31b6eSAndy Yan .reg_offset = 0x200, 7281a33b790fSDamon Ding .axi_id = 0, 7282a33b790fSDamon Ding .axi_yrgb_id = 6, 7283a33b790fSDamon Ding .axi_uv_id = 7, 7284b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER1, 72855fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 72865fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 72875fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 72885fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7289*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 72904c765862SDamon Ding .max_upscale_factor = 4, 72914c765862SDamon Ding .max_downscale_factor = 4, 72929c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7293ecc31b6eSAndy Yan }, 7294ecc31b6eSAndy Yan 7295ecc31b6eSAndy Yan { 7296ecc31b6eSAndy Yan .name = "Cluster2", 7297ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2, 7298ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER3, 7299ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7300ecc31b6eSAndy Yan .win_sel_port_offset = 2, 73015fa6e665SDamon Ding .layer_sel_win_id = { 4, 4, 4, 4 }, 7302ecc31b6eSAndy Yan .reg_offset = 0x400, 7303a33b790fSDamon Ding .axi_id = 1, 7304a33b790fSDamon Ding .axi_yrgb_id = 2, 7305a33b790fSDamon Ding .axi_uv_id = 3, 7306b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER2, 73075fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 73085fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 73095fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 73105fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7311*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 73124c765862SDamon Ding .max_upscale_factor = 4, 73134c765862SDamon Ding .max_downscale_factor = 4, 73149c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7315ecc31b6eSAndy Yan }, 7316ecc31b6eSAndy Yan 7317ecc31b6eSAndy Yan { 7318ecc31b6eSAndy Yan .name = "Cluster3", 7319ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3, 7320ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7321ecc31b6eSAndy Yan .win_sel_port_offset = 3, 73225fa6e665SDamon Ding .layer_sel_win_id = { 5, 5, 5, 5 }, 7323ecc31b6eSAndy Yan .reg_offset = 0x600, 7324a33b790fSDamon Ding .axi_id = 1, 7325a33b790fSDamon Ding .axi_yrgb_id = 6, 7326a33b790fSDamon Ding .axi_uv_id = 7, 7327b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER3, 73285fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 73295fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 73305fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 73315fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7332*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 73334c765862SDamon Ding .max_upscale_factor = 4, 73344c765862SDamon Ding .max_downscale_factor = 4, 73359c7848c3SDamon Ding .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7336ecc31b6eSAndy Yan }, 7337ecc31b6eSAndy Yan 7338ecc31b6eSAndy Yan { 7339ecc31b6eSAndy Yan .name = "Esmart0", 7340ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0, 7341ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART1, 7342ecc31b6eSAndy Yan .type = ESMART_LAYER, 7343ecc31b6eSAndy Yan .win_sel_port_offset = 4, 73445fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 2 }, 7345ecc31b6eSAndy Yan .reg_offset = 0, 7346a33b790fSDamon Ding .axi_id = 0, 7347a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 7348a33b790fSDamon Ding .axi_uv_id = 0x0b, 73495fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 73505fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 73515fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 73525fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7353*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 73544c765862SDamon Ding .max_upscale_factor = 8, 73554c765862SDamon Ding .max_downscale_factor = 8, 73569c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7357ecc31b6eSAndy Yan }, 7358ecc31b6eSAndy Yan 7359ecc31b6eSAndy Yan { 7360ecc31b6eSAndy Yan .name = "Esmart1", 7361ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1, 7362ecc31b6eSAndy Yan .type = ESMART_LAYER, 7363ecc31b6eSAndy Yan .win_sel_port_offset = 5, 73645fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 3 }, 7365ecc31b6eSAndy Yan .reg_offset = 0x200, 7366a33b790fSDamon Ding .axi_id = 0, 7367a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 7368a33b790fSDamon Ding .axi_uv_id = 0x0d, 7369b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 73705fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 73715fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 73725fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 73735fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7374*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 73754c765862SDamon Ding .max_upscale_factor = 8, 73764c765862SDamon Ding .max_downscale_factor = 8, 73779c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7378ecc31b6eSAndy Yan }, 7379ecc31b6eSAndy Yan 7380ecc31b6eSAndy Yan { 7381ecc31b6eSAndy Yan .name = "Esmart2", 7382ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2, 7383ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART3, 7384ecc31b6eSAndy Yan .type = ESMART_LAYER, 7385ecc31b6eSAndy Yan .win_sel_port_offset = 6, 73865fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 6 }, 7387ecc31b6eSAndy Yan .reg_offset = 0x400, 7388a33b790fSDamon Ding .axi_id = 1, 7389a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 7390a33b790fSDamon Ding .axi_uv_id = 0x0b, 7391b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 73925fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 73935fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 73945fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 73955fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7396*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 73974c765862SDamon Ding .max_upscale_factor = 8, 73984c765862SDamon Ding .max_downscale_factor = 8, 73999c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7400ecc31b6eSAndy Yan }, 7401ecc31b6eSAndy Yan 7402ecc31b6eSAndy Yan { 7403ecc31b6eSAndy Yan .name = "Esmart3", 7404ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3, 7405ecc31b6eSAndy Yan .type = ESMART_LAYER, 7406ecc31b6eSAndy Yan .win_sel_port_offset = 7, 74075fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 7 }, 7408ecc31b6eSAndy Yan .reg_offset = 0x600, 7409a33b790fSDamon Ding .axi_id = 1, 7410a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 7411a33b790fSDamon Ding .axi_uv_id = 0x0d, 7412b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 74135fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 74145fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 74155fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 74165fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7417*13bc92e8SDamon Ding .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 74184c765862SDamon Ding .max_upscale_factor = 8, 74194c765862SDamon Ding .max_downscale_factor = 8, 74209c7848c3SDamon Ding .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7421ecc31b6eSAndy Yan }, 7422ecc31b6eSAndy Yan }; 7423ecc31b6eSAndy Yan 742412ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = { 742512ee5af0SDamon Ding {0x00000000, "no error detected by DSC encoder"}, 742612ee5af0SDamon Ding {0x0030ffff, "bits per component error"}, 742712ee5af0SDamon Ding {0x0040ffff, "multiple mode error"}, 742812ee5af0SDamon Ding {0x0050ffff, "line buffer depth error"}, 742912ee5af0SDamon Ding {0x0060ffff, "minor version error"}, 743012ee5af0SDamon Ding {0x0070ffff, "picture height error"}, 743112ee5af0SDamon Ding {0x0080ffff, "picture width error"}, 743212ee5af0SDamon Ding {0x0090ffff, "number of slices error"}, 743312ee5af0SDamon Ding {0x00c0ffff, "slice height Error "}, 743412ee5af0SDamon Ding {0x00d0ffff, "slice width error"}, 743512ee5af0SDamon Ding {0x00e0ffff, "second line BPG offset error"}, 743612ee5af0SDamon Ding {0x00f0ffff, "non second line BPG offset error"}, 743712ee5af0SDamon Ding {0x0100ffff, "PPS ID error"}, 743812ee5af0SDamon Ding {0x0110ffff, "bits per pixel (BPP) Error"}, 743912ee5af0SDamon Ding {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */ 744012ee5af0SDamon Ding 744112ee5af0SDamon Ding {0x01510001, "slice 0 RC buffer model overflow error"}, 744212ee5af0SDamon Ding {0x01510002, "slice 1 RC buffer model overflow error"}, 744312ee5af0SDamon Ding {0x01510004, "slice 2 RC buffer model overflow error"}, 744412ee5af0SDamon Ding {0x01510008, "slice 3 RC buffer model overflow error"}, 744512ee5af0SDamon Ding {0x01510010, "slice 4 RC buffer model overflow error"}, 744612ee5af0SDamon Ding {0x01510020, "slice 5 RC buffer model overflow error"}, 744712ee5af0SDamon Ding {0x01510040, "slice 6 RC buffer model overflow error"}, 744812ee5af0SDamon Ding {0x01510080, "slice 7 RC buffer model overflow error"}, 744912ee5af0SDamon Ding 745012ee5af0SDamon Ding {0x01610001, "slice 0 RC buffer model underflow error"}, 745112ee5af0SDamon Ding {0x01610002, "slice 1 RC buffer model underflow error"}, 745212ee5af0SDamon Ding {0x01610004, "slice 2 RC buffer model underflow error"}, 745312ee5af0SDamon Ding {0x01610008, "slice 3 RC buffer model underflow error"}, 745412ee5af0SDamon Ding {0x01610010, "slice 4 RC buffer model underflow error"}, 745512ee5af0SDamon Ding {0x01610020, "slice 5 RC buffer model underflow error"}, 745612ee5af0SDamon Ding {0x01610040, "slice 6 RC buffer model underflow error"}, 745712ee5af0SDamon Ding {0x01610080, "slice 7 RC buffer model underflow error"}, 745812ee5af0SDamon Ding 745912ee5af0SDamon Ding {0xffffffff, "unsuccessful RESET cycle status"}, 746012ee5af0SDamon Ding {0x00a0ffff, "ICH full error precision settings error"}, 746112ee5af0SDamon Ding {0x0020ffff, "native mode"}, 746212ee5af0SDamon Ding }; 746312ee5af0SDamon Ding 746412ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = { 746512ee5af0SDamon Ding {0x00000000, "rate buffer status"}, 746612ee5af0SDamon Ding {0x00000001, "line buffer status"}, 746712ee5af0SDamon Ding {0x00000002, "decoder model status"}, 746812ee5af0SDamon Ding {0x00000003, "pixel buffer status"}, 746912ee5af0SDamon Ding {0x00000004, "balance fifo buffer status"}, 747012ee5af0SDamon Ding {0x00000005, "syntax element fifo status"}, 747112ee5af0SDamon Ding }; 747212ee5af0SDamon Ding 747312ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = { 747412ee5af0SDamon Ding { 747512ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_8K, 747612ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_8K, 747712ee5af0SDamon Ding .max_slice_num = 8, 747812ee5af0SDamon Ding .max_linebuf_depth = 11, 7479b61227a3SDamon Ding .min_bits_per_pixel = 8, 748012ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src", 748112ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_8k_txp_clk", 748212ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_8k_pxl_clk", 748312ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_8k_cds_clk", 748412ee5af0SDamon Ding }, 748512ee5af0SDamon Ding 748612ee5af0SDamon Ding { 748712ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_4K, 748812ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_4K, 748912ee5af0SDamon Ding .max_slice_num = 2, 749012ee5af0SDamon Ding .max_linebuf_depth = 11, 7491b61227a3SDamon Ding .min_bits_per_pixel = 8, 749212ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src", 749312ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_4k_txp_clk", 749412ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_4k_pxl_clk", 749512ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_4k_cds_clk", 749612ee5af0SDamon Ding }, 749712ee5af0SDamon Ding }; 749812ee5af0SDamon Ding 7499ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = { 7500ecc31b6eSAndy Yan { 7501ee01dbb2SDamon Ding .splice_vp_id = 1, 7502ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 7503b890760eSAlgea Cao .pre_scan_max_dly = 54, 7504ecc31b6eSAndy Yan .max_dclk = 600000, 7505ecc31b6eSAndy Yan .max_output = {7680, 4320}, 7506ecc31b6eSAndy Yan }, 7507ecc31b6eSAndy Yan { 7508ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 7509ee01dbb2SDamon Ding .pre_scan_max_dly = 54, 7510ecc31b6eSAndy Yan .max_dclk = 600000, 7511ecc31b6eSAndy Yan .max_output = {4096, 2304}, 7512ecc31b6eSAndy Yan }, 7513ecc31b6eSAndy Yan { 7514ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 7515ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 7516ecc31b6eSAndy Yan .max_dclk = 600000, 7517ecc31b6eSAndy Yan .max_output = {4096, 2304}, 7518ecc31b6eSAndy Yan }, 7519ecc31b6eSAndy Yan { 7520ecc31b6eSAndy Yan .feature = 0, 7521ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 7522ecc31b6eSAndy Yan .max_dclk = 200000, 7523ecc31b6eSAndy Yan .max_output = {1920, 1080}, 7524ecc31b6eSAndy Yan }, 7525ecc31b6eSAndy Yan }; 7526ecc31b6eSAndy Yan 7527b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = { 7528b6ba80b4SDamon Ding { 7529b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER0, 7530b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0), 7531b6ba80b4SDamon Ding }, 7532b6ba80b4SDamon Ding { 7533b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER1, 7534b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1), 7535b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 7536b6ba80b4SDamon Ding }, 7537b6ba80b4SDamon Ding { 7538b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER2, 7539b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2), 7540b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 7541b6ba80b4SDamon Ding }, 7542b6ba80b4SDamon Ding { 7543b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER3, 7544b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3), 7545b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 7546b6ba80b4SDamon Ding }, 7547b6ba80b4SDamon Ding { 7548b6ba80b4SDamon Ding .id = VOP2_PD_ESMART, 7549b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) | 7550b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | 7551b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART3), 7552b6ba80b4SDamon Ding }, 7553b6ba80b4SDamon Ding { 7554b6ba80b4SDamon Ding .id = VOP2_PD_DSC_8K, 7555b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K), 7556b6ba80b4SDamon Ding }, 7557b6ba80b4SDamon Ding { 7558b6ba80b4SDamon Ding .id = VOP2_PD_DSC_4K, 7559b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K), 7560b6ba80b4SDamon Ding }, 7561b6ba80b4SDamon Ding }; 7562b6ba80b4SDamon Ding 75639c7848c3SDamon Ding static const struct vop2_ops rk3588_vop_ops = { 75649c7848c3SDamon Ding .setup_win_dly = rk3568_setup_win_dly, 7565b7195f56SDamon Ding .setup_overlay = rk3568_setup_overlay, 75669c7848c3SDamon Ding }; 75679c7848c3SDamon Ding 7568ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = { 7569ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588, 7570ecc31b6eSAndy Yan .nr_vps = 4, 7571ecc31b6eSAndy Yan .vp_data = rk3588_vp_data, 7572ecc31b6eSAndy Yan .win_data = rk3588_win_data, 7573ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0], 7574ecc31b6eSAndy Yan .plane_table = rk3588_plane_table, 7575b6ba80b4SDamon Ding .pd = rk3588_vop_pd_data, 757612ee5af0SDamon Ding .dsc = rk3588_dsc_data, 757712ee5af0SDamon Ding .dsc_error_ecw = dsc_ecw, 757812ee5af0SDamon Ding .dsc_error_buffer_flow = dsc_buffer_flow, 7579337d1c13SDamon Ding .vp_primary_plane_order = rk3588_vp_primary_plane_order, 7580ecc31b6eSAndy Yan .nr_layers = 8, 7581ecc31b6eSAndy Yan .nr_mixers = 7, 7582ecc31b6eSAndy Yan .nr_gammas = 4, 7583b6ba80b4SDamon Ding .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data), 758412ee5af0SDamon Ding .nr_dscs = 2, 758512ee5af0SDamon Ding .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw), 758612ee5af0SDamon Ding .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow), 758772388c26SDamon Ding .dump_regs = rk3588_dump_regs, 758872388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs), 75899c7848c3SDamon Ding .ops = &rk3588_vop_ops, 7590ecc31b6eSAndy Yan }; 7591ecc31b6eSAndy Yan 7592d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 7593d0408543SAndy Yan .preinit = rockchip_vop2_preinit, 7594d0408543SAndy Yan .prepare = rockchip_vop2_prepare, 7595d0408543SAndy Yan .init = rockchip_vop2_init, 7596d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane, 7597d0408543SAndy Yan .enable = rockchip_vop2_enable, 7598efa01fe4SZhang Yubing .post_enable = rockchip_vop2_post_enable, 7599d0408543SAndy Yan .disable = rockchip_vop2_disable, 7600b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts, 76010675a2a4SDamon Ding .send_mcu_cmd = rockchip_vop2_send_mcu_cmd, 7602820a5c17SDamon Ding .check = rockchip_vop2_check, 760322007755SDamon Ding .mode_valid = rockchip_vop2_mode_valid, 7604b02eb70bSDamon Ding .mode_fixup = rockchip_vop2_mode_fixup, 76054c765862SDamon Ding .plane_check = rockchip_vop2_plane_check, 760672388c26SDamon Ding .regs_dump = rockchip_vop2_regs_dump, 760772388c26SDamon Ding .active_regs_dump = rockchip_vop2_active_regs_dump, 76088e7ef808SDamon Ding .apply_soft_te = rockchip_vop2_apply_soft_te, 7609d0408543SAndy Yan }; 7610