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 3125fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL 0x520 313452afb13SDamon Ding #define ESMART_DLY_NUM_MASK 0xff 314452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT 0 3155fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL 0x524 3165fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL 0x528 3175fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C 3185fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530 3195fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 3205fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 3215fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c 322a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540 323a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544 324a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548 325a552a69cSDamon Ding #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c 3265fa6e665SDamon Ding 3275fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL 0x600 32863cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600 329ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK 0x1 330ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT 0 33163cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 3325fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL 0x604 33363cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604 33463cb669fSSandy Huang #define LAYER_SEL_MASK 0xf 33563cb669fSSandy Huang 33663cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608 33763cb669fSSandy Huang #define PORT_MUX_MASK 0xf 33863cb669fSSandy Huang #define PORT_MUX_SHIFT 0 33963cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3 34063cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16 34163cb669fSSandy Huang 34263cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 34363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 34463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 34563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 3465fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620 3475fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624 3485fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628 3495fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C 3505fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630 3515fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634 3525fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638 3535fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C 3545fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640 3555fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644 3565fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648 3575fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C 35863cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 35963cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654 36063cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 36163cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 362a552a69cSDamon Ding #define RK3576_EXTRA_SRC_COLOR_CTRL 0x650 363a552a69cSDamon Ding #define RK3576_EXTRA_DST_COLOR_CTRL 0x654 364a552a69cSDamon Ding #define RK3576_EXTRA_SRC_ALPHA_CTRL 0x658 365a552a69cSDamon Ding #define RK3576_EXTRA_DST_ALPHA_CTRL 0x65C 3665fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL 0x660 3675fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL 0x664 3685fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL 0x668 3695fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL 0x66C 3705fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670 37163cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 37263cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 37363cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 37463cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 37563cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0 37663cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff 37763cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24 37863cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4 37963cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8 38063cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0 38163cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8 38263cb669fSSandy Huang 3835fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL 0x700 3845fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL 0x704 3855fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720 3865fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724 3875fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728 3885fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C 3895fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730 3905fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734 3915fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738 3925fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C 3935fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740 3945fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744 3955fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748 3965fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C 3975fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770 398a552a69cSDamon Ding #define RK3576_OVL_PORT2_CTRL 0x800 399a552a69cSDamon Ding #define RK3576_OVL_PORT2_LAYER_SEL 0x804 400a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL 0x820 401a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL 0x824 402a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL 0x828 403a552a69cSDamon Ding #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL 0x82C 404a552a69cSDamon Ding #define RK3576_OVL_PORT2_BG_MIX_CTRL 0x870 4055fa6e665SDamon Ding 406d0408543SAndy Yan /* Video Port registers definition */ 407d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00 408d0408543SAndy Yan #define OUT_MODE_MASK 0xf 409d0408543SAndy Yan #define OUT_MODE_SHIFT 0 41010ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f 41110ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8 41265747de7SDamon Ding #define DSP_BG_SWAP 0x1 41365747de7SDamon Ding #define DSP_RB_SWAP 0x2 41465747de7SDamon Ding #define DSP_RG_SWAP 0x4 41565747de7SDamon Ding #define DSP_DELTA_SWAP 0x8 41610ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4 417d0408543SAndy Yan #define P2I_EN_SHIFT 5 4187a20be36SSandy Huang #define DSP_FILED_POL 6 419d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7 420c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT 13 42110ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15 422d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16 423d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17 424e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_SHIFT 18 425e2bdb3b3SDamon Ding #define DITHER_DOWN_SEL_MASK 0x3 426452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT 20 427db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT 22 4281147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28 4291147facaSSandy Huang 430d0408543SAndy Yan #define STANDBY_EN_SHIFT 31 431d0408543SAndy Yan 432d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04 43310ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4 43410ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3 435d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20 436d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21 43741874944SGuochun Huang #define EDPI_TE_EN 28 43841874944SGuochun Huang #define EDPI_WMS_HOLD_EN 30 43941874944SGuochun Huang #define EDPI_WMS_FS 31 44041874944SGuochun Huang 441d0408543SAndy Yan 442d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 44344b1b62cSDamon Ding #define POST_URGENCY_EN_SHIFT 8 44444b1b62cSDamon Ding #define POST_URGENCY_THL_SHIFT 16 44544b1b62cSDamon Ding #define POST_URGENCY_THL_MASK 0xf 44644b1b62cSDamon Ding #define POST_URGENCY_THH_SHIFT 20 44744b1b62cSDamon Ding #define POST_URGENCY_THH_MASK 0xf 4485fa6e665SDamon Ding 4495fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL 0xC0C 450a552a69cSDamon Ding #define RK3576_DCLK_CORE_SEL_SHIFT 0 451a552a69cSDamon Ding #define RK3576_DCLK_OUT_SEL_SHIFT 2 4525fa6e665SDamon Ding 4536414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10 4546414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0 4556414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2 4566414e3bcSSandy Huang 457ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C 458ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0 459ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2 460ecc31b6eSAndy Yan 4616414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20 4626414e3bcSSandy Huang 463d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C 464d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 465d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 466d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 467d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 468d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40 4697504507fSSandy Huang #define RK3568_VP0_POST_SCALE_MASK 0x3 4707504507fSSandy Huang #define RK3568_VP0_POST_SCALE_SHIFT 0 471d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 472d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 473d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 474d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 475d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54 476d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 477d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 478d0408543SAndy Yan 479ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60 480ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0 481ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1 482ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 483ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 484ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4 485ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1 486ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 487ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 488ac500a1fSSandy Huang 489ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64 490ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0 491ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF 492ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8 493ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF 494ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20 495ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF 496ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30 497ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3 498ac500a1fSSandy Huang 499ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68 500ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0 501ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF 502ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16 503ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF 504ac500a1fSSandy Huang 505ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C 506ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31 507ac500a1fSSandy Huang #define BCSH_EN_MASK 1 508ac500a1fSSandy Huang 509a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_0 0xCA0 510a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_1 0xCA4 511a552a69cSDamon Ding #define RK3576_VP0_POST_DITHER_FRC_2 0xCA8 512a552a69cSDamon Ding 5136027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL 0xCD0 5146027c871SZhang Yubing #define POST_CSC_COE00_MASK 0xFFFF 5156027c871SZhang Yubing #define POST_CSC_COE00_SHIFT 16 5166027c871SZhang Yubing #define POST_R2Y_MODE_MASK 0x7 5176027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT 8 5186027c871SZhang Yubing #define POST_CSC_MODE_MASK 0x7 5196027c871SZhang Yubing #define POST_CSC_MODE_SHIFT 3 5206027c871SZhang Yubing #define POST_R2Y_EN_MASK 0x1 5216027c871SZhang Yubing #define POST_R2Y_EN_SHIFT 2 5226027c871SZhang Yubing #define POST_CSC_EN_MASK 0x1 5236027c871SZhang Yubing #define POST_CSC_EN_SHIFT 1 5246027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK 0x1 5256027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT 0 5266027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02 0xCD4 5276027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11 0xCD8 5286027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20 0xCDC 5296027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22 0xCE0 5306027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0 0xCE4 5316027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1 0xCE8 5326027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2 0xCEC 5336027c871SZhang Yubing 5340675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL 0xCF8 5350675a2a4SDamon Ding #define MCU_TYPE_SHIFT 31 5360675a2a4SDamon Ding #define MCU_BYPASS_SHIFT 30 5370675a2a4SDamon Ding #define MCU_RS_SHIFT 29 5380675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT 28 5390675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT 27 5400675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT 26 5410675a2a4SDamon Ding #define MCU_CLK_SEL_MASK 0x1 5420675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT 20 5430675a2a4SDamon Ding #define MCU_RW_PEND_MASK 0x3F 5440675a2a4SDamon Ding #define MCU_RW_PST_SHIFT 16 5450675a2a4SDamon Ding #define MCU_RW_PST_MASK 0xF 5460675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT 10 5470675a2a4SDamon Ding #define MCU_CS_PEND_MASK 0x3F 5480675a2a4SDamon Ding #define MCU_CS_PST_SHIFT 6 5490675a2a4SDamon Ding #define MCU_CS_PST_MASK 0xF 5500675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT 0 5510675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK 0x3F 5520675a2a4SDamon Ding 5530675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT 0xCFC 5540675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT 0 5550675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK 0xFFFFFFFF 5560675a2a4SDamon Ding 557d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00 558d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04 559d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 560d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 561d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 562d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 563d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 564d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40 565d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34 566d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38 567d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 568d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 569d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 570d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 571d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54 572d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 573d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 574d0408543SAndy Yan 575d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00 576d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04 577d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 578d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 579d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 580d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 581d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 582d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40 583d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34 584d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38 585d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 586d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 587d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 588d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 589d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54 590d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 591d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 592a552a69cSDamon Ding #define RK3568_VP2_BCSH_CTRL 0xE60 593a552a69cSDamon Ding #define RK3568_VP2_BCSH_BCS 0xE64 594a552a69cSDamon Ding #define RK3568_VP2_BCSH_H 0xE68 595a552a69cSDamon Ding #define RK3568_VP2_BCSH_COLOR_BAR 0xE6C 596a552a69cSDamon Ding #define RK3576_VP2_MCU_CTRL 0xEF8 597a552a69cSDamon Ding #define RK3576_VP2_MCU_RW_BYPASS_PORT 0xEFC 598d0408543SAndy Yan 599d0408543SAndy Yan /* Cluster0 register definition */ 600d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 601ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8 602ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9 603ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10 604840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT 18 605d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 6065fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12 6075fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 6085fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 6095fa6e665SDamon Ding #define AVG2_MASK 0x1 6105fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT 18 6115fa6e665SDamon Ding #define AVG4_MASK 0x1 6125fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT 19 6135fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22 6145fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT 24 6155fa6e665SDamon Ding #define XGT_MODE_MASK 0x3 6165fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT 25 6175fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT 27 618ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28 619ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29 620a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008 621a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK 0x1f 622a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT 0 623a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK 0x1f 624a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT 5 625a33b790fSDamon Ding 626d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 627d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 628d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018 629d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 630d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 631d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 632d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 633a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_CTRL 0x1040 634a552a69cSDamon Ding #define WIN0_ZME_DERING_EN_SHIFT 3 635a552a69cSDamon Ding #define WIN0_ZME_GATING_EN_SHIFT 31 636a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA 0x1044 637d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 638d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 639d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 640d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 641d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 642d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 643d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 644a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT 7 645a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET 0x1078 646a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE 0x107C 647d0408543SAndy Yan 648d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 649d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 650d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 651d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 652d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098 653d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 654d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 655d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 656d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 657d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 658d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 659d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 660d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 661d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 662d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 663d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 664a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET 0x10F8 665a552a69cSDamon Ding #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE 0x10FC 666d0408543SAndy Yan 667d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100 668ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0 669a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK 0x1 670a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT 13 671a552a69cSDamon Ding #define RK3576_CLUSTER0_PORT_SEL 0x11F4 672a552a69cSDamon Ding #define CLUSTER_PORT_SEL_SHIFT 0 673a552a69cSDamon Ding #define CLUSTER_PORT_SEL_MASK 0x3 674a552a69cSDamon Ding #define RK3576_CLUSTER0_DLY_NUM 0x11F8 675a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_SHIFT 0 676a552a69cSDamon Ding #define CLUSTER_WIN0_DLY_NUM_MASK 0xff 677a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_SHIFT 0 678a552a69cSDamon Ding #define CLUSTER_WIN1_DLY_NUM_MASK 0xff 679d0408543SAndy Yan 680d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 681d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 682d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 683d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 684d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218 685d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 686d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 687d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 688d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 689a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_CTRL 0x1240 690a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA 0x1244 691d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 692d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 693d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 694d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 695d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 696d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 697d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 698a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET 0x1278 699a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE 0x127C 700d0408543SAndy Yan 701d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 702d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 703d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 704d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 705d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298 706d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 707d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 708d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 709d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 710d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 711d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 712d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 713d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 714d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 715d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 716d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 717a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET 0x12F8 718a552a69cSDamon Ding #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE 0x12FC 719d0408543SAndy Yan 720d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300 721a552a69cSDamon Ding #define RK3576_CLUSTER1_PORT_SEL 0x13F4 722a552a69cSDamon Ding #define RK3576_CLUSTER1_DLY_NUM 0x13F8 723d0408543SAndy Yan 724d0408543SAndy Yan /* Esmart register definition */ 725d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800 72610ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1 72710ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2 72810ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3 7295fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT 12 7305fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK 0x3 731d0408543SAndy Yan 732d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804 733a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK 0x1f 734a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT 4 735a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK 0x1f 736a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT 12 737d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31 738a33b790fSDamon Ding 739a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL 0x1808 740a33b790fSDamon Ding #define ESMART_AXI_ID_MASK 0x1 741a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT 1 742a33b790fSDamon Ding 743d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810 744d0408543SAndy Yan #define WIN_EN_SHIFT 0 745d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f 746d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1 747840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT 12 7485fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT 14 7495fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT 20 7505fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT 21 7515fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT 22 752d0408543SAndy Yan 753d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 754d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 755d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C 756d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 757d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 758d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 759d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 7603e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3 7613e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0 7623e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3 7633e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2 7643e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3 7653e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4 7663e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3 7673e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6 7683e39a5a1SSandy Huang 769d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 770d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 771d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 772d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840 7733e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1 7743e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8 7753e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1 7763e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9 7773e39a5a1SSandy Huang 778d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 779d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 780d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C 781d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 782d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 783d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 784d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 785d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 786d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 787d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 788d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870 789d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 790d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 791d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C 792d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 793d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 794d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 795d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 796d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 797d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 798d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 799d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0 800d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 801d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 802d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC 803d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 804d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 805d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 806d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 807d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 808d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 809d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 810a552a69cSDamon Ding #define RK3568_ESMART0_COLOR_KEY_CTRL 0x18D0 811a552a69cSDamon Ding #define RK3576_ESMART0_ALPHA_MAP 0x18D8 812a552a69cSDamon Ding #define RK3576_ESMART0_PORT_SEL 0x18F4 813a552a69cSDamon Ding #define ESMART_PORT_SEL_SHIFT 0 814a552a69cSDamon Ding #define ESMART_PORT_SEL_MASK 0x3 815a552a69cSDamon Ding #define RK3576_ESMART0_DLY_NUM 0x18F8 816d0408543SAndy Yan 817d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00 818d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04 819d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10 820d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 821d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 822d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C 823d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 824d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 825d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 826d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 827d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 828d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 829d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 830d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40 831d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 832d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 833d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C 834d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 835d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 836d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 837d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 838d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 839d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 840d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 841d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70 842d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 843d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 844d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C 845d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 846d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 847d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 848d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 849d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 850d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 851d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 852d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 853d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 854d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 855d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC 856d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 857d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 858d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 859d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 860d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 861d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 862d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 863a552a69cSDamon Ding #define RK3576_ESMART1_ALPHA_MAP 0x1AD8 864a552a69cSDamon Ding #define RK3576_ESMART1_PORT_SEL 0x1AF4 865a552a69cSDamon Ding #define RK3576_ESMART1_DLY_NUM 0x1AF8 866d0408543SAndy Yan 867d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00 868d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04 869d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10 870d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 871d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 872d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C 873d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 874d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 875d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 876d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 877d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 878d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 879d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 880d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40 881d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 882d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 883d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C 884d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 885d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 886d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 887d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 888d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 889d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 890d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 891d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70 892d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 893d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 894d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C 895d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 896d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 897d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 898d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 899d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 900d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 901d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 902d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0 903d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 904d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 905d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC 906d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 907d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 908d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 909d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 910d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 911d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 912d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 913a552a69cSDamon Ding #define RK3576_ESMART2_ALPHA_MAP 0x1CD8 914a552a69cSDamon Ding #define RK3576_ESMART2_PORT_SEL 0x1CF4 915a552a69cSDamon Ding #define RK3576_ESMART2_DLY_NUM 0x1CF8 916d0408543SAndy Yan 917d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00 918d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04 919d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10 920d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 921d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 922d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C 923d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 924d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 925d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 926d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 927d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 928d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 929d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 930d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40 931d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 932d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 933d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C 934d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 935d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 936d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 937d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 938d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 939d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 940d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 941d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70 942d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 943d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 944d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C 945d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 946d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 947d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 948d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 949d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 950d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 951d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 952d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0 953d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 954d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 955d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC 956d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 957d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 958d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 959d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 960d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 961d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 962d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 963a552a69cSDamon Ding #define RK3576_ESMART3_ALPHA_MAP 0x1ED8 964a552a69cSDamon Ding #define RK3576_ESMART3_PORT_SEL 0x1EF4 965a552a69cSDamon Ding #define RK3576_ESMART3_DLY_NUM 0x1EF8 966d0408543SAndy Yan 96772388c26SDamon Ding /* HDR register definition */ 96872388c26SDamon Ding #define RK3568_HDR_LUT_CTRL 0x2000 96972388c26SDamon Ding 97072388c26SDamon Ding #define RK3588_VP3_DSP_CTRL 0xF00 97172388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400 97272388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0 0x1600 97372388c26SDamon Ding 97412ee5af0SDamon Ding /* DSC 8K/4K register definition */ 97512ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3 0x4000 97612ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0 0x40A0 97712ee5af0SDamon Ding #define DSC_EN_SHIFT 0 97812ee5af0SDamon Ding #define DSC_RBIT_SHIFT 2 97912ee5af0SDamon Ding #define DSC_RBYT_SHIFT 3 98012ee5af0SDamon Ding #define DSC_FLAL_SHIFT 4 98112ee5af0SDamon Ding #define DSC_MER_SHIFT 5 98212ee5af0SDamon Ding #define DSC_EPB_SHIFT 6 98312ee5af0SDamon Ding #define DSC_EPL_SHIFT 7 9841ace1b6dSDamon Ding #define DSC_NSLC_MASK 0x7 98512ee5af0SDamon Ding #define DSC_NSLC_SHIFT 16 98612ee5af0SDamon Ding #define DSC_SBO_SHIFT 28 98712ee5af0SDamon Ding #define DSC_IFEP_SHIFT 29 98812ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT 31 989baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \ 990baf2c414SDamon Ding (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \ 991baf2c414SDamon Ding (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT)) 99212ee5af0SDamon Ding 99312ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1 0x40A4 99412ee5af0SDamon Ding #define RK3588_DSC_8K_STS0 0x40A8 99512ee5af0SDamon Ding #define RK3588_DSC_8K_ERS 0x40C4 99612ee5af0SDamon Ding 99712ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3 0x4100 99812ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0 0x41A0 99912ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1 0x41A4 100012ee5af0SDamon Ding #define RK3588_DSC_4K_STS0 0x41A8 100112ee5af0SDamon Ding #define RK3588_DSC_4K_ERS 0x41C4 100212ee5af0SDamon Ding 100372388c26SDamon Ding /* RK3528 HDR register definition */ 100472388c26SDamon Ding #define RK3528_HDR_LUT_CTRL 0x2000 100572388c26SDamon Ding 10066027c871SZhang Yubing /* RK3528 ACM register definition */ 10076027c871SZhang Yubing #define RK3528_ACM_CTRL 0x6400 10086027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE 0x6404 10096027c871SZhang Yubing #define RK3528_ACM_FETCH_START 0x6408 10106027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE 0x6420 10116027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500 10126027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760 10136027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764 10146027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4 10156027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8 10166027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8 10176027c871SZhang Yubing 1018d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0 1019d0408543SAndy Yan 1020452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON 0x10500 102152ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364 102252ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1 102352ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2 102452ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3 102552ee18acSSandy Huang 1026a552a69cSDamon Ding /* Base SYS_GRF: 0x2600a000*/ 1027a552a69cSDamon Ding #define RK3576_SYS_GRF_MEMFAULT_STATUS0 0x0148 1028a552a69cSDamon Ding 1029a552a69cSDamon Ding /* Base IOC_GRF: 0x26040000 */ 1030a552a69cSDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8 0x6420 1031a552a69cSDamon Ding #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT 9 1032a552a69cSDamon Ding #define RK3576_IOC_VOPLITE_SEL_SHIFT 11 1033a552a69cSDamon Ding 1034a552a69cSDamon Ding /* Base PMU2: 0x27380000 */ 1035a552a69cSDamon Ding #define RK3576_PMU_PWR_GATE_STS 0x0230 1036a552a69cSDamon Ding #define PD_VOP_ESMART_DWN_STAT 12 1037a552a69cSDamon Ding #define PD_VOP_CLUSTER_DWN_STAT 13 1038a552a69cSDamon Ding #define RK3576_PMU_BISR_PDGEN_CON0 0x0510 1039a552a69cSDamon Ding #define PD_VOP_ESMART_REPAIR_ENA_SHIFT 12 1040a552a69cSDamon Ding #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT 13 1041a552a69cSDamon Ding #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0 0x0570 1042a552a69cSDamon Ding #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT 12 1043a552a69cSDamon Ding #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT 13 1044a552a69cSDamon Ding 10455d2768f7SDamon Ding #define RK3588_GRF_SOC_CON1 0x0304 10465d2768f7SDamon Ding #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT 14 10475d2768f7SDamon Ding 1048ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008 1049ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 1050ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 1051ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 1052ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 1053ecc31b6eSAndy Yan 1054b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0 0x0000 1055b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK 0x3 1056b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT 5 1057b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT 7 1058b890760eSAlgea Cao 105960e469f5SDamon Ding #define RK3588_PMU_BISR_CON3 0x20C 106060e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 106160e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 106260e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 106360e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 1064b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13 1065b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14 106660e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 106760e469f5SDamon Ding 106860e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5 0x294 106960e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 107060e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 107160e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 107260e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 1073b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13 1074b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14 107560e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 107660e469f5SDamon Ding 1077d0408543SAndy Yan #define VOP2_LAYER_MAX 8 107863cb669fSSandy Huang 1079ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH 4096 1080ee01dbb2SDamon Ding 1081631ee99aSZhang Yubing /* KHz */ 1082631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE 600000 1083631ee99aSZhang Yubing 1084b6ba80b4SDamon Ding /* 1085b6ba80b4SDamon Ding * vop2 dsc id 1086b6ba80b4SDamon Ding */ 1087b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K 0 1088b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K 1 1089b6ba80b4SDamon Ding 1090b6ba80b4SDamon Ding /* 1091b6ba80b4SDamon Ding * vop2 internal power domain id, 1092b6ba80b4SDamon Ding * should be all none zero, 0 will be 1093b6ba80b4SDamon Ding * treat as invalid; 1094b6ba80b4SDamon Ding */ 1095b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0 BIT(0) 1096b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1 BIT(1) 1097b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2 BIT(2) 1098b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3 BIT(3) 1099b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K BIT(5) 1100b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K BIT(6) 1101b6ba80b4SDamon Ding #define VOP2_PD_ESMART BIT(7) 1102a552a69cSDamon Ding #define VOP2_PD_CLUSTER BIT(8) 1103b6ba80b4SDamon Ding 11044c765862SDamon Ding #define VOP2_PLANE_NO_SCALING BIT(16) 11054c765862SDamon Ding 11065fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 11075fa6e665SDamon Ding #define VOP_FEATURE_AFBDC BIT(1) 11085fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE BIT(2) 11095fa6e665SDamon Ding #define VOP_FEATURE_HDR10 BIT(3) 11105fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR BIT(4) 11115fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */ 11125fa6e665SDamon Ding #define VOP_FEATURE_SPLICE BIT(5) 11135fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN BIT(6) 11146027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR BIT(7) 11156027c871SZhang Yubing #define VOP_FEATURE_POST_ACM BIT(8) 11166027c871SZhang Yubing #define VOP_FEATURE_POST_CSC BIT(9) 1117a552a69cSDamon Ding #define VOP_FEATURE_POST_FRC_V2 BIT(10) 1118a552a69cSDamon Ding #define VOP_FEATURE_POST_SHARP BIT(11) 11195fa6e665SDamon Ding 11205fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR BIT(0) 11215fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR BIT(1) 11225fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY BIT(2) 11235fa6e665SDamon Ding #define WIN_FEATURE_AFBDC BIT(3) 11245fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN BIT(4) 11255fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB BIT(5) 11265fa6e665SDamon Ding /* a mirror win can only get fb address 11275fa6e665SDamon Ding * from source win: 11285fa6e665SDamon Ding * Cluster1---->Cluster0 11295fa6e665SDamon Ding * Esmart1 ---->Esmart0 11305fa6e665SDamon Ding * Smart1 ---->Smart0 11315fa6e665SDamon Ding * This is a feather on rk3566 11325fa6e665SDamon Ding */ 11335fa6e665SDamon Ding #define WIN_FEATURE_MIRROR BIT(6) 11345fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA BIT(7) 11355fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8) 1136a552a69cSDamon Ding #define WIN_FEATURE_DCI BIT(9) 11375fa6e665SDamon Ding 11385fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F 0xfe 11395fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F 0xff 11405fa6e665SDamon Ding 11415fa6e665SDamon Ding enum vop_csc_format { 114210ee9f5bSAlgea Cao CSC_BT601L, 114310ee9f5bSAlgea Cao CSC_BT709L, 114410ee9f5bSAlgea Cao CSC_BT601F, 1145df0a5c43SDamon Ding CSC_BT2020L, 11465fa6e665SDamon Ding CSC_BT709L_13BIT, 11475fa6e665SDamon Ding CSC_BT709F_13BIT, 11485fa6e665SDamon Ding CSC_BT2020L_13BIT, 11495fa6e665SDamon Ding CSC_BT2020F_13BIT, 11505fa6e665SDamon Ding }; 11515fa6e665SDamon Ding 11525fa6e665SDamon Ding enum vop_csc_bit_depth { 11535fa6e665SDamon Ding CSC_10BIT_DEPTH, 11545fa6e665SDamon Ding CSC_13BIT_DEPTH, 115510ee9f5bSAlgea Cao }; 115610ee9f5bSAlgea Cao 115710ee9f5bSAlgea Cao enum vop2_pol { 115810ee9f5bSAlgea Cao HSYNC_POSITIVE = 0, 115910ee9f5bSAlgea Cao VSYNC_POSITIVE = 1, 116010ee9f5bSAlgea Cao DEN_NEGATIVE = 2, 116110ee9f5bSAlgea Cao DCLK_INVERT = 3 116210ee9f5bSAlgea Cao }; 116310ee9f5bSAlgea Cao 1164ac500a1fSSandy Huang enum vop2_bcsh_out_mode { 1165ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK, 1166ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE, 1167ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR, 1168ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, 1169ac500a1fSSandy Huang }; 1170ac500a1fSSandy Huang 1171d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \ 1172d0408543SAndy Yan { \ 1173d0408543SAndy Yan .offset = off, \ 1174d0408543SAndy Yan .mask = _mask, \ 1175d0408543SAndy Yan .shift = _shift, \ 1176d0408543SAndy Yan .write_mask = _write_mask, \ 1177d0408543SAndy Yan } 1178d0408543SAndy Yan 1179d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \ 1180d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false) 1181d0408543SAndy Yan enum dither_down_mode { 1182d0408543SAndy Yan RGB888_TO_RGB565 = 0x0, 1183d0408543SAndy Yan RGB888_TO_RGB666 = 0x1 1184d0408543SAndy Yan }; 1185d0408543SAndy Yan 1186a552a69cSDamon Ding enum dither_down_mode_sel { 1187a552a69cSDamon Ding DITHER_DOWN_ALLEGRO = 0x0, 1188a552a69cSDamon Ding DITHER_DOWN_FRC = 0x1 1189a552a69cSDamon Ding }; 1190a552a69cSDamon Ding 1191d0408543SAndy Yan enum vop2_video_ports_id { 1192d0408543SAndy Yan VOP2_VP0, 1193d0408543SAndy Yan VOP2_VP1, 1194d0408543SAndy Yan VOP2_VP2, 1195d0408543SAndy Yan VOP2_VP3, 1196d0408543SAndy Yan VOP2_VP_MAX, 1197d0408543SAndy Yan }; 1198d0408543SAndy Yan 1199ee008497SSandy Huang enum vop2_layer_type { 1200ee008497SSandy Huang CLUSTER_LAYER = 0, 1201ee008497SSandy Huang ESMART_LAYER = 1, 1202ee008497SSandy Huang SMART_LAYER = 2, 1203ee008497SSandy Huang }; 1204ee008497SSandy Huang 1205b0989546SSandy Huang /* This define must same with kernel win phy id */ 1206b0989546SSandy Huang enum vop2_layer_phy_id { 1207b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0, 1208b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, 1209b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0, 1210b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 1211b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 1212b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 1213b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2, 1214b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3, 1215b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2, 1216b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3, 1217ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX, 121827cec8e2SDamon Ding ROCKCHIP_VOP2_PHY_ID_INVALID = -1, 1219d0408543SAndy Yan }; 1220d0408543SAndy Yan 12213e39a5a1SSandy Huang enum vop2_scale_up_mode { 12223e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR, 12233e39a5a1SSandy Huang VOP2_SCALE_UP_BIL, 12243e39a5a1SSandy Huang VOP2_SCALE_UP_BIC, 1225a552a69cSDamon Ding VOP2_SCALE_UP_ZME, 12263e39a5a1SSandy Huang }; 12273e39a5a1SSandy Huang 12283e39a5a1SSandy Huang enum vop2_scale_down_mode { 12293e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR, 12303e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL, 12313e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG, 1232a552a69cSDamon Ding VOP2_SCALE_DOWN_ZME, 12333e39a5a1SSandy Huang }; 12343e39a5a1SSandy Huang 12353e39a5a1SSandy Huang enum scale_mode { 12363e39a5a1SSandy Huang SCALE_NONE = 0x0, 12373e39a5a1SSandy Huang SCALE_UP = 0x1, 12383e39a5a1SSandy Huang SCALE_DOWN = 0x2 12393e39a5a1SSandy Huang }; 12403e39a5a1SSandy Huang 124112ee5af0SDamon Ding enum vop_dsc_interface_mode { 124212ee5af0SDamon Ding VOP_DSC_IF_DISABLE = 0, 124312ee5af0SDamon Ding VOP_DSC_IF_HDMI = 1, 124412ee5af0SDamon Ding VOP_DSC_IF_MIPI_DS_MODE = 2, 124512ee5af0SDamon Ding VOP_DSC_IF_MIPI_VIDEO_MODE = 3, 124612ee5af0SDamon Ding }; 124712ee5af0SDamon Ding 12485fa6e665SDamon Ding enum vop3_pre_scale_down_mode { 12495fa6e665SDamon Ding VOP3_PRE_SCALE_UNSPPORT, 12505fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_GT, 12515fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_AVG, 12525fa6e665SDamon Ding }; 12535fa6e665SDamon Ding 12545fa6e665SDamon Ding enum vop3_esmart_lb_mode { 12555fa6e665SDamon Ding VOP3_ESMART_8K_MODE, 12565fa6e665SDamon Ding VOP3_ESMART_4K_4K_MODE, 12575fa6e665SDamon Ding VOP3_ESMART_4K_2K_2K_MODE, 12585fa6e665SDamon Ding VOP3_ESMART_2K_2K_2K_2K_MODE, 1259a552a69cSDamon Ding VOP3_ESMART_4K_4K_4K_MODE, 1260a552a69cSDamon Ding VOP3_ESMART_4K_4K_2K_2K_MODE, 12615fa6e665SDamon Ding }; 12625fa6e665SDamon Ding 12633e39a5a1SSandy Huang struct vop2_layer { 12643e39a5a1SSandy Huang u8 id; 12653e39a5a1SSandy Huang /** 12663e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected. 12673e39a5a1SSandy Huang * Every layer must make sure to select different 12683e39a5a1SSandy Huang * windows of others. 12693e39a5a1SSandy Huang */ 12703e39a5a1SSandy Huang u8 win_phys_id; 12713e39a5a1SSandy Huang }; 12723e39a5a1SSandy Huang 127360e469f5SDamon Ding struct vop2_power_domain_data { 1274a552a69cSDamon Ding u16 id; 1275a552a69cSDamon Ding u16 parent_id; 1276b6ba80b4SDamon Ding /* 1277b6ba80b4SDamon Ding * @module_id_mask: module id of which module this power domain is belongs to. 1278b6ba80b4SDamon Ding * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 1279b6ba80b4SDamon Ding */ 1280b6ba80b4SDamon Ding u32 module_id_mask; 128160e469f5SDamon Ding }; 128260e469f5SDamon Ding 1283b0989546SSandy Huang struct vop2_win_data { 1284b0989546SSandy Huang char *name; 128563cb669fSSandy Huang u8 phys_id; 1286ecc31b6eSAndy Yan enum vop2_layer_type type; 1287b0989546SSandy Huang u8 win_sel_port_offset; 12885fa6e665SDamon Ding u8 layer_sel_win_id[VOP2_VP_MAX]; 1289a33b790fSDamon Ding u8 axi_id; 1290a33b790fSDamon Ding u8 axi_uv_id; 1291a33b790fSDamon Ding u8 axi_yrgb_id; 1292ee01dbb2SDamon Ding u8 splice_win_id; 12935fa6e665SDamon Ding u8 hsu_filter_mode; 12945fa6e665SDamon Ding u8 hsd_filter_mode; 12955fa6e665SDamon Ding u8 vsu_filter_mode; 12965fa6e665SDamon Ding u8 vsd_filter_mode; 12975fa6e665SDamon Ding u8 hsd_pre_filter_mode; 12985fa6e665SDamon Ding u8 vsd_pre_filter_mode; 12995fa6e665SDamon Ding u8 scale_engine_num; 13001c9572c7SDamon Ding u8 source_win_id; 1301a552a69cSDamon Ding u8 possible_crtcs; 1302a552a69cSDamon Ding u16 pd_id; 1303b0989546SSandy Huang u32 reg_offset; 13044c765862SDamon Ding u32 max_upscale_factor; 13054c765862SDamon Ding u32 max_downscale_factor; 13061c9572c7SDamon Ding u32 feature; 1307a552a69cSDamon Ding u32 supported_rotations; 1308ee01dbb2SDamon Ding bool splice_mode_right; 130963cb669fSSandy Huang }; 131063cb669fSSandy Huang 131163cb669fSSandy Huang struct vop2_vp_data { 131263cb669fSSandy Huang u32 feature; 131344b1b62cSDamon Ding u32 max_dclk; 131463cb669fSSandy Huang u8 pre_scan_max_dly; 1315452afb13SDamon Ding u8 layer_mix_dly; 1316a552a69cSDamon Ding u8 hdrvivid_dly; 1317a552a69cSDamon Ding u8 sdr2hdr_dly; 1318452afb13SDamon Ding u8 hdr_mix_dly; 1319452afb13SDamon Ding u8 win_dly; 1320ee01dbb2SDamon Ding u8 splice_vp_id; 1321a552a69cSDamon Ding u8 pixel_rate; 132263cb669fSSandy Huang struct vop_rect max_output; 132344b1b62cSDamon Ding struct vop_urgency *urgency; 1324d0408543SAndy Yan }; 1325d0408543SAndy Yan 1326ee008497SSandy Huang struct vop2_plane_table { 1327ee008497SSandy Huang enum vop2_layer_phy_id plane_id; 1328ee008497SSandy Huang enum vop2_layer_type plane_type; 1329ee008497SSandy Huang }; 1330ee008497SSandy Huang 1331b0989546SSandy Huang struct vop2_vp_plane_mask { 1332b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */ 1333b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */ 1334b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 1335b0989546SSandy Huang u32 plane_mask; 1336ee008497SSandy Huang int cursor_plane_id; 1337b0989546SSandy Huang }; 1338b0989546SSandy Huang 133912ee5af0SDamon Ding struct vop2_dsc_data { 134012ee5af0SDamon Ding u8 id; 134112ee5af0SDamon Ding u8 max_slice_num; 134212ee5af0SDamon Ding u8 max_linebuf_depth; /* used to generate the bitstream */ 134312ee5af0SDamon Ding u8 min_bits_per_pixel; /* bit num after encoder compress */ 1344a552a69cSDamon Ding u16 pd_id; 134512ee5af0SDamon Ding const char *dsc_txp_clk_src_name; 134612ee5af0SDamon Ding const char *dsc_txp_clk_name; 134712ee5af0SDamon Ding const char *dsc_pxl_clk_name; 134812ee5af0SDamon Ding const char *dsc_cds_clk_name; 134912ee5af0SDamon Ding }; 135012ee5af0SDamon Ding 135112ee5af0SDamon Ding struct dsc_error_info { 135212ee5af0SDamon Ding u32 dsc_error_val; 135312ee5af0SDamon Ding char dsc_error_info[50]; 135412ee5af0SDamon Ding }; 135512ee5af0SDamon Ding 135672388c26SDamon Ding struct vop2_dump_regs { 135772388c26SDamon Ding u32 offset; 135872388c26SDamon Ding const char *name; 135972388c26SDamon Ding u32 state_base; 136072388c26SDamon Ding u32 state_mask; 136172388c26SDamon Ding u32 state_shift; 136272388c26SDamon Ding bool enable_state; 1363a552a69cSDamon Ding u32 size; 1364a552a69cSDamon Ding }; 1365a552a69cSDamon Ding 1366a552a69cSDamon Ding struct vop2_esmart_lb_map { 1367a552a69cSDamon Ding u8 lb_mode; 1368a552a69cSDamon Ding u8 lb_map_value; 136972388c26SDamon Ding }; 137072388c26SDamon Ding 1371d0408543SAndy Yan struct vop2_data { 137252ee18acSSandy Huang u32 version; 13735fa6e665SDamon Ding u32 esmart_lb_mode; 137463cb669fSSandy Huang struct vop2_vp_data *vp_data; 1375b0989546SSandy Huang struct vop2_win_data *win_data; 1376b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 1377ee008497SSandy Huang struct vop2_plane_table *plane_table; 1378b6ba80b4SDamon Ding struct vop2_power_domain_data *pd; 137912ee5af0SDamon Ding struct vop2_dsc_data *dsc; 138012ee5af0SDamon Ding struct dsc_error_info *dsc_error_ecw; 138112ee5af0SDamon Ding struct dsc_error_info *dsc_error_buffer_flow; 138272388c26SDamon Ding struct vop2_dump_regs *dump_regs; 1383a552a69cSDamon Ding const struct vop2_esmart_lb_map *esmart_lb_mode_map; 1384337d1c13SDamon Ding u8 *vp_primary_plane_order; 1385a552a69cSDamon Ding u8 *vp_default_primary_plane; 138663cb669fSSandy Huang u8 nr_vps; 138763cb669fSSandy Huang u8 nr_layers; 138863cb669fSSandy Huang u8 nr_mixers; 13891147facaSSandy Huang u8 nr_gammas; 1390b6ba80b4SDamon Ding u8 nr_pd; 139112ee5af0SDamon Ding u8 nr_dscs; 139212ee5af0SDamon Ding u8 nr_dsc_ecw; 139312ee5af0SDamon Ding u8 nr_dsc_buffer_flow; 1394a552a69cSDamon Ding u8 esmart_lb_mode_num; 1395ecc31b6eSAndy Yan u32 reg_len; 139672388c26SDamon Ding u32 dump_regs_size; 1397d0408543SAndy Yan }; 1398d0408543SAndy Yan 1399d0408543SAndy Yan struct vop2 { 1400d0408543SAndy Yan u32 *regsbak; 1401d0408543SAndy Yan void *regs; 1402d0408543SAndy Yan void *grf; 1403ecc31b6eSAndy Yan void *vop_grf; 1404ecc31b6eSAndy Yan void *vo1_grf; 140560e469f5SDamon Ding void *sys_pmu; 1406a552a69cSDamon Ding void *ioc_grf; 140752ee18acSSandy Huang u32 reg_len; 140852ee18acSSandy Huang u32 version; 14095fa6e665SDamon Ding u32 esmart_lb_mode; 141063cb669fSSandy Huang bool global_init; 1411a552a69cSDamon Ding bool merge_irq; 1412d0408543SAndy Yan const struct vop2_data *data; 1413b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 1414d0408543SAndy Yan }; 1415d0408543SAndy Yan 1416d0408543SAndy Yan static struct vop2 *rockchip_vop2; 14175fa6e665SDamon Ding 141827cec8e2SDamon Ding /* vop2_layer_phy_id */ 141927cec8e2SDamon Ding static const char *const vop2_layer_name_list[] = { 142027cec8e2SDamon Ding "Cluster0", 142127cec8e2SDamon Ding "Cluster1", 142227cec8e2SDamon Ding "Esmart0", 142327cec8e2SDamon Ding "Esmart1", 142427cec8e2SDamon Ding "Smart0", 142527cec8e2SDamon Ding "Smart1", 142627cec8e2SDamon Ding "Cluster2", 142727cec8e2SDamon Ding "Cluster3", 142827cec8e2SDamon Ding "Esmart2", 142927cec8e2SDamon Ding "Esmart3", 143027cec8e2SDamon Ding }; 143127cec8e2SDamon Ding 143227cec8e2SDamon Ding static inline const char *vop2_plane_id_to_string(unsigned long phy) 143327cec8e2SDamon Ding { 143427cec8e2SDamon Ding if (phy == ROCKCHIP_VOP2_PHY_ID_INVALID) 143527cec8e2SDamon Ding return "INVALID"; 143627cec8e2SDamon Ding 143727cec8e2SDamon Ding if (WARN_ON(phy >= ARRAY_SIZE(vop2_layer_name_list))) 143827cec8e2SDamon Ding return NULL; 143927cec8e2SDamon Ding 144027cec8e2SDamon Ding return vop2_layer_name_list[phy]; 144127cec8e2SDamon Ding } 144227cec8e2SDamon Ding 14435fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2) 14445fa6e665SDamon Ding { 14455fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) 14465fa6e665SDamon Ding return false; 14475fa6e665SDamon Ding else 14485fa6e665SDamon Ding return true; 14495fa6e665SDamon Ding } 14505fa6e665SDamon Ding 14513e39a5a1SSandy Huang /* 14523e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12; 14533e39a5a1SSandy Huang * avg_sd_factor: 14543e39a5a1SSandy Huang * bli_su_factor: 14553e39a5a1SSandy Huang * bic_su_factor: 14563e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16; 14573e39a5a1SSandy Huang * 14585fa6e665SDamon Ding * ygt2 enable: dst get one line from two line of the src 14595fa6e665SDamon Ding * ygt4 enable: dst get one line from four line of the src. 14603e39a5a1SSandy Huang * 14613e39a5a1SSandy Huang */ 14623e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 14633e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 14643e39a5a1SSandy Huang 14653e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 14663e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1)) 14673e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 14683e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1)) 14695fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \ 14705fa6e665SDamon Ding (fac * (dst - 1) >> 16 < (src - 1)) 14713e39a5a1SSandy Huang 14723e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode, 14733e39a5a1SSandy Huang int32_t filter_mode, 14743e39a5a1SSandy Huang uint32_t src, uint32_t dst) 14753e39a5a1SSandy Huang { 14763e39a5a1SSandy Huang uint32_t fac = 0; 14773e39a5a1SSandy Huang int i = 0; 14783e39a5a1SSandy Huang 14793e39a5a1SSandy Huang if (mode == SCALE_NONE) 14803e39a5a1SSandy Huang return 0; 14813e39a5a1SSandy Huang 14823e39a5a1SSandy Huang /* 14833e39a5a1SSandy Huang * A workaround to avoid zero div. 14843e39a5a1SSandy Huang */ 14853e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) { 14863e39a5a1SSandy Huang dst = dst + 1; 14873e39a5a1SSandy Huang src = src + 1; 14883e39a5a1SSandy Huang } 14893e39a5a1SSandy Huang 14903e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 14913e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst); 14923e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 14933e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 14943e39a5a1SSandy Huang break; 14953e39a5a1SSandy Huang fac -= 1; 14963e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 14973e39a5a1SSandy Huang } 14983e39a5a1SSandy Huang } else { 14993e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst); 15003e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 15013e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 15023e39a5a1SSandy Huang break; 15033e39a5a1SSandy Huang fac -= 1; 15043e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 15053e39a5a1SSandy Huang } 15063e39a5a1SSandy Huang } 15073e39a5a1SSandy Huang 15083e39a5a1SSandy Huang return fac; 15093e39a5a1SSandy Huang } 15103e39a5a1SSandy Huang 15115fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor) 15125fa6e665SDamon Ding { 15135fa6e665SDamon Ding if (is_hor) 15145fa6e665SDamon Ding return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac); 15155fa6e665SDamon Ding return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac); 15165fa6e665SDamon Ding } 15175fa6e665SDamon Ding 15185fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode, 15195fa6e665SDamon Ding uint32_t src, uint32_t dst, bool is_hor) 15205fa6e665SDamon Ding { 15215fa6e665SDamon Ding uint32_t fac = 0; 15225fa6e665SDamon Ding int i = 0; 15235fa6e665SDamon Ding 15245fa6e665SDamon Ding if (mode == SCALE_NONE) 15255fa6e665SDamon Ding return 0; 15265fa6e665SDamon Ding 15275fa6e665SDamon Ding /* 15285fa6e665SDamon Ding * A workaround to avoid zero div. 15295fa6e665SDamon Ding */ 15305fa6e665SDamon Ding if ((dst == 1) || (src == 1)) { 15315fa6e665SDamon Ding dst = dst + 1; 15325fa6e665SDamon Ding src = src + 1; 15335fa6e665SDamon Ding } 15345fa6e665SDamon Ding 15355fa6e665SDamon Ding if (mode == SCALE_DOWN) { 15365fa6e665SDamon Ding fac = VOP2_BILI_SCL_DN(src, dst); 15375fa6e665SDamon Ding for (i = 0; i < 100; i++) { 15385fa6e665SDamon Ding if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 15395fa6e665SDamon Ding break; 15405fa6e665SDamon Ding fac -= 1; 15415fa6e665SDamon Ding printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 15425fa6e665SDamon Ding } 15435fa6e665SDamon Ding } else { 15445fa6e665SDamon Ding fac = VOP2_COMMON_SCL(src, dst); 15455fa6e665SDamon Ding for (i = 0; i < 100; i++) { 15465fa6e665SDamon Ding if (vop3_scale_up_fac_check(src, dst, fac, is_hor)) 15475fa6e665SDamon Ding break; 15485fa6e665SDamon Ding fac -= 1; 15495fa6e665SDamon Ding printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 15505fa6e665SDamon Ding } 15515fa6e665SDamon Ding } 15525fa6e665SDamon Ding 15535fa6e665SDamon Ding return fac; 15545fa6e665SDamon Ding } 15555fa6e665SDamon Ding 15563e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst) 15573e39a5a1SSandy Huang { 15583e39a5a1SSandy Huang if (src < dst) 15593e39a5a1SSandy Huang return SCALE_UP; 15603e39a5a1SSandy Huang else if (src > dst) 15613e39a5a1SSandy Huang return SCALE_DOWN; 15623e39a5a1SSandy Huang 15633e39a5a1SSandy Huang return SCALE_NONE; 15643e39a5a1SSandy Huang } 1565d0408543SAndy Yan 1566ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x) 1567ac500a1fSSandy Huang { 1568ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 1569ac500a1fSSandy Huang } 1570ac500a1fSSandy Huang 1571b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 1572b0989546SSandy Huang { 1573b0989546SSandy Huang int i = 0; 1574ecc31b6eSAndy Yan 1575337d1c13SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 1576337d1c13SDamon Ding if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i])) 1577337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[i]; 1578ecc31b6eSAndy Yan } 1579b0989546SSandy Huang 1580337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[0]; 1581b0989546SSandy Huang } 1582b0989546SSandy Huang 158363cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift) 1584d0408543SAndy Yan { 1585d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 1586d0408543SAndy Yan } 1587d0408543SAndy Yan 158863cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst) 1589d0408543SAndy Yan { 1590d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1); 1591d0408543SAndy Yan } 1592d0408543SAndy Yan 159352ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 1594d0408543SAndy Yan { 1595d0408543SAndy Yan writel(v, vop2->regs + offset); 1596d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1597d0408543SAndy Yan } 1598d0408543SAndy Yan 159952ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 1600d0408543SAndy Yan { 1601d0408543SAndy Yan return readl(vop2->regs + offset); 1602d0408543SAndy Yan } 1603d0408543SAndy Yan 160452ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 160552ee18acSSandy Huang u32 mask, u32 shift, u32 v, 1606d0408543SAndy Yan bool write_mask) 1607d0408543SAndy Yan { 1608d0408543SAndy Yan if (!mask) 1609d0408543SAndy Yan return; 1610d0408543SAndy Yan 1611d0408543SAndy Yan if (write_mask) { 1612d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16)); 1613d0408543SAndy Yan } else { 161452ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2]; 1615d0408543SAndy Yan 1616d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 1617d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1618d0408543SAndy Yan } 1619d0408543SAndy Yan 1620d0408543SAndy Yan writel(v, vop2->regs + offset); 1621d0408543SAndy Yan } 1622d0408543SAndy Yan 1623ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 162452ee18acSSandy Huang u32 mask, u32 shift, u32 v) 162552ee18acSSandy Huang { 162652ee18acSSandy Huang u32 val = 0; 162752ee18acSSandy Huang 162852ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16)); 1629ecc31b6eSAndy Yan writel(val, grf_base + offset); 163052ee18acSSandy Huang } 163152ee18acSSandy Huang 163260e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 163360e469f5SDamon Ding u32 mask, u32 shift) 163460e469f5SDamon Ding { 163560e469f5SDamon Ding return (readl(grf_base + offset) >> shift) & mask; 163660e469f5SDamon Ding } 163760e469f5SDamon Ding 163852ee18acSSandy Huang static bool is_yuv_output(u32 bus_format) 1639d0408543SAndy Yan { 1640d0408543SAndy Yan switch (bus_format) { 1641d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 1642d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 1643034a46b5SAlgea Cao case MEDIA_BUS_FMT_YUYV10_1X20: 1644d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1645d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1646a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 1647a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 1648a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8: 1649a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8: 1650a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 1651a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 1652a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16: 1653a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16: 1654d0408543SAndy Yan return true; 1655d0408543SAndy Yan default: 1656d0408543SAndy Yan return false; 1657d0408543SAndy Yan } 1658d0408543SAndy Yan } 1659d0408543SAndy Yan 1660df0a5c43SDamon Ding static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding, 1661df0a5c43SDamon Ding enum drm_color_range color_range, 1662df0a5c43SDamon Ding int bit_depth) 166310ee9f5bSAlgea Cao { 1664df0a5c43SDamon Ding bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; 1665df0a5c43SDamon Ding enum vop_csc_format csc_mode = CSC_BT709L; 1666df0a5c43SDamon Ding 1667df0a5c43SDamon Ding 1668df0a5c43SDamon Ding switch (color_encoding) { 1669df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT601: 1670df0a5c43SDamon Ding if (full_range) 1671df0a5c43SDamon Ding csc_mode = CSC_BT601F; 16725fa6e665SDamon Ding else 1673df0a5c43SDamon Ding csc_mode = CSC_BT601L; 1674df0a5c43SDamon Ding break; 1675df0a5c43SDamon Ding 1676df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT709: 1677df0a5c43SDamon Ding if (full_range) { 1678df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F; 1679df0a5c43SDamon Ding if (bit_depth != CSC_13BIT_DEPTH) 1680df0a5c43SDamon Ding printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n"); 16815fa6e665SDamon Ding } else { 1682df0a5c43SDamon Ding csc_mode = CSC_BT709L; 16835fa6e665SDamon Ding } 1684df0a5c43SDamon Ding break; 1685df0a5c43SDamon Ding 1686df0a5c43SDamon Ding case DRM_COLOR_YCBCR_BT2020: 1687df0a5c43SDamon Ding if (full_range) { 1688df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F; 1689df0a5c43SDamon Ding if (bit_depth != CSC_13BIT_DEPTH) 1690df0a5c43SDamon Ding printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n"); 16915fa6e665SDamon Ding } else { 1692df0a5c43SDamon Ding csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L; 16935fa6e665SDamon Ding } 1694df0a5c43SDamon Ding break; 1695df0a5c43SDamon Ding 169610ee9f5bSAlgea Cao default: 1697df0a5c43SDamon Ding printf("Unsuport color_encoding:%d\n", color_encoding); 169810ee9f5bSAlgea Cao } 1699df0a5c43SDamon Ding 1700df0a5c43SDamon Ding return csc_mode; 170110ee9f5bSAlgea Cao } 170210ee9f5bSAlgea Cao 1703c8820b76SDamon Ding static bool is_uv_swap(struct display_state *state) 1704d0408543SAndy Yan { 1705c8820b76SDamon Ding struct connector_state *conn_state = &state->conn_state; 1706c8820b76SDamon Ding u32 bus_format = conn_state->bus_format; 1707c8820b76SDamon Ding u32 output_mode = conn_state->output_mode; 1708c8820b76SDamon Ding u32 output_type = conn_state->type; 1709c8820b76SDamon Ding 1710d0408543SAndy Yan /* 1711d0408543SAndy Yan * FIXME: 1712d0408543SAndy Yan * 1713d0408543SAndy Yan * There is no media type for YUV444 output, 1714d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on 1715d0408543SAndy Yan * yuv format. 1716d0408543SAndy Yan * 1717c8820b76SDamon Ding * From H/W testing, YUV444 mode need a rb swap except eDP. 1718d0408543SAndy Yan */ 17193e59c137SSandy Huang if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || 17203e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || 17213e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || 17223e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || 17233e59c137SSandy Huang ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1724d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1725d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA || 1726c8820b76SDamon Ding output_mode == ROCKCHIP_OUT_MODE_P888) && 1727c8820b76SDamon Ding !(output_type == DRM_MODE_CONNECTOR_eDP))) 1728d0408543SAndy Yan return true; 1729d0408543SAndy Yan else 1730d0408543SAndy Yan return false; 1731d0408543SAndy Yan } 1732d0408543SAndy Yan 1733c8820b76SDamon Ding static bool is_rb_swap(struct display_state *state) 17340675a2a4SDamon Ding { 1735c8820b76SDamon Ding struct connector_state *conn_state = &state->conn_state; 1736c8820b76SDamon Ding u32 bus_format = conn_state->bus_format; 1737c8820b76SDamon Ding 17380675a2a4SDamon Ding /* 17390675a2a4SDamon Ding * The default component order of serial rgb3x8 formats 17400675a2a4SDamon Ding * is BGR. So it is needed to enable RB swap. 17410675a2a4SDamon Ding */ 1742b7b383ebSDamon Ding if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 || 1743b7b383ebSDamon Ding bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8) 17440675a2a4SDamon Ding return true; 17450675a2a4SDamon Ding else 17460675a2a4SDamon Ding return false; 17470675a2a4SDamon Ding } 17480675a2a4SDamon Ding 17495d2768f7SDamon Ding static bool is_yc_swap(u32 bus_format) 17505d2768f7SDamon Ding { 17515d2768f7SDamon Ding switch (bus_format) { 17525d2768f7SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 17535d2768f7SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 17545d2768f7SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 17555d2768f7SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 17565d2768f7SDamon Ding return true; 17575d2768f7SDamon Ding default: 17585d2768f7SDamon Ding return false; 17595d2768f7SDamon Ding } 17605d2768f7SDamon Ding } 17615d2768f7SDamon Ding 1762b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type) 176363cb669fSSandy Huang { 1764b0989546SSandy Huang switch (output_type) { 1765b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA: 1766b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB: 1767b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV: 1768b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort: 1769b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA: 1770b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown: 1771b0989546SSandy Huang return true; 1772b0989546SSandy Huang default: 1773b0989546SSandy Huang return false; 177463cb669fSSandy Huang } 177563cb669fSSandy Huang } 177663cb669fSSandy Huang 1777ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1778ecc31b6eSAndy Yan { 1779ecc31b6eSAndy Yan int i = 0; 1780ecc31b6eSAndy Yan 1781ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) { 1782ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id) 1783ecc31b6eSAndy Yan return &vop2->data->win_data[i]; 1784ecc31b6eSAndy Yan } 1785ecc31b6eSAndy Yan 1786ecc31b6eSAndy Yan return NULL; 1787ecc31b6eSAndy Yan } 1788ecc31b6eSAndy Yan 1789b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id) 1790b6ba80b4SDamon Ding { 1791b6ba80b4SDamon Ding int i = 0; 1792b6ba80b4SDamon Ding 1793b6ba80b4SDamon Ding for (i = 0; i < vop2->data->nr_pd; i++) { 1794b6ba80b4SDamon Ding if (vop2->data->pd[i].id == pd_id) 1795b6ba80b4SDamon Ding return &vop2->data->pd[i]; 1796b6ba80b4SDamon Ding } 1797b6ba80b4SDamon Ding 1798b6ba80b4SDamon Ding return NULL; 1799b6ba80b4SDamon Ding } 1800b6ba80b4SDamon Ding 1801db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1802db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1803db328a0dSDamon Ding { 1804db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1805db328a0dSDamon Ding int i; 1806db328a0dSDamon Ding 1807db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1808db328a0dSDamon Ding GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 1809db328a0dSDamon Ding crtc_id, false); 1810db328a0dSDamon Ding 1811db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1812db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1813db328a0dSDamon Ding 1814db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1815db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1816db328a0dSDamon Ding } 1817db328a0dSDamon Ding 1818db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1819db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1820db328a0dSDamon Ding { 1821db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1822db328a0dSDamon Ding int i; 1823db328a0dSDamon Ding 1824db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1825db328a0dSDamon Ding GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT, 1826db328a0dSDamon Ding crtc_id, false); 1827db328a0dSDamon Ding 1828db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1829db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1830db328a0dSDamon Ding 1831db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1832db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1833db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1834db328a0dSDamon Ding EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false); 1835db328a0dSDamon Ding } 1836db328a0dSDamon Ding 18371147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1838d0408543SAndy Yan struct display_state *state) 1839d0408543SAndy Yan { 18401147facaSSandy Huang struct connector_state *conn_state = &state->conn_state; 18411147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state; 18421147facaSSandy Huang struct resource gamma_res; 18431147facaSSandy Huang fdt_size_t lut_size; 18441147facaSSandy Huang int i, lut_len, ret = 0; 18451147facaSSandy Huang u32 *lut_regs; 18461147facaSSandy Huang u32 r, g, b; 18471147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 18481147facaSSandy Huang static int gamma_lut_en_num = 1; 18491147facaSSandy Huang 18501147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) { 18511147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 18521147facaSSandy Huang return 0; 18531147facaSSandy Huang } 18541147facaSSandy Huang 18551147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 18561147facaSSandy Huang if (ret) 18571147facaSSandy Huang printf("failed to get gamma lut res\n"); 18581147facaSSandy Huang lut_regs = (u32 *)gamma_res.start; 18591147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1; 18601147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 18611147facaSSandy Huang printf("failed to get gamma lut register\n"); 18621147facaSSandy Huang return 0; 18631147facaSSandy Huang } 18641147facaSSandy Huang lut_len = lut_size / 4; 18651147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) { 18661147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 18671147facaSSandy Huang return 0; 18681147facaSSandy Huang } 18690669ab1fSDamon Ding 18700669ab1fSDamon Ding if (!cstate->lut_val) { 18710669ab1fSDamon Ding if (!disp_info) 18720669ab1fSDamon Ding return 0; 18730669ab1fSDamon Ding 18740669ab1fSDamon Ding if (!disp_info->gamma_lut_data.size) 18750669ab1fSDamon Ding return 0; 18760669ab1fSDamon Ding 18770669ab1fSDamon Ding cstate->lut_val = (u32 *)calloc(1, lut_size); 18781147facaSSandy Huang for (i = 0; i < lut_len; i++) { 18791147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 18801147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 18811147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 18821147facaSSandy Huang 18830669ab1fSDamon Ding cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 18840669ab1fSDamon Ding } 18851147facaSSandy Huang } 18861147facaSSandy Huang 1887db328a0dSDamon Ding if (vop2->version == VOP_VERSION_RK3568) { 18880669ab1fSDamon Ding rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, 18890669ab1fSDamon Ding cstate->lut_val, lut_len); 18901147facaSSandy Huang gamma_lut_en_num++; 189118d9b8adSDamon Ding } else { 18920669ab1fSDamon Ding rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, 18930669ab1fSDamon Ding cstate->lut_val, lut_len); 1894db328a0dSDamon Ding if (cstate->splice_mode) { 18950669ab1fSDamon Ding rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, 18960669ab1fSDamon Ding cstate->lut_val, lut_len); 1897db328a0dSDamon Ding gamma_lut_en_num++; 1898db328a0dSDamon Ding } 1899db328a0dSDamon Ding gamma_lut_en_num++; 1900db328a0dSDamon Ding } 19011147facaSSandy Huang 19020669ab1fSDamon Ding free(cstate->lut_val); 19030669ab1fSDamon Ding 1904d0408543SAndy Yan return 0; 1905d0408543SAndy Yan } 1906d0408543SAndy Yan 19076414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 19086414e3bcSSandy Huang struct display_state *state) 19096414e3bcSSandy Huang { 19106414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state; 19116414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state; 19126414e3bcSSandy Huang int i, cubic_lut_len; 19136414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 19146414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 19156414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 19166414e3bcSSandy Huang u32 *cubic_lut_addr; 19176414e3bcSSandy Huang 19186414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 19196414e3bcSSandy Huang return 0; 19206414e3bcSSandy Huang 19216414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size) 19226414e3bcSSandy Huang return 0; 19236414e3bcSSandy Huang 19246414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 19256414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size; 19266414e3bcSSandy Huang 19276414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) { 19286414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 19296414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 19306414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 19316414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 19326414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) + 19336414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 19346414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28); 19356414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 19366414e3bcSSandy Huang *cubic_lut_addr++ = 0; 19376414e3bcSSandy Huang } 19386414e3bcSSandy Huang 19396414e3bcSSandy Huang if (cubic_lut_len % 2) { 19406414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 19416414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 19426414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 19436414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 19446414e3bcSSandy Huang *cubic_lut_addr++ = 0; 19456414e3bcSSandy Huang *cubic_lut_addr = 0; 19466414e3bcSSandy Huang } 19476414e3bcSSandy Huang 19486414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 19496414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id)); 19506414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 19516414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 19526414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 19536414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 19546414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 19556414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 19566414e3bcSSandy Huang 19576414e3bcSSandy Huang return 0; 19586414e3bcSSandy Huang } 19596414e3bcSSandy Huang 1960ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2, 1961ee01dbb2SDamon Ding struct bcsh_state *bcsh_state, int crtc_id) 1962ee01dbb2SDamon Ding { 1963ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1964ee01dbb2SDamon Ding u32 vp_offset = crtc_id * 0x100; 1965ee01dbb2SDamon Ding 1966ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 1967ee01dbb2SDamon Ding BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false); 1968ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 1969ee01dbb2SDamon Ding BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false); 1970ee01dbb2SDamon Ding 1971ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 1972ee01dbb2SDamon Ding BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1973ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 1974ee01dbb2SDamon Ding BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1975ee01dbb2SDamon Ding 1976ee01dbb2SDamon Ding if (!cstate->bcsh_en) { 1977ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1978ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 1979ee01dbb2SDamon Ding return; 1980ee01dbb2SDamon Ding } 1981ee01dbb2SDamon Ding 1982ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1983ee01dbb2SDamon Ding BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 1984ee01dbb2SDamon Ding bcsh_state->brightness, false); 1985ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1986ee01dbb2SDamon Ding BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false); 1987ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1988ee01dbb2SDamon Ding BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 1989ee01dbb2SDamon Ding bcsh_state->saturation * bcsh_state->contrast / 0x100, false); 1990ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1991ee01dbb2SDamon Ding BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false); 1992ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1993ee01dbb2SDamon Ding BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false); 1994ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1995ee01dbb2SDamon Ding BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 1996ee01dbb2SDamon Ding BCSH_OUT_MODE_NORMAL_VIDEO, false); 1997ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1998ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 1999ee01dbb2SDamon Ding } 2000ee01dbb2SDamon Ding 2001ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 2002ac500a1fSSandy Huang { 2003ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state; 2004ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info; 2005ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state; 2006ee01dbb2SDamon Ding struct bcsh_state bcsh_state; 2007ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue; 2008ac500a1fSSandy Huang 2009ac500a1fSSandy Huang if (!conn_state->disp_info) 2010ac500a1fSSandy Huang return; 2011ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info; 2012ac500a1fSSandy Huang if (!bcsh_info) 2013ac500a1fSSandy Huang return; 2014ac500a1fSSandy Huang 2015ac500a1fSSandy Huang if (bcsh_info->brightness != 50 || 2016ac500a1fSSandy Huang bcsh_info->contrast != 50 || 2017ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50) 2018ee01dbb2SDamon Ding cstate->bcsh_en = true; 2019ac500a1fSSandy Huang 2020ee01dbb2SDamon Ding if (cstate->bcsh_en) { 2021ac500a1fSSandy Huang if (!cstate->yuv_overlay) 2022ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 2023ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format)) 2024ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 2025ac500a1fSSandy Huang } else { 2026ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 2027ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 2028ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 2029ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 2030ac500a1fSSandy Huang } 2031ac500a1fSSandy Huang 2032df0a5c43SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, 2033df0a5c43SDamon Ding conn_state->color_range, 2034df0a5c43SDamon Ding CSC_10BIT_DEPTH); 2035ac500a1fSSandy Huang 2036ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 2037ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127, 2038ac500a1fSSandy Huang bcsh_info->brightness); 2039ac500a1fSSandy Huang else 2040ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31, 2041ac500a1fSSandy Huang bcsh_info->brightness); 2042ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 2043ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 2044ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 2045ac500a1fSSandy Huang 2046ac500a1fSSandy Huang 2047ac500a1fSSandy Huang /* 2048ac500a1fSSandy Huang * a:[-30~0): 2049ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256; 2050ac500a1fSSandy Huang * cos_hue = cos(a)*256; 2051ac500a1fSSandy Huang * a:[0~30] 2052ac500a1fSSandy Huang * sin_hue = sin(a)*256; 2053ac500a1fSSandy Huang * cos_hue = cos(a)*256; 2054ac500a1fSSandy Huang */ 2055ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23; 2056ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23; 2057ac500a1fSSandy Huang 2058ee01dbb2SDamon Ding bcsh_state.brightness = brightness; 2059ee01dbb2SDamon Ding bcsh_state.contrast = contrast; 2060ee01dbb2SDamon Ding bcsh_state.saturation = saturation; 2061ee01dbb2SDamon Ding bcsh_state.sin_hue = sin_hue; 2062ee01dbb2SDamon Ding bcsh_state.cos_hue = cos_hue; 2063ee01dbb2SDamon Ding 2064ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id); 2065ee01dbb2SDamon Ding if (cstate->splice_mode) 2066ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id); 2067ee01dbb2SDamon Ding } 2068ee01dbb2SDamon Ding 2069ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id) 2070ee01dbb2SDamon Ding { 2071ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 2072ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 2073ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 2074ee01dbb2SDamon Ding u32 bg_ovl_dly, bg_dly, pre_scan_dly; 2075ee01dbb2SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 2076ee01dbb2SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2077ee01dbb2SDamon Ding 2078ee01dbb2SDamon Ding bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly; 2079ee01dbb2SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly; 2080ee01dbb2SDamon Ding bg_dly -= bg_ovl_dly; 2081ee01dbb2SDamon Ding 2082a552a69cSDamon Ding /* 2083a552a69cSDamon Ding * splice mode: hdisplay must roundup as 4 pixel, 2084a552a69cSDamon Ding * no splice mode: hdisplay must roundup as 2 pixel. 2085a552a69cSDamon Ding */ 2086ee01dbb2SDamon Ding if (cstate->splice_mode) 2087a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1; 2088ee01dbb2SDamon Ding else 2089a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1; 2090ee01dbb2SDamon Ding 2091ee01dbb2SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 2092ee01dbb2SDamon Ding hsync_len = 8; 2093ee01dbb2SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 2094ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4, 2095ee01dbb2SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 2096ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 2097ac500a1fSSandy Huang } 2098ac500a1fSSandy Huang 2099452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id) 2100452afb13SDamon Ding { 2101452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 2102452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 2103452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 2104452afb13SDamon Ding struct vop2_win_data *win_data; 2105452afb13SDamon Ding u32 bg_dly, pre_scan_dly; 2106452afb13SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 2107452afb13SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2108452afb13SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 2109452afb13SDamon Ding u8 win_id; 2110452afb13SDamon Ding 2111452afb13SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 2112452afb13SDamon Ding win_id = atoi(&win_data->name[strlen(win_data->name) - 1]); 2113452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL + win_id * 4, 2114452afb13SDamon Ding ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 0, false); 2115452afb13SDamon Ding 2116452afb13SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].win_dly + 2117452afb13SDamon Ding vop2->data->vp_data[crtc_id].layer_mix_dly + 2118452afb13SDamon Ding vop2->data->vp_data[crtc_id].hdr_mix_dly; 2119a552a69cSDamon Ding /* hdisplay must roundup as 2 pixel */ 2120a552a69cSDamon Ding pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1; 2121a552a69cSDamon Ding /** 2122a552a69cSDamon Ding * pre_scan_hblank minimum value is 8, otherwise the win reset signal will 2123a552a69cSDamon Ding * lead to first line data be zero. 2124a552a69cSDamon Ding */ 2125a552a69cSDamon Ding pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len); 2126452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100, 2127452afb13SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 2128452afb13SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 2129452afb13SDamon Ding } 2130452afb13SDamon Ding 2131d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 2132d0408543SAndy Yan { 2133d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 2134d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 213552ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state; 213652ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2137d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal; 2138d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 2139d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 2140d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2141d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay; 2142d0408543SAndy Yan u16 hsize = 2143d0408543SAndy Yan hdisplay * (conn_state->overscan.left_margin + 2144d0408543SAndy Yan conn_state->overscan.right_margin) / 200; 2145d0408543SAndy Yan u16 vsize = 2146d0408543SAndy Yan vdisplay * (conn_state->overscan.top_margin + 2147d0408543SAndy Yan conn_state->overscan.bottom_margin) / 200; 2148d0408543SAndy Yan u16 hact_end, vact_end; 2149d0408543SAndy Yan u32 val; 2150d0408543SAndy Yan 215174bd8269SSandy Huang hsize = round_down(hsize, 2); 2152d0408543SAndy Yan vsize = round_down(vsize, 2); 2153d0408543SAndy Yan 2154d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 2155d0408543SAndy Yan hact_end = hact_st + hsize; 2156d0408543SAndy Yan val = hact_st << 16; 2157d0408543SAndy Yan val |= hact_end; 2158d0408543SAndy Yan 215952ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 2160d0408543SAndy Yan vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 2161d0408543SAndy Yan vact_end = vact_st + vsize; 2162d0408543SAndy Yan val = vact_st << 16; 2163d0408543SAndy Yan val |= vact_end; 216452ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 2165d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16; 2166d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize); 216752ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 2168d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 2169d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 21707504507fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 21717504507fSSandy Huang RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT, 2172d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 21737504507fSSandy Huang POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false); 2174d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 2175d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 2176d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize; 2177d0408543SAndy Yan 2178d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 217952ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 2180d0408543SAndy Yan } 2181d0408543SAndy Yan 2182452afb13SDamon Ding if (is_vop3(vop2)) { 2183452afb13SDamon Ding vop3_setup_pipe_dly(state, vop2, cstate->crtc_id); 2184452afb13SDamon Ding } else { 2185ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id); 2186ee01dbb2SDamon Ding if (cstate->splice_mode) 2187ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id); 2188d0408543SAndy Yan } 2189452afb13SDamon Ding } 2190d0408543SAndy Yan 21916027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2) 21926027c871SZhang Yubing { 21936027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 21946027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 21956027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 21966027c871SZhang Yubing struct drm_display_mode *mode = &conn_state->mode; 21976027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 21986027c871SZhang Yubing s16 *lut_y; 21996027c871SZhang Yubing s16 *lut_h; 22006027c871SZhang Yubing s16 *lut_s; 22016027c871SZhang Yubing u32 value; 22026027c871SZhang Yubing int i; 22036027c871SZhang Yubing 22046027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2205b8db91d0SZhang Yubing POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 2206b8db91d0SZhang Yubing if (!acm->acm_enable) { 2207b8db91d0SZhang Yubing writel(0, vop2->regs + RK3528_ACM_CTRL); 22086027c871SZhang Yubing return; 22096027c871SZhang Yubing } 22106027c871SZhang Yubing 22116027c871SZhang Yubing printf("post acm enable\n"); 22126027c871SZhang Yubing 22136027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_START); 22146027c871SZhang Yubing 22156027c871SZhang Yubing value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) + 22166027c871SZhang Yubing ((mode->vdisplay & 0xfff) << 20); 22176027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_CTRL); 22186027c871SZhang Yubing 22196027c871SZhang Yubing value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + 22206027c871SZhang Yubing ((acm->s_gain << 20) & 0x3ff00000); 22216027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE); 22226027c871SZhang Yubing 22236027c871SZhang Yubing lut_y = &acm->gain_lut_hy[0]; 22246027c871SZhang Yubing lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH]; 22256027c871SZhang Yubing lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2]; 22266027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) { 22276027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 22286027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 22296027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2)); 22306027c871SZhang Yubing } 22316027c871SZhang Yubing 22326027c871SZhang Yubing lut_y = &acm->gain_lut_hs[0]; 22336027c871SZhang Yubing lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH]; 22346027c871SZhang Yubing lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2]; 22356027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) { 22366027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 22376027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 22386027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2)); 22396027c871SZhang Yubing } 22406027c871SZhang Yubing 22416027c871SZhang Yubing lut_y = &acm->delta_lut_h[0]; 22426027c871SZhang Yubing lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH]; 22436027c871SZhang Yubing lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2]; 22446027c871SZhang Yubing for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) { 22456027c871SZhang Yubing value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) + 22466027c871SZhang Yubing ((lut_s[i] << 20) & 0x3ff00000); 22476027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2)); 22486027c871SZhang Yubing } 22496027c871SZhang Yubing 22506027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_DONE); 22516027c871SZhang Yubing } 22526027c871SZhang Yubing 22536027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2) 22546027c871SZhang Yubing { 22556027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 22566027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 22576027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 22586027c871SZhang Yubing struct csc_info *csc = &conn_state->disp_info->csc_info; 22596027c871SZhang Yubing struct post_csc_coef csc_coef; 22606027c871SZhang Yubing bool is_input_yuv = false; 22616027c871SZhang Yubing bool is_output_yuv = false; 22626027c871SZhang Yubing bool post_r2y_en = false; 22636027c871SZhang Yubing bool post_csc_en = false; 22646027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 22656027c871SZhang Yubing u32 value; 22666027c871SZhang Yubing int range_type; 22676027c871SZhang Yubing 22686027c871SZhang Yubing printf("post csc enable\n"); 22696027c871SZhang Yubing 22706027c871SZhang Yubing if (acm->acm_enable) { 22716027c871SZhang Yubing if (!cstate->yuv_overlay) 22726027c871SZhang Yubing post_r2y_en = true; 22736027c871SZhang Yubing 22746027c871SZhang Yubing /* do y2r in csc module */ 22756027c871SZhang Yubing if (!is_yuv_output(conn_state->bus_format)) 22766027c871SZhang Yubing post_csc_en = true; 22776027c871SZhang Yubing } else { 22786027c871SZhang Yubing if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 22796027c871SZhang Yubing post_r2y_en = true; 22806027c871SZhang Yubing 22816027c871SZhang Yubing /* do y2r in csc module */ 22826027c871SZhang Yubing if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 22836027c871SZhang Yubing post_csc_en = true; 22846027c871SZhang Yubing } 22856027c871SZhang Yubing 22866027c871SZhang Yubing if (csc->csc_enable) 22876027c871SZhang Yubing post_csc_en = true; 22886027c871SZhang Yubing 22896027c871SZhang Yubing if (cstate->yuv_overlay || post_r2y_en) 22906027c871SZhang Yubing is_input_yuv = true; 22916027c871SZhang Yubing 22926027c871SZhang Yubing if (is_yuv_output(conn_state->bus_format)) 22936027c871SZhang Yubing is_output_yuv = true; 22946027c871SZhang Yubing 2295df0a5c43SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, 2296df0a5c43SDamon Ding conn_state->color_range, 2297df0a5c43SDamon Ding CSC_13BIT_DEPTH); 22986027c871SZhang Yubing 22996027c871SZhang Yubing if (post_csc_en) { 23006027c871SZhang Yubing rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv, 23016027c871SZhang Yubing is_output_yuv); 23026027c871SZhang Yubing 23036027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23046027c871SZhang Yubing POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT, 23056027c871SZhang Yubing csc_coef.csc_coef00, false); 23065743c73eSZhang Yubing value = csc_coef.csc_coef01 & 0xffff; 23075743c73eSZhang Yubing value |= (csc_coef.csc_coef02 << 16) & 0xffff0000; 23086027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02); 23095743c73eSZhang Yubing value = csc_coef.csc_coef10 & 0xffff; 23105743c73eSZhang Yubing value |= (csc_coef.csc_coef11 << 16) & 0xffff0000; 23116027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11); 23125743c73eSZhang Yubing value = csc_coef.csc_coef12 & 0xffff; 23135743c73eSZhang Yubing value |= (csc_coef.csc_coef20 << 16) & 0xffff0000; 23146027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20); 23155743c73eSZhang Yubing value = csc_coef.csc_coef21 & 0xffff; 23165743c73eSZhang Yubing value |= (csc_coef.csc_coef22 << 16) & 0xffff0000; 23176027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22); 23186027c871SZhang Yubing writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0); 23196027c871SZhang Yubing writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1); 23206027c871SZhang Yubing writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2); 23216027c871SZhang Yubing 23226027c871SZhang Yubing range_type = csc_coef.range_type ? 0 : 1; 23236027c871SZhang Yubing range_type <<= is_input_yuv ? 0 : 1; 23246027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23256027c871SZhang Yubing POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false); 23266027c871SZhang Yubing } 23276027c871SZhang Yubing 23286027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23295743c73eSZhang Yubing POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false); 23306027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23316027c871SZhang Yubing POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false); 23326027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 23336027c871SZhang Yubing POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false); 23346027c871SZhang Yubing } 23356027c871SZhang Yubing 23366027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2) 23376027c871SZhang Yubing { 23386027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 23396027c871SZhang Yubing struct base2_disp_info *disp_info = conn_state->disp_info; 23406027c871SZhang Yubing const char *enable_flag; 23416027c871SZhang Yubing if (!disp_info) { 23426027c871SZhang Yubing printf("disp_info is empty\n"); 23436027c871SZhang Yubing return; 23446027c871SZhang Yubing } 23456027c871SZhang Yubing 23466027c871SZhang Yubing enable_flag = (const char *)&disp_info->cacm_header; 23476027c871SZhang Yubing if (strncasecmp(enable_flag, "CACM", 4)) { 23486027c871SZhang Yubing printf("acm and csc is not support\n"); 23496027c871SZhang Yubing return; 23506027c871SZhang Yubing } 23516027c871SZhang Yubing 23526027c871SZhang Yubing vop3_post_acm_config(state, vop2); 23536027c871SZhang Yubing vop3_post_csc_config(state, vop2); 23546027c871SZhang Yubing } 23556027c871SZhang Yubing 2356a552a69cSDamon Ding static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2, 2357a552a69cSDamon Ding struct vop2_power_domain_data *pd_data) 2358a552a69cSDamon Ding { 2359a552a69cSDamon Ding int val = 0; 2360a552a69cSDamon Ding bool is_bisr_en, is_otp_bisr_en; 2361a552a69cSDamon Ding 2362a552a69cSDamon Ding if (pd_data->id == VOP2_PD_CLUSTER) { 2363a552a69cSDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0, 2364a552a69cSDamon Ding EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT); 2365a552a69cSDamon Ding is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0, 2366a552a69cSDamon Ding EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT); 2367a552a69cSDamon Ding if (is_bisr_en && is_otp_bisr_en) 2368a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 2369a552a69cSDamon Ding val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1), 2370a552a69cSDamon Ding 50 * 1000); 2371a552a69cSDamon Ding else 2372a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS, 2373*0e0a0ff9SDamon Ding val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1), 2374a552a69cSDamon Ding 50 * 1000); 2375a552a69cSDamon Ding } else { 2376a552a69cSDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0, 2377a552a69cSDamon Ding EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT); 2378a552a69cSDamon Ding is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0, 2379a552a69cSDamon Ding EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT); 2380a552a69cSDamon Ding if (is_bisr_en && is_otp_bisr_en) 2381a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 2382a552a69cSDamon Ding val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1), 2383a552a69cSDamon Ding 50 * 1000); 2384a552a69cSDamon Ding else 2385a552a69cSDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS, 2386a552a69cSDamon Ding val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1), 2387a552a69cSDamon Ding 50 * 1000); 2388a552a69cSDamon Ding } 2389a552a69cSDamon Ding } 2390a552a69cSDamon Ding 2391a552a69cSDamon Ding static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 2392a552a69cSDamon Ding { 2393a552a69cSDamon Ding int ret = 0; 2394a552a69cSDamon Ding 2395a552a69cSDamon Ding if (pd_data->id == VOP2_PD_CLUSTER) 2396a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK, 2397a552a69cSDamon Ding RK3576_CLUSTER_PD_EN_SHIFT, 0, true); 2398a552a69cSDamon Ding else 2399a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK, 2400a552a69cSDamon Ding RK3576_ESMART_PD_EN_SHIFT, 0, true); 2401a552a69cSDamon Ding ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data); 2402a552a69cSDamon Ding if (ret) { 2403a552a69cSDamon Ding printf("wait vop2 power domain timeout\n"); 2404a552a69cSDamon Ding return ret; 2405a552a69cSDamon Ding } 2406a552a69cSDamon Ding 2407a552a69cSDamon Ding return 0; 2408a552a69cSDamon Ding } 2409a552a69cSDamon Ding 2410a552a69cSDamon Ding static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2, 2411a552a69cSDamon Ding struct vop2_power_domain_data *pd_data) 241260e469f5SDamon Ding { 241360e469f5SDamon Ding int val = 0; 241460e469f5SDamon Ding int shift = 0; 2415b6ba80b4SDamon Ding int shift_factor = 0; 241660e469f5SDamon Ding bool is_bisr_en = false; 241760e469f5SDamon Ding 2418b6ba80b4SDamon Ding /* 2419b6ba80b4SDamon Ding * The order of pd status bits in BISR_STS register 2420b6ba80b4SDamon Ding * is different from that in VOP SYS_STS register. 2421b6ba80b4SDamon Ding */ 2422b6ba80b4SDamon Ding if (pd_data->id == VOP2_PD_DSC_8K || 2423b6ba80b4SDamon Ding pd_data->id == VOP2_PD_DSC_4K || 2424b6ba80b4SDamon Ding pd_data->id == VOP2_PD_ESMART) 2425b6ba80b4SDamon Ding shift_factor = 1; 2426b6ba80b4SDamon Ding 2427b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor; 2428b6ba80b4SDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift); 242960e469f5SDamon Ding if (is_bisr_en) { 2430b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor; 2431b6ba80b4SDamon Ding 243260e469f5SDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 2433d2e91fdcSDamon Ding ((val >> shift) & 0x1), 50 * 1000); 243460e469f5SDamon Ding } else { 2435b6ba80b4SDamon Ding shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1; 2436b6ba80b4SDamon Ding 243760e469f5SDamon Ding return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 243860e469f5SDamon Ding !((val >> shift) & 0x1), 50 * 1000); 243960e469f5SDamon Ding } 244060e469f5SDamon Ding } 244160e469f5SDamon Ding 2442a552a69cSDamon Ding static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 2443a552a69cSDamon Ding { 2444a552a69cSDamon Ding int ret = 0; 2445a552a69cSDamon Ding 2446a552a69cSDamon Ding vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK, 2447a552a69cSDamon Ding RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false); 2448a552a69cSDamon Ding ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data); 2449a552a69cSDamon Ding if (ret) { 2450a552a69cSDamon Ding printf("wait vop2 power domain timeout\n"); 2451a552a69cSDamon Ding return ret; 2452a552a69cSDamon Ding } 2453a552a69cSDamon Ding 2454a552a69cSDamon Ding return 0; 2455a552a69cSDamon Ding } 2456a552a69cSDamon Ding 2457b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id) 245860e469f5SDamon Ding { 245960e469f5SDamon Ding struct vop2_power_domain_data *pd_data; 246060e469f5SDamon Ding int ret = 0; 246160e469f5SDamon Ding 2462b6ba80b4SDamon Ding if (!pd_id) 2463b6ba80b4SDamon Ding return 0; 2464b6ba80b4SDamon Ding 2465b6ba80b4SDamon Ding pd_data = vop2_find_pd_data_by_id(vop2, pd_id); 2466b6ba80b4SDamon Ding if (!pd_data) { 2467b6ba80b4SDamon Ding printf("can't find pd_data by id\n"); 246860e469f5SDamon Ding return -EINVAL; 246960e469f5SDamon Ding } 24702c66af11SDamon Ding 2471b6ba80b4SDamon Ding if (pd_data->parent_id) { 2472b6ba80b4SDamon Ding ret = vop2_power_domain_on(vop2, pd_data->parent_id); 247360e469f5SDamon Ding if (ret) { 247460e469f5SDamon Ding printf("can't open parent power domain\n"); 247560e469f5SDamon Ding return -EINVAL; 247660e469f5SDamon Ding } 247760e469f5SDamon Ding } 247860e469f5SDamon Ding 2479a552a69cSDamon Ding /* 2480a552a69cSDamon Ding * Read VOP internal power domain on/off status. 2481a552a69cSDamon Ding * We should query BISR_STS register in PMU for 2482a552a69cSDamon Ding * power up/down status when memory repair is enabled. 2483a552a69cSDamon Ding * Return value: 1 for power on, 0 for power off; 2484a552a69cSDamon Ding */ 2485a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 2486a552a69cSDamon Ding ret = rk3576_vop2_power_domain_on(vop2, pd_data); 2487a552a69cSDamon Ding else 2488a552a69cSDamon Ding ret = rk3588_vop2_power_domain_on(vop2, pd_data); 248960e469f5SDamon Ding 2490a552a69cSDamon Ding return ret; 249160e469f5SDamon Ding } 249260e469f5SDamon Ding 2493ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2) 2494ecc31b6eSAndy Yan { 2495ecc31b6eSAndy Yan u32 *base = vop2->regs; 2496ecc31b6eSAndy Yan int i = 0; 2497ecc31b6eSAndy Yan 2498ecc31b6eSAndy Yan /* 2499ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 2500ecc31b6eSAndy Yan */ 2501ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++) 2502ecc31b6eSAndy Yan vop2->regsbak[i] = base[i]; 2503ecc31b6eSAndy Yan } 2504ecc31b6eSAndy Yan 25055fa6e665SDamon Ding static void vop3_overlay_init(struct vop2 *vop2, struct display_state *state) 25065fa6e665SDamon Ding { 25075fa6e665SDamon Ding struct vop2_win_data *win_data; 25085fa6e665SDamon Ding int layer_phy_id = 0; 25095fa6e665SDamon Ding int i, j; 25105fa6e665SDamon Ding u32 ovl_port_offset = 0; 25115fa6e665SDamon Ding u32 layer_nr = 0; 25125fa6e665SDamon Ding u8 shift = 0; 25135fa6e665SDamon Ding 25145fa6e665SDamon Ding /* layer sel win id */ 25155fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 25165fa6e665SDamon Ding shift = 0; 25175fa6e665SDamon Ding ovl_port_offset = 0x100 * i; 25185fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 25195fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 25205fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 25215fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 25225fa6e665SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + ovl_port_offset, LAYER_SEL_MASK, 25235fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 25245fa6e665SDamon Ding shift += 4; 25255fa6e665SDamon Ding } 25265fa6e665SDamon Ding } 25275fa6e665SDamon Ding 2528a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3576) { 25295fa6e665SDamon Ding /* win sel port */ 25305fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 25315fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 25325fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 25335fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 25345fa6e665SDamon Ding continue; 25355fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 25365fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 25375fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 2538a552a69cSDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL, 2539a552a69cSDamon Ding LAYER_SEL_PORT_MASK, shift, i, false); 2540a552a69cSDamon Ding } 25415fa6e665SDamon Ding } 25425fa6e665SDamon Ding } 25435fa6e665SDamon Ding } 25445fa6e665SDamon Ding 25455fa6e665SDamon Ding static void vop2_overlay_init(struct vop2 *vop2, struct display_state *state) 25465fa6e665SDamon Ding { 25475fa6e665SDamon Ding struct crtc_state *cstate = &state->crtc_state; 25485fa6e665SDamon Ding struct vop2_win_data *win_data; 25495fa6e665SDamon Ding int layer_phy_id = 0; 25505fa6e665SDamon Ding int total_used_layer = 0; 25515fa6e665SDamon Ding int port_mux = 0; 25525fa6e665SDamon Ding int i, j; 25535fa6e665SDamon Ding u32 layer_nr = 0; 25545fa6e665SDamon Ding u8 shift = 0; 25555fa6e665SDamon Ding 25565fa6e665SDamon Ding /* layer sel win id */ 25575fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 25585fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 25595fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 25605fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 25615fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 25625fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 25635fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 25645fa6e665SDamon Ding shift += 4; 25655fa6e665SDamon Ding } 25665fa6e665SDamon Ding } 25675fa6e665SDamon Ding 25685fa6e665SDamon Ding /* win sel port */ 25695fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 25705fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 25715fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 25725fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 25735fa6e665SDamon Ding continue; 25745fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 25755fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 25765fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 25775fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 25785fa6e665SDamon Ding LAYER_SEL_PORT_SHIFT + shift, i, false); 25795fa6e665SDamon Ding } 25805fa6e665SDamon Ding } 25815fa6e665SDamon Ding 25825fa6e665SDamon Ding /** 25835fa6e665SDamon Ding * port mux config 25845fa6e665SDamon Ding */ 25855fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 25865fa6e665SDamon Ding shift = i * 4; 25875fa6e665SDamon Ding if (vop2->vp_plane_mask[i].attached_layers_nr) { 25885fa6e665SDamon Ding total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 25895fa6e665SDamon Ding port_mux = total_used_layer - 1; 25905fa6e665SDamon Ding } else { 25915fa6e665SDamon Ding port_mux = 8; 25925fa6e665SDamon Ding } 25935fa6e665SDamon Ding 25945fa6e665SDamon Ding if (i == vop2->data->nr_vps - 1) 25955fa6e665SDamon Ding port_mux = vop2->data->nr_mixers; 25965fa6e665SDamon Ding 25975fa6e665SDamon Ding cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 25985fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 25995fa6e665SDamon Ding PORT_MUX_SHIFT + shift, port_mux, false); 26005fa6e665SDamon Ding } 26015fa6e665SDamon Ding } 26025fa6e665SDamon Ding 26035fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win) 26045fa6e665SDamon Ding { 26055fa6e665SDamon Ding if (!is_vop3(vop2)) 26065fa6e665SDamon Ding return false; 26075fa6e665SDamon Ding 26085fa6e665SDamon Ding if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE && 26095fa6e665SDamon Ding win->phys_id != ROCKCHIP_VOP2_ESMART0) 26105fa6e665SDamon Ding return true; 26115fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE && 26125fa6e665SDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) 26135fa6e665SDamon Ding return true; 26145fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && 26155fa6e665SDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART1) 26165fa6e665SDamon Ding return true; 2617a552a69cSDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE && 2618a552a69cSDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART3) 2619a552a69cSDamon Ding return true; 26205fa6e665SDamon Ding else 26215fa6e665SDamon Ding return false; 26225fa6e665SDamon Ding } 26235fa6e665SDamon Ding 26245fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2) 26255fa6e665SDamon Ding { 26265fa6e665SDamon Ding struct vop2_win_data *win_data; 2627fa4ecc32SDamon Ding int i; 26285fa6e665SDamon Ding u8 scale_engine_num = 0; 26295fa6e665SDamon Ding 26305fa6e665SDamon Ding /* store plane mask for vop2_fixup_dts */ 2631fa4ecc32SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 2632fa4ecc32SDamon Ding win_data = &vop2->data->win_data[i]; 26335fa6e665SDamon Ding if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data)) 26345fa6e665SDamon Ding continue; 26355fa6e665SDamon Ding 26365fa6e665SDamon Ding win_data->scale_engine_num = scale_engine_num++; 26375fa6e665SDamon Ding } 26385fa6e665SDamon Ding } 26395fa6e665SDamon Ding 2640a552a69cSDamon Ding static int vop3_get_esmart_lb_mode(struct vop2 *vop2) 2641a552a69cSDamon Ding { 2642a552a69cSDamon Ding const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map; 2643a552a69cSDamon Ding int i; 2644a552a69cSDamon Ding 2645a552a69cSDamon Ding if (!esmart_lb_mode_map) 2646a552a69cSDamon Ding return vop2->esmart_lb_mode; 2647a552a69cSDamon Ding 2648a552a69cSDamon Ding for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) { 2649a552a69cSDamon Ding if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode) 2650a552a69cSDamon Ding return esmart_lb_mode_map->lb_map_value; 2651a552a69cSDamon Ding esmart_lb_mode_map++; 2652a552a69cSDamon Ding } 2653a552a69cSDamon Ding 2654a552a69cSDamon Ding if (i == vop2->data->esmart_lb_mode_num) 2655a552a69cSDamon Ding printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode); 2656a552a69cSDamon Ding 2657a552a69cSDamon Ding return vop2->data->esmart_lb_mode_map[0].lb_map_value; 2658a552a69cSDamon Ding } 2659a552a69cSDamon Ding 2660b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 2661d0408543SAndy Yan { 2662b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 2663b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 2664a552a69cSDamon Ding int active_vp_num = 0; 26655fa6e665SDamon Ding int layer_phy_id = 0; 26665fa6e665SDamon Ding int i, j; 2667fa4ecc32SDamon Ding int ret; 26685fa6e665SDamon Ding u32 layer_nr = 0; 2669d0408543SAndy Yan 267063cb669fSSandy Huang if (vop2->global_init) 2671d0408543SAndy Yan return; 267263cb669fSSandy Huang 2673b0989546SSandy Huang /* OTP must enable at the first time, otherwise mirror layer register is error */ 267463cb669fSSandy Huang if (soc_is_rk3566()) 267563cb669fSSandy Huang vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 267663cb669fSSandy Huang OTP_WIN_EN_SHIFT, 1, false); 2677b0989546SSandy Huang 2678b0989546SSandy Huang if (cstate->crtc->assign_plane) {/* dts assign plane */ 2679b0989546SSandy Huang u32 plane_mask; 2680b0989546SSandy Huang int primary_plane_id; 2681b0989546SSandy Huang 2682b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2683b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask; 2684b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2685b0989546SSandy Huang layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 2686b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 26875fc2b656SDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 2688337d1c13SDamon Ding if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX) 2689b0989546SSandy Huang primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 2690b0989546SSandy Huang vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 2691b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2692b0989546SSandy Huang 2693b0989546SSandy Huang /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 2694b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2695b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 2696b0989546SSandy Huang plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 269763cb669fSSandy Huang } 2698b0989546SSandy Huang } 2699b0989546SSandy Huang } else {/* need soft assign plane mask */ 2700a552a69cSDamon Ding printf("Assign plane mask automatically\n"); 2701a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 2702a552a69cSDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 2703a552a69cSDamon Ding if (cstate->crtc->vps[i].enable) { 2704a552a69cSDamon Ding vop2->vp_plane_mask[i].attached_layers_nr = 1; 2705a552a69cSDamon Ding vop2->vp_plane_mask[i].primary_plane_id = 2706a552a69cSDamon Ding vop2->data->vp_default_primary_plane[i]; 2707a552a69cSDamon Ding vop2->vp_plane_mask[i].attached_layers[0] = 2708a552a69cSDamon Ding vop2->data->vp_default_primary_plane[i]; 2709a552a69cSDamon Ding vop2->vp_plane_mask[i].plane_mask |= 2710a552a69cSDamon Ding BIT(vop2->data->vp_default_primary_plane[i]); 2711a552a69cSDamon Ding active_vp_num++; 2712a552a69cSDamon Ding } 2713a552a69cSDamon Ding } 2714a552a69cSDamon Ding printf("VOP have %d active VP\n", active_vp_num); 2715a552a69cSDamon Ding } else { 2716b0989546SSandy Huang /* find the first unplug devices and set it as main display */ 2717b0989546SSandy Huang int main_vp_index = -1; 2718b0989546SSandy Huang 2719b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2720b0989546SSandy Huang if (cstate->crtc->vps[i].enable) 2721b0989546SSandy Huang active_vp_num++; 2722b0989546SSandy Huang } 2723b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num); 2724b0989546SSandy Huang 2725b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2) 2726b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n"); 2727b0989546SSandy Huang plane_mask = vop2->data->plane_mask; 2728b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 27295fa6e665SDamon Ding /* 2730a552a69cSDamon Ding * For rk3528, one display policy for hdmi store in plane_mask[0], and 2731a552a69cSDamon Ding * the other for cvbs store in plane_mask[2]. 27325fa6e665SDamon Ding */ 27335fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 && 27345fa6e665SDamon Ding cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV) 27355fa6e665SDamon Ding plane_mask += 2 * VOP2_VP_MAX; 2736b0989546SSandy Huang 27375fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528) { 27385fa6e665SDamon Ding /* 2739a552a69cSDamon Ding * For rk3528, the plane mask of vp is limited, only esmart2 can 2740a552a69cSDamon Ding * be selected by both vp0 and vp1. 27415fa6e665SDamon Ding */ 27425fa6e665SDamon Ding j = 0; 27435fa6e665SDamon Ding } else { 2744b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2745b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 2746a552a69cSDamon Ding /* the first store main display plane mask */ 2747a552a69cSDamon Ding vop2->vp_plane_mask[i] = plane_mask[0]; 2748b0989546SSandy Huang main_vp_index = i; 2749e007876dSSandy Huang break; 2750b0989546SSandy Huang } 2751b0989546SSandy Huang } 2752b0989546SSandy Huang 2753b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */ 2754b0989546SSandy Huang if (main_vp_index < 0) { 2755b0989546SSandy Huang main_vp_index = 0; 2756b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0]; 2757b0989546SSandy Huang } 2758b0989546SSandy Huang 2759a552a69cSDamon Ding /* plane_mask[0] store main display, so we from plane_mask[1] */ 2760a552a69cSDamon Ding j = 1; 27615fa6e665SDamon Ding } 2762b0989546SSandy Huang 2763b0989546SSandy Huang /* init other display except main display */ 2764b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2765a552a69cSDamon Ding /* main display or no connect devices */ 2766a552a69cSDamon Ding if (i == main_vp_index || !cstate->crtc->vps[i].enable) 2767b0989546SSandy Huang continue; 2768b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++]; 2769b0989546SSandy Huang } 2770a552a69cSDamon Ding } 2771b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */ 2772b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2773b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 2774b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2775b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 2776b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 2777b0989546SSandy Huang } 2778b0989546SSandy Huang } 2779b0989546SSandy Huang } 2780b0989546SSandy Huang 278160e469f5SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 278260e469f5SDamon Ding rk3588_vop2_regsbak(vop2); 278360e469f5SDamon Ding else 278460e469f5SDamon Ding memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 278560e469f5SDamon Ding 278660e469f5SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 278760e469f5SDamon Ding OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 278860e469f5SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 278960e469f5SDamon Ding IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 279060e469f5SDamon Ding 2791b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2792b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 2793b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 279427cec8e2SDamon Ding printf("%s ", 279527cec8e2SDamon Ding vop2_plane_id_to_string(vop2->vp_plane_mask[i].attached_layers[j])); 279627cec8e2SDamon Ding printf("], primary plane: %s\n", 279727cec8e2SDamon Ding vop2_plane_id_to_string(vop2->vp_plane_mask[i].primary_plane_id)); 2798b0989546SSandy Huang } 2799b0989546SSandy Huang 28005fa6e665SDamon Ding if (is_vop3(vop2)) 28015fa6e665SDamon Ding vop3_overlay_init(vop2, state); 28025fa6e665SDamon Ding else 28035fa6e665SDamon Ding vop2_overlay_init(vop2, state); 2804b0989546SSandy Huang 28055fa6e665SDamon Ding if (is_vop3(vop2)) { 28065fa6e665SDamon Ding /* 28075fa6e665SDamon Ding * you can rewrite at dts vop node: 28085fa6e665SDamon Ding * 28095fa6e665SDamon Ding * VOP3_ESMART_8K_MODE = 0, 28105fa6e665SDamon Ding * VOP3_ESMART_4K_4K_MODE = 1, 28115fa6e665SDamon Ding * VOP3_ESMART_4K_2K_2K_MODE = 2, 28125fa6e665SDamon Ding * VOP3_ESMART_2K_2K_2K_2K_MODE = 3, 28135fa6e665SDamon Ding * 28145fa6e665SDamon Ding * &vop { 28155fa6e665SDamon Ding * esmart_lb_mode = /bits/ 8 <2>; 28165fa6e665SDamon Ding * }; 281763cb669fSSandy Huang */ 2818fa4ecc32SDamon Ding ret = ofnode_read_u32(cstate->node, "esmart_lb_mode", &vop2->esmart_lb_mode); 2819fa4ecc32SDamon Ding if (ret < 0) 28205fa6e665SDamon Ding vop2->esmart_lb_mode = vop2->data->esmart_lb_mode; 2821a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 2822a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, 2823a552a69cSDamon Ding RK3576_ESMART_LB_MODE_SEL_MASK, 2824a552a69cSDamon Ding RK3576_ESMART_LB_MODE_SEL_SHIFT, 2825a552a69cSDamon Ding vop3_get_esmart_lb_mode(vop2), true); 2826a552a69cSDamon Ding else 2827a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 2828a552a69cSDamon Ding ESMART_LB_MODE_SEL_MASK, 2829a552a69cSDamon Ding ESMART_LB_MODE_SEL_SHIFT, 2830f6e9a2a3SDamon Ding vop3_get_esmart_lb_mode(vop2), false); 2831d0408543SAndy Yan 28325fa6e665SDamon Ding vop3_init_esmart_scale_engine(vop2); 2833aa670293SDamon Ding 283412ee4de7SDamon Ding if (vop2->version == VOP_VERSION_RK3576) 283512ee4de7SDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK, 283612ee4de7SDamon Ding RK3576_DSP_VS_T_SEL_SHIFT, 0, true); 283712ee4de7SDamon Ding else 2838aa670293SDamon Ding vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK, 2839aa670293SDamon Ding DSP_VS_T_SEL_SHIFT, 0, false); 2840bb7ec356SDamon Ding 2841bb7ec356SDamon Ding /* 2842bb7ec356SDamon Ding * This is a workaround for RK3528/RK3562/RK3576: 2843bb7ec356SDamon Ding * 2844bb7ec356SDamon Ding * The aclk pre auto gating function may disable the aclk 2845bb7ec356SDamon Ding * in some unexpected cases, which detected by hardware 2846bb7ec356SDamon Ding * automatically. 2847bb7ec356SDamon Ding * 2848bb7ec356SDamon Ding * For example, if the above function is enabled, the post 2849bb7ec356SDamon Ding * scale function will be affected, resulting in abnormal 2850bb7ec356SDamon Ding * display. 2851bb7ec356SDamon Ding */ 2852bb7ec356SDamon Ding if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 || 2853bb7ec356SDamon Ding vop2->version == VOP_VERSION_RK3576) 2854bb7ec356SDamon Ding vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK, 2855bb7ec356SDamon Ding ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false); 285663cb669fSSandy Huang } 285763cb669fSSandy Huang 2858ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568) 285963cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 286063cb669fSSandy Huang 2861a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 2862a552a69cSDamon Ding vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq"); 2863a552a69cSDamon Ding 2864f67105fbSSandy Huang /* Default use rkiommu 1.0 for axi0 */ 2865f67105fbSSandy Huang vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 0, true); 2866a552a69cSDamon Ding 2867a552a69cSDamon Ding /* Init frc2.0 config */ 2868a552a69cSDamon Ding vop2_writel(vop2, 0xca0, 0xc8); 2869a552a69cSDamon Ding vop2_writel(vop2, 0xca4, 0x01000100); 2870a552a69cSDamon Ding vop2_writel(vop2, 0xca8, 0x03ff0100); 2871a552a69cSDamon Ding vop2_writel(vop2, 0xda0, 0xc8); 2872a552a69cSDamon Ding vop2_writel(vop2, 0xda4, 0x01000100); 2873a552a69cSDamon Ding vop2_writel(vop2, 0xda8, 0x03ff0100); 2874a552a69cSDamon Ding 2875a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true) 2876a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK, 2877a552a69cSDamon Ding VP_INTR_MERGE_EN_SHIFT, 1, true); 2878a552a69cSDamon Ding 2879a552a69cSDamon Ding /* Set reg done every field for interlace */ 2880a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK, 2881a552a69cSDamon Ding INTERLACE_FRM_REG_DONE_SHIFT, 0, false); 2882a552a69cSDamon Ding } 2883a552a69cSDamon Ding 288463cb669fSSandy Huang vop2->global_init = true; 2885d0408543SAndy Yan } 2886d0408543SAndy Yan 2887344e932aSDamon Ding static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state) 2888344e932aSDamon Ding { 2889344e932aSDamon Ding struct crtc_state *cstate = &state->crtc_state; 2890344e932aSDamon Ding const struct vop2_data *vop2_data = vop2->data; 2891344e932aSDamon Ding const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id]; 2892344e932aSDamon Ding struct resource sharp_regs; 2893344e932aSDamon Ding u32 *sharp_reg_base; 2894344e932aSDamon Ding int ret; 2895344e932aSDamon Ding 2896344e932aSDamon Ding if (!(vp_data->feature & VOP_FEATURE_POST_SHARP)) 2897344e932aSDamon Ding return; 2898344e932aSDamon Ding 2899344e932aSDamon Ding ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs); 2900344e932aSDamon Ding if (ret) { 2901344e932aSDamon Ding printf("failed to get sharp regs\n"); 2902344e932aSDamon Ding return; 2903344e932aSDamon Ding } 2904344e932aSDamon Ding sharp_reg_base = (u32 *)sharp_regs.start; 2905344e932aSDamon Ding 2906344e932aSDamon Ding /* 2907344e932aSDamon Ding * After vop initialization, keep sw_sharp_enable always on. 2908344e932aSDamon Ding * Only enable/disable sharp submodule to avoid black screen. 2909344e932aSDamon Ding */ 2910344e932aSDamon Ding writel(0x1, sharp_reg_base); 2911344e932aSDamon Ding } 2912344e932aSDamon Ding 2913c54cc5d2SAlgea Cao static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state) 2914c54cc5d2SAlgea Cao { 2915c54cc5d2SAlgea Cao struct crtc_state *cstate = &state->crtc_state; 2916c54cc5d2SAlgea Cao const struct vop2_data *vop2_data = vop2->data; 2917c54cc5d2SAlgea Cao const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id]; 2918c54cc5d2SAlgea Cao struct resource acm_regs; 2919c54cc5d2SAlgea Cao u32 *acm_reg_base; 2920c54cc5d2SAlgea Cao u32 vp_offset = (cstate->crtc_id * 0x100); 2921c54cc5d2SAlgea Cao int ret; 2922c54cc5d2SAlgea Cao 2923c54cc5d2SAlgea Cao if (!(vp_data->feature & VOP_FEATURE_POST_ACM)) 2924c54cc5d2SAlgea Cao return; 2925c54cc5d2SAlgea Cao 2926c54cc5d2SAlgea Cao ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs); 2927c54cc5d2SAlgea Cao if (ret) { 2928c54cc5d2SAlgea Cao printf("failed to get acm regs\n"); 2929c54cc5d2SAlgea Cao return; 2930c54cc5d2SAlgea Cao } 2931c54cc5d2SAlgea Cao acm_reg_base = (u32 *)acm_regs.start; 2932c54cc5d2SAlgea Cao 2933c54cc5d2SAlgea Cao /* 2934c54cc5d2SAlgea Cao * Black screen is displayed when acm bypass switched 2935c54cc5d2SAlgea Cao * between enable and disable. Therefore, disable acm 2936c54cc5d2SAlgea Cao * bypass by default after system boot. 2937c54cc5d2SAlgea Cao */ 2938c54cc5d2SAlgea Cao vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2939c54cc5d2SAlgea Cao POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 2940c54cc5d2SAlgea Cao 2941e1946cbdSAlgea Cao writel(0, acm_reg_base + 0); 2942c54cc5d2SAlgea Cao } 2943c54cc5d2SAlgea Cao 29440669ab1fSDamon Ding static int rockchip_vop2_of_get_gamma_lut(struct display_state *state, 29450669ab1fSDamon Ding struct device_node *dsp_lut_node) 29460669ab1fSDamon Ding { 29470669ab1fSDamon Ding struct crtc_state *cstate = &state->crtc_state; 29480669ab1fSDamon Ding struct resource gamma_res; 29490669ab1fSDamon Ding fdt_size_t lut_size; 29500669ab1fSDamon Ding u32 *lut_regs; 29510669ab1fSDamon Ding u32 *lut; 29520669ab1fSDamon Ding u32 r, g, b; 29530669ab1fSDamon Ding int lut_len; 29540669ab1fSDamon Ding int length; 29550669ab1fSDamon Ding int i, j; 29560669ab1fSDamon Ding int ret = 0; 29570669ab1fSDamon Ding 29580669ab1fSDamon Ding of_get_property(dsp_lut_node, "gamma-lut", &length); 29590669ab1fSDamon Ding if (!length) 29600669ab1fSDamon Ding return -EINVAL; 29610669ab1fSDamon Ding 29620669ab1fSDamon Ding ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 29630669ab1fSDamon Ding if (ret) 29640669ab1fSDamon Ding printf("failed to get gamma lut res\n"); 29650669ab1fSDamon Ding lut_regs = (u32 *)gamma_res.start; 29660669ab1fSDamon Ding lut_size = gamma_res.end - gamma_res.start + 1; 29670669ab1fSDamon Ding if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 29680669ab1fSDamon Ding printf("failed to get gamma lut register\n"); 29690669ab1fSDamon Ding return -EINVAL; 29700669ab1fSDamon Ding } 29710669ab1fSDamon Ding lut_len = lut_size / 4; 29720669ab1fSDamon Ding 29730669ab1fSDamon Ding cstate->lut_val = (u32 *)calloc(1, lut_size); 29740669ab1fSDamon Ding if (!cstate->lut_val) 29750669ab1fSDamon Ding return -ENOMEM; 29760669ab1fSDamon Ding 29770669ab1fSDamon Ding length >>= 2; 29780669ab1fSDamon Ding if (length != lut_len) { 29790669ab1fSDamon Ding lut = (u32 *)calloc(1, lut_len); 29800669ab1fSDamon Ding if (!lut) { 29810669ab1fSDamon Ding free(cstate->lut_val); 29820669ab1fSDamon Ding return -ENOMEM; 29830669ab1fSDamon Ding } 29840669ab1fSDamon Ding 29850669ab1fSDamon Ding ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length); 29860669ab1fSDamon Ding if (ret) { 29870669ab1fSDamon Ding printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id); 29880669ab1fSDamon Ding free(cstate->lut_val); 29890669ab1fSDamon Ding free(lut); 29900669ab1fSDamon Ding return -EINVAL; 29910669ab1fSDamon Ding } 29920669ab1fSDamon Ding 29930669ab1fSDamon Ding /* 29940669ab1fSDamon Ding * In order to achieve the same gamma correction effect in different 29950669ab1fSDamon Ding * platforms, the following conversion helps to translate from 8bit 29960669ab1fSDamon Ding * gamma table with 256 parameters to 10bit gamma with 1024 parameters. 29970669ab1fSDamon Ding */ 29980669ab1fSDamon Ding for (i = 0; i < lut_len; i++) { 29990669ab1fSDamon Ding j = i * length / lut_len; 30000669ab1fSDamon Ding r = lut[j] / length / length * lut_len / length; 30010669ab1fSDamon Ding g = lut[j] / length % length * lut_len / length; 30020669ab1fSDamon Ding b = lut[j] % length * lut_len / length; 30030669ab1fSDamon Ding 30040669ab1fSDamon Ding cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b; 30050669ab1fSDamon Ding } 30060669ab1fSDamon Ding free(lut); 30070669ab1fSDamon Ding } else { 30080669ab1fSDamon Ding of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len); 30090669ab1fSDamon Ding } 30100669ab1fSDamon Ding 30110669ab1fSDamon Ding return 0; 30120669ab1fSDamon Ding } 30130669ab1fSDamon Ding 30140669ab1fSDamon Ding static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state) 30150669ab1fSDamon Ding { 30160669ab1fSDamon Ding struct crtc_state *cstate = &state->crtc_state; 30170669ab1fSDamon Ding struct device_node *dsp_lut_node; 30180669ab1fSDamon Ding int phandle; 30190669ab1fSDamon Ding int ret = 0; 30200669ab1fSDamon Ding 30210669ab1fSDamon Ding phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1); 30220669ab1fSDamon Ding if (phandle < 0) 30230669ab1fSDamon Ding return; 30240669ab1fSDamon Ding 30250669ab1fSDamon Ding dsp_lut_node = of_find_node_by_phandle(phandle); 30260669ab1fSDamon Ding if (!dsp_lut_node) 30270669ab1fSDamon Ding return; 30280669ab1fSDamon Ding 30290669ab1fSDamon Ding ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node); 30300669ab1fSDamon Ding if (ret) 30310669ab1fSDamon Ding printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id); 30320669ab1fSDamon Ding } 30330669ab1fSDamon Ding 3034d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state) 3035d0408543SAndy Yan { 30360669ab1fSDamon Ding rockchip_vop2_of_get_dsp_lut(vop2, state); 30370669ab1fSDamon Ding 30381147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state); 30396414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state); 3040344e932aSDamon Ding rockchip_vop2_sharp_init(vop2, state); 3041c54cc5d2SAlgea Cao rockchip_vop2_acm_init(vop2, state); 3042d0408543SAndy Yan 3043d0408543SAndy Yan return 0; 3044d0408543SAndy Yan } 3045d0408543SAndy Yan 3046d0408543SAndy Yan /* 3047d0408543SAndy Yan * VOP2 have multi video ports. 3048d0408543SAndy Yan * video port ------- crtc 3049d0408543SAndy Yan */ 3050d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state) 3051d0408543SAndy Yan { 3052d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3053d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data; 3054734a0ce6SDamon Ding struct regmap *map; 30550686a6a6SZhang Yubing char dclk_name[16]; 30560686a6a6SZhang Yubing int ret; 3057d0408543SAndy Yan 3058d0408543SAndy Yan if (!rockchip_vop2) { 30590d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2)); 3060d0408543SAndy Yan if (!rockchip_vop2) 3061d0408543SAndy Yan return -ENOMEM; 3062d8e7f4a5SSandy Huang memset(rockchip_vop2, 0, sizeof(struct vop2)); 3063d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 3064d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG; 3065d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD 3066d8e7f4a5SSandy Huang rockchip_vop2->regs = (void *)RK3528_VOP_BASE; 3067d8e7f4a5SSandy Huang #else 3068d8e7f4a5SSandy Huang rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 3069734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf"); 3070734a0ce6SDamon Ding rockchip_vop2->grf = regmap_get_range(map, 0); 3071d0408543SAndy Yan if (rockchip_vop2->grf <= 0) 307263cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 3073d8e7f4a5SSandy Huang #endif 3074d0408543SAndy Yan rockchip_vop2->version = vop2_data->version; 3075d0408543SAndy Yan rockchip_vop2->data = vop2_data; 3076ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) { 3077734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf"); 3078734a0ce6SDamon Ding rockchip_vop2->vop_grf = regmap_get_range(map, 0); 3079ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0) 3080a552a69cSDamon Ding printf("%s: Get syscon vop_grf failed (ret=%p)\n", 3081a552a69cSDamon Ding __func__, rockchip_vop2->vop_grf); 3082b890760eSAlgea Cao map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); 3083b890760eSAlgea Cao rockchip_vop2->vo1_grf = regmap_get_range(map, 0); 3084ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0) 3085a552a69cSDamon Ding printf("%s: Get syscon vo1_grf failed (ret=%p)\n", 3086a552a69cSDamon Ding __func__, rockchip_vop2->vo1_grf); 3087734a0ce6SDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu"); 3088734a0ce6SDamon Ding rockchip_vop2->sys_pmu = regmap_get_range(map, 0); 3089b890760eSAlgea Cao if (rockchip_vop2->sys_pmu <= 0) 3090a552a69cSDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", 3091a552a69cSDamon Ding __func__, rockchip_vop2->sys_pmu); 3092a552a69cSDamon Ding } else if (rockchip_vop2->version == VOP_VERSION_RK3576) { 3093a552a69cSDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf"); 3094a552a69cSDamon Ding rockchip_vop2->ioc_grf = regmap_get_range(map, 0); 3095a552a69cSDamon Ding if (rockchip_vop2->ioc_grf <= 0) 3096a552a69cSDamon Ding printf("%s: Get syscon ioc_grf failed (ret=%p)\n", 3097a552a69cSDamon Ding __func__, rockchip_vop2->ioc_grf); 3098a552a69cSDamon Ding map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu"); 3099a552a69cSDamon Ding rockchip_vop2->sys_pmu = regmap_get_range(map, 0); 3100a552a69cSDamon Ding if (rockchip_vop2->sys_pmu <= 0) 3101a552a69cSDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", 3102a552a69cSDamon Ding __func__, rockchip_vop2->sys_pmu); 3103ecc31b6eSAndy Yan } 3104d0408543SAndy Yan } 3105d0408543SAndy Yan 31060686a6a6SZhang Yubing snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 31070686a6a6SZhang Yubing ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst); 31080686a6a6SZhang Yubing if (ret < 0) { 31090686a6a6SZhang Yubing printf("%s: failed to get dclk reset: %d\n", __func__, ret); 31100686a6a6SZhang Yubing cstate->dclk_rst.dev = NULL; 31110686a6a6SZhang Yubing } 31120686a6a6SZhang Yubing 3113d0408543SAndy Yan cstate->private = rockchip_vop2; 311463cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 311563cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 3116d0408543SAndy Yan 311789912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state); 311889912f2dSSandy Huang 3119d0408543SAndy Yan return 0; 3120d0408543SAndy Yan } 3121d0408543SAndy Yan 3122ecc31b6eSAndy Yan /* 3123ecc31b6eSAndy Yan * calc the dclk on rk3588 3124ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4 3125ecc31b6eSAndy Yan * 3126ecc31b6eSAndy Yan */ 3127ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 3128ecc31b6eSAndy Yan { 3129ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk) 3130ecc31b6eSAndy Yan return child_clk * 4; 3131ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk) 3132ecc31b6eSAndy Yan return child_clk * 2; 3133ecc31b6eSAndy Yan else if (child_clk <= max_dclk) 3134ecc31b6eSAndy Yan return child_clk; 3135ecc31b6eSAndy Yan else 3136ecc31b6eSAndy Yan return 0; 3137ecc31b6eSAndy Yan } 3138ecc31b6eSAndy Yan 3139ecc31b6eSAndy Yan /* 3140ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588 3141ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core 3142ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core 3143ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core 3144ecc31b6eSAndy Yan */ 3145ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state, 3146ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div, 3147ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div) 3148d0408543SAndy Yan { 3149d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3150d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 3151d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3152d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 31530a1fb152SZhang Yubing unsigned long v_pixclk = mode->crtc_clock; 3154ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2; 3155ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk; 3156ecc31b6eSAndy Yan unsigned long dclk_out_rate; 3157ecc31b6eSAndy Yan u64 if_dclk_rate; 3158ecc31b6eSAndy Yan u64 if_pixclk_rate; 3159ecc31b6eSAndy Yan int output_type = conn_state->type; 3160ecc31b6eSAndy Yan int output_mode = conn_state->output_mode; 3161ecc31b6eSAndy Yan int K = 1; 3162ecc31b6eSAndy Yan 31630a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE && 31640a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 31650a1fb152SZhang Yubing printf("Dual channel and YUV420 can't work together\n"); 31660a1fb152SZhang Yubing return -EINVAL; 31670a1fb152SZhang Yubing } 31680a1fb152SZhang Yubing 31690a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 31700a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) 31710a1fb152SZhang Yubing K = 2; 31720a1fb152SZhang Yubing 3173ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 3174ecc31b6eSAndy Yan /* 3175ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 3176ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 3177ecc31b6eSAndy Yan */ 31780a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 31790a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 3180b890760eSAlgea Cao dclk_rate = dclk_rate >> 1; 3181ecc31b6eSAndy Yan K = 2; 3182b890760eSAlgea Cao } 318312ee5af0SDamon Ding if (cstate->dsc_enable) { 318412ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate << 1; 318512ee5af0SDamon Ding if_dclk_rate = cstate->dsc_cds_clk_rate; 3186ecc31b6eSAndy Yan } else { 3187ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K; 3188ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K; 3189ecc31b6eSAndy Yan } 3190ecc31b6eSAndy Yan 3191631ee99aSZhang Yubing if (v_pixclk > VOP2_MAX_DCLK_RATE) 31924b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_core_rate, 31934b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 3194631ee99aSZhang Yubing 3195ecc31b6eSAndy Yan if (!dclk_rate) { 3196ecc31b6eSAndy Yan printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 31974b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate); 3198ecc31b6eSAndy Yan return -EINVAL; 3199ecc31b6eSAndy Yan } 3200ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 3201ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate; 3202b890760eSAlgea Cao *dclk_core_div = dclk_rate / dclk_core_rate; 3203b890760eSAlgea Cao printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n", 3204b890760eSAlgea Cao dclk_rate, *if_pixclk_div, *if_dclk_div); 3205ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 3206ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */ 3207ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K; 3208ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K; 3209ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K; 3210ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3211ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 3212ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div; 3213ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 3214ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2; 32150a1fb152SZhang Yubing dclk_out_rate = dclk_out_rate / K; 3216ecc31b6eSAndy Yan 32174b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 32184b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 3219ecc31b6eSAndy Yan if (!dclk_rate) { 3220ecc31b6eSAndy Yan printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 32214b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate); 3222ecc31b6eSAndy Yan return -EINVAL; 3223ecc31b6eSAndy Yan } 3224ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 3225ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3226ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 3227ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3228ecc31b6eSAndy Yan K = 2; 322912ee5af0SDamon Ding if (cstate->dsc_enable) 323012ee5af0SDamon Ding /* dsc output is 96bit, dsi input is 192 bit */ 323112ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1; 3232ecc31b6eSAndy Yan else 3233ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K; 3234ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 323512ee5af0SDamon Ding dclk_out_rate = dclk_core_rate / K; 3236ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 32374b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 32384b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 32399f076eccSZhang Yubing if (!dclk_rate) { 32409f076eccSZhang Yubing printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n", 32414b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate); 32429f076eccSZhang Yubing return -EINVAL; 32439f076eccSZhang Yubing } 324412ee5af0SDamon Ding 324512ee5af0SDamon Ding if (cstate->dsc_enable) 3246d57af898SDamon Ding dclk_rate /= cstate->dsc_slice_num; 324712ee5af0SDamon Ding 3248ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 3249ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3250ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 325112ee5af0SDamon Ding if (cstate->dsc_enable) 32521ace1b6dSDamon Ding *if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate; 3253ecc31b6eSAndy Yan 3254ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 3255ecc31b6eSAndy Yan dclk_rate = v_pixclk; 3256ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 3257ecc31b6eSAndy Yan } 3258ecc31b6eSAndy Yan 3259ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div); 3260ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div); 3261ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div); 3262ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div); 3263ecc31b6eSAndy Yan 3264ecc31b6eSAndy Yan return dclk_rate; 3265ecc31b6eSAndy Yan } 3266ecc31b6eSAndy Yan 326712ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state) 3268ecc31b6eSAndy Yan { 326912ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 3270ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 327112ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 32721ace1b6dSDamon Ding u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */ 3273ecc31b6eSAndy Yan u8 k = 1; 3274ecc31b6eSAndy Yan 3275ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3276ecc31b6eSAndy Yan k = 2; 3277ecc31b6eSAndy Yan 327812ee5af0SDamon Ding cstate->dsc_txp_clk_rate = v_pixclk; 327912ee5af0SDamon Ding do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k)); 3280ecc31b6eSAndy Yan 328112ee5af0SDamon Ding cstate->dsc_pxl_clk_rate = v_pixclk; 328212ee5af0SDamon Ding do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k)); 3283ecc31b6eSAndy Yan 3284ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 3285ecc31b6eSAndy Yan * cds_dat_width = 96; 3286ecc31b6eSAndy Yan * bits_per_pixel = [8-12]; 3287b61227a3SDamon Ding * As cds clk is div from txp clk and only support 1/2/4 div, 3288b61227a3SDamon Ding * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4, 3289b61227a3SDamon Ding * otherwise dsc_cds = crtc_clock / 8; 3290ecc31b6eSAndy Yan */ 3291b61227a3SDamon Ding cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8); 3292ecc31b6eSAndy Yan 3293ecc31b6eSAndy Yan return 0; 3294ecc31b6eSAndy Yan } 3295ecc31b6eSAndy Yan 3296ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 3297ecc31b6eSAndy Yan { 3298ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3299ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3300ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 330112ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 3302ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 330352ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 3304ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 3305ecc31b6eSAndy Yan int output_if = conn_state->output_if; 3306ecc31b6eSAndy Yan int if_pixclk_div = 0; 3307ecc31b6eSAndy Yan int if_dclk_div = 0; 3308ecc31b6eSAndy Yan unsigned long dclk_rate; 33095d2768f7SDamon Ding bool dclk_inv, yc_swap = false; 3310d0408543SAndy Yan u32 val; 3311ecc31b6eSAndy Yan 33125d2768f7SDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3313b890760eSAlgea Cao if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 3314b890760eSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 3315b890760eSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 3316b890760eSAlgea Cao } else { 3317ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3318ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3319b890760eSAlgea Cao } 3320ecc31b6eSAndy Yan 332112ee5af0SDamon Ding if (cstate->dsc_enable) { 332212ee5af0SDamon Ding int k = 1; 332312ee5af0SDamon Ding 3324ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) { 332512ee5af0SDamon Ding printf("Unsupported DSC\n"); 3326ecc31b6eSAndy Yan return 0; 3327ecc31b6eSAndy Yan } 332812ee5af0SDamon Ding 332912ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 333012ee5af0SDamon Ding k = 2; 333112ee5af0SDamon Ding 333212ee5af0SDamon Ding cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 333312ee5af0SDamon Ding cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k; 333412ee5af0SDamon Ding cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num; 333512ee5af0SDamon Ding 333612ee5af0SDamon Ding vop2_calc_dsc_clk(state); 333712ee5af0SDamon Ding printf("Enable DSC%d slice:%dx%d, slice num:%d\n", 333812ee5af0SDamon Ding cstate->dsc_id, dsc_sink_cap->slice_width, 333912ee5af0SDamon Ding dsc_sink_cap->slice_height, cstate->dsc_slice_num); 3340ecc31b6eSAndy Yan } 3341ecc31b6eSAndy Yan 3342b61227a3SDamon Ding dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div); 3343ecc31b6eSAndy Yan 3344ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) { 3345ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3346ecc31b6eSAndy Yan 4, false); 33475d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 33485d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3349ecc31b6eSAndy Yan } 3350ecc31b6eSAndy Yan 3351ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) { 3352ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3353ecc31b6eSAndy Yan 3, false); 33545d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 33555d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 33565d2768f7SDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 33575d2768f7SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT, 33585d2768f7SDamon Ding yc_swap, false); 3359ecc31b6eSAndy Yan } 3360ecc31b6eSAndy Yan 3361ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) { 3362ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3363ecc31b6eSAndy Yan 2, false); 33645d2768f7SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 33655d2768f7SDamon Ding RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 33665d2768f7SDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 33675d2768f7SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT, 33685d2768f7SDamon Ding yc_swap, false); 3369ecc31b6eSAndy Yan } 3370ecc31b6eSAndy Yan 3371ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) { 3372ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 3373ecc31b6eSAndy Yan val = 0; 3374ecc31b6eSAndy Yan else 3375ecc31b6eSAndy Yan val = 1; 337641874944SGuochun Huang 33773df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 337841874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 337941874944SGuochun Huang RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 338041874944SGuochun Huang 3381ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 3382ecc31b6eSAndy Yan 1, false); 3383ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 3384ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 3385ecc31b6eSAndy Yan if_pixclk_div, false); 338641874944SGuochun Huang 338741874944SGuochun Huang if (conn_state->hold_mode) { 338841874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 33898e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 339041874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 339141874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 339241874944SGuochun Huang } 3393ecc31b6eSAndy Yan } 3394ecc31b6eSAndy Yan 3395ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) { 3396ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 3397ecc31b6eSAndy Yan val = 0; 3398ecc31b6eSAndy Yan else if (cstate->crtc_id == 3) 3399ecc31b6eSAndy Yan val = 1; 3400ecc31b6eSAndy Yan else 3401ecc31b6eSAndy Yan val = 3; /*VP1*/ 34023df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 340341874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 340441874944SGuochun Huang RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 340541874944SGuochun Huang 3406ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 3407ecc31b6eSAndy Yan 1, false); 3408ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 3409ecc31b6eSAndy Yan val, false); 3410ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 3411ecc31b6eSAndy Yan if_pixclk_div, false); 341241874944SGuochun Huang 341341874944SGuochun Huang if (conn_state->hold_mode) { 341441874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 34158e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 341641874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 341741874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 341841874944SGuochun Huang } 3419ecc31b6eSAndy Yan } 3420ecc31b6eSAndy Yan 3421ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 34223df6e59eSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 34233df6e59eSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 3424ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3425ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3426ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 3427ecc31b6eSAndy Yan false); 34280a1fb152SZhang Yubing switch (conn_state->type) { 34290a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DisplayPort: 34300a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 34310a1fb152SZhang Yubing RK3588_DP_DUAL_EN_SHIFT, 1, false); 34320a1fb152SZhang Yubing break; 34330a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_eDP: 34340a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 34350a1fb152SZhang Yubing RK3588_EDP_DUAL_EN_SHIFT, 1, false); 34360a1fb152SZhang Yubing break; 34370a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_HDMIA: 34380a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 34390a1fb152SZhang Yubing RK3588_HDMI_DUAL_EN_SHIFT, 1, false); 34400a1fb152SZhang Yubing break; 34410a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DSI: 34420a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 34430a1fb152SZhang Yubing RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 34440a1fb152SZhang Yubing break; 34450a1fb152SZhang Yubing default: 34460a1fb152SZhang Yubing break; 34470a1fb152SZhang Yubing } 3448ecc31b6eSAndy Yan } 3449ecc31b6eSAndy Yan 3450ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) { 3451ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 3452ecc31b6eSAndy Yan 1, false); 3453ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 3454ecc31b6eSAndy Yan cstate->crtc_id, false); 3455ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 3456ecc31b6eSAndy Yan if_dclk_div, false); 3457ecc31b6eSAndy Yan 3458ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 3459ecc31b6eSAndy Yan if_pixclk_div, false); 3460ecc31b6eSAndy Yan 3461ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3462ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 3463ecc31b6eSAndy Yan } 3464ecc31b6eSAndy Yan 3465ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) { 3466ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 3467ecc31b6eSAndy Yan 1, false); 3468ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 3469ecc31b6eSAndy Yan cstate->crtc_id, false); 3470ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 3471ecc31b6eSAndy Yan if_dclk_div, false); 3472ecc31b6eSAndy Yan 3473ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 3474ecc31b6eSAndy Yan if_pixclk_div, false); 34751848455fSDamon Ding 34761848455fSDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 34771848455fSDamon Ding RK3588_GRF_EDP1_ENABLE_SHIFT, 1); 3478ecc31b6eSAndy Yan } 3479ecc31b6eSAndy Yan 3480ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) { 3481ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 3482ecc31b6eSAndy Yan 1, false); 3483ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 3484ecc31b6eSAndy Yan cstate->crtc_id, false); 3485ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 3486ecc31b6eSAndy Yan if_dclk_div, false); 3487ecc31b6eSAndy Yan 3488ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 3489ecc31b6eSAndy Yan if_pixclk_div, false); 3490b890760eSAlgea Cao 3491b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3492b890760eSAlgea Cao RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1); 3493b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 3494b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 3495b890760eSAlgea Cao HDMI0_SYNC_POL_SHIFT, val); 3496ecc31b6eSAndy Yan } 3497ecc31b6eSAndy Yan 3498ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) { 3499ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 3500ecc31b6eSAndy Yan 1, false); 3501ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 3502ecc31b6eSAndy Yan cstate->crtc_id, false); 3503ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 3504ecc31b6eSAndy Yan if_dclk_div, false); 3505ecc31b6eSAndy Yan 3506ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 3507ecc31b6eSAndy Yan if_pixclk_div, false); 3508b890760eSAlgea Cao 3509b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3510b890760eSAlgea Cao RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1); 3511b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 3512b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 3513b890760eSAlgea Cao HDMI1_SYNC_POL_SHIFT, val); 3514ecc31b6eSAndy Yan } 3515ecc31b6eSAndy Yan 3516ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) { 3517ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 3518ecc31b6eSAndy Yan cstate->crtc_id, false); 3519ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 3520ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false); 3521ecc31b6eSAndy Yan } 3522ecc31b6eSAndy Yan 3523ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) { 3524ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 3525ecc31b6eSAndy Yan cstate->crtc_id, false); 3526ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 3527ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false); 3528ecc31b6eSAndy Yan } 3529ecc31b6eSAndy Yan 3530ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 3531b61227a3SDamon Ding DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false); 3532ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 3533b61227a3SDamon Ding DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false); 3534ecc31b6eSAndy Yan 3535ecc31b6eSAndy Yan return dclk_rate; 3536ecc31b6eSAndy Yan } 3537ecc31b6eSAndy Yan 3538a552a69cSDamon Ding static unsigned long rk3576_vop2_if_cfg(struct display_state *state) 3539a552a69cSDamon Ding { 3540a552a69cSDamon Ding struct crtc_state *cstate = &state->crtc_state; 3541a552a69cSDamon Ding struct connector_state *conn_state = &state->conn_state; 3542a552a69cSDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3543a552a69cSDamon Ding struct vop2 *vop2 = cstate->private; 3544a552a69cSDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 3545a552a69cSDamon Ding u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate; 3546a552a69cSDamon Ding int output_if = conn_state->output_if; 3547a552a69cSDamon Ding bool dclk_inv, yc_swap = false; 3548a552a69cSDamon Ding bool split_mode = !!(conn_state->output_flags & 3549a552a69cSDamon Ding ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE); 3550a552a69cSDamon Ding bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false; 3551a552a69cSDamon Ding bool interface_dclk_sel, interface_pix_clk_sel = false; 3552a552a69cSDamon Ding bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK || 3553a552a69cSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656; 3554cce1f2abSDamon Ding unsigned long dclk_in_rate, dclk_core_rate; 3555a552a69cSDamon Ding u32 val; 3556a552a69cSDamon Ding 3557a552a69cSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3558a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_MIPI0) { 3559a552a69cSDamon Ding /* 3560a552a69cSDamon Ding * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update, 3561a552a69cSDamon Ding * so set VOP hsync/vsync polarity as positive by default. 3562a552a69cSDamon Ding */ 3563a552a69cSDamon Ding val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE); 3564a552a69cSDamon Ding } else { 3565a552a69cSDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3566a552a69cSDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3567a552a69cSDamon Ding } 3568a552a69cSDamon Ding 3569cce1f2abSDamon Ding if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 || 3570cce1f2abSDamon Ding mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode)) 3571a552a69cSDamon Ding cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */ 3572a552a69cSDamon Ding else 3573cce1f2abSDamon Ding cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */ 3574cce1f2abSDamon Ding dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div; 3575cce1f2abSDamon Ding 3576cce1f2abSDamon Ding if (double_pixel) 3577cce1f2abSDamon Ding dclk_core_rate = mode->crtc_clock / 2; 3578cce1f2abSDamon Ding else 3579cce1f2abSDamon Ding dclk_core_rate = mode->crtc_clock / port_pix_rate; 3580cce1f2abSDamon Ding post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */ 3581a552a69cSDamon Ding 3582a552a69cSDamon Ding if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 3583a552a69cSDamon Ding pix_half_rate = true; 3584a552a69cSDamon Ding post_dclk_out_sel = true; 3585a552a69cSDamon Ding } 3586a552a69cSDamon Ding 3587a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_RGB) { 3588a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3589a552a69cSDamon Ding /* 3590a552a69cSDamon Ding * RGB interface_pix_clk_sel will auto config according 3591a552a69cSDamon Ding * to rgb_en/bt1120_en/bt656_en. 3592a552a69cSDamon Ding */ 3593a552a69cSDamon Ding } else if (output_if & VOP_OUTPUT_IF_eDP0) { 3594a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3595a552a69cSDamon Ding interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0; 3596a552a69cSDamon Ding } else { 3597a552a69cSDamon Ding interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3598a552a69cSDamon Ding interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0; 3599a552a69cSDamon Ding } 3600a552a69cSDamon Ding 3601a552a69cSDamon Ding /* dclk_core */ 3602a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK, 3603a552a69cSDamon Ding RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false); 3604a552a69cSDamon Ding /* dclk_out */ 3605a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK, 3606a552a69cSDamon Ding RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false); 3607a552a69cSDamon Ding 3608a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_RGB) { 3609a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */ 3610a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3611a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3612a552a69cSDamon Ding 3613a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3614a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3615a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3616a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3617a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3618a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3619a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3620a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3621a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3622a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3623a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3624a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv); 3625a552a69cSDamon Ding } 3626a552a69cSDamon Ding 3627a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_BT1120) { 3628a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */ 3629a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3630a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3631a552a69cSDamon Ding 3632a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3633a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3634a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3635a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3636a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3637a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3638a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3639a552a69cSDamon Ding RK3576_BT1120_OUT_EN_SHIFT, 1, false); 3640a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3641a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3642a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3643a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3644a552a69cSDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 3645a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3646a552a69cSDamon Ding RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false); 3647a552a69cSDamon Ding } 3648a552a69cSDamon Ding 3649a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_BT656) { 3650a552a69cSDamon Ding /* 0: dclk_core, 1: dclk_out */ 3651a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3652a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3653a552a69cSDamon Ding 3654a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3655a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3656a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3657a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3658a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3659a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3660a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3661a552a69cSDamon Ding RK3576_BT656_OUT_EN_SHIFT, 1, false); 3662a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3663a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3664a552a69cSDamon Ding vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3665a552a69cSDamon Ding RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3666a552a69cSDamon Ding yc_swap = is_yc_swap(conn_state->bus_format); 3667a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3668a552a69cSDamon Ding RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false); 3669a552a69cSDamon Ding } 3670a552a69cSDamon Ding 3671a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_MIPI0) { 3672a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3673a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3674a552a69cSDamon Ding /* 0: div2, 1: div4 */ 3675a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3676a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3677a552a69cSDamon Ding 3678a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3679a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3680a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3681a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3682a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3683a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3684a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3685a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3686a552a69cSDamon Ding /* 3687a552a69cSDamon Ding * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update, 3688a552a69cSDamon Ding * so set VOP hsync/vsync polarity as positive by default. 3689a552a69cSDamon Ding */ 3690a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 3691a552a69cSDamon Ding val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE); 3692a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3693a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3694a552a69cSDamon Ding 3695a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 3696a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3697a552a69cSDamon Ding RK3576_MIPI_CMD_MODE_SHIFT, 1, false); 3698a552a69cSDamon Ding 3699a552a69cSDamon Ding if (conn_state->hold_mode) { 3700a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3701a552a69cSDamon Ding EDPI_TE_EN, !cstate->soft_te, false); 3702a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3703a552a69cSDamon Ding EDPI_WMS_HOLD_EN, 1, false); 3704a552a69cSDamon Ding } 3705a552a69cSDamon Ding } 3706a552a69cSDamon Ding 3707a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 3708a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3709a552a69cSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 3710a552a69cSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3711a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3712a552a69cSDamon Ding MIPI_DUAL_SWAP_EN_SHIFT, 1, false); 3713a552a69cSDamon Ding switch (conn_state->type) { 3714a552a69cSDamon Ding case DRM_MODE_CONNECTOR_DisplayPort: 3715a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 3716a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3717a552a69cSDamon Ding break; 3718a552a69cSDamon Ding case DRM_MODE_CONNECTOR_eDP: 3719a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3720a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3721a552a69cSDamon Ding break; 3722a552a69cSDamon Ding case DRM_MODE_CONNECTOR_HDMIA: 3723a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3724a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3725a552a69cSDamon Ding break; 3726a552a69cSDamon Ding case DRM_MODE_CONNECTOR_DSI: 3727a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3728a552a69cSDamon Ding RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3729a552a69cSDamon Ding break; 3730a552a69cSDamon Ding default: 3731a552a69cSDamon Ding break; 3732a552a69cSDamon Ding } 3733a552a69cSDamon Ding } 3734a552a69cSDamon Ding 3735a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_eDP0) { 3736a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3737a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3738a552a69cSDamon Ding /* 0: dclk, 1: port0_dclk */ 3739a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3740a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3741a552a69cSDamon Ding 3742a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3743a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3744a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3745a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3746a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3747a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3748a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3749a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3750a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3751a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3752a552a69cSDamon Ding } 3753a552a69cSDamon Ding 3754a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_HDMI0) { 3755a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3756a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3757a552a69cSDamon Ding /* 0: div2, 1: div4 */ 3758a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3759a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3760a552a69cSDamon Ding 3761a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3762a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3763a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3764a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3765a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3766a552a69cSDamon Ding RK3576_IF_OUT_EN_SHIFT, 1, false); 3767a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_HDMI0_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_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3770a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3771a552a69cSDamon Ding } 3772a552a69cSDamon Ding 3773a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP0) { 3774a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3775a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3776a552a69cSDamon Ding /* 0: no div, 1: div2 */ 3777a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3778a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3779a552a69cSDamon Ding 3780a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 3781a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3782a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 3783a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3784a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3785a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3786a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3787a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3788a552a69cSDamon Ding } 3789a552a69cSDamon Ding 3790a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP1) { 3791a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3792a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3793a552a69cSDamon Ding /* 0: no div, 1: div2 */ 3794a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3795a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3796a552a69cSDamon Ding 3797a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 3798a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3799a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 3800a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3801a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3802a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3803a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3804a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3805a552a69cSDamon Ding } 3806a552a69cSDamon Ding 3807a552a69cSDamon Ding if (output_if & VOP_OUTPUT_IF_DP2) { 3808a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3809a552a69cSDamon Ding RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3810a552a69cSDamon Ding /* 0: no div, 1: div2 */ 3811a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3812a552a69cSDamon Ding RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3813a552a69cSDamon Ding 3814a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 3815a552a69cSDamon Ding RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3816a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 3817a552a69cSDamon Ding RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3818a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3819a552a69cSDamon Ding RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3820a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3821a552a69cSDamon Ding RK3576_IF_PIN_POL_SHIFT, val, false); 3822a552a69cSDamon Ding } 3823a552a69cSDamon Ding 3824a552a69cSDamon Ding return mode->crtc_clock; 3825a552a69cSDamon Ding } 3826a552a69cSDamon Ding 3827a2a16809SChaoyi Chen static void rk3568_vop2_setup_dual_channel_if(struct display_state *state) 3828a2a16809SChaoyi Chen { 3829a2a16809SChaoyi Chen struct crtc_state *cstate = &state->crtc_state; 3830a2a16809SChaoyi Chen struct connector_state *conn_state = &state->conn_state; 3831a2a16809SChaoyi Chen struct vop2 *vop2 = cstate->private; 3832a2a16809SChaoyi Chen u32 vp_offset = (cstate->crtc_id * 0x100); 3833a2a16809SChaoyi Chen 3834a2a16809SChaoyi Chen if (conn_state->output_flags & 3835a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) { 3836a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3837a2a16809SChaoyi Chen LVDS_DUAL_EN_SHIFT, 1, false); 3838a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3839a2a16809SChaoyi Chen LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false); 3840a2a16809SChaoyi Chen if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3841a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3842a2a16809SChaoyi Chen LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 3843a2a16809SChaoyi Chen 3844a2a16809SChaoyi Chen return; 3845a2a16809SChaoyi Chen } 3846a2a16809SChaoyi Chen 3847a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3848a2a16809SChaoyi Chen MIPI_DUAL_EN_SHIFT, 1, false); 3849a2a16809SChaoyi Chen if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) { 3850a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3851a2a16809SChaoyi Chen MIPI_DUAL_SWAP_EN_SHIFT, 1, false); 3852a2a16809SChaoyi Chen } 3853a2a16809SChaoyi Chen 3854a2a16809SChaoyi Chen if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 3855a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3856a2a16809SChaoyi Chen LVDS_DUAL_EN_SHIFT, 1, false); 3857a2a16809SChaoyi Chen vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3858a2a16809SChaoyi Chen LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false); 3859a2a16809SChaoyi Chen } 3860a2a16809SChaoyi Chen } 3861a2a16809SChaoyi Chen 3862ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 3863ecc31b6eSAndy Yan { 3864ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3865ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3866ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3867ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 3868d0408543SAndy Yan bool dclk_inv; 3869ecc31b6eSAndy Yan u32 val; 38708895aec1SSandy Huang 387113f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 387210ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 387310ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3874d0408543SAndy Yan 3875d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3876d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3877d0408543SAndy Yan 1, false); 3878d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3879d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 388015f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 388115f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3882ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 3883c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 3884d0408543SAndy Yan } 3885d0408543SAndy Yan 3886d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 388752ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 388852ee18acSSandy Huang 1, false); 3889d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 3890d0408543SAndy Yan BT1120_EN_SHIFT, 1, false); 3891d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3892d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 3893ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 389452ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 3895d0408543SAndy Yan } 3896d0408543SAndy Yan 3897d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 3898d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 3899d0408543SAndy Yan 1, false); 3900d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3901d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 3902ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 390352ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 3904d0408543SAndy Yan } 3905d0408543SAndy Yan 3906d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3907d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3908d0408543SAndy Yan 1, false); 3909d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3910d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false); 391115f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 391215f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 391311f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 391415f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3915d0408543SAndy Yan } 3916d0408543SAndy Yan 3917d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 3918d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 3919d0408543SAndy Yan 1, false); 3920d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3921d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false); 392215f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 392315f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 392411f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 392515f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3926d0408543SAndy Yan } 3927d0408543SAndy Yan 3928d0408543SAndy Yan 3929d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3930d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3931d0408543SAndy Yan 1, false); 3932d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3933d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3934d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3935c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3936de022775SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK, 3937de022775SGuochun Huang IF_CTRL_MIPI_PIN_POL_SHIFT, val, false); 3938d0408543SAndy Yan } 3939d0408543SAndy Yan 3940d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 3941d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 3942d0408543SAndy Yan 1, false); 3943d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3944d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false); 3945d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3946c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3947de022775SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK, 3948de022775SGuochun Huang IF_CTRL_MIPI_PIN_POL_SHIFT, val, false); 3949d0408543SAndy Yan } 3950d0408543SAndy Yan 3951d0408543SAndy Yan if (conn_state->output_flags & 3952a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 3953a2a16809SChaoyi Chen conn_state->output_flags & 3954a2a16809SChaoyi Chen ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) 3955a2a16809SChaoyi Chen rk3568_vop2_setup_dual_channel_if(state); 3956d0408543SAndy Yan 3957d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 3958d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 3959d0408543SAndy Yan 1, false); 3960d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3961d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false); 3962c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3963c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 39647bcdc6eeSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK, 39657bcdc6eeSDamon Ding IF_CTRL_EDP_PIN_POL_SHIFT, val, false); 3966d0408543SAndy Yan } 3967d0408543SAndy Yan 3968d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 3969d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 3970d0408543SAndy Yan 1, false); 3971d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3972d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false); 397310ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 397410ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 397510ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, 397610ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK, 397710ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 3978d0408543SAndy Yan } 397910ee9f5bSAlgea Cao 3980823146b6SDamon Ding return mode->crtc_clock; 3981ecc31b6eSAndy Yan } 3982ecc31b6eSAndy Yan 3983452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state) 3984452afb13SDamon Ding { 3985452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 3986452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 3987452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3988452afb13SDamon Ding struct vop2 *vop2 = cstate->private; 3989452afb13SDamon Ding bool dclk_inv; 3990606f72bdSDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 3991452afb13SDamon Ding u32 val; 3992452afb13SDamon Ding 399313f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3994452afb13SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3995452afb13SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3996452afb13SDamon Ding 3997452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3998452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3999452afb13SDamon Ding 1, false); 4000452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4001452afb13SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 4002452afb13SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK, 4003452afb13SDamon Ding GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 4004452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 400515f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 4006452afb13SDamon Ding } 4007452afb13SDamon Ding 4008452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 4009452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 4010452afb13SDamon Ding 1, false); 4011452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4012452afb13SDamon Ding LVDS0_MUX_SHIFT, cstate->crtc_id, false); 4013452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 401415f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 4015452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 401615f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 4017452afb13SDamon Ding } 4018452afb13SDamon Ding 4019452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 4020452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 4021452afb13SDamon Ding 1, false); 4022452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4023452afb13SDamon Ding MIPI0_MUX_SHIFT, cstate->crtc_id, false); 4024452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4025452afb13SDamon Ding RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false); 4026452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 4027452afb13SDamon Ding RK3562_MIPI_PIN_POL_SHIFT, val, false); 4028606f72bdSDamon Ding 4029606f72bdSDamon Ding if (conn_state->hold_mode) { 4030606f72bdSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 4031606f72bdSDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 4032606f72bdSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 4033606f72bdSDamon Ding EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 4034606f72bdSDamon Ding } 4035452afb13SDamon Ding } 4036452afb13SDamon Ding 4037452afb13SDamon Ding return mode->crtc_clock; 4038452afb13SDamon Ding } 4039452afb13SDamon Ding 4040a552a69cSDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state) 4041a552a69cSDamon Ding { 4042a552a69cSDamon Ding struct crtc_state *cstate = &state->crtc_state; 4043a552a69cSDamon Ding struct connector_state *conn_state = &state->conn_state; 4044a552a69cSDamon Ding struct drm_display_mode *mode = &conn_state->mode; 4045a552a69cSDamon Ding struct vop2 *vop2 = cstate->private; 4046a552a69cSDamon Ding u32 val; 4047a552a69cSDamon Ding 4048a552a69cSDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 4049a552a69cSDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 4050a552a69cSDamon Ding 4051a552a69cSDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 4052a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 4053a552a69cSDamon Ding 1, false); 4054a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4055a552a69cSDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 4056a552a69cSDamon Ding } 4057a552a69cSDamon Ding 4058a552a69cSDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 4059a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 4060a552a69cSDamon Ding 1, false); 4061a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4062a552a69cSDamon Ding HDMI0_MUX_SHIFT, cstate->crtc_id, false); 4063a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4064a552a69cSDamon Ding IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 4065a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, 4066a552a69cSDamon Ding IF_CRTL_HDMI_PIN_POL_MASK, 4067a552a69cSDamon Ding IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 4068a552a69cSDamon Ding } 4069a552a69cSDamon Ding 4070a552a69cSDamon Ding return mode->crtc_clock; 4071a552a69cSDamon Ding } 4072a552a69cSDamon Ding 407365747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state) 407465747de7SDamon Ding { 407565747de7SDamon Ding struct crtc_state *cstate = &state->crtc_state; 407665747de7SDamon Ding struct connector_state *conn_state = &state->conn_state; 407765747de7SDamon Ding struct vop2 *vop2 = cstate->private; 407865747de7SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 407965747de7SDamon Ding u32 output_type = conn_state->type; 408065747de7SDamon Ding u32 data_swap = 0; 408165747de7SDamon Ding 4082c8820b76SDamon Ding if (is_uv_swap(state) || is_rb_swap(state)) 408365747de7SDamon Ding data_swap = DSP_RB_SWAP; 408465747de7SDamon Ding 4085a552a69cSDamon Ding if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) { 4086a552a69cSDamon Ding if ((output_type == DRM_MODE_CONNECTOR_HDMIA || 4087e6e4c154SDamon Ding output_type == DRM_MODE_CONNECTOR_DisplayPort) && 408865747de7SDamon Ding (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 408965747de7SDamon Ding conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 409065747de7SDamon Ding data_swap |= DSP_RG_SWAP; 4091a552a69cSDamon Ding } 409265747de7SDamon Ding 409365747de7SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 409465747de7SDamon Ding DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 409565747de7SDamon Ding } 409665747de7SDamon Ding 4097b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent) 4098b890760eSAlgea Cao { 4099b890760eSAlgea Cao int ret = 0; 4100b890760eSAlgea Cao 4101b890760eSAlgea Cao if (parent->dev) 4102b890760eSAlgea Cao ret = clk_set_parent(clk, parent); 4103b890760eSAlgea Cao if (ret < 0) 4104b890760eSAlgea Cao debug("failed to set %s as parent for %s\n", 4105b890760eSAlgea Cao parent->dev->name, clk->dev->name); 4106b890760eSAlgea Cao } 4107b890760eSAlgea Cao 4108b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate) 4109b890760eSAlgea Cao { 4110b890760eSAlgea Cao int ret = 0; 4111b890760eSAlgea Cao 4112b890760eSAlgea Cao if (clk->dev) 4113b890760eSAlgea Cao ret = clk_set_rate(clk, rate); 4114b890760eSAlgea Cao if (ret < 0) 4115b890760eSAlgea Cao debug("failed to set %s rate %lu \n", clk->dev->name, rate); 4116b890760eSAlgea Cao 4117b890760eSAlgea Cao return ret; 4118b890760eSAlgea Cao } 4119b890760eSAlgea Cao 412012ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state, 412112ee5af0SDamon Ding int *dsc_txp_clk_div, int *dsc_pxl_clk_div, 412212ee5af0SDamon Ding int *dsc_cds_clk_div, u64 dclk_rate) 412312ee5af0SDamon Ding { 412412ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 412512ee5af0SDamon Ding 412612ee5af0SDamon Ding *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate; 412712ee5af0SDamon Ding *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate; 412812ee5af0SDamon Ding *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate; 412912ee5af0SDamon Ding 413012ee5af0SDamon Ding *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div); 413112ee5af0SDamon Ding *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div); 413212ee5af0SDamon Ding *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div); 413312ee5af0SDamon Ding } 413412ee5af0SDamon Ding 413512ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id) 413612ee5af0SDamon Ding { 413712ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 413812ee5af0SDamon Ding struct drm_dsc_picture_parameter_set *pps = &cstate->pps; 413912ee5af0SDamon Ding struct drm_dsc_picture_parameter_set config_pps; 414012ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 414112ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 414212ee5af0SDamon Ding u32 *pps_val = (u32 *)&config_pps; 414312ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 414412ee5af0SDamon Ding int i = 0; 414512ee5af0SDamon Ding 414612ee5af0SDamon Ding memcpy(&config_pps, pps, sizeof(config_pps)); 414712ee5af0SDamon Ding 414812ee5af0SDamon Ding if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) { 414912ee5af0SDamon Ding config_pps.pps_3 &= 0xf0; 415012ee5af0SDamon Ding config_pps.pps_3 |= dsc_data->max_linebuf_depth; 415112ee5af0SDamon Ding printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n", 415212ee5af0SDamon Ding dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf); 415312ee5af0SDamon Ding } 415412ee5af0SDamon Ding 415512ee5af0SDamon Ding for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 415612ee5af0SDamon Ding config_pps.rc_range_parameters[i] = 415712ee5af0SDamon Ding (pps->rc_range_parameters[i] >> 3 & 0x1f) | 415812ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) | 415912ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) | 416012ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10); 416112ee5af0SDamon Ding } 416212ee5af0SDamon Ding 416312ee5af0SDamon Ding for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++) 416412ee5af0SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++); 416512ee5af0SDamon Ding } 416612ee5af0SDamon Ding 416712ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate) 416812ee5af0SDamon Ding { 416912ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 417012ee5af0SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 417112ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 417212ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 417312ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 417412ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 417512ee5af0SDamon Ding bool mipi_ds_mode = false; 417612ee5af0SDamon Ding u8 dsc_interface_mode = 0; 417712ee5af0SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 417812ee5af0SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 417912ee5af0SDamon Ding u16 htotal = mode->crtc_htotal; 418012ee5af0SDamon Ding u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 418112ee5af0SDamon Ding u16 vdisplay = mode->crtc_vdisplay; 418212ee5af0SDamon Ding u16 vtotal = mode->crtc_vtotal; 418312ee5af0SDamon Ding u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 418412ee5af0SDamon Ding u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 418512ee5af0SDamon Ding u16 vact_end = vact_st + vdisplay; 418612ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 418712ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 418812ee5af0SDamon Ding int dsc_txp_clk_div = 0; 418912ee5af0SDamon Ding int dsc_pxl_clk_div = 0; 419012ee5af0SDamon Ding int dsc_cds_clk_div = 0; 4191baf2c414SDamon Ding int val = 0; 419212ee5af0SDamon Ding 419312ee5af0SDamon Ding if (!vop2->data->nr_dscs) { 419412ee5af0SDamon Ding printf("Unsupported DSC\n"); 419512ee5af0SDamon Ding return; 419612ee5af0SDamon Ding } 419712ee5af0SDamon Ding 419812ee5af0SDamon Ding if (cstate->dsc_slice_num > dsc_data->max_slice_num) 419912ee5af0SDamon Ding printf("DSC%d supported max slice is: %d, current is: %d\n", 420012ee5af0SDamon Ding dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num); 420112ee5af0SDamon Ding 420212ee5af0SDamon Ding if (dsc_data->pd_id) { 420312ee5af0SDamon Ding if (vop2_power_domain_on(vop2, dsc_data->pd_id)) 420412ee5af0SDamon Ding printf("open dsc%d pd fail\n", dsc_id); 420512ee5af0SDamon Ding } 420612ee5af0SDamon Ding 420712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK, 420812ee5af0SDamon Ding SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false); 420912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK, 421012ee5af0SDamon Ding DSC_PORT_SEL_SHIFT, cstate->crtc_id, false); 421112ee5af0SDamon Ding if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 421212ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_HDMI; 421312ee5af0SDamon Ding } else { 421412ee5af0SDamon Ding mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE); 421512ee5af0SDamon Ding if (mipi_ds_mode) 421612ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE; 421712ee5af0SDamon Ding else 421812ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE; 421912ee5af0SDamon Ding } 422012ee5af0SDamon Ding 422112ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 422212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 422312ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 0, false); 422412ee5af0SDamon Ding else 422512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 422612ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 1, false); 422712ee5af0SDamon Ding 422812ee5af0SDamon Ding vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate); 422912ee5af0SDamon Ding 423012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK, 423112ee5af0SDamon Ding DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false); 423212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK, 423312ee5af0SDamon Ding DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false); 423412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK, 423512ee5af0SDamon Ding DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false); 423612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK, 423712ee5af0SDamon Ding DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false); 423812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 423912ee5af0SDamon Ding DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false); 424012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK, 424112ee5af0SDamon Ding DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false); 424212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 424312ee5af0SDamon Ding DSC_HALT_EN_SHIFT, mipi_ds_mode, false); 424412ee5af0SDamon Ding 424512ee5af0SDamon Ding if (!mipi_ds_mode) { 424612ee5af0SDamon Ding u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end; 424712ee5af0SDamon Ding u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16; 424812ee5af0SDamon Ding u64 dsc_cds_rate = cstate->dsc_cds_clk_rate; 424912ee5af0SDamon Ding u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */ 425012ee5af0SDamon Ding u32 dly_num, dsc_cds_rate_mhz, val = 0; 4251b61227a3SDamon Ding int k = 1; 4252b61227a3SDamon Ding 4253b61227a3SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 4254b61227a3SDamon Ding k = 2; 425512ee5af0SDamon Ding 425612ee5af0SDamon Ding if (target_bpp >> 4 < dsc_data->min_bits_per_pixel) 425712ee5af0SDamon Ding printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel); 425812ee5af0SDamon Ding 425912ee5af0SDamon Ding /* 426012ee5af0SDamon Ding * dly_num = delay_line_num * T(one-line) / T (dsc_cds) 426112ee5af0SDamon Ding * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz 426212ee5af0SDamon Ding * T (dsc_cds) = 1 / dsc_cds_rate_mhz 42631ace1b6dSDamon Ding * 42641ace1b6dSDamon Ding * HDMI: 426512ee5af0SDamon Ding * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay 426612ee5af0SDamon Ding * delay_line_num = 4 - BPP / 8 426712ee5af0SDamon Ding * = (64 - target_bpp / 8) / 16 426812ee5af0SDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 42691ace1b6dSDamon Ding * 42701ace1b6dSDamon Ding * MIPI DSI[4320 and 9216 is buffer size for DSC]: 42711ace1b6dSDamon Ding * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size; 42721ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 42731ace1b6dSDamon Ding * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size; 42741ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 42751ace1b6dSDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num 427612ee5af0SDamon Ding */ 427712ee5af0SDamon Ding do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ 427812ee5af0SDamon Ding dsc_cds_rate_mhz = dsc_cds_rate; 42791ace1b6dSDamon Ding dsc_hsync = hsync_len / 2; 42801ace1b6dSDamon Ding if (dsc_interface_mode == VOP_DSC_IF_HDMI) { 428112ee5af0SDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 42821ace1b6dSDamon Ding } else { 42831ace1b6dSDamon Ding int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2; 42841ace1b6dSDamon Ding int delay_line_num = dsc_buf_size / cstate->dsc_slice_num / 42851ace1b6dSDamon Ding be16_to_cpu(cstate->pps.chunk_size); 42861ace1b6dSDamon Ding 42871ace1b6dSDamon Ding delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 42881ace1b6dSDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num; 42891ace1b6dSDamon Ding 42901ace1b6dSDamon Ding /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */ 42911ace1b6dSDamon Ding if (dsc_hsync < 8) 42921ace1b6dSDamon Ding dsc_hsync = 8; 42931ace1b6dSDamon Ding } 429412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK, 429512ee5af0SDamon Ding DSC_INIT_DLY_MODE_SHIFT, 0, false); 429612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK, 429712ee5af0SDamon Ding DSC_INIT_DLY_NUM_SHIFT, dly_num, false); 429812ee5af0SDamon Ding 4299b61227a3SDamon Ding /* 4300b61227a3SDamon Ding * htotal / dclk_core = dsc_htotal /cds_clk 4301b61227a3SDamon Ding * 4302b61227a3SDamon Ding * dclk_core = DCLK / (1 << dclk_core->div_val) 4303b61227a3SDamon Ding * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val) 4304b61227a3SDamon Ding * txp_clk = DCLK / (1 << dsc_txp_clk->div_val) 4305b61227a3SDamon Ding * 4306b61227a3SDamon Ding * dsc_htotal = htotal * (1 << dclk_core->div_val) / 4307b61227a3SDamon Ding * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val)) 4308b61227a3SDamon Ding */ 4309b61227a3SDamon Ding dsc_htotal = htotal * (1 << cstate->dclk_core_div) / 4310b61227a3SDamon Ding ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div)); 431112ee5af0SDamon Ding val = dsc_htotal << 16 | dsc_hsync; 431212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK, 431312ee5af0SDamon Ding DSC_HTOTAL_PW_SHIFT, val, false); 431412ee5af0SDamon Ding 431512ee5af0SDamon Ding dsc_hact_st = hact_st / 2; 4316b61227a3SDamon Ding dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st; 431712ee5af0SDamon Ding val = dsc_hact_end << 16 | dsc_hact_st; 431812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK, 431912ee5af0SDamon Ding DSC_HACT_ST_END_SHIFT, val, false); 432012ee5af0SDamon Ding 432112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK, 432212ee5af0SDamon Ding DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false); 432312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK, 432412ee5af0SDamon Ding DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false); 432512ee5af0SDamon Ding } 432612ee5af0SDamon Ding 432712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK, 432812ee5af0SDamon Ding RST_DEASSERT_SHIFT, 1, false); 432912ee5af0SDamon Ding udelay(10); 433012ee5af0SDamon Ding 4331baf2c414SDamon Ding val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) | 4332baf2c414SDamon Ding ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT); 4333baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 4334baf2c414SDamon Ding 433512ee5af0SDamon Ding vop2_load_pps(state, vop2, dsc_id); 433612ee5af0SDamon Ding 4337baf2c414SDamon Ding val |= (1 << DSC_PPS_UPD_SHIFT); 4338baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 433912ee5af0SDamon Ding 434012ee5af0SDamon Ding printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n", 434112ee5af0SDamon Ding dsc_id, 434212ee5af0SDamon Ding cstate->dsc_txp_clk_rate, dsc_txp_clk_div, 434312ee5af0SDamon Ding cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div, 434412ee5af0SDamon Ding cstate->dsc_cds_clk_rate, dsc_cds_clk_div); 434512ee5af0SDamon Ding } 434612ee5af0SDamon Ding 43475f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev) 43485f1357a2SZhang Yubing { 43495f1357a2SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 43505f1357a2SZhang Yubing struct vop2 *vop2 = cstate->private; 43515f1357a2SZhang Yubing struct udevice *vp_dev, *dev; 43525f1357a2SZhang Yubing struct ofnode_phandle_args args; 43535f1357a2SZhang Yubing char vp_name[10]; 43545f1357a2SZhang Yubing int ret; 43555f1357a2SZhang Yubing 4356a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576) 43575f1357a2SZhang Yubing return false; 43585f1357a2SZhang Yubing 43595f1357a2SZhang Yubing sprintf(vp_name, "port@%d", cstate->crtc_id); 43605f1357a2SZhang Yubing if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) { 43615e85f4a7SZhang Yubing debug("warn: can't get vp device\n"); 43625f1357a2SZhang Yubing return false; 43635f1357a2SZhang Yubing } 43645f1357a2SZhang Yubing 43655f1357a2SZhang Yubing ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0, 43665f1357a2SZhang Yubing 0, &args); 43675f1357a2SZhang Yubing if (ret) { 43685e85f4a7SZhang Yubing debug("assigned-clock-parents's node not define\n"); 43695f1357a2SZhang Yubing return false; 43705f1357a2SZhang Yubing } 43715f1357a2SZhang Yubing 43725f1357a2SZhang Yubing if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) { 43735e85f4a7SZhang Yubing debug("warn: can't get clk device\n"); 43745f1357a2SZhang Yubing return false; 43755f1357a2SZhang Yubing } 43765f1357a2SZhang Yubing 43775f1357a2SZhang Yubing if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) { 43785f1357a2SZhang Yubing printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name); 43795f1357a2SZhang Yubing if (clk_dev) 43805f1357a2SZhang Yubing *clk_dev = dev; 43815f1357a2SZhang Yubing return true; 43825f1357a2SZhang Yubing } 43835f1357a2SZhang Yubing 43845f1357a2SZhang Yubing return false; 43855f1357a2SZhang Yubing } 43865f1357a2SZhang Yubing 43870675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state) 43880675a2a4SDamon Ding { 43890675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 43900675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 43910675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 43920675a2a4SDamon Ding 43930675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 43940675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false); 43950675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 43960675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false); 43970675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 43980675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false); 43990675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 44000675a2a4SDamon Ding MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false); 44010675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 44020675a2a4SDamon Ding MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false); 44030675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 44040675a2a4SDamon Ding MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false); 44050675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 44060675a2a4SDamon Ding MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false); 44070675a2a4SDamon Ding } 44080675a2a4SDamon Ding 44090675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state) 44100675a2a4SDamon Ding { 44110675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 44120675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 44130675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 44140675a2a4SDamon Ding 44150675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44160675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false); 44170675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44180675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false); 44190675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 44200675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, 53, false); 44210675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 44220675a2a4SDamon Ding MCU_CS_PST_SHIFT, 6, false); 44230675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 44240675a2a4SDamon Ding MCU_CS_PEND_SHIFT, 48, false); 44250675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 44260675a2a4SDamon Ding MCU_RW_PST_SHIFT, 12, false); 44270675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 44280675a2a4SDamon Ding MCU_RW_PEND_SHIFT, 30, false); 44290675a2a4SDamon Ding } 44300675a2a4SDamon Ding 44310675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value) 44320675a2a4SDamon Ding { 44330675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 44340675a2a4SDamon Ding struct connector_state *conn_state = &state->conn_state; 44350675a2a4SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 44360675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 44370675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 44380675a2a4SDamon Ding 44390675a2a4SDamon Ding /* 444058cf1fa3SDamon Ding * 1.set mcu bypass mode timing. 444158cf1fa3SDamon Ding * 2.set dclk rate to 150M. 44420675a2a4SDamon Ding */ 44430675a2a4SDamon Ding if (type == MCU_SETBYPASS && value) { 44440675a2a4SDamon Ding vop3_mcu_bypass_mode_setup(state); 44450675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, 150000000); 44460675a2a4SDamon Ding } 44470675a2a4SDamon Ding 44480675a2a4SDamon Ding switch (type) { 44490675a2a4SDamon Ding case MCU_WRCMD: 44500675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44510675a2a4SDamon Ding MCU_RS_SHIFT, 0, false); 44520675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 44530675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 44540675a2a4SDamon Ding value, false); 44550675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44560675a2a4SDamon Ding MCU_RS_SHIFT, 1, false); 44570675a2a4SDamon Ding break; 44580675a2a4SDamon Ding case MCU_WRDATA: 44590675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44600675a2a4SDamon Ding MCU_RS_SHIFT, 1, false); 44610675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 44620675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 44630675a2a4SDamon Ding value, false); 44640675a2a4SDamon Ding break; 44650675a2a4SDamon Ding case MCU_SETBYPASS: 44660675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 44670675a2a4SDamon Ding MCU_BYPASS_SHIFT, value ? 1 : 0, false); 44680675a2a4SDamon Ding break; 44690675a2a4SDamon Ding default: 44700675a2a4SDamon Ding break; 44710675a2a4SDamon Ding } 44720675a2a4SDamon Ding 44730675a2a4SDamon Ding /* 447458cf1fa3SDamon Ding * 1.restore mcu data mode timing. 447558cf1fa3SDamon Ding * 2.restore dclk rate to crtc_clock. 44760675a2a4SDamon Ding */ 44770675a2a4SDamon Ding if (type == MCU_SETBYPASS && !value) { 44780675a2a4SDamon Ding vop3_mcu_mode_setup(state); 44790675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000); 44800675a2a4SDamon Ding } 44810675a2a4SDamon Ding 44820675a2a4SDamon Ding return 0; 44830675a2a4SDamon Ding } 44840675a2a4SDamon Ding 448534d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id) 448634d37ef0SDamon Ding { 4487a552a69cSDamon Ding const struct vop2_data *vop2_data = vop2->data; 4488a552a69cSDamon Ding const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id]; 448934d37ef0SDamon Ding u32 vp_offset = crtc_id * 0x100; 449034d37ef0SDamon Ding bool pre_dither_down_en = false; 449134d37ef0SDamon Ding 449234d37ef0SDamon Ding switch (bus_format) { 449334d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB565_1X16: 449440608a7cSDamon Ding case MEDIA_BUS_FMT_RGB565_2X8_LE: 4495e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4496e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, true, false); 4497e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4498e2bdb3b3SDamon Ding DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false); 449934d37ef0SDamon Ding pre_dither_down_en = true; 450034d37ef0SDamon Ding break; 450134d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X18: 450234d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 450334d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 450440608a7cSDamon Ding case MEDIA_BUS_FMT_RGB666_3X6: 4505e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4506e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, true, false); 4507e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4508e2bdb3b3SDamon Ding DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false); 450934d37ef0SDamon Ding pre_dither_down_en = true; 451034d37ef0SDamon Ding break; 451134d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 451234d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV8_1X24: 451334d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 4514e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4515e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false); 451634d37ef0SDamon Ding pre_dither_down_en = true; 451734d37ef0SDamon Ding break; 451834d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV10_1X20: 451934d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV10_1X30: 452034d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 452134d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB101010_1X30: 4522e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4523e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false); 452434d37ef0SDamon Ding pre_dither_down_en = false; 452534d37ef0SDamon Ding break; 452634d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_3X8: 452734d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: 452834d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X24: 452934d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 453034d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 453134d37ef0SDamon Ding default: 4532e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4533e2bdb3b3SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, false, false); 453434d37ef0SDamon Ding pre_dither_down_en = true; 453534d37ef0SDamon Ding break; 453634d37ef0SDamon Ding } 453734d37ef0SDamon Ding 4538e2bdb3b3SDamon Ding if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0) 453934d37ef0SDamon Ding pre_dither_down_en = false; 454034d37ef0SDamon Ding 4541a552a69cSDamon Ding if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) { 4542481ef52dSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 4543481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000); 4544481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100); 4545481ef52dSDamon Ding vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100); 4546481ef52dSDamon Ding } 4547481ef52dSDamon Ding 4548a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4549a552a69cSDamon Ding PRE_DITHER_DOWN_EN_SHIFT, 0, false); 4550e2bdb3b3SDamon Ding /* enable frc2.0 do 10->8 */ 4551a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4552a552a69cSDamon Ding DITHER_DOWN_EN_SHIFT, 1, false); 4553e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK, 4554e2bdb3b3SDamon Ding DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false); 4555a552a69cSDamon Ding } else { 455634d37ef0SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 455734d37ef0SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 4558e2bdb3b3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK, 4559e2bdb3b3SDamon Ding DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false); 456034d37ef0SDamon Ding } 4561a552a69cSDamon Ding } 456234d37ef0SDamon Ding 4563ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state) 4564ecc31b6eSAndy Yan { 4565ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4566c2b1fe35SDamon Ding struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id]; 4567ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 4568ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 4569ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4570ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 4571ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 4572ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal; 4573ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 4574ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay; 4575ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay; 4576ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal; 4577ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 4578ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 4579ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay; 4580ecc31b6eSAndy Yan bool yuv_overlay = false; 4581ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 458266724b9cSDamon Ding u32 line_flag_offset = (cstate->crtc_id * 4); 458366724b9cSDamon Ding u32 val, act_end; 458458cf1fa3SDamon Ding u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4585edfef528SDamon Ding u8 dclk_div_factor = 0; 4586a552a69cSDamon Ding u8 vp_dclk_div = 1; 4587ecc31b6eSAndy Yan char output_type_name[30] = {0}; 4588d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 4589ecc31b6eSAndy Yan char dclk_name[9]; 4590d8e7f4a5SSandy Huang #endif 4591b890760eSAlgea Cao struct clk hdmi0_phy_pll; 4592b890760eSAlgea Cao struct clk hdmi1_phy_pll; 45935f1357a2SZhang Yubing struct clk hdmi_phy_pll; 45943e05a7b8SZhang Yubing struct udevice *disp_dev; 45955fa6e665SDamon Ding unsigned long dclk_rate = 0; 4596ecc31b6eSAndy Yan int ret; 4597ecc31b6eSAndy Yan 4598ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 459971ac76f7SDamon Ding mode->crtc_hdisplay, mode->vdisplay, 4600ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 46014d64cedbSDamon Ding mode->vrefresh, 46022264c88bSDamon Ding rockchip_get_output_if_name(conn_state->output_if, output_type_name), 4603ecc31b6eSAndy Yan cstate->crtc_id); 4604ecc31b6eSAndy Yan 4605ee01dbb2SDamon Ding if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { 4606ee01dbb2SDamon Ding cstate->splice_mode = true; 4607ee01dbb2SDamon Ding cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id; 4608ee01dbb2SDamon Ding if (!cstate->splice_crtc_id) { 4609ee01dbb2SDamon Ding printf("%s: Splice mode is unsupported by vp%d\n", 4610ee01dbb2SDamon Ding __func__, cstate->crtc_id); 4611ee01dbb2SDamon Ding return -EINVAL; 4612ee01dbb2SDamon Ding } 4613b70b2d79SDamon Ding 4614b70b2d79SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK, 4615b70b2d79SDamon Ding PORT_MERGE_EN_SHIFT, 1, false); 4616ee01dbb2SDamon Ding } 4617ee01dbb2SDamon Ding 4618cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 4619cd6c85a9SDamon Ding RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false); 4620cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 4621cd6c85a9SDamon Ding RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false); 4622cd6c85a9SDamon Ding 462344b1b62cSDamon Ding if (vop2->data->vp_data[cstate->crtc_id].urgency) { 462444b1b62cSDamon Ding u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl; 462544b1b62cSDamon Ding u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh; 462644b1b62cSDamon Ding 462744b1b62cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK, 462844b1b62cSDamon Ding AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false); 462944b1b62cSDamon Ding vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK, 463044b1b62cSDamon Ding AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false); 463144b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK, 463244b1b62cSDamon Ding POST_URGENCY_EN_SHIFT, 1, false); 463344b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK, 463444b1b62cSDamon Ding POST_URGENCY_THL_SHIFT, urgen_thl, false); 463544b1b62cSDamon Ding vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK, 463644b1b62cSDamon Ding POST_URGENCY_THH_SHIFT, urgen_thh, false); 463744b1b62cSDamon Ding } 463844b1b62cSDamon Ding 4639ecc31b6eSAndy Yan vop2_initial(vop2, state); 4640ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 4641ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state); 4642a552a69cSDamon Ding else if (vop2->version == VOP_VERSION_RK3576) 4643a552a69cSDamon Ding dclk_rate = rk3576_vop2_if_cfg(state); 46445fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3568) 4645ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state); 4646452afb13SDamon Ding else if (vop2->version == VOP_VERSION_RK3562) 4647452afb13SDamon Ding dclk_rate = rk3562_vop2_if_cfg(state); 4648a552a69cSDamon Ding else if (vop2->version == VOP_VERSION_RK3528) 4649a552a69cSDamon Ding dclk_rate = rk3528_vop2_if_cfg(state); 4650ecc31b6eSAndy Yan 46515d2768f7SDamon Ding if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 46525d2768f7SDamon Ding !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) || 46535d2768f7SDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 46547bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 46557bdd0eb6SSandy Huang 4656bf7c1abfSDamon Ding if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 4657bf7c1abfSDamon Ding if (vop2->version == VOP_VERSION_RK3588 && 4658bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_DisplayPort) 4659bf7c1abfSDamon Ding conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420; 4660bf7c1abfSDamon Ding } else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) { 4661bf7c1abfSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && 4662bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_eDP) 4663bf7c1abfSDamon Ding conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422; 4664bf7c1abfSDamon Ding else if (vop2->version == VOP_VERSION_RK3588 && 4665bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_eDP) 4666bf7c1abfSDamon Ding conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422; 4667bf7c1abfSDamon Ding else if (vop2->version == VOP_VERSION_RK3576 && 4668bf7c1abfSDamon Ding conn_state->type == DRM_MODE_CONNECTOR_HDMIA) 4669bf7c1abfSDamon Ding conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422; 4670bf7c1abfSDamon Ding else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort) 4671bf7c1abfSDamon Ding conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422; 4672bf7c1abfSDamon Ding } 4673bf7c1abfSDamon Ding 467465747de7SDamon Ding vop2_post_color_swap(state); 467510ee9f5bSAlgea Cao 4676d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 4677d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false); 4678d0408543SAndy Yan 467934d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id); 468034d37ef0SDamon Ding if (cstate->splice_mode) 468134d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id); 4682d0408543SAndy Yan 4683d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 4684d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 4685d0408543SAndy Yan yuv_overlay, false); 4686d0408543SAndy Yan 4687d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay; 4688d0408543SAndy Yan 4689d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 4690d0408543SAndy Yan (htotal << 16) | hsync_len); 4691d0408543SAndy Yan val = hact_st << 16; 4692d0408543SAndy Yan val |= hact_end; 4693d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 4694d0408543SAndy Yan val = vact_st << 16; 4695d0408543SAndy Yan val |= vact_end; 4696d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 4697d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 4698d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 4699d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay; 4700d0408543SAndy Yan 4701d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 4702d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 4703d0408543SAndy Yan val); 4704d0408543SAndy Yan 4705d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len); 4706d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 4707d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4708d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false); 4709d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 47107a20be36SSandy Huang DSP_FILED_POL, 1, false); 47117a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4712d0408543SAndy Yan P2I_EN_SHIFT, 1, false); 4713d0408543SAndy Yan vtotal += vtotal + 1; 471466724b9cSDamon Ding act_end = vact_end_f1; 4715d0408543SAndy Yan } else { 4716d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4717d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false); 4718d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4719d0408543SAndy Yan P2I_EN_SHIFT, 0, false); 472066724b9cSDamon Ding act_end = vact_end; 4721d0408543SAndy Yan } 4722d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 4723d0408543SAndy Yan (vtotal << 16) | vsync_len); 472467be2ffcSDamon Ding 4725a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3528 || 4726a552a69cSDamon Ding vop2->version == VOP_VERSION_RK3562 || 4727a552a69cSDamon Ding vop2->version == VOP_VERSION_RK3568) { 472867be2ffcSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || 472967be2ffcSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 4730d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 473167be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 1, false); 473267be2ffcSDamon Ding else 473367be2ffcSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 473467be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 0, false); 473510ee9f5bSAlgea Cao 473610ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 473763cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 473863cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 473910ee9f5bSAlgea Cao else 474063cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 474163cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 4742a552a69cSDamon Ding } 474310ee9f5bSAlgea Cao 4744ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 4745ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false); 4746ee01dbb2SDamon Ding 474710ee9f5bSAlgea Cao if (yuv_overlay) 474810ee9f5bSAlgea Cao val = 0x20010200; 474910ee9f5bSAlgea Cao else 475010ee9f5bSAlgea Cao val = 0; 475110ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 4752b70b2d79SDamon Ding if (cstate->splice_mode) { 4753ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 4754ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id, 4755ee01dbb2SDamon Ding yuv_overlay, false); 4756ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val); 4757ee01dbb2SDamon Ding } 475810ee9f5bSAlgea Cao 475910ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 476010ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 4761d0408543SAndy Yan 4762c2b1fe35SDamon Ding if (vp->xmirror_en) 4763c2b1fe35SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4764c2b1fe35SDamon Ding DSP_X_MIR_EN_SHIFT, 1, false); 4765c2b1fe35SDamon Ding 4766ac500a1fSSandy Huang vop2_tv_config_update(state, vop2); 4767d0408543SAndy Yan vop2_post_config(state, vop2); 47686027c871SZhang Yubing if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) 47696027c871SZhang Yubing vop3_post_config(state, vop2); 4770d0408543SAndy Yan 477112ee5af0SDamon Ding if (cstate->dsc_enable) { 477212ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 47731ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL); 47741ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL); 477512ee5af0SDamon Ding } else { 47761ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL); 477712ee5af0SDamon Ding } 477812ee5af0SDamon Ding } 477912ee5af0SDamon Ding 4780d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 4781ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 47820675a2a4SDamon Ding ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk); 4783b890760eSAlgea Cao if (ret) { 4784b890760eSAlgea Cao printf("%s: Failed to get dclk ret=%d\n", __func__, ret); 4785b890760eSAlgea Cao return ret; 4786b890760eSAlgea Cao } 4787d8e7f4a5SSandy Huang #endif 4788b890760eSAlgea Cao 47893e05a7b8SZhang Yubing ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev); 47903e05a7b8SZhang Yubing if (!ret) { 47913e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll); 47923e05a7b8SZhang Yubing if (ret) 47935e85f4a7SZhang Yubing debug("%s: hdmi0_phy_pll may not define\n", __func__); 47943e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll); 47953e05a7b8SZhang Yubing if (ret) 47965e85f4a7SZhang Yubing debug("%s: hdmi1_phy_pll may not define\n", __func__); 47973e05a7b8SZhang Yubing } else { 4798b890760eSAlgea Cao hdmi0_phy_pll.dev = NULL; 4799545a0218SAlgea Cao hdmi1_phy_pll.dev = NULL; 48005e85f4a7SZhang Yubing debug("%s: Faile to find display-subsystem node\n", __func__); 4801b890760eSAlgea Cao } 4802b890760eSAlgea Cao 4803ebbd144cSAlgea Cao if (vop2->version == VOP_VERSION_RK3528) { 4804ebbd144cSAlgea Cao struct ofnode_phandle_args args; 4805ebbd144cSAlgea Cao 4806ebbd144cSAlgea Cao ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents", 4807ebbd144cSAlgea Cao "#clock-cells", 0, 0, &args); 4808ebbd144cSAlgea Cao if (!ret) { 4809ebbd144cSAlgea Cao ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev); 4810ebbd144cSAlgea Cao if (ret) { 4811ebbd144cSAlgea Cao debug("warn: can't get clk device\n"); 4812ebbd144cSAlgea Cao return ret; 4813ebbd144cSAlgea Cao } 4814ebbd144cSAlgea Cao } else { 4815ebbd144cSAlgea Cao debug("assigned-clock-parents's node not define\n"); 4816ebbd144cSAlgea Cao } 4817ebbd144cSAlgea Cao } 4818ebbd144cSAlgea Cao 4819cce1f2abSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 4820cce1f2abSDamon Ding vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div; 4821cce1f2abSDamon Ding 48220a1fb152SZhang Yubing if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) { 4823b890760eSAlgea Cao if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) 48240675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll); 4825b890760eSAlgea Cao else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1) 48260675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll); 4827b890760eSAlgea Cao 4828b890760eSAlgea Cao /* 4829b890760eSAlgea Cao * uboot clk driver won't set dclk parent's rate when use 4830b890760eSAlgea Cao * hdmi phypll as dclk source. 4831b890760eSAlgea Cao * So set dclk rate is meaningless. Set hdmi phypll rate 4832b890760eSAlgea Cao * directly. 4833b890760eSAlgea Cao */ 48345f1357a2SZhang Yubing if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) { 4835cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000); 48365f1357a2SZhang Yubing } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) { 4837cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000); 48385f1357a2SZhang Yubing } else { 48397efea85dSDamon Ding if (is_extend_pll(state, &hdmi_phy_pll.dev)) { 4840cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi_phy_pll, 4841cce1f2abSDamon Ding dclk_rate / vp_dclk_div * 1000); 48427efea85dSDamon Ding } else { 4843d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 4844a552a69cSDamon Ding ret = vop2_clk_set_rate(&cstate->dclk, 4845a552a69cSDamon Ding dclk_rate / vp_dclk_div * 1000); 4846d8e7f4a5SSandy Huang #else 4847d8e7f4a5SSandy Huang if (vop2->version == VOP_VERSION_RK3528) { 4848d8e7f4a5SSandy Huang void *cru_base = (void *)RK3528_CRU_BASE; 4849d8e7f4a5SSandy Huang 4850d8e7f4a5SSandy Huang /* dclk src switch to hdmiphy pll */ 4851d8e7f4a5SSandy Huang writel((BIT(0) << 16) | BIT(0), cru_base + 0x450); 4852d8e7f4a5SSandy Huang rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000); 4853d8e7f4a5SSandy Huang ret = dclk_rate * 1000; 4854d8e7f4a5SSandy Huang } 4855d8e7f4a5SSandy Huang #endif 48565f1357a2SZhang Yubing } 48577efea85dSDamon Ding } 4858631ee99aSZhang Yubing } else { 48595f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev)) 4860cce1f2abSDamon Ding ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000); 48615f1357a2SZhang Yubing else 4862cce1f2abSDamon Ding ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000); 4863edfef528SDamon Ding } 486463638f32SDamon Ding 486563638f32SDamon Ding if (IS_ERR_VALUE(ret)) { 486663638f32SDamon Ding printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 486763638f32SDamon Ding __func__, cstate->crtc_id, dclk_rate, ret); 486863638f32SDamon Ding return ret; 486963638f32SDamon Ding } else { 48704d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total) { 48714d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) / 1000; 48724d64cedbSDamon Ding } else { 48739655ad2fSDamon Ding dclk_div_factor = mode->crtc_clock / dclk_rate; 48744d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000; 48754d64cedbSDamon Ding } 4876edfef528SDamon Ding printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); 4877631ee99aSZhang Yubing } 4878ecc31b6eSAndy Yan 487966724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 4880e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false); 488166724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 4882e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false); 488366724b9cSDamon Ding 488458cf1fa3SDamon Ding if (cstate->mcu_timing.mcu_pix_total) { 488558cf1fa3SDamon Ding vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 488658cf1fa3SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 488758cf1fa3SDamon Ding STANDBY_EN_SHIFT, 0, false); 48880675a2a4SDamon Ding vop3_mcu_mode_setup(state); 488958cf1fa3SDamon Ding } 48900675a2a4SDamon Ding 4891d0408543SAndy Yan return 0; 4892d0408543SAndy Yan } 4893d0408543SAndy Yan 4894ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 48953e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w, 48963e39a5a1SSandy Huang uint32_t dst_h) 48973e39a5a1SSandy Huang { 48983e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 48993e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode; 49005fa6e665SDamon Ding uint8_t xgt2 = 0, xgt4 = 0; 49015fa6e665SDamon Ding uint8_t ygt2 = 0, ygt4 = 0; 49023e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0; 4903ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 49045fa6e665SDamon Ding bool xgt_en = false; 49055fa6e665SDamon Ding bool xavg_en = false; 49063e39a5a1SSandy Huang 49075fa6e665SDamon Ding if (is_vop3(vop2)) { 4908a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) { 4909a552a69cSDamon Ding if (src_w >= (8 * dst_w)) { 4910a552a69cSDamon Ding xgt4 = 1; 4911a552a69cSDamon Ding src_w >>= 2; 4912a552a69cSDamon Ding } else if (src_w >= (4 * dst_w)) { 4913a552a69cSDamon Ding xgt2 = 1; 4914a552a69cSDamon Ding src_w >>= 1; 4915a552a69cSDamon Ding } 4916a552a69cSDamon Ding } else { 49175fa6e665SDamon Ding if (src_w >= (4 * dst_w)) { 49185fa6e665SDamon Ding xgt4 = 1; 49195fa6e665SDamon Ding src_w >>= 2; 49205fa6e665SDamon Ding } else if (src_w >= (2 * dst_w)) { 49215fa6e665SDamon Ding xgt2 = 1; 49225fa6e665SDamon Ding src_w >>= 1; 49235fa6e665SDamon Ding } 49245fa6e665SDamon Ding } 4925a552a69cSDamon Ding } 49263e39a5a1SSandy Huang 4927183eb252SDamon Ding /** 4928183eb252SDamon Ding * The rk3528 is processed as 2 pixel/cycle, 4929183eb252SDamon Ding * so ygt2/ygt4 needs to be triggered in advance to improve performance 4930183eb252SDamon Ding * when src_w is bigger than 1920. 4931183eb252SDamon Ding * dst_h / src_h is at [1, 0.65) ygt2=0; ygt4=0; 4932183eb252SDamon Ding * dst_h / src_h is at [0.65, 0.35) ygt2=1; ygt4=0; 4933183eb252SDamon Ding * dst_h / src_h is at [0.35, 0) ygt2=0; ygt4=1; 4934183eb252SDamon Ding */ 4935183eb252SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) { 4936183eb252SDamon Ding if (src_h >= (100 * dst_h / 35)) { 4937183eb252SDamon Ding ygt4 = 1; 4938183eb252SDamon Ding src_h >>= 2; 4939183eb252SDamon Ding } else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) { 4940183eb252SDamon Ding ygt2 = 1; 4941183eb252SDamon Ding src_h >>= 1; 4942183eb252SDamon Ding } 4943183eb252SDamon Ding } else { 4944a552a69cSDamon Ding if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { 4945a552a69cSDamon Ding if (src_h >= (8 * dst_h)) { 4946a552a69cSDamon Ding ygt4 = 1; 4947a552a69cSDamon Ding src_h >>= 2; 4948a552a69cSDamon Ding } else if (src_h >= (4 * dst_h)) { 4949a552a69cSDamon Ding ygt2 = 1; 4950a552a69cSDamon Ding src_h >>= 1; 4951a552a69cSDamon Ding } 4952a552a69cSDamon Ding } else { 49535fa6e665SDamon Ding if (src_h >= (4 * dst_h)) { 49545fa6e665SDamon Ding ygt4 = 1; 49553e39a5a1SSandy Huang src_h >>= 2; 49565fa6e665SDamon Ding } else if (src_h >= (2 * dst_h)) { 49575fa6e665SDamon Ding ygt2 = 1; 49583e39a5a1SSandy Huang src_h >>= 1; 49595fa6e665SDamon Ding } 4960183eb252SDamon Ding } 4961a552a69cSDamon Ding } 49623e39a5a1SSandy Huang 49633e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 49643e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 49653e39a5a1SSandy Huang 49663e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP) 49675fa6e665SDamon Ding hscl_filter_mode = win->hsu_filter_mode; 49683e39a5a1SSandy Huang else 49695fa6e665SDamon Ding hscl_filter_mode = win->hsd_filter_mode; 49703e39a5a1SSandy Huang 49713e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP) 49725fa6e665SDamon Ding vscl_filter_mode = win->vsu_filter_mode; 49733e39a5a1SSandy Huang else 49745fa6e665SDamon Ding vscl_filter_mode = win->vsd_filter_mode; 49753e39a5a1SSandy Huang 49763e39a5a1SSandy Huang /* 49773e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel 49783e39a5a1SSandy Huang * at scale down mode 49793e39a5a1SSandy Huang */ 49805fa6e665SDamon Ding if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) { 49813e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 49823e39a5a1SSandy Huang dst_w += 1; 49833e39a5a1SSandy Huang } 49843e39a5a1SSandy Huang 49855fa6e665SDamon Ding if (is_vop3(vop2)) { 49865fa6e665SDamon Ding xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true); 49875fa6e665SDamon Ding yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false); 49885fa6e665SDamon Ding 49895fa6e665SDamon Ding if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG) 49905fa6e665SDamon Ding xavg_en = xgt2 || xgt4; 49915fa6e665SDamon Ding else 49925fa6e665SDamon Ding xgt_en = xgt2 || xgt4; 4993a552a69cSDamon Ding 4994a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) { 4995a552a69cSDamon Ding bool zme_dering_en = false; 4996a552a69cSDamon Ding 4997a552a69cSDamon Ding if ((yrgb_hor_scl_mode == SCALE_UP && 4998a552a69cSDamon Ding hscl_filter_mode == VOP2_SCALE_UP_ZME) || 4999a552a69cSDamon Ding (yrgb_ver_scl_mode == SCALE_UP && 5000a552a69cSDamon Ding vscl_filter_mode == VOP2_SCALE_UP_ZME)) 5001a552a69cSDamon Ding zme_dering_en = true; 5002a552a69cSDamon Ding 5003a552a69cSDamon Ding /* Recommended configuration from the algorithm */ 5004a552a69cSDamon Ding vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset, 5005a552a69cSDamon Ding 0x04100d10); 5006a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset, 5007a552a69cSDamon Ding EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false); 5008a552a69cSDamon Ding } 50095fa6e665SDamon Ding } else { 50103e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 50113e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 50125fa6e665SDamon Ding } 5013ecc31b6eSAndy Yan 5014ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) { 5015ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 5016ecc31b6eSAndy Yan yfac << 16 | xfac); 5017ecc31b6eSAndy Yan 50185fa6e665SDamon Ding if (is_vop3(vop2)) { 5019ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50205fa6e665SDamon Ding EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false); 5021ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50225fa6e665SDamon Ding EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false); 50235fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50245fa6e665SDamon Ding XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 5025ecc31b6eSAndy Yan 5026ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50275fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT, 50285fa6e665SDamon Ding yrgb_hor_scl_mode, false); 5029ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50305fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT, 50315fa6e665SDamon Ding yrgb_ver_scl_mode, false); 50325fa6e665SDamon Ding } else { 50335fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50345fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT, 50355fa6e665SDamon Ding yrgb_hor_scl_mode, false); 50365fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50375fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT, 50385fa6e665SDamon Ding yrgb_ver_scl_mode, false); 50395fa6e665SDamon Ding } 5040ecc31b6eSAndy Yan 50415fa6e665SDamon Ding if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) { 50425fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50435fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false); 50445fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50455fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false); 50465fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50475fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false); 50485fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50495fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false); 50505fa6e665SDamon Ding } else { 50515fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50525fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false); 50535fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50545fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false); 50555fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50565fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false); 50575fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 50585fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false); 50595fa6e665SDamon Ding } 5060ecc31b6eSAndy Yan } else { 50613e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 50623e39a5a1SSandy Huang yfac << 16 | xfac); 50633e39a5a1SSandy Huang 50645fa6e665SDamon Ding if (is_vop3(vop2)) { 506534a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50665fa6e665SDamon Ding EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false); 506734a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50685fa6e665SDamon Ding EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false); 50695fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50705fa6e665SDamon Ding XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 50715fa6e665SDamon Ding } 50725fa6e665SDamon Ding 50735fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50745fa6e665SDamon Ding YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false); 50755fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 50765fa6e665SDamon Ding YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false); 50773e39a5a1SSandy Huang 50783e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50793e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 50803e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50813e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 50823e39a5a1SSandy Huang 50833e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50843e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 50853e39a5a1SSandy Huang hscl_filter_mode, false); 50863e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 50873e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 50883e39a5a1SSandy Huang vscl_filter_mode, false); 50893e39a5a1SSandy Huang } 5090ecc31b6eSAndy Yan } 50913e39a5a1SSandy Huang 5092a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win) 5093a33b790fSDamon Ding { 5094a33b790fSDamon Ding u32 win_offset = win->reg_offset; 5095a33b790fSDamon Ding 5096a33b790fSDamon Ding if (win->type == CLUSTER_LAYER) { 5097a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK, 5098a33b790fSDamon Ding CLUSTER_AXI_ID_SHIFT, win->axi_id, false); 5099a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK, 5100a33b790fSDamon Ding CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 5101a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK, 5102a33b790fSDamon Ding CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 5103a33b790fSDamon Ding } else { 5104a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK, 5105a33b790fSDamon Ding ESMART_AXI_ID_SHIFT, win->axi_id, false); 5106a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK, 5107a33b790fSDamon Ding ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 5108a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK, 5109a33b790fSDamon Ding ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 5110a33b790fSDamon Ding } 5111a33b790fSDamon Ding } 5112a33b790fSDamon Ding 5113840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format) 5114840bf541SDamon Ding { 5115840bf541SDamon Ding switch (format) { 5116840bf541SDamon Ding case ROCKCHIP_FMT_RGB565: 5117840bf541SDamon Ding return true; 5118840bf541SDamon Ding default: 5119840bf541SDamon Ding return false; 5120840bf541SDamon Ding } 5121840bf541SDamon Ding } 5122840bf541SDamon Ding 51231c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win) 51241c9572c7SDamon Ding { 51251c9572c7SDamon Ding return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR); 51261c9572c7SDamon Ding } 51271c9572c7SDamon Ding 51281c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 5129d0408543SAndy Yan { 5130d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 5131d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 5132d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 5133d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 5134ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 5135ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 5136ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 5137ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 5138ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 5139ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 5140d0408543SAndy Yan int xvir = cstate->xvir; 5141d0408543SAndy Yan int y_mirror = 0; 514210ee9f5bSAlgea Cao int csc_mode; 5143ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 5144ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 5145ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 5146ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 5147ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 5148ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5149840bf541SDamon Ding bool dither_up; 5150d0408543SAndy Yan 5151ee01dbb2SDamon Ding if (win->splice_mode_right) { 5152ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 5153ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 5154ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 5155ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 5156ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 5157ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 5158ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 5159ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 5160ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5161ee01dbb2SDamon Ding } 5162ee01dbb2SDamon Ding 5163ecc31b6eSAndy Yan act_info = (src_h - 1) << 16; 5164ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff; 5165ecc31b6eSAndy Yan 5166ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16; 5167ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 5168ecc31b6eSAndy Yan 5169ecc31b6eSAndy Yan dsp_stx = crtc_x; 5170ecc31b6eSAndy Yan dsp_sty = crtc_y; 5171ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 5172ecc31b6eSAndy Yan 5173ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 5174ecc31b6eSAndy Yan y_mirror = 1; 5175ecc31b6eSAndy Yan else 5176ecc31b6eSAndy Yan y_mirror = 0; 5177ecc31b6eSAndy Yan 5178ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 5179ecc31b6eSAndy Yan 5180a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3568) 5181a33b790fSDamon Ding vop2_axi_config(vop2, win); 5182a33b790fSDamon Ding 5183ecc31b6eSAndy Yan if (y_mirror) 5184ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n"); 5185ecc31b6eSAndy Yan 5186a552a69cSDamon Ding if (is_vop3(vop2)) 5187a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset, 5188a552a69cSDamon Ding CLUSTER_PORT_SEL_SHIFT, CLUSTER_PORT_SEL_SHIFT, 5189a552a69cSDamon Ding cstate->crtc_id, false); 5190a552a69cSDamon Ding 5191e84ccd9bSDamon Ding /* 5192e84ccd9bSDamon Ding * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode. 5193e84ccd9bSDamon Ding */ 5194e84ccd9bSDamon Ding if (vop2->version >= VOP_VERSION_RK3588) 5195a59754e1SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset, 5196a59754e1SDamon Ding EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false); 5197a59754e1SDamon Ding 5198ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 5199ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 5200ecc31b6eSAndy Yan false); 5201ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 5202ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, 5203ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 5204ecc31b6eSAndy Yan 5205ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 5206ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 5207ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 5208ecc31b6eSAndy Yan 5209ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 5210ecc31b6eSAndy Yan 5211df0a5c43SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range, 5212df0a5c43SDamon Ding CSC_10BIT_DEPTH); 5213ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 5214ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT, 5215ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false); 5216ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 5217ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 5218840bf541SDamon Ding 5219840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format); 5220840bf541SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 5221840bf541SDamon Ding CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false); 5222840bf541SDamon Ding 5223ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 5224ecc31b6eSAndy Yan 5225ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 52261c9572c7SDamon Ding 52271c9572c7SDamon Ding return 0; 5228d0408543SAndy Yan } 5229d0408543SAndy Yan 52301c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 5231ecc31b6eSAndy Yan { 5232ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 5233ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 5234ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 5235ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 5236ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 5237ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 5238ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 5239ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 5240ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 5241ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 5242ecc31b6eSAndy Yan int xvir = cstate->xvir; 5243ecc31b6eSAndy Yan int y_mirror = 0; 5244ecc31b6eSAndy Yan int csc_mode; 5245ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 5246ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 5247ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 5248ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 5249ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 5250ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 52511c9572c7SDamon Ding u32 val; 5252840bf541SDamon Ding bool dither_up; 5253ecc31b6eSAndy Yan 52541c9572c7SDamon Ding if (vop2_is_mirror_win(win)) { 52551c9572c7SDamon Ding struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id); 52561c9572c7SDamon Ding 52571c9572c7SDamon Ding if (!source_win) { 52581c9572c7SDamon Ding printf("invalid source win id %d\n", win->source_win_id); 52591c9572c7SDamon Ding return -ENODEV; 52601c9572c7SDamon Ding } 52611c9572c7SDamon Ding 52621c9572c7SDamon Ding val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset); 52631c9572c7SDamon Ding if (!(val & BIT(WIN_EN_SHIFT))) { 52641c9572c7SDamon Ding printf("WARN: the source win should be enabled before mirror win\n"); 52651c9572c7SDamon Ding return -EAGAIN; 52661c9572c7SDamon Ding } 52671c9572c7SDamon Ding } 52681c9572c7SDamon Ding 5269ee01dbb2SDamon Ding if (win->splice_mode_right) { 5270ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 5271ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 5272ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 5273ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 5274ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 5275ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 5276ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 5277ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 5278ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5279ee01dbb2SDamon Ding } 5280ee01dbb2SDamon Ding 528174bd8269SSandy Huang /* 528274bd8269SSandy Huang * This is workaround solution for IC design: 528374bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1. 528474bd8269SSandy Huang */ 528574bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) { 528674bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 528774bd8269SSandy Huang src_w -= 1; 528874bd8269SSandy Huang } 528974bd8269SSandy Huang 5290d0408543SAndy Yan act_info = (src_h - 1) << 16; 5291d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff; 5292d0408543SAndy Yan 5293d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16; 5294d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 5295d0408543SAndy Yan 5296d0408543SAndy Yan dsp_stx = crtc_x; 5297d0408543SAndy Yan dsp_sty = crtc_y; 5298d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 5299d0408543SAndy Yan 5300d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 5301d0408543SAndy Yan y_mirror = 1; 5302d0408543SAndy Yan else 5303d0408543SAndy Yan y_mirror = 0; 5304d0408543SAndy Yan 5305a552a69cSDamon Ding if (is_vop3(vop2)) { 5306a552a69cSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, 5307a552a69cSDamon Ding ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT, 5308a552a69cSDamon Ding win->scale_engine_num, false); 5309a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset, 5310a552a69cSDamon Ding ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT, 5311a552a69cSDamon Ding cstate->crtc_id, false); 5312a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM + win_offset, 5313a552a69cSDamon Ding ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 5314a552a69cSDamon Ding 0, false); 5315a552a69cSDamon Ding 5316a552a69cSDamon Ding /* Merge esmart1/3 from vp1 post to vp0 */ 5317a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 && 5318a552a69cSDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || 5319a552a69cSDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART3)) 5320a552a69cSDamon Ding vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset, 5321a552a69cSDamon Ding ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT, 5322a552a69cSDamon Ding 1, false); 5323a552a69cSDamon Ding } 53245fa6e665SDamon Ding 5325ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 53263e39a5a1SSandy Huang 5327a552a69cSDamon Ding if (vop2->version != VOP_VERSION_RK3568) 5328a33b790fSDamon Ding vop2_axi_config(vop2, win); 5329a33b790fSDamon Ding 5330d0408543SAndy Yan if (y_mirror) 5331d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4; 5332d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 5333d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false); 5334d0408543SAndy Yan 5335d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5336d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 5337d0408543SAndy Yan false); 5338a552a69cSDamon Ding 5339a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3576) 5340a552a69cSDamon Ding vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00); 5341a552a69cSDamon Ding 5342d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 5343d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 5344ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 5345d0408543SAndy Yan 5346d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 5347d0408543SAndy Yan act_info); 5348d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 5349d0408543SAndy Yan dsp_info); 5350d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 5351d0408543SAndy Yan 5352d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 5353d0408543SAndy Yan WIN_EN_SHIFT, 1, false); 5354d0408543SAndy Yan 5355df0a5c43SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range, 5356df0a5c43SDamon Ding CSC_10BIT_DEPTH); 535710ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 535810ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT, 535910ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false); 536010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 536110ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false); 536210ee9f5bSAlgea Cao 5363840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format); 5364840bf541SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 5365840bf541SDamon Ding REGION0_DITHER_UP_EN_SHIFT, dither_up, false); 5366840bf541SDamon Ding 5367d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 53681c9572c7SDamon Ding 53691c9572c7SDamon Ding return 0; 5370ecc31b6eSAndy Yan } 5371ecc31b6eSAndy Yan 5372ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state) 5373ee01dbb2SDamon Ding { 5374ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 5375ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 5376ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 5377ee01dbb2SDamon Ding struct display_rect *src_rect = &cstate->src_rect; 5378ee01dbb2SDamon Ding struct display_rect *dst_rect = &cstate->crtc_rect; 5379ee01dbb2SDamon Ding struct display_rect left_src, left_dst, right_src, right_dst; 5380ee01dbb2SDamon Ding u16 half_hdisplay = mode->crtc_hdisplay >> 1; 5381ee01dbb2SDamon Ding int left_src_w, left_dst_w, right_dst_w; 5382ee01dbb2SDamon Ding 5383ee01dbb2SDamon Ding left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x; 5384ee01dbb2SDamon Ding if (left_dst_w < 0) 5385ee01dbb2SDamon Ding left_dst_w = 0; 5386ee01dbb2SDamon Ding right_dst_w = dst_rect->w - left_dst_w; 5387ee01dbb2SDamon Ding 5388ee01dbb2SDamon Ding if (!right_dst_w) 5389ee01dbb2SDamon Ding left_src_w = src_rect->w; 5390ee01dbb2SDamon Ding else 53910df0fd39SSandy Huang left_src_w = src_rect->x + src_rect->w - src_rect->w / 2; 5392ee01dbb2SDamon Ding 5393ee01dbb2SDamon Ding left_src.x = src_rect->x; 5394ee01dbb2SDamon Ding left_src.w = left_src_w; 5395ee01dbb2SDamon Ding left_dst.x = dst_rect->x; 5396ee01dbb2SDamon Ding left_dst.w = left_dst_w; 5397ee01dbb2SDamon Ding right_src.x = left_src.x + left_src.w; 5398ee01dbb2SDamon Ding right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w; 5399ee01dbb2SDamon Ding right_dst.x = dst_rect->x + left_dst_w - half_hdisplay; 5400ee01dbb2SDamon Ding right_dst.w = right_dst_w; 5401ee01dbb2SDamon Ding 5402ee01dbb2SDamon Ding left_src.y = src_rect->y; 5403ee01dbb2SDamon Ding left_src.h = src_rect->h; 5404ee01dbb2SDamon Ding left_dst.y = dst_rect->y; 5405ee01dbb2SDamon Ding left_dst.h = dst_rect->h; 5406ee01dbb2SDamon Ding right_src.y = src_rect->y; 5407ee01dbb2SDamon Ding right_src.h = src_rect->h; 5408ee01dbb2SDamon Ding right_dst.y = dst_rect->y; 5409ee01dbb2SDamon Ding right_dst.h = dst_rect->h; 5410ee01dbb2SDamon Ding 5411ee01dbb2SDamon Ding memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect)); 5412ee01dbb2SDamon Ding memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect)); 5413ee01dbb2SDamon Ding memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect)); 5414ee01dbb2SDamon Ding memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect)); 5415ee01dbb2SDamon Ding } 5416ee01dbb2SDamon Ding 5417ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state) 5418ecc31b6eSAndy Yan { 5419ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 5420ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 5421ecc31b6eSAndy Yan struct vop2_win_data *win_data; 5422ee01dbb2SDamon Ding struct vop2_win_data *splice_win_data; 5423ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 54241c9572c7SDamon Ding int ret; 5425ecc31b6eSAndy Yan 5426ee01dbb2SDamon Ding if (cstate->crtc_rect.w > cstate->max_output.width) { 5427ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n", 5428ee01dbb2SDamon Ding cstate->crtc_rect.w, cstate->max_output.width); 5429ecc31b6eSAndy Yan return -EINVAL; 5430ecc31b6eSAndy Yan } 5431ecc31b6eSAndy Yan 5432ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 5433ecc31b6eSAndy Yan if (!win_data) { 5434ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id); 5435ecc31b6eSAndy Yan return -ENODEV; 5436ecc31b6eSAndy Yan } 5437ecc31b6eSAndy Yan 54385fa6e665SDamon Ding /* ignore some plane register according vop3 esmart lb mode */ 54395fa6e665SDamon Ding if (vop3_ignore_plane(vop2, win_data)) 54405fa6e665SDamon Ding return -EACCES; 54415fa6e665SDamon Ding 5442a552a69cSDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) { 5443b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, win_data->pd_id)) 5444b6ba80b4SDamon Ding printf("open vp%d plane pd fail\n", cstate->crtc_id); 5445b6ba80b4SDamon Ding } 5446b6ba80b4SDamon Ding 5447ee01dbb2SDamon Ding if (cstate->splice_mode) { 5448ee01dbb2SDamon Ding if (win_data->splice_win_id) { 5449ee01dbb2SDamon Ding splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id); 5450ee01dbb2SDamon Ding splice_win_data->splice_mode_right = true; 5451b6ba80b4SDamon Ding 5452b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, splice_win_data->pd_id)) 5453b6ba80b4SDamon Ding printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id); 5454b6ba80b4SDamon Ding 5455ee01dbb2SDamon Ding vop2_calc_display_rect_for_splice(state); 5456ee01dbb2SDamon Ding if (win_data->type == CLUSTER_LAYER) 5457ee01dbb2SDamon Ding vop2_set_cluster_win(state, splice_win_data); 5458ee01dbb2SDamon Ding else 5459ee01dbb2SDamon Ding vop2_set_smart_win(state, splice_win_data); 5460ee01dbb2SDamon Ding } else { 5461ee01dbb2SDamon Ding printf("ERROR: splice mode is unsupported by plane %s\n", 546227cec8e2SDamon Ding vop2_plane_id_to_string(primary_plane_id)); 5463ee01dbb2SDamon Ding return -EINVAL; 5464ee01dbb2SDamon Ding } 5465ee01dbb2SDamon Ding } 5466ee01dbb2SDamon Ding 5467ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER) 54681c9572c7SDamon Ding ret = vop2_set_cluster_win(state, win_data); 5469ecc31b6eSAndy Yan else 54701c9572c7SDamon Ding ret = vop2_set_smart_win(state, win_data); 54711c9572c7SDamon Ding if (ret) 54721c9572c7SDamon Ding return ret; 54738895aec1SSandy Huang 54748895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 547527cec8e2SDamon Ding cstate->crtc_id, vop2_plane_id_to_string(primary_plane_id), 5476ee01dbb2SDamon Ding cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h, 5477ee01dbb2SDamon Ding cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format, 54788895aec1SSandy Huang cstate->dma_addr); 54798895aec1SSandy Huang 5480d0408543SAndy Yan return 0; 5481d0408543SAndy Yan } 5482d0408543SAndy Yan 5483d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state) 5484d0408543SAndy Yan { 5485d0408543SAndy Yan return 0; 5486d0408543SAndy Yan } 5487d0408543SAndy Yan 548812ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state) 548912ee5af0SDamon Ding { 549012ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 549112ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 549212ee5af0SDamon Ding struct vop2 *vop2 = cstate->private; 549312ee5af0SDamon Ding u8 dsc_id = cstate->dsc_id; 549412ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 549512ee5af0SDamon Ding 549612ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 549712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK, 549812ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 549912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK, 550012ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 550112ee5af0SDamon Ding } else { 550212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK, 550312ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 550412ee5af0SDamon Ding } 550512ee5af0SDamon Ding } 550612ee5af0SDamon Ding 5507d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state) 5508d0408543SAndy Yan { 5509d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 5510d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 551152ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 5512ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5513d0408543SAndy Yan 5514d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5515d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false); 5516ee01dbb2SDamon Ding 5517ee01dbb2SDamon Ding if (cstate->splice_mode) 5518ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5519ee01dbb2SDamon Ding 5520d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5521d0408543SAndy Yan 552212ee5af0SDamon Ding if (cstate->dsc_enable) 552312ee5af0SDamon Ding vop2_dsc_cfg_done(state); 552412ee5af0SDamon Ding 55250675a2a4SDamon Ding if (cstate->mcu_timing.mcu_pix_total) 55260675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 55270675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 0, false); 55280675a2a4SDamon Ding 5529d0408543SAndy Yan return 0; 5530d0408543SAndy Yan } 5531d0408543SAndy Yan 5532efa01fe4SZhang Yubing static int rk3588_vop2_post_enable(struct display_state *state) 5533efa01fe4SZhang Yubing { 5534efa01fe4SZhang Yubing struct connector_state *conn_state = &state->conn_state; 5535efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 5536efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private; 5537efa01fe4SZhang Yubing int output_if = conn_state->output_if; 5538efa01fe4SZhang Yubing u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5539efa01fe4SZhang Yubing int ret, val; 5540efa01fe4SZhang Yubing 5541efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP0) 5542efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 5543efa01fe4SZhang Yubing 1, false); 5544efa01fe4SZhang Yubing 5545efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP1) 5546efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT, 5547efa01fe4SZhang Yubing 1, false); 5548efa01fe4SZhang Yubing 5549efa01fe4SZhang Yubing if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) { 5550efa01fe4SZhang Yubing vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5551efa01fe4SZhang Yubing ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val, 5552efa01fe4SZhang Yubing val & BIT(cstate->crtc_id), 50 * 1000); 5553efa01fe4SZhang Yubing if (ret) 5554efa01fe4SZhang Yubing printf("%s wait cfg done timeout\n", __func__); 55550686a6a6SZhang Yubing 55560686a6a6SZhang Yubing if (cstate->dclk_rst.dev) { 55570686a6a6SZhang Yubing reset_assert(&cstate->dclk_rst); 55580686a6a6SZhang Yubing udelay(20); 55590686a6a6SZhang Yubing reset_deassert(&cstate->dclk_rst); 55600686a6a6SZhang Yubing } 5561efa01fe4SZhang Yubing } 5562efa01fe4SZhang Yubing 5563efa01fe4SZhang Yubing return 0; 5564efa01fe4SZhang Yubing } 5565efa01fe4SZhang Yubing 5566efa01fe4SZhang Yubing static int rk3576_vop2_post_enable(struct display_state *state) 5567efa01fe4SZhang Yubing { 5568efa01fe4SZhang Yubing struct connector_state *conn_state = &state->conn_state; 5569efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 5570efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private; 5571efa01fe4SZhang Yubing int output_if = conn_state->output_if; 5572efa01fe4SZhang Yubing u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5573efa01fe4SZhang Yubing int ret, val; 5574efa01fe4SZhang Yubing 5575efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP0) 5576efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 5577efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false); 5578efa01fe4SZhang Yubing 5579efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP1) 5580efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 5581efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false); 5582efa01fe4SZhang Yubing 5583efa01fe4SZhang Yubing if (output_if & VOP_OUTPUT_IF_DP2) 5584efa01fe4SZhang Yubing vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 5585efa01fe4SZhang Yubing RK3576_IF_OUT_EN_SHIFT, 1, false); 5586efa01fe4SZhang Yubing 5587efa01fe4SZhang Yubing if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) { 5588efa01fe4SZhang Yubing vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5589efa01fe4SZhang Yubing ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val, 5590efa01fe4SZhang Yubing val & BIT(cstate->crtc_id), 50 * 1000); 5591efa01fe4SZhang Yubing if (ret) 5592efa01fe4SZhang Yubing printf("%s wait cfg done timeout\n", __func__); 55930686a6a6SZhang Yubing 55940686a6a6SZhang Yubing if (cstate->dclk_rst.dev) { 55950686a6a6SZhang Yubing reset_assert(&cstate->dclk_rst); 55960686a6a6SZhang Yubing udelay(20); 55970686a6a6SZhang Yubing reset_deassert(&cstate->dclk_rst); 55980686a6a6SZhang Yubing } 5599efa01fe4SZhang Yubing } 5600efa01fe4SZhang Yubing 5601efa01fe4SZhang Yubing return 0; 5602efa01fe4SZhang Yubing } 5603efa01fe4SZhang Yubing 5604efa01fe4SZhang Yubing static int rockchip_vop2_post_enable(struct display_state *state) 5605efa01fe4SZhang Yubing { 5606efa01fe4SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 5607efa01fe4SZhang Yubing struct vop2 *vop2 = cstate->private; 5608efa01fe4SZhang Yubing 5609efa01fe4SZhang Yubing if (vop2->version == VOP_VERSION_RK3588) 5610efa01fe4SZhang Yubing rk3588_vop2_post_enable(state); 5611efa01fe4SZhang Yubing else if (vop2->version == VOP_VERSION_RK3576) 5612efa01fe4SZhang Yubing rk3576_vop2_post_enable(state); 5613efa01fe4SZhang Yubing 5614efa01fe4SZhang Yubing return 0; 5615efa01fe4SZhang Yubing } 5616efa01fe4SZhang Yubing 5617d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state) 5618d0408543SAndy Yan { 5619d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 5620d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 562152ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 5622ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5623d0408543SAndy Yan 5624d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5625d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false); 5626ee01dbb2SDamon Ding 5627ee01dbb2SDamon Ding if (cstate->splice_mode) 5628ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5629ee01dbb2SDamon Ding 5630d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5631d0408543SAndy Yan 5632d0408543SAndy Yan return 0; 5633d0408543SAndy Yan } 5634d0408543SAndy Yan 5635ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 5636ee008497SSandy Huang { 5637ee008497SSandy Huang struct crtc_state *cstate = &state->crtc_state; 5638ee008497SSandy Huang struct vop2 *vop2 = cstate->private; 5639ee008497SSandy Huang int i = 0; 5640ee008497SSandy Huang int correct_cursor_plane = -1; 5641ee008497SSandy Huang int plane_type = -1; 5642ee008497SSandy Huang 5643ee008497SSandy Huang if (cursor_plane < 0) 5644ee008497SSandy Huang return -1; 5645ee008497SSandy Huang 5646ee008497SSandy Huang if (plane_mask & (1 << cursor_plane)) 5647ee008497SSandy Huang return cursor_plane; 5648ee008497SSandy Huang 5649ee008497SSandy Huang /* Get current cursor plane type */ 5650ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 5651ee008497SSandy Huang if (vop2->data->plane_table[i].plane_id == cursor_plane) { 5652ee008497SSandy Huang plane_type = vop2->data->plane_table[i].plane_type; 5653ee008497SSandy Huang break; 5654ee008497SSandy Huang } 5655ee008497SSandy Huang } 5656ee008497SSandy Huang 5657ee008497SSandy Huang /* Get the other same plane type plane id */ 5658ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 5659ee008497SSandy Huang if (vop2->data->plane_table[i].plane_type == plane_type && 5660ee008497SSandy Huang vop2->data->plane_table[i].plane_id != cursor_plane) { 5661ee008497SSandy Huang correct_cursor_plane = vop2->data->plane_table[i].plane_id; 5662ee008497SSandy Huang break; 5663ee008497SSandy Huang } 5664ee008497SSandy Huang } 5665ee008497SSandy Huang 5666ee008497SSandy Huang /* To check whether the new correct_cursor_plane is attach to current vp */ 5667ee008497SSandy Huang if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 5668ee008497SSandy Huang printf("error: faild to find correct plane as cursor plane\n"); 5669ee008497SSandy Huang return -1; 5670ee008497SSandy Huang } 5671ee008497SSandy Huang 5672ee008497SSandy Huang printf("vp%d adjust cursor plane from %d to %d\n", 5673ee008497SSandy Huang cstate->crtc_id, cursor_plane, correct_cursor_plane); 5674ee008497SSandy Huang 5675ee008497SSandy Huang return correct_cursor_plane; 5676ee008497SSandy Huang } 5677ee008497SSandy Huang 5678b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 5679b0989546SSandy Huang { 5680b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 5681b0989546SSandy Huang struct vop2 *vop2 = cstate->private; 5682b0989546SSandy Huang ofnode vp_node; 5683b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node; 5684b0989546SSandy Huang static bool vop_fix_dts; 5685b0989546SSandy Huang const char *path; 5686b0989546SSandy Huang u32 plane_mask = 0; 5687b0989546SSandy Huang int vp_id = 0; 5688ee008497SSandy Huang int cursor_plane_id = -1; 5689b0989546SSandy Huang 56905fa6e665SDamon Ding if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528) 5691b0989546SSandy Huang return 0; 5692b0989546SSandy Huang 5693b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 5694b0989546SSandy Huang path = vp_node.np->full_name; 5695b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 5696b0989546SSandy Huang 56978b1fe597SSandy Huang if (cstate->crtc->assign_plane) 56988b1fe597SSandy Huang continue; 5699ee008497SSandy Huang cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 5700ee008497SSandy Huang cstate->crtc->vps[vp_id].cursor_plane); 5701ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 5702b0989546SSandy Huang vp_id, plane_mask, 5703ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 5704ee008497SSandy Huang cursor_plane_id); 5705b0989546SSandy Huang 5706b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 5707b0989546SSandy Huang plane_mask, 1); 5708b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 5709b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 5710ee008497SSandy Huang if (cursor_plane_id >= 0) 5711ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id", 5712ee008497SSandy Huang cursor_plane_id, 1); 5713b0989546SSandy Huang vp_id++; 5714b0989546SSandy Huang } 5715b0989546SSandy Huang 5716b0989546SSandy Huang vop_fix_dts = true; 5717b0989546SSandy Huang 5718b0989546SSandy Huang return 0; 5719b0989546SSandy Huang } 5720b0989546SSandy Huang 5721820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state) 5722820a5c17SDamon Ding { 5723820a5c17SDamon Ding struct crtc_state *cstate = &state->crtc_state; 5724820a5c17SDamon Ding struct rockchip_crtc *crtc = cstate->crtc; 5725820a5c17SDamon Ding 5726820a5c17SDamon Ding if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) { 5727820a5c17SDamon Ding printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id); 5728820a5c17SDamon Ding return -ENOTSUPP; 5729820a5c17SDamon Ding } 5730820a5c17SDamon Ding 5731820a5c17SDamon Ding if (cstate->splice_mode) { 5732820a5c17SDamon Ding crtc->splice_mode = true; 5733820a5c17SDamon Ding crtc->splice_crtc_id = cstate->splice_crtc_id; 5734820a5c17SDamon Ding } 5735820a5c17SDamon Ding 5736820a5c17SDamon Ding return 0; 5737820a5c17SDamon Ding } 5738820a5c17SDamon Ding 573922007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state) 574022007755SDamon Ding { 574122007755SDamon Ding struct connector_state *conn_state = &state->conn_state; 574222007755SDamon Ding struct crtc_state *cstate = &state->crtc_state; 574322007755SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 574422007755SDamon Ding struct videomode vm; 574522007755SDamon Ding 574622007755SDamon Ding drm_display_mode_to_videomode(mode, &vm); 574722007755SDamon Ding 574822007755SDamon Ding if (vm.hactive < 32 || vm.vactive < 32 || 574922007755SDamon Ding (vm.hfront_porch * vm.hsync_len * vm.hback_porch * 575022007755SDamon Ding vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) { 575122007755SDamon Ding printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id); 575222007755SDamon Ding return -EINVAL; 575322007755SDamon Ding } 575422007755SDamon Ding 575522007755SDamon Ding return 0; 575622007755SDamon Ding } 575722007755SDamon Ding 5758b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state) 5759b02eb70bSDamon Ding { 5760b02eb70bSDamon Ding struct connector_state *conn_state = &state->conn_state; 57610e19fecdSDamon Ding struct rockchip_connector *conn = conn_state->connector; 5762b02eb70bSDamon Ding struct drm_display_mode *mode = &conn_state->mode; 5763b02eb70bSDamon Ding struct crtc_state *cstate = &state->crtc_state; 5764b02eb70bSDamon Ding struct vop2 *vop2 = cstate->private; 5765b02eb70bSDamon Ding 57660e19fecdSDamon Ding if (conn_state->secondary) { 57670e19fecdSDamon Ding if (!(conn->dual_channel_mode && 57680e19fecdSDamon Ding conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) && 57692b992d78SDamon Ding conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS) 57702b992d78SDamon Ding drm_mode_convert_to_split_mode(mode); 57710e19fecdSDamon Ding } 57722b992d78SDamon Ding 57731b5811e7SDamon Ding drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE); 5774b02eb70bSDamon Ding 5775243f0077SDamon Ding /* 5776640211a0SDamon Ding * For RK3568 and RK3588, the hactive of video timing must 5777640211a0SDamon Ding * be 4-pixel aligned. 5778640211a0SDamon Ding */ 5779640211a0SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) { 5780640211a0SDamon Ding if (mode->crtc_hdisplay % 4) { 5781640211a0SDamon Ding int old_hdisplay = mode->crtc_hdisplay; 5782640211a0SDamon Ding int align = 4 - (mode->crtc_hdisplay % 4); 5783640211a0SDamon Ding 5784640211a0SDamon Ding mode->crtc_hdisplay += align; 5785640211a0SDamon Ding mode->crtc_hsync_start += align; 5786640211a0SDamon Ding mode->crtc_hsync_end += align; 5787640211a0SDamon Ding mode->crtc_htotal += align; 5788640211a0SDamon Ding 5789640211a0SDamon Ding printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n", 5790640211a0SDamon Ding old_hdisplay, mode->hdisplay); 5791640211a0SDamon Ding } 5792640211a0SDamon Ding } 5793640211a0SDamon Ding 5794640211a0SDamon Ding /* 5795243f0077SDamon Ding * For RK3576 YUV420 output, hden signal introduce one cycle delay, 5796243f0077SDamon Ding * so we need to adjust hfp and hbp to compatible with this design. 5797243f0077SDamon Ding */ 5798243f0077SDamon Ding if (vop2->version == VOP_VERSION_RK3576 && 5799243f0077SDamon Ding conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 5800243f0077SDamon Ding mode->crtc_hsync_start += 2; 5801243f0077SDamon Ding mode->crtc_hsync_end += 2; 5802243f0077SDamon Ding } 5803243f0077SDamon Ding 5804b02eb70bSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656) 5805b02eb70bSDamon Ding mode->crtc_clock *= 2; 5806b02eb70bSDamon Ding 5807b02eb70bSDamon Ding /* 5808b02eb70bSDamon Ding * For RK3528, the path of CVBS output is like: 5809b02eb70bSDamon Ding * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC 5810b02eb70bSDamon Ding * The vop2 dclk should be four times crtc_clock for CVBS sampling 5811b02eb70bSDamon Ding * clock needs. 5812b02eb70bSDamon Ding */ 5813b02eb70bSDamon Ding if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656) 5814b02eb70bSDamon Ding mode->crtc_clock *= 4; 5815b02eb70bSDamon Ding 58164d64cedbSDamon Ding mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format); 58174d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total) 58184d64cedbSDamon Ding mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1; 58190675a2a4SDamon Ding 5820b02eb70bSDamon Ding return 0; 5821b02eb70bSDamon Ding } 5822b02eb70bSDamon Ding 58234c765862SDamon Ding #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) 58244c765862SDamon Ding 58254c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state) 58264c765862SDamon Ding { 58274c765862SDamon Ding struct crtc_state *cstate = &state->crtc_state; 58284c765862SDamon Ding struct vop2 *vop2 = cstate->private; 58294c765862SDamon Ding struct display_rect *src = &cstate->src_rect; 58304c765862SDamon Ding struct display_rect *dst = &cstate->crtc_rect; 58314c765862SDamon Ding struct vop2_win_data *win_data; 58324c765862SDamon Ding int min_scale, max_scale; 58334c765862SDamon Ding int hscale, vscale; 58344c765862SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 58354c765862SDamon Ding 58364c765862SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 58374c765862SDamon Ding if (!win_data) { 58384c765862SDamon Ding printf("ERROR: invalid win id %d\n", primary_plane_id); 58394c765862SDamon Ding return -ENODEV; 58404c765862SDamon Ding } 58414c765862SDamon Ding 58424c765862SDamon Ding min_scale = FRAC_16_16(1, win_data->max_downscale_factor); 58434c765862SDamon Ding max_scale = FRAC_16_16(win_data->max_upscale_factor, 1); 58444c765862SDamon Ding 58454c765862SDamon Ding hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale); 58464c765862SDamon Ding vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale); 58474c765862SDamon Ding if (hscale < 0 || vscale < 0) { 58484c765862SDamon Ding printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name); 58494c765862SDamon Ding return -ERANGE; 58504c765862SDamon Ding } 58514c765862SDamon Ding 58524c765862SDamon Ding return 0; 58534c765862SDamon Ding } 5854337d1c13SDamon Ding 58558e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state) 58568e7ef808SDamon Ding { 5857d8e7f4a5SSandy Huang __maybe_unused struct connector_state *conn_state = &state->conn_state; 58588e7ef808SDamon Ding struct crtc_state *cstate = &state->crtc_state; 58598e7ef808SDamon Ding struct vop2 *vop2 = cstate->private; 58608e7ef808SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 58618e7ef808SDamon Ding int val = 0; 58628e7ef808SDamon Ding int ret = 0; 58638e7ef808SDamon Ding 58648e7ef808SDamon Ding ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val, 58658e7ef808SDamon Ding (val >> EDPI_WMS_FS) & 0x1, 50 * 1000); 58668e7ef808SDamon Ding if (!ret) { 5867d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 58688e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 58698e7ef808SDamon Ding !val, 50 * 1000); 58708e7ef808SDamon Ding if (!ret) { 58718e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 58728e7ef808SDamon Ding val, 50 * 1000); 58738e7ef808SDamon Ding if (!ret) { 58748e7ef808SDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 58758e7ef808SDamon Ding EN_MASK, EDPI_WMS_FS, 1, false); 58768e7ef808SDamon Ding } else { 58778e7ef808SDamon Ding printf("ERROR: vp%d wait for active TE signal timeout\n", 58788e7ef808SDamon Ding cstate->crtc_id); 58798e7ef808SDamon Ding return ret; 58808e7ef808SDamon Ding } 58818e7ef808SDamon Ding } else { 58828e7ef808SDamon Ding printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id); 58838e7ef808SDamon Ding return ret; 58848e7ef808SDamon Ding } 5885d8e7f4a5SSandy Huang #endif 58868e7ef808SDamon Ding } else { 58878e7ef808SDamon Ding printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id); 58888e7ef808SDamon Ding return ret; 58898e7ef808SDamon Ding } 58908e7ef808SDamon Ding 58918e7ef808SDamon Ding return 0; 58928e7ef808SDamon Ding } 58938e7ef808SDamon Ding 589472388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state) 589572388c26SDamon Ding { 589672388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 589772388c26SDamon Ding struct vop2 *vop2 = cstate->private; 589872388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 589972388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 5900a552a69cSDamon Ding u32 len = 128; 590172388c26SDamon Ding u32 n, i, j; 590272388c26SDamon Ding u32 base; 590372388c26SDamon Ding 590472388c26SDamon Ding if (!cstate->crtc->active) 590572388c26SDamon Ding return -EINVAL; 590672388c26SDamon Ding 590772388c26SDamon Ding n = vop2_data->dump_regs_size; 590872388c26SDamon Ding for (i = 0; i < n; i++) { 590972388c26SDamon Ding base = regs[i].offset; 5910a552a69cSDamon Ding len = 128; 5911a552a69cSDamon Ding if (regs[i].size) 5912a552a69cSDamon Ding len = min(len, regs[i].size >> 2); 591372388c26SDamon Ding printf("\n%s:\n", regs[i].name); 5914a552a69cSDamon Ding for (j = 0; j < len;) { 591572388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 591672388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 591772388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 591872388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 591972388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 592072388c26SDamon Ding j += 4; 592172388c26SDamon Ding } 592272388c26SDamon Ding } 592372388c26SDamon Ding 592472388c26SDamon Ding return 0; 592572388c26SDamon Ding } 592672388c26SDamon Ding 592772388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state) 592872388c26SDamon Ding { 592972388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 593072388c26SDamon Ding struct vop2 *vop2 = cstate->private; 593172388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 593272388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 5933a552a69cSDamon Ding u32 len = 128; 593472388c26SDamon Ding u32 n, i, j; 593572388c26SDamon Ding u32 base; 593672388c26SDamon Ding bool enable_state; 593772388c26SDamon Ding 593872388c26SDamon Ding if (!cstate->crtc->active) 593972388c26SDamon Ding return -EINVAL; 594072388c26SDamon Ding 594172388c26SDamon Ding n = vop2_data->dump_regs_size; 594272388c26SDamon Ding for (i = 0; i < n; i++) { 594372388c26SDamon Ding if (regs[i].state_mask) { 594472388c26SDamon Ding enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) & 594572388c26SDamon Ding regs[i].state_mask; 594672388c26SDamon Ding if (enable_state != regs[i].enable_state) 594772388c26SDamon Ding continue; 594872388c26SDamon Ding } 594972388c26SDamon Ding 595072388c26SDamon Ding base = regs[i].offset; 5951a552a69cSDamon Ding len = 128; 5952a552a69cSDamon Ding if (regs[i].size) 5953a552a69cSDamon Ding len = min(len, regs[i].size >> 2); 595472388c26SDamon Ding printf("\n%s:\n", regs[i].name); 5955a552a69cSDamon Ding for (j = 0; j < len;) { 595672388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 595772388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 595872388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 595972388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 596072388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 596172388c26SDamon Ding j += 4; 596272388c26SDamon Ding } 596372388c26SDamon Ding } 596472388c26SDamon Ding 596572388c26SDamon Ding return 0; 596672388c26SDamon Ding } 596772388c26SDamon Ding 596872388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = { 596972388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 597072388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 597172388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 597272388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 597372388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 597472388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 597572388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 597672388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 597772388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 597872388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 597972388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 598072388c26SDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 598172388c26SDamon Ding { RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1}, 598272388c26SDamon Ding }; 598372388c26SDamon Ding 59845fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 59855fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, 59865fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART1, 59875fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, 59885fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART3, 59895fa6e665SDamon Ding }; 59905fa6e665SDamon Ding 59915fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 59925fa6e665SDamon Ding {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 59935fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 59945fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 59955fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 59965fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 59975fa6e665SDamon Ding }; 59985fa6e665SDamon Ding 59995fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 60005fa6e665SDamon Ding { /* one display policy for hdmi */ 60015fa6e665SDamon Ding {/* main display */ 6002ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 60035fa6e665SDamon Ding .attached_layers_nr = 4, 60045fa6e665SDamon Ding .attached_layers = { 60055fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 60065fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2 60075fa6e665SDamon Ding }, 60085fa6e665SDamon Ding }, 60095fa6e665SDamon Ding {/* second display */}, 60105fa6e665SDamon Ding {/* third display */}, 60115fa6e665SDamon Ding {/* fourth display */}, 60125fa6e665SDamon Ding }, 60135fa6e665SDamon Ding 60145fa6e665SDamon Ding { /* two display policy */ 60155fa6e665SDamon Ding {/* main display */ 6016ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 60175fa6e665SDamon Ding .attached_layers_nr = 3, 60185fa6e665SDamon Ding .attached_layers = { 60195fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 60205fa6e665SDamon Ding }, 60215fa6e665SDamon Ding }, 60225fa6e665SDamon Ding 60235fa6e665SDamon Ding {/* second display */ 60245fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 60255fa6e665SDamon Ding .attached_layers_nr = 2, 60265fa6e665SDamon Ding .attached_layers = { 60275fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 60285fa6e665SDamon Ding }, 60295fa6e665SDamon Ding }, 60305fa6e665SDamon Ding {/* third display */}, 60315fa6e665SDamon Ding {/* fourth display */}, 60325fa6e665SDamon Ding }, 60335fa6e665SDamon Ding 60345fa6e665SDamon Ding { /* one display policy for cvbs */ 60355fa6e665SDamon Ding {/* main display */ 60365fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 60375fa6e665SDamon Ding .attached_layers_nr = 2, 60385fa6e665SDamon Ding .attached_layers = { 60395fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 60405fa6e665SDamon Ding }, 60415fa6e665SDamon Ding }, 60425fa6e665SDamon Ding {/* second display */}, 60435fa6e665SDamon Ding {/* third display */}, 60445fa6e665SDamon Ding {/* fourth display */}, 60455fa6e665SDamon Ding }, 60465fa6e665SDamon Ding 60475fa6e665SDamon Ding {/* reserved */}, 60485fa6e665SDamon Ding }; 60495fa6e665SDamon Ding 60505fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = { 60515fa6e665SDamon Ding { 60525fa6e665SDamon Ding .name = "Esmart0", 60535fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 60545fa6e665SDamon Ding .type = ESMART_LAYER, 60555fa6e665SDamon Ding .win_sel_port_offset = 8, 60565fa6e665SDamon Ding .layer_sel_win_id = { 1, 0xff, 0xff, 0xff }, 60575fa6e665SDamon Ding .reg_offset = 0, 60585fa6e665SDamon Ding .axi_id = 0, 60595fa6e665SDamon Ding .axi_yrgb_id = 0x06, 60605fa6e665SDamon Ding .axi_uv_id = 0x07, 60615fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 60625fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 60635fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 60645fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 60655fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 60665fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 60675fa6e665SDamon Ding .max_upscale_factor = 8, 60685fa6e665SDamon Ding .max_downscale_factor = 8, 60695fa6e665SDamon Ding }, 60705fa6e665SDamon Ding 60715fa6e665SDamon Ding { 60725fa6e665SDamon Ding .name = "Esmart1", 60735fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 60745fa6e665SDamon Ding .type = ESMART_LAYER, 60755fa6e665SDamon Ding .win_sel_port_offset = 10, 60765fa6e665SDamon Ding .layer_sel_win_id = { 2, 0xff, 0xff, 0xff }, 60775fa6e665SDamon Ding .reg_offset = 0x200, 60785fa6e665SDamon Ding .axi_id = 0, 60795fa6e665SDamon Ding .axi_yrgb_id = 0x08, 60805fa6e665SDamon Ding .axi_uv_id = 0x09, 60815fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 60825fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 60835fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 60845fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 60855fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 60865fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 60875fa6e665SDamon Ding .max_upscale_factor = 8, 60885fa6e665SDamon Ding .max_downscale_factor = 8, 60895fa6e665SDamon Ding }, 60905fa6e665SDamon Ding 60915fa6e665SDamon Ding { 60925fa6e665SDamon Ding .name = "Esmart2", 60935fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 60945fa6e665SDamon Ding .type = ESMART_LAYER, 60955fa6e665SDamon Ding .win_sel_port_offset = 12, 60965fa6e665SDamon Ding .layer_sel_win_id = { 3, 0, 0xff, 0xff }, 60975fa6e665SDamon Ding .reg_offset = 0x400, 60985fa6e665SDamon Ding .axi_id = 0, 60995fa6e665SDamon Ding .axi_yrgb_id = 0x0a, 61005fa6e665SDamon Ding .axi_uv_id = 0x0b, 61015fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 61025fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 61035fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 61045fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 61055fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 61065fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 61075fa6e665SDamon Ding .max_upscale_factor = 8, 61085fa6e665SDamon Ding .max_downscale_factor = 8, 61095fa6e665SDamon Ding }, 61105fa6e665SDamon Ding 61115fa6e665SDamon Ding { 61125fa6e665SDamon Ding .name = "Esmart3", 61135fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 61145fa6e665SDamon Ding .type = ESMART_LAYER, 61155fa6e665SDamon Ding .win_sel_port_offset = 14, 61165fa6e665SDamon Ding .layer_sel_win_id = { 0xff, 1, 0xff, 0xff }, 61175fa6e665SDamon Ding .reg_offset = 0x600, 61185fa6e665SDamon Ding .axi_id = 0, 61195fa6e665SDamon Ding .axi_yrgb_id = 0x0c, 61205fa6e665SDamon Ding .axi_uv_id = 0x0d, 61215fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 61225fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 61235fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 61245fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 61255fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 61265fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 61275fa6e665SDamon Ding .max_upscale_factor = 8, 61285fa6e665SDamon Ding .max_downscale_factor = 8, 61295fa6e665SDamon Ding }, 61305fa6e665SDamon Ding 61315fa6e665SDamon Ding { 61325fa6e665SDamon Ding .name = "Cluster0", 61335fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0, 61345fa6e665SDamon Ding .type = CLUSTER_LAYER, 61355fa6e665SDamon Ding .win_sel_port_offset = 0, 61365fa6e665SDamon Ding .layer_sel_win_id = { 0, 0xff, 0xff, 0xff }, 61375fa6e665SDamon Ding .reg_offset = 0, 61385fa6e665SDamon Ding .axi_id = 0, 61395fa6e665SDamon Ding .axi_yrgb_id = 0x02, 61405fa6e665SDamon Ding .axi_uv_id = 0x03, 61415fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 61425fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 61435fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 61445fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 61455fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 61465fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 61475fa6e665SDamon Ding .max_upscale_factor = 8, 61485fa6e665SDamon Ding .max_downscale_factor = 8, 61495fa6e665SDamon Ding }, 61505fa6e665SDamon Ding }; 61515fa6e665SDamon Ding 61525fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = { 61535fa6e665SDamon Ding { 61546027c871SZhang Yubing .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM | 61556027c871SZhang Yubing VOP_FEATURE_POST_CSC, 61565fa6e665SDamon Ding .max_output = {4096, 4096}, 6157b05105abSDamon Ding .layer_mix_dly = 6, 6158b05105abSDamon Ding .hdr_mix_dly = 2, 6159b05105abSDamon Ding .win_dly = 8, 61605fa6e665SDamon Ding }, 61615fa6e665SDamon Ding { 61625fa6e665SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 61635fa6e665SDamon Ding .max_output = {1920, 1080}, 6164b05105abSDamon Ding .layer_mix_dly = 2, 6165b05105abSDamon Ding .hdr_mix_dly = 0, 6166b05105abSDamon Ding .win_dly = 8, 61675fa6e665SDamon Ding }, 61685fa6e665SDamon Ding }; 61695fa6e665SDamon Ding 61705fa6e665SDamon Ding const struct vop2_data rk3528_vop = { 61715fa6e665SDamon Ding .version = VOP_VERSION_RK3528, 61725fa6e665SDamon Ding .nr_vps = 2, 61735fa6e665SDamon Ding .vp_data = rk3528_vp_data, 61745fa6e665SDamon Ding .win_data = rk3528_win_data, 61755fa6e665SDamon Ding .plane_mask = rk3528_vp_plane_mask[0], 61765fa6e665SDamon Ding .plane_table = rk3528_plane_table, 61775fa6e665SDamon Ding .vp_primary_plane_order = rk3528_vp_primary_plane_order, 61785fa6e665SDamon Ding .nr_layers = 5, 61795fa6e665SDamon Ding .nr_mixers = 3, 61805fa6e665SDamon Ding .nr_gammas = 2, 61815fa6e665SDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE, 618272388c26SDamon Ding .dump_regs = rk3528_dump_regs, 618372388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3528_dump_regs), 618472388c26SDamon Ding }; 618572388c26SDamon Ding 618672388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = { 618772388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 618872388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 618972388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 619072388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 619172388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 619272388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 619372388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 619472388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 619572388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 619672388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 61975fa6e665SDamon Ding }; 61985fa6e665SDamon Ding 6199452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 6200452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, 6201452afb13SDamon Ding ROCKCHIP_VOP2_ESMART1, 6202452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, 6203452afb13SDamon Ding ROCKCHIP_VOP2_ESMART3, 6204452afb13SDamon Ding }; 6205452afb13SDamon Ding 6206452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 6207452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 6208452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 6209452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 6210452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 6211452afb13SDamon Ding }; 6212452afb13SDamon Ding 6213452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 6214452afb13SDamon Ding { /* one display policy for hdmi */ 6215452afb13SDamon Ding {/* main display */ 6216452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6217452afb13SDamon Ding .attached_layers_nr = 4, 6218452afb13SDamon Ding .attached_layers = { 6219452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, 6220452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 6221452afb13SDamon Ding }, 6222452afb13SDamon Ding }, 6223452afb13SDamon Ding {/* second display */}, 6224452afb13SDamon Ding {/* third display */}, 6225452afb13SDamon Ding {/* fourth display */}, 6226452afb13SDamon Ding }, 6227452afb13SDamon Ding 6228452afb13SDamon Ding { /* two display policy */ 6229452afb13SDamon Ding {/* main display */ 6230452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6231452afb13SDamon Ding .attached_layers_nr = 2, 6232452afb13SDamon Ding .attached_layers = { 6233452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 6234452afb13SDamon Ding }, 6235452afb13SDamon Ding }, 6236452afb13SDamon Ding 6237452afb13SDamon Ding {/* second display */ 6238452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 6239452afb13SDamon Ding .attached_layers_nr = 2, 6240452afb13SDamon Ding .attached_layers = { 6241452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 6242452afb13SDamon Ding }, 6243452afb13SDamon Ding }, 6244452afb13SDamon Ding {/* third display */}, 6245452afb13SDamon Ding {/* fourth display */}, 6246452afb13SDamon Ding }, 6247452afb13SDamon Ding 6248452afb13SDamon Ding {/* reserved */}, 6249452afb13SDamon Ding }; 6250452afb13SDamon Ding 6251452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = { 6252452afb13SDamon Ding { 6253452afb13SDamon Ding .name = "Esmart0", 6254452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 6255452afb13SDamon Ding .type = ESMART_LAYER, 6256452afb13SDamon Ding .win_sel_port_offset = 8, 6257452afb13SDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 6258452afb13SDamon Ding .reg_offset = 0, 6259452afb13SDamon Ding .axi_id = 0, 6260452afb13SDamon Ding .axi_yrgb_id = 0x02, 6261452afb13SDamon Ding .axi_uv_id = 0x03, 6262452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6263452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6264452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6265452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6266452afb13SDamon Ding .max_upscale_factor = 8, 6267452afb13SDamon Ding .max_downscale_factor = 8, 6268452afb13SDamon Ding }, 6269452afb13SDamon Ding 6270452afb13SDamon Ding { 6271452afb13SDamon Ding .name = "Esmart1", 6272452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 6273452afb13SDamon Ding .type = ESMART_LAYER, 6274452afb13SDamon Ding .win_sel_port_offset = 10, 6275452afb13SDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 6276452afb13SDamon Ding .reg_offset = 0x200, 6277452afb13SDamon Ding .axi_id = 0, 6278452afb13SDamon Ding .axi_yrgb_id = 0x04, 6279452afb13SDamon Ding .axi_uv_id = 0x05, 6280452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6281452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6282452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6283452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6284452afb13SDamon Ding .max_upscale_factor = 8, 6285452afb13SDamon Ding .max_downscale_factor = 8, 6286452afb13SDamon Ding }, 6287452afb13SDamon Ding 6288452afb13SDamon Ding { 6289452afb13SDamon Ding .name = "Esmart2", 6290452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 6291452afb13SDamon Ding .type = ESMART_LAYER, 6292452afb13SDamon Ding .win_sel_port_offset = 12, 6293452afb13SDamon Ding .layer_sel_win_id = { 2, 2, 0xff, 0xff }, 6294452afb13SDamon Ding .reg_offset = 0x400, 6295452afb13SDamon Ding .axi_id = 0, 6296452afb13SDamon Ding .axi_yrgb_id = 0x06, 6297452afb13SDamon Ding .axi_uv_id = 0x07, 6298452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6299452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6300452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6301452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6302452afb13SDamon Ding .max_upscale_factor = 8, 6303452afb13SDamon Ding .max_downscale_factor = 8, 6304452afb13SDamon Ding }, 6305452afb13SDamon Ding 6306452afb13SDamon Ding { 6307452afb13SDamon Ding .name = "Esmart3", 6308452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 6309452afb13SDamon Ding .type = ESMART_LAYER, 6310452afb13SDamon Ding .win_sel_port_offset = 14, 6311452afb13SDamon Ding .layer_sel_win_id = { 3, 3, 0xff, 0xff }, 6312452afb13SDamon Ding .reg_offset = 0x600, 6313452afb13SDamon Ding .axi_id = 0, 6314452afb13SDamon Ding .axi_yrgb_id = 0x08, 6315452afb13SDamon Ding .axi_uv_id = 0x0d, 6316452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6317452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6318452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6319452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6320452afb13SDamon Ding .max_upscale_factor = 8, 6321452afb13SDamon Ding .max_downscale_factor = 8, 6322452afb13SDamon Ding }, 6323452afb13SDamon Ding }; 6324452afb13SDamon Ding 6325452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = { 6326452afb13SDamon Ding { 6327452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6328452afb13SDamon Ding .max_output = {2048, 4096}, 6329452afb13SDamon Ding .win_dly = 8, 6330452afb13SDamon Ding .layer_mix_dly = 8, 6331452afb13SDamon Ding }, 6332452afb13SDamon Ding { 6333452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6334452afb13SDamon Ding .max_output = {2048, 1080}, 6335452afb13SDamon Ding .win_dly = 8, 6336452afb13SDamon Ding .layer_mix_dly = 8, 6337452afb13SDamon Ding }, 6338452afb13SDamon Ding }; 6339452afb13SDamon Ding 6340452afb13SDamon Ding const struct vop2_data rk3562_vop = { 6341452afb13SDamon Ding .version = VOP_VERSION_RK3562, 6342452afb13SDamon Ding .nr_vps = 2, 6343452afb13SDamon Ding .vp_data = rk3562_vp_data, 6344452afb13SDamon Ding .win_data = rk3562_win_data, 6345452afb13SDamon Ding .plane_mask = rk3562_vp_plane_mask[0], 6346452afb13SDamon Ding .plane_table = rk3562_plane_table, 6347452afb13SDamon Ding .vp_primary_plane_order = rk3562_vp_primary_plane_order, 6348452afb13SDamon Ding .nr_layers = 4, 6349452afb13SDamon Ding .nr_mixers = 3, 6350452afb13SDamon Ding .nr_gammas = 2, 6351452afb13SDamon Ding .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE, 635272388c26SDamon Ding .dump_regs = rk3562_dump_regs, 635372388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3562_dump_regs), 635472388c26SDamon Ding }; 635572388c26SDamon Ding 635672388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = { 635772388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 635872388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 635972388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 636072388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 636172388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 636272388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 636372388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 636472388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 636572388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 636672388c26SDamon Ding { RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 636772388c26SDamon Ding { RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 636872388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 6369452afb13SDamon Ding }; 6370452afb13SDamon Ding 6371337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 6372337d1c13SDamon Ding ROCKCHIP_VOP2_SMART0, 6373337d1c13SDamon Ding ROCKCHIP_VOP2_SMART1, 6374337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 6375337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 6376337d1c13SDamon Ding }; 6377337d1c13SDamon Ding 6378ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 6379ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 6380ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 6381ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 6382ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 6383ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 6384ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 6385ee008497SSandy Huang }; 6386ee008497SSandy Huang 6387b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 6388b0989546SSandy Huang { /* one display policy */ 6389b0989546SSandy Huang {/* main display */ 6390b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6391b0989546SSandy Huang .attached_layers_nr = 6, 6392b0989546SSandy Huang .attached_layers = { 6393b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 6394b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 6395b0989546SSandy Huang }, 6396b0989546SSandy Huang }, 6397b0989546SSandy Huang {/* second display */}, 6398b0989546SSandy Huang {/* third display */}, 6399b0989546SSandy Huang {/* fourth display */}, 6400b0989546SSandy Huang }, 6401b0989546SSandy Huang 6402b0989546SSandy Huang { /* two display policy */ 6403b0989546SSandy Huang {/* main display */ 6404b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6405b0989546SSandy Huang .attached_layers_nr = 3, 6406b0989546SSandy Huang .attached_layers = { 6407b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 6408b0989546SSandy Huang }, 6409b0989546SSandy Huang }, 6410b0989546SSandy Huang 6411b0989546SSandy Huang {/* second display */ 6412b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 6413b0989546SSandy Huang .attached_layers_nr = 3, 6414b0989546SSandy Huang .attached_layers = { 6415b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 6416b0989546SSandy Huang }, 6417b0989546SSandy Huang }, 6418b0989546SSandy Huang {/* third display */}, 6419b0989546SSandy Huang {/* fourth display */}, 6420b0989546SSandy Huang }, 6421b0989546SSandy Huang 6422b0989546SSandy Huang { /* three display policy */ 6423b0989546SSandy Huang {/* main display */ 6424b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6425b0989546SSandy Huang .attached_layers_nr = 3, 6426b0989546SSandy Huang .attached_layers = { 6427b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 6428b0989546SSandy Huang }, 6429b0989546SSandy Huang }, 6430b0989546SSandy Huang 6431b0989546SSandy Huang {/* second display */ 6432b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 6433b0989546SSandy Huang .attached_layers_nr = 2, 6434b0989546SSandy Huang .attached_layers = { 6435b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 6436b0989546SSandy Huang }, 6437b0989546SSandy Huang }, 6438b0989546SSandy Huang 6439b0989546SSandy Huang {/* third display */ 6440b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 6441b0989546SSandy Huang .attached_layers_nr = 1, 6442b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 6443b0989546SSandy Huang }, 6444b0989546SSandy Huang 6445b0989546SSandy Huang {/* fourth display */}, 6446b0989546SSandy Huang }, 6447b0989546SSandy Huang 6448b0989546SSandy Huang {/* reserved for four display policy */}, 6449b0989546SSandy Huang }; 6450b0989546SSandy Huang 6451b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = { 6452b0989546SSandy Huang { 6453b0989546SSandy Huang .name = "Cluster0", 6454b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0, 6455ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 6456b0989546SSandy Huang .win_sel_port_offset = 0, 64575fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0xff }, 6458b0989546SSandy Huang .reg_offset = 0, 64595fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 64605fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 64615fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 64625fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 64634c765862SDamon Ding .max_upscale_factor = 4, 64644c765862SDamon Ding .max_downscale_factor = 4, 6465b0989546SSandy Huang }, 6466b0989546SSandy Huang 6467b0989546SSandy Huang { 6468b0989546SSandy Huang .name = "Cluster1", 6469b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1, 6470ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 6471b0989546SSandy Huang .win_sel_port_offset = 1, 64725fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 0xff }, 6473b0989546SSandy Huang .reg_offset = 0x200, 64745fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 64755fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 64765fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 64775fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 64784c765862SDamon Ding .max_upscale_factor = 4, 64794c765862SDamon Ding .max_downscale_factor = 4, 64801c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_CLUSTER0, 64811c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 6482b0989546SSandy Huang }, 6483b0989546SSandy Huang 6484b0989546SSandy Huang { 6485b0989546SSandy Huang .name = "Esmart0", 6486b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0, 6487ecc31b6eSAndy Yan .type = ESMART_LAYER, 6488b0989546SSandy Huang .win_sel_port_offset = 4, 64895fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 0xff }, 6490b0989546SSandy Huang .reg_offset = 0, 64915fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 64925fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 64935fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 64945fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 64954c765862SDamon Ding .max_upscale_factor = 8, 64964c765862SDamon Ding .max_downscale_factor = 8, 6497b0989546SSandy Huang }, 6498b0989546SSandy Huang 6499b0989546SSandy Huang { 6500b0989546SSandy Huang .name = "Esmart1", 6501b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1, 6502ecc31b6eSAndy Yan .type = ESMART_LAYER, 6503b0989546SSandy Huang .win_sel_port_offset = 5, 65045fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 0xff }, 6505b0989546SSandy Huang .reg_offset = 0x200, 65065fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 65075fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 65085fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 65095fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 65104c765862SDamon Ding .max_upscale_factor = 8, 65114c765862SDamon Ding .max_downscale_factor = 8, 65121c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_ESMART0, 65131c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 6514b0989546SSandy Huang }, 6515b0989546SSandy Huang 6516b0989546SSandy Huang { 6517b0989546SSandy Huang .name = "Smart0", 6518b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0, 6519ecc31b6eSAndy Yan .type = SMART_LAYER, 6520b0989546SSandy Huang .win_sel_port_offset = 6, 65215fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 0xff }, 6522b0989546SSandy Huang .reg_offset = 0x400, 65235fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 65245fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 65255fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 65265fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 65274c765862SDamon Ding .max_upscale_factor = 8, 65284c765862SDamon Ding .max_downscale_factor = 8, 6529b0989546SSandy Huang }, 6530b0989546SSandy Huang 6531b0989546SSandy Huang { 6532b0989546SSandy Huang .name = "Smart1", 6533b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1, 6534ecc31b6eSAndy Yan .type = SMART_LAYER, 6535b0989546SSandy Huang .win_sel_port_offset = 7, 65365fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 0xff }, 6537b0989546SSandy Huang .reg_offset = 0x600, 65385fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 65395fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 65405fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 65415fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 65424c765862SDamon Ding .max_upscale_factor = 8, 65434c765862SDamon Ding .max_downscale_factor = 8, 65441c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_SMART0, 65451c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 6546b0989546SSandy Huang }, 6547b0989546SSandy Huang }; 6548b0989546SSandy Huang 654963cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = { 655063cb669fSSandy Huang { 655163cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT, 655263cb669fSSandy Huang .pre_scan_max_dly = 42, 655363cb669fSSandy Huang .max_output = {4096, 2304}, 6554d0408543SAndy Yan }, 655563cb669fSSandy Huang { 655663cb669fSSandy Huang .feature = 0, 655763cb669fSSandy Huang .pre_scan_max_dly = 40, 655863cb669fSSandy Huang .max_output = {2048, 1536}, 655963cb669fSSandy Huang }, 656063cb669fSSandy Huang { 656163cb669fSSandy Huang .feature = 0, 656263cb669fSSandy Huang .pre_scan_max_dly = 40, 656363cb669fSSandy Huang .max_output = {1920, 1080}, 656463cb669fSSandy Huang }, 656563cb669fSSandy Huang }; 6566d0408543SAndy Yan 656763cb669fSSandy Huang const struct vop2_data rk3568_vop = { 6568ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568, 656963cb669fSSandy Huang .nr_vps = 3, 657063cb669fSSandy Huang .vp_data = rk3568_vp_data, 6571b0989546SSandy Huang .win_data = rk3568_win_data, 6572b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0], 6573ee008497SSandy Huang .plane_table = rk356x_plane_table, 6574337d1c13SDamon Ding .vp_primary_plane_order = rk3568_vp_primary_plane_order, 6575d0408543SAndy Yan .nr_layers = 6, 657663cb669fSSandy Huang .nr_mixers = 5, 65771147facaSSandy Huang .nr_gammas = 1, 657872388c26SDamon Ding .dump_regs = rk3568_dump_regs, 657972388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs), 6580d0408543SAndy Yan }; 6581d0408543SAndy Yan 6582a552a69cSDamon Ding static u8 rk3576_vp_default_primary_plane[VOP2_VP_MAX] = { 6583a552a69cSDamon Ding ROCKCHIP_VOP2_ESMART0, 6584a552a69cSDamon Ding ROCKCHIP_VOP2_ESMART1, 6585a552a69cSDamon Ding ROCKCHIP_VOP2_ESMART2, 6586a552a69cSDamon Ding }; 6587a552a69cSDamon Ding 6588a552a69cSDamon Ding static struct vop2_plane_table rk3576_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 6589a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 6590a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 6591a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 6592a552a69cSDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 6593a552a69cSDamon Ding {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 6594a552a69cSDamon Ding {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 6595a552a69cSDamon Ding }; 6596a552a69cSDamon Ding 6597a552a69cSDamon Ding static struct vop2_dump_regs rk3576_dump_regs[] = { 6598a552a69cSDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 }, 6599a552a69cSDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 }, 6600a552a69cSDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 }, 6601a552a69cSDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 }, 6602a552a69cSDamon Ding { RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 }, 6603a552a69cSDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 6604a552a69cSDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 6605a552a69cSDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 6606a552a69cSDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 }, 6607a552a69cSDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 }, 6608a552a69cSDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 }, 6609a552a69cSDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 }, 6610a552a69cSDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 }, 6611a552a69cSDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 }, 6612a552a69cSDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 }, 6613a552a69cSDamon Ding }; 6614a552a69cSDamon Ding 6615a552a69cSDamon Ding /* 6616a552a69cSDamon Ding * RK3576 VOP with 2 Cluster win and 4 Esmart win. 6617a552a69cSDamon Ding * Every Esmart win support 4 multi-region. 6618a552a69cSDamon Ding * VP0 can use Cluster0/1 and Esmart0/2 6619a552a69cSDamon Ding * VP1 can use Cluster0/1 and Esmart1/3 6620a552a69cSDamon Ding * VP2 can use Esmart0/1/2/3 6621a552a69cSDamon Ding * 6622a552a69cSDamon Ding * Scale filter mode: 6623a552a69cSDamon Ding * 6624a552a69cSDamon Ding * * Cluster: 6625a552a69cSDamon Ding * * Support prescale down: 6626a552a69cSDamon Ding * * H/V: gt2/avg2 or gt4/avg4 6627a552a69cSDamon Ding * * After prescale down: 6628a552a69cSDamon Ding * * nearest-neighbor/bilinear/multi-phase filter for scale up 6629a552a69cSDamon Ding * * nearest-neighbor/bilinear/multi-phase filter for scale down 6630a552a69cSDamon Ding * 6631a552a69cSDamon Ding * * Esmart: 6632a552a69cSDamon Ding * * Support prescale down: 6633a552a69cSDamon Ding * * H: gt2/avg2 or gt4/avg4 6634a552a69cSDamon Ding * * V: gt2 or gt4 6635a552a69cSDamon Ding * * After prescale down: 6636a552a69cSDamon Ding * * nearest-neighbor/bilinear/bicubic for scale up 6637a552a69cSDamon Ding * * nearest-neighbor/bilinear for scale down 6638cc517d73SDamon Ding * 6639cc517d73SDamon Ding * AXI config:: 6640cc517d73SDamon Ding * 6641cc517d73SDamon Ding * * Cluster0 win0: 0xa, 0xb [AXI0] 6642cc517d73SDamon Ding * * Cluster0 win1: 0xc, 0xd [AXI0] 6643cc517d73SDamon Ding * * Cluster1 win0: 0x6, 0x7 [AXI0] 6644cc517d73SDamon Ding * * Cluster1 win1: 0x8, 0x9 [AXI0] 6645cc517d73SDamon Ding * * Esmart0: 0x10, 0x11 [AXI0] 6646cc517d73SDamon Ding * * Esmart1: 0x12, 0x13 [AXI0] 6647cc517d73SDamon Ding * * Esmart2: 0xa, 0xb [AXI1] 6648cc517d73SDamon Ding * * Esmart3: 0xc, 0xd [AXI1] 6649cc517d73SDamon Ding * * Lut dma rid: 0x1, 0x2, 0x3 [AXI0] 6650cc517d73SDamon Ding * * DCI dma rid: 0x4 [AXI0] 6651cc517d73SDamon Ding * * Metadata rid: 0x5 [AXI0] 6652cc517d73SDamon Ding * 6653cc517d73SDamon Ding * * Limit: 6654cc517d73SDamon Ding * * (1) 0x0 and 0xf can't be used; 6655cc517d73SDamon Ding * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf, 6656cc517d73SDamon Ding * * VOP will dead at the system bandwidth very terrible scene. 6657a552a69cSDamon Ding */ 6658a552a69cSDamon Ding static struct vop2_win_data rk3576_win_data[6] = { 6659a552a69cSDamon Ding { 6660a552a69cSDamon Ding .name = "Esmart0", 6661a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 6662a552a69cSDamon Ding .type = ESMART_LAYER, 6663a552a69cSDamon Ding .layer_sel_win_id = { 2, 0xff, 0, 0xff }, 6664a552a69cSDamon Ding .reg_offset = 0x0, 6665a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6666a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6667a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6668a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6669a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6670a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6671a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6672a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6673a552a69cSDamon Ding .axi_id = 0, 6674cc517d73SDamon Ding .axi_yrgb_id = 0x10, 6675cc517d73SDamon Ding .axi_uv_id = 0x11, 6676a552a69cSDamon Ding .possible_crtcs = 0x5,/* vp0 or vp2 */ 6677a552a69cSDamon Ding .max_upscale_factor = 8, 6678a552a69cSDamon Ding .max_downscale_factor = 8, 6679a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH, 6680a552a69cSDamon Ding }, 6681a552a69cSDamon Ding { 6682a552a69cSDamon Ding .name = "Esmart1", 6683a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 6684a552a69cSDamon Ding .type = ESMART_LAYER, 6685a552a69cSDamon Ding .layer_sel_win_id = { 0xff, 2, 1, 0xff }, 6686a552a69cSDamon Ding .reg_offset = 0x200, 6687a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6688a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6689a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6690a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6691a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6692a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6693a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6694a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6695a552a69cSDamon Ding .axi_id = 0, 6696cc517d73SDamon Ding .axi_yrgb_id = 0x12, 6697cc517d73SDamon Ding .axi_uv_id = 0x13, 6698a552a69cSDamon Ding .possible_crtcs = 0x6,/* vp1 or vp2 */ 6699a552a69cSDamon Ding .max_upscale_factor = 8, 6700a552a69cSDamon Ding .max_downscale_factor = 8, 6701a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA, 6702a552a69cSDamon Ding }, 6703a552a69cSDamon Ding 6704a552a69cSDamon Ding { 6705a552a69cSDamon Ding .name = "Esmart2", 6706a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 6707a552a69cSDamon Ding .type = ESMART_LAYER, 6708a552a69cSDamon Ding .layer_sel_win_id = { 3, 0xff, 2, 0xff }, 6709a552a69cSDamon Ding .reg_offset = 0x400, 6710a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6711a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6712a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6713a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6714a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6715a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6716a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6717a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6718a552a69cSDamon Ding .axi_id = 1, 6719a552a69cSDamon Ding .axi_yrgb_id = 0x0a, 6720a552a69cSDamon Ding .axi_uv_id = 0x0b, 6721a552a69cSDamon Ding .possible_crtcs = 0x5,/* vp0 or vp2 */ 6722a552a69cSDamon Ding .max_upscale_factor = 8, 6723a552a69cSDamon Ding .max_downscale_factor = 8, 6724a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA, 6725a552a69cSDamon Ding }, 6726a552a69cSDamon Ding 6727a552a69cSDamon Ding { 6728a552a69cSDamon Ding .name = "Esmart3", 6729a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 6730a552a69cSDamon Ding .type = ESMART_LAYER, 6731a552a69cSDamon Ding .layer_sel_win_id = { 0xff, 3, 3, 0xff }, 6732a552a69cSDamon Ding .reg_offset = 0x600, 6733a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_Y, 6734a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6735a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6736a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6737a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6738a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6739a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 6740a552a69cSDamon Ding .pd_id = VOP2_PD_ESMART, 6741a552a69cSDamon Ding .axi_id = 1, 6742a552a69cSDamon Ding .axi_yrgb_id = 0x0c, 6743a552a69cSDamon Ding .axi_uv_id = 0x0d, 6744a552a69cSDamon Ding .possible_crtcs = 0x6,/* vp1 or vp2 */ 6745a552a69cSDamon Ding .max_upscale_factor = 8, 6746a552a69cSDamon Ding .max_downscale_factor = 8, 6747a552a69cSDamon Ding .feature = WIN_FEATURE_MULTI_AREA, 6748a552a69cSDamon Ding }, 6749a552a69cSDamon Ding 6750a552a69cSDamon Ding { 6751a552a69cSDamon Ding .name = "Cluster0", 6752a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0, 6753a552a69cSDamon Ding .type = CLUSTER_LAYER, 6754a552a69cSDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 6755a552a69cSDamon Ding .reg_offset = 0x0, 6756a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, 6757a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIL, 6758a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6759a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6760a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6761a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6762a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6763a552a69cSDamon Ding .pd_id = VOP2_PD_CLUSTER, 6764cc517d73SDamon Ding .axi_yrgb_id = 0x0a, 6765cc517d73SDamon Ding .axi_uv_id = 0x0b, 6766a552a69cSDamon Ding .possible_crtcs = 0x3,/* vp0 or vp1 */ 6767a552a69cSDamon Ding .max_upscale_factor = 8, 6768a552a69cSDamon Ding .max_downscale_factor = 8, 6769a552a69cSDamon Ding .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | 6770a552a69cSDamon Ding WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI, 6771a552a69cSDamon Ding }, 6772a552a69cSDamon Ding 6773a552a69cSDamon Ding { 6774a552a69cSDamon Ding .name = "Cluster1", 6775a552a69cSDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER1, 6776a552a69cSDamon Ding .type = CLUSTER_LAYER, 6777a552a69cSDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 6778a552a69cSDamon Ding .reg_offset = 0x200, 6779a552a69cSDamon Ding .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, 6780a552a69cSDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIL, 6781a552a69cSDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6782a552a69cSDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6783a552a69cSDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6784a552a69cSDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6785a552a69cSDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 6786a552a69cSDamon Ding .pd_id = VOP2_PD_CLUSTER, 6787a552a69cSDamon Ding .axi_yrgb_id = 0x06, 6788a552a69cSDamon Ding .axi_uv_id = 0x07, 6789a552a69cSDamon Ding .possible_crtcs = 0x3,/* vp0 or vp1 */ 6790a552a69cSDamon Ding .max_upscale_factor = 8, 6791a552a69cSDamon Ding .max_downscale_factor = 8, 6792a552a69cSDamon Ding .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | 6793a552a69cSDamon Ding WIN_FEATURE_Y2R_13BIT_DEPTH, 6794a552a69cSDamon Ding }, 6795a552a69cSDamon Ding }; 6796a552a69cSDamon Ding 679744b1b62cSDamon Ding /* 679844b1b62cSDamon Ding * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4, 679944b1b62cSDamon Ding * the urgency signal will be set to 1, when full post line buffer is over 6, the 680044b1b62cSDamon Ding * urgency signal will be set to 0. 680144b1b62cSDamon Ding */ 680244b1b62cSDamon Ding static struct vop_urgency rk3576_vp0_urgency = { 680344b1b62cSDamon Ding .urgen_thl = 4, 680444b1b62cSDamon Ding .urgen_thh = 6, 680544b1b62cSDamon Ding }; 680644b1b62cSDamon Ding 6807a552a69cSDamon Ding static struct vop2_vp_data rk3576_vp_data[3] = { 6808a552a69cSDamon Ding { 6809a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR | 6810a552a69cSDamon Ding VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT | 6811a552a69cSDamon Ding VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP, 6812a552a69cSDamon Ding .max_output = { 4096, 4096 }, 6813a552a69cSDamon Ding .hdrvivid_dly = 21, 6814a552a69cSDamon Ding .sdr2hdr_dly = 21, 6815a552a69cSDamon Ding .layer_mix_dly = 8, 6816a552a69cSDamon Ding .hdr_mix_dly = 2, 6817a552a69cSDamon Ding .win_dly = 10, 6818a552a69cSDamon Ding .pixel_rate = 2, 681944b1b62cSDamon Ding .urgency = &rk3576_vp0_urgency, 6820a552a69cSDamon Ding }, 6821a552a69cSDamon Ding { 6822a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | 6823a552a69cSDamon Ding VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2, 6824a552a69cSDamon Ding .max_output = { 2560, 2560 }, 6825a552a69cSDamon Ding .hdrvivid_dly = 0, 6826a552a69cSDamon Ding .sdr2hdr_dly = 0, 6827a552a69cSDamon Ding .layer_mix_dly = 6, 6828a552a69cSDamon Ding .hdr_mix_dly = 0, 6829a552a69cSDamon Ding .win_dly = 10, 6830a552a69cSDamon Ding .pixel_rate = 1, 6831a552a69cSDamon Ding }, 6832a552a69cSDamon Ding { 6833a552a69cSDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6834a552a69cSDamon Ding .max_output = { 1920, 1920 }, 6835a552a69cSDamon Ding .hdrvivid_dly = 0, 6836a552a69cSDamon Ding .sdr2hdr_dly = 0, 6837a552a69cSDamon Ding .layer_mix_dly = 6, 6838a552a69cSDamon Ding .hdr_mix_dly = 0, 6839a552a69cSDamon Ding .win_dly = 10, 6840a552a69cSDamon Ding .pixel_rate = 1, 6841a552a69cSDamon Ding }, 6842a552a69cSDamon Ding }; 6843a552a69cSDamon Ding 6844a552a69cSDamon Ding static struct vop2_power_domain_data rk3576_vop_pd_data[] = { 6845a552a69cSDamon Ding { 6846a552a69cSDamon Ding .id = VOP2_PD_CLUSTER, 6847a552a69cSDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1), 6848a552a69cSDamon Ding }, 6849a552a69cSDamon Ding { 6850a552a69cSDamon Ding .id = VOP2_PD_ESMART, 6851a552a69cSDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | 6852a552a69cSDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3), 6853a552a69cSDamon Ding }, 6854a552a69cSDamon Ding }; 6855a552a69cSDamon Ding 6856a552a69cSDamon Ding static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = { 6857a552a69cSDamon Ding {VOP3_ESMART_4K_4K_4K_MODE, 2}, 6858a552a69cSDamon Ding {VOP3_ESMART_4K_4K_2K_2K_MODE, 3} 6859a552a69cSDamon Ding }; 6860a552a69cSDamon Ding 6861a552a69cSDamon Ding const struct vop2_data rk3576_vop = { 6862a552a69cSDamon Ding .version = VOP_VERSION_RK3576, 6863a552a69cSDamon Ding .nr_vps = 3, 6864a552a69cSDamon Ding .nr_mixers = 4, 6865a552a69cSDamon Ding .nr_layers = 6, 6866a552a69cSDamon Ding .nr_gammas = 3, 6867a552a69cSDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE, 6868a552a69cSDamon Ding .esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map), 6869a552a69cSDamon Ding .esmart_lb_mode_map = rk3576_esmart_lb_mode_map, 6870a552a69cSDamon Ding .vp_data = rk3576_vp_data, 6871a552a69cSDamon Ding .win_data = rk3576_win_data, 6872a552a69cSDamon Ding .plane_table = rk3576_plane_table, 6873a552a69cSDamon Ding .pd = rk3576_vop_pd_data, 6874a552a69cSDamon Ding .vp_default_primary_plane = rk3576_vp_default_primary_plane, 6875a552a69cSDamon Ding .nr_pd = ARRAY_SIZE(rk3576_vop_pd_data), 6876a552a69cSDamon Ding .dump_regs = rk3576_dump_regs, 6877a552a69cSDamon Ding .dump_regs_size = ARRAY_SIZE(rk3576_dump_regs), 6878a552a69cSDamon Ding }; 6879a552a69cSDamon Ding 6880337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 6881337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 6882337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 6883337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART2, 6884337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART3, 6885337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 6886337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER1, 6887337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER2, 6888337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER3, 6889337d1c13SDamon Ding }; 6890337d1c13SDamon Ding 6891ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 6892ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 6893ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 6894ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 6895ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 6896ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 6897ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 6898ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 6899ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 6900ecc31b6eSAndy Yan }; 6901ecc31b6eSAndy Yan 690272388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = { 690372388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 690472388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 690572388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 690672388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 690772388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 690872388c26SDamon Ding { RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 }, 690972388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 691072388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 691172388c26SDamon Ding { RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 }, 691272388c26SDamon Ding { RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 }, 691372388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 691472388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 691572388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 691672388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 691772388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 691872388c26SDamon Ding }; 691972388c26SDamon Ding 6920ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 6921ecc31b6eSAndy Yan { /* one display policy */ 6922ecc31b6eSAndy Yan {/* main display */ 6923608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6924ecc31b6eSAndy Yan .attached_layers_nr = 8, 6925ecc31b6eSAndy Yan .attached_layers = { 6926ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, 6927ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, 6928ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 6929ecc31b6eSAndy Yan }, 6930ecc31b6eSAndy Yan }, 6931ecc31b6eSAndy Yan {/* second display */}, 6932ecc31b6eSAndy Yan {/* third display */}, 6933ecc31b6eSAndy Yan {/* fourth display */}, 6934ecc31b6eSAndy Yan }, 6935ecc31b6eSAndy Yan 6936ecc31b6eSAndy Yan { /* two display policy */ 6937ecc31b6eSAndy Yan {/* main display */ 6938608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6939ecc31b6eSAndy Yan .attached_layers_nr = 4, 6940ecc31b6eSAndy Yan .attached_layers = { 6941ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 6942ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 6943ecc31b6eSAndy Yan }, 6944ecc31b6eSAndy Yan }, 6945ecc31b6eSAndy Yan 6946ecc31b6eSAndy Yan {/* second display */ 6947608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 6948ecc31b6eSAndy Yan .attached_layers_nr = 4, 6949ecc31b6eSAndy Yan .attached_layers = { 6950ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, 6951ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 6952ecc31b6eSAndy Yan }, 6953ecc31b6eSAndy Yan }, 6954ecc31b6eSAndy Yan {/* third display */}, 6955ecc31b6eSAndy Yan {/* fourth display */}, 6956ecc31b6eSAndy Yan }, 6957ecc31b6eSAndy Yan 6958ecc31b6eSAndy Yan { /* three display policy */ 6959ecc31b6eSAndy Yan {/* main display */ 6960608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6961ecc31b6eSAndy Yan .attached_layers_nr = 3, 6962ecc31b6eSAndy Yan .attached_layers = { 6963ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 6964ecc31b6eSAndy Yan }, 6965ecc31b6eSAndy Yan }, 6966ecc31b6eSAndy Yan 6967ecc31b6eSAndy Yan {/* second display */ 6968608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 6969ecc31b6eSAndy Yan .attached_layers_nr = 3, 6970ecc31b6eSAndy Yan .attached_layers = { 6971ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 6972ecc31b6eSAndy Yan }, 6973ecc31b6eSAndy Yan }, 6974ecc31b6eSAndy Yan 6975ecc31b6eSAndy Yan {/* third display */ 6976ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 6977ecc31b6eSAndy Yan .attached_layers_nr = 2, 6978ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 6979ecc31b6eSAndy Yan }, 6980ecc31b6eSAndy Yan 6981ecc31b6eSAndy Yan {/* fourth display */}, 6982ecc31b6eSAndy Yan }, 6983ecc31b6eSAndy Yan 6984ecc31b6eSAndy Yan { /* four display policy */ 6985ecc31b6eSAndy Yan {/* main display */ 6986608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 6987ecc31b6eSAndy Yan .attached_layers_nr = 2, 6988ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 6989ecc31b6eSAndy Yan }, 6990ecc31b6eSAndy Yan 6991ecc31b6eSAndy Yan {/* second display */ 6992608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 6993ecc31b6eSAndy Yan .attached_layers_nr = 2, 6994ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 6995ecc31b6eSAndy Yan }, 6996ecc31b6eSAndy Yan 6997ecc31b6eSAndy Yan {/* third display */ 6998608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 6999ecc31b6eSAndy Yan .attached_layers_nr = 2, 7000ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 7001ecc31b6eSAndy Yan }, 7002ecc31b6eSAndy Yan 7003ecc31b6eSAndy Yan {/* fourth display */ 7004608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 7005ecc31b6eSAndy Yan .attached_layers_nr = 2, 7006ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 7007ecc31b6eSAndy Yan }, 7008ecc31b6eSAndy Yan }, 7009ecc31b6eSAndy Yan 7010ecc31b6eSAndy Yan }; 7011ecc31b6eSAndy Yan 7012ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = { 7013ecc31b6eSAndy Yan { 7014ecc31b6eSAndy Yan .name = "Cluster0", 7015ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0, 7016ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER1, 7017ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7018ecc31b6eSAndy Yan .win_sel_port_offset = 0, 70195fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0 }, 7020ecc31b6eSAndy Yan .reg_offset = 0, 7021a33b790fSDamon Ding .axi_id = 0, 7022a33b790fSDamon Ding .axi_yrgb_id = 2, 7023a33b790fSDamon Ding .axi_uv_id = 3, 7024b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER0, 70255fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 70265fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70275fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 70285fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70294c765862SDamon Ding .max_upscale_factor = 4, 70304c765862SDamon Ding .max_downscale_factor = 4, 7031ecc31b6eSAndy Yan }, 7032ecc31b6eSAndy Yan 7033ecc31b6eSAndy Yan { 7034ecc31b6eSAndy Yan .name = "Cluster1", 7035ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1, 7036ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7037ecc31b6eSAndy Yan .win_sel_port_offset = 1, 70385fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 1 }, 7039ecc31b6eSAndy Yan .reg_offset = 0x200, 7040a33b790fSDamon Ding .axi_id = 0, 7041a33b790fSDamon Ding .axi_yrgb_id = 6, 7042a33b790fSDamon Ding .axi_uv_id = 7, 7043b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER1, 70445fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 70455fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70465fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 70475fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70484c765862SDamon Ding .max_upscale_factor = 4, 70494c765862SDamon Ding .max_downscale_factor = 4, 7050ecc31b6eSAndy Yan }, 7051ecc31b6eSAndy Yan 7052ecc31b6eSAndy Yan { 7053ecc31b6eSAndy Yan .name = "Cluster2", 7054ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2, 7055ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER3, 7056ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7057ecc31b6eSAndy Yan .win_sel_port_offset = 2, 70585fa6e665SDamon Ding .layer_sel_win_id = { 4, 4, 4, 4 }, 7059ecc31b6eSAndy Yan .reg_offset = 0x400, 7060a33b790fSDamon Ding .axi_id = 1, 7061a33b790fSDamon Ding .axi_yrgb_id = 2, 7062a33b790fSDamon Ding .axi_uv_id = 3, 7063b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER2, 70645fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 70655fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70665fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 70675fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70684c765862SDamon Ding .max_upscale_factor = 4, 70694c765862SDamon Ding .max_downscale_factor = 4, 7070ecc31b6eSAndy Yan }, 7071ecc31b6eSAndy Yan 7072ecc31b6eSAndy Yan { 7073ecc31b6eSAndy Yan .name = "Cluster3", 7074ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3, 7075ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 7076ecc31b6eSAndy Yan .win_sel_port_offset = 3, 70775fa6e665SDamon Ding .layer_sel_win_id = { 5, 5, 5, 5 }, 7078ecc31b6eSAndy Yan .reg_offset = 0x600, 7079a33b790fSDamon Ding .axi_id = 1, 7080a33b790fSDamon Ding .axi_yrgb_id = 6, 7081a33b790fSDamon Ding .axi_uv_id = 7, 7082b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER3, 70835fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 70845fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70855fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 70865fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 70874c765862SDamon Ding .max_upscale_factor = 4, 70884c765862SDamon Ding .max_downscale_factor = 4, 7089ecc31b6eSAndy Yan }, 7090ecc31b6eSAndy Yan 7091ecc31b6eSAndy Yan { 7092ecc31b6eSAndy Yan .name = "Esmart0", 7093ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0, 7094ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART1, 7095ecc31b6eSAndy Yan .type = ESMART_LAYER, 7096ecc31b6eSAndy Yan .win_sel_port_offset = 4, 70975fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 2 }, 7098ecc31b6eSAndy Yan .reg_offset = 0, 7099a33b790fSDamon Ding .axi_id = 0, 7100a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 7101a33b790fSDamon Ding .axi_uv_id = 0x0b, 71025fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 71035fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71045fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 71055fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71064c765862SDamon Ding .max_upscale_factor = 8, 71074c765862SDamon Ding .max_downscale_factor = 8, 7108ecc31b6eSAndy Yan }, 7109ecc31b6eSAndy Yan 7110ecc31b6eSAndy Yan { 7111ecc31b6eSAndy Yan .name = "Esmart1", 7112ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1, 7113ecc31b6eSAndy Yan .type = ESMART_LAYER, 7114ecc31b6eSAndy Yan .win_sel_port_offset = 5, 71155fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 3 }, 7116ecc31b6eSAndy Yan .reg_offset = 0x200, 7117a33b790fSDamon Ding .axi_id = 0, 7118a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 7119a33b790fSDamon Ding .axi_uv_id = 0x0d, 7120b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 71215fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 71225fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71235fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 71245fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71254c765862SDamon Ding .max_upscale_factor = 8, 71264c765862SDamon Ding .max_downscale_factor = 8, 7127ecc31b6eSAndy Yan }, 7128ecc31b6eSAndy Yan 7129ecc31b6eSAndy Yan { 7130ecc31b6eSAndy Yan .name = "Esmart2", 7131ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2, 7132ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART3, 7133ecc31b6eSAndy Yan .type = ESMART_LAYER, 7134ecc31b6eSAndy Yan .win_sel_port_offset = 6, 71355fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 6 }, 7136ecc31b6eSAndy Yan .reg_offset = 0x400, 7137a33b790fSDamon Ding .axi_id = 1, 7138a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 7139a33b790fSDamon Ding .axi_uv_id = 0x0b, 7140b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 71415fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 71425fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71435fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 71445fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71454c765862SDamon Ding .max_upscale_factor = 8, 71464c765862SDamon Ding .max_downscale_factor = 8, 7147ecc31b6eSAndy Yan }, 7148ecc31b6eSAndy Yan 7149ecc31b6eSAndy Yan { 7150ecc31b6eSAndy Yan .name = "Esmart3", 7151ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3, 7152ecc31b6eSAndy Yan .type = ESMART_LAYER, 7153ecc31b6eSAndy Yan .win_sel_port_offset = 7, 71545fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 7 }, 7155ecc31b6eSAndy Yan .reg_offset = 0x600, 7156a33b790fSDamon Ding .axi_id = 1, 7157a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 7158a33b790fSDamon Ding .axi_uv_id = 0x0d, 7159b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 71605fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 71615fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71625fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 71635fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 71644c765862SDamon Ding .max_upscale_factor = 8, 71654c765862SDamon Ding .max_downscale_factor = 8, 7166ecc31b6eSAndy Yan }, 7167ecc31b6eSAndy Yan }; 7168ecc31b6eSAndy Yan 716912ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = { 717012ee5af0SDamon Ding {0x00000000, "no error detected by DSC encoder"}, 717112ee5af0SDamon Ding {0x0030ffff, "bits per component error"}, 717212ee5af0SDamon Ding {0x0040ffff, "multiple mode error"}, 717312ee5af0SDamon Ding {0x0050ffff, "line buffer depth error"}, 717412ee5af0SDamon Ding {0x0060ffff, "minor version error"}, 717512ee5af0SDamon Ding {0x0070ffff, "picture height error"}, 717612ee5af0SDamon Ding {0x0080ffff, "picture width error"}, 717712ee5af0SDamon Ding {0x0090ffff, "number of slices error"}, 717812ee5af0SDamon Ding {0x00c0ffff, "slice height Error "}, 717912ee5af0SDamon Ding {0x00d0ffff, "slice width error"}, 718012ee5af0SDamon Ding {0x00e0ffff, "second line BPG offset error"}, 718112ee5af0SDamon Ding {0x00f0ffff, "non second line BPG offset error"}, 718212ee5af0SDamon Ding {0x0100ffff, "PPS ID error"}, 718312ee5af0SDamon Ding {0x0110ffff, "bits per pixel (BPP) Error"}, 718412ee5af0SDamon Ding {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */ 718512ee5af0SDamon Ding 718612ee5af0SDamon Ding {0x01510001, "slice 0 RC buffer model overflow error"}, 718712ee5af0SDamon Ding {0x01510002, "slice 1 RC buffer model overflow error"}, 718812ee5af0SDamon Ding {0x01510004, "slice 2 RC buffer model overflow error"}, 718912ee5af0SDamon Ding {0x01510008, "slice 3 RC buffer model overflow error"}, 719012ee5af0SDamon Ding {0x01510010, "slice 4 RC buffer model overflow error"}, 719112ee5af0SDamon Ding {0x01510020, "slice 5 RC buffer model overflow error"}, 719212ee5af0SDamon Ding {0x01510040, "slice 6 RC buffer model overflow error"}, 719312ee5af0SDamon Ding {0x01510080, "slice 7 RC buffer model overflow error"}, 719412ee5af0SDamon Ding 719512ee5af0SDamon Ding {0x01610001, "slice 0 RC buffer model underflow error"}, 719612ee5af0SDamon Ding {0x01610002, "slice 1 RC buffer model underflow error"}, 719712ee5af0SDamon Ding {0x01610004, "slice 2 RC buffer model underflow error"}, 719812ee5af0SDamon Ding {0x01610008, "slice 3 RC buffer model underflow error"}, 719912ee5af0SDamon Ding {0x01610010, "slice 4 RC buffer model underflow error"}, 720012ee5af0SDamon Ding {0x01610020, "slice 5 RC buffer model underflow error"}, 720112ee5af0SDamon Ding {0x01610040, "slice 6 RC buffer model underflow error"}, 720212ee5af0SDamon Ding {0x01610080, "slice 7 RC buffer model underflow error"}, 720312ee5af0SDamon Ding 720412ee5af0SDamon Ding {0xffffffff, "unsuccessful RESET cycle status"}, 720512ee5af0SDamon Ding {0x00a0ffff, "ICH full error precision settings error"}, 720612ee5af0SDamon Ding {0x0020ffff, "native mode"}, 720712ee5af0SDamon Ding }; 720812ee5af0SDamon Ding 720912ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = { 721012ee5af0SDamon Ding {0x00000000, "rate buffer status"}, 721112ee5af0SDamon Ding {0x00000001, "line buffer status"}, 721212ee5af0SDamon Ding {0x00000002, "decoder model status"}, 721312ee5af0SDamon Ding {0x00000003, "pixel buffer status"}, 721412ee5af0SDamon Ding {0x00000004, "balance fifo buffer status"}, 721512ee5af0SDamon Ding {0x00000005, "syntax element fifo status"}, 721612ee5af0SDamon Ding }; 721712ee5af0SDamon Ding 721812ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = { 721912ee5af0SDamon Ding { 722012ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_8K, 722112ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_8K, 722212ee5af0SDamon Ding .max_slice_num = 8, 722312ee5af0SDamon Ding .max_linebuf_depth = 11, 7224b61227a3SDamon Ding .min_bits_per_pixel = 8, 722512ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src", 722612ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_8k_txp_clk", 722712ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_8k_pxl_clk", 722812ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_8k_cds_clk", 722912ee5af0SDamon Ding }, 723012ee5af0SDamon Ding 723112ee5af0SDamon Ding { 723212ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_4K, 723312ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_4K, 723412ee5af0SDamon Ding .max_slice_num = 2, 723512ee5af0SDamon Ding .max_linebuf_depth = 11, 7236b61227a3SDamon Ding .min_bits_per_pixel = 8, 723712ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src", 723812ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_4k_txp_clk", 723912ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_4k_pxl_clk", 724012ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_4k_cds_clk", 724112ee5af0SDamon Ding }, 724212ee5af0SDamon Ding }; 724312ee5af0SDamon Ding 7244ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = { 7245ecc31b6eSAndy Yan { 7246ee01dbb2SDamon Ding .splice_vp_id = 1, 7247ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 7248b890760eSAlgea Cao .pre_scan_max_dly = 54, 7249ecc31b6eSAndy Yan .max_dclk = 600000, 7250ecc31b6eSAndy Yan .max_output = {7680, 4320}, 7251ecc31b6eSAndy Yan }, 7252ecc31b6eSAndy Yan { 7253ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 7254ee01dbb2SDamon Ding .pre_scan_max_dly = 54, 7255ecc31b6eSAndy Yan .max_dclk = 600000, 7256ecc31b6eSAndy Yan .max_output = {4096, 2304}, 7257ecc31b6eSAndy Yan }, 7258ecc31b6eSAndy Yan { 7259ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 7260ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 7261ecc31b6eSAndy Yan .max_dclk = 600000, 7262ecc31b6eSAndy Yan .max_output = {4096, 2304}, 7263ecc31b6eSAndy Yan }, 7264ecc31b6eSAndy Yan { 7265ecc31b6eSAndy Yan .feature = 0, 7266ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 7267ecc31b6eSAndy Yan .max_dclk = 200000, 7268ecc31b6eSAndy Yan .max_output = {1920, 1080}, 7269ecc31b6eSAndy Yan }, 7270ecc31b6eSAndy Yan }; 7271ecc31b6eSAndy Yan 7272b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = { 7273b6ba80b4SDamon Ding { 7274b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER0, 7275b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0), 7276b6ba80b4SDamon Ding }, 7277b6ba80b4SDamon Ding { 7278b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER1, 7279b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1), 7280b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 7281b6ba80b4SDamon Ding }, 7282b6ba80b4SDamon Ding { 7283b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER2, 7284b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2), 7285b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 7286b6ba80b4SDamon Ding }, 7287b6ba80b4SDamon Ding { 7288b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER3, 7289b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3), 7290b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 7291b6ba80b4SDamon Ding }, 7292b6ba80b4SDamon Ding { 7293b6ba80b4SDamon Ding .id = VOP2_PD_ESMART, 7294b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) | 7295b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | 7296b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART3), 7297b6ba80b4SDamon Ding }, 7298b6ba80b4SDamon Ding { 7299b6ba80b4SDamon Ding .id = VOP2_PD_DSC_8K, 7300b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K), 7301b6ba80b4SDamon Ding }, 7302b6ba80b4SDamon Ding { 7303b6ba80b4SDamon Ding .id = VOP2_PD_DSC_4K, 7304b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K), 7305b6ba80b4SDamon Ding }, 7306b6ba80b4SDamon Ding }; 7307b6ba80b4SDamon Ding 7308ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = { 7309ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588, 7310ecc31b6eSAndy Yan .nr_vps = 4, 7311ecc31b6eSAndy Yan .vp_data = rk3588_vp_data, 7312ecc31b6eSAndy Yan .win_data = rk3588_win_data, 7313ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0], 7314ecc31b6eSAndy Yan .plane_table = rk3588_plane_table, 7315b6ba80b4SDamon Ding .pd = rk3588_vop_pd_data, 731612ee5af0SDamon Ding .dsc = rk3588_dsc_data, 731712ee5af0SDamon Ding .dsc_error_ecw = dsc_ecw, 731812ee5af0SDamon Ding .dsc_error_buffer_flow = dsc_buffer_flow, 7319337d1c13SDamon Ding .vp_primary_plane_order = rk3588_vp_primary_plane_order, 7320ecc31b6eSAndy Yan .nr_layers = 8, 7321ecc31b6eSAndy Yan .nr_mixers = 7, 7322ecc31b6eSAndy Yan .nr_gammas = 4, 7323b6ba80b4SDamon Ding .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data), 732412ee5af0SDamon Ding .nr_dscs = 2, 732512ee5af0SDamon Ding .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw), 732612ee5af0SDamon Ding .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow), 732772388c26SDamon Ding .dump_regs = rk3588_dump_regs, 732872388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs), 7329ecc31b6eSAndy Yan }; 7330ecc31b6eSAndy Yan 7331d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 7332d0408543SAndy Yan .preinit = rockchip_vop2_preinit, 7333d0408543SAndy Yan .prepare = rockchip_vop2_prepare, 7334d0408543SAndy Yan .init = rockchip_vop2_init, 7335d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane, 7336d0408543SAndy Yan .enable = rockchip_vop2_enable, 7337efa01fe4SZhang Yubing .post_enable = rockchip_vop2_post_enable, 7338d0408543SAndy Yan .disable = rockchip_vop2_disable, 7339b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts, 73400675a2a4SDamon Ding .send_mcu_cmd = rockchip_vop2_send_mcu_cmd, 7341820a5c17SDamon Ding .check = rockchip_vop2_check, 734222007755SDamon Ding .mode_valid = rockchip_vop2_mode_valid, 7343b02eb70bSDamon Ding .mode_fixup = rockchip_vop2_mode_fixup, 73444c765862SDamon Ding .plane_check = rockchip_vop2_plane_check, 734572388c26SDamon Ding .regs_dump = rockchip_vop2_regs_dump, 734672388c26SDamon Ding .active_regs_dump = rockchip_vop2_active_regs_dump, 73478e7ef808SDamon Ding .apply_soft_te = rockchip_vop2_apply_soft_te, 7348d0408543SAndy Yan }; 7349