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> 13feffd38eSSandy Huang #include <asm/arch/cpu.h> 14d0408543SAndy Yan #include <asm/unaligned.h> 15d0408543SAndy Yan #include <asm/io.h> 16d0408543SAndy Yan #include <linux/list.h> 17*ecc31b6eSAndy Yan #include <linux/log2.h> 18d0408543SAndy Yan #include <linux/media-bus-format.h> 19d0408543SAndy Yan #include <clk.h> 20d0408543SAndy Yan #include <asm/arch/clock.h> 21d0408543SAndy Yan #include <linux/err.h> 221147facaSSandy Huang #include <linux/ioport.h> 23d0408543SAndy Yan #include <dm/device.h> 24d0408543SAndy Yan #include <dm/read.h> 25ac500a1fSSandy Huang #include <fixp-arith.h> 26d0408543SAndy Yan #include <syscon.h> 27d0408543SAndy Yan 28d0408543SAndy Yan #include "rockchip_display.h" 29d0408543SAndy Yan #include "rockchip_crtc.h" 30d0408543SAndy Yan #include "rockchip_connector.h" 31d0408543SAndy Yan 32d0408543SAndy Yan /* System registers definition */ 33d0408543SAndy Yan #define RK3568_REG_CFG_DONE 0x000 34d0408543SAndy Yan #define CFG_DONE_EN BIT(15) 35d0408543SAndy Yan 36d0408543SAndy Yan #define RK3568_VERSION_INFO 0x004 37d0408543SAndy Yan #define EN_MASK 1 38d0408543SAndy Yan 3963cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL 0x008 4063cb669fSSandy Huang 416414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL 0x024 426414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT 0 436414e3bcSSandy Huang 44d0408543SAndy Yan #define RK3568_DSP_IF_EN 0x028 45d0408543SAndy Yan #define RGB_EN_SHIFT 0 46*ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT 0 47*ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT 1 48*ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT 8 49d0408543SAndy Yan #define HDMI0_EN_SHIFT 1 50d0408543SAndy Yan #define EDP0_EN_SHIFT 3 51*ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT 2 52*ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT 3 53d0408543SAndy Yan #define MIPI0_EN_SHIFT 4 54*ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT 4 55*ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT 5 56*ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT 6 57d0408543SAndy Yan #define MIPI1_EN_SHIFT 20 58*ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT 7 59d0408543SAndy Yan #define LVDS0_EN_SHIFT 5 60d0408543SAndy Yan #define LVDS1_EN_SHIFT 24 61d0408543SAndy Yan #define BT1120_EN_SHIFT 6 62d0408543SAndy Yan #define BT656_EN_SHIFT 7 63d0408543SAndy Yan #define IF_MUX_MASK 3 64d0408543SAndy Yan #define RGB_MUX_SHIFT 8 65d0408543SAndy Yan #define HDMI0_MUX_SHIFT 10 66*ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT 12 67*ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT 14 68d0408543SAndy Yan #define EDP0_MUX_SHIFT 14 69*ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT 16 70*ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT 18 71d0408543SAndy Yan #define MIPI0_MUX_SHIFT 16 72*ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT 20 73d0408543SAndy Yan #define MIPI1_MUX_SHIFT 21 7411f53190SSandy Huang #define LVDS0_MUX_SHIFT 18 75d0408543SAndy Yan #define LVDS1_MUX_SHIFT 25 76d0408543SAndy Yan 77d0408543SAndy Yan #define RK3568_DSP_IF_CTRL 0x02c 78d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT 0 79d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 80d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT 2 81d0408543SAndy Yan #define RK3568_DSP_IF_POL 0x030 82d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_MASK 1 83d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT 28 84d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 85d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT 15 86d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 8710ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 8810ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT 4 89*ecc31b6eSAndy Yan 90*ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT 8 91*ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT 12 92*ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK 0x7 93*ecc31b6eSAndy Yan 94d0408543SAndy Yan #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT 3 95*ecc31b6eSAndy Yan 96*ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT 16 97*ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 98*ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT 20 99*ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 100*ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT 24 101*ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT 26 102*ecc31b6eSAndy Yan 103feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN 0x50 104feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT 0 1051147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL 0x58 1061147facaSSandy Huang #define GAMMA_PORT_SEL_MASK 0x3 1071147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT 0 108*ecc31b6eSAndy Yan #define RK3568_MIPI_DUAL_EN_SHIFT 10 1091147facaSSandy Huang 110*ecc31b6eSAndy Yan #define RK3568_SYS_PD_CTRL 0x034 111d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG 0x70 112d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG 0x74 113d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG 0x78 114d0408543SAndy Yan #define RK3568_SYS0_INT_EN 0x80 115d0408543SAndy Yan #define RK3568_SYS0_INT_CLR 0x84 116d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS 0x88 117d0408543SAndy Yan #define RK3568_SYS1_INT_EN 0x90 118d0408543SAndy Yan #define RK3568_SYS1_INT_CLR 0x94 119d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS 0x98 120d0408543SAndy Yan #define RK3568_VP0_INT_EN 0xA0 121d0408543SAndy Yan #define RK3568_VP0_INT_CLR 0xA4 122d0408543SAndy Yan #define RK3568_VP0_INT_STATUS 0xA8 123d0408543SAndy Yan #define RK3568_VP1_INT_EN 0xB0 124d0408543SAndy Yan #define RK3568_VP1_INT_CLR 0xB4 125d0408543SAndy Yan #define RK3568_VP1_INT_STATUS 0xB8 126d0408543SAndy Yan #define RK3568_VP2_INT_EN 0xC0 127d0408543SAndy Yan #define RK3568_VP2_INT_CLR 0xC4 128d0408543SAndy Yan #define RK3568_VP2_INT_STATUS 0xC8 129d0408543SAndy Yan 13063cb669fSSandy Huang /* Overlay registers definition */ 13163cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600 13263cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 13363cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604 13463cb669fSSandy Huang #define LAYER_SEL_MASK 0xf 13563cb669fSSandy Huang 13663cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608 13763cb669fSSandy Huang #define PORT_MUX_MASK 0xf 13863cb669fSSandy Huang #define PORT_MUX_SHIFT 0 13963cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3 14063cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16 14163cb669fSSandy Huang 14263cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 14363cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 14463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 14563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 14663cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 14763cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654 14863cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 14963cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 15063cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 15163cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 15263cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 15363cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 15463cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0 15563cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff 15663cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24 15763cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4 15863cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8 15963cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0 16063cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8 16163cb669fSSandy Huang 162d0408543SAndy Yan /* Video Port registers definition */ 163d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00 164d0408543SAndy Yan #define OUT_MODE_MASK 0xf 165d0408543SAndy Yan #define OUT_MODE_SHIFT 0 16610ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f 16710ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8 16810ee9f5bSAlgea Cao #define DSP_RB_SWAP 2 16910ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4 170d0408543SAndy Yan #define P2I_EN_SHIFT 5 1717a20be36SSandy Huang #define DSP_FILED_POL 6 172d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7 17310ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15 174d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16 175d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17 1761147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28 1771147facaSSandy Huang 178d0408543SAndy Yan #define STANDBY_EN_SHIFT 31 179d0408543SAndy Yan 180d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04 18110ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4 18210ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3 183d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20 184d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21 185d0408543SAndy Yan 186d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 1876414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10 1886414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0 1896414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2 1906414e3bcSSandy Huang 191*ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C 192*ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0 193*ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2 194*ecc31b6eSAndy Yan 1956414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20 1966414e3bcSSandy Huang 197d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C 198d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 199d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 200d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 201d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 202d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40 203d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 204d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 205d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 206d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 207d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54 208d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 209d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 210d0408543SAndy Yan 211ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60 212ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0 213ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1 214ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 215ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 216ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4 217ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1 218ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 219ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 220ac500a1fSSandy Huang 221ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64 222ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0 223ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF 224ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8 225ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF 226ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20 227ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF 228ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30 229ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3 230ac500a1fSSandy Huang 231ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68 232ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0 233ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF 234ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16 235ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF 236ac500a1fSSandy Huang 237ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C 238ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31 239ac500a1fSSandy Huang #define BCSH_EN_MASK 1 240ac500a1fSSandy Huang 241d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00 242d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04 243d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 244d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 245d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 246d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 247d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 248d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40 249d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34 250d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38 251d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 252d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 253d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 254d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 255d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54 256d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 257d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 258d0408543SAndy Yan 259d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00 260d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04 261d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 262d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 263d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 264d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 265d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 266d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40 267d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34 268d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38 269d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 270d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 271d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 272d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 273d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54 274d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 275d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 276d0408543SAndy Yan 277d0408543SAndy Yan /* Cluster0 register definition */ 278d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 279*ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8 280*ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9 281*ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10 282*ecc31b6eSAndy Yan #define CLUSTER_YRGB_XSCL_MODE_SHIFT 12 283*ecc31b6eSAndy Yan #define CLUSTER_YRGB_YSCL_MODE_SHIFT 14 284d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 285*ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28 286*ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29 287d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 288d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 289d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018 290d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 291d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 292d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 293d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 294d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 295d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 296d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 297d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 298d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 299d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 300d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 301d0408543SAndy Yan 302d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 303d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 304d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 305d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 306d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098 307d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 308d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 309d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 310d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 311d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 312d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 313d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 314d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 315d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 316d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 317d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 318d0408543SAndy Yan 319d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100 320*ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0 321d0408543SAndy Yan 322d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 323d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 324d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 325d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 326d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218 327d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 328d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 329d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 330d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 331d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 332d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 333d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 334d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 335d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 336d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 337d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 338d0408543SAndy Yan 339d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 340d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 341d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 342d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 343d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298 344d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 345d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 346d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 347d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 348d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 349d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 350d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 351d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 352d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 353d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 354d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 355d0408543SAndy Yan 356d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300 357d0408543SAndy Yan 358d0408543SAndy Yan /* Esmart register definition */ 359d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800 36010ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1 36110ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2 36210ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3 363d0408543SAndy Yan 364d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804 365d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31 366d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810 36710ee9f5bSAlgea Cao #define REGION0_RB_SWAP_SHIFT 14 368d0408543SAndy Yan #define WIN_EN_SHIFT 0 369d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f 370d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1 371d0408543SAndy Yan 372d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 373d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 374d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C 375d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 376d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 377d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 378d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 3793e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3 3803e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0 3813e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3 3823e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2 3833e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3 3843e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4 3853e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3 3863e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6 3873e39a5a1SSandy Huang 388d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 389d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 390d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 391d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840 3923e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1 3933e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8 3943e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1 3953e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9 3963e39a5a1SSandy Huang 397d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 398d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 399d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C 400d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 401d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 402d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 403d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 404d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 405d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 406d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 407d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870 408d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 409d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 410d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C 411d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 412d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 413d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 414d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 415d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 416d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 417d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 418d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0 419d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 420d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 421d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC 422d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 423d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 424d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 425d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 426d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 427d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 428d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 429d0408543SAndy Yan 430d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00 431d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04 432d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10 433d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 434d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 435d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C 436d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 437d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 438d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 439d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 440d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 441d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 442d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 443d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40 444d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 445d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 446d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C 447d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 448d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 449d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 450d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 451d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 452d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 453d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 454d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70 455d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 456d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 457d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C 458d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 459d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 460d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 461d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 462d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 463d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 464d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 465d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 466d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 467d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 468d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC 469d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 470d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 471d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 472d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 473d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 474d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 475d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 476d0408543SAndy Yan 477d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00 478d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04 479d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10 480d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 481d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 482d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C 483d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 484d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 485d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 486d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 487d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 488d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 489d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 490d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40 491d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 492d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 493d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C 494d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 495d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 496d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 497d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 498d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 499d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 500d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 501d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70 502d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 503d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 504d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C 505d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 506d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 507d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 508d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 509d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 510d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 511d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 512d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0 513d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 514d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 515d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC 516d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 517d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 518d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 519d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 520d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 521d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 522d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 523d0408543SAndy Yan 524d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00 525d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04 526d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10 527d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 528d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 529d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C 530d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 531d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 532d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 533d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 534d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 535d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 536d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 537d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40 538d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 539d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 540d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C 541d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 542d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 543d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 544d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 545d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 546d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 547d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 548d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70 549d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 550d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 551d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C 552d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 553d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 554d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 555d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 556d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 557d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 558d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 559d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0 560d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 561d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 562d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC 563d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 564d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 565d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 566d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 567d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 568d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 569d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 570d0408543SAndy Yan 571d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0 572d0408543SAndy Yan 57352ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364 57452ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1 57552ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2 57652ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3 57752ee18acSSandy Huang 578*ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008 579*ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 580*ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 581*ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 582*ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 583*ecc31b6eSAndy Yan 584d0408543SAndy Yan #define VOP2_LAYER_MAX 8 58563cb669fSSandy Huang 58663cb669fSSandy Huang #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 587d0408543SAndy Yan 58810ee9f5bSAlgea Cao enum vop2_csc_format { 58910ee9f5bSAlgea Cao CSC_BT601L, 59010ee9f5bSAlgea Cao CSC_BT709L, 59110ee9f5bSAlgea Cao CSC_BT601F, 59210ee9f5bSAlgea Cao CSC_BT2020, 59310ee9f5bSAlgea Cao }; 59410ee9f5bSAlgea Cao 59510ee9f5bSAlgea Cao enum vop2_pol { 59610ee9f5bSAlgea Cao HSYNC_POSITIVE = 0, 59710ee9f5bSAlgea Cao VSYNC_POSITIVE = 1, 59810ee9f5bSAlgea Cao DEN_NEGATIVE = 2, 59910ee9f5bSAlgea Cao DCLK_INVERT = 3 60010ee9f5bSAlgea Cao }; 60110ee9f5bSAlgea Cao 602ac500a1fSSandy Huang enum vop2_bcsh_out_mode { 603ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK, 604ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE, 605ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR, 606ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, 607ac500a1fSSandy Huang }; 608ac500a1fSSandy Huang 609d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \ 610d0408543SAndy Yan { \ 611d0408543SAndy Yan .offset = off, \ 612d0408543SAndy Yan .mask = _mask, \ 613d0408543SAndy Yan .shift = _shift, \ 614d0408543SAndy Yan .write_mask = _write_mask, \ 615d0408543SAndy Yan } 616d0408543SAndy Yan 617d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \ 618d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false) 619d0408543SAndy Yan enum dither_down_mode { 620d0408543SAndy Yan RGB888_TO_RGB565 = 0x0, 621d0408543SAndy Yan RGB888_TO_RGB666 = 0x1 622d0408543SAndy Yan }; 623d0408543SAndy Yan 624d0408543SAndy Yan enum vop2_video_ports_id { 625d0408543SAndy Yan VOP2_VP0, 626d0408543SAndy Yan VOP2_VP1, 627d0408543SAndy Yan VOP2_VP2, 628d0408543SAndy Yan VOP2_VP3, 629d0408543SAndy Yan VOP2_VP_MAX, 630d0408543SAndy Yan }; 631d0408543SAndy Yan 632ee008497SSandy Huang enum vop2_layer_type { 633ee008497SSandy Huang CLUSTER_LAYER = 0, 634ee008497SSandy Huang ESMART_LAYER = 1, 635ee008497SSandy Huang SMART_LAYER = 2, 636ee008497SSandy Huang }; 637ee008497SSandy Huang 638b0989546SSandy Huang /* This define must same with kernel win phy id */ 639b0989546SSandy Huang enum vop2_layer_phy_id { 640b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0, 641b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, 642b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0, 643b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 644b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 645b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 646b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2, 647b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3, 648b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2, 649b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3, 650ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX, 651d0408543SAndy Yan }; 652d0408543SAndy Yan 6533e39a5a1SSandy Huang enum vop2_scale_up_mode { 6543e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR, 6553e39a5a1SSandy Huang VOP2_SCALE_UP_BIL, 6563e39a5a1SSandy Huang VOP2_SCALE_UP_BIC, 6573e39a5a1SSandy Huang }; 6583e39a5a1SSandy Huang 6593e39a5a1SSandy Huang enum vop2_scale_down_mode { 6603e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR, 6613e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL, 6623e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG, 6633e39a5a1SSandy Huang }; 6643e39a5a1SSandy Huang 6653e39a5a1SSandy Huang enum scale_mode { 6663e39a5a1SSandy Huang SCALE_NONE = 0x0, 6673e39a5a1SSandy Huang SCALE_UP = 0x1, 6683e39a5a1SSandy Huang SCALE_DOWN = 0x2 6693e39a5a1SSandy Huang }; 6703e39a5a1SSandy Huang 6713e39a5a1SSandy Huang struct vop2_layer { 6723e39a5a1SSandy Huang u8 id; 6733e39a5a1SSandy Huang /** 6743e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected. 6753e39a5a1SSandy Huang * Every layer must make sure to select different 6763e39a5a1SSandy Huang * windows of others. 6773e39a5a1SSandy Huang */ 6783e39a5a1SSandy Huang u8 win_phys_id; 6793e39a5a1SSandy Huang }; 6803e39a5a1SSandy Huang 681b0989546SSandy Huang struct vop2_win_data { 682b0989546SSandy Huang char *name; 68363cb669fSSandy Huang u8 phys_id; 684*ecc31b6eSAndy Yan enum vop2_layer_type type; 685b0989546SSandy Huang u8 win_sel_port_offset; 686b0989546SSandy Huang u8 layer_sel_win_id; 687b0989546SSandy Huang u32 reg_offset; 68863cb669fSSandy Huang }; 68963cb669fSSandy Huang 69063cb669fSSandy Huang struct vop2_vp_data { 69163cb669fSSandy Huang u32 feature; 69263cb669fSSandy Huang u8 pre_scan_max_dly; 69363cb669fSSandy Huang struct vop_rect max_output; 694*ecc31b6eSAndy Yan u32 max_dclk; 695d0408543SAndy Yan }; 696d0408543SAndy Yan 697ee008497SSandy Huang struct vop2_plane_table { 698ee008497SSandy Huang enum vop2_layer_phy_id plane_id; 699ee008497SSandy Huang enum vop2_layer_type plane_type; 700ee008497SSandy Huang }; 701ee008497SSandy Huang 702b0989546SSandy Huang struct vop2_vp_plane_mask { 703b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */ 704b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */ 705b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 706b0989546SSandy Huang u32 plane_mask; 707ee008497SSandy Huang int cursor_plane_id; 708b0989546SSandy Huang }; 709b0989546SSandy Huang 710d0408543SAndy Yan struct vop2_data { 71152ee18acSSandy Huang u32 version; 71263cb669fSSandy Huang struct vop2_vp_data *vp_data; 713b0989546SSandy Huang struct vop2_win_data *win_data; 714b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 715ee008497SSandy Huang struct vop2_plane_table *plane_table; 71663cb669fSSandy Huang u8 nr_vps; 71763cb669fSSandy Huang u8 nr_layers; 71863cb669fSSandy Huang u8 nr_mixers; 7191147facaSSandy Huang u8 nr_gammas; 720*ecc31b6eSAndy Yan u8 nr_dscs; 721*ecc31b6eSAndy Yan u32 reg_len; 722d0408543SAndy Yan }; 723d0408543SAndy Yan 724d0408543SAndy Yan struct vop2 { 725d0408543SAndy Yan u32 *regsbak; 726d0408543SAndy Yan void *regs; 727d0408543SAndy Yan void *grf; 728*ecc31b6eSAndy Yan void *vop_grf; 729*ecc31b6eSAndy Yan void *vo1_grf; 73052ee18acSSandy Huang u32 reg_len; 73152ee18acSSandy Huang u32 version; 73263cb669fSSandy Huang bool global_init; 733d0408543SAndy Yan const struct vop2_data *data; 734b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 735d0408543SAndy Yan }; 736d0408543SAndy Yan 737d0408543SAndy Yan static struct vop2 *rockchip_vop2; 7383e39a5a1SSandy Huang /* 7393e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12; 7403e39a5a1SSandy Huang * avg_sd_factor: 7413e39a5a1SSandy Huang * bli_su_factor: 7423e39a5a1SSandy Huang * bic_su_factor: 7433e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16; 7443e39a5a1SSandy Huang * 7453e39a5a1SSandy Huang * gt2 enable: dst get one line from two line of the src 7463e39a5a1SSandy Huang * gt4 enable: dst get one line from four line of the src. 7473e39a5a1SSandy Huang * 7483e39a5a1SSandy Huang */ 7493e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 7503e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 7513e39a5a1SSandy Huang 7523e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 7533e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1)) 7543e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 7553e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1)) 7563e39a5a1SSandy Huang 7573e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode, 7583e39a5a1SSandy Huang int32_t filter_mode, 7593e39a5a1SSandy Huang uint32_t src, uint32_t dst) 7603e39a5a1SSandy Huang { 7613e39a5a1SSandy Huang uint32_t fac = 0; 7623e39a5a1SSandy Huang int i = 0; 7633e39a5a1SSandy Huang 7643e39a5a1SSandy Huang if (mode == SCALE_NONE) 7653e39a5a1SSandy Huang return 0; 7663e39a5a1SSandy Huang 7673e39a5a1SSandy Huang /* 7683e39a5a1SSandy Huang * A workaround to avoid zero div. 7693e39a5a1SSandy Huang */ 7703e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) { 7713e39a5a1SSandy Huang dst = dst + 1; 7723e39a5a1SSandy Huang src = src + 1; 7733e39a5a1SSandy Huang } 7743e39a5a1SSandy Huang 7753e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 7763e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst); 7773e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 7783e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 7793e39a5a1SSandy Huang break; 7803e39a5a1SSandy Huang fac -= 1; 7813e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 7823e39a5a1SSandy Huang } 7833e39a5a1SSandy Huang } else { 7843e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst); 7853e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 7863e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 7873e39a5a1SSandy Huang break; 7883e39a5a1SSandy Huang fac -= 1; 7893e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 7903e39a5a1SSandy Huang } 7913e39a5a1SSandy Huang } 7923e39a5a1SSandy Huang 7933e39a5a1SSandy Huang return fac; 7943e39a5a1SSandy Huang } 7953e39a5a1SSandy Huang 7963e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst) 7973e39a5a1SSandy Huang { 7983e39a5a1SSandy Huang if (src < dst) 7993e39a5a1SSandy Huang return SCALE_UP; 8003e39a5a1SSandy Huang else if (src > dst) 8013e39a5a1SSandy Huang return SCALE_DOWN; 8023e39a5a1SSandy Huang 8033e39a5a1SSandy Huang return SCALE_NONE; 8043e39a5a1SSandy Huang } 805d0408543SAndy Yan 806*ecc31b6eSAndy Yan static u8 rk3588_vop2_vp_primary_plane_order[VOP2_VP_MAX] = { 807*ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART0, 808*ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART1, 809*ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART2, 810*ecc31b6eSAndy Yan ROCKCHIP_VOP2_ESMART3, 811*ecc31b6eSAndy Yan }; 812*ecc31b6eSAndy Yan 813*ecc31b6eSAndy Yan static u8 rk3568_vop2_vp_primary_plane_order[VOP2_VP_MAX] = { 814b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 815b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 816b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 817b0989546SSandy Huang }; 818b0989546SSandy Huang 819ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x) 820ac500a1fSSandy Huang { 821ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 822ac500a1fSSandy Huang } 823ac500a1fSSandy Huang 824b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 825b0989546SSandy Huang { 826b0989546SSandy Huang int i = 0; 827*ecc31b6eSAndy Yan u8 *vop2_vp_primary_plane_order; 828*ecc31b6eSAndy Yan u8 default_primary_plane; 829*ecc31b6eSAndy Yan 830*ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) { 831*ecc31b6eSAndy Yan vop2_vp_primary_plane_order = rk3588_vop2_vp_primary_plane_order; 832*ecc31b6eSAndy Yan default_primary_plane = ROCKCHIP_VOP2_ESMART0; 833*ecc31b6eSAndy Yan } else { 834*ecc31b6eSAndy Yan vop2_vp_primary_plane_order = rk3568_vop2_vp_primary_plane_order; 835*ecc31b6eSAndy Yan default_primary_plane = ROCKCHIP_VOP2_SMART0; 836*ecc31b6eSAndy Yan } 837b0989546SSandy Huang 838b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 839b0989546SSandy Huang if (plane_mask & BIT(vop2_vp_primary_plane_order[i])) 840b0989546SSandy Huang return vop2_vp_primary_plane_order[i]; 841b0989546SSandy Huang } 842b0989546SSandy Huang 843*ecc31b6eSAndy Yan return default_primary_plane; 844b0989546SSandy Huang } 845b0989546SSandy Huang 84663cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift) 847d0408543SAndy Yan { 848d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 849d0408543SAndy Yan } 850d0408543SAndy Yan 85163cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst) 852d0408543SAndy Yan { 853d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1); 854d0408543SAndy Yan } 855d0408543SAndy Yan 85652ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 857d0408543SAndy Yan { 858d0408543SAndy Yan writel(v, vop2->regs + offset); 859d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 860d0408543SAndy Yan } 861d0408543SAndy Yan 86252ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 863d0408543SAndy Yan { 864d0408543SAndy Yan return readl(vop2->regs + offset); 865d0408543SAndy Yan } 866d0408543SAndy Yan 86752ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 86852ee18acSSandy Huang u32 mask, u32 shift, u32 v, 869d0408543SAndy Yan bool write_mask) 870d0408543SAndy Yan { 871d0408543SAndy Yan if (!mask) 872d0408543SAndy Yan return; 873d0408543SAndy Yan 874d0408543SAndy Yan if (write_mask) { 875d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16)); 876d0408543SAndy Yan } else { 87752ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2]; 878d0408543SAndy Yan 879d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 880d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 881d0408543SAndy Yan } 882d0408543SAndy Yan 883d0408543SAndy Yan writel(v, vop2->regs + offset); 884d0408543SAndy Yan } 885d0408543SAndy Yan 886*ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 88752ee18acSSandy Huang u32 mask, u32 shift, u32 v) 88852ee18acSSandy Huang { 88952ee18acSSandy Huang u32 val = 0; 89052ee18acSSandy Huang 89152ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16)); 892*ecc31b6eSAndy Yan writel(val, grf_base + offset); 89352ee18acSSandy Huang } 89452ee18acSSandy Huang 895d0408543SAndy Yan static inline int us_to_vertical_line(struct drm_display_mode *mode, int us) 896d0408543SAndy Yan { 897d0408543SAndy Yan return us * mode->clock / mode->htotal / 1000; 898d0408543SAndy Yan } 899d0408543SAndy Yan 9008895aec1SSandy Huang static char* get_output_if_name(u32 output_if, char *name) 9018895aec1SSandy Huang { 9028895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_RGB) 9038895aec1SSandy Huang strcat(name, " RGB"); 9048895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT1120) 9058895aec1SSandy Huang strcat(name, " BT1120"); 9068895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT656) 9078895aec1SSandy Huang strcat(name, " BT656"); 9088895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS0) 9098895aec1SSandy Huang strcat(name, " LVDS0"); 9108895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS1) 9118895aec1SSandy Huang strcat(name, " LVDS1"); 9128895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI0) 9138895aec1SSandy Huang strcat(name, " MIPI0"); 9148895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI1) 9158895aec1SSandy Huang strcat(name, " MIPI1"); 9168895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP0) 9178895aec1SSandy Huang strcat(name, " eDP0"); 9188895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP1) 9198895aec1SSandy Huang strcat(name, " eDP1"); 9208895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP0) 9218895aec1SSandy Huang strcat(name, " DP0"); 9228895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP1) 9238895aec1SSandy Huang strcat(name, " DP1"); 9248895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI0) 9258895aec1SSandy Huang strcat(name, " HDMI0"); 9268895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI1) 9278895aec1SSandy Huang strcat(name, " HDMI1"); 9288895aec1SSandy Huang 9298895aec1SSandy Huang return name; 9308895aec1SSandy Huang } 9318895aec1SSandy Huang 9328895aec1SSandy Huang static char *get_plane_name(int plane_id, char *name) 9338895aec1SSandy Huang { 9348895aec1SSandy Huang switch (plane_id) { 9358895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER0: 9368895aec1SSandy Huang strcat(name, "Cluster0"); 9378895aec1SSandy Huang break; 9388895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER1: 9398895aec1SSandy Huang strcat(name, "Cluster1"); 9408895aec1SSandy Huang break; 9418895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART0: 9428895aec1SSandy Huang strcat(name, "Esmart0"); 9438895aec1SSandy Huang break; 9448895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART1: 9458895aec1SSandy Huang strcat(name, "Esmart1"); 9468895aec1SSandy Huang break; 9478895aec1SSandy Huang case ROCKCHIP_VOP2_SMART0: 9488895aec1SSandy Huang strcat(name, "Smart0"); 9498895aec1SSandy Huang break; 9508895aec1SSandy Huang case ROCKCHIP_VOP2_SMART1: 9518895aec1SSandy Huang strcat(name, "Smart1"); 9528895aec1SSandy Huang break; 9538895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER2: 9548895aec1SSandy Huang strcat(name, "Cluster2"); 9558895aec1SSandy Huang break; 9568895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER3: 9578895aec1SSandy Huang strcat(name, "Cluster3"); 9588895aec1SSandy Huang break; 9598895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART2: 9608895aec1SSandy Huang strcat(name, "Esmart2"); 9618895aec1SSandy Huang break; 9628895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART3: 9638895aec1SSandy Huang strcat(name, "Esmart3"); 9648895aec1SSandy Huang break; 9658895aec1SSandy Huang } 9668895aec1SSandy Huang 9678895aec1SSandy Huang return name; 9688895aec1SSandy Huang } 9698895aec1SSandy Huang 97052ee18acSSandy Huang static bool is_yuv_output(u32 bus_format) 971d0408543SAndy Yan { 972d0408543SAndy Yan switch (bus_format) { 973d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 974d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 975d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 976d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 977a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 978a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 979a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8: 980a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8: 981a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 982a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 983a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16: 984a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16: 985d0408543SAndy Yan return true; 986d0408543SAndy Yan default: 987d0408543SAndy Yan return false; 988d0408543SAndy Yan } 989d0408543SAndy Yan } 990d0408543SAndy Yan 99110ee9f5bSAlgea Cao static int vop2_convert_csc_mode(int csc_mode) 99210ee9f5bSAlgea Cao { 99310ee9f5bSAlgea Cao switch (csc_mode) { 99410ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE170M: 99510ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_M: 99610ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_BG: 99710ee9f5bSAlgea Cao return CSC_BT601L; 99810ee9f5bSAlgea Cao case V4L2_COLORSPACE_REC709: 99910ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE240M: 100010ee9f5bSAlgea Cao case V4L2_COLORSPACE_DEFAULT: 100110ee9f5bSAlgea Cao return CSC_BT709L; 100210ee9f5bSAlgea Cao case V4L2_COLORSPACE_JPEG: 100310ee9f5bSAlgea Cao return CSC_BT601F; 100410ee9f5bSAlgea Cao case V4L2_COLORSPACE_BT2020: 100510ee9f5bSAlgea Cao return CSC_BT2020; 100610ee9f5bSAlgea Cao default: 100710ee9f5bSAlgea Cao return CSC_BT709L; 100810ee9f5bSAlgea Cao } 100910ee9f5bSAlgea Cao } 101010ee9f5bSAlgea Cao 1011b0989546SSandy Huang static bool is_uv_swap(u32 bus_format, u32 output_mode) 1012d0408543SAndy Yan { 1013d0408543SAndy Yan /* 1014d0408543SAndy Yan * FIXME: 1015d0408543SAndy Yan * 1016d0408543SAndy Yan * There is no media type for YUV444 output, 1017d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on 1018d0408543SAndy Yan * yuv format. 1019d0408543SAndy Yan * 1020d0408543SAndy Yan * From H/W testing, YUV444 mode need a rb swap. 1021d0408543SAndy Yan */ 1022d0408543SAndy Yan if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1023d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1024d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA || 1025d0408543SAndy Yan output_mode == ROCKCHIP_OUT_MODE_P888)) 1026d0408543SAndy Yan return true; 1027d0408543SAndy Yan else 1028d0408543SAndy Yan return false; 1029d0408543SAndy Yan } 1030d0408543SAndy Yan 1031b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type) 103263cb669fSSandy Huang { 1033b0989546SSandy Huang switch (output_type) { 1034b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA: 1035b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB: 1036b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV: 1037b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort: 1038b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA: 1039b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown: 1040b0989546SSandy Huang return true; 1041b0989546SSandy Huang default: 1042b0989546SSandy Huang return false; 104363cb669fSSandy Huang } 104463cb669fSSandy Huang } 104563cb669fSSandy Huang 1046*ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1047*ecc31b6eSAndy Yan { 1048*ecc31b6eSAndy Yan int i = 0; 1049*ecc31b6eSAndy Yan 1050*ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) { 1051*ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id) 1052*ecc31b6eSAndy Yan return &vop2->data->win_data[i]; 1053*ecc31b6eSAndy Yan } 1054*ecc31b6eSAndy Yan 1055*ecc31b6eSAndy Yan return NULL; 1056*ecc31b6eSAndy Yan } 1057*ecc31b6eSAndy Yan 10581147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1059d0408543SAndy Yan struct display_state *state) 1060d0408543SAndy Yan { 10611147facaSSandy Huang struct connector_state *conn_state = &state->conn_state; 10621147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state; 10631147facaSSandy Huang struct resource gamma_res; 10641147facaSSandy Huang fdt_size_t lut_size; 10651147facaSSandy Huang int i, lut_len, ret = 0; 10661147facaSSandy Huang u32 *lut_regs; 10671147facaSSandy Huang u32 *lut_val; 10681147facaSSandy Huang u32 r, g, b; 10691147facaSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 10701147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 10711147facaSSandy Huang static int gamma_lut_en_num = 1; 10721147facaSSandy Huang 10731147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) { 10741147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 10751147facaSSandy Huang return 0; 10761147facaSSandy Huang } 10771147facaSSandy Huang 10781147facaSSandy Huang if (!disp_info) 10791147facaSSandy Huang return 0; 10801147facaSSandy Huang 10811147facaSSandy Huang if (!disp_info->gamma_lut_data.size) 10821147facaSSandy Huang return 0; 10831147facaSSandy Huang 10841147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 10851147facaSSandy Huang if (ret) 10861147facaSSandy Huang printf("failed to get gamma lut res\n"); 10871147facaSSandy Huang lut_regs = (u32 *)gamma_res.start; 10881147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1; 10891147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 10901147facaSSandy Huang printf("failed to get gamma lut register\n"); 10911147facaSSandy Huang return 0; 10921147facaSSandy Huang } 10931147facaSSandy Huang lut_len = lut_size / 4; 10941147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) { 10951147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 10961147facaSSandy Huang return 0; 10971147facaSSandy Huang } 10981147facaSSandy Huang lut_val = (u32 *)calloc(1, lut_size); 10991147facaSSandy Huang for (i = 0; i < lut_len; i++) { 11001147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 11011147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 11021147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 11031147facaSSandy Huang 11041147facaSSandy Huang lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 11051147facaSSandy Huang } 11061147facaSSandy Huang 11071147facaSSandy Huang for (i = 0; i < lut_len; i++) 11081147facaSSandy Huang writel(lut_val[i], lut_regs + i); 11091147facaSSandy Huang 11101147facaSSandy Huang vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 11111147facaSSandy Huang GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 11121147facaSSandy Huang cstate->crtc_id , false); 11131147facaSSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 11141147facaSSandy Huang EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 11151147facaSSandy Huang gamma_lut_en_num++; 11161147facaSSandy Huang 1117d0408543SAndy Yan return 0; 1118d0408543SAndy Yan } 1119d0408543SAndy Yan 11206414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 11216414e3bcSSandy Huang struct display_state *state) 11226414e3bcSSandy Huang { 11236414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state; 11246414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state; 11256414e3bcSSandy Huang int i, cubic_lut_len; 11266414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 11276414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 11286414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 11296414e3bcSSandy Huang u32 *cubic_lut_addr; 11306414e3bcSSandy Huang 11316414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 11326414e3bcSSandy Huang return 0; 11336414e3bcSSandy Huang 11346414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size) 11356414e3bcSSandy Huang return 0; 11366414e3bcSSandy Huang 11376414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 11386414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size; 11396414e3bcSSandy Huang 11406414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) { 11416414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 11426414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 11436414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 11446414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 11456414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) + 11466414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 11476414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28); 11486414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 11496414e3bcSSandy Huang *cubic_lut_addr++ = 0; 11506414e3bcSSandy Huang } 11516414e3bcSSandy Huang 11526414e3bcSSandy Huang if (cubic_lut_len % 2) { 11536414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 11546414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 11556414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 11566414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 11576414e3bcSSandy Huang *cubic_lut_addr++ = 0; 11586414e3bcSSandy Huang *cubic_lut_addr = 0; 11596414e3bcSSandy Huang } 11606414e3bcSSandy Huang 11616414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 11626414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id)); 11636414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 11646414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 11656414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 11666414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 11676414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 11686414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 11696414e3bcSSandy Huang 11706414e3bcSSandy Huang return 0; 11716414e3bcSSandy Huang } 11726414e3bcSSandy Huang 1173ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 1174ac500a1fSSandy Huang { 1175ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state; 1176ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info; 1177ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state; 1178ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue; 1179ac500a1fSSandy Huang bool bcsh_en = false, post_r2y_en = false, post_y2r_en = false; 1180ac500a1fSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 1181ac500a1fSSandy Huang int post_csc_mode; 1182ac500a1fSSandy Huang 1183ac500a1fSSandy Huang if (!conn_state->disp_info) 1184ac500a1fSSandy Huang return; 1185ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info; 1186ac500a1fSSandy Huang if (!bcsh_info) 1187ac500a1fSSandy Huang return; 1188ac500a1fSSandy Huang 1189ac500a1fSSandy Huang if (bcsh_info->brightness != 50 || 1190ac500a1fSSandy Huang bcsh_info->contrast != 50 || 1191ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50) 1192ac500a1fSSandy Huang bcsh_en = true; 1193ac500a1fSSandy Huang 1194ac500a1fSSandy Huang if (bcsh_en) { 1195ac500a1fSSandy Huang if (!cstate->yuv_overlay) 1196ac500a1fSSandy Huang post_r2y_en = 1; 1197ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format)) 1198ac500a1fSSandy Huang post_y2r_en = 1; 1199ac500a1fSSandy Huang } else { 1200ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 1201ac500a1fSSandy Huang post_r2y_en = 1; 1202ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 1203ac500a1fSSandy Huang post_y2r_en = 1; 1204ac500a1fSSandy Huang } 1205ac500a1fSSandy Huang 1206ac500a1fSSandy Huang post_csc_mode = vop2_convert_csc_mode(conn_state->color_space); 1207ac500a1fSSandy Huang 1208ac500a1fSSandy Huang 1209ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 1210ac500a1fSSandy Huang BCSH_CTRL_R2Y_SHIFT, post_r2y_en, false); 1211ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 1212ac500a1fSSandy Huang BCSH_CTRL_Y2R_SHIFT, post_y2r_en, false); 1213ac500a1fSSandy Huang 1214ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 1215ac500a1fSSandy Huang BCSH_CTRL_R2Y_CSC_MODE_SHIFT, post_csc_mode, false); 1216ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 1217ac500a1fSSandy Huang BCSH_CTRL_Y2R_CSC_MODE_SHIFT, post_csc_mode, false); 1218ac500a1fSSandy Huang if (!bcsh_en) { 1219ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1220ac500a1fSSandy Huang BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 1221ac500a1fSSandy Huang return; 1222ac500a1fSSandy Huang } 1223ac500a1fSSandy Huang 1224ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 1225ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127, 1226ac500a1fSSandy Huang bcsh_info->brightness); 1227ac500a1fSSandy Huang else 1228ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31, 1229ac500a1fSSandy Huang bcsh_info->brightness); 1230ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 1231ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 1232ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 1233ac500a1fSSandy Huang 1234ac500a1fSSandy Huang 1235ac500a1fSSandy Huang /* 1236ac500a1fSSandy Huang * a:[-30~0): 1237ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256; 1238ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1239ac500a1fSSandy Huang * a:[0~30] 1240ac500a1fSSandy Huang * sin_hue = sin(a)*256; 1241ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1242ac500a1fSSandy Huang */ 1243ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23; 1244ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23; 1245ac500a1fSSandy Huang 1246ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1247ac500a1fSSandy Huang BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 1248ac500a1fSSandy Huang brightness, false); 1249ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1250ac500a1fSSandy Huang BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, contrast, false); 1251ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1252ac500a1fSSandy Huang BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 1253ac500a1fSSandy Huang saturation * contrast / 0x100, false); 1254ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1255ac500a1fSSandy Huang BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, sin_hue, false); 1256ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1257ac500a1fSSandy Huang BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, cos_hue, false); 1258ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1259ac500a1fSSandy Huang BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 1260ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, false); 1261ac500a1fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1262ac500a1fSSandy Huang BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 1263ac500a1fSSandy Huang } 1264ac500a1fSSandy Huang 1265d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 1266d0408543SAndy Yan { 1267d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 1268d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 126952ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state; 127052ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 1271d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal; 1272d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 1273d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 1274d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay; 1275d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay; 1276d0408543SAndy Yan u16 hsize = 1277d0408543SAndy Yan hdisplay * (conn_state->overscan.left_margin + 1278d0408543SAndy Yan conn_state->overscan.right_margin) / 200; 1279d0408543SAndy Yan u16 vsize = 1280d0408543SAndy Yan vdisplay * (conn_state->overscan.top_margin + 1281d0408543SAndy Yan conn_state->overscan.bottom_margin) / 200; 1282d0408543SAndy Yan u16 hact_end, vact_end; 1283d0408543SAndy Yan u32 val; 1284d0408543SAndy Yan u32 bg_ovl_dly, bg_dly, pre_scan_dly; 1285d0408543SAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1286d0408543SAndy Yan 128774bd8269SSandy Huang hsize = round_down(hsize, 2); 1288d0408543SAndy Yan vsize = round_down(vsize, 2); 1289d0408543SAndy Yan 1290d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 1291d0408543SAndy Yan hact_end = hact_st + hsize; 1292d0408543SAndy Yan val = hact_st << 16; 1293d0408543SAndy Yan val |= hact_end; 1294d0408543SAndy Yan 129552ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 1296d0408543SAndy Yan vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 1297d0408543SAndy Yan vact_end = vact_st + vsize; 1298d0408543SAndy Yan val = vact_st << 16; 1299d0408543SAndy Yan val |= vact_end; 130052ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 1301d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16; 1302d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize); 130352ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 1304d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 1305d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 130652ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 1307d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 1308d0408543SAndy Yan POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 1309d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1310d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 1311d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize; 1312d0408543SAndy Yan 1313d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 131452ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 1315d0408543SAndy Yan } 1316d0408543SAndy Yan 131763cb669fSSandy Huang bg_ovl_dly = cstate->crtc->vps[cstate->crtc_id].bg_ovl_dly; 131863cb669fSSandy Huang bg_dly = vop2->data->vp_data[cstate->crtc_id].pre_scan_max_dly; 131963cb669fSSandy Huang bg_dly -= bg_ovl_dly; 1320d0408543SAndy Yan pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1321*ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 1322*ecc31b6eSAndy Yan hsync_len = 8; 1323d0408543SAndy Yan pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 132463cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + cstate->crtc_id * 4, 132563cb669fSSandy Huang BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 132652ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + vp_offset, pre_scan_dly); 1327d0408543SAndy Yan } 1328d0408543SAndy Yan 1329*ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2) 1330*ecc31b6eSAndy Yan { 1331*ecc31b6eSAndy Yan u32 *base = vop2->regs; 1332*ecc31b6eSAndy Yan int i = 0; 1333*ecc31b6eSAndy Yan 1334*ecc31b6eSAndy Yan /* 1335*ecc31b6eSAndy Yan * Open the global pd 1336*ecc31b6eSAndy Yan */ 1337*ecc31b6eSAndy Yan writel(0xffff0000, 0xfd8d8150); 1338*ecc31b6eSAndy Yan udelay(500); 1339*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_SYS_PD_CTRL, 0x0); 1340*ecc31b6eSAndy Yan 1341*ecc31b6eSAndy Yan /* 1342*ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 1343*ecc31b6eSAndy Yan */ 1344*ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++) 1345*ecc31b6eSAndy Yan vop2->regsbak[i] = base[i]; 1346*ecc31b6eSAndy Yan } 1347*ecc31b6eSAndy Yan 1348b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 1349d0408543SAndy Yan { 1350b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 1351b0989546SSandy Huang int i, j, port_mux = 0, total_used_layer = 0; 135263cb669fSSandy Huang u8 shift = 0; 1353b0989546SSandy Huang int layer_phy_id = 0; 1354b0989546SSandy Huang u32 layer_nr = 0; 1355b0989546SSandy Huang struct vop2_win_data *win_data; 1356b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 1357d0408543SAndy Yan 135863cb669fSSandy Huang if (vop2->global_init) 1359d0408543SAndy Yan return; 136063cb669fSSandy Huang 1361b0989546SSandy Huang /* OTP must enable at the first time, otherwise mirror layer register is error */ 136263cb669fSSandy Huang if (soc_is_rk3566()) 136363cb669fSSandy Huang vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 136463cb669fSSandy Huang OTP_WIN_EN_SHIFT, 1, false); 1365b0989546SSandy Huang 1366*ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 1367*ecc31b6eSAndy Yan rk3588_vop2_regsbak(vop2); 1368*ecc31b6eSAndy Yan else 1369b0989546SSandy Huang memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 137063cb669fSSandy Huang vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 137163cb669fSSandy Huang OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 137263cb669fSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 137363cb669fSSandy Huang IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 1374b0989546SSandy Huang 1375b0989546SSandy Huang if (cstate->crtc->assign_plane) {/* dts assign plane */ 1376b0989546SSandy Huang u32 plane_mask; 1377b0989546SSandy Huang int primary_plane_id; 1378b0989546SSandy Huang 1379b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1380b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask; 1381b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 1382b0989546SSandy Huang layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 1383b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 1384b0989546SSandy Huang primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 1385b0989546SSandy Huang vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 1386b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 1387b0989546SSandy Huang 1388b0989546SSandy Huang /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 1389b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1390b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 1391b0989546SSandy Huang plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 139263cb669fSSandy Huang } 1393b0989546SSandy Huang } 1394b0989546SSandy Huang } else {/* need soft assign plane mask */ 1395b0989546SSandy Huang /* find the first unplug devices and set it as main display */ 1396b0989546SSandy Huang int main_vp_index = -1; 1397b0989546SSandy Huang int active_vp_num = 0; 1398b0989546SSandy Huang 1399b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1400b0989546SSandy Huang if (cstate->crtc->vps[i].enable) 1401b0989546SSandy Huang active_vp_num++; 1402b0989546SSandy Huang } 1403b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num); 1404b0989546SSandy Huang 1405b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2) 1406b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n"); 1407b0989546SSandy Huang plane_mask = vop2->data->plane_mask; 1408b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 1409b0989546SSandy Huang 1410b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1411b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 1412b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/ 1413b0989546SSandy Huang main_vp_index = i; 1414e007876dSSandy Huang break; 1415b0989546SSandy Huang } 1416b0989546SSandy Huang } 1417b0989546SSandy Huang 1418b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */ 1419b0989546SSandy Huang if (main_vp_index < 0) { 1420b0989546SSandy Huang main_vp_index = 0; 1421b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0]; 1422b0989546SSandy Huang } 1423b0989546SSandy Huang 1424b0989546SSandy Huang j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */ 1425b0989546SSandy Huang 1426b0989546SSandy Huang /* init other display except main display */ 1427b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1428b0989546SSandy Huang if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */ 1429b0989546SSandy Huang continue; 1430b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++]; 1431b0989546SSandy Huang } 1432b0989546SSandy Huang 1433b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */ 1434b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1435b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1436efb5a62dSSandy Huang /* rk3566 only support 3+3 policy */ 1437efb5a62dSSandy Huang if (soc_is_rk3566() && active_vp_num == 1) { 1438efb5a62dSSandy Huang if (cstate->crtc->vps[i].enable) { 1439efb5a62dSSandy Huang for (j = 0; j < 3; j++) { 1440efb5a62dSSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1441efb5a62dSSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 1442efb5a62dSSandy Huang } 1443efb5a62dSSandy Huang } 1444efb5a62dSSandy Huang } else { 1445b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1446b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1447b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 1448b0989546SSandy Huang } 1449b0989546SSandy Huang } 1450b0989546SSandy Huang } 1451efb5a62dSSandy Huang } 1452b0989546SSandy Huang 1453b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1454b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 1455b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 1456b0989546SSandy Huang printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]); 1457b0989546SSandy Huang printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id); 1458b0989546SSandy Huang } 1459b0989546SSandy Huang 1460b0989546SSandy Huang shift = 0; 1461b0989546SSandy Huang /* layer sel win id */ 1462b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1463b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1464b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1465b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1466*ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 1467b0989546SSandy Huang vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 1468b0989546SSandy Huang shift, win_data->layer_sel_win_id, false); 1469b0989546SSandy Huang shift += 4; 1470b0989546SSandy Huang } 1471b0989546SSandy Huang } 1472b0989546SSandy Huang 1473b0989546SSandy Huang /* win sel port */ 1474b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 1475b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1476b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 1477*ecc31b6eSAndy Yan if (!vop2->vp_plane_mask[i].attached_layers[j]) 1478b0989546SSandy Huang continue; 1479b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1480*ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 1481b0989546SSandy Huang shift = win_data->win_sel_port_offset * 2; 1482b0989546SSandy Huang vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 1483b0989546SSandy Huang LAYER_SEL_PORT_SHIFT + shift, i, false); 1484b0989546SSandy Huang } 1485b0989546SSandy Huang } 1486b0989546SSandy Huang 148763cb669fSSandy Huang /** 148863cb669fSSandy Huang * port mux config 148963cb669fSSandy Huang */ 1490b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 149163cb669fSSandy Huang shift = i * 4; 1492*ecc31b6eSAndy Yan if (vop2->vp_plane_mask[i].attached_layers_nr) { 1493b0989546SSandy Huang total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 149463cb669fSSandy Huang port_mux = total_used_layer - 1; 149563cb669fSSandy Huang } else { 149663cb669fSSandy Huang port_mux = 8; 1497d0408543SAndy Yan } 1498d0408543SAndy Yan 1499b0989546SSandy Huang if (i == vop2->data->nr_vps - 1) 150063cb669fSSandy Huang port_mux = vop2->data->nr_mixers; 150163cb669fSSandy Huang 150263cb669fSSandy Huang cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 150363cb669fSSandy Huang vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 150463cb669fSSandy Huang PORT_MUX_SHIFT + shift, port_mux, false); 150563cb669fSSandy Huang } 150663cb669fSSandy Huang 1507*ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568) 150863cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 150963cb669fSSandy Huang 151063cb669fSSandy Huang vop2->global_init = true; 1511d0408543SAndy Yan } 1512d0408543SAndy Yan 1513d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state) 1514d0408543SAndy Yan { 1515d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 151663cb669fSSandy Huang int ret; 1517d0408543SAndy Yan 1518d0408543SAndy Yan /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1519d0408543SAndy Yan ret = clk_set_defaults(cstate->dev); 1520d0408543SAndy Yan if (ret) 1521d0408543SAndy Yan debug("%s clk_set_defaults failed %d\n", __func__, ret); 1522d0408543SAndy Yan 15231147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state); 15246414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state); 1525d0408543SAndy Yan 1526d0408543SAndy Yan return 0; 1527d0408543SAndy Yan } 1528d0408543SAndy Yan 1529d0408543SAndy Yan /* 1530d0408543SAndy Yan * VOP2 have multi video ports. 1531d0408543SAndy Yan * video port ------- crtc 1532d0408543SAndy Yan */ 1533d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state) 1534d0408543SAndy Yan { 1535d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 1536d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data; 1537d0408543SAndy Yan 1538d0408543SAndy Yan if (!rockchip_vop2) { 15390d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2)); 1540d0408543SAndy Yan if (!rockchip_vop2) 1541d0408543SAndy Yan return -ENOMEM; 1542d0408543SAndy Yan rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 1543d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 1544d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG; 154563cb669fSSandy Huang rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 1546d0408543SAndy Yan if (rockchip_vop2->grf <= 0) 154763cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 1548d0408543SAndy Yan rockchip_vop2->version = vop2_data->version; 1549d0408543SAndy Yan rockchip_vop2->data = vop2_data; 1550*ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) { 1551*ecc31b6eSAndy Yan rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF); 1552*ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0) 1553*ecc31b6eSAndy Yan printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf); 1554*ecc31b6eSAndy Yan rockchip_vop2->vo1_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VO_GRF); 1555*ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0) 1556*ecc31b6eSAndy Yan printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf); 1557*ecc31b6eSAndy Yan } 1558d0408543SAndy Yan } 1559d0408543SAndy Yan 1560d0408543SAndy Yan cstate->private = rockchip_vop2; 156163cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 156263cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 1563d0408543SAndy Yan 156489912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state); 156589912f2dSSandy Huang 1566d0408543SAndy Yan return 0; 1567d0408543SAndy Yan } 1568d0408543SAndy Yan 1569*ecc31b6eSAndy Yan /* 1570*ecc31b6eSAndy Yan * calc the dclk on rk3588 1571*ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4 1572*ecc31b6eSAndy Yan * 1573*ecc31b6eSAndy Yan */ 1574*ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 1575*ecc31b6eSAndy Yan { 1576*ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk) 1577*ecc31b6eSAndy Yan return child_clk * 4; 1578*ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk) 1579*ecc31b6eSAndy Yan return child_clk * 2; 1580*ecc31b6eSAndy Yan else if (child_clk <= max_dclk) 1581*ecc31b6eSAndy Yan return child_clk; 1582*ecc31b6eSAndy Yan else 1583*ecc31b6eSAndy Yan return 0; 1584*ecc31b6eSAndy Yan } 1585*ecc31b6eSAndy Yan 1586*ecc31b6eSAndy Yan /* 1587*ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588 1588*ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core 1589*ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core 1590*ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core 1591*ecc31b6eSAndy Yan */ 1592*ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state, 1593*ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div, 1594*ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div) 1595d0408543SAndy Yan { 1596d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 1597d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 1598d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 1599d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 1600*ecc31b6eSAndy Yan unsigned long v_pixclk = mode->clock; 1601*ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2; 1602*ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk; 1603*ecc31b6eSAndy Yan unsigned long dclk_out_rate; 1604*ecc31b6eSAndy Yan u64 if_dclk_rate; 1605*ecc31b6eSAndy Yan u64 if_pixclk_rate; 1606*ecc31b6eSAndy Yan int output_type = conn_state->type; 1607*ecc31b6eSAndy Yan int output_mode = conn_state->output_mode; 1608*ecc31b6eSAndy Yan int K = 1; 1609*ecc31b6eSAndy Yan 1610*ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 1611*ecc31b6eSAndy Yan /* 1612*ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 1613*ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 1614*ecc31b6eSAndy Yan */ 1615*ecc31b6eSAndy Yan if (output_mode == ROCKCHIP_OUT_MODE_YUV420) 1616*ecc31b6eSAndy Yan K = 2; 1617*ecc31b6eSAndy Yan if (conn_state->dsc_enable) { 1618*ecc31b6eSAndy Yan if_pixclk_rate = conn_state->dsc_cds_clk << 1; 1619*ecc31b6eSAndy Yan if_dclk_rate = conn_state->dsc_cds_clk; 1620*ecc31b6eSAndy Yan } else { 1621*ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K; 1622*ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K; 1623*ecc31b6eSAndy Yan } 1624*ecc31b6eSAndy Yan 1625*ecc31b6eSAndy Yan dclk_rate = vop2_calc_dclk(if_pixclk_rate, vop2->data->vp_data->max_dclk); 1626*ecc31b6eSAndy Yan if (!dclk_rate) { 1627*ecc31b6eSAndy Yan printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 1628*ecc31b6eSAndy Yan vop2->data->vp_data->max_dclk, if_pixclk_rate); 1629*ecc31b6eSAndy Yan return -EINVAL; 1630*ecc31b6eSAndy Yan } 1631*ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 1632*ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate; 1633*ecc31b6eSAndy Yan 1634*ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 1635*ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */ 1636*ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K; 1637*ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K; 1638*ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K; 1639*ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 1640*ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 1641*ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div; 1642*ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 1643*ecc31b6eSAndy Yan if (output_mode == ROCKCHIP_OUT_MODE_YUV420) 1644*ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 3; 1645*ecc31b6eSAndy Yan else 1646*ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2; 1647*ecc31b6eSAndy Yan 1648*ecc31b6eSAndy Yan dclk_rate = vop2_calc_dclk(dclk_core_rate, vop2->data->vp_data->max_dclk); 1649*ecc31b6eSAndy Yan if (!dclk_rate) { 1650*ecc31b6eSAndy Yan printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 1651*ecc31b6eSAndy Yan vop2->data->vp_data->max_dclk, dclk_core_rate); 1652*ecc31b6eSAndy Yan return -EINVAL; 1653*ecc31b6eSAndy Yan } 1654*ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 1655*ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 1656*ecc31b6eSAndy Yan 1657*ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 1658*ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 1659*ecc31b6eSAndy Yan K = 2; 1660*ecc31b6eSAndy Yan if (conn_state->dsc_enable) 1661*ecc31b6eSAndy Yan if_pixclk_rate = conn_state->dsc_cds_clk >> 1; 1662*ecc31b6eSAndy Yan else 1663*ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K; 1664*ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 1665*ecc31b6eSAndy Yan dclk_out_rate = if_pixclk_rate; 1666*ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 1667*ecc31b6eSAndy Yan dclk_rate = dclk_core_rate; 1668*ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 1669*ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 1670*ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 1671*ecc31b6eSAndy Yan 1672*ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 1673*ecc31b6eSAndy Yan dclk_rate = v_pixclk; 1674*ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 1675*ecc31b6eSAndy Yan } 1676*ecc31b6eSAndy Yan 1677*ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div); 1678*ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div); 1679*ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div); 1680*ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div); 1681*ecc31b6eSAndy Yan 1682*ecc31b6eSAndy Yan return dclk_rate; 1683*ecc31b6eSAndy Yan } 1684*ecc31b6eSAndy Yan 1685*ecc31b6eSAndy Yan static int vop2_calc_dsc_clk(struct connector_state *conn_state) 1686*ecc31b6eSAndy Yan { 1687*ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 1688*ecc31b6eSAndy Yan u64 v_pixclk = mode->clock * 1000LL; /* video timing pixclk */ 1689*ecc31b6eSAndy Yan u8 k = 1; 1690*ecc31b6eSAndy Yan 1691*ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 1692*ecc31b6eSAndy Yan k = 2; 1693*ecc31b6eSAndy Yan 1694*ecc31b6eSAndy Yan conn_state->dsc_pxl_clk = v_pixclk; 1695*ecc31b6eSAndy Yan do_div(conn_state->dsc_pxl_clk, (conn_state->dsc_slice_num * k)); 1696*ecc31b6eSAndy Yan 1697*ecc31b6eSAndy Yan conn_state->dsc_txp_clk = v_pixclk; 1698*ecc31b6eSAndy Yan do_div(conn_state->dsc_txp_clk, (conn_state->dsc_pixel_num * k)); 1699*ecc31b6eSAndy Yan 1700*ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 1701*ecc31b6eSAndy Yan * cds_dat_width = 96; 1702*ecc31b6eSAndy Yan * bits_per_pixel = [8-12]; 1703*ecc31b6eSAndy Yan * As only support 1/2/4 div, so we set dsc_cds = crtc_clock / 8; 1704*ecc31b6eSAndy Yan */ 1705*ecc31b6eSAndy Yan conn_state->dsc_cds_clk = mode->crtc_clock / 8 * 1000; 1706*ecc31b6eSAndy Yan 1707*ecc31b6eSAndy Yan return 0; 1708*ecc31b6eSAndy Yan } 1709*ecc31b6eSAndy Yan 1710*ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 1711*ecc31b6eSAndy Yan { 1712*ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 1713*ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 1714*ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 1715*ecc31b6eSAndy Yan struct rockchip_dsc_sink_cap *dsc_sink_cap = &conn_state->dsc_sink_cap; 1716*ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 171752ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 1718*ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 1719*ecc31b6eSAndy Yan int output_if = conn_state->output_if; 1720*ecc31b6eSAndy Yan int dclk_core_div = 0; 1721*ecc31b6eSAndy Yan int dclk_out_div = 0; 1722*ecc31b6eSAndy Yan int if_pixclk_div = 0; 1723*ecc31b6eSAndy Yan int if_dclk_div = 0; 1724*ecc31b6eSAndy Yan unsigned long dclk_rate; 1725d0408543SAndy Yan u32 val; 1726*ecc31b6eSAndy Yan 1727*ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 1728*ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 1729*ecc31b6eSAndy Yan 1730*ecc31b6eSAndy Yan if (conn_state->dsc_enable) { 1731*ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) { 1732*ecc31b6eSAndy Yan printf("No DSC\n"); 1733*ecc31b6eSAndy Yan return 0; 1734*ecc31b6eSAndy Yan } 1735*ecc31b6eSAndy Yan conn_state->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 1736*ecc31b6eSAndy Yan conn_state->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width; 1737*ecc31b6eSAndy Yan conn_state->dsc_pixel_num = conn_state->dsc_slice_num >= 4 ? 1738*ecc31b6eSAndy Yan 4 : conn_state->dsc_slice_num >= 2 ? 2 : 1; 1739*ecc31b6eSAndy Yan vop2_calc_dsc_clk(conn_state); 1740*ecc31b6eSAndy Yan } 1741*ecc31b6eSAndy Yan 1742*ecc31b6eSAndy Yan dclk_rate = vop2_calc_cru_cfg(state, &dclk_core_div, &dclk_out_div, &if_pixclk_div, &if_dclk_div); 1743*ecc31b6eSAndy Yan 1744*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) { 1745*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 1746*ecc31b6eSAndy Yan 4, false); 1747*ecc31b6eSAndy Yan } 1748*ecc31b6eSAndy Yan 1749*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) { 1750*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 1751*ecc31b6eSAndy Yan 3, false); 1752*ecc31b6eSAndy Yan } 1753*ecc31b6eSAndy Yan 1754*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) { 1755*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 1756*ecc31b6eSAndy Yan 2, false); 1757*ecc31b6eSAndy Yan } 1758*ecc31b6eSAndy Yan 1759*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) { 1760*ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 1761*ecc31b6eSAndy Yan val = 0; 1762*ecc31b6eSAndy Yan else 1763*ecc31b6eSAndy Yan val = 1; 1764*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 1765*ecc31b6eSAndy Yan 1, false); 1766*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 1767*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 1768*ecc31b6eSAndy Yan if_pixclk_div, false); 1769*ecc31b6eSAndy Yan } 1770*ecc31b6eSAndy Yan 1771*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) { 1772*ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 1773*ecc31b6eSAndy Yan val = 0; 1774*ecc31b6eSAndy Yan else if (cstate->crtc_id == 3) 1775*ecc31b6eSAndy Yan val = 1; 1776*ecc31b6eSAndy Yan else 1777*ecc31b6eSAndy Yan val = 3; /*VP1*/ 1778*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 1779*ecc31b6eSAndy Yan 1, false); 1780*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 1781*ecc31b6eSAndy Yan val, false); 1782*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 1783*ecc31b6eSAndy Yan if_pixclk_div, false); 1784*ecc31b6eSAndy Yan } 1785*ecc31b6eSAndy Yan 1786*ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 1787*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 1788*ecc31b6eSAndy Yan RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 1789*ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 1790*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1791*ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 1792*ecc31b6eSAndy Yan false); 1793*ecc31b6eSAndy Yan } 1794*ecc31b6eSAndy Yan 1795*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) { 1796*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 1797*ecc31b6eSAndy Yan 1, false); 1798*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 1799*ecc31b6eSAndy Yan cstate->crtc_id, false); 1800*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 1801*ecc31b6eSAndy Yan if_dclk_div, false); 1802*ecc31b6eSAndy Yan 1803*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 1804*ecc31b6eSAndy Yan if_pixclk_div, false); 1805*ecc31b6eSAndy Yan 1806*ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 1807*ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 1808*ecc31b6eSAndy Yan } 1809*ecc31b6eSAndy Yan 1810*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) { 1811*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 1812*ecc31b6eSAndy Yan 1, false); 1813*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 1814*ecc31b6eSAndy Yan cstate->crtc_id, false); 1815*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 1816*ecc31b6eSAndy Yan if_dclk_div, false); 1817*ecc31b6eSAndy Yan 1818*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 1819*ecc31b6eSAndy Yan if_pixclk_div, false); 1820*ecc31b6eSAndy Yan } 1821*ecc31b6eSAndy Yan 1822*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) { 1823*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 1824*ecc31b6eSAndy Yan 1, false); 1825*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 1826*ecc31b6eSAndy Yan cstate->crtc_id, false); 1827*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 1828*ecc31b6eSAndy Yan if_dclk_div, false); 1829*ecc31b6eSAndy Yan 1830*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 1831*ecc31b6eSAndy Yan if_pixclk_div, false); 1832*ecc31b6eSAndy Yan } 1833*ecc31b6eSAndy Yan 1834*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) { 1835*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 1836*ecc31b6eSAndy Yan 1, false); 1837*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 1838*ecc31b6eSAndy Yan cstate->crtc_id, false); 1839*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 1840*ecc31b6eSAndy Yan if_dclk_div, false); 1841*ecc31b6eSAndy Yan 1842*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 1843*ecc31b6eSAndy Yan if_pixclk_div, false); 1844*ecc31b6eSAndy Yan } 1845*ecc31b6eSAndy Yan 1846*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) { 1847*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 1848*ecc31b6eSAndy Yan 1, false); 1849*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 1850*ecc31b6eSAndy Yan cstate->crtc_id, false); 1851*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 1852*ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false); 1853*ecc31b6eSAndy Yan } 1854*ecc31b6eSAndy Yan 1855*ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) { 1856*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 1857*ecc31b6eSAndy Yan 1, false); 1858*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 1859*ecc31b6eSAndy Yan cstate->crtc_id, false); 1860*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 1861*ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false); 1862*ecc31b6eSAndy Yan } 1863*ecc31b6eSAndy Yan 1864*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 1865*ecc31b6eSAndy Yan DCLK_CORE_DIV_SHIFT, dclk_core_div, false); 1866*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 1867*ecc31b6eSAndy Yan DCLK_OUT_DIV_SHIFT, dclk_out_div, false); 1868*ecc31b6eSAndy Yan 1869*ecc31b6eSAndy Yan return dclk_rate; 1870*ecc31b6eSAndy Yan } 1871*ecc31b6eSAndy Yan 1872*ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 1873*ecc31b6eSAndy Yan { 1874*ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 1875*ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 1876*ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 1877*ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 1878*ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 1879d0408543SAndy Yan bool dclk_inv; 1880*ecc31b6eSAndy Yan u32 val; 18818895aec1SSandy Huang 1882d0408543SAndy Yan dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 188310ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 188410ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 1885d0408543SAndy Yan 1886d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 1887d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 1888d0408543SAndy Yan 1, false); 1889d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1890d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 1891*ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 1892c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 1893d0408543SAndy Yan } 1894d0408543SAndy Yan 1895d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 189652ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 189752ee18acSSandy Huang 1, false); 1898d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 1899d0408543SAndy Yan BT1120_EN_SHIFT, 1, false); 1900d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1901d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 1902*ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 190352ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 1904d0408543SAndy Yan } 1905d0408543SAndy Yan 1906d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 1907d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 1908d0408543SAndy Yan 1, false); 1909d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1910d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 1911*ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 191252ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 1913d0408543SAndy Yan } 1914d0408543SAndy Yan 1915d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 1916d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 1917d0408543SAndy Yan 1, false); 1918d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1919d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false); 192011f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 192111f53190SSandy Huang IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 1922d0408543SAndy Yan } 1923d0408543SAndy Yan 1924d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 1925d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 1926d0408543SAndy Yan 1, false); 1927d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1928d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false); 192911f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 193011f53190SSandy Huang IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 1931d0408543SAndy Yan } 1932d0408543SAndy Yan 1933d0408543SAndy Yan if (conn_state->output_flags & 1934d0408543SAndy Yan (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 1935d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 1936d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 1937d0408543SAndy Yan LVDS_DUAL_EN_SHIFT, 1, false); 1938d0408543SAndy Yan if (conn_state->output_flags & 1939d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 1940d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 1941d0408543SAndy Yan LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 1942d0408543SAndy Yan false); 1943d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 1944d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 1945d0408543SAndy Yan LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 1946d0408543SAndy Yan } 1947d0408543SAndy Yan 1948d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 1949d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 1950d0408543SAndy Yan 1, false); 1951d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1952d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false); 1953d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 1954c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 1955d0408543SAndy Yan } 1956d0408543SAndy Yan 1957d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 1958d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 1959d0408543SAndy Yan 1, false); 1960d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1961d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false); 1962d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 1963c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 1964d0408543SAndy Yan } 1965d0408543SAndy Yan 1966d0408543SAndy Yan if (conn_state->output_flags & 1967d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 1968d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 1969d0408543SAndy Yan MIPI_DUAL_EN_SHIFT, 1, false); 1970d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 1971d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1972d0408543SAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 1973d0408543SAndy Yan false); 1974d0408543SAndy Yan } 1975d0408543SAndy Yan 1976d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 1977d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 1978d0408543SAndy Yan 1, false); 1979d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1980d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false); 1981c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 1982c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 1983d0408543SAndy Yan } 1984d0408543SAndy Yan 1985d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 1986d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 1987d0408543SAndy Yan 1, false); 1988d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 1989d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false); 199010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 199110ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 199210ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, 199310ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK, 199410ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 1995d0408543SAndy Yan } 199610ee9f5bSAlgea Cao 1997*ecc31b6eSAndy Yan return mode->clock; 1998*ecc31b6eSAndy Yan } 1999*ecc31b6eSAndy Yan 2000*ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state) 2001*ecc31b6eSAndy Yan { 2002*ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2003*ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2004*ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2005*ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2006*ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2007*ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2008*ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal; 2009*ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 2010*ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay; 2011*ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay; 2012*ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal; 2013*ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 2014*ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 2015*ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay; 2016*ecc31b6eSAndy Yan bool yuv_overlay = false; 2017*ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 2018*ecc31b6eSAndy Yan u32 val; 2019*ecc31b6eSAndy Yan u8 dither_down_en = 0; 2020*ecc31b6eSAndy Yan u8 pre_dither_down_en = 0; 2021*ecc31b6eSAndy Yan char output_type_name[30] = {0}; 2022*ecc31b6eSAndy Yan char dclk_name[9]; 2023*ecc31b6eSAndy Yan struct clk dclk; 2024*ecc31b6eSAndy Yan unsigned long dclk_rate; 2025*ecc31b6eSAndy Yan int ret; 2026*ecc31b6eSAndy Yan 2027*ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 2028*ecc31b6eSAndy Yan mode->hdisplay, mode->vdisplay, 2029*ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 2030*ecc31b6eSAndy Yan mode->vscan, 2031*ecc31b6eSAndy Yan get_output_if_name(conn_state->output_if, output_type_name), 2032*ecc31b6eSAndy Yan cstate->crtc_id); 2033*ecc31b6eSAndy Yan 2034*ecc31b6eSAndy Yan vop2_initial(vop2, state); 2035*ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 2036*ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state); 2037*ecc31b6eSAndy Yan else 2038*ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state); 2039*ecc31b6eSAndy Yan 204063cb669fSSandy Huang if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 204163cb669fSSandy Huang !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) 20427bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 20437bdd0eb6SSandy Huang 204410ee9f5bSAlgea Cao if (is_uv_swap(conn_state->bus_format, conn_state->output_mode)) 204510ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 204610ee9f5bSAlgea Cao DATA_SWAP_MASK, DATA_SWAP_SHIFT, DSP_RB_SWAP, 204710ee9f5bSAlgea Cao false); 204810ee9f5bSAlgea Cao else 204910ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 205010ee9f5bSAlgea Cao DATA_SWAP_MASK, DATA_SWAP_SHIFT, 0, 205110ee9f5bSAlgea Cao false); 205210ee9f5bSAlgea Cao 2053d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 2054d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false); 2055d0408543SAndy Yan 2056d0408543SAndy Yan switch (conn_state->bus_format) { 2057d0408543SAndy Yan case MEDIA_BUS_FMT_RGB565_1X16: 2058d0408543SAndy Yan dither_down_en = 1; 2059d0408543SAndy Yan break; 2060d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X18: 2061d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 2062d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 2063d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: 2064d0408543SAndy Yan dither_down_en = 1; 2065d0408543SAndy Yan break; 2066d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 2067d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 2068d0408543SAndy Yan dither_down_en = 0; 2069d0408543SAndy Yan pre_dither_down_en = 1; 2070d0408543SAndy Yan break; 2071d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 2072d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 2073d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X24: 2074d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 2075d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 2076d0408543SAndy Yan default: 2077d0408543SAndy Yan dither_down_en = 0; 2078d0408543SAndy Yan pre_dither_down_en = 0; 2079d0408543SAndy Yan break; 2080d0408543SAndy Yan } 2081d0408543SAndy Yan 2082d0408543SAndy Yan if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA) 2083d0408543SAndy Yan pre_dither_down_en = 0; 2084d0408543SAndy Yan else 2085d0408543SAndy Yan pre_dither_down_en = 1; 2086d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2087d0408543SAndy Yan DITHER_DOWN_EN_SHIFT, dither_down_en, false); 2088d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2089d0408543SAndy Yan PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 2090d0408543SAndy Yan 2091d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 2092d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 2093d0408543SAndy Yan yuv_overlay, false); 2094d0408543SAndy Yan 2095d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay; 2096d0408543SAndy Yan 2097d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 2098d0408543SAndy Yan (htotal << 16) | hsync_len); 2099d0408543SAndy Yan val = hact_st << 16; 2100d0408543SAndy Yan val |= hact_end; 2101d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 2102d0408543SAndy Yan val = vact_st << 16; 2103d0408543SAndy Yan val |= vact_end; 2104d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 2105d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 2106d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 2107d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay; 2108d0408543SAndy Yan 2109d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 2110d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 2111d0408543SAndy Yan val); 2112d0408543SAndy Yan 2113d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len); 2114d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 2115d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2116d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false); 2117d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 21187a20be36SSandy Huang DSP_FILED_POL, 1, false); 21197a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2120d0408543SAndy Yan P2I_EN_SHIFT, 1, false); 2121d0408543SAndy Yan vtotal += vtotal + 1; 2122d0408543SAndy Yan } else { 2123d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2124d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false); 2125d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2126d0408543SAndy Yan P2I_EN_SHIFT, 0, false); 2127d0408543SAndy Yan } 2128d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 2129d0408543SAndy Yan (vtotal << 16) | vsync_len); 2130d0408543SAndy Yan val = !!(mode->flags & DRM_MODE_FLAG_DBLCLK); 2131d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 213210ee9f5bSAlgea Cao CORE_DCLK_DIV_EN_SHIFT, val, false); 213310ee9f5bSAlgea Cao 213410ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 213563cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 213663cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 213710ee9f5bSAlgea Cao else 213863cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 213963cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 214010ee9f5bSAlgea Cao 214110ee9f5bSAlgea Cao if (yuv_overlay) 214210ee9f5bSAlgea Cao val = 0x20010200; 214310ee9f5bSAlgea Cao else 214410ee9f5bSAlgea Cao val = 0; 214510ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 214610ee9f5bSAlgea Cao 214710ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 214810ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 2149d0408543SAndy Yan 2150ac500a1fSSandy Huang vop2_tv_config_update(state, vop2); 2151d0408543SAndy Yan vop2_post_config(state, vop2); 2152d0408543SAndy Yan 2153*ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 2154*ecc31b6eSAndy Yan ret = clk_get_by_name(cstate->dev, dclk_name, &dclk); 2155*ecc31b6eSAndy Yan if (!ret) 2156*ecc31b6eSAndy Yan ret = clk_set_rate(&dclk, dclk_rate * 1000); 2157*ecc31b6eSAndy Yan if (IS_ERR_VALUE(ret)) { 2158*ecc31b6eSAndy Yan printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 2159*ecc31b6eSAndy Yan __func__, cstate->crtc_id, dclk_rate, ret); 2160*ecc31b6eSAndy Yan return ret; 2161*ecc31b6eSAndy Yan } 2162*ecc31b6eSAndy Yan 2163d0408543SAndy Yan return 0; 2164d0408543SAndy Yan } 2165d0408543SAndy Yan 2166*ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 21673e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w, 21683e39a5a1SSandy Huang uint32_t dst_h) 21693e39a5a1SSandy Huang { 21703e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 21713e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode; 21723e39a5a1SSandy Huang uint8_t gt2 = 0, gt4 = 0; 21733e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0; 21743e39a5a1SSandy Huang uint16_t hsu_filter_mode = VOP2_SCALE_UP_BIC; 21753e39a5a1SSandy Huang uint16_t hsd_filter_mode = VOP2_SCALE_DOWN_BIL; 21763e39a5a1SSandy Huang uint16_t vsu_filter_mode = VOP2_SCALE_UP_BIL; 21773e39a5a1SSandy Huang uint16_t vsd_filter_mode = VOP2_SCALE_DOWN_BIL; 2178*ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 21793e39a5a1SSandy Huang 21803e39a5a1SSandy Huang if (src_h >= (4 * dst_h)) 21813e39a5a1SSandy Huang gt4 = 1; 21823e39a5a1SSandy Huang else if (src_h >= (2 * dst_h)) 21833e39a5a1SSandy Huang gt2 = 1; 21843e39a5a1SSandy Huang 21853e39a5a1SSandy Huang if (gt4) 21863e39a5a1SSandy Huang src_h >>= 2; 21873e39a5a1SSandy Huang else if (gt2) 21883e39a5a1SSandy Huang src_h >>= 1; 21893e39a5a1SSandy Huang 21903e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 21913e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 21923e39a5a1SSandy Huang 21933e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP) 21943e39a5a1SSandy Huang hscl_filter_mode = hsu_filter_mode; 21953e39a5a1SSandy Huang else 21963e39a5a1SSandy Huang hscl_filter_mode = hsd_filter_mode; 21973e39a5a1SSandy Huang 21983e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP) 21993e39a5a1SSandy Huang vscl_filter_mode = vsu_filter_mode; 22003e39a5a1SSandy Huang else 22013e39a5a1SSandy Huang vscl_filter_mode = vsd_filter_mode; 22023e39a5a1SSandy Huang 22033e39a5a1SSandy Huang /* 22043e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel 22053e39a5a1SSandy Huang * at scale down mode 22063e39a5a1SSandy Huang */ 22073e39a5a1SSandy Huang if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) { 22083e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 22093e39a5a1SSandy Huang dst_w += 1; 22103e39a5a1SSandy Huang } 22113e39a5a1SSandy Huang 22123e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 22133e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 2214*ecc31b6eSAndy Yan 2215*ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) { 2216*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 2217*ecc31b6eSAndy Yan yfac << 16 | xfac); 2218*ecc31b6eSAndy Yan 2219*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2220*ecc31b6eSAndy Yan YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, gt2, false); 2221*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2222*ecc31b6eSAndy Yan YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, gt4, false); 2223*ecc31b6eSAndy Yan 2224*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2225*ecc31b6eSAndy Yan YRGB_XSCL_MODE_MASK, CLUSTER_YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 2226*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2227*ecc31b6eSAndy Yan YRGB_YSCL_MODE_MASK, CLUSTER_YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 2228*ecc31b6eSAndy Yan 2229*ecc31b6eSAndy Yan } else { 22303e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 22313e39a5a1SSandy Huang yfac << 16 | xfac); 22323e39a5a1SSandy Huang 223334a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 22343e39a5a1SSandy Huang YRGB_GT2_MASK, YRGB_GT2_SHIFT, gt2, false); 223534a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 22363e39a5a1SSandy Huang YRGB_GT4_MASK, YRGB_GT4_SHIFT, gt4, false); 22373e39a5a1SSandy Huang 22383e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 22393e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 22403e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 22413e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 22423e39a5a1SSandy Huang 22433e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 22443e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 22453e39a5a1SSandy Huang hscl_filter_mode, false); 22463e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 22473e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 22483e39a5a1SSandy Huang vscl_filter_mode, false); 22493e39a5a1SSandy Huang } 2250*ecc31b6eSAndy Yan } 22513e39a5a1SSandy Huang 2252*ecc31b6eSAndy Yan static void vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 2253d0408543SAndy Yan { 2254d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2255d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 2256d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2257d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 2258d0408543SAndy Yan int src_w = cstate->src_w; 2259d0408543SAndy Yan int src_h = cstate->src_h; 2260d0408543SAndy Yan int crtc_x = cstate->crtc_x; 2261d0408543SAndy Yan int crtc_y = cstate->crtc_y; 2262d0408543SAndy Yan int crtc_w = cstate->crtc_w; 2263d0408543SAndy Yan int crtc_h = cstate->crtc_h; 2264d0408543SAndy Yan int xvir = cstate->xvir; 2265d0408543SAndy Yan int y_mirror = 0; 226610ee9f5bSAlgea Cao int csc_mode; 2267*ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 2268*ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 2269*ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2270d0408543SAndy Yan 2271*ecc31b6eSAndy Yan act_info = (src_h - 1) << 16; 2272*ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff; 2273*ecc31b6eSAndy Yan 2274*ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16; 2275*ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 2276*ecc31b6eSAndy Yan 2277*ecc31b6eSAndy Yan dsp_stx = crtc_x; 2278*ecc31b6eSAndy Yan dsp_sty = crtc_y; 2279*ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 2280*ecc31b6eSAndy Yan 2281*ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 2282*ecc31b6eSAndy Yan y_mirror = 1; 2283*ecc31b6eSAndy Yan else 2284*ecc31b6eSAndy Yan y_mirror = 0; 2285*ecc31b6eSAndy Yan 2286*ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 2287*ecc31b6eSAndy Yan 2288*ecc31b6eSAndy Yan if (y_mirror) 2289*ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n"); 2290*ecc31b6eSAndy Yan 2291*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 2292*ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 2293*ecc31b6eSAndy Yan false); 2294*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 2295*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, cstate->dma_addr); 2296*ecc31b6eSAndy Yan 2297*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 2298*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 2299*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 2300*ecc31b6eSAndy Yan 2301*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 2302*ecc31b6eSAndy Yan 2303*ecc31b6eSAndy Yan csc_mode = vop2_convert_csc_mode(conn_state->color_space); 2304*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 2305*ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT, 2306*ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false); 2307*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 2308*ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 2309*ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 2310*ecc31b6eSAndy Yan 2311*ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2312d0408543SAndy Yan } 2313d0408543SAndy Yan 2314*ecc31b6eSAndy Yan static void vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 2315*ecc31b6eSAndy Yan { 2316*ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2317*ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2318*ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2319*ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2320*ecc31b6eSAndy Yan int src_w = cstate->src_w; 2321*ecc31b6eSAndy Yan int src_h = cstate->src_h; 2322*ecc31b6eSAndy Yan int crtc_x = cstate->crtc_x; 2323*ecc31b6eSAndy Yan int crtc_y = cstate->crtc_y; 2324*ecc31b6eSAndy Yan int crtc_w = cstate->crtc_w; 2325*ecc31b6eSAndy Yan int crtc_h = cstate->crtc_h; 2326*ecc31b6eSAndy Yan int xvir = cstate->xvir; 2327*ecc31b6eSAndy Yan int y_mirror = 0; 2328*ecc31b6eSAndy Yan int csc_mode; 2329*ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 2330*ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 2331*ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2332*ecc31b6eSAndy Yan 233374bd8269SSandy Huang /* 233474bd8269SSandy Huang * This is workaround solution for IC design: 233574bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1. 233674bd8269SSandy Huang */ 233774bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) { 233874bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 233974bd8269SSandy Huang src_w -= 1; 234074bd8269SSandy Huang } 234174bd8269SSandy Huang 2342d0408543SAndy Yan act_info = (src_h - 1) << 16; 2343d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff; 2344d0408543SAndy Yan 2345d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16; 2346d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 2347d0408543SAndy Yan 2348d0408543SAndy Yan dsp_stx = crtc_x; 2349d0408543SAndy Yan dsp_sty = crtc_y; 2350d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 2351d0408543SAndy Yan 2352d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 2353d0408543SAndy Yan y_mirror = 1; 2354d0408543SAndy Yan else 2355d0408543SAndy Yan y_mirror = 0; 2356d0408543SAndy Yan 2357*ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 23583e39a5a1SSandy Huang 2359d0408543SAndy Yan if (y_mirror) 2360d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4; 2361d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 2362d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false); 2363d0408543SAndy Yan 2364d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 2365d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 2366d0408543SAndy Yan false); 2367d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 2368d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 2369d0408543SAndy Yan cstate->dma_addr); 2370d0408543SAndy Yan 2371d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 2372d0408543SAndy Yan act_info); 2373d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 2374d0408543SAndy Yan dsp_info); 2375d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 2376d0408543SAndy Yan 2377d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 2378d0408543SAndy Yan WIN_EN_SHIFT, 1, false); 2379d0408543SAndy Yan 238010ee9f5bSAlgea Cao csc_mode = vop2_convert_csc_mode(conn_state->color_space); 238110ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 238210ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT, 238310ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false); 238410ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 238510ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false); 238610ee9f5bSAlgea Cao 2387d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2388*ecc31b6eSAndy Yan } 2389*ecc31b6eSAndy Yan 2390*ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state) 2391*ecc31b6eSAndy Yan { 2392*ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2393*ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2394*ecc31b6eSAndy Yan struct vop2_win_data *win_data; 2395*ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 2396*ecc31b6eSAndy Yan char plane_name[10] = {0}; 2397*ecc31b6eSAndy Yan 2398*ecc31b6eSAndy Yan if (cstate->crtc_w > cstate->max_output.width) { 2399*ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n", 2400*ecc31b6eSAndy Yan cstate->crtc_w, cstate->max_output.width); 2401*ecc31b6eSAndy Yan return -EINVAL; 2402*ecc31b6eSAndy Yan } 2403*ecc31b6eSAndy Yan 2404*ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 2405*ecc31b6eSAndy Yan if (!win_data) { 2406*ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id); 2407*ecc31b6eSAndy Yan return -ENODEV; 2408*ecc31b6eSAndy Yan } 2409*ecc31b6eSAndy Yan 2410*ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER) 2411*ecc31b6eSAndy Yan vop2_set_cluster_win(state, win_data); 2412*ecc31b6eSAndy Yan else 2413*ecc31b6eSAndy Yan vop2_set_smart_win(state, win_data); 24148895aec1SSandy Huang 24158895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 24168895aec1SSandy Huang cstate->crtc_id, get_plane_name(primary_plane_id, plane_name), 2417*ecc31b6eSAndy Yan cstate->src_w, cstate->src_h, cstate->crtc_w, cstate->crtc_h, 2418*ecc31b6eSAndy Yan cstate->crtc_x, cstate->crtc_y, cstate->format, 24198895aec1SSandy Huang cstate->dma_addr); 24208895aec1SSandy Huang 2421d0408543SAndy Yan return 0; 2422d0408543SAndy Yan } 2423d0408543SAndy Yan 2424d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state) 2425d0408543SAndy Yan { 2426d0408543SAndy Yan return 0; 2427d0408543SAndy Yan } 2428d0408543SAndy Yan 2429d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state) 2430d0408543SAndy Yan { 2431d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2432d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 243352ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2434*ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2435d0408543SAndy Yan 2436d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2437d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false); 2438d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2439d0408543SAndy Yan 2440d0408543SAndy Yan return 0; 2441d0408543SAndy Yan } 2442d0408543SAndy Yan 2443d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state) 2444d0408543SAndy Yan { 2445d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2446d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 244752ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2448*ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2449d0408543SAndy Yan 2450d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2451d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false); 2452d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2453d0408543SAndy Yan 2454d0408543SAndy Yan return 0; 2455d0408543SAndy Yan } 2456d0408543SAndy Yan 2457ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 2458ee008497SSandy Huang { 2459ee008497SSandy Huang struct crtc_state *cstate = &state->crtc_state; 2460ee008497SSandy Huang struct vop2 *vop2 = cstate->private; 2461ee008497SSandy Huang int i = 0; 2462ee008497SSandy Huang int correct_cursor_plane = -1; 2463ee008497SSandy Huang int plane_type = -1; 2464ee008497SSandy Huang 2465ee008497SSandy Huang if (cursor_plane < 0) 2466ee008497SSandy Huang return -1; 2467ee008497SSandy Huang 2468ee008497SSandy Huang if (plane_mask & (1 << cursor_plane)) 2469ee008497SSandy Huang return cursor_plane; 2470ee008497SSandy Huang 2471ee008497SSandy Huang /* Get current cursor plane type */ 2472ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 2473ee008497SSandy Huang if (vop2->data->plane_table[i].plane_id == cursor_plane) { 2474ee008497SSandy Huang plane_type = vop2->data->plane_table[i].plane_type; 2475ee008497SSandy Huang break; 2476ee008497SSandy Huang } 2477ee008497SSandy Huang } 2478ee008497SSandy Huang 2479ee008497SSandy Huang /* Get the other same plane type plane id */ 2480ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 2481ee008497SSandy Huang if (vop2->data->plane_table[i].plane_type == plane_type && 2482ee008497SSandy Huang vop2->data->plane_table[i].plane_id != cursor_plane) { 2483ee008497SSandy Huang correct_cursor_plane = vop2->data->plane_table[i].plane_id; 2484ee008497SSandy Huang break; 2485ee008497SSandy Huang } 2486ee008497SSandy Huang } 2487ee008497SSandy Huang 2488ee008497SSandy Huang /* To check whether the new correct_cursor_plane is attach to current vp */ 2489ee008497SSandy Huang if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 2490ee008497SSandy Huang printf("error: faild to find correct plane as cursor plane\n"); 2491ee008497SSandy Huang return -1; 2492ee008497SSandy Huang } 2493ee008497SSandy Huang 2494ee008497SSandy Huang printf("vp%d adjust cursor plane from %d to %d\n", 2495ee008497SSandy Huang cstate->crtc_id, cursor_plane, correct_cursor_plane); 2496ee008497SSandy Huang 2497ee008497SSandy Huang return correct_cursor_plane; 2498ee008497SSandy Huang } 2499ee008497SSandy Huang 2500b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 2501b0989546SSandy Huang { 2502b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 2503b0989546SSandy Huang struct vop2 *vop2 = cstate->private; 2504b0989546SSandy Huang ofnode vp_node; 2505b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node; 2506b0989546SSandy Huang static bool vop_fix_dts; 2507b0989546SSandy Huang const char *path; 2508b0989546SSandy Huang u32 plane_mask = 0; 2509b0989546SSandy Huang int vp_id = 0; 2510ee008497SSandy Huang int cursor_plane_id = -1; 2511b0989546SSandy Huang 2512b0989546SSandy Huang if (vop_fix_dts) 2513b0989546SSandy Huang return 0; 2514b0989546SSandy Huang 2515b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 2516b0989546SSandy Huang path = vp_node.np->full_name; 2517b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 2518b0989546SSandy Huang 25198b1fe597SSandy Huang if (cstate->crtc->assign_plane) 25208b1fe597SSandy Huang continue; 2521ee008497SSandy Huang cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 2522ee008497SSandy Huang cstate->crtc->vps[vp_id].cursor_plane); 2523ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 2524b0989546SSandy Huang vp_id, plane_mask, 2525ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 2526ee008497SSandy Huang cursor_plane_id); 2527b0989546SSandy Huang 2528b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 2529b0989546SSandy Huang plane_mask, 1); 2530b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 2531b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 2532ee008497SSandy Huang if (cursor_plane_id >= 0) 2533ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id", 2534ee008497SSandy Huang cursor_plane_id, 1); 2535b0989546SSandy Huang vp_id++; 2536b0989546SSandy Huang } 2537b0989546SSandy Huang 2538b0989546SSandy Huang vop_fix_dts = true; 2539b0989546SSandy Huang 2540b0989546SSandy Huang return 0; 2541b0989546SSandy Huang } 2542b0989546SSandy Huang 2543ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 2544ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 2545ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 2546ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 2547ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 2548ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 2549ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 2550ee008497SSandy Huang }; 2551ee008497SSandy Huang 2552b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 2553b0989546SSandy Huang { /* one display policy */ 2554b0989546SSandy Huang {/* main display */ 2555b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 2556b0989546SSandy Huang .attached_layers_nr = 6, 2557b0989546SSandy Huang .attached_layers = { 2558b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 2559b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 2560b0989546SSandy Huang }, 2561b0989546SSandy Huang }, 2562b0989546SSandy Huang {/* second display */}, 2563b0989546SSandy Huang {/* third display */}, 2564b0989546SSandy Huang {/* fourth display */}, 2565b0989546SSandy Huang }, 2566b0989546SSandy Huang 2567b0989546SSandy Huang { /* two display policy */ 2568b0989546SSandy Huang {/* main display */ 2569b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 2570b0989546SSandy Huang .attached_layers_nr = 3, 2571b0989546SSandy Huang .attached_layers = { 2572b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 2573b0989546SSandy Huang }, 2574b0989546SSandy Huang }, 2575b0989546SSandy Huang 2576b0989546SSandy Huang {/* second display */ 2577b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 2578b0989546SSandy Huang .attached_layers_nr = 3, 2579b0989546SSandy Huang .attached_layers = { 2580b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 2581b0989546SSandy Huang }, 2582b0989546SSandy Huang }, 2583b0989546SSandy Huang {/* third display */}, 2584b0989546SSandy Huang {/* fourth display */}, 2585b0989546SSandy Huang }, 2586b0989546SSandy Huang 2587b0989546SSandy Huang { /* three display policy */ 2588b0989546SSandy Huang {/* main display */ 2589b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 2590b0989546SSandy Huang .attached_layers_nr = 3, 2591b0989546SSandy Huang .attached_layers = { 2592b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 2593b0989546SSandy Huang }, 2594b0989546SSandy Huang }, 2595b0989546SSandy Huang 2596b0989546SSandy Huang {/* second display */ 2597b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 2598b0989546SSandy Huang .attached_layers_nr = 2, 2599b0989546SSandy Huang .attached_layers = { 2600b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 2601b0989546SSandy Huang }, 2602b0989546SSandy Huang }, 2603b0989546SSandy Huang 2604b0989546SSandy Huang {/* third display */ 2605b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 2606b0989546SSandy Huang .attached_layers_nr = 1, 2607b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 2608b0989546SSandy Huang }, 2609b0989546SSandy Huang 2610b0989546SSandy Huang {/* fourth display */}, 2611b0989546SSandy Huang }, 2612b0989546SSandy Huang 2613b0989546SSandy Huang {/* reserved for four display policy */}, 2614b0989546SSandy Huang }; 2615b0989546SSandy Huang 2616b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = { 2617b0989546SSandy Huang { 2618b0989546SSandy Huang .name = "Cluster0", 2619b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0, 2620*ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 2621b0989546SSandy Huang .win_sel_port_offset = 0, 2622b0989546SSandy Huang .layer_sel_win_id = 0, 2623b0989546SSandy Huang .reg_offset = 0, 2624b0989546SSandy Huang }, 2625b0989546SSandy Huang 2626b0989546SSandy Huang { 2627b0989546SSandy Huang .name = "Cluster1", 2628b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1, 2629*ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 2630b0989546SSandy Huang .win_sel_port_offset = 1, 2631b0989546SSandy Huang .layer_sel_win_id = 1, 2632b0989546SSandy Huang .reg_offset = 0x200, 2633b0989546SSandy Huang }, 2634b0989546SSandy Huang 2635b0989546SSandy Huang { 2636b0989546SSandy Huang .name = "Esmart0", 2637b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0, 2638*ecc31b6eSAndy Yan .type = ESMART_LAYER, 2639b0989546SSandy Huang .win_sel_port_offset = 4, 2640b0989546SSandy Huang .layer_sel_win_id = 2, 2641b0989546SSandy Huang .reg_offset = 0, 2642b0989546SSandy Huang }, 2643b0989546SSandy Huang 2644b0989546SSandy Huang { 2645b0989546SSandy Huang .name = "Esmart1", 2646b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1, 2647*ecc31b6eSAndy Yan .type = ESMART_LAYER, 2648b0989546SSandy Huang .win_sel_port_offset = 5, 2649b0989546SSandy Huang .layer_sel_win_id = 6, 2650b0989546SSandy Huang .reg_offset = 0x200, 2651b0989546SSandy Huang }, 2652b0989546SSandy Huang 2653b0989546SSandy Huang { 2654b0989546SSandy Huang .name = "Smart0", 2655b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0, 2656*ecc31b6eSAndy Yan .type = SMART_LAYER, 2657b0989546SSandy Huang .win_sel_port_offset = 6, 2658b0989546SSandy Huang .layer_sel_win_id = 3, 2659b0989546SSandy Huang .reg_offset = 0x400, 2660b0989546SSandy Huang }, 2661b0989546SSandy Huang 2662b0989546SSandy Huang { 2663b0989546SSandy Huang .name = "Smart1", 2664b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1, 2665*ecc31b6eSAndy Yan .type = SMART_LAYER, 2666b0989546SSandy Huang .win_sel_port_offset = 7, 2667b0989546SSandy Huang .layer_sel_win_id = 7, 2668b0989546SSandy Huang .reg_offset = 0x600, 2669b0989546SSandy Huang }, 2670b0989546SSandy Huang }; 2671b0989546SSandy Huang 267263cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = { 267363cb669fSSandy Huang { 267463cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT, 267563cb669fSSandy Huang .pre_scan_max_dly = 42, 267663cb669fSSandy Huang .max_output = {4096, 2304}, 2677d0408543SAndy Yan }, 267863cb669fSSandy Huang { 267963cb669fSSandy Huang .feature = 0, 268063cb669fSSandy Huang .pre_scan_max_dly = 40, 268163cb669fSSandy Huang .max_output = {2048, 1536}, 268263cb669fSSandy Huang }, 268363cb669fSSandy Huang { 268463cb669fSSandy Huang .feature = 0, 268563cb669fSSandy Huang .pre_scan_max_dly = 40, 268663cb669fSSandy Huang .max_output = {1920, 1080}, 268763cb669fSSandy Huang }, 268863cb669fSSandy Huang }; 2689d0408543SAndy Yan 269063cb669fSSandy Huang const struct vop2_data rk3568_vop = { 2691*ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568, 269263cb669fSSandy Huang .nr_vps = 3, 269363cb669fSSandy Huang .vp_data = rk3568_vp_data, 2694b0989546SSandy Huang .win_data = rk3568_win_data, 2695b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0], 2696ee008497SSandy Huang .plane_table = rk356x_plane_table, 2697d0408543SAndy Yan .nr_layers = 6, 269863cb669fSSandy Huang .nr_mixers = 5, 26991147facaSSandy Huang .nr_gammas = 1, 2700d0408543SAndy Yan }; 2701d0408543SAndy Yan 2702*ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 2703*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 2704*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 2705*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 2706*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 2707*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 2708*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 2709*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 2710*ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 2711*ecc31b6eSAndy Yan }; 2712*ecc31b6eSAndy Yan 2713*ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 2714*ecc31b6eSAndy Yan { /* one display policy */ 2715*ecc31b6eSAndy Yan {/* main display */ 2716*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2717*ecc31b6eSAndy Yan .attached_layers_nr = 8, 2718*ecc31b6eSAndy Yan .attached_layers = { 2719*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, 2720*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, 2721*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 2722*ecc31b6eSAndy Yan }, 2723*ecc31b6eSAndy Yan }, 2724*ecc31b6eSAndy Yan {/* second display */}, 2725*ecc31b6eSAndy Yan {/* third display */}, 2726*ecc31b6eSAndy Yan {/* fourth display */}, 2727*ecc31b6eSAndy Yan }, 2728*ecc31b6eSAndy Yan 2729*ecc31b6eSAndy Yan { /* two display policy */ 2730*ecc31b6eSAndy Yan {/* main display */ 2731*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2732*ecc31b6eSAndy Yan .attached_layers_nr = 4, 2733*ecc31b6eSAndy Yan .attached_layers = { 2734*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 2735*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 2736*ecc31b6eSAndy Yan }, 2737*ecc31b6eSAndy Yan }, 2738*ecc31b6eSAndy Yan 2739*ecc31b6eSAndy Yan {/* second display */ 2740*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 2741*ecc31b6eSAndy Yan .attached_layers_nr = 4, 2742*ecc31b6eSAndy Yan .attached_layers = { 2743*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, 2744*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 2745*ecc31b6eSAndy Yan }, 2746*ecc31b6eSAndy Yan }, 2747*ecc31b6eSAndy Yan {/* third display */}, 2748*ecc31b6eSAndy Yan {/* fourth display */}, 2749*ecc31b6eSAndy Yan }, 2750*ecc31b6eSAndy Yan 2751*ecc31b6eSAndy Yan { /* three display policy */ 2752*ecc31b6eSAndy Yan {/* main display */ 2753*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2754*ecc31b6eSAndy Yan .attached_layers_nr = 3, 2755*ecc31b6eSAndy Yan .attached_layers = { 2756*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 2757*ecc31b6eSAndy Yan }, 2758*ecc31b6eSAndy Yan }, 2759*ecc31b6eSAndy Yan 2760*ecc31b6eSAndy Yan {/* second display */ 2761*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 2762*ecc31b6eSAndy Yan .attached_layers_nr = 3, 2763*ecc31b6eSAndy Yan .attached_layers = { 2764*ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 2765*ecc31b6eSAndy Yan }, 2766*ecc31b6eSAndy Yan }, 2767*ecc31b6eSAndy Yan 2768*ecc31b6eSAndy Yan {/* third display */ 2769*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 2770*ecc31b6eSAndy Yan .attached_layers_nr = 2, 2771*ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 2772*ecc31b6eSAndy Yan }, 2773*ecc31b6eSAndy Yan 2774*ecc31b6eSAndy Yan {/* fourth display */}, 2775*ecc31b6eSAndy Yan }, 2776*ecc31b6eSAndy Yan 2777*ecc31b6eSAndy Yan { /* four display policy */ 2778*ecc31b6eSAndy Yan {/* main display */ 2779*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2780*ecc31b6eSAndy Yan .attached_layers_nr = 2, 2781*ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 2782*ecc31b6eSAndy Yan }, 2783*ecc31b6eSAndy Yan 2784*ecc31b6eSAndy Yan {/* second display */ 2785*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER1, 2786*ecc31b6eSAndy Yan .attached_layers_nr = 2, 2787*ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 2788*ecc31b6eSAndy Yan }, 2789*ecc31b6eSAndy Yan 2790*ecc31b6eSAndy Yan {/* third display */ 2791*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 2792*ecc31b6eSAndy Yan .attached_layers_nr = 2, 2793*ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 2794*ecc31b6eSAndy Yan }, 2795*ecc31b6eSAndy Yan 2796*ecc31b6eSAndy Yan {/* fourth display */ 2797*ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER3, 2798*ecc31b6eSAndy Yan .attached_layers_nr = 2, 2799*ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 2800*ecc31b6eSAndy Yan }, 2801*ecc31b6eSAndy Yan }, 2802*ecc31b6eSAndy Yan 2803*ecc31b6eSAndy Yan }; 2804*ecc31b6eSAndy Yan 2805*ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = { 2806*ecc31b6eSAndy Yan { 2807*ecc31b6eSAndy Yan .name = "Cluster0", 2808*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0, 2809*ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 2810*ecc31b6eSAndy Yan .win_sel_port_offset = 0, 2811*ecc31b6eSAndy Yan .layer_sel_win_id = 0, 2812*ecc31b6eSAndy Yan .reg_offset = 0, 2813*ecc31b6eSAndy Yan }, 2814*ecc31b6eSAndy Yan 2815*ecc31b6eSAndy Yan { 2816*ecc31b6eSAndy Yan .name = "Cluster1", 2817*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1, 2818*ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 2819*ecc31b6eSAndy Yan .win_sel_port_offset = 1, 2820*ecc31b6eSAndy Yan .layer_sel_win_id = 1, 2821*ecc31b6eSAndy Yan .reg_offset = 0x200, 2822*ecc31b6eSAndy Yan }, 2823*ecc31b6eSAndy Yan 2824*ecc31b6eSAndy Yan { 2825*ecc31b6eSAndy Yan .name = "Cluster2", 2826*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2, 2827*ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 2828*ecc31b6eSAndy Yan .win_sel_port_offset = 2, 2829*ecc31b6eSAndy Yan .layer_sel_win_id = 4, 2830*ecc31b6eSAndy Yan .reg_offset = 0x400, 2831*ecc31b6eSAndy Yan }, 2832*ecc31b6eSAndy Yan 2833*ecc31b6eSAndy Yan { 2834*ecc31b6eSAndy Yan .name = "Cluster3", 2835*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3, 2836*ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 2837*ecc31b6eSAndy Yan .win_sel_port_offset = 3, 2838*ecc31b6eSAndy Yan .layer_sel_win_id = 5, 2839*ecc31b6eSAndy Yan .reg_offset = 0x600, 2840*ecc31b6eSAndy Yan }, 2841*ecc31b6eSAndy Yan 2842*ecc31b6eSAndy Yan { 2843*ecc31b6eSAndy Yan .name = "Esmart0", 2844*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0, 2845*ecc31b6eSAndy Yan .type = ESMART_LAYER, 2846*ecc31b6eSAndy Yan .win_sel_port_offset = 4, 2847*ecc31b6eSAndy Yan .layer_sel_win_id = 2, 2848*ecc31b6eSAndy Yan .reg_offset = 0, 2849*ecc31b6eSAndy Yan }, 2850*ecc31b6eSAndy Yan 2851*ecc31b6eSAndy Yan { 2852*ecc31b6eSAndy Yan .name = "Esmart1", 2853*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1, 2854*ecc31b6eSAndy Yan .type = ESMART_LAYER, 2855*ecc31b6eSAndy Yan .win_sel_port_offset = 5, 2856*ecc31b6eSAndy Yan .layer_sel_win_id = 3, 2857*ecc31b6eSAndy Yan .reg_offset = 0x200, 2858*ecc31b6eSAndy Yan }, 2859*ecc31b6eSAndy Yan 2860*ecc31b6eSAndy Yan { 2861*ecc31b6eSAndy Yan .name = "Esmart2", 2862*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2, 2863*ecc31b6eSAndy Yan .type = ESMART_LAYER, 2864*ecc31b6eSAndy Yan .win_sel_port_offset = 6, 2865*ecc31b6eSAndy Yan .layer_sel_win_id = 6, 2866*ecc31b6eSAndy Yan .reg_offset = 0x400, 2867*ecc31b6eSAndy Yan }, 2868*ecc31b6eSAndy Yan 2869*ecc31b6eSAndy Yan { 2870*ecc31b6eSAndy Yan .name = "Esmart3", 2871*ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3, 2872*ecc31b6eSAndy Yan .type = ESMART_LAYER, 2873*ecc31b6eSAndy Yan .win_sel_port_offset = 7, 2874*ecc31b6eSAndy Yan .layer_sel_win_id = 7, 2875*ecc31b6eSAndy Yan .reg_offset = 0x600, 2876*ecc31b6eSAndy Yan }, 2877*ecc31b6eSAndy Yan }; 2878*ecc31b6eSAndy Yan 2879*ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = { 2880*ecc31b6eSAndy Yan { 2881*ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 2882*ecc31b6eSAndy Yan .pre_scan_max_dly = 42, 2883*ecc31b6eSAndy Yan .max_dclk = 600000, 2884*ecc31b6eSAndy Yan .max_output = {7680, 4320}, 2885*ecc31b6eSAndy Yan }, 2886*ecc31b6eSAndy Yan { 2887*ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 2888*ecc31b6eSAndy Yan .pre_scan_max_dly = 40, 2889*ecc31b6eSAndy Yan .max_dclk = 600000, 2890*ecc31b6eSAndy Yan .max_output = {4096, 2304}, 2891*ecc31b6eSAndy Yan }, 2892*ecc31b6eSAndy Yan { 2893*ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 2894*ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 2895*ecc31b6eSAndy Yan .max_dclk = 600000, 2896*ecc31b6eSAndy Yan .max_output = {4096, 2304}, 2897*ecc31b6eSAndy Yan }, 2898*ecc31b6eSAndy Yan { 2899*ecc31b6eSAndy Yan .feature = 0, 2900*ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 2901*ecc31b6eSAndy Yan .max_dclk = 200000, 2902*ecc31b6eSAndy Yan .max_output = {1920, 1080}, 2903*ecc31b6eSAndy Yan }, 2904*ecc31b6eSAndy Yan }; 2905*ecc31b6eSAndy Yan 2906*ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = { 2907*ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588, 2908*ecc31b6eSAndy Yan .nr_vps = 4, 2909*ecc31b6eSAndy Yan .vp_data = rk3588_vp_data, 2910*ecc31b6eSAndy Yan .win_data = rk3588_win_data, 2911*ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0], 2912*ecc31b6eSAndy Yan .plane_table = rk3588_plane_table, 2913*ecc31b6eSAndy Yan .nr_layers = 8, 2914*ecc31b6eSAndy Yan .nr_mixers = 7, 2915*ecc31b6eSAndy Yan .nr_gammas = 4, 2916*ecc31b6eSAndy Yan .nr_dscs = 2, 2917*ecc31b6eSAndy Yan }; 2918*ecc31b6eSAndy Yan 2919d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 2920d0408543SAndy Yan .preinit = rockchip_vop2_preinit, 2921d0408543SAndy Yan .prepare = rockchip_vop2_prepare, 2922d0408543SAndy Yan .init = rockchip_vop2_init, 2923d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane, 2924d0408543SAndy Yan .enable = rockchip_vop2_enable, 2925d0408543SAndy Yan .disable = rockchip_vop2_disable, 2926b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts, 2927d0408543SAndy Yan }; 2928