1d0408543SAndy Yan // SPDX-License-Identifier: GPL-2.0-only 2d0408543SAndy Yan /* 3d0408543SAndy Yan * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 4d0408543SAndy Yan * 5d0408543SAndy Yan */ 6d0408543SAndy Yan 7d0408543SAndy Yan #include <config.h> 8d0408543SAndy Yan #include <common.h> 9d0408543SAndy Yan #include <errno.h> 10d0408543SAndy Yan #include <malloc.h> 11d0408543SAndy Yan #include <fdtdec.h> 12d0408543SAndy Yan #include <fdt_support.h> 13b890760eSAlgea Cao #include <regmap.h> 14feffd38eSSandy Huang #include <asm/arch/cpu.h> 15d0408543SAndy Yan #include <asm/unaligned.h> 16d0408543SAndy Yan #include <asm/io.h> 17d0408543SAndy Yan #include <linux/list.h> 18ecc31b6eSAndy Yan #include <linux/log2.h> 19d0408543SAndy Yan #include <linux/media-bus-format.h> 20d0408543SAndy Yan #include <clk.h> 21d0408543SAndy Yan #include <asm/arch/clock.h> 228e7ef808SDamon Ding #include <asm/gpio.h> 23d0408543SAndy Yan #include <linux/err.h> 241147facaSSandy Huang #include <linux/ioport.h> 25d0408543SAndy Yan #include <dm/device.h> 26d0408543SAndy Yan #include <dm/read.h> 275fa6e665SDamon Ding #include <dm/ofnode.h> 28ac500a1fSSandy Huang #include <fixp-arith.h> 29d0408543SAndy Yan #include <syscon.h> 3060e469f5SDamon Ding #include <linux/iopoll.h> 315f1357a2SZhang Yubing #include <dm/uclass-internal.h> 32452afb13SDamon Ding #include <stdlib.h> 33d0408543SAndy Yan 34d0408543SAndy Yan #include "rockchip_display.h" 35d0408543SAndy Yan #include "rockchip_crtc.h" 36d0408543SAndy Yan #include "rockchip_connector.h" 37*d8e7f4a5SSandy Huang #include "rockchip_phy.h" 386027c871SZhang Yubing #include "rockchip_post_csc.h" 39d0408543SAndy Yan 40d0408543SAndy Yan /* System registers definition */ 41d0408543SAndy Yan #define RK3568_REG_CFG_DONE 0x000 42d0408543SAndy Yan #define CFG_DONE_EN BIT(15) 43d0408543SAndy Yan 44d0408543SAndy Yan #define RK3568_VERSION_INFO 0x004 45d0408543SAndy Yan #define EN_MASK 1 46d0408543SAndy Yan 4763cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL 0x008 4863cb669fSSandy Huang 496414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL 0x024 506414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT 0 51aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT 16 526414e3bcSSandy Huang 53d0408543SAndy Yan #define RK3568_DSP_IF_EN 0x028 54d0408543SAndy Yan #define RGB_EN_SHIFT 0 55ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT 0 56ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT 1 57ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT 8 58d0408543SAndy Yan #define HDMI0_EN_SHIFT 1 59d0408543SAndy Yan #define EDP0_EN_SHIFT 3 60ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT 2 61ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT 3 62d0408543SAndy Yan #define MIPI0_EN_SHIFT 4 63ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT 4 64ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT 5 65ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT 6 66d0408543SAndy Yan #define MIPI1_EN_SHIFT 20 67ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT 7 68d0408543SAndy Yan #define LVDS0_EN_SHIFT 5 69d0408543SAndy Yan #define LVDS1_EN_SHIFT 24 70d0408543SAndy Yan #define BT1120_EN_SHIFT 6 71d0408543SAndy Yan #define BT656_EN_SHIFT 7 72d0408543SAndy Yan #define IF_MUX_MASK 3 73d0408543SAndy Yan #define RGB_MUX_SHIFT 8 74d0408543SAndy Yan #define HDMI0_MUX_SHIFT 10 75ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT 12 76ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT 14 77d0408543SAndy Yan #define EDP0_MUX_SHIFT 14 78ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT 16 79ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT 18 80d0408543SAndy Yan #define MIPI0_MUX_SHIFT 16 81ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT 20 82d0408543SAndy Yan #define MIPI1_MUX_SHIFT 21 8311f53190SSandy Huang #define LVDS0_MUX_SHIFT 18 84d0408543SAndy Yan #define LVDS1_MUX_SHIFT 25 85d0408543SAndy Yan 86d0408543SAndy Yan #define RK3568_DSP_IF_CTRL 0x02c 87d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT 0 88d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 89d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT 2 905fa6e665SDamon Ding #define BT656_UV_SWAP 4 915fa6e665SDamon Ding #define BT656_YC_SWAP 5 925fa6e665SDamon Ding #define BT656_DCLK_POL 6 930a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT 8 940a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT 8 950a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT 9 9641874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT 10 9741874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11 9841874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12 9941874944SGuochun Huang 100d0408543SAndy Yan #define RK3568_DSP_IF_POL 0x030 101d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_MASK 1 102d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT 28 103d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 104d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT 15 1057bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_MASK 0x7 1067bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_SHIFT 12 107d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 10810ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 10910ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT 4 11015f69071SDamon Ding #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT 3 11115f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_MASK 0x7 11215f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT 0 113ecc31b6eSAndy Yan 114452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT 15 115452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT 12 116452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK 0x7 117452afb13SDamon Ding 118ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT 8 119ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT 12 120ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK 0x7 121ecc31b6eSAndy Yan 122ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT 16 123ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 124ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT 20 125ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 126ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT 24 127ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT 26 128ecc31b6eSAndy Yan 129feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN 0x50 130feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT 0 1311147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL 0x58 1321147facaSSandy Huang #define GAMMA_PORT_SEL_MASK 0x3 1331147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT 0 134db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK 0x3 135db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT 12 136ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT 16 1375fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK 0x3 1385fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT 26 1391147facaSSandy Huang 140ecc31b6eSAndy Yan #define RK3568_SYS_PD_CTRL 0x034 141d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG 0x70 142d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG 0x74 143d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG 0x78 144d0408543SAndy Yan #define RK3568_SYS0_INT_EN 0x80 145d0408543SAndy Yan #define RK3568_SYS0_INT_CLR 0x84 146d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS 0x88 147d0408543SAndy Yan #define RK3568_SYS1_INT_EN 0x90 148d0408543SAndy Yan #define RK3568_SYS1_INT_CLR 0x94 149d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS 0x98 150d0408543SAndy Yan #define RK3568_VP0_INT_EN 0xA0 151d0408543SAndy Yan #define RK3568_VP0_INT_CLR 0xA4 152d0408543SAndy Yan #define RK3568_VP0_INT_STATUS 0xA8 153d0408543SAndy Yan #define RK3568_VP1_INT_EN 0xB0 154d0408543SAndy Yan #define RK3568_VP1_INT_CLR 0xB4 155d0408543SAndy Yan #define RK3568_VP1_INT_STATUS 0xB8 156d0408543SAndy Yan #define RK3568_VP2_INT_EN 0xC0 157d0408543SAndy Yan #define RK3568_VP2_INT_CLR 0xC4 158d0408543SAndy Yan #define RK3568_VP2_INT_STATUS 0xC8 15960e469f5SDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT 0 16060e469f5SDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT 1 16160e469f5SDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT 2 16260e469f5SDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT 3 163b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT 5 164b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT 6 16560e469f5SDamon Ding #define RK3588_ESMART_PD_EN_SHIFT 7 16660e469f5SDamon Ding 167cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL 0x038 168cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT 20 169cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT 24 170cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT 28 171cd6c85a9SDamon Ding 17260e469f5SDamon Ding #define RK3568_SYS_STATUS0 0x60 17360e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8 17460e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9 17560e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10 17660e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11 177b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT 13 178b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT 14 17960e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT 15 180d0408543SAndy Yan 18166724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0 0x70 18266724b9cSDamon Ding #define LINE_FLAG_NUM_MASK 0x1fff 18366724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0 18466724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16 18566724b9cSDamon Ding 18612ee5af0SDamon Ding /* DSC CTRL registers definition */ 18712ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL 0x200 18812ee5af0SDamon Ding #define DSC_PORT_SEL_MASK 0x3 18912ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT 0 19012ee5af0SDamon Ding #define DSC_MAN_MODE_MASK 0x1 19112ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT 2 19212ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK 0x3 19312ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT 4 19412ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK 0x3 19512ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT 6 19612ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK 0x1 19712ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT 8 19812ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK 0x3 19912ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT 12 20012ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK 0x3 20112ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT 14 20212ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK 0x1 20312ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT 16 20412ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT 17 20512ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT 18 20612ee5af0SDamon Ding 20712ee5af0SDamon Ding #define RK3588_DSC_8K_RST 0x204 20812ee5af0SDamon Ding #define RST_DEASSERT_MASK 0x1 20912ee5af0SDamon Ding #define RST_DEASSERT_SHIFT 0 21012ee5af0SDamon Ding 21112ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE 0x208 21212ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT 0 21312ee5af0SDamon Ding 21412ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY 0x20C 21512ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK 0xffff 21612ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT 0 21712ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16 21812ee5af0SDamon Ding 21912ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END 0x210 22012ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK 0xffffffff 22112ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT 0 22212ee5af0SDamon Ding 22312ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END 0x214 22412ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK 0xffffffff 22512ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT 0 22612ee5af0SDamon Ding 22712ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END 0x218 22812ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK 0xffffffff 22912ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT 0 23012ee5af0SDamon Ding 23112ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END 0x21C 23212ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK 0xffffffff 23312ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT 0 23412ee5af0SDamon Ding 23512ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS 0x220 23612ee5af0SDamon Ding 23763cb669fSSandy Huang /* Overlay registers definition */ 2385fa6e665SDamon Ding #define RK3528_OVL_SYS 0x500 2395fa6e665SDamon Ding #define RK3528_OVL_SYS_PORT_SEL_IMD 0x504 2405fa6e665SDamon Ding #define RK3528_OVL_SYS_GATING_EN_IMD 0x508 2415fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL 0x510 2425fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL 0x520 243452afb13SDamon Ding #define ESMART_DLY_NUM_MASK 0xff 244452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT 0 2455fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL 0x524 2465fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL 0x528 2475fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C 2485fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530 2495fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 2505fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 2515fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c 2525fa6e665SDamon Ding 2535fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL 0x600 25463cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600 255ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK 0x1 256ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT 0 25763cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 2585fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL 0x604 25963cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604 26063cb669fSSandy Huang #define LAYER_SEL_MASK 0xf 26163cb669fSSandy Huang 26263cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608 26363cb669fSSandy Huang #define PORT_MUX_MASK 0xf 26463cb669fSSandy Huang #define PORT_MUX_SHIFT 0 26563cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3 26663cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16 26763cb669fSSandy Huang 26863cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 26963cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 27063cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 27163cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 2725fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620 2735fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624 2745fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628 2755fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C 2765fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630 2775fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634 2785fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638 2795fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C 2805fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640 2815fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644 2825fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648 2835fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C 28463cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 28563cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654 28663cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 28763cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 2885fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL 0x660 2895fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL 0x664 2905fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL 0x668 2915fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL 0x66C 2925fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670 29363cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 29463cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 29563cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 29663cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 29763cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0 29863cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff 29963cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24 30063cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4 30163cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8 30263cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0 30363cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8 30463cb669fSSandy Huang 3055fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL 0x700 3065fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL 0x704 3075fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720 3085fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724 3095fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728 3105fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C 3115fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730 3125fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734 3135fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738 3145fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C 3155fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740 3165fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744 3175fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748 3185fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C 3195fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770 3205fa6e665SDamon Ding 321d0408543SAndy Yan /* Video Port registers definition */ 322d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00 323d0408543SAndy Yan #define OUT_MODE_MASK 0xf 324d0408543SAndy Yan #define OUT_MODE_SHIFT 0 32510ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f 32610ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8 32765747de7SDamon Ding #define DSP_BG_SWAP 0x1 32865747de7SDamon Ding #define DSP_RB_SWAP 0x2 32965747de7SDamon Ding #define DSP_RG_SWAP 0x4 33065747de7SDamon Ding #define DSP_DELTA_SWAP 0x8 33110ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4 332d0408543SAndy Yan #define P2I_EN_SHIFT 5 3337a20be36SSandy Huang #define DSP_FILED_POL 6 334d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7 335c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT 13 33610ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15 337d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16 338d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17 339452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT 20 340db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT 22 3411147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28 3421147facaSSandy Huang 343d0408543SAndy Yan #define STANDBY_EN_SHIFT 31 344d0408543SAndy Yan 345d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04 34610ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4 34710ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3 348d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20 349d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21 35041874944SGuochun Huang #define EDPI_TE_EN 28 35141874944SGuochun Huang #define EDPI_WMS_HOLD_EN 30 35241874944SGuochun Huang #define EDPI_WMS_FS 31 35341874944SGuochun Huang 354d0408543SAndy Yan 355d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 3565fa6e665SDamon Ding 3575fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL 0xC0C 3585fa6e665SDamon Ding 3596414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10 3606414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0 3616414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2 3626414e3bcSSandy Huang 363ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C 364ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0 365ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2 366ecc31b6eSAndy Yan 3676414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20 3686414e3bcSSandy Huang 369d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C 370d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 371d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 372d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 373d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 374d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40 375d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 376d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 377d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 378d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 379d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54 380d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 381d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 382d0408543SAndy Yan 383ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60 384ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0 385ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1 386ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 387ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 388ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4 389ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1 390ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 391ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 392ac500a1fSSandy Huang 393ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64 394ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0 395ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF 396ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8 397ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF 398ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20 399ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF 400ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30 401ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3 402ac500a1fSSandy Huang 403ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68 404ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0 405ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF 406ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16 407ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF 408ac500a1fSSandy Huang 409ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C 410ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31 411ac500a1fSSandy Huang #define BCSH_EN_MASK 1 412ac500a1fSSandy Huang 4136027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL 0xCD0 4146027c871SZhang Yubing #define POST_CSC_COE00_MASK 0xFFFF 4156027c871SZhang Yubing #define POST_CSC_COE00_SHIFT 16 4166027c871SZhang Yubing #define POST_R2Y_MODE_MASK 0x7 4176027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT 8 4186027c871SZhang Yubing #define POST_CSC_MODE_MASK 0x7 4196027c871SZhang Yubing #define POST_CSC_MODE_SHIFT 3 4206027c871SZhang Yubing #define POST_R2Y_EN_MASK 0x1 4216027c871SZhang Yubing #define POST_R2Y_EN_SHIFT 2 4226027c871SZhang Yubing #define POST_CSC_EN_MASK 0x1 4236027c871SZhang Yubing #define POST_CSC_EN_SHIFT 1 4246027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK 0x1 4256027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT 0 4266027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02 0xCD4 4276027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11 0xCD8 4286027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20 0xCDC 4296027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22 0xCE0 4306027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0 0xCE4 4316027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1 0xCE8 4326027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2 0xCEC 4336027c871SZhang Yubing 434d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00 435d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04 436d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 437d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 438d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 439d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 440d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 441d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40 442d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34 443d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38 444d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 445d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 446d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 447d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 448d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54 449d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 450d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 451d0408543SAndy Yan 452d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00 453d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04 454d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 455d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 456d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 457d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 458d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 459d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40 460d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34 461d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38 462d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 463d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 464d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 465d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 466d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54 467d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 468d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 469d0408543SAndy Yan 470d0408543SAndy Yan /* Cluster0 register definition */ 471d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 472ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8 473ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9 474ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10 475d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 4765fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12 4775fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 4785fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 4795fa6e665SDamon Ding #define AVG2_MASK 0x1 4805fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT 18 4815fa6e665SDamon Ding #define AVG4_MASK 0x1 4825fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT 19 4835fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22 4845fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT 24 4855fa6e665SDamon Ding #define XGT_MODE_MASK 0x3 4865fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT 25 4875fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT 27 488ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28 489ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29 490a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008 491a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK 0x1f 492a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT 0 493a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK 0x1f 494a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT 5 495a33b790fSDamon Ding 496d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 497d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 498d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018 499d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 500d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 501d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 502d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 503d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 504d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 505d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 506d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 507d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 508d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 509d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 510a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT 7 511d0408543SAndy Yan 512d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 513d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 514d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 515d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 516d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098 517d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 518d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 519d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 520d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 521d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 522d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 523d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 524d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 525d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 526d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 527d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 528d0408543SAndy Yan 529d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100 530ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0 531a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK 0x1 532a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT 13 533d0408543SAndy Yan 534d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 535d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 536d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 537d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 538d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218 539d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 540d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 541d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 542d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 543d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 544d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 545d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 546d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 547d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 548d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 549d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 550d0408543SAndy Yan 551d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 552d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 553d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 554d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 555d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298 556d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 557d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 558d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 559d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 560d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 561d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 562d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 563d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 564d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 565d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 566d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 567d0408543SAndy Yan 568d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300 569d0408543SAndy Yan 570d0408543SAndy Yan /* Esmart register definition */ 571d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800 57210ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1 57310ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2 57410ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3 5755fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT 12 5765fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK 0x3 577d0408543SAndy Yan 578d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804 579a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK 0x1f 580a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT 4 581a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK 0x1f 582a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT 12 583d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31 584a33b790fSDamon Ding 585a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL 0x1808 586a33b790fSDamon Ding #define ESMART_AXI_ID_MASK 0x1 587a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT 1 588a33b790fSDamon Ding 589d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810 590d0408543SAndy Yan #define WIN_EN_SHIFT 0 591d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f 592d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1 5935fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT 14 5945fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT 20 5955fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT 21 5965fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT 22 597d0408543SAndy Yan 598d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 599d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 600d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C 601d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 602d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 603d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 604d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 6053e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3 6063e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0 6073e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3 6083e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2 6093e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3 6103e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4 6113e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3 6123e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6 6133e39a5a1SSandy Huang 614d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 615d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 616d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 617d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840 6183e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1 6193e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8 6203e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1 6213e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9 6223e39a5a1SSandy Huang 623d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 624d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 625d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C 626d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 627d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 628d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 629d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 630d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 631d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 632d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 633d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870 634d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 635d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 636d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C 637d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 638d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 639d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 640d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 641d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 642d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 643d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 644d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0 645d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 646d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 647d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC 648d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 649d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 650d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 651d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 652d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 653d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 654d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 655d0408543SAndy Yan 656d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00 657d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04 658d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10 659d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 660d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 661d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C 662d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 663d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 664d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 665d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 666d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 667d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 668d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 669d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40 670d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 671d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 672d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C 673d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 674d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 675d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 676d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 677d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 678d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 679d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 680d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70 681d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 682d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 683d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C 684d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 685d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 686d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 687d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 688d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 689d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 690d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 691d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 692d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 693d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 694d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC 695d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 696d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 697d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 698d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 699d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 700d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 701d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 702d0408543SAndy Yan 703d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00 704d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04 705d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10 706d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 707d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 708d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C 709d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 710d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 711d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 712d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 713d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 714d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 715d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 716d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40 717d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 718d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 719d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C 720d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 721d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 722d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 723d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 724d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 725d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 726d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 727d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70 728d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 729d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 730d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C 731d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 732d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 733d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 734d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 735d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 736d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 737d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 738d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0 739d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 740d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 741d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC 742d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 743d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 744d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 745d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 746d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 747d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 748d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 749d0408543SAndy Yan 750d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00 751d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04 752d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10 753d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 754d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 755d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C 756d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 757d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 758d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 759d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 760d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 761d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 762d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 763d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40 764d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 765d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 766d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C 767d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 768d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 769d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 770d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 771d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 772d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 773d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 774d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70 775d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 776d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 777d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C 778d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 779d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 780d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 781d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 782d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 783d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 784d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 785d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0 786d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 787d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 788d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC 789d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 790d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 791d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 792d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 793d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 794d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 795d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 796d0408543SAndy Yan 79772388c26SDamon Ding /* HDR register definition */ 79872388c26SDamon Ding #define RK3568_HDR_LUT_CTRL 0x2000 79972388c26SDamon Ding 80072388c26SDamon Ding #define RK3588_VP3_DSP_CTRL 0xF00 80172388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400 80272388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0 0x1600 80372388c26SDamon Ding 80412ee5af0SDamon Ding /* DSC 8K/4K register definition */ 80512ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3 0x4000 80612ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0 0x40A0 80712ee5af0SDamon Ding #define DSC_EN_SHIFT 0 80812ee5af0SDamon Ding #define DSC_RBIT_SHIFT 2 80912ee5af0SDamon Ding #define DSC_RBYT_SHIFT 3 81012ee5af0SDamon Ding #define DSC_FLAL_SHIFT 4 81112ee5af0SDamon Ding #define DSC_MER_SHIFT 5 81212ee5af0SDamon Ding #define DSC_EPB_SHIFT 6 81312ee5af0SDamon Ding #define DSC_EPL_SHIFT 7 8141ace1b6dSDamon Ding #define DSC_NSLC_MASK 0x7 81512ee5af0SDamon Ding #define DSC_NSLC_SHIFT 16 81612ee5af0SDamon Ding #define DSC_SBO_SHIFT 28 81712ee5af0SDamon Ding #define DSC_IFEP_SHIFT 29 81812ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT 31 819baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \ 820baf2c414SDamon Ding (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \ 821baf2c414SDamon Ding (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT)) 82212ee5af0SDamon Ding 82312ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1 0x40A4 82412ee5af0SDamon Ding #define RK3588_DSC_8K_STS0 0x40A8 82512ee5af0SDamon Ding #define RK3588_DSC_8K_ERS 0x40C4 82612ee5af0SDamon Ding 82712ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3 0x4100 82812ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0 0x41A0 82912ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1 0x41A4 83012ee5af0SDamon Ding #define RK3588_DSC_4K_STS0 0x41A8 83112ee5af0SDamon Ding #define RK3588_DSC_4K_ERS 0x41C4 83212ee5af0SDamon Ding 83372388c26SDamon Ding /* RK3528 HDR register definition */ 83472388c26SDamon Ding #define RK3528_HDR_LUT_CTRL 0x2000 83572388c26SDamon Ding 8366027c871SZhang Yubing /* RK3528 ACM register definition */ 8376027c871SZhang Yubing #define RK3528_ACM_CTRL 0x6400 8386027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE 0x6404 8396027c871SZhang Yubing #define RK3528_ACM_FETCH_START 0x6408 8406027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE 0x6420 8416027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500 8426027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760 8436027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764 8446027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4 8456027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8 8466027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8 8476027c871SZhang Yubing 848d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0 849d0408543SAndy Yan 850452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON 0x10500 85152ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364 85252ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1 85352ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2 85452ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3 85552ee18acSSandy Huang 856ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008 857ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 858ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 859ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 860ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 861ecc31b6eSAndy Yan 862b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0 0x0000 863b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK 0x3 864b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT 5 865b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT 7 866b890760eSAlgea Cao 86760e469f5SDamon Ding #define RK3588_PMU_BISR_CON3 0x20C 86860e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 86960e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 87060e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 87160e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 872b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13 873b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14 87460e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 87560e469f5SDamon Ding 87660e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5 0x294 87760e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 87860e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 87960e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 88060e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 881b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13 882b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14 88360e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 88460e469f5SDamon Ding 885d0408543SAndy Yan #define VOP2_LAYER_MAX 8 88663cb669fSSandy Huang 887ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH 4096 888ee01dbb2SDamon Ding 88963cb669fSSandy Huang #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 890d0408543SAndy Yan 891631ee99aSZhang Yubing /* KHz */ 892631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE 600000 893631ee99aSZhang Yubing 894b6ba80b4SDamon Ding /* 895b6ba80b4SDamon Ding * vop2 dsc id 896b6ba80b4SDamon Ding */ 897b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K 0 898b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K 1 899b6ba80b4SDamon Ding 900b6ba80b4SDamon Ding /* 901b6ba80b4SDamon Ding * vop2 internal power domain id, 902b6ba80b4SDamon Ding * should be all none zero, 0 will be 903b6ba80b4SDamon Ding * treat as invalid; 904b6ba80b4SDamon Ding */ 905b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0 BIT(0) 906b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1 BIT(1) 907b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2 BIT(2) 908b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3 BIT(3) 909b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K BIT(5) 910b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K BIT(6) 911b6ba80b4SDamon Ding #define VOP2_PD_ESMART BIT(7) 912b6ba80b4SDamon Ding 9134c765862SDamon Ding #define VOP2_PLANE_NO_SCALING BIT(16) 9144c765862SDamon Ding 9155fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 9165fa6e665SDamon Ding #define VOP_FEATURE_AFBDC BIT(1) 9175fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE BIT(2) 9185fa6e665SDamon Ding #define VOP_FEATURE_HDR10 BIT(3) 9195fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR BIT(4) 9205fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */ 9215fa6e665SDamon Ding #define VOP_FEATURE_SPLICE BIT(5) 9225fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN BIT(6) 9236027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR BIT(7) 9246027c871SZhang Yubing #define VOP_FEATURE_POST_ACM BIT(8) 9256027c871SZhang Yubing #define VOP_FEATURE_POST_CSC BIT(9) 9265fa6e665SDamon Ding 9275fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR BIT(0) 9285fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR BIT(1) 9295fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY BIT(2) 9305fa6e665SDamon Ding #define WIN_FEATURE_AFBDC BIT(3) 9315fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN BIT(4) 9325fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB BIT(5) 9335fa6e665SDamon Ding /* a mirror win can only get fb address 9345fa6e665SDamon Ding * from source win: 9355fa6e665SDamon Ding * Cluster1---->Cluster0 9365fa6e665SDamon Ding * Esmart1 ---->Esmart0 9375fa6e665SDamon Ding * Smart1 ---->Smart0 9385fa6e665SDamon Ding * This is a feather on rk3566 9395fa6e665SDamon Ding */ 9405fa6e665SDamon Ding #define WIN_FEATURE_MIRROR BIT(6) 9415fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA BIT(7) 9425fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8) 9435fa6e665SDamon Ding 9445fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F 0xfe 9455fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F 0xff 9465fa6e665SDamon Ding 9475fa6e665SDamon Ding enum vop_csc_format { 94810ee9f5bSAlgea Cao CSC_BT601L, 94910ee9f5bSAlgea Cao CSC_BT709L, 95010ee9f5bSAlgea Cao CSC_BT601F, 95110ee9f5bSAlgea Cao CSC_BT2020, 9525fa6e665SDamon Ding CSC_BT709L_13BIT, 9535fa6e665SDamon Ding CSC_BT709F_13BIT, 9545fa6e665SDamon Ding CSC_BT2020L_13BIT, 9555fa6e665SDamon Ding CSC_BT2020F_13BIT, 9565fa6e665SDamon Ding }; 9575fa6e665SDamon Ding 9585fa6e665SDamon Ding enum vop_csc_bit_depth { 9595fa6e665SDamon Ding CSC_10BIT_DEPTH, 9605fa6e665SDamon Ding CSC_13BIT_DEPTH, 96110ee9f5bSAlgea Cao }; 96210ee9f5bSAlgea Cao 96310ee9f5bSAlgea Cao enum vop2_pol { 96410ee9f5bSAlgea Cao HSYNC_POSITIVE = 0, 96510ee9f5bSAlgea Cao VSYNC_POSITIVE = 1, 96610ee9f5bSAlgea Cao DEN_NEGATIVE = 2, 96710ee9f5bSAlgea Cao DCLK_INVERT = 3 96810ee9f5bSAlgea Cao }; 96910ee9f5bSAlgea Cao 970ac500a1fSSandy Huang enum vop2_bcsh_out_mode { 971ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK, 972ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE, 973ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR, 974ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, 975ac500a1fSSandy Huang }; 976ac500a1fSSandy Huang 977d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \ 978d0408543SAndy Yan { \ 979d0408543SAndy Yan .offset = off, \ 980d0408543SAndy Yan .mask = _mask, \ 981d0408543SAndy Yan .shift = _shift, \ 982d0408543SAndy Yan .write_mask = _write_mask, \ 983d0408543SAndy Yan } 984d0408543SAndy Yan 985d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \ 986d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false) 987d0408543SAndy Yan enum dither_down_mode { 988d0408543SAndy Yan RGB888_TO_RGB565 = 0x0, 989d0408543SAndy Yan RGB888_TO_RGB666 = 0x1 990d0408543SAndy Yan }; 991d0408543SAndy Yan 992d0408543SAndy Yan enum vop2_video_ports_id { 993d0408543SAndy Yan VOP2_VP0, 994d0408543SAndy Yan VOP2_VP1, 995d0408543SAndy Yan VOP2_VP2, 996d0408543SAndy Yan VOP2_VP3, 997d0408543SAndy Yan VOP2_VP_MAX, 998d0408543SAndy Yan }; 999d0408543SAndy Yan 1000ee008497SSandy Huang enum vop2_layer_type { 1001ee008497SSandy Huang CLUSTER_LAYER = 0, 1002ee008497SSandy Huang ESMART_LAYER = 1, 1003ee008497SSandy Huang SMART_LAYER = 2, 1004ee008497SSandy Huang }; 1005ee008497SSandy Huang 1006b0989546SSandy Huang /* This define must same with kernel win phy id */ 1007b0989546SSandy Huang enum vop2_layer_phy_id { 1008b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0, 1009b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, 1010b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0, 1011b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 1012b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 1013b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 1014b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2, 1015b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3, 1016b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2, 1017b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3, 1018ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX, 1019d0408543SAndy Yan }; 1020d0408543SAndy Yan 10213e39a5a1SSandy Huang enum vop2_scale_up_mode { 10223e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR, 10233e39a5a1SSandy Huang VOP2_SCALE_UP_BIL, 10243e39a5a1SSandy Huang VOP2_SCALE_UP_BIC, 10253e39a5a1SSandy Huang }; 10263e39a5a1SSandy Huang 10273e39a5a1SSandy Huang enum vop2_scale_down_mode { 10283e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR, 10293e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL, 10303e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG, 10313e39a5a1SSandy Huang }; 10323e39a5a1SSandy Huang 10333e39a5a1SSandy Huang enum scale_mode { 10343e39a5a1SSandy Huang SCALE_NONE = 0x0, 10353e39a5a1SSandy Huang SCALE_UP = 0x1, 10363e39a5a1SSandy Huang SCALE_DOWN = 0x2 10373e39a5a1SSandy Huang }; 10383e39a5a1SSandy Huang 103912ee5af0SDamon Ding enum vop_dsc_interface_mode { 104012ee5af0SDamon Ding VOP_DSC_IF_DISABLE = 0, 104112ee5af0SDamon Ding VOP_DSC_IF_HDMI = 1, 104212ee5af0SDamon Ding VOP_DSC_IF_MIPI_DS_MODE = 2, 104312ee5af0SDamon Ding VOP_DSC_IF_MIPI_VIDEO_MODE = 3, 104412ee5af0SDamon Ding }; 104512ee5af0SDamon Ding 10465fa6e665SDamon Ding enum vop3_pre_scale_down_mode { 10475fa6e665SDamon Ding VOP3_PRE_SCALE_UNSPPORT, 10485fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_GT, 10495fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_AVG, 10505fa6e665SDamon Ding }; 10515fa6e665SDamon Ding 10525fa6e665SDamon Ding enum vop3_esmart_lb_mode { 10535fa6e665SDamon Ding VOP3_ESMART_8K_MODE, 10545fa6e665SDamon Ding VOP3_ESMART_4K_4K_MODE, 10555fa6e665SDamon Ding VOP3_ESMART_4K_2K_2K_MODE, 10565fa6e665SDamon Ding VOP3_ESMART_2K_2K_2K_2K_MODE, 10575fa6e665SDamon Ding }; 10585fa6e665SDamon Ding 10593e39a5a1SSandy Huang struct vop2_layer { 10603e39a5a1SSandy Huang u8 id; 10613e39a5a1SSandy Huang /** 10623e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected. 10633e39a5a1SSandy Huang * Every layer must make sure to select different 10643e39a5a1SSandy Huang * windows of others. 10653e39a5a1SSandy Huang */ 10663e39a5a1SSandy Huang u8 win_phys_id; 10673e39a5a1SSandy Huang }; 10683e39a5a1SSandy Huang 106960e469f5SDamon Ding struct vop2_power_domain_data { 1070b6ba80b4SDamon Ding u8 id; 1071b6ba80b4SDamon Ding u8 parent_id; 1072b6ba80b4SDamon Ding /* 1073b6ba80b4SDamon Ding * @module_id_mask: module id of which module this power domain is belongs to. 1074b6ba80b4SDamon Ding * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 1075b6ba80b4SDamon Ding */ 1076b6ba80b4SDamon Ding u32 module_id_mask; 107760e469f5SDamon Ding }; 107860e469f5SDamon Ding 1079b0989546SSandy Huang struct vop2_win_data { 1080b0989546SSandy Huang char *name; 108163cb669fSSandy Huang u8 phys_id; 1082ecc31b6eSAndy Yan enum vop2_layer_type type; 1083b0989546SSandy Huang u8 win_sel_port_offset; 10845fa6e665SDamon Ding u8 layer_sel_win_id[VOP2_VP_MAX]; 1085a33b790fSDamon Ding u8 axi_id; 1086a33b790fSDamon Ding u8 axi_uv_id; 1087a33b790fSDamon Ding u8 axi_yrgb_id; 1088ee01dbb2SDamon Ding u8 splice_win_id; 1089b6ba80b4SDamon Ding u8 pd_id; 10905fa6e665SDamon Ding u8 hsu_filter_mode; 10915fa6e665SDamon Ding u8 hsd_filter_mode; 10925fa6e665SDamon Ding u8 vsu_filter_mode; 10935fa6e665SDamon Ding u8 vsd_filter_mode; 10945fa6e665SDamon Ding u8 hsd_pre_filter_mode; 10955fa6e665SDamon Ding u8 vsd_pre_filter_mode; 10965fa6e665SDamon Ding u8 scale_engine_num; 1097b0989546SSandy Huang u32 reg_offset; 10984c765862SDamon Ding u32 max_upscale_factor; 10994c765862SDamon Ding u32 max_downscale_factor; 1100ee01dbb2SDamon Ding bool splice_mode_right; 110163cb669fSSandy Huang }; 110263cb669fSSandy Huang 110363cb669fSSandy Huang struct vop2_vp_data { 110463cb669fSSandy Huang u32 feature; 110563cb669fSSandy Huang u8 pre_scan_max_dly; 1106452afb13SDamon Ding u8 layer_mix_dly; 1107452afb13SDamon Ding u8 hdr_mix_dly; 1108452afb13SDamon Ding u8 win_dly; 1109ee01dbb2SDamon Ding u8 splice_vp_id; 111063cb669fSSandy Huang struct vop_rect max_output; 1111ecc31b6eSAndy Yan u32 max_dclk; 1112d0408543SAndy Yan }; 1113d0408543SAndy Yan 1114ee008497SSandy Huang struct vop2_plane_table { 1115ee008497SSandy Huang enum vop2_layer_phy_id plane_id; 1116ee008497SSandy Huang enum vop2_layer_type plane_type; 1117ee008497SSandy Huang }; 1118ee008497SSandy Huang 1119b0989546SSandy Huang struct vop2_vp_plane_mask { 1120b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */ 1121b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */ 1122b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 1123b0989546SSandy Huang u32 plane_mask; 1124ee008497SSandy Huang int cursor_plane_id; 1125b0989546SSandy Huang }; 1126b0989546SSandy Huang 112712ee5af0SDamon Ding struct vop2_dsc_data { 112812ee5af0SDamon Ding u8 id; 112912ee5af0SDamon Ding u8 pd_id; 113012ee5af0SDamon Ding u8 max_slice_num; 113112ee5af0SDamon Ding u8 max_linebuf_depth; /* used to generate the bitstream */ 113212ee5af0SDamon Ding u8 min_bits_per_pixel; /* bit num after encoder compress */ 113312ee5af0SDamon Ding const char *dsc_txp_clk_src_name; 113412ee5af0SDamon Ding const char *dsc_txp_clk_name; 113512ee5af0SDamon Ding const char *dsc_pxl_clk_name; 113612ee5af0SDamon Ding const char *dsc_cds_clk_name; 113712ee5af0SDamon Ding }; 113812ee5af0SDamon Ding 113912ee5af0SDamon Ding struct dsc_error_info { 114012ee5af0SDamon Ding u32 dsc_error_val; 114112ee5af0SDamon Ding char dsc_error_info[50]; 114212ee5af0SDamon Ding }; 114312ee5af0SDamon Ding 114472388c26SDamon Ding struct vop2_dump_regs { 114572388c26SDamon Ding u32 offset; 114672388c26SDamon Ding const char *name; 114772388c26SDamon Ding u32 state_base; 114872388c26SDamon Ding u32 state_mask; 114972388c26SDamon Ding u32 state_shift; 115072388c26SDamon Ding bool enable_state; 115172388c26SDamon Ding }; 115272388c26SDamon Ding 1153d0408543SAndy Yan struct vop2_data { 115452ee18acSSandy Huang u32 version; 11555fa6e665SDamon Ding u32 esmart_lb_mode; 115663cb669fSSandy Huang struct vop2_vp_data *vp_data; 1157b0989546SSandy Huang struct vop2_win_data *win_data; 1158b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 1159ee008497SSandy Huang struct vop2_plane_table *plane_table; 1160b6ba80b4SDamon Ding struct vop2_power_domain_data *pd; 116112ee5af0SDamon Ding struct vop2_dsc_data *dsc; 116212ee5af0SDamon Ding struct dsc_error_info *dsc_error_ecw; 116312ee5af0SDamon Ding struct dsc_error_info *dsc_error_buffer_flow; 116472388c26SDamon Ding struct vop2_dump_regs *dump_regs; 1165337d1c13SDamon Ding u8 *vp_primary_plane_order; 116663cb669fSSandy Huang u8 nr_vps; 116763cb669fSSandy Huang u8 nr_layers; 116863cb669fSSandy Huang u8 nr_mixers; 11691147facaSSandy Huang u8 nr_gammas; 1170b6ba80b4SDamon Ding u8 nr_pd; 117112ee5af0SDamon Ding u8 nr_dscs; 117212ee5af0SDamon Ding u8 nr_dsc_ecw; 117312ee5af0SDamon Ding u8 nr_dsc_buffer_flow; 1174ecc31b6eSAndy Yan u32 reg_len; 117572388c26SDamon Ding u32 dump_regs_size; 1176d0408543SAndy Yan }; 1177d0408543SAndy Yan 1178d0408543SAndy Yan struct vop2 { 1179d0408543SAndy Yan u32 *regsbak; 1180d0408543SAndy Yan void *regs; 1181d0408543SAndy Yan void *grf; 1182ecc31b6eSAndy Yan void *vop_grf; 1183ecc31b6eSAndy Yan void *vo1_grf; 118460e469f5SDamon Ding void *sys_pmu; 118552ee18acSSandy Huang u32 reg_len; 118652ee18acSSandy Huang u32 version; 11875fa6e665SDamon Ding u32 esmart_lb_mode; 118863cb669fSSandy Huang bool global_init; 1189d0408543SAndy Yan const struct vop2_data *data; 1190b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 1191d0408543SAndy Yan }; 1192d0408543SAndy Yan 1193d0408543SAndy Yan static struct vop2 *rockchip_vop2; 11945fa6e665SDamon Ding 11955fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2) 11965fa6e665SDamon Ding { 11975fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) 11985fa6e665SDamon Ding return false; 11995fa6e665SDamon Ding else 12005fa6e665SDamon Ding return true; 12015fa6e665SDamon Ding } 12025fa6e665SDamon Ding 12033e39a5a1SSandy Huang /* 12043e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12; 12053e39a5a1SSandy Huang * avg_sd_factor: 12063e39a5a1SSandy Huang * bli_su_factor: 12073e39a5a1SSandy Huang * bic_su_factor: 12083e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16; 12093e39a5a1SSandy Huang * 12105fa6e665SDamon Ding * ygt2 enable: dst get one line from two line of the src 12115fa6e665SDamon Ding * ygt4 enable: dst get one line from four line of the src. 12123e39a5a1SSandy Huang * 12133e39a5a1SSandy Huang */ 12143e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 12153e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 12163e39a5a1SSandy Huang 12173e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 12183e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1)) 12193e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 12203e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1)) 12215fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \ 12225fa6e665SDamon Ding (fac * (dst - 1) >> 16 < (src - 1)) 12233e39a5a1SSandy Huang 12243e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode, 12253e39a5a1SSandy Huang int32_t filter_mode, 12263e39a5a1SSandy Huang uint32_t src, uint32_t dst) 12273e39a5a1SSandy Huang { 12283e39a5a1SSandy Huang uint32_t fac = 0; 12293e39a5a1SSandy Huang int i = 0; 12303e39a5a1SSandy Huang 12313e39a5a1SSandy Huang if (mode == SCALE_NONE) 12323e39a5a1SSandy Huang return 0; 12333e39a5a1SSandy Huang 12343e39a5a1SSandy Huang /* 12353e39a5a1SSandy Huang * A workaround to avoid zero div. 12363e39a5a1SSandy Huang */ 12373e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) { 12383e39a5a1SSandy Huang dst = dst + 1; 12393e39a5a1SSandy Huang src = src + 1; 12403e39a5a1SSandy Huang } 12413e39a5a1SSandy Huang 12423e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 12433e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst); 12443e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 12453e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 12463e39a5a1SSandy Huang break; 12473e39a5a1SSandy Huang fac -= 1; 12483e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12493e39a5a1SSandy Huang } 12503e39a5a1SSandy Huang } else { 12513e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst); 12523e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 12533e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 12543e39a5a1SSandy Huang break; 12553e39a5a1SSandy Huang fac -= 1; 12563e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12573e39a5a1SSandy Huang } 12583e39a5a1SSandy Huang } 12593e39a5a1SSandy Huang 12603e39a5a1SSandy Huang return fac; 12613e39a5a1SSandy Huang } 12623e39a5a1SSandy Huang 12635fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor) 12645fa6e665SDamon Ding { 12655fa6e665SDamon Ding if (is_hor) 12665fa6e665SDamon Ding return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac); 12675fa6e665SDamon Ding return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac); 12685fa6e665SDamon Ding } 12695fa6e665SDamon Ding 12705fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode, 12715fa6e665SDamon Ding uint32_t src, uint32_t dst, bool is_hor) 12725fa6e665SDamon Ding { 12735fa6e665SDamon Ding uint32_t fac = 0; 12745fa6e665SDamon Ding int i = 0; 12755fa6e665SDamon Ding 12765fa6e665SDamon Ding if (mode == SCALE_NONE) 12775fa6e665SDamon Ding return 0; 12785fa6e665SDamon Ding 12795fa6e665SDamon Ding /* 12805fa6e665SDamon Ding * A workaround to avoid zero div. 12815fa6e665SDamon Ding */ 12825fa6e665SDamon Ding if ((dst == 1) || (src == 1)) { 12835fa6e665SDamon Ding dst = dst + 1; 12845fa6e665SDamon Ding src = src + 1; 12855fa6e665SDamon Ding } 12865fa6e665SDamon Ding 12875fa6e665SDamon Ding if (mode == SCALE_DOWN) { 12885fa6e665SDamon Ding fac = VOP2_BILI_SCL_DN(src, dst); 12895fa6e665SDamon Ding for (i = 0; i < 100; i++) { 12905fa6e665SDamon Ding if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 12915fa6e665SDamon Ding break; 12925fa6e665SDamon Ding fac -= 1; 12935fa6e665SDamon Ding printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12945fa6e665SDamon Ding } 12955fa6e665SDamon Ding } else { 12965fa6e665SDamon Ding fac = VOP2_COMMON_SCL(src, dst); 12975fa6e665SDamon Ding for (i = 0; i < 100; i++) { 12985fa6e665SDamon Ding if (vop3_scale_up_fac_check(src, dst, fac, is_hor)) 12995fa6e665SDamon Ding break; 13005fa6e665SDamon Ding fac -= 1; 13015fa6e665SDamon Ding printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 13025fa6e665SDamon Ding } 13035fa6e665SDamon Ding } 13045fa6e665SDamon Ding 13055fa6e665SDamon Ding return fac; 13065fa6e665SDamon Ding } 13075fa6e665SDamon Ding 13083e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst) 13093e39a5a1SSandy Huang { 13103e39a5a1SSandy Huang if (src < dst) 13113e39a5a1SSandy Huang return SCALE_UP; 13123e39a5a1SSandy Huang else if (src > dst) 13133e39a5a1SSandy Huang return SCALE_DOWN; 13143e39a5a1SSandy Huang 13153e39a5a1SSandy Huang return SCALE_NONE; 13163e39a5a1SSandy Huang } 1317d0408543SAndy Yan 1318ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x) 1319ac500a1fSSandy Huang { 1320ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 1321ac500a1fSSandy Huang } 1322ac500a1fSSandy Huang 1323b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 1324b0989546SSandy Huang { 1325b0989546SSandy Huang int i = 0; 1326ecc31b6eSAndy Yan 1327337d1c13SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 1328337d1c13SDamon Ding if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i])) 1329337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[i]; 1330ecc31b6eSAndy Yan } 1331b0989546SSandy Huang 1332337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[0]; 1333b0989546SSandy Huang } 1334b0989546SSandy Huang 133563cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift) 1336d0408543SAndy Yan { 1337d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 1338d0408543SAndy Yan } 1339d0408543SAndy Yan 134063cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst) 1341d0408543SAndy Yan { 1342d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1); 1343d0408543SAndy Yan } 1344d0408543SAndy Yan 134552ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 1346d0408543SAndy Yan { 1347d0408543SAndy Yan writel(v, vop2->regs + offset); 1348d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1349d0408543SAndy Yan } 1350d0408543SAndy Yan 135152ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 1352d0408543SAndy Yan { 1353d0408543SAndy Yan return readl(vop2->regs + offset); 1354d0408543SAndy Yan } 1355d0408543SAndy Yan 135652ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 135752ee18acSSandy Huang u32 mask, u32 shift, u32 v, 1358d0408543SAndy Yan bool write_mask) 1359d0408543SAndy Yan { 1360d0408543SAndy Yan if (!mask) 1361d0408543SAndy Yan return; 1362d0408543SAndy Yan 1363d0408543SAndy Yan if (write_mask) { 1364d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16)); 1365d0408543SAndy Yan } else { 136652ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2]; 1367d0408543SAndy Yan 1368d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 1369d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1370d0408543SAndy Yan } 1371d0408543SAndy Yan 1372d0408543SAndy Yan writel(v, vop2->regs + offset); 1373d0408543SAndy Yan } 1374d0408543SAndy Yan 1375ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 137652ee18acSSandy Huang u32 mask, u32 shift, u32 v) 137752ee18acSSandy Huang { 137852ee18acSSandy Huang u32 val = 0; 137952ee18acSSandy Huang 138052ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16)); 1381ecc31b6eSAndy Yan writel(val, grf_base + offset); 138252ee18acSSandy Huang } 138352ee18acSSandy Huang 138460e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 138560e469f5SDamon Ding u32 mask, u32 shift) 138660e469f5SDamon Ding { 138760e469f5SDamon Ding return (readl(grf_base + offset) >> shift) & mask; 138860e469f5SDamon Ding } 138960e469f5SDamon Ding 13908895aec1SSandy Huang static char* get_output_if_name(u32 output_if, char *name) 13918895aec1SSandy Huang { 13928895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_RGB) 13938895aec1SSandy Huang strcat(name, " RGB"); 13948895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT1120) 13958895aec1SSandy Huang strcat(name, " BT1120"); 13968895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT656) 13978895aec1SSandy Huang strcat(name, " BT656"); 13988895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS0) 13998895aec1SSandy Huang strcat(name, " LVDS0"); 14008895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS1) 14018895aec1SSandy Huang strcat(name, " LVDS1"); 14028895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI0) 14038895aec1SSandy Huang strcat(name, " MIPI0"); 14048895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI1) 14058895aec1SSandy Huang strcat(name, " MIPI1"); 14068895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP0) 14078895aec1SSandy Huang strcat(name, " eDP0"); 14088895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP1) 14098895aec1SSandy Huang strcat(name, " eDP1"); 14108895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP0) 14118895aec1SSandy Huang strcat(name, " DP0"); 14128895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP1) 14138895aec1SSandy Huang strcat(name, " DP1"); 14148895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI0) 14158895aec1SSandy Huang strcat(name, " HDMI0"); 14168895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI1) 14178895aec1SSandy Huang strcat(name, " HDMI1"); 14188895aec1SSandy Huang 14198895aec1SSandy Huang return name; 14208895aec1SSandy Huang } 14218895aec1SSandy Huang 14228895aec1SSandy Huang static char *get_plane_name(int plane_id, char *name) 14238895aec1SSandy Huang { 14248895aec1SSandy Huang switch (plane_id) { 14258895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER0: 14268895aec1SSandy Huang strcat(name, "Cluster0"); 14278895aec1SSandy Huang break; 14288895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER1: 14298895aec1SSandy Huang strcat(name, "Cluster1"); 14308895aec1SSandy Huang break; 14318895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART0: 14328895aec1SSandy Huang strcat(name, "Esmart0"); 14338895aec1SSandy Huang break; 14348895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART1: 14358895aec1SSandy Huang strcat(name, "Esmart1"); 14368895aec1SSandy Huang break; 14378895aec1SSandy Huang case ROCKCHIP_VOP2_SMART0: 14388895aec1SSandy Huang strcat(name, "Smart0"); 14398895aec1SSandy Huang break; 14408895aec1SSandy Huang case ROCKCHIP_VOP2_SMART1: 14418895aec1SSandy Huang strcat(name, "Smart1"); 14428895aec1SSandy Huang break; 14438895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER2: 14448895aec1SSandy Huang strcat(name, "Cluster2"); 14458895aec1SSandy Huang break; 14468895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER3: 14478895aec1SSandy Huang strcat(name, "Cluster3"); 14488895aec1SSandy Huang break; 14498895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART2: 14508895aec1SSandy Huang strcat(name, "Esmart2"); 14518895aec1SSandy Huang break; 14528895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART3: 14538895aec1SSandy Huang strcat(name, "Esmart3"); 14548895aec1SSandy Huang break; 14558895aec1SSandy Huang } 14568895aec1SSandy Huang 14578895aec1SSandy Huang return name; 14588895aec1SSandy Huang } 14598895aec1SSandy Huang 146052ee18acSSandy Huang static bool is_yuv_output(u32 bus_format) 1461d0408543SAndy Yan { 1462d0408543SAndy Yan switch (bus_format) { 1463d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 1464d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 1465034a46b5SAlgea Cao case MEDIA_BUS_FMT_YUYV10_1X20: 1466d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1467d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1468a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 1469a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 1470a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8: 1471a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8: 1472a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 1473a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 1474a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16: 1475a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16: 1476d0408543SAndy Yan return true; 1477d0408543SAndy Yan default: 1478d0408543SAndy Yan return false; 1479d0408543SAndy Yan } 1480d0408543SAndy Yan } 1481d0408543SAndy Yan 14825fa6e665SDamon Ding static int vop2_convert_csc_mode(int csc_mode, int bit_depth) 148310ee9f5bSAlgea Cao { 148410ee9f5bSAlgea Cao switch (csc_mode) { 148510ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE170M: 148610ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_M: 148710ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_BG: 148810ee9f5bSAlgea Cao return CSC_BT601L; 148910ee9f5bSAlgea Cao case V4L2_COLORSPACE_REC709: 149010ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE240M: 149110ee9f5bSAlgea Cao case V4L2_COLORSPACE_DEFAULT: 14925fa6e665SDamon Ding if (bit_depth == CSC_13BIT_DEPTH) 14935fa6e665SDamon Ding return CSC_BT709L_13BIT; 14945fa6e665SDamon Ding else 149510ee9f5bSAlgea Cao return CSC_BT709L; 149610ee9f5bSAlgea Cao case V4L2_COLORSPACE_JPEG: 149710ee9f5bSAlgea Cao return CSC_BT601F; 149810ee9f5bSAlgea Cao case V4L2_COLORSPACE_BT2020: 14995fa6e665SDamon Ding if (bit_depth == CSC_13BIT_DEPTH) 15005fa6e665SDamon Ding return CSC_BT2020L_13BIT; 15015fa6e665SDamon Ding else 150210ee9f5bSAlgea Cao return CSC_BT2020; 15035fa6e665SDamon Ding case V4L2_COLORSPACE_BT709F: 15045fa6e665SDamon Ding if (bit_depth == CSC_10BIT_DEPTH) { 15055fa6e665SDamon Ding printf("WARN: Unsupported bt709f at 10bit csc depth, use bt601f instead\n"); 15065fa6e665SDamon Ding return CSC_BT601F; 15075fa6e665SDamon Ding } else { 15085fa6e665SDamon Ding return CSC_BT709F_13BIT; 15095fa6e665SDamon Ding } 15105fa6e665SDamon Ding case V4L2_COLORSPACE_BT2020F: 15115fa6e665SDamon Ding if (bit_depth == CSC_10BIT_DEPTH) { 15125fa6e665SDamon Ding printf("WARN: Unsupported bt2020f at 10bit csc depth, use bt601f instead\n"); 15135fa6e665SDamon Ding return CSC_BT601F; 15145fa6e665SDamon Ding } else { 15155fa6e665SDamon Ding return CSC_BT2020F_13BIT; 15165fa6e665SDamon Ding } 151710ee9f5bSAlgea Cao default: 151810ee9f5bSAlgea Cao return CSC_BT709L; 151910ee9f5bSAlgea Cao } 152010ee9f5bSAlgea Cao } 152110ee9f5bSAlgea Cao 1522b0989546SSandy Huang static bool is_uv_swap(u32 bus_format, u32 output_mode) 1523d0408543SAndy Yan { 1524d0408543SAndy Yan /* 1525d0408543SAndy Yan * FIXME: 1526d0408543SAndy Yan * 1527d0408543SAndy Yan * There is no media type for YUV444 output, 1528d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on 1529d0408543SAndy Yan * yuv format. 1530d0408543SAndy Yan * 1531d0408543SAndy Yan * From H/W testing, YUV444 mode need a rb swap. 1532d0408543SAndy Yan */ 15333e59c137SSandy Huang if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || 15343e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || 15353e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || 15363e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || 15373e59c137SSandy Huang ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1538d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1539d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA || 15403e59c137SSandy Huang output_mode == ROCKCHIP_OUT_MODE_P888))) 1541d0408543SAndy Yan return true; 1542d0408543SAndy Yan else 1543d0408543SAndy Yan return false; 1544d0408543SAndy Yan } 1545d0408543SAndy Yan 1546b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type) 154763cb669fSSandy Huang { 1548b0989546SSandy Huang switch (output_type) { 1549b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA: 1550b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB: 1551b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV: 1552b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort: 1553b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA: 1554b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown: 1555b0989546SSandy Huang return true; 1556b0989546SSandy Huang default: 1557b0989546SSandy Huang return false; 155863cb669fSSandy Huang } 155963cb669fSSandy Huang } 156063cb669fSSandy Huang 1561ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1562ecc31b6eSAndy Yan { 1563ecc31b6eSAndy Yan int i = 0; 1564ecc31b6eSAndy Yan 1565ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) { 1566ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id) 1567ecc31b6eSAndy Yan return &vop2->data->win_data[i]; 1568ecc31b6eSAndy Yan } 1569ecc31b6eSAndy Yan 1570ecc31b6eSAndy Yan return NULL; 1571ecc31b6eSAndy Yan } 1572ecc31b6eSAndy Yan 1573b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id) 1574b6ba80b4SDamon Ding { 1575b6ba80b4SDamon Ding int i = 0; 1576b6ba80b4SDamon Ding 1577b6ba80b4SDamon Ding for (i = 0; i < vop2->data->nr_pd; i++) { 1578b6ba80b4SDamon Ding if (vop2->data->pd[i].id == pd_id) 1579b6ba80b4SDamon Ding return &vop2->data->pd[i]; 1580b6ba80b4SDamon Ding } 1581b6ba80b4SDamon Ding 1582b6ba80b4SDamon Ding return NULL; 1583b6ba80b4SDamon Ding } 1584b6ba80b4SDamon Ding 1585db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1586db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1587db328a0dSDamon Ding { 1588db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1589db328a0dSDamon Ding int i; 1590db328a0dSDamon Ding 1591db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1592db328a0dSDamon Ding GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 1593db328a0dSDamon Ding crtc_id, false); 1594db328a0dSDamon Ding 1595db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1596db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1597db328a0dSDamon Ding 1598db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1599db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1600db328a0dSDamon Ding } 1601db328a0dSDamon Ding 1602db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1603db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1604db328a0dSDamon Ding { 1605db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1606db328a0dSDamon Ding int i; 1607db328a0dSDamon Ding 1608db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1609db328a0dSDamon Ding GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT, 1610db328a0dSDamon Ding crtc_id, false); 1611db328a0dSDamon Ding 1612db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1613db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1614db328a0dSDamon Ding 1615db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1616db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1617db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1618db328a0dSDamon Ding EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false); 1619db328a0dSDamon Ding } 1620db328a0dSDamon Ding 16211147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1622d0408543SAndy Yan struct display_state *state) 1623d0408543SAndy Yan { 16241147facaSSandy Huang struct connector_state *conn_state = &state->conn_state; 16251147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state; 16261147facaSSandy Huang struct resource gamma_res; 16271147facaSSandy Huang fdt_size_t lut_size; 16281147facaSSandy Huang int i, lut_len, ret = 0; 16291147facaSSandy Huang u32 *lut_regs; 16301147facaSSandy Huang u32 *lut_val; 16311147facaSSandy Huang u32 r, g, b; 16321147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 16331147facaSSandy Huang static int gamma_lut_en_num = 1; 16341147facaSSandy Huang 16351147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) { 16361147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 16371147facaSSandy Huang return 0; 16381147facaSSandy Huang } 16391147facaSSandy Huang 16401147facaSSandy Huang if (!disp_info) 16411147facaSSandy Huang return 0; 16421147facaSSandy Huang 16431147facaSSandy Huang if (!disp_info->gamma_lut_data.size) 16441147facaSSandy Huang return 0; 16451147facaSSandy Huang 16461147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 16471147facaSSandy Huang if (ret) 16481147facaSSandy Huang printf("failed to get gamma lut res\n"); 16491147facaSSandy Huang lut_regs = (u32 *)gamma_res.start; 16501147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1; 16511147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 16521147facaSSandy Huang printf("failed to get gamma lut register\n"); 16531147facaSSandy Huang return 0; 16541147facaSSandy Huang } 16551147facaSSandy Huang lut_len = lut_size / 4; 16561147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) { 16571147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 16581147facaSSandy Huang return 0; 16591147facaSSandy Huang } 16601147facaSSandy Huang lut_val = (u32 *)calloc(1, lut_size); 16611147facaSSandy Huang for (i = 0; i < lut_len; i++) { 16621147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 16631147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 16641147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 16651147facaSSandy Huang 16661147facaSSandy Huang lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 16671147facaSSandy Huang } 16681147facaSSandy Huang 1669db328a0dSDamon Ding if (vop2->version == VOP_VERSION_RK3568) { 1670db328a0dSDamon Ding rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len); 16711147facaSSandy Huang gamma_lut_en_num++; 1672db328a0dSDamon Ding } else if (vop2->version == VOP_VERSION_RK3588) { 1673db328a0dSDamon Ding rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len); 1674db328a0dSDamon Ding if (cstate->splice_mode) { 1675db328a0dSDamon Ding rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, lut_val, lut_len); 1676db328a0dSDamon Ding gamma_lut_en_num++; 1677db328a0dSDamon Ding } 1678db328a0dSDamon Ding gamma_lut_en_num++; 1679db328a0dSDamon Ding } 16801147facaSSandy Huang 1681d0408543SAndy Yan return 0; 1682d0408543SAndy Yan } 1683d0408543SAndy Yan 16846414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 16856414e3bcSSandy Huang struct display_state *state) 16866414e3bcSSandy Huang { 16876414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state; 16886414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state; 16896414e3bcSSandy Huang int i, cubic_lut_len; 16906414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 16916414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 16926414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 16936414e3bcSSandy Huang u32 *cubic_lut_addr; 16946414e3bcSSandy Huang 16956414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 16966414e3bcSSandy Huang return 0; 16976414e3bcSSandy Huang 16986414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size) 16996414e3bcSSandy Huang return 0; 17006414e3bcSSandy Huang 17016414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 17026414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size; 17036414e3bcSSandy Huang 17046414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) { 17056414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 17066414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 17076414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 17086414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 17096414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) + 17106414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 17116414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28); 17126414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 17136414e3bcSSandy Huang *cubic_lut_addr++ = 0; 17146414e3bcSSandy Huang } 17156414e3bcSSandy Huang 17166414e3bcSSandy Huang if (cubic_lut_len % 2) { 17176414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 17186414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 17196414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 17206414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 17216414e3bcSSandy Huang *cubic_lut_addr++ = 0; 17226414e3bcSSandy Huang *cubic_lut_addr = 0; 17236414e3bcSSandy Huang } 17246414e3bcSSandy Huang 17256414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 17266414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id)); 17276414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 17286414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 17296414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 17306414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 17316414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 17326414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 17336414e3bcSSandy Huang 17346414e3bcSSandy Huang return 0; 17356414e3bcSSandy Huang } 17366414e3bcSSandy Huang 1737ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2, 1738ee01dbb2SDamon Ding struct bcsh_state *bcsh_state, int crtc_id) 1739ee01dbb2SDamon Ding { 1740ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1741ee01dbb2SDamon Ding u32 vp_offset = crtc_id * 0x100; 1742ee01dbb2SDamon Ding 1743ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 1744ee01dbb2SDamon Ding BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false); 1745ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 1746ee01dbb2SDamon Ding BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false); 1747ee01dbb2SDamon Ding 1748ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 1749ee01dbb2SDamon Ding BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1750ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 1751ee01dbb2SDamon Ding BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1752ee01dbb2SDamon Ding 1753ee01dbb2SDamon Ding if (!cstate->bcsh_en) { 1754ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1755ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 1756ee01dbb2SDamon Ding return; 1757ee01dbb2SDamon Ding } 1758ee01dbb2SDamon Ding 1759ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1760ee01dbb2SDamon Ding BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 1761ee01dbb2SDamon Ding bcsh_state->brightness, false); 1762ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1763ee01dbb2SDamon Ding BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false); 1764ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1765ee01dbb2SDamon Ding BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 1766ee01dbb2SDamon Ding bcsh_state->saturation * bcsh_state->contrast / 0x100, false); 1767ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1768ee01dbb2SDamon Ding BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false); 1769ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1770ee01dbb2SDamon Ding BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false); 1771ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1772ee01dbb2SDamon Ding BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 1773ee01dbb2SDamon Ding BCSH_OUT_MODE_NORMAL_VIDEO, false); 1774ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1775ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 1776ee01dbb2SDamon Ding } 1777ee01dbb2SDamon Ding 1778ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 1779ac500a1fSSandy Huang { 1780ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state; 1781ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info; 1782ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state; 1783ee01dbb2SDamon Ding struct bcsh_state bcsh_state; 1784ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue; 1785ac500a1fSSandy Huang 1786ac500a1fSSandy Huang if (!conn_state->disp_info) 1787ac500a1fSSandy Huang return; 1788ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info; 1789ac500a1fSSandy Huang if (!bcsh_info) 1790ac500a1fSSandy Huang return; 1791ac500a1fSSandy Huang 1792ac500a1fSSandy Huang if (bcsh_info->brightness != 50 || 1793ac500a1fSSandy Huang bcsh_info->contrast != 50 || 1794ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50) 1795ee01dbb2SDamon Ding cstate->bcsh_en = true; 1796ac500a1fSSandy Huang 1797ee01dbb2SDamon Ding if (cstate->bcsh_en) { 1798ac500a1fSSandy Huang if (!cstate->yuv_overlay) 1799ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1800ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format)) 1801ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1802ac500a1fSSandy Huang } else { 1803ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 1804ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1805ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 1806ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1807ac500a1fSSandy Huang } 1808ac500a1fSSandy Huang 18095fa6e665SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 1810ac500a1fSSandy Huang 1811ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 1812ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127, 1813ac500a1fSSandy Huang bcsh_info->brightness); 1814ac500a1fSSandy Huang else 1815ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31, 1816ac500a1fSSandy Huang bcsh_info->brightness); 1817ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 1818ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 1819ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 1820ac500a1fSSandy Huang 1821ac500a1fSSandy Huang 1822ac500a1fSSandy Huang /* 1823ac500a1fSSandy Huang * a:[-30~0): 1824ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256; 1825ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1826ac500a1fSSandy Huang * a:[0~30] 1827ac500a1fSSandy Huang * sin_hue = sin(a)*256; 1828ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1829ac500a1fSSandy Huang */ 1830ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23; 1831ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23; 1832ac500a1fSSandy Huang 1833ee01dbb2SDamon Ding bcsh_state.brightness = brightness; 1834ee01dbb2SDamon Ding bcsh_state.contrast = contrast; 1835ee01dbb2SDamon Ding bcsh_state.saturation = saturation; 1836ee01dbb2SDamon Ding bcsh_state.sin_hue = sin_hue; 1837ee01dbb2SDamon Ding bcsh_state.cos_hue = cos_hue; 1838ee01dbb2SDamon Ding 1839ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id); 1840ee01dbb2SDamon Ding if (cstate->splice_mode) 1841ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id); 1842ee01dbb2SDamon Ding } 1843ee01dbb2SDamon Ding 1844ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id) 1845ee01dbb2SDamon Ding { 1846ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 1847ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 1848ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1849ee01dbb2SDamon Ding u32 bg_ovl_dly, bg_dly, pre_scan_dly; 1850ee01dbb2SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 1851ee01dbb2SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1852ee01dbb2SDamon Ding 1853ee01dbb2SDamon Ding bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly; 1854ee01dbb2SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly; 1855ee01dbb2SDamon Ding bg_dly -= bg_ovl_dly; 1856ee01dbb2SDamon Ding 1857ee01dbb2SDamon Ding if (cstate->splice_mode) 1858ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 2) - 1; 1859ee01dbb2SDamon Ding else 1860ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1861ee01dbb2SDamon Ding 1862ee01dbb2SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 1863ee01dbb2SDamon Ding hsync_len = 8; 1864ee01dbb2SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1865ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4, 1866ee01dbb2SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1867ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 1868ac500a1fSSandy Huang } 1869ac500a1fSSandy Huang 1870452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id) 1871452afb13SDamon Ding { 1872452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 1873452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 1874452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1875452afb13SDamon Ding struct vop2_win_data *win_data; 1876452afb13SDamon Ding u32 bg_dly, pre_scan_dly; 1877452afb13SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 1878452afb13SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1879452afb13SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 1880452afb13SDamon Ding u8 win_id; 1881452afb13SDamon Ding 1882452afb13SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 1883452afb13SDamon Ding win_id = atoi(&win_data->name[strlen(win_data->name) - 1]); 1884452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL + win_id * 4, 1885452afb13SDamon Ding ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 0, false); 1886452afb13SDamon Ding 1887452afb13SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].win_dly + 1888452afb13SDamon Ding vop2->data->vp_data[crtc_id].layer_mix_dly + 1889452afb13SDamon Ding vop2->data->vp_data[crtc_id].hdr_mix_dly; 1890452afb13SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1891452afb13SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1892452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100, 1893452afb13SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1894452afb13SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 1895452afb13SDamon Ding } 1896452afb13SDamon Ding 1897d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 1898d0408543SAndy Yan { 1899d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 1900d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 190152ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state; 190252ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 1903d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal; 1904d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 1905d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 1906d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay; 1907d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay; 1908d0408543SAndy Yan u16 hsize = 1909d0408543SAndy Yan hdisplay * (conn_state->overscan.left_margin + 1910d0408543SAndy Yan conn_state->overscan.right_margin) / 200; 1911d0408543SAndy Yan u16 vsize = 1912d0408543SAndy Yan vdisplay * (conn_state->overscan.top_margin + 1913d0408543SAndy Yan conn_state->overscan.bottom_margin) / 200; 1914d0408543SAndy Yan u16 hact_end, vact_end; 1915d0408543SAndy Yan u32 val; 1916d0408543SAndy Yan 191774bd8269SSandy Huang hsize = round_down(hsize, 2); 1918d0408543SAndy Yan vsize = round_down(vsize, 2); 1919d0408543SAndy Yan 1920d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 1921d0408543SAndy Yan hact_end = hact_st + hsize; 1922d0408543SAndy Yan val = hact_st << 16; 1923d0408543SAndy Yan val |= hact_end; 1924d0408543SAndy Yan 192552ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 1926d0408543SAndy Yan vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 1927d0408543SAndy Yan vact_end = vact_st + vsize; 1928d0408543SAndy Yan val = vact_st << 16; 1929d0408543SAndy Yan val |= vact_end; 193052ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 1931d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16; 1932d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize); 193352ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 1934d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 1935d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 193652ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 1937d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 1938d0408543SAndy Yan POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 1939d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1940d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 1941d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize; 1942d0408543SAndy Yan 1943d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 194452ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 1945d0408543SAndy Yan } 1946d0408543SAndy Yan 1947452afb13SDamon Ding if (is_vop3(vop2)) { 1948452afb13SDamon Ding vop3_setup_pipe_dly(state, vop2, cstate->crtc_id); 1949452afb13SDamon Ding } else { 1950ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id); 1951ee01dbb2SDamon Ding if (cstate->splice_mode) 1952ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id); 1953d0408543SAndy Yan } 1954452afb13SDamon Ding } 1955d0408543SAndy Yan 19566027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2) 19576027c871SZhang Yubing { 19586027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 19596027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 19606027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 19616027c871SZhang Yubing struct drm_display_mode *mode = &conn_state->mode; 19626027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 19636027c871SZhang Yubing s16 *lut_y; 19646027c871SZhang Yubing s16 *lut_h; 19656027c871SZhang Yubing s16 *lut_s; 19666027c871SZhang Yubing u32 value; 19676027c871SZhang Yubing int i; 19686027c871SZhang Yubing 19696027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 1970b8db91d0SZhang Yubing POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 1971b8db91d0SZhang Yubing if (!acm->acm_enable) { 1972b8db91d0SZhang Yubing writel(0, vop2->regs + RK3528_ACM_CTRL); 19736027c871SZhang Yubing return; 19746027c871SZhang Yubing } 19756027c871SZhang Yubing 19766027c871SZhang Yubing printf("post acm enable\n"); 19776027c871SZhang Yubing 19786027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_START); 19796027c871SZhang Yubing 19806027c871SZhang Yubing value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) + 19816027c871SZhang Yubing ((mode->vdisplay & 0xfff) << 20); 19826027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_CTRL); 19836027c871SZhang Yubing 19846027c871SZhang Yubing value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + 19856027c871SZhang Yubing ((acm->s_gain << 20) & 0x3ff00000); 19866027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE); 19876027c871SZhang Yubing 19886027c871SZhang Yubing lut_y = &acm->gain_lut_hy[0]; 19896027c871SZhang Yubing lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH]; 19906027c871SZhang Yubing lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2]; 19916027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) { 19926027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 19936027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 19946027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2)); 19956027c871SZhang Yubing } 19966027c871SZhang Yubing 19976027c871SZhang Yubing lut_y = &acm->gain_lut_hs[0]; 19986027c871SZhang Yubing lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH]; 19996027c871SZhang Yubing lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2]; 20006027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) { 20016027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 20026027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 20036027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2)); 20046027c871SZhang Yubing } 20056027c871SZhang Yubing 20066027c871SZhang Yubing lut_y = &acm->delta_lut_h[0]; 20076027c871SZhang Yubing lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH]; 20086027c871SZhang Yubing lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2]; 20096027c871SZhang Yubing for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) { 20106027c871SZhang Yubing value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) + 20116027c871SZhang Yubing ((lut_s[i] << 20) & 0x3ff00000); 20126027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2)); 20136027c871SZhang Yubing } 20146027c871SZhang Yubing 20156027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_DONE); 20166027c871SZhang Yubing } 20176027c871SZhang Yubing 20186027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2) 20196027c871SZhang Yubing { 20206027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 20216027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 20226027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 20236027c871SZhang Yubing struct csc_info *csc = &conn_state->disp_info->csc_info; 20246027c871SZhang Yubing struct post_csc_coef csc_coef; 20256027c871SZhang Yubing bool is_input_yuv = false; 20266027c871SZhang Yubing bool is_output_yuv = false; 20276027c871SZhang Yubing bool post_r2y_en = false; 20286027c871SZhang Yubing bool post_csc_en = false; 20296027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 20306027c871SZhang Yubing u32 value; 20316027c871SZhang Yubing int range_type; 20326027c871SZhang Yubing 20336027c871SZhang Yubing printf("post csc enable\n"); 20346027c871SZhang Yubing 20356027c871SZhang Yubing if (acm->acm_enable) { 20366027c871SZhang Yubing if (!cstate->yuv_overlay) 20376027c871SZhang Yubing post_r2y_en = true; 20386027c871SZhang Yubing 20396027c871SZhang Yubing /* do y2r in csc module */ 20406027c871SZhang Yubing if (!is_yuv_output(conn_state->bus_format)) 20416027c871SZhang Yubing post_csc_en = true; 20426027c871SZhang Yubing } else { 20436027c871SZhang Yubing if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 20446027c871SZhang Yubing post_r2y_en = true; 20456027c871SZhang Yubing 20466027c871SZhang Yubing /* do y2r in csc module */ 20476027c871SZhang Yubing if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 20486027c871SZhang Yubing post_csc_en = true; 20496027c871SZhang Yubing } 20506027c871SZhang Yubing 20516027c871SZhang Yubing if (csc->csc_enable) 20526027c871SZhang Yubing post_csc_en = true; 20536027c871SZhang Yubing 20546027c871SZhang Yubing if (cstate->yuv_overlay || post_r2y_en) 20556027c871SZhang Yubing is_input_yuv = true; 20566027c871SZhang Yubing 20576027c871SZhang Yubing if (is_yuv_output(conn_state->bus_format)) 20586027c871SZhang Yubing is_output_yuv = true; 20596027c871SZhang Yubing 20606027c871SZhang Yubing cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_13BIT_DEPTH); 20616027c871SZhang Yubing 20626027c871SZhang Yubing if (post_csc_en) { 20636027c871SZhang Yubing rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv, 20646027c871SZhang Yubing is_output_yuv); 20656027c871SZhang Yubing 20666027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20676027c871SZhang Yubing POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT, 20686027c871SZhang Yubing csc_coef.csc_coef00, false); 20695743c73eSZhang Yubing value = csc_coef.csc_coef01 & 0xffff; 20705743c73eSZhang Yubing value |= (csc_coef.csc_coef02 << 16) & 0xffff0000; 20716027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02); 20725743c73eSZhang Yubing value = csc_coef.csc_coef10 & 0xffff; 20735743c73eSZhang Yubing value |= (csc_coef.csc_coef11 << 16) & 0xffff0000; 20746027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11); 20755743c73eSZhang Yubing value = csc_coef.csc_coef12 & 0xffff; 20765743c73eSZhang Yubing value |= (csc_coef.csc_coef20 << 16) & 0xffff0000; 20776027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20); 20785743c73eSZhang Yubing value = csc_coef.csc_coef21 & 0xffff; 20795743c73eSZhang Yubing value |= (csc_coef.csc_coef22 << 16) & 0xffff0000; 20806027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22); 20816027c871SZhang Yubing writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0); 20826027c871SZhang Yubing writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1); 20836027c871SZhang Yubing writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2); 20846027c871SZhang Yubing 20856027c871SZhang Yubing range_type = csc_coef.range_type ? 0 : 1; 20866027c871SZhang Yubing range_type <<= is_input_yuv ? 0 : 1; 20876027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20886027c871SZhang Yubing POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false); 20896027c871SZhang Yubing } 20906027c871SZhang Yubing 20916027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20925743c73eSZhang Yubing POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false); 20936027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20946027c871SZhang Yubing POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false); 20956027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20966027c871SZhang Yubing POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false); 20976027c871SZhang Yubing } 20986027c871SZhang Yubing 20996027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2) 21006027c871SZhang Yubing { 21016027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 21026027c871SZhang Yubing struct base2_disp_info *disp_info = conn_state->disp_info; 21036027c871SZhang Yubing const char *enable_flag; 21046027c871SZhang Yubing if (!disp_info) { 21056027c871SZhang Yubing printf("disp_info is empty\n"); 21066027c871SZhang Yubing return; 21076027c871SZhang Yubing } 21086027c871SZhang Yubing 21096027c871SZhang Yubing enable_flag = (const char *)&disp_info->cacm_header; 21106027c871SZhang Yubing if (strncasecmp(enable_flag, "CACM", 4)) { 21116027c871SZhang Yubing printf("acm and csc is not support\n"); 21126027c871SZhang Yubing return; 21136027c871SZhang Yubing } 21146027c871SZhang Yubing 21156027c871SZhang Yubing vop3_post_acm_config(state, vop2); 21166027c871SZhang Yubing vop3_post_csc_config(state, vop2); 21176027c871SZhang Yubing } 21186027c871SZhang Yubing 2119d2e91fdcSDamon Ding /* 2120d2e91fdcSDamon Ding * Read VOP internal power domain on/off status. 2121d2e91fdcSDamon Ding * We should query BISR_STS register in PMU for 2122d2e91fdcSDamon Ding * power up/down status when memory repair is enabled. 2123d2e91fdcSDamon Ding * Return value: 1 for power on, 0 for power off; 2124d2e91fdcSDamon Ding */ 212560e469f5SDamon Ding static int vop2_wait_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 212660e469f5SDamon Ding { 212760e469f5SDamon Ding int val = 0; 212860e469f5SDamon Ding int shift = 0; 2129b6ba80b4SDamon Ding int shift_factor = 0; 213060e469f5SDamon Ding bool is_bisr_en = false; 213160e469f5SDamon Ding 2132b6ba80b4SDamon Ding /* 2133b6ba80b4SDamon Ding * The order of pd status bits in BISR_STS register 2134b6ba80b4SDamon Ding * is different from that in VOP SYS_STS register. 2135b6ba80b4SDamon Ding */ 2136b6ba80b4SDamon Ding if (pd_data->id == VOP2_PD_DSC_8K || 2137b6ba80b4SDamon Ding pd_data->id == VOP2_PD_DSC_4K || 2138b6ba80b4SDamon Ding pd_data->id == VOP2_PD_ESMART) 2139b6ba80b4SDamon Ding shift_factor = 1; 2140b6ba80b4SDamon Ding 2141b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor; 2142b6ba80b4SDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift); 214360e469f5SDamon Ding if (is_bisr_en) { 2144b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor; 2145b6ba80b4SDamon Ding 214660e469f5SDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 2147d2e91fdcSDamon Ding ((val >> shift) & 0x1), 50 * 1000); 214860e469f5SDamon Ding } else { 2149b6ba80b4SDamon Ding shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1; 2150b6ba80b4SDamon Ding 215160e469f5SDamon Ding return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 215260e469f5SDamon Ding !((val >> shift) & 0x1), 50 * 1000); 215360e469f5SDamon Ding } 215460e469f5SDamon Ding } 215560e469f5SDamon Ding 2156b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id) 215760e469f5SDamon Ding { 215860e469f5SDamon Ding struct vop2_power_domain_data *pd_data; 215960e469f5SDamon Ding int ret = 0; 216060e469f5SDamon Ding 2161b6ba80b4SDamon Ding if (!pd_id) 2162b6ba80b4SDamon Ding return 0; 2163b6ba80b4SDamon Ding 2164b6ba80b4SDamon Ding pd_data = vop2_find_pd_data_by_id(vop2, pd_id); 2165b6ba80b4SDamon Ding if (!pd_data) { 2166b6ba80b4SDamon Ding printf("can't find pd_data by id\n"); 216760e469f5SDamon Ding return -EINVAL; 216860e469f5SDamon Ding } 21692c66af11SDamon Ding 2170b6ba80b4SDamon Ding if (pd_data->parent_id) { 2171b6ba80b4SDamon Ding ret = vop2_power_domain_on(vop2, pd_data->parent_id); 217260e469f5SDamon Ding if (ret) { 217360e469f5SDamon Ding printf("can't open parent power domain\n"); 217460e469f5SDamon Ding return -EINVAL; 217560e469f5SDamon Ding } 217660e469f5SDamon Ding } 217760e469f5SDamon Ding 2178b6ba80b4SDamon Ding vop2_mask_write(vop2, RK3568_SYS_PD_CTRL, EN_MASK, 2179b6ba80b4SDamon Ding RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_id) - 1, 0, false); 218060e469f5SDamon Ding ret = vop2_wait_power_domain_on(vop2, pd_data); 218160e469f5SDamon Ding if (ret) { 218260e469f5SDamon Ding printf("wait vop2 power domain timeout\n"); 218360e469f5SDamon Ding return ret; 218460e469f5SDamon Ding } 218560e469f5SDamon Ding 218660e469f5SDamon Ding return 0; 218760e469f5SDamon Ding } 218860e469f5SDamon Ding 2189ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2) 2190ecc31b6eSAndy Yan { 2191ecc31b6eSAndy Yan u32 *base = vop2->regs; 2192ecc31b6eSAndy Yan int i = 0; 2193ecc31b6eSAndy Yan 2194ecc31b6eSAndy Yan /* 2195ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 2196ecc31b6eSAndy Yan */ 2197ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++) 2198ecc31b6eSAndy Yan vop2->regsbak[i] = base[i]; 2199ecc31b6eSAndy Yan } 2200ecc31b6eSAndy Yan 22015fa6e665SDamon Ding static void vop3_overlay_init(struct vop2 *vop2, struct display_state *state) 22025fa6e665SDamon Ding { 22035fa6e665SDamon Ding struct vop2_win_data *win_data; 22045fa6e665SDamon Ding int layer_phy_id = 0; 22055fa6e665SDamon Ding int i, j; 22065fa6e665SDamon Ding u32 ovl_port_offset = 0; 22075fa6e665SDamon Ding u32 layer_nr = 0; 22085fa6e665SDamon Ding u8 shift = 0; 22095fa6e665SDamon Ding 22105fa6e665SDamon Ding /* layer sel win id */ 22115fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22125fa6e665SDamon Ding shift = 0; 22135fa6e665SDamon Ding ovl_port_offset = 0x100 * i; 22145fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22155fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22165fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22175fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22185fa6e665SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + ovl_port_offset, LAYER_SEL_MASK, 22195fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 22205fa6e665SDamon Ding shift += 4; 22215fa6e665SDamon Ding } 22225fa6e665SDamon Ding } 22235fa6e665SDamon Ding 22245fa6e665SDamon Ding /* win sel port */ 22255fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22265fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22275fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22285fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 22295fa6e665SDamon Ding continue; 22305fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22315fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22325fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 22335fa6e665SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL_IMD, LAYER_SEL_PORT_MASK, 22345fa6e665SDamon Ding shift, i, false); 22355fa6e665SDamon Ding } 22365fa6e665SDamon Ding } 22375fa6e665SDamon Ding } 22385fa6e665SDamon Ding 22395fa6e665SDamon Ding static void vop2_overlay_init(struct vop2 *vop2, struct display_state *state) 22405fa6e665SDamon Ding { 22415fa6e665SDamon Ding struct crtc_state *cstate = &state->crtc_state; 22425fa6e665SDamon Ding struct vop2_win_data *win_data; 22435fa6e665SDamon Ding int layer_phy_id = 0; 22445fa6e665SDamon Ding int total_used_layer = 0; 22455fa6e665SDamon Ding int port_mux = 0; 22465fa6e665SDamon Ding int i, j; 22475fa6e665SDamon Ding u32 layer_nr = 0; 22485fa6e665SDamon Ding u8 shift = 0; 22495fa6e665SDamon Ding 22505fa6e665SDamon Ding /* layer sel win id */ 22515fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22525fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22535fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22545fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22555fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22565fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 22575fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 22585fa6e665SDamon Ding shift += 4; 22595fa6e665SDamon Ding } 22605fa6e665SDamon Ding } 22615fa6e665SDamon Ding 22625fa6e665SDamon Ding /* win sel port */ 22635fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22645fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22655fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22665fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 22675fa6e665SDamon Ding continue; 22685fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22695fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22705fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 22715fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 22725fa6e665SDamon Ding LAYER_SEL_PORT_SHIFT + shift, i, false); 22735fa6e665SDamon Ding } 22745fa6e665SDamon Ding } 22755fa6e665SDamon Ding 22765fa6e665SDamon Ding /** 22775fa6e665SDamon Ding * port mux config 22785fa6e665SDamon Ding */ 22795fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22805fa6e665SDamon Ding shift = i * 4; 22815fa6e665SDamon Ding if (vop2->vp_plane_mask[i].attached_layers_nr) { 22825fa6e665SDamon Ding total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 22835fa6e665SDamon Ding port_mux = total_used_layer - 1; 22845fa6e665SDamon Ding } else { 22855fa6e665SDamon Ding port_mux = 8; 22865fa6e665SDamon Ding } 22875fa6e665SDamon Ding 22885fa6e665SDamon Ding if (i == vop2->data->nr_vps - 1) 22895fa6e665SDamon Ding port_mux = vop2->data->nr_mixers; 22905fa6e665SDamon Ding 22915fa6e665SDamon Ding cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 22925fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 22935fa6e665SDamon Ding PORT_MUX_SHIFT + shift, port_mux, false); 22945fa6e665SDamon Ding } 22955fa6e665SDamon Ding } 22965fa6e665SDamon Ding 22975fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win) 22985fa6e665SDamon Ding { 22995fa6e665SDamon Ding if (!is_vop3(vop2)) 23005fa6e665SDamon Ding return false; 23015fa6e665SDamon Ding 23025fa6e665SDamon Ding if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE && 23035fa6e665SDamon Ding win->phys_id != ROCKCHIP_VOP2_ESMART0) 23045fa6e665SDamon Ding return true; 23055fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE && 23065fa6e665SDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) 23075fa6e665SDamon Ding return true; 23085fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && 23095fa6e665SDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART1) 23105fa6e665SDamon Ding return true; 23115fa6e665SDamon Ding else 23125fa6e665SDamon Ding return false; 23135fa6e665SDamon Ding } 23145fa6e665SDamon Ding 23155fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2) 23165fa6e665SDamon Ding { 23175fa6e665SDamon Ding struct vop2_win_data *win_data; 2318fa4ecc32SDamon Ding int i; 23195fa6e665SDamon Ding u8 scale_engine_num = 0; 23205fa6e665SDamon Ding 23215fa6e665SDamon Ding /* store plane mask for vop2_fixup_dts */ 2322fa4ecc32SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 2323fa4ecc32SDamon Ding win_data = &vop2->data->win_data[i]; 23245fa6e665SDamon Ding if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data)) 23255fa6e665SDamon Ding continue; 23265fa6e665SDamon Ding 23275fa6e665SDamon Ding win_data->scale_engine_num = scale_engine_num++; 23285fa6e665SDamon Ding } 23295fa6e665SDamon Ding } 23305fa6e665SDamon Ding 2331b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 2332d0408543SAndy Yan { 2333b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 2334b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 23355fa6e665SDamon Ding int layer_phy_id = 0; 23365fa6e665SDamon Ding int i, j; 2337fa4ecc32SDamon Ding int ret; 23385fa6e665SDamon Ding u32 layer_nr = 0; 2339d0408543SAndy Yan 234063cb669fSSandy Huang if (vop2->global_init) 2341d0408543SAndy Yan return; 234263cb669fSSandy Huang 2343b0989546SSandy Huang /* OTP must enable at the first time, otherwise mirror layer register is error */ 234463cb669fSSandy Huang if (soc_is_rk3566()) 234563cb669fSSandy Huang vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 234663cb669fSSandy Huang OTP_WIN_EN_SHIFT, 1, false); 2347b0989546SSandy Huang 2348b0989546SSandy Huang if (cstate->crtc->assign_plane) {/* dts assign plane */ 2349b0989546SSandy Huang u32 plane_mask; 2350b0989546SSandy Huang int primary_plane_id; 2351b0989546SSandy Huang 2352b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2353b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask; 2354b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2355b0989546SSandy Huang layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 2356b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 23575fc2b656SDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 2358337d1c13SDamon Ding if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX) 2359b0989546SSandy Huang primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 2360b0989546SSandy Huang vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 2361b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2362b0989546SSandy Huang 2363b0989546SSandy Huang /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 2364b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2365b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 2366b0989546SSandy Huang plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 236763cb669fSSandy Huang } 2368b0989546SSandy Huang } 2369b0989546SSandy Huang } else {/* need soft assign plane mask */ 2370b0989546SSandy Huang /* find the first unplug devices and set it as main display */ 2371b0989546SSandy Huang int main_vp_index = -1; 2372b0989546SSandy Huang int active_vp_num = 0; 2373b0989546SSandy Huang 2374b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2375b0989546SSandy Huang if (cstate->crtc->vps[i].enable) 2376b0989546SSandy Huang active_vp_num++; 2377b0989546SSandy Huang } 2378b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num); 2379b0989546SSandy Huang 2380b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2) 2381b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n"); 2382b0989546SSandy Huang plane_mask = vop2->data->plane_mask; 2383b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 23845fa6e665SDamon Ding /* 23855fa6e665SDamon Ding * For rk3528, one display policy for hdmi store in plane_mask[0], and the other 23865fa6e665SDamon Ding * for cvbs store in plane_mask[2]. 23875fa6e665SDamon Ding */ 23885fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 && 23895fa6e665SDamon Ding cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV) 23905fa6e665SDamon Ding plane_mask += 2 * VOP2_VP_MAX; 2391b0989546SSandy Huang 23925fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528) { 23935fa6e665SDamon Ding /* 23945fa6e665SDamon Ding * For rk3528, the plane mask of vp is limited, only esmart2 can be selected 23955fa6e665SDamon Ding * by both vp0 and vp1. 23965fa6e665SDamon Ding */ 23975fa6e665SDamon Ding j = 0; 23985fa6e665SDamon Ding } else { 2399b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2400b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 2401b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/ 2402b0989546SSandy Huang main_vp_index = i; 2403e007876dSSandy Huang break; 2404b0989546SSandy Huang } 2405b0989546SSandy Huang } 2406b0989546SSandy Huang 2407b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */ 2408b0989546SSandy Huang if (main_vp_index < 0) { 2409b0989546SSandy Huang main_vp_index = 0; 2410b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0]; 2411b0989546SSandy Huang } 2412b0989546SSandy Huang 2413b0989546SSandy Huang j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */ 24145fa6e665SDamon Ding } 2415b0989546SSandy Huang 2416b0989546SSandy Huang /* init other display except main display */ 2417b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2418b0989546SSandy Huang if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */ 2419b0989546SSandy Huang continue; 2420b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++]; 2421b0989546SSandy Huang } 2422b0989546SSandy Huang 2423b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */ 2424b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2425b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 2426b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2427b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 2428b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 2429b0989546SSandy Huang } 2430b0989546SSandy Huang } 2431b0989546SSandy Huang } 2432b0989546SSandy Huang 243360e469f5SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 243460e469f5SDamon Ding rk3588_vop2_regsbak(vop2); 243560e469f5SDamon Ding else 243660e469f5SDamon Ding memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 243760e469f5SDamon Ding 243860e469f5SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 243960e469f5SDamon Ding OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 244060e469f5SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 244160e469f5SDamon Ding IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 244260e469f5SDamon Ding 2443b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2444b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 2445b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 2446b0989546SSandy Huang printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]); 2447b0989546SSandy Huang printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id); 2448b0989546SSandy Huang } 2449b0989546SSandy Huang 24505fa6e665SDamon Ding if (is_vop3(vop2)) 24515fa6e665SDamon Ding vop3_overlay_init(vop2, state); 24525fa6e665SDamon Ding else 24535fa6e665SDamon Ding vop2_overlay_init(vop2, state); 2454b0989546SSandy Huang 24555fa6e665SDamon Ding if (is_vop3(vop2)) { 24565fa6e665SDamon Ding /* 24575fa6e665SDamon Ding * you can rewrite at dts vop node: 24585fa6e665SDamon Ding * 24595fa6e665SDamon Ding * VOP3_ESMART_8K_MODE = 0, 24605fa6e665SDamon Ding * VOP3_ESMART_4K_4K_MODE = 1, 24615fa6e665SDamon Ding * VOP3_ESMART_4K_2K_2K_MODE = 2, 24625fa6e665SDamon Ding * VOP3_ESMART_2K_2K_2K_2K_MODE = 3, 24635fa6e665SDamon Ding * 24645fa6e665SDamon Ding * &vop { 24655fa6e665SDamon Ding * esmart_lb_mode = /bits/ 8 <2>; 24665fa6e665SDamon Ding * }; 246763cb669fSSandy Huang */ 2468fa4ecc32SDamon Ding ret = ofnode_read_u32(cstate->node, "esmart_lb_mode", &vop2->esmart_lb_mode); 2469fa4ecc32SDamon Ding if (ret < 0) 24705fa6e665SDamon Ding vop2->esmart_lb_mode = vop2->data->esmart_lb_mode; 24715fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, ESMART_LB_MODE_SEL_MASK, 24725fa6e665SDamon Ding ESMART_LB_MODE_SEL_SHIFT, vop2->esmart_lb_mode, false); 2473d0408543SAndy Yan 24745fa6e665SDamon Ding vop3_init_esmart_scale_engine(vop2); 2475aa670293SDamon Ding 2476aa670293SDamon Ding vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK, 2477aa670293SDamon Ding DSP_VS_T_SEL_SHIFT, 0, false); 247863cb669fSSandy Huang } 247963cb669fSSandy Huang 2480ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568) 248163cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 248263cb669fSSandy Huang 248363cb669fSSandy Huang vop2->global_init = true; 2484d0408543SAndy Yan } 2485d0408543SAndy Yan 2486d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state) 2487d0408543SAndy Yan { 2488d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 248963cb669fSSandy Huang int ret; 2490d0408543SAndy Yan 2491d0408543SAndy Yan /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 2492d0408543SAndy Yan ret = clk_set_defaults(cstate->dev); 2493d0408543SAndy Yan if (ret) 2494d0408543SAndy Yan debug("%s clk_set_defaults failed %d\n", __func__, ret); 2495d0408543SAndy Yan 24961147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state); 24976414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state); 2498d0408543SAndy Yan 2499d0408543SAndy Yan return 0; 2500d0408543SAndy Yan } 2501d0408543SAndy Yan 2502d0408543SAndy Yan /* 2503d0408543SAndy Yan * VOP2 have multi video ports. 2504d0408543SAndy Yan * video port ------- crtc 2505d0408543SAndy Yan */ 2506d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state) 2507d0408543SAndy Yan { 2508d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2509d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data; 2510d0408543SAndy Yan 2511d0408543SAndy Yan if (!rockchip_vop2) { 25120d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2)); 2513d0408543SAndy Yan if (!rockchip_vop2) 2514d0408543SAndy Yan return -ENOMEM; 2515*d8e7f4a5SSandy Huang memset(rockchip_vop2, 0, sizeof(struct vop2)); 2516d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 2517d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG; 2518*d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD 2519*d8e7f4a5SSandy Huang rockchip_vop2->regs = (void *)RK3528_VOP_BASE; 2520*d8e7f4a5SSandy Huang #else 2521*d8e7f4a5SSandy Huang rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 252263cb669fSSandy Huang rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2523d0408543SAndy Yan if (rockchip_vop2->grf <= 0) 252463cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 2525*d8e7f4a5SSandy Huang #endif 2526d0408543SAndy Yan rockchip_vop2->version = vop2_data->version; 2527d0408543SAndy Yan rockchip_vop2->data = vop2_data; 2528ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) { 2529b890760eSAlgea Cao struct regmap *map; 2530b890760eSAlgea Cao 2531ecc31b6eSAndy Yan rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF); 2532ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0) 2533ecc31b6eSAndy Yan printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf); 2534b890760eSAlgea Cao map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); 2535b890760eSAlgea Cao rockchip_vop2->vo1_grf = regmap_get_range(map, 0); 2536ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0) 2537ecc31b6eSAndy Yan printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf); 253860e469f5SDamon Ding rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); 2539b890760eSAlgea Cao if (rockchip_vop2->sys_pmu <= 0) 254060e469f5SDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu); 2541ecc31b6eSAndy Yan } 2542d0408543SAndy Yan } 2543d0408543SAndy Yan 2544d0408543SAndy Yan cstate->private = rockchip_vop2; 254563cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 254663cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 2547d0408543SAndy Yan 254889912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state); 254989912f2dSSandy Huang 2550d0408543SAndy Yan return 0; 2551d0408543SAndy Yan } 2552d0408543SAndy Yan 2553ecc31b6eSAndy Yan /* 2554ecc31b6eSAndy Yan * calc the dclk on rk3588 2555ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4 2556ecc31b6eSAndy Yan * 2557ecc31b6eSAndy Yan */ 2558ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 2559ecc31b6eSAndy Yan { 2560ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk) 2561ecc31b6eSAndy Yan return child_clk * 4; 2562ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk) 2563ecc31b6eSAndy Yan return child_clk * 2; 2564ecc31b6eSAndy Yan else if (child_clk <= max_dclk) 2565ecc31b6eSAndy Yan return child_clk; 2566ecc31b6eSAndy Yan else 2567ecc31b6eSAndy Yan return 0; 2568ecc31b6eSAndy Yan } 2569ecc31b6eSAndy Yan 2570ecc31b6eSAndy Yan /* 2571ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588 2572ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core 2573ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core 2574ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core 2575ecc31b6eSAndy Yan */ 2576ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state, 2577ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div, 2578ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div) 2579d0408543SAndy Yan { 2580d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2581d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 2582d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2583d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 25840a1fb152SZhang Yubing unsigned long v_pixclk = mode->crtc_clock; 2585ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2; 2586ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk; 2587ecc31b6eSAndy Yan unsigned long dclk_out_rate; 2588ecc31b6eSAndy Yan u64 if_dclk_rate; 2589ecc31b6eSAndy Yan u64 if_pixclk_rate; 2590ecc31b6eSAndy Yan int output_type = conn_state->type; 2591ecc31b6eSAndy Yan int output_mode = conn_state->output_mode; 2592ecc31b6eSAndy Yan int K = 1; 2593ecc31b6eSAndy Yan 25940a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE && 25950a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 25960a1fb152SZhang Yubing printf("Dual channel and YUV420 can't work together\n"); 25970a1fb152SZhang Yubing return -EINVAL; 25980a1fb152SZhang Yubing } 25990a1fb152SZhang Yubing 26000a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 26010a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) 26020a1fb152SZhang Yubing K = 2; 26030a1fb152SZhang Yubing 2604ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 2605ecc31b6eSAndy Yan /* 2606ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 2607ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 2608ecc31b6eSAndy Yan */ 26090a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 26100a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 2611b890760eSAlgea Cao dclk_rate = dclk_rate >> 1; 2612ecc31b6eSAndy Yan K = 2; 2613b890760eSAlgea Cao } 261412ee5af0SDamon Ding if (cstate->dsc_enable) { 261512ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate << 1; 261612ee5af0SDamon Ding if_dclk_rate = cstate->dsc_cds_clk_rate; 2617ecc31b6eSAndy Yan } else { 2618ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K; 2619ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K; 2620ecc31b6eSAndy Yan } 2621ecc31b6eSAndy Yan 2622631ee99aSZhang Yubing if (v_pixclk > VOP2_MAX_DCLK_RATE) 26234b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_core_rate, 26244b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 2625631ee99aSZhang Yubing 2626ecc31b6eSAndy Yan if (!dclk_rate) { 2627ecc31b6eSAndy Yan printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 26284b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate); 2629ecc31b6eSAndy Yan return -EINVAL; 2630ecc31b6eSAndy Yan } 2631ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 2632ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate; 2633b890760eSAlgea Cao *dclk_core_div = dclk_rate / dclk_core_rate; 2634b890760eSAlgea Cao printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n", 2635b890760eSAlgea Cao dclk_rate, *if_pixclk_div, *if_dclk_div); 2636ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 2637ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */ 2638ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K; 2639ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K; 2640ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K; 2641ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2642ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 2643ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div; 2644ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 2645ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2; 26460a1fb152SZhang Yubing dclk_out_rate = dclk_out_rate / K; 2647ecc31b6eSAndy Yan 26484b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 26494b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 2650ecc31b6eSAndy Yan if (!dclk_rate) { 2651ecc31b6eSAndy Yan printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 26524b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate); 2653ecc31b6eSAndy Yan return -EINVAL; 2654ecc31b6eSAndy Yan } 2655ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 2656ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2657ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 2658ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2659ecc31b6eSAndy Yan K = 2; 266012ee5af0SDamon Ding if (cstate->dsc_enable) 266112ee5af0SDamon Ding /* dsc output is 96bit, dsi input is 192 bit */ 266212ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1; 2663ecc31b6eSAndy Yan else 2664ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K; 2665ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 266612ee5af0SDamon Ding dclk_out_rate = dclk_core_rate / K; 2667ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 26684b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 26694b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 26709f076eccSZhang Yubing if (!dclk_rate) { 26719f076eccSZhang Yubing printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n", 26724b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate); 26739f076eccSZhang Yubing return -EINVAL; 26749f076eccSZhang Yubing } 267512ee5af0SDamon Ding 267612ee5af0SDamon Ding if (cstate->dsc_enable) 2677d57af898SDamon Ding dclk_rate /= cstate->dsc_slice_num; 267812ee5af0SDamon Ding 2679ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 2680ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2681ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 268212ee5af0SDamon Ding if (cstate->dsc_enable) 26831ace1b6dSDamon Ding *if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate; 2684ecc31b6eSAndy Yan 2685ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 2686ecc31b6eSAndy Yan dclk_rate = v_pixclk; 2687ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2688ecc31b6eSAndy Yan } 2689ecc31b6eSAndy Yan 2690ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div); 2691ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div); 2692ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div); 2693ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div); 2694ecc31b6eSAndy Yan 2695ecc31b6eSAndy Yan return dclk_rate; 2696ecc31b6eSAndy Yan } 2697ecc31b6eSAndy Yan 269812ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state) 2699ecc31b6eSAndy Yan { 270012ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 2701ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 270212ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 27031ace1b6dSDamon Ding u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */ 2704ecc31b6eSAndy Yan u8 k = 1; 2705ecc31b6eSAndy Yan 2706ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2707ecc31b6eSAndy Yan k = 2; 2708ecc31b6eSAndy Yan 270912ee5af0SDamon Ding cstate->dsc_txp_clk_rate = v_pixclk; 271012ee5af0SDamon Ding do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k)); 2711ecc31b6eSAndy Yan 271212ee5af0SDamon Ding cstate->dsc_pxl_clk_rate = v_pixclk; 271312ee5af0SDamon Ding do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k)); 2714ecc31b6eSAndy Yan 2715ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 2716ecc31b6eSAndy Yan * cds_dat_width = 96; 2717ecc31b6eSAndy Yan * bits_per_pixel = [8-12]; 2718b61227a3SDamon Ding * As cds clk is div from txp clk and only support 1/2/4 div, 2719b61227a3SDamon Ding * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4, 2720b61227a3SDamon Ding * otherwise dsc_cds = crtc_clock / 8; 2721ecc31b6eSAndy Yan */ 2722b61227a3SDamon Ding cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8); 2723ecc31b6eSAndy Yan 2724ecc31b6eSAndy Yan return 0; 2725ecc31b6eSAndy Yan } 2726ecc31b6eSAndy Yan 2727ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 2728ecc31b6eSAndy Yan { 2729ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2730ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2731ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 273212ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 2733ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 273452ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2735ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2736ecc31b6eSAndy Yan int output_if = conn_state->output_if; 2737ecc31b6eSAndy Yan int if_pixclk_div = 0; 2738ecc31b6eSAndy Yan int if_dclk_div = 0; 2739ecc31b6eSAndy Yan unsigned long dclk_rate; 2740d0408543SAndy Yan u32 val; 2741ecc31b6eSAndy Yan 2742b890760eSAlgea Cao if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 2743b890760eSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 2744b890760eSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 2745b890760eSAlgea Cao } else { 2746ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 2747ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2748b890760eSAlgea Cao } 2749ecc31b6eSAndy Yan 275012ee5af0SDamon Ding if (cstate->dsc_enable) { 275112ee5af0SDamon Ding int k = 1; 275212ee5af0SDamon Ding 2753ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) { 275412ee5af0SDamon Ding printf("Unsupported DSC\n"); 2755ecc31b6eSAndy Yan return 0; 2756ecc31b6eSAndy Yan } 275712ee5af0SDamon Ding 275812ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 275912ee5af0SDamon Ding k = 2; 276012ee5af0SDamon Ding 276112ee5af0SDamon Ding cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 276212ee5af0SDamon Ding cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k; 276312ee5af0SDamon Ding cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num; 276412ee5af0SDamon Ding 276512ee5af0SDamon Ding vop2_calc_dsc_clk(state); 276612ee5af0SDamon Ding printf("Enable DSC%d slice:%dx%d, slice num:%d\n", 276712ee5af0SDamon Ding cstate->dsc_id, dsc_sink_cap->slice_width, 276812ee5af0SDamon Ding dsc_sink_cap->slice_height, cstate->dsc_slice_num); 2769ecc31b6eSAndy Yan } 2770ecc31b6eSAndy Yan 2771b61227a3SDamon Ding dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div); 2772ecc31b6eSAndy Yan 2773ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) { 2774ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2775ecc31b6eSAndy Yan 4, false); 2776ecc31b6eSAndy Yan } 2777ecc31b6eSAndy Yan 2778ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) { 2779ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2780ecc31b6eSAndy Yan 3, false); 2781ecc31b6eSAndy Yan } 2782ecc31b6eSAndy Yan 2783ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) { 2784ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2785ecc31b6eSAndy Yan 2, false); 2786ecc31b6eSAndy Yan } 2787ecc31b6eSAndy Yan 2788ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) { 2789ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2790ecc31b6eSAndy Yan val = 0; 2791ecc31b6eSAndy Yan else 2792ecc31b6eSAndy Yan val = 1; 279341874944SGuochun Huang 27943df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 279541874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 279641874944SGuochun Huang RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 279741874944SGuochun Huang 2798ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 2799ecc31b6eSAndy Yan 1, false); 2800ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 2801ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 2802ecc31b6eSAndy Yan if_pixclk_div, false); 280341874944SGuochun Huang 280441874944SGuochun Huang if (conn_state->hold_mode) { 280541874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 28068e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 280741874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 280841874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 280941874944SGuochun Huang } 2810ecc31b6eSAndy Yan } 2811ecc31b6eSAndy Yan 2812ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) { 2813ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2814ecc31b6eSAndy Yan val = 0; 2815ecc31b6eSAndy Yan else if (cstate->crtc_id == 3) 2816ecc31b6eSAndy Yan val = 1; 2817ecc31b6eSAndy Yan else 2818ecc31b6eSAndy Yan val = 3; /*VP1*/ 28193df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 282041874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 282141874944SGuochun Huang RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 282241874944SGuochun Huang 2823ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 2824ecc31b6eSAndy Yan 1, false); 2825ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 2826ecc31b6eSAndy Yan val, false); 2827ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 2828ecc31b6eSAndy Yan if_pixclk_div, false); 282941874944SGuochun Huang 283041874944SGuochun Huang if (conn_state->hold_mode) { 283141874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 28328e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 283341874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 283441874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 283541874944SGuochun Huang } 2836ecc31b6eSAndy Yan } 2837ecc31b6eSAndy Yan 2838ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 28393df6e59eSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 28403df6e59eSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 2841ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2842ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2843ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 2844ecc31b6eSAndy Yan false); 28450a1fb152SZhang Yubing switch (conn_state->type) { 28460a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DisplayPort: 28470a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28480a1fb152SZhang Yubing RK3588_DP_DUAL_EN_SHIFT, 1, false); 28490a1fb152SZhang Yubing break; 28500a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_eDP: 28510a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28520a1fb152SZhang Yubing RK3588_EDP_DUAL_EN_SHIFT, 1, false); 28530a1fb152SZhang Yubing break; 28540a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_HDMIA: 28550a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28560a1fb152SZhang Yubing RK3588_HDMI_DUAL_EN_SHIFT, 1, false); 28570a1fb152SZhang Yubing break; 28580a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DSI: 28590a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28600a1fb152SZhang Yubing RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 28610a1fb152SZhang Yubing break; 28620a1fb152SZhang Yubing default: 28630a1fb152SZhang Yubing break; 28640a1fb152SZhang Yubing } 2865ecc31b6eSAndy Yan } 2866ecc31b6eSAndy Yan 2867ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) { 2868ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 2869ecc31b6eSAndy Yan 1, false); 2870ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2871ecc31b6eSAndy Yan cstate->crtc_id, false); 2872ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2873ecc31b6eSAndy Yan if_dclk_div, false); 2874ecc31b6eSAndy Yan 2875ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2876ecc31b6eSAndy Yan if_pixclk_div, false); 2877ecc31b6eSAndy Yan 2878ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2879ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 2880ecc31b6eSAndy Yan } 2881ecc31b6eSAndy Yan 2882ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) { 2883ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 2884ecc31b6eSAndy Yan 1, false); 2885ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2886ecc31b6eSAndy Yan cstate->crtc_id, false); 2887ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2888ecc31b6eSAndy Yan if_dclk_div, false); 2889ecc31b6eSAndy Yan 2890ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2891ecc31b6eSAndy Yan if_pixclk_div, false); 28921848455fSDamon Ding 28931848455fSDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 28941848455fSDamon Ding RK3588_GRF_EDP1_ENABLE_SHIFT, 1); 2895ecc31b6eSAndy Yan } 2896ecc31b6eSAndy Yan 2897ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) { 2898ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 2899ecc31b6eSAndy Yan 1, false); 2900ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2901ecc31b6eSAndy Yan cstate->crtc_id, false); 2902ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2903ecc31b6eSAndy Yan if_dclk_div, false); 2904ecc31b6eSAndy Yan 2905ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2906ecc31b6eSAndy Yan if_pixclk_div, false); 2907b890760eSAlgea Cao 2908b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2909b890760eSAlgea Cao RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1); 2910b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2911b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2912b890760eSAlgea Cao HDMI0_SYNC_POL_SHIFT, val); 2913ecc31b6eSAndy Yan } 2914ecc31b6eSAndy Yan 2915ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) { 2916ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 2917ecc31b6eSAndy Yan 1, false); 2918ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2919ecc31b6eSAndy Yan cstate->crtc_id, false); 2920ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2921ecc31b6eSAndy Yan if_dclk_div, false); 2922ecc31b6eSAndy Yan 2923ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2924ecc31b6eSAndy Yan if_pixclk_div, false); 2925b890760eSAlgea Cao 2926b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2927b890760eSAlgea Cao RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1); 2928b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2929b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2930b890760eSAlgea Cao HDMI1_SYNC_POL_SHIFT, val); 2931ecc31b6eSAndy Yan } 2932ecc31b6eSAndy Yan 2933ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) { 2934ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 2935ecc31b6eSAndy Yan 1, false); 2936ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 2937ecc31b6eSAndy Yan cstate->crtc_id, false); 2938ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2939ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false); 2940ecc31b6eSAndy Yan } 2941ecc31b6eSAndy Yan 2942ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) { 2943108c5f8bSZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT, 2944ecc31b6eSAndy Yan 1, false); 2945ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 2946ecc31b6eSAndy Yan cstate->crtc_id, false); 2947ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2948ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false); 2949ecc31b6eSAndy Yan } 2950ecc31b6eSAndy Yan 2951ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2952b61227a3SDamon Ding DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false); 2953ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2954b61227a3SDamon Ding DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false); 2955ecc31b6eSAndy Yan 2956ecc31b6eSAndy Yan return dclk_rate; 2957ecc31b6eSAndy Yan } 2958ecc31b6eSAndy Yan 2959ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 2960ecc31b6eSAndy Yan { 2961ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2962ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2963ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2964ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2965ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 2966d0408543SAndy Yan bool dclk_inv; 2967ecc31b6eSAndy Yan u32 val; 29688895aec1SSandy Huang 2969d0408543SAndy Yan dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 297010ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 297110ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2972d0408543SAndy Yan 2973d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 2974d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 2975d0408543SAndy Yan 1, false); 2976d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2977d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 297815f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 297915f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 2980ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 2981c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 2982d0408543SAndy Yan } 2983d0408543SAndy Yan 2984d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 298552ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 298652ee18acSSandy Huang 1, false); 2987d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 2988d0408543SAndy Yan BT1120_EN_SHIFT, 1, false); 2989d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2990d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 2991ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 299252ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 2993d0408543SAndy Yan } 2994d0408543SAndy Yan 2995d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 2996d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 2997d0408543SAndy Yan 1, false); 2998d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2999d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 3000ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 300152ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 3002d0408543SAndy Yan } 3003d0408543SAndy Yan 3004d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3005d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3006d0408543SAndy Yan 1, false); 3007d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3008d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false); 300915f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 301015f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 301111f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 301215f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3013d0408543SAndy Yan } 3014d0408543SAndy Yan 3015d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 3016d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 3017d0408543SAndy Yan 1, false); 3018d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3019d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false); 302015f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 302115f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 302211f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 302315f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3024d0408543SAndy Yan } 3025d0408543SAndy Yan 3026d0408543SAndy Yan if (conn_state->output_flags & 3027d0408543SAndy Yan (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 3028d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 3029d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3030d0408543SAndy Yan LVDS_DUAL_EN_SHIFT, 1, false); 3031d0408543SAndy Yan if (conn_state->output_flags & 3032d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3033d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3034d0408543SAndy Yan LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 3035d0408543SAndy Yan false); 3036d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3037d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3038d0408543SAndy Yan LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 3039d0408543SAndy Yan } 3040d0408543SAndy Yan 3041d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3042d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3043d0408543SAndy Yan 1, false); 3044d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3045d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3046d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3047c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3048d0408543SAndy Yan } 3049d0408543SAndy Yan 3050d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 3051d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 3052d0408543SAndy Yan 1, false); 3053d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3054d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false); 3055d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3056c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3057d0408543SAndy Yan } 3058d0408543SAndy Yan 3059d0408543SAndy Yan if (conn_state->output_flags & 3060d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 3061d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3062d0408543SAndy Yan MIPI_DUAL_EN_SHIFT, 1, false); 3063d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3064d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3065d0408543SAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 3066d0408543SAndy Yan false); 3067d0408543SAndy Yan } 3068d0408543SAndy Yan 3069d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 3070d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 3071d0408543SAndy Yan 1, false); 3072d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3073d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false); 3074c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3075c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 30767bcdc6eeSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK, 30777bcdc6eeSDamon Ding IF_CTRL_EDP_PIN_POL_SHIFT, val, false); 3078d0408543SAndy Yan } 3079d0408543SAndy Yan 3080d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 3081d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 3082d0408543SAndy Yan 1, false); 3083d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3084d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false); 308510ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 308610ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 308710ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, 308810ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK, 308910ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 3090d0408543SAndy Yan } 309110ee9f5bSAlgea Cao 3092ecc31b6eSAndy Yan return mode->clock; 3093ecc31b6eSAndy Yan } 3094ecc31b6eSAndy Yan 30955fa6e665SDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state) 30965fa6e665SDamon Ding { 30975fa6e665SDamon Ding struct crtc_state *cstate = &state->crtc_state; 30985fa6e665SDamon Ding struct connector_state *conn_state = &state->conn_state; 30995fa6e665SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 31005fa6e665SDamon Ding struct vop2 *vop2 = cstate->private; 31015fa6e665SDamon Ding u32 val; 31025fa6e665SDamon Ding 31035fa6e665SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 31045fa6e665SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 31055fa6e665SDamon Ding 31065fa6e665SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 31075fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 31085fa6e665SDamon Ding 1, false); 31095fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 31105fa6e665SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 31115fa6e665SDamon Ding } 31125fa6e665SDamon Ding 31135fa6e665SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 31145fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 31155fa6e665SDamon Ding 1, false); 31165fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 31175fa6e665SDamon Ding HDMI0_MUX_SHIFT, cstate->crtc_id, false); 31185fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 31195fa6e665SDamon Ding IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 31205fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, 31215fa6e665SDamon Ding IF_CRTL_HDMI_PIN_POL_MASK, 31225fa6e665SDamon Ding IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 31235fa6e665SDamon Ding } 31245fa6e665SDamon Ding 31255fa6e665SDamon Ding return mode->crtc_clock; 31265fa6e665SDamon Ding } 31275fa6e665SDamon Ding 3128452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state) 3129452afb13SDamon Ding { 3130452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 3131452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 3132452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3133452afb13SDamon Ding struct vop2 *vop2 = cstate->private; 3134452afb13SDamon Ding bool dclk_inv; 3135452afb13SDamon Ding u32 val; 3136452afb13SDamon Ding 3137452afb13SDamon Ding dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 3138452afb13SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3139452afb13SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3140452afb13SDamon Ding 3141452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3142452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3143452afb13SDamon Ding 1, false); 3144452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3145452afb13SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 3146452afb13SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK, 3147452afb13SDamon Ding GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 3148452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 314915f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3150452afb13SDamon Ding } 3151452afb13SDamon Ding 3152452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3153452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3154452afb13SDamon Ding 1, false); 3155452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3156452afb13SDamon Ding LVDS0_MUX_SHIFT, cstate->crtc_id, false); 3157452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 315815f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3159452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 316015f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3161452afb13SDamon Ding } 3162452afb13SDamon Ding 3163452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3164452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3165452afb13SDamon Ding 1, false); 3166452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3167452afb13SDamon Ding MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3168452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3169452afb13SDamon Ding RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false); 3170452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 3171452afb13SDamon Ding RK3562_MIPI_PIN_POL_SHIFT, val, false); 3172452afb13SDamon Ding } 3173452afb13SDamon Ding 3174452afb13SDamon Ding return mode->crtc_clock; 3175452afb13SDamon Ding } 3176452afb13SDamon Ding 317765747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state) 317865747de7SDamon Ding { 317965747de7SDamon Ding struct crtc_state *cstate = &state->crtc_state; 318065747de7SDamon Ding struct connector_state *conn_state = &state->conn_state; 318165747de7SDamon Ding struct vop2 *vop2 = cstate->private; 318265747de7SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 318365747de7SDamon Ding u32 output_type = conn_state->type; 318465747de7SDamon Ding u32 data_swap = 0; 318565747de7SDamon Ding 318665747de7SDamon Ding if (is_uv_swap(conn_state->bus_format, conn_state->output_mode)) 318765747de7SDamon Ding data_swap = DSP_RB_SWAP; 318865747de7SDamon Ding 318965747de7SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && 319065747de7SDamon Ding (output_type == DRM_MODE_CONNECTOR_HDMIA || 319165747de7SDamon Ding output_type == DRM_MODE_CONNECTOR_eDP) && 319265747de7SDamon Ding (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 319365747de7SDamon Ding conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 319465747de7SDamon Ding data_swap |= DSP_RG_SWAP; 319565747de7SDamon Ding 319665747de7SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 319765747de7SDamon Ding DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 319865747de7SDamon Ding } 319965747de7SDamon Ding 3200b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent) 3201b890760eSAlgea Cao { 3202b890760eSAlgea Cao int ret = 0; 3203b890760eSAlgea Cao 3204b890760eSAlgea Cao if (parent->dev) 3205b890760eSAlgea Cao ret = clk_set_parent(clk, parent); 3206b890760eSAlgea Cao if (ret < 0) 3207b890760eSAlgea Cao debug("failed to set %s as parent for %s\n", 3208b890760eSAlgea Cao parent->dev->name, clk->dev->name); 3209b890760eSAlgea Cao } 3210b890760eSAlgea Cao 3211b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate) 3212b890760eSAlgea Cao { 3213b890760eSAlgea Cao int ret = 0; 3214b890760eSAlgea Cao 3215b890760eSAlgea Cao if (clk->dev) 3216b890760eSAlgea Cao ret = clk_set_rate(clk, rate); 3217b890760eSAlgea Cao if (ret < 0) 3218b890760eSAlgea Cao debug("failed to set %s rate %lu \n", clk->dev->name, rate); 3219b890760eSAlgea Cao 3220b890760eSAlgea Cao return ret; 3221b890760eSAlgea Cao } 3222b890760eSAlgea Cao 322312ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state, 322412ee5af0SDamon Ding int *dsc_txp_clk_div, int *dsc_pxl_clk_div, 322512ee5af0SDamon Ding int *dsc_cds_clk_div, u64 dclk_rate) 322612ee5af0SDamon Ding { 322712ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 322812ee5af0SDamon Ding 322912ee5af0SDamon Ding *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate; 323012ee5af0SDamon Ding *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate; 323112ee5af0SDamon Ding *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate; 323212ee5af0SDamon Ding 323312ee5af0SDamon Ding *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div); 323412ee5af0SDamon Ding *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div); 323512ee5af0SDamon Ding *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div); 323612ee5af0SDamon Ding } 323712ee5af0SDamon Ding 323812ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id) 323912ee5af0SDamon Ding { 324012ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 324112ee5af0SDamon Ding struct drm_dsc_picture_parameter_set *pps = &cstate->pps; 324212ee5af0SDamon Ding struct drm_dsc_picture_parameter_set config_pps; 324312ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 324412ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 324512ee5af0SDamon Ding u32 *pps_val = (u32 *)&config_pps; 324612ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 324712ee5af0SDamon Ding int i = 0; 324812ee5af0SDamon Ding 324912ee5af0SDamon Ding memcpy(&config_pps, pps, sizeof(config_pps)); 325012ee5af0SDamon Ding 325112ee5af0SDamon Ding if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) { 325212ee5af0SDamon Ding config_pps.pps_3 &= 0xf0; 325312ee5af0SDamon Ding config_pps.pps_3 |= dsc_data->max_linebuf_depth; 325412ee5af0SDamon Ding printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n", 325512ee5af0SDamon Ding dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf); 325612ee5af0SDamon Ding } 325712ee5af0SDamon Ding 325812ee5af0SDamon Ding for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 325912ee5af0SDamon Ding config_pps.rc_range_parameters[i] = 326012ee5af0SDamon Ding (pps->rc_range_parameters[i] >> 3 & 0x1f) | 326112ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) | 326212ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) | 326312ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10); 326412ee5af0SDamon Ding } 326512ee5af0SDamon Ding 326612ee5af0SDamon Ding for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++) 326712ee5af0SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++); 326812ee5af0SDamon Ding } 326912ee5af0SDamon Ding 327012ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate) 327112ee5af0SDamon Ding { 327212ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 327312ee5af0SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 327412ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 327512ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 327612ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 327712ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 327812ee5af0SDamon Ding bool mipi_ds_mode = false; 327912ee5af0SDamon Ding u8 dsc_interface_mode = 0; 328012ee5af0SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 328112ee5af0SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 328212ee5af0SDamon Ding u16 htotal = mode->crtc_htotal; 328312ee5af0SDamon Ding u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 328412ee5af0SDamon Ding u16 vdisplay = mode->crtc_vdisplay; 328512ee5af0SDamon Ding u16 vtotal = mode->crtc_vtotal; 328612ee5af0SDamon Ding u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 328712ee5af0SDamon Ding u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 328812ee5af0SDamon Ding u16 vact_end = vact_st + vdisplay; 328912ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 329012ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 329112ee5af0SDamon Ding int dsc_txp_clk_div = 0; 329212ee5af0SDamon Ding int dsc_pxl_clk_div = 0; 329312ee5af0SDamon Ding int dsc_cds_clk_div = 0; 3294baf2c414SDamon Ding int val = 0; 329512ee5af0SDamon Ding 329612ee5af0SDamon Ding if (!vop2->data->nr_dscs) { 329712ee5af0SDamon Ding printf("Unsupported DSC\n"); 329812ee5af0SDamon Ding return; 329912ee5af0SDamon Ding } 330012ee5af0SDamon Ding 330112ee5af0SDamon Ding if (cstate->dsc_slice_num > dsc_data->max_slice_num) 330212ee5af0SDamon Ding printf("DSC%d supported max slice is: %d, current is: %d\n", 330312ee5af0SDamon Ding dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num); 330412ee5af0SDamon Ding 330512ee5af0SDamon Ding if (dsc_data->pd_id) { 330612ee5af0SDamon Ding if (vop2_power_domain_on(vop2, dsc_data->pd_id)) 330712ee5af0SDamon Ding printf("open dsc%d pd fail\n", dsc_id); 330812ee5af0SDamon Ding } 330912ee5af0SDamon Ding 331012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK, 331112ee5af0SDamon Ding SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false); 331212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK, 331312ee5af0SDamon Ding DSC_PORT_SEL_SHIFT, cstate->crtc_id, false); 331412ee5af0SDamon Ding if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 331512ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_HDMI; 331612ee5af0SDamon Ding } else { 331712ee5af0SDamon Ding mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE); 331812ee5af0SDamon Ding if (mipi_ds_mode) 331912ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE; 332012ee5af0SDamon Ding else 332112ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE; 332212ee5af0SDamon Ding } 332312ee5af0SDamon Ding 332412ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 332512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 332612ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 0, false); 332712ee5af0SDamon Ding else 332812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 332912ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 1, false); 333012ee5af0SDamon Ding 333112ee5af0SDamon Ding vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate); 333212ee5af0SDamon Ding 333312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK, 333412ee5af0SDamon Ding DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false); 333512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK, 333612ee5af0SDamon Ding DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false); 333712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK, 333812ee5af0SDamon Ding DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false); 333912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK, 334012ee5af0SDamon Ding DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false); 334112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 334212ee5af0SDamon Ding DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false); 334312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK, 334412ee5af0SDamon Ding DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false); 334512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 334612ee5af0SDamon Ding DSC_HALT_EN_SHIFT, mipi_ds_mode, false); 334712ee5af0SDamon Ding 334812ee5af0SDamon Ding if (!mipi_ds_mode) { 334912ee5af0SDamon Ding u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end; 335012ee5af0SDamon Ding u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16; 335112ee5af0SDamon Ding u64 dsc_cds_rate = cstate->dsc_cds_clk_rate; 335212ee5af0SDamon Ding u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */ 335312ee5af0SDamon Ding u32 dly_num, dsc_cds_rate_mhz, val = 0; 3354b61227a3SDamon Ding int k = 1; 3355b61227a3SDamon Ding 3356b61227a3SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3357b61227a3SDamon Ding k = 2; 335812ee5af0SDamon Ding 335912ee5af0SDamon Ding if (target_bpp >> 4 < dsc_data->min_bits_per_pixel) 336012ee5af0SDamon Ding printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel); 336112ee5af0SDamon Ding 336212ee5af0SDamon Ding /* 336312ee5af0SDamon Ding * dly_num = delay_line_num * T(one-line) / T (dsc_cds) 336412ee5af0SDamon Ding * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz 336512ee5af0SDamon Ding * T (dsc_cds) = 1 / dsc_cds_rate_mhz 33661ace1b6dSDamon Ding * 33671ace1b6dSDamon Ding * HDMI: 336812ee5af0SDamon Ding * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay 336912ee5af0SDamon Ding * delay_line_num = 4 - BPP / 8 337012ee5af0SDamon Ding * = (64 - target_bpp / 8) / 16 337112ee5af0SDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 33721ace1b6dSDamon Ding * 33731ace1b6dSDamon Ding * MIPI DSI[4320 and 9216 is buffer size for DSC]: 33741ace1b6dSDamon Ding * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size; 33751ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 33761ace1b6dSDamon Ding * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size; 33771ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 33781ace1b6dSDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num 337912ee5af0SDamon Ding */ 338012ee5af0SDamon Ding do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ 338112ee5af0SDamon Ding dsc_cds_rate_mhz = dsc_cds_rate; 33821ace1b6dSDamon Ding dsc_hsync = hsync_len / 2; 33831ace1b6dSDamon Ding if (dsc_interface_mode == VOP_DSC_IF_HDMI) { 338412ee5af0SDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 33851ace1b6dSDamon Ding } else { 33861ace1b6dSDamon Ding int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2; 33871ace1b6dSDamon Ding int delay_line_num = dsc_buf_size / cstate->dsc_slice_num / 33881ace1b6dSDamon Ding be16_to_cpu(cstate->pps.chunk_size); 33891ace1b6dSDamon Ding 33901ace1b6dSDamon Ding delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 33911ace1b6dSDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num; 33921ace1b6dSDamon Ding 33931ace1b6dSDamon Ding /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */ 33941ace1b6dSDamon Ding if (dsc_hsync < 8) 33951ace1b6dSDamon Ding dsc_hsync = 8; 33961ace1b6dSDamon Ding } 339712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK, 339812ee5af0SDamon Ding DSC_INIT_DLY_MODE_SHIFT, 0, false); 339912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK, 340012ee5af0SDamon Ding DSC_INIT_DLY_NUM_SHIFT, dly_num, false); 340112ee5af0SDamon Ding 3402b61227a3SDamon Ding /* 3403b61227a3SDamon Ding * htotal / dclk_core = dsc_htotal /cds_clk 3404b61227a3SDamon Ding * 3405b61227a3SDamon Ding * dclk_core = DCLK / (1 << dclk_core->div_val) 3406b61227a3SDamon Ding * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val) 3407b61227a3SDamon Ding * txp_clk = DCLK / (1 << dsc_txp_clk->div_val) 3408b61227a3SDamon Ding * 3409b61227a3SDamon Ding * dsc_htotal = htotal * (1 << dclk_core->div_val) / 3410b61227a3SDamon Ding * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val)) 3411b61227a3SDamon Ding */ 3412b61227a3SDamon Ding dsc_htotal = htotal * (1 << cstate->dclk_core_div) / 3413b61227a3SDamon Ding ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div)); 341412ee5af0SDamon Ding val = dsc_htotal << 16 | dsc_hsync; 341512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK, 341612ee5af0SDamon Ding DSC_HTOTAL_PW_SHIFT, val, false); 341712ee5af0SDamon Ding 341812ee5af0SDamon Ding dsc_hact_st = hact_st / 2; 3419b61227a3SDamon Ding dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st; 342012ee5af0SDamon Ding val = dsc_hact_end << 16 | dsc_hact_st; 342112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK, 342212ee5af0SDamon Ding DSC_HACT_ST_END_SHIFT, val, false); 342312ee5af0SDamon Ding 342412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK, 342512ee5af0SDamon Ding DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false); 342612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK, 342712ee5af0SDamon Ding DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false); 342812ee5af0SDamon Ding } 342912ee5af0SDamon Ding 343012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK, 343112ee5af0SDamon Ding RST_DEASSERT_SHIFT, 1, false); 343212ee5af0SDamon Ding udelay(10); 343312ee5af0SDamon Ding 3434baf2c414SDamon Ding val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) | 3435baf2c414SDamon Ding ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT); 3436baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 3437baf2c414SDamon Ding 343812ee5af0SDamon Ding vop2_load_pps(state, vop2, dsc_id); 343912ee5af0SDamon Ding 3440baf2c414SDamon Ding val |= (1 << DSC_PPS_UPD_SHIFT); 3441baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 344212ee5af0SDamon Ding 344312ee5af0SDamon Ding printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n", 344412ee5af0SDamon Ding dsc_id, 344512ee5af0SDamon Ding cstate->dsc_txp_clk_rate, dsc_txp_clk_div, 344612ee5af0SDamon Ding cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div, 344712ee5af0SDamon Ding cstate->dsc_cds_clk_rate, dsc_cds_clk_div); 344812ee5af0SDamon Ding } 344912ee5af0SDamon Ding 34505f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev) 34515f1357a2SZhang Yubing { 34525f1357a2SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 34535f1357a2SZhang Yubing struct vop2 *vop2 = cstate->private; 34545f1357a2SZhang Yubing struct udevice *vp_dev, *dev; 34555f1357a2SZhang Yubing struct ofnode_phandle_args args; 34565f1357a2SZhang Yubing char vp_name[10]; 34575f1357a2SZhang Yubing int ret; 34585f1357a2SZhang Yubing 34595f1357a2SZhang Yubing if (vop2->version != VOP_VERSION_RK3588) 34605f1357a2SZhang Yubing return false; 34615f1357a2SZhang Yubing 34625f1357a2SZhang Yubing sprintf(vp_name, "port@%d", cstate->crtc_id); 34635f1357a2SZhang Yubing if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) { 34645e85f4a7SZhang Yubing debug("warn: can't get vp device\n"); 34655f1357a2SZhang Yubing return false; 34665f1357a2SZhang Yubing } 34675f1357a2SZhang Yubing 34685f1357a2SZhang Yubing ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0, 34695f1357a2SZhang Yubing 0, &args); 34705f1357a2SZhang Yubing if (ret) { 34715e85f4a7SZhang Yubing debug("assigned-clock-parents's node not define\n"); 34725f1357a2SZhang Yubing return false; 34735f1357a2SZhang Yubing } 34745f1357a2SZhang Yubing 34755f1357a2SZhang Yubing if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) { 34765e85f4a7SZhang Yubing debug("warn: can't get clk device\n"); 34775f1357a2SZhang Yubing return false; 34785f1357a2SZhang Yubing } 34795f1357a2SZhang Yubing 34805f1357a2SZhang Yubing if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) { 34815f1357a2SZhang Yubing printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name); 34825f1357a2SZhang Yubing if (clk_dev) 34835f1357a2SZhang Yubing *clk_dev = dev; 34845f1357a2SZhang Yubing return true; 34855f1357a2SZhang Yubing } 34865f1357a2SZhang Yubing 34875f1357a2SZhang Yubing return false; 34885f1357a2SZhang Yubing } 34895f1357a2SZhang Yubing 3490ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state) 3491ecc31b6eSAndy Yan { 3492ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3493c2b1fe35SDamon Ding struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id]; 3494ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3495ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3496ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 3497ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 3498ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 3499ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal; 3500ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 3501ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay; 3502ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay; 3503ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal; 3504ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 3505ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 3506ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay; 3507ecc31b6eSAndy Yan bool yuv_overlay = false; 3508ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 350966724b9cSDamon Ding u32 line_flag_offset = (cstate->crtc_id * 4); 351066724b9cSDamon Ding u32 val, act_end; 3511ecc31b6eSAndy Yan u8 dither_down_en = 0; 3512452afb13SDamon Ding u8 dither_down_mode = 0; 3513ecc31b6eSAndy Yan u8 pre_dither_down_en = 0; 3514edfef528SDamon Ding u8 dclk_div_factor = 0; 3515ecc31b6eSAndy Yan char output_type_name[30] = {0}; 3516*d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 3517ecc31b6eSAndy Yan char dclk_name[9]; 3518*d8e7f4a5SSandy Huang #endif 3519ecc31b6eSAndy Yan struct clk dclk; 3520b890760eSAlgea Cao struct clk hdmi0_phy_pll; 3521b890760eSAlgea Cao struct clk hdmi1_phy_pll; 35225f1357a2SZhang Yubing struct clk hdmi_phy_pll; 35233e05a7b8SZhang Yubing struct udevice *disp_dev; 35245fa6e665SDamon Ding unsigned long dclk_rate = 0; 3525ecc31b6eSAndy Yan int ret; 3526ecc31b6eSAndy Yan 3527ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 352871ac76f7SDamon Ding mode->crtc_hdisplay, mode->vdisplay, 3529ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 35305e85f4a7SZhang Yubing mode->vrefresh, 3531ecc31b6eSAndy Yan get_output_if_name(conn_state->output_if, output_type_name), 3532ecc31b6eSAndy Yan cstate->crtc_id); 3533ecc31b6eSAndy Yan 3534ee01dbb2SDamon Ding if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { 3535ee01dbb2SDamon Ding cstate->splice_mode = true; 3536ee01dbb2SDamon Ding cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id; 3537ee01dbb2SDamon Ding if (!cstate->splice_crtc_id) { 3538ee01dbb2SDamon Ding printf("%s: Splice mode is unsupported by vp%d\n", 3539ee01dbb2SDamon Ding __func__, cstate->crtc_id); 3540ee01dbb2SDamon Ding return -EINVAL; 3541ee01dbb2SDamon Ding } 3542b70b2d79SDamon Ding 3543b70b2d79SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK, 3544b70b2d79SDamon Ding PORT_MERGE_EN_SHIFT, 1, false); 3545ee01dbb2SDamon Ding } 3546ee01dbb2SDamon Ding 3547cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 3548cd6c85a9SDamon Ding RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false); 3549cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 3550cd6c85a9SDamon Ding RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false); 3551cd6c85a9SDamon Ding 3552ecc31b6eSAndy Yan vop2_initial(vop2, state); 3553ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 3554ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state); 35555fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3568) 3556ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state); 35575fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3528) 35585fa6e665SDamon Ding dclk_rate = rk3528_vop2_if_cfg(state); 3559452afb13SDamon Ding else if (vop2->version == VOP_VERSION_RK3562) 3560452afb13SDamon Ding dclk_rate = rk3562_vop2_if_cfg(state); 3561ecc31b6eSAndy Yan 356263cb669fSSandy Huang if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 356363cb669fSSandy Huang !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) 35647bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 35657bdd0eb6SSandy Huang 356665747de7SDamon Ding vop2_post_color_swap(state); 356710ee9f5bSAlgea Cao 3568d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 3569d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false); 3570d0408543SAndy Yan 3571d0408543SAndy Yan switch (conn_state->bus_format) { 3572d0408543SAndy Yan case MEDIA_BUS_FMT_RGB565_1X16: 3573d0408543SAndy Yan dither_down_en = 1; 3574452afb13SDamon Ding dither_down_mode = RGB888_TO_RGB565; 3575452afb13SDamon Ding pre_dither_down_en = 1; 3576d0408543SAndy Yan break; 3577d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X18: 3578d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 3579d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 3580d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: 3581d0408543SAndy Yan dither_down_en = 1; 3582452afb13SDamon Ding dither_down_mode = RGB888_TO_RGB666; 3583452afb13SDamon Ding pre_dither_down_en = 1; 3584d0408543SAndy Yan break; 3585d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 3586d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 3587d0408543SAndy Yan dither_down_en = 0; 3588d0408543SAndy Yan pre_dither_down_en = 1; 3589d0408543SAndy Yan break; 3590d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 3591d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 3592452afb13SDamon Ding dither_down_en = 0; 3593452afb13SDamon Ding pre_dither_down_en = 0; 3594452afb13SDamon Ding break; 3595034a46b5SAlgea Cao case MEDIA_BUS_FMT_YUYV10_1X20: 3596d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X24: 3597d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 3598d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 3599034a46b5SAlgea Cao case MEDIA_BUS_FMT_RGB101010_1X30: 3600d0408543SAndy Yan default: 3601d0408543SAndy Yan dither_down_en = 0; 3602452afb13SDamon Ding pre_dither_down_en = 1; 3603d0408543SAndy Yan break; 3604d0408543SAndy Yan } 3605d0408543SAndy Yan 3606d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3607d0408543SAndy Yan DITHER_DOWN_EN_SHIFT, dither_down_en, false); 3608d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3609034a46b5SAlgea Cao DITHER_DOWN_MODE_SHIFT, dither_down_mode, false); 3610034a46b5SAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3611d0408543SAndy Yan PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 3612452afb13SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3613452afb13SDamon Ding DITHER_DOWN_MODE_SHIFT, dither_down_mode, false); 3614d0408543SAndy Yan 3615d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 3616d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 3617d0408543SAndy Yan yuv_overlay, false); 3618d0408543SAndy Yan 3619d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay; 3620d0408543SAndy Yan 3621d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 3622d0408543SAndy Yan (htotal << 16) | hsync_len); 3623d0408543SAndy Yan val = hact_st << 16; 3624d0408543SAndy Yan val |= hact_end; 3625d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 3626d0408543SAndy Yan val = vact_st << 16; 3627d0408543SAndy Yan val |= vact_end; 3628d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 3629d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 3630d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 3631d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay; 3632d0408543SAndy Yan 3633d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 3634d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 3635d0408543SAndy Yan val); 3636d0408543SAndy Yan 3637d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len); 3638d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 3639d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3640d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false); 3641d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 36427a20be36SSandy Huang DSP_FILED_POL, 1, false); 36437a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3644d0408543SAndy Yan P2I_EN_SHIFT, 1, false); 3645d0408543SAndy Yan vtotal += vtotal + 1; 364666724b9cSDamon Ding act_end = vact_end_f1; 3647d0408543SAndy Yan } else { 3648d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3649d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false); 3650d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3651d0408543SAndy Yan P2I_EN_SHIFT, 0, false); 365266724b9cSDamon Ding act_end = vact_end; 3653d0408543SAndy Yan } 3654d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 3655d0408543SAndy Yan (vtotal << 16) | vsync_len); 365667be2ffcSDamon Ding 36575fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3528) { 365867be2ffcSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || 365967be2ffcSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 3660d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 366167be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 1, false); 366267be2ffcSDamon Ding else 366367be2ffcSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 366467be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 0, false); 366567be2ffcSDamon Ding } 366610ee9f5bSAlgea Cao 366710ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 366863cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 366963cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 367010ee9f5bSAlgea Cao else 367163cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 367263cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 367310ee9f5bSAlgea Cao 3674ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 3675ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false); 3676ee01dbb2SDamon Ding 367710ee9f5bSAlgea Cao if (yuv_overlay) 367810ee9f5bSAlgea Cao val = 0x20010200; 367910ee9f5bSAlgea Cao else 368010ee9f5bSAlgea Cao val = 0; 368110ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 3682b70b2d79SDamon Ding if (cstate->splice_mode) { 3683ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 3684ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id, 3685ee01dbb2SDamon Ding yuv_overlay, false); 3686ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val); 3687ee01dbb2SDamon Ding } 368810ee9f5bSAlgea Cao 368910ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 369010ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 3691d0408543SAndy Yan 3692c2b1fe35SDamon Ding if (vp->xmirror_en) 3693c2b1fe35SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3694c2b1fe35SDamon Ding DSP_X_MIR_EN_SHIFT, 1, false); 3695c2b1fe35SDamon Ding 3696ac500a1fSSandy Huang vop2_tv_config_update(state, vop2); 3697d0408543SAndy Yan vop2_post_config(state, vop2); 36986027c871SZhang Yubing if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) 36996027c871SZhang Yubing vop3_post_config(state, vop2); 3700d0408543SAndy Yan 370112ee5af0SDamon Ding if (cstate->dsc_enable) { 370212ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 37031ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL); 37041ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL); 370512ee5af0SDamon Ding } else { 37061ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL); 370712ee5af0SDamon Ding } 370812ee5af0SDamon Ding } 370912ee5af0SDamon Ding 3710*d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 3711ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 3712ecc31b6eSAndy Yan ret = clk_get_by_name(cstate->dev, dclk_name, &dclk); 3713b890760eSAlgea Cao if (ret) { 3714b890760eSAlgea Cao printf("%s: Failed to get dclk ret=%d\n", __func__, ret); 3715b890760eSAlgea Cao return ret; 3716b890760eSAlgea Cao } 3717*d8e7f4a5SSandy Huang #endif 3718b890760eSAlgea Cao 37193e05a7b8SZhang Yubing ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev); 37203e05a7b8SZhang Yubing if (!ret) { 37213e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll); 37223e05a7b8SZhang Yubing if (ret) 37235e85f4a7SZhang Yubing debug("%s: hdmi0_phy_pll may not define\n", __func__); 37243e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll); 37253e05a7b8SZhang Yubing if (ret) 37265e85f4a7SZhang Yubing debug("%s: hdmi1_phy_pll may not define\n", __func__); 37273e05a7b8SZhang Yubing } else { 3728b890760eSAlgea Cao hdmi0_phy_pll.dev = NULL; 3729545a0218SAlgea Cao hdmi1_phy_pll.dev = NULL; 37305e85f4a7SZhang Yubing debug("%s: Faile to find display-subsystem node\n", __func__); 3731b890760eSAlgea Cao } 3732b890760eSAlgea Cao 3733ebbd144cSAlgea Cao if (vop2->version == VOP_VERSION_RK3528) { 3734ebbd144cSAlgea Cao struct ofnode_phandle_args args; 3735ebbd144cSAlgea Cao 3736ebbd144cSAlgea Cao ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents", 3737ebbd144cSAlgea Cao "#clock-cells", 0, 0, &args); 3738ebbd144cSAlgea Cao if (!ret) { 3739ebbd144cSAlgea Cao ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev); 3740ebbd144cSAlgea Cao if (ret) { 3741ebbd144cSAlgea Cao debug("warn: can't get clk device\n"); 3742ebbd144cSAlgea Cao return ret; 3743ebbd144cSAlgea Cao } 3744ebbd144cSAlgea Cao } else { 3745ebbd144cSAlgea Cao debug("assigned-clock-parents's node not define\n"); 3746ebbd144cSAlgea Cao } 3747ebbd144cSAlgea Cao } 3748ebbd144cSAlgea Cao 37490a1fb152SZhang Yubing if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) { 3750b890760eSAlgea Cao if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) 3751b890760eSAlgea Cao vop2_clk_set_parent(&dclk, &hdmi0_phy_pll); 3752b890760eSAlgea Cao else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1) 3753b890760eSAlgea Cao vop2_clk_set_parent(&dclk, &hdmi1_phy_pll); 3754b890760eSAlgea Cao 3755b890760eSAlgea Cao /* 3756b890760eSAlgea Cao * uboot clk driver won't set dclk parent's rate when use 3757b890760eSAlgea Cao * hdmi phypll as dclk source. 3758b890760eSAlgea Cao * So set dclk rate is meaningless. Set hdmi phypll rate 3759b890760eSAlgea Cao * directly. 3760b890760eSAlgea Cao */ 37615f1357a2SZhang Yubing if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) { 3762b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate * 1000); 37635f1357a2SZhang Yubing } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) { 3764b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate * 1000); 37655f1357a2SZhang Yubing } else { 37667efea85dSDamon Ding if (is_extend_pll(state, &hdmi_phy_pll.dev)) { 37675f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 37687efea85dSDamon Ding } else { 3769*d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 37707efea85dSDamon Ding /* 37717efea85dSDamon Ding * For RK3528, the path of CVBS output is like: 37727efea85dSDamon Ding * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC 37737efea85dSDamon Ding * The vop2 dclk should be four times crtc_clock for CVBS sampling 37747efea85dSDamon Ding * clock needs. 37757efea85dSDamon Ding */ 37767efea85dSDamon Ding if (vop2->version == VOP_VERSION_RK3528 && 37777efea85dSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 37787efea85dSDamon Ding ret = vop2_clk_set_rate(&dclk, 4 * dclk_rate * 1000); 3779b890760eSAlgea Cao else 3780b890760eSAlgea Cao ret = vop2_clk_set_rate(&dclk, dclk_rate * 1000); 3781*d8e7f4a5SSandy Huang #else 3782*d8e7f4a5SSandy Huang if (vop2->version == VOP_VERSION_RK3528) { 3783*d8e7f4a5SSandy Huang void *cru_base = (void *)RK3528_CRU_BASE; 3784*d8e7f4a5SSandy Huang 3785*d8e7f4a5SSandy Huang /* dclk src switch to hdmiphy pll */ 3786*d8e7f4a5SSandy Huang writel((BIT(0) << 16) | BIT(0), cru_base + 0x450); 3787*d8e7f4a5SSandy Huang rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000); 3788*d8e7f4a5SSandy Huang ret = dclk_rate * 1000; 3789*d8e7f4a5SSandy Huang } 3790*d8e7f4a5SSandy Huang #endif 37915f1357a2SZhang Yubing } 37927efea85dSDamon Ding } 3793631ee99aSZhang Yubing } else { 37945f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev)) 37955f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 37965f1357a2SZhang Yubing else 3797631ee99aSZhang Yubing ret = vop2_clk_set_rate(&dclk, dclk_rate * 1000); 3798edfef528SDamon Ding } 379963638f32SDamon Ding 380063638f32SDamon Ding if (IS_ERR_VALUE(ret)) { 380163638f32SDamon Ding printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 380263638f32SDamon Ding __func__, cstate->crtc_id, dclk_rate, ret); 380363638f32SDamon Ding return ret; 380463638f32SDamon Ding } else { 3805edfef528SDamon Ding dclk_div_factor = mode->clock / dclk_rate; 38065fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && 38075fa6e665SDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 38085fa6e665SDamon Ding mode->crtc_clock = ret / 4 / 1000; 38095fa6e665SDamon Ding else 3810edfef528SDamon Ding mode->crtc_clock = ret * dclk_div_factor / 1000; 3811edfef528SDamon Ding printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); 3812631ee99aSZhang Yubing } 3813ecc31b6eSAndy Yan 381466724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 3815e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false); 381666724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 3817e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false); 381866724b9cSDamon Ding 3819d0408543SAndy Yan return 0; 3820d0408543SAndy Yan } 3821d0408543SAndy Yan 3822ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 38233e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w, 38243e39a5a1SSandy Huang uint32_t dst_h) 38253e39a5a1SSandy Huang { 38263e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 38273e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode; 38285fa6e665SDamon Ding uint8_t xgt2 = 0, xgt4 = 0; 38295fa6e665SDamon Ding uint8_t ygt2 = 0, ygt4 = 0; 38303e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0; 3831ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 38325fa6e665SDamon Ding bool xgt_en = false; 38335fa6e665SDamon Ding bool xavg_en = false; 38343e39a5a1SSandy Huang 38355fa6e665SDamon Ding if (is_vop3(vop2)) { 38365fa6e665SDamon Ding if (src_w >= (4 * dst_w)) { 38375fa6e665SDamon Ding xgt4 = 1; 38385fa6e665SDamon Ding src_w >>= 2; 38395fa6e665SDamon Ding } else if (src_w >= (2 * dst_w)) { 38405fa6e665SDamon Ding xgt2 = 1; 38415fa6e665SDamon Ding src_w >>= 1; 38425fa6e665SDamon Ding } 38435fa6e665SDamon Ding } 38443e39a5a1SSandy Huang 38455fa6e665SDamon Ding if (src_h >= (4 * dst_h)) { 38465fa6e665SDamon Ding ygt4 = 1; 38473e39a5a1SSandy Huang src_h >>= 2; 38485fa6e665SDamon Ding } else if (src_h >= (2 * dst_h)) { 38495fa6e665SDamon Ding ygt2 = 1; 38503e39a5a1SSandy Huang src_h >>= 1; 38515fa6e665SDamon Ding } 38523e39a5a1SSandy Huang 38533e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 38543e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 38553e39a5a1SSandy Huang 38563e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP) 38575fa6e665SDamon Ding hscl_filter_mode = win->hsu_filter_mode; 38583e39a5a1SSandy Huang else 38595fa6e665SDamon Ding hscl_filter_mode = win->hsd_filter_mode; 38603e39a5a1SSandy Huang 38613e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP) 38625fa6e665SDamon Ding vscl_filter_mode = win->vsu_filter_mode; 38633e39a5a1SSandy Huang else 38645fa6e665SDamon Ding vscl_filter_mode = win->vsd_filter_mode; 38653e39a5a1SSandy Huang 38663e39a5a1SSandy Huang /* 38673e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel 38683e39a5a1SSandy Huang * at scale down mode 38693e39a5a1SSandy Huang */ 38705fa6e665SDamon Ding if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) { 38713e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 38723e39a5a1SSandy Huang dst_w += 1; 38733e39a5a1SSandy Huang } 38743e39a5a1SSandy Huang 38755fa6e665SDamon Ding if (is_vop3(vop2)) { 38765fa6e665SDamon Ding xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true); 38775fa6e665SDamon Ding yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false); 38785fa6e665SDamon Ding 38795fa6e665SDamon Ding if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG) 38805fa6e665SDamon Ding xavg_en = xgt2 || xgt4; 38815fa6e665SDamon Ding else 38825fa6e665SDamon Ding xgt_en = xgt2 || xgt4; 38835fa6e665SDamon Ding } else { 38843e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 38853e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 38865fa6e665SDamon Ding } 3887ecc31b6eSAndy Yan 3888ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) { 3889ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 3890ecc31b6eSAndy Yan yfac << 16 | xfac); 3891ecc31b6eSAndy Yan 38925fa6e665SDamon Ding if (is_vop3(vop2)) { 3893ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38945fa6e665SDamon Ding EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false); 3895ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38965fa6e665SDamon Ding EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false); 38975fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38985fa6e665SDamon Ding XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 3899ecc31b6eSAndy Yan 3900ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39015fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT, 39025fa6e665SDamon Ding yrgb_hor_scl_mode, false); 3903ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39045fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT, 39055fa6e665SDamon Ding yrgb_ver_scl_mode, false); 39065fa6e665SDamon Ding } else { 39075fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39085fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT, 39095fa6e665SDamon Ding yrgb_hor_scl_mode, false); 39105fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39115fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT, 39125fa6e665SDamon Ding yrgb_ver_scl_mode, false); 39135fa6e665SDamon Ding } 3914ecc31b6eSAndy Yan 39155fa6e665SDamon Ding if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) { 39165fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39175fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false); 39185fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39195fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false); 39205fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39215fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false); 39225fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39235fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false); 39245fa6e665SDamon Ding } else { 39255fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39265fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false); 39275fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39285fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false); 39295fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39305fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false); 39315fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 39325fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false); 39335fa6e665SDamon Ding } 3934ecc31b6eSAndy Yan } else { 39353e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 39363e39a5a1SSandy Huang yfac << 16 | xfac); 39373e39a5a1SSandy Huang 39385fa6e665SDamon Ding if (is_vop3(vop2)) { 393934a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 39405fa6e665SDamon Ding EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false); 394134a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 39425fa6e665SDamon Ding EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false); 39435fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 39445fa6e665SDamon Ding XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 39455fa6e665SDamon Ding } 39465fa6e665SDamon Ding 39475fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 39485fa6e665SDamon Ding YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false); 39495fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 39505fa6e665SDamon Ding YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false); 39513e39a5a1SSandy Huang 39523e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39533e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 39543e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39553e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 39563e39a5a1SSandy Huang 39573e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39583e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 39593e39a5a1SSandy Huang hscl_filter_mode, false); 39603e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39613e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 39623e39a5a1SSandy Huang vscl_filter_mode, false); 39633e39a5a1SSandy Huang } 3964ecc31b6eSAndy Yan } 39653e39a5a1SSandy Huang 3966a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win) 3967a33b790fSDamon Ding { 3968a33b790fSDamon Ding u32 win_offset = win->reg_offset; 3969a33b790fSDamon Ding 3970a33b790fSDamon Ding if (win->type == CLUSTER_LAYER) { 3971a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK, 3972a33b790fSDamon Ding CLUSTER_AXI_ID_SHIFT, win->axi_id, false); 3973a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK, 3974a33b790fSDamon Ding CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 3975a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK, 3976a33b790fSDamon Ding CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 3977a33b790fSDamon Ding } else { 3978a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK, 3979a33b790fSDamon Ding ESMART_AXI_ID_SHIFT, win->axi_id, false); 3980a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK, 3981a33b790fSDamon Ding ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 3982a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK, 3983a33b790fSDamon Ding ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 3984a33b790fSDamon Ding } 3985a33b790fSDamon Ding } 3986a33b790fSDamon Ding 3987ecc31b6eSAndy Yan static void vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 3988d0408543SAndy Yan { 3989d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3990d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 3991d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3992d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 3993ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 3994ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 3995ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 3996ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 3997ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 3998ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 3999d0408543SAndy Yan int xvir = cstate->xvir; 4000d0408543SAndy Yan int y_mirror = 0; 400110ee9f5bSAlgea Cao int csc_mode; 4002ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 4003ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 4004ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 4005ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 4006ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 4007ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4008d0408543SAndy Yan 4009ee01dbb2SDamon Ding if (win->splice_mode_right) { 4010ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 4011ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 4012ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 4013ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 4014ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 4015ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 4016ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 4017ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 4018ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4019ee01dbb2SDamon Ding } 4020ee01dbb2SDamon Ding 4021ecc31b6eSAndy Yan act_info = (src_h - 1) << 16; 4022ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff; 4023ecc31b6eSAndy Yan 4024ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16; 4025ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 4026ecc31b6eSAndy Yan 4027ecc31b6eSAndy Yan dsp_stx = crtc_x; 4028ecc31b6eSAndy Yan dsp_sty = crtc_y; 4029ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 4030ecc31b6eSAndy Yan 4031ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 4032ecc31b6eSAndy Yan y_mirror = 1; 4033ecc31b6eSAndy Yan else 4034ecc31b6eSAndy Yan y_mirror = 0; 4035ecc31b6eSAndy Yan 4036ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 4037ecc31b6eSAndy Yan 4038452afb13SDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 || 4039452afb13SDamon Ding vop2->version == VOP_VERSION_RK3562) 4040a33b790fSDamon Ding vop2_axi_config(vop2, win); 4041a33b790fSDamon Ding 4042ecc31b6eSAndy Yan if (y_mirror) 4043ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n"); 4044ecc31b6eSAndy Yan 4045a59754e1SDamon Ding /* rk3588 should set half_blocK_en to 1 in line and tile mode */ 4046a59754e1SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 4047a59754e1SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset, 4048a59754e1SDamon Ding EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false); 4049a59754e1SDamon Ding 4050ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 4051ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 4052ecc31b6eSAndy Yan false); 4053ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 4054ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, 4055ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 4056ecc31b6eSAndy Yan 4057ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 4058ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 4059ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 4060ecc31b6eSAndy Yan 4061ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 4062ecc31b6eSAndy Yan 40635fa6e665SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 4064ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 4065ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT, 4066ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false); 4067ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 4068ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 4069ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 4070ecc31b6eSAndy Yan 4071ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4072d0408543SAndy Yan } 4073d0408543SAndy Yan 4074ecc31b6eSAndy Yan static void vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 4075ecc31b6eSAndy Yan { 4076ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4077ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 4078ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 4079ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4080ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 4081ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 4082ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 4083ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 4084ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 4085ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 4086ecc31b6eSAndy Yan int xvir = cstate->xvir; 4087ecc31b6eSAndy Yan int y_mirror = 0; 4088ecc31b6eSAndy Yan int csc_mode; 4089ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 4090ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 4091ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 4092ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 4093ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 4094ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4095ecc31b6eSAndy Yan 4096ee01dbb2SDamon Ding if (win->splice_mode_right) { 4097ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 4098ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 4099ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 4100ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 4101ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 4102ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 4103ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 4104ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 4105ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4106ee01dbb2SDamon Ding } 4107ee01dbb2SDamon Ding 410874bd8269SSandy Huang /* 410974bd8269SSandy Huang * This is workaround solution for IC design: 411074bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1. 411174bd8269SSandy Huang */ 411274bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) { 411374bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 411474bd8269SSandy Huang src_w -= 1; 411574bd8269SSandy Huang } 411674bd8269SSandy Huang 4117d0408543SAndy Yan act_info = (src_h - 1) << 16; 4118d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff; 4119d0408543SAndy Yan 4120d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16; 4121d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 4122d0408543SAndy Yan 4123d0408543SAndy Yan dsp_stx = crtc_x; 4124d0408543SAndy Yan dsp_sty = crtc_y; 4125d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 4126d0408543SAndy Yan 4127d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 4128d0408543SAndy Yan y_mirror = 1; 4129d0408543SAndy Yan else 4130d0408543SAndy Yan y_mirror = 0; 4131d0408543SAndy Yan 41325fa6e665SDamon Ding if (is_vop3(vop2)) 41335fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, ESMART_LB_SELECT_MASK, 41345fa6e665SDamon Ding ESMART_LB_SELECT_SHIFT, win->scale_engine_num, false); 41355fa6e665SDamon Ding 4136ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 41373e39a5a1SSandy Huang 4138452afb13SDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 || 4139452afb13SDamon Ding vop2->version == VOP_VERSION_RK3562) 4140a33b790fSDamon Ding vop2_axi_config(vop2, win); 4141a33b790fSDamon Ding 4142d0408543SAndy Yan if (y_mirror) 4143d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4; 4144d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 4145d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false); 4146d0408543SAndy Yan 4147d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 4148d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 4149d0408543SAndy Yan false); 4150d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 4151d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 4152ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 4153d0408543SAndy Yan 4154d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 4155d0408543SAndy Yan act_info); 4156d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 4157d0408543SAndy Yan dsp_info); 4158d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 4159d0408543SAndy Yan 4160d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 4161d0408543SAndy Yan WIN_EN_SHIFT, 1, false); 4162d0408543SAndy Yan 41635fa6e665SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 416410ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 416510ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT, 416610ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false); 416710ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 416810ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false); 416910ee9f5bSAlgea Cao 4170d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4171ecc31b6eSAndy Yan } 4172ecc31b6eSAndy Yan 4173ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state) 4174ee01dbb2SDamon Ding { 4175ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 4176ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 4177ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 4178ee01dbb2SDamon Ding struct display_rect *src_rect = &cstate->src_rect; 4179ee01dbb2SDamon Ding struct display_rect *dst_rect = &cstate->crtc_rect; 4180ee01dbb2SDamon Ding struct display_rect left_src, left_dst, right_src, right_dst; 4181ee01dbb2SDamon Ding u16 half_hdisplay = mode->crtc_hdisplay >> 1; 4182ee01dbb2SDamon Ding int left_src_w, left_dst_w, right_dst_w; 4183ee01dbb2SDamon Ding 4184ee01dbb2SDamon Ding left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x; 4185ee01dbb2SDamon Ding if (left_dst_w < 0) 4186ee01dbb2SDamon Ding left_dst_w = 0; 4187ee01dbb2SDamon Ding right_dst_w = dst_rect->w - left_dst_w; 4188ee01dbb2SDamon Ding 4189ee01dbb2SDamon Ding if (!right_dst_w) 4190ee01dbb2SDamon Ding left_src_w = src_rect->w; 4191ee01dbb2SDamon Ding else 41920df0fd39SSandy Huang left_src_w = src_rect->x + src_rect->w - src_rect->w / 2; 4193ee01dbb2SDamon Ding 4194ee01dbb2SDamon Ding left_src.x = src_rect->x; 4195ee01dbb2SDamon Ding left_src.w = left_src_w; 4196ee01dbb2SDamon Ding left_dst.x = dst_rect->x; 4197ee01dbb2SDamon Ding left_dst.w = left_dst_w; 4198ee01dbb2SDamon Ding right_src.x = left_src.x + left_src.w; 4199ee01dbb2SDamon Ding right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w; 4200ee01dbb2SDamon Ding right_dst.x = dst_rect->x + left_dst_w - half_hdisplay; 4201ee01dbb2SDamon Ding right_dst.w = right_dst_w; 4202ee01dbb2SDamon Ding 4203ee01dbb2SDamon Ding left_src.y = src_rect->y; 4204ee01dbb2SDamon Ding left_src.h = src_rect->h; 4205ee01dbb2SDamon Ding left_dst.y = dst_rect->y; 4206ee01dbb2SDamon Ding left_dst.h = dst_rect->h; 4207ee01dbb2SDamon Ding right_src.y = src_rect->y; 4208ee01dbb2SDamon Ding right_src.h = src_rect->h; 4209ee01dbb2SDamon Ding right_dst.y = dst_rect->y; 4210ee01dbb2SDamon Ding right_dst.h = dst_rect->h; 4211ee01dbb2SDamon Ding 4212ee01dbb2SDamon Ding memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect)); 4213ee01dbb2SDamon Ding memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect)); 4214ee01dbb2SDamon Ding memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect)); 4215ee01dbb2SDamon Ding memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect)); 4216ee01dbb2SDamon Ding } 4217ee01dbb2SDamon Ding 4218ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state) 4219ecc31b6eSAndy Yan { 4220ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4221ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4222ecc31b6eSAndy Yan struct vop2_win_data *win_data; 4223ee01dbb2SDamon Ding struct vop2_win_data *splice_win_data; 4224ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 4225ecc31b6eSAndy Yan char plane_name[10] = {0}; 4226ecc31b6eSAndy Yan 4227ee01dbb2SDamon Ding if (cstate->crtc_rect.w > cstate->max_output.width) { 4228ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n", 4229ee01dbb2SDamon Ding cstate->crtc_rect.w, cstate->max_output.width); 4230ecc31b6eSAndy Yan return -EINVAL; 4231ecc31b6eSAndy Yan } 4232ecc31b6eSAndy Yan 4233ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 4234ecc31b6eSAndy Yan if (!win_data) { 4235ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id); 4236ecc31b6eSAndy Yan return -ENODEV; 4237ecc31b6eSAndy Yan } 4238ecc31b6eSAndy Yan 42395fa6e665SDamon Ding /* ignore some plane register according vop3 esmart lb mode */ 42405fa6e665SDamon Ding if (vop3_ignore_plane(vop2, win_data)) 42415fa6e665SDamon Ding return -EACCES; 42425fa6e665SDamon Ding 4243b6ba80b4SDamon Ding if (vop2->version == VOP_VERSION_RK3588) { 4244b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, win_data->pd_id)) 4245b6ba80b4SDamon Ding printf("open vp%d plane pd fail\n", cstate->crtc_id); 4246b6ba80b4SDamon Ding } 4247b6ba80b4SDamon Ding 4248ee01dbb2SDamon Ding if (cstate->splice_mode) { 4249ee01dbb2SDamon Ding if (win_data->splice_win_id) { 4250ee01dbb2SDamon Ding splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id); 4251ee01dbb2SDamon Ding splice_win_data->splice_mode_right = true; 4252b6ba80b4SDamon Ding 4253b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, splice_win_data->pd_id)) 4254b6ba80b4SDamon Ding printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id); 4255b6ba80b4SDamon Ding 4256ee01dbb2SDamon Ding vop2_calc_display_rect_for_splice(state); 4257ee01dbb2SDamon Ding if (win_data->type == CLUSTER_LAYER) 4258ee01dbb2SDamon Ding vop2_set_cluster_win(state, splice_win_data); 4259ee01dbb2SDamon Ding else 4260ee01dbb2SDamon Ding vop2_set_smart_win(state, splice_win_data); 4261ee01dbb2SDamon Ding } else { 4262ee01dbb2SDamon Ding printf("ERROR: splice mode is unsupported by plane %s\n", 4263ee01dbb2SDamon Ding get_plane_name(primary_plane_id, plane_name)); 4264ee01dbb2SDamon Ding return -EINVAL; 4265ee01dbb2SDamon Ding } 4266ee01dbb2SDamon Ding } 4267ee01dbb2SDamon Ding 4268ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER) 4269ecc31b6eSAndy Yan vop2_set_cluster_win(state, win_data); 4270ecc31b6eSAndy Yan else 4271ecc31b6eSAndy Yan vop2_set_smart_win(state, win_data); 42728895aec1SSandy Huang 42738895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 42748895aec1SSandy Huang cstate->crtc_id, get_plane_name(primary_plane_id, plane_name), 4275ee01dbb2SDamon Ding cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h, 4276ee01dbb2SDamon Ding cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format, 42778895aec1SSandy Huang cstate->dma_addr); 42788895aec1SSandy Huang 4279d0408543SAndy Yan return 0; 4280d0408543SAndy Yan } 4281d0408543SAndy Yan 4282d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state) 4283d0408543SAndy Yan { 4284d0408543SAndy Yan return 0; 4285d0408543SAndy Yan } 4286d0408543SAndy Yan 428712ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state) 428812ee5af0SDamon Ding { 428912ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 429012ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 429112ee5af0SDamon Ding struct vop2 *vop2 = cstate->private; 429212ee5af0SDamon Ding u8 dsc_id = cstate->dsc_id; 429312ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 429412ee5af0SDamon Ding 429512ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 429612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK, 429712ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 429812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK, 429912ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 430012ee5af0SDamon Ding } else { 430112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK, 430212ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 430312ee5af0SDamon Ding } 430412ee5af0SDamon Ding } 430512ee5af0SDamon Ding 4306d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state) 4307d0408543SAndy Yan { 4308d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 4309d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 431052ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 4311ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4312d0408543SAndy Yan 4313d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4314d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false); 4315ee01dbb2SDamon Ding 4316ee01dbb2SDamon Ding if (cstate->splice_mode) 4317ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4318ee01dbb2SDamon Ding 4319d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4320d0408543SAndy Yan 432112ee5af0SDamon Ding if (cstate->dsc_enable) 432212ee5af0SDamon Ding vop2_dsc_cfg_done(state); 432312ee5af0SDamon Ding 4324d0408543SAndy Yan return 0; 4325d0408543SAndy Yan } 4326d0408543SAndy Yan 4327d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state) 4328d0408543SAndy Yan { 4329d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 4330d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 433152ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 4332ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4333d0408543SAndy Yan 4334d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4335d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false); 4336ee01dbb2SDamon Ding 4337ee01dbb2SDamon Ding if (cstate->splice_mode) 4338ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4339ee01dbb2SDamon Ding 4340d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4341d0408543SAndy Yan 4342d0408543SAndy Yan return 0; 4343d0408543SAndy Yan } 4344d0408543SAndy Yan 4345ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 4346ee008497SSandy Huang { 4347ee008497SSandy Huang struct crtc_state *cstate = &state->crtc_state; 4348ee008497SSandy Huang struct vop2 *vop2 = cstate->private; 4349ee008497SSandy Huang int i = 0; 4350ee008497SSandy Huang int correct_cursor_plane = -1; 4351ee008497SSandy Huang int plane_type = -1; 4352ee008497SSandy Huang 4353ee008497SSandy Huang if (cursor_plane < 0) 4354ee008497SSandy Huang return -1; 4355ee008497SSandy Huang 4356ee008497SSandy Huang if (plane_mask & (1 << cursor_plane)) 4357ee008497SSandy Huang return cursor_plane; 4358ee008497SSandy Huang 4359ee008497SSandy Huang /* Get current cursor plane type */ 4360ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 4361ee008497SSandy Huang if (vop2->data->plane_table[i].plane_id == cursor_plane) { 4362ee008497SSandy Huang plane_type = vop2->data->plane_table[i].plane_type; 4363ee008497SSandy Huang break; 4364ee008497SSandy Huang } 4365ee008497SSandy Huang } 4366ee008497SSandy Huang 4367ee008497SSandy Huang /* Get the other same plane type plane id */ 4368ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 4369ee008497SSandy Huang if (vop2->data->plane_table[i].plane_type == plane_type && 4370ee008497SSandy Huang vop2->data->plane_table[i].plane_id != cursor_plane) { 4371ee008497SSandy Huang correct_cursor_plane = vop2->data->plane_table[i].plane_id; 4372ee008497SSandy Huang break; 4373ee008497SSandy Huang } 4374ee008497SSandy Huang } 4375ee008497SSandy Huang 4376ee008497SSandy Huang /* To check whether the new correct_cursor_plane is attach to current vp */ 4377ee008497SSandy Huang if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 4378ee008497SSandy Huang printf("error: faild to find correct plane as cursor plane\n"); 4379ee008497SSandy Huang return -1; 4380ee008497SSandy Huang } 4381ee008497SSandy Huang 4382ee008497SSandy Huang printf("vp%d adjust cursor plane from %d to %d\n", 4383ee008497SSandy Huang cstate->crtc_id, cursor_plane, correct_cursor_plane); 4384ee008497SSandy Huang 4385ee008497SSandy Huang return correct_cursor_plane; 4386ee008497SSandy Huang } 4387ee008497SSandy Huang 4388b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 4389b0989546SSandy Huang { 4390b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 4391b0989546SSandy Huang struct vop2 *vop2 = cstate->private; 4392b0989546SSandy Huang ofnode vp_node; 4393b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node; 4394b0989546SSandy Huang static bool vop_fix_dts; 4395b0989546SSandy Huang const char *path; 4396b0989546SSandy Huang u32 plane_mask = 0; 4397b0989546SSandy Huang int vp_id = 0; 4398ee008497SSandy Huang int cursor_plane_id = -1; 4399b0989546SSandy Huang 44005fa6e665SDamon Ding if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528) 4401b0989546SSandy Huang return 0; 4402b0989546SSandy Huang 4403b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 4404b0989546SSandy Huang path = vp_node.np->full_name; 4405b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 4406b0989546SSandy Huang 44078b1fe597SSandy Huang if (cstate->crtc->assign_plane) 44088b1fe597SSandy Huang continue; 4409ee008497SSandy Huang cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 4410ee008497SSandy Huang cstate->crtc->vps[vp_id].cursor_plane); 4411ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 4412b0989546SSandy Huang vp_id, plane_mask, 4413ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 4414ee008497SSandy Huang cursor_plane_id); 4415b0989546SSandy Huang 4416b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 4417b0989546SSandy Huang plane_mask, 1); 4418b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 4419b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 4420ee008497SSandy Huang if (cursor_plane_id >= 0) 4421ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id", 4422ee008497SSandy Huang cursor_plane_id, 1); 4423b0989546SSandy Huang vp_id++; 4424b0989546SSandy Huang } 4425b0989546SSandy Huang 4426b0989546SSandy Huang vop_fix_dts = true; 4427b0989546SSandy Huang 4428b0989546SSandy Huang return 0; 4429b0989546SSandy Huang } 4430b0989546SSandy Huang 4431820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state) 4432820a5c17SDamon Ding { 4433820a5c17SDamon Ding struct crtc_state *cstate = &state->crtc_state; 4434820a5c17SDamon Ding struct rockchip_crtc *crtc = cstate->crtc; 4435820a5c17SDamon Ding 4436820a5c17SDamon Ding if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) { 4437820a5c17SDamon Ding printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id); 4438820a5c17SDamon Ding return -ENOTSUPP; 4439820a5c17SDamon Ding } 4440820a5c17SDamon Ding 4441820a5c17SDamon Ding if (cstate->splice_mode) { 4442820a5c17SDamon Ding crtc->splice_mode = true; 4443820a5c17SDamon Ding crtc->splice_crtc_id = cstate->splice_crtc_id; 4444820a5c17SDamon Ding } 4445820a5c17SDamon Ding 4446820a5c17SDamon Ding return 0; 4447820a5c17SDamon Ding } 4448820a5c17SDamon Ding 444922007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state) 445022007755SDamon Ding { 445122007755SDamon Ding struct connector_state *conn_state = &state->conn_state; 445222007755SDamon Ding struct crtc_state *cstate = &state->crtc_state; 445322007755SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 445422007755SDamon Ding struct videomode vm; 445522007755SDamon Ding 445622007755SDamon Ding drm_display_mode_to_videomode(mode, &vm); 445722007755SDamon Ding 445822007755SDamon Ding if (vm.hactive < 32 || vm.vactive < 32 || 445922007755SDamon Ding (vm.hfront_porch * vm.hsync_len * vm.hback_porch * 446022007755SDamon Ding vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) { 446122007755SDamon Ding printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id); 446222007755SDamon Ding return -EINVAL; 446322007755SDamon Ding } 446422007755SDamon Ding 446522007755SDamon Ding return 0; 446622007755SDamon Ding } 446722007755SDamon Ding 44684c765862SDamon Ding #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) 44694c765862SDamon Ding 44704c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state) 44714c765862SDamon Ding { 44724c765862SDamon Ding struct crtc_state *cstate = &state->crtc_state; 44734c765862SDamon Ding struct vop2 *vop2 = cstate->private; 44744c765862SDamon Ding struct display_rect *src = &cstate->src_rect; 44754c765862SDamon Ding struct display_rect *dst = &cstate->crtc_rect; 44764c765862SDamon Ding struct vop2_win_data *win_data; 44774c765862SDamon Ding int min_scale, max_scale; 44784c765862SDamon Ding int hscale, vscale; 44794c765862SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 44804c765862SDamon Ding 44814c765862SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 44824c765862SDamon Ding if (!win_data) { 44834c765862SDamon Ding printf("ERROR: invalid win id %d\n", primary_plane_id); 44844c765862SDamon Ding return -ENODEV; 44854c765862SDamon Ding } 44864c765862SDamon Ding 44874c765862SDamon Ding min_scale = FRAC_16_16(1, win_data->max_downscale_factor); 44884c765862SDamon Ding max_scale = FRAC_16_16(win_data->max_upscale_factor, 1); 44894c765862SDamon Ding 44904c765862SDamon Ding hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale); 44914c765862SDamon Ding vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale); 44924c765862SDamon Ding if (hscale < 0 || vscale < 0) { 44934c765862SDamon Ding printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name); 44944c765862SDamon Ding return -ERANGE; 44954c765862SDamon Ding } 44964c765862SDamon Ding 44974c765862SDamon Ding return 0; 44984c765862SDamon Ding } 4499337d1c13SDamon Ding 45008e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state) 45018e7ef808SDamon Ding { 4502*d8e7f4a5SSandy Huang __maybe_unused struct connector_state *conn_state = &state->conn_state; 45038e7ef808SDamon Ding struct crtc_state *cstate = &state->crtc_state; 45048e7ef808SDamon Ding struct vop2 *vop2 = cstate->private; 45058e7ef808SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 45068e7ef808SDamon Ding int val = 0; 45078e7ef808SDamon Ding int ret = 0; 45088e7ef808SDamon Ding 45098e7ef808SDamon Ding ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val, 45108e7ef808SDamon Ding (val >> EDPI_WMS_FS) & 0x1, 50 * 1000); 45118e7ef808SDamon Ding if (!ret) { 4512*d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 45138e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 45148e7ef808SDamon Ding !val, 50 * 1000); 45158e7ef808SDamon Ding if (!ret) { 45168e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 45178e7ef808SDamon Ding val, 50 * 1000); 45188e7ef808SDamon Ding if (!ret) { 45198e7ef808SDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 45208e7ef808SDamon Ding EN_MASK, EDPI_WMS_FS, 1, false); 45218e7ef808SDamon Ding } else { 45228e7ef808SDamon Ding printf("ERROR: vp%d wait for active TE signal timeout\n", 45238e7ef808SDamon Ding cstate->crtc_id); 45248e7ef808SDamon Ding return ret; 45258e7ef808SDamon Ding } 45268e7ef808SDamon Ding } else { 45278e7ef808SDamon Ding printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id); 45288e7ef808SDamon Ding return ret; 45298e7ef808SDamon Ding } 4530*d8e7f4a5SSandy Huang #endif 45318e7ef808SDamon Ding } else { 45328e7ef808SDamon Ding printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id); 45338e7ef808SDamon Ding return ret; 45348e7ef808SDamon Ding } 45358e7ef808SDamon Ding 45368e7ef808SDamon Ding return 0; 45378e7ef808SDamon Ding } 45388e7ef808SDamon Ding 453972388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state) 454072388c26SDamon Ding { 454172388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 454272388c26SDamon Ding struct vop2 *vop2 = cstate->private; 454372388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 454472388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 454572388c26SDamon Ding u32 n, i, j; 454672388c26SDamon Ding u32 base; 454772388c26SDamon Ding 454872388c26SDamon Ding if (!cstate->crtc->active) 454972388c26SDamon Ding return -EINVAL; 455072388c26SDamon Ding 455172388c26SDamon Ding n = vop2_data->dump_regs_size; 455272388c26SDamon Ding for (i = 0; i < n; i++) { 455372388c26SDamon Ding base = regs[i].offset; 455472388c26SDamon Ding printf("\n%s:\n", regs[i].name); 455572388c26SDamon Ding for (j = 0; j < 68;) { 455672388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 455772388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 455872388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 455972388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 456072388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 456172388c26SDamon Ding j += 4; 456272388c26SDamon Ding } 456372388c26SDamon Ding } 456472388c26SDamon Ding 456572388c26SDamon Ding return 0; 456672388c26SDamon Ding } 456772388c26SDamon Ding 456872388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state) 456972388c26SDamon Ding { 457072388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 457172388c26SDamon Ding struct vop2 *vop2 = cstate->private; 457272388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 457372388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 457472388c26SDamon Ding u32 n, i, j; 457572388c26SDamon Ding u32 base; 457672388c26SDamon Ding bool enable_state; 457772388c26SDamon Ding 457872388c26SDamon Ding if (!cstate->crtc->active) 457972388c26SDamon Ding return -EINVAL; 458072388c26SDamon Ding 458172388c26SDamon Ding n = vop2_data->dump_regs_size; 458272388c26SDamon Ding for (i = 0; i < n; i++) { 458372388c26SDamon Ding if (regs[i].state_mask) { 458472388c26SDamon Ding enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) & 458572388c26SDamon Ding regs[i].state_mask; 458672388c26SDamon Ding if (enable_state != regs[i].enable_state) 458772388c26SDamon Ding continue; 458872388c26SDamon Ding } 458972388c26SDamon Ding 459072388c26SDamon Ding base = regs[i].offset; 459172388c26SDamon Ding printf("\n%s:\n", regs[i].name); 459272388c26SDamon Ding for (j = 0; j < 68;) { 459372388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 459472388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 459572388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 459672388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 459772388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 459872388c26SDamon Ding j += 4; 459972388c26SDamon Ding } 460072388c26SDamon Ding } 460172388c26SDamon Ding 460272388c26SDamon Ding return 0; 460372388c26SDamon Ding } 460472388c26SDamon Ding 460572388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = { 460672388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 460772388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 460872388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 460972388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 461072388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 461172388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 461272388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 461372388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 461472388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 461572388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 461672388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 461772388c26SDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 461872388c26SDamon Ding { RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1}, 461972388c26SDamon Ding }; 462072388c26SDamon Ding 46215fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 46225fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, 46235fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART1, 46245fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, 46255fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART3, 46265fa6e665SDamon Ding }; 46275fa6e665SDamon Ding 46285fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 46295fa6e665SDamon Ding {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 46305fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 46315fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 46325fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 46335fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 46345fa6e665SDamon Ding }; 46355fa6e665SDamon Ding 46365fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 46375fa6e665SDamon Ding { /* one display policy for hdmi */ 46385fa6e665SDamon Ding {/* main display */ 4639ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 46405fa6e665SDamon Ding .attached_layers_nr = 4, 46415fa6e665SDamon Ding .attached_layers = { 46425fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 46435fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2 46445fa6e665SDamon Ding }, 46455fa6e665SDamon Ding }, 46465fa6e665SDamon Ding {/* second display */}, 46475fa6e665SDamon Ding {/* third display */}, 46485fa6e665SDamon Ding {/* fourth display */}, 46495fa6e665SDamon Ding }, 46505fa6e665SDamon Ding 46515fa6e665SDamon Ding { /* two display policy */ 46525fa6e665SDamon Ding {/* main display */ 4653ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 46545fa6e665SDamon Ding .attached_layers_nr = 3, 46555fa6e665SDamon Ding .attached_layers = { 46565fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 46575fa6e665SDamon Ding }, 46585fa6e665SDamon Ding }, 46595fa6e665SDamon Ding 46605fa6e665SDamon Ding {/* second display */ 46615fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 46625fa6e665SDamon Ding .attached_layers_nr = 2, 46635fa6e665SDamon Ding .attached_layers = { 46645fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 46655fa6e665SDamon Ding }, 46665fa6e665SDamon Ding }, 46675fa6e665SDamon Ding {/* third display */}, 46685fa6e665SDamon Ding {/* fourth display */}, 46695fa6e665SDamon Ding }, 46705fa6e665SDamon Ding 46715fa6e665SDamon Ding { /* one display policy for cvbs */ 46725fa6e665SDamon Ding {/* main display */ 46735fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 46745fa6e665SDamon Ding .attached_layers_nr = 2, 46755fa6e665SDamon Ding .attached_layers = { 46765fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 46775fa6e665SDamon Ding }, 46785fa6e665SDamon Ding }, 46795fa6e665SDamon Ding {/* second display */}, 46805fa6e665SDamon Ding {/* third display */}, 46815fa6e665SDamon Ding {/* fourth display */}, 46825fa6e665SDamon Ding }, 46835fa6e665SDamon Ding 46845fa6e665SDamon Ding {/* reserved */}, 46855fa6e665SDamon Ding }; 46865fa6e665SDamon Ding 46875fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = { 46885fa6e665SDamon Ding { 46895fa6e665SDamon Ding .name = "Esmart0", 46905fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 46915fa6e665SDamon Ding .type = ESMART_LAYER, 46925fa6e665SDamon Ding .win_sel_port_offset = 8, 46935fa6e665SDamon Ding .layer_sel_win_id = { 1, 0xff, 0xff, 0xff }, 46945fa6e665SDamon Ding .reg_offset = 0, 46955fa6e665SDamon Ding .axi_id = 0, 46965fa6e665SDamon Ding .axi_yrgb_id = 0x06, 46975fa6e665SDamon Ding .axi_uv_id = 0x07, 46985fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 46995fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47005fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 47015fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47025fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 47035fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 47045fa6e665SDamon Ding .max_upscale_factor = 8, 47055fa6e665SDamon Ding .max_downscale_factor = 8, 47065fa6e665SDamon Ding }, 47075fa6e665SDamon Ding 47085fa6e665SDamon Ding { 47095fa6e665SDamon Ding .name = "Esmart1", 47105fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 47115fa6e665SDamon Ding .type = ESMART_LAYER, 47125fa6e665SDamon Ding .win_sel_port_offset = 10, 47135fa6e665SDamon Ding .layer_sel_win_id = { 2, 0xff, 0xff, 0xff }, 47145fa6e665SDamon Ding .reg_offset = 0x200, 47155fa6e665SDamon Ding .axi_id = 0, 47165fa6e665SDamon Ding .axi_yrgb_id = 0x08, 47175fa6e665SDamon Ding .axi_uv_id = 0x09, 47185fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 47195fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47205fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 47215fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47225fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 47235fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 47245fa6e665SDamon Ding .max_upscale_factor = 8, 47255fa6e665SDamon Ding .max_downscale_factor = 8, 47265fa6e665SDamon Ding }, 47275fa6e665SDamon Ding 47285fa6e665SDamon Ding { 47295fa6e665SDamon Ding .name = "Esmart2", 47305fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 47315fa6e665SDamon Ding .type = ESMART_LAYER, 47325fa6e665SDamon Ding .win_sel_port_offset = 12, 47335fa6e665SDamon Ding .layer_sel_win_id = { 3, 0, 0xff, 0xff }, 47345fa6e665SDamon Ding .reg_offset = 0x400, 47355fa6e665SDamon Ding .axi_id = 0, 47365fa6e665SDamon Ding .axi_yrgb_id = 0x0a, 47375fa6e665SDamon Ding .axi_uv_id = 0x0b, 47385fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 47395fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47405fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 47415fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47425fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 47435fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 47445fa6e665SDamon Ding .max_upscale_factor = 8, 47455fa6e665SDamon Ding .max_downscale_factor = 8, 47465fa6e665SDamon Ding }, 47475fa6e665SDamon Ding 47485fa6e665SDamon Ding { 47495fa6e665SDamon Ding .name = "Esmart3", 47505fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 47515fa6e665SDamon Ding .type = ESMART_LAYER, 47525fa6e665SDamon Ding .win_sel_port_offset = 14, 47535fa6e665SDamon Ding .layer_sel_win_id = { 0xff, 1, 0xff, 0xff }, 47545fa6e665SDamon Ding .reg_offset = 0x600, 47555fa6e665SDamon Ding .axi_id = 0, 47565fa6e665SDamon Ding .axi_yrgb_id = 0x0c, 47575fa6e665SDamon Ding .axi_uv_id = 0x0d, 47585fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 47595fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47605fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 47615fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47625fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 47635fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 47645fa6e665SDamon Ding .max_upscale_factor = 8, 47655fa6e665SDamon Ding .max_downscale_factor = 8, 47665fa6e665SDamon Ding }, 47675fa6e665SDamon Ding 47685fa6e665SDamon Ding { 47695fa6e665SDamon Ding .name = "Cluster0", 47705fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0, 47715fa6e665SDamon Ding .type = CLUSTER_LAYER, 47725fa6e665SDamon Ding .win_sel_port_offset = 0, 47735fa6e665SDamon Ding .layer_sel_win_id = { 0, 0xff, 0xff, 0xff }, 47745fa6e665SDamon Ding .reg_offset = 0, 47755fa6e665SDamon Ding .axi_id = 0, 47765fa6e665SDamon Ding .axi_yrgb_id = 0x02, 47775fa6e665SDamon Ding .axi_uv_id = 0x03, 47785fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 47795fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47805fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 47815fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 47825fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 47835fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 47845fa6e665SDamon Ding .max_upscale_factor = 8, 47855fa6e665SDamon Ding .max_downscale_factor = 8, 47865fa6e665SDamon Ding }, 47875fa6e665SDamon Ding }; 47885fa6e665SDamon Ding 47895fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = { 47905fa6e665SDamon Ding { 47916027c871SZhang Yubing .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM | 47926027c871SZhang Yubing VOP_FEATURE_POST_CSC, 47935fa6e665SDamon Ding .max_output = {4096, 4096}, 4794b05105abSDamon Ding .layer_mix_dly = 6, 4795b05105abSDamon Ding .hdr_mix_dly = 2, 4796b05105abSDamon Ding .win_dly = 8, 47975fa6e665SDamon Ding }, 47985fa6e665SDamon Ding { 47995fa6e665SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 48005fa6e665SDamon Ding .max_output = {1920, 1080}, 4801b05105abSDamon Ding .layer_mix_dly = 2, 4802b05105abSDamon Ding .hdr_mix_dly = 0, 4803b05105abSDamon Ding .win_dly = 8, 48045fa6e665SDamon Ding }, 48055fa6e665SDamon Ding }; 48065fa6e665SDamon Ding 48075fa6e665SDamon Ding const struct vop2_data rk3528_vop = { 48085fa6e665SDamon Ding .version = VOP_VERSION_RK3528, 48095fa6e665SDamon Ding .nr_vps = 2, 48105fa6e665SDamon Ding .vp_data = rk3528_vp_data, 48115fa6e665SDamon Ding .win_data = rk3528_win_data, 48125fa6e665SDamon Ding .plane_mask = rk3528_vp_plane_mask[0], 48135fa6e665SDamon Ding .plane_table = rk3528_plane_table, 48145fa6e665SDamon Ding .vp_primary_plane_order = rk3528_vp_primary_plane_order, 48155fa6e665SDamon Ding .nr_layers = 5, 48165fa6e665SDamon Ding .nr_mixers = 3, 48175fa6e665SDamon Ding .nr_gammas = 2, 48185fa6e665SDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE, 481972388c26SDamon Ding .dump_regs = rk3528_dump_regs, 482072388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3528_dump_regs), 482172388c26SDamon Ding }; 482272388c26SDamon Ding 482372388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = { 482472388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 482572388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 482672388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 482772388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 482872388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 482972388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 483072388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 483172388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 483272388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 483372388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 48345fa6e665SDamon Ding }; 48355fa6e665SDamon Ding 4836452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 4837452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, 4838452afb13SDamon Ding ROCKCHIP_VOP2_ESMART1, 4839452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, 4840452afb13SDamon Ding ROCKCHIP_VOP2_ESMART3, 4841452afb13SDamon Ding }; 4842452afb13SDamon Ding 4843452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 4844452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 4845452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 4846452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 4847452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 4848452afb13SDamon Ding }; 4849452afb13SDamon Ding 4850452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 4851452afb13SDamon Ding { /* one display policy for hdmi */ 4852452afb13SDamon Ding {/* main display */ 4853452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 4854452afb13SDamon Ding .attached_layers_nr = 4, 4855452afb13SDamon Ding .attached_layers = { 4856452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, 4857452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 4858452afb13SDamon Ding }, 4859452afb13SDamon Ding }, 4860452afb13SDamon Ding {/* second display */}, 4861452afb13SDamon Ding {/* third display */}, 4862452afb13SDamon Ding {/* fourth display */}, 4863452afb13SDamon Ding }, 4864452afb13SDamon Ding 4865452afb13SDamon Ding { /* two display policy */ 4866452afb13SDamon Ding {/* main display */ 4867452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 4868452afb13SDamon Ding .attached_layers_nr = 2, 4869452afb13SDamon Ding .attached_layers = { 4870452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 4871452afb13SDamon Ding }, 4872452afb13SDamon Ding }, 4873452afb13SDamon Ding 4874452afb13SDamon Ding {/* second display */ 4875452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 4876452afb13SDamon Ding .attached_layers_nr = 2, 4877452afb13SDamon Ding .attached_layers = { 4878452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 4879452afb13SDamon Ding }, 4880452afb13SDamon Ding }, 4881452afb13SDamon Ding {/* third display */}, 4882452afb13SDamon Ding {/* fourth display */}, 4883452afb13SDamon Ding }, 4884452afb13SDamon Ding 4885452afb13SDamon Ding {/* reserved */}, 4886452afb13SDamon Ding }; 4887452afb13SDamon Ding 4888452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = { 4889452afb13SDamon Ding { 4890452afb13SDamon Ding .name = "Esmart0", 4891452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 4892452afb13SDamon Ding .type = ESMART_LAYER, 4893452afb13SDamon Ding .win_sel_port_offset = 8, 4894452afb13SDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 4895452afb13SDamon Ding .reg_offset = 0, 4896452afb13SDamon Ding .axi_id = 0, 4897452afb13SDamon Ding .axi_yrgb_id = 0x02, 4898452afb13SDamon Ding .axi_uv_id = 0x03, 4899452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4900452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4901452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4902452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4903452afb13SDamon Ding .max_upscale_factor = 8, 4904452afb13SDamon Ding .max_downscale_factor = 8, 4905452afb13SDamon Ding }, 4906452afb13SDamon Ding 4907452afb13SDamon Ding { 4908452afb13SDamon Ding .name = "Esmart1", 4909452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 4910452afb13SDamon Ding .type = ESMART_LAYER, 4911452afb13SDamon Ding .win_sel_port_offset = 10, 4912452afb13SDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 4913452afb13SDamon Ding .reg_offset = 0x200, 4914452afb13SDamon Ding .axi_id = 0, 4915452afb13SDamon Ding .axi_yrgb_id = 0x04, 4916452afb13SDamon Ding .axi_uv_id = 0x05, 4917452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4918452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4919452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4920452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4921452afb13SDamon Ding .max_upscale_factor = 8, 4922452afb13SDamon Ding .max_downscale_factor = 8, 4923452afb13SDamon Ding }, 4924452afb13SDamon Ding 4925452afb13SDamon Ding { 4926452afb13SDamon Ding .name = "Esmart2", 4927452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 4928452afb13SDamon Ding .type = ESMART_LAYER, 4929452afb13SDamon Ding .win_sel_port_offset = 12, 4930452afb13SDamon Ding .layer_sel_win_id = { 2, 2, 0xff, 0xff }, 4931452afb13SDamon Ding .reg_offset = 0x400, 4932452afb13SDamon Ding .axi_id = 0, 4933452afb13SDamon Ding .axi_yrgb_id = 0x06, 4934452afb13SDamon Ding .axi_uv_id = 0x07, 4935452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4936452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4937452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4938452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4939452afb13SDamon Ding .max_upscale_factor = 8, 4940452afb13SDamon Ding .max_downscale_factor = 8, 4941452afb13SDamon Ding }, 4942452afb13SDamon Ding 4943452afb13SDamon Ding { 4944452afb13SDamon Ding .name = "Esmart3", 4945452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 4946452afb13SDamon Ding .type = ESMART_LAYER, 4947452afb13SDamon Ding .win_sel_port_offset = 14, 4948452afb13SDamon Ding .layer_sel_win_id = { 3, 3, 0xff, 0xff }, 4949452afb13SDamon Ding .reg_offset = 0x600, 4950452afb13SDamon Ding .axi_id = 0, 4951452afb13SDamon Ding .axi_yrgb_id = 0x08, 4952452afb13SDamon Ding .axi_uv_id = 0x0d, 4953452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4954452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4955452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4956452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4957452afb13SDamon Ding .max_upscale_factor = 8, 4958452afb13SDamon Ding .max_downscale_factor = 8, 4959452afb13SDamon Ding }, 4960452afb13SDamon Ding }; 4961452afb13SDamon Ding 4962452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = { 4963452afb13SDamon Ding { 4964452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 4965452afb13SDamon Ding .max_output = {2048, 4096}, 4966452afb13SDamon Ding .win_dly = 8, 4967452afb13SDamon Ding .layer_mix_dly = 8, 4968452afb13SDamon Ding }, 4969452afb13SDamon Ding { 4970452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 4971452afb13SDamon Ding .max_output = {2048, 1080}, 4972452afb13SDamon Ding .win_dly = 8, 4973452afb13SDamon Ding .layer_mix_dly = 8, 4974452afb13SDamon Ding }, 4975452afb13SDamon Ding }; 4976452afb13SDamon Ding 4977452afb13SDamon Ding const struct vop2_data rk3562_vop = { 4978452afb13SDamon Ding .version = VOP_VERSION_RK3562, 4979452afb13SDamon Ding .nr_vps = 2, 4980452afb13SDamon Ding .vp_data = rk3562_vp_data, 4981452afb13SDamon Ding .win_data = rk3562_win_data, 4982452afb13SDamon Ding .plane_mask = rk3562_vp_plane_mask[0], 4983452afb13SDamon Ding .plane_table = rk3562_plane_table, 4984452afb13SDamon Ding .vp_primary_plane_order = rk3562_vp_primary_plane_order, 4985452afb13SDamon Ding .nr_layers = 4, 4986452afb13SDamon Ding .nr_mixers = 3, 4987452afb13SDamon Ding .nr_gammas = 2, 4988452afb13SDamon Ding .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE, 498972388c26SDamon Ding .dump_regs = rk3562_dump_regs, 499072388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3562_dump_regs), 499172388c26SDamon Ding }; 499272388c26SDamon Ding 499372388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = { 499472388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 499572388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 499672388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 499772388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 499872388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 499972388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 500072388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 500172388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 500272388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 500372388c26SDamon Ding { RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 500472388c26SDamon Ding { RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 500572388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 5006452afb13SDamon Ding }; 5007452afb13SDamon Ding 5008337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 5009337d1c13SDamon Ding ROCKCHIP_VOP2_SMART0, 5010337d1c13SDamon Ding ROCKCHIP_VOP2_SMART1, 5011337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 5012337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 5013337d1c13SDamon Ding }; 5014337d1c13SDamon Ding 5015ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 5016ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 5017ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 5018ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 5019ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 5020ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 5021ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 5022ee008497SSandy Huang }; 5023ee008497SSandy Huang 5024b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 5025b0989546SSandy Huang { /* one display policy */ 5026b0989546SSandy Huang {/* main display */ 5027b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 5028b0989546SSandy Huang .attached_layers_nr = 6, 5029b0989546SSandy Huang .attached_layers = { 5030b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 5031b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 5032b0989546SSandy Huang }, 5033b0989546SSandy Huang }, 5034b0989546SSandy Huang {/* second display */}, 5035b0989546SSandy Huang {/* third display */}, 5036b0989546SSandy Huang {/* fourth display */}, 5037b0989546SSandy Huang }, 5038b0989546SSandy Huang 5039b0989546SSandy Huang { /* two display policy */ 5040b0989546SSandy Huang {/* main display */ 5041b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 5042b0989546SSandy Huang .attached_layers_nr = 3, 5043b0989546SSandy Huang .attached_layers = { 5044b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 5045b0989546SSandy Huang }, 5046b0989546SSandy Huang }, 5047b0989546SSandy Huang 5048b0989546SSandy Huang {/* second display */ 5049b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 5050b0989546SSandy Huang .attached_layers_nr = 3, 5051b0989546SSandy Huang .attached_layers = { 5052b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 5053b0989546SSandy Huang }, 5054b0989546SSandy Huang }, 5055b0989546SSandy Huang {/* third display */}, 5056b0989546SSandy Huang {/* fourth display */}, 5057b0989546SSandy Huang }, 5058b0989546SSandy Huang 5059b0989546SSandy Huang { /* three display policy */ 5060b0989546SSandy Huang {/* main display */ 5061b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 5062b0989546SSandy Huang .attached_layers_nr = 3, 5063b0989546SSandy Huang .attached_layers = { 5064b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 5065b0989546SSandy Huang }, 5066b0989546SSandy Huang }, 5067b0989546SSandy Huang 5068b0989546SSandy Huang {/* second display */ 5069b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 5070b0989546SSandy Huang .attached_layers_nr = 2, 5071b0989546SSandy Huang .attached_layers = { 5072b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 5073b0989546SSandy Huang }, 5074b0989546SSandy Huang }, 5075b0989546SSandy Huang 5076b0989546SSandy Huang {/* third display */ 5077b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 5078b0989546SSandy Huang .attached_layers_nr = 1, 5079b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 5080b0989546SSandy Huang }, 5081b0989546SSandy Huang 5082b0989546SSandy Huang {/* fourth display */}, 5083b0989546SSandy Huang }, 5084b0989546SSandy Huang 5085b0989546SSandy Huang {/* reserved for four display policy */}, 5086b0989546SSandy Huang }; 5087b0989546SSandy Huang 5088b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = { 5089b0989546SSandy Huang { 5090b0989546SSandy Huang .name = "Cluster0", 5091b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0, 5092ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5093b0989546SSandy Huang .win_sel_port_offset = 0, 50945fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0xff }, 5095b0989546SSandy Huang .reg_offset = 0, 50965fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 50975fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 50985fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 50995fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51004c765862SDamon Ding .max_upscale_factor = 4, 51014c765862SDamon Ding .max_downscale_factor = 4, 5102b0989546SSandy Huang }, 5103b0989546SSandy Huang 5104b0989546SSandy Huang { 5105b0989546SSandy Huang .name = "Cluster1", 5106b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1, 5107ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5108b0989546SSandy Huang .win_sel_port_offset = 1, 51095fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 0xff }, 5110b0989546SSandy Huang .reg_offset = 0x200, 51115fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51125fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51135fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51145fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51154c765862SDamon Ding .max_upscale_factor = 4, 51164c765862SDamon Ding .max_downscale_factor = 4, 5117b0989546SSandy Huang }, 5118b0989546SSandy Huang 5119b0989546SSandy Huang { 5120b0989546SSandy Huang .name = "Esmart0", 5121b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0, 5122ecc31b6eSAndy Yan .type = ESMART_LAYER, 5123b0989546SSandy Huang .win_sel_port_offset = 4, 51245fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 0xff }, 5125b0989546SSandy Huang .reg_offset = 0, 51265fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51275fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51285fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51295fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51304c765862SDamon Ding .max_upscale_factor = 8, 51314c765862SDamon Ding .max_downscale_factor = 8, 5132b0989546SSandy Huang }, 5133b0989546SSandy Huang 5134b0989546SSandy Huang { 5135b0989546SSandy Huang .name = "Esmart1", 5136b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1, 5137ecc31b6eSAndy Yan .type = ESMART_LAYER, 5138b0989546SSandy Huang .win_sel_port_offset = 5, 51395fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 0xff }, 5140b0989546SSandy Huang .reg_offset = 0x200, 51415fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51425fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51435fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51445fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51454c765862SDamon Ding .max_upscale_factor = 8, 51464c765862SDamon Ding .max_downscale_factor = 8, 5147b0989546SSandy Huang }, 5148b0989546SSandy Huang 5149b0989546SSandy Huang { 5150b0989546SSandy Huang .name = "Smart0", 5151b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0, 5152ecc31b6eSAndy Yan .type = SMART_LAYER, 5153b0989546SSandy Huang .win_sel_port_offset = 6, 51545fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 0xff }, 5155b0989546SSandy Huang .reg_offset = 0x400, 51565fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51575fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51585fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51595fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51604c765862SDamon Ding .max_upscale_factor = 8, 51614c765862SDamon Ding .max_downscale_factor = 8, 5162b0989546SSandy Huang }, 5163b0989546SSandy Huang 5164b0989546SSandy Huang { 5165b0989546SSandy Huang .name = "Smart1", 5166b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1, 5167ecc31b6eSAndy Yan .type = SMART_LAYER, 5168b0989546SSandy Huang .win_sel_port_offset = 7, 51695fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 0xff }, 5170b0989546SSandy Huang .reg_offset = 0x600, 51715fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51725fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51735fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51745fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51754c765862SDamon Ding .max_upscale_factor = 8, 51764c765862SDamon Ding .max_downscale_factor = 8, 5177b0989546SSandy Huang }, 5178b0989546SSandy Huang }; 5179b0989546SSandy Huang 518063cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = { 518163cb669fSSandy Huang { 518263cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT, 518363cb669fSSandy Huang .pre_scan_max_dly = 42, 518463cb669fSSandy Huang .max_output = {4096, 2304}, 5185d0408543SAndy Yan }, 518663cb669fSSandy Huang { 518763cb669fSSandy Huang .feature = 0, 518863cb669fSSandy Huang .pre_scan_max_dly = 40, 518963cb669fSSandy Huang .max_output = {2048, 1536}, 519063cb669fSSandy Huang }, 519163cb669fSSandy Huang { 519263cb669fSSandy Huang .feature = 0, 519363cb669fSSandy Huang .pre_scan_max_dly = 40, 519463cb669fSSandy Huang .max_output = {1920, 1080}, 519563cb669fSSandy Huang }, 519663cb669fSSandy Huang }; 5197d0408543SAndy Yan 519863cb669fSSandy Huang const struct vop2_data rk3568_vop = { 5199ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568, 520063cb669fSSandy Huang .nr_vps = 3, 520163cb669fSSandy Huang .vp_data = rk3568_vp_data, 5202b0989546SSandy Huang .win_data = rk3568_win_data, 5203b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0], 5204ee008497SSandy Huang .plane_table = rk356x_plane_table, 5205337d1c13SDamon Ding .vp_primary_plane_order = rk3568_vp_primary_plane_order, 5206d0408543SAndy Yan .nr_layers = 6, 520763cb669fSSandy Huang .nr_mixers = 5, 52081147facaSSandy Huang .nr_gammas = 1, 520972388c26SDamon Ding .dump_regs = rk3568_dump_regs, 521072388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs), 5211d0408543SAndy Yan }; 5212d0408543SAndy Yan 5213337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 5214337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 5215337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 5216337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART2, 5217337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART3, 5218337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 5219337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER1, 5220337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER2, 5221337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER3, 5222337d1c13SDamon Ding }; 5223337d1c13SDamon Ding 5224ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 5225ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 5226ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 5227ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 5228ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 5229ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 5230ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 5231ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 5232ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 5233ecc31b6eSAndy Yan }; 5234ecc31b6eSAndy Yan 523572388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = { 523672388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 523772388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 523872388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 523972388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 524072388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 524172388c26SDamon Ding { RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 }, 524272388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 524372388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 524472388c26SDamon Ding { RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 }, 524572388c26SDamon Ding { RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 }, 524672388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 524772388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 524872388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 524972388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 525072388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 525172388c26SDamon Ding }; 525272388c26SDamon Ding 5253ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 5254ecc31b6eSAndy Yan { /* one display policy */ 5255ecc31b6eSAndy Yan {/* main display */ 5256608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5257ecc31b6eSAndy Yan .attached_layers_nr = 8, 5258ecc31b6eSAndy Yan .attached_layers = { 5259ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, 5260ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, 5261ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 5262ecc31b6eSAndy Yan }, 5263ecc31b6eSAndy Yan }, 5264ecc31b6eSAndy Yan {/* second display */}, 5265ecc31b6eSAndy Yan {/* third display */}, 5266ecc31b6eSAndy Yan {/* fourth display */}, 5267ecc31b6eSAndy Yan }, 5268ecc31b6eSAndy Yan 5269ecc31b6eSAndy Yan { /* two display policy */ 5270ecc31b6eSAndy Yan {/* main display */ 5271608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5272ecc31b6eSAndy Yan .attached_layers_nr = 4, 5273ecc31b6eSAndy Yan .attached_layers = { 5274ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 5275ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 5276ecc31b6eSAndy Yan }, 5277ecc31b6eSAndy Yan }, 5278ecc31b6eSAndy Yan 5279ecc31b6eSAndy Yan {/* second display */ 5280608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5281ecc31b6eSAndy Yan .attached_layers_nr = 4, 5282ecc31b6eSAndy Yan .attached_layers = { 5283ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, 5284ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 5285ecc31b6eSAndy Yan }, 5286ecc31b6eSAndy Yan }, 5287ecc31b6eSAndy Yan {/* third display */}, 5288ecc31b6eSAndy Yan {/* fourth display */}, 5289ecc31b6eSAndy Yan }, 5290ecc31b6eSAndy Yan 5291ecc31b6eSAndy Yan { /* three display policy */ 5292ecc31b6eSAndy Yan {/* main display */ 5293608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5294ecc31b6eSAndy Yan .attached_layers_nr = 3, 5295ecc31b6eSAndy Yan .attached_layers = { 5296ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 5297ecc31b6eSAndy Yan }, 5298ecc31b6eSAndy Yan }, 5299ecc31b6eSAndy Yan 5300ecc31b6eSAndy Yan {/* second display */ 5301608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 5302ecc31b6eSAndy Yan .attached_layers_nr = 3, 5303ecc31b6eSAndy Yan .attached_layers = { 5304ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 5305ecc31b6eSAndy Yan }, 5306ecc31b6eSAndy Yan }, 5307ecc31b6eSAndy Yan 5308ecc31b6eSAndy Yan {/* third display */ 5309ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5310ecc31b6eSAndy Yan .attached_layers_nr = 2, 5311ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 5312ecc31b6eSAndy Yan }, 5313ecc31b6eSAndy Yan 5314ecc31b6eSAndy Yan {/* fourth display */}, 5315ecc31b6eSAndy Yan }, 5316ecc31b6eSAndy Yan 5317ecc31b6eSAndy Yan { /* four display policy */ 5318ecc31b6eSAndy Yan {/* main display */ 5319608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5320ecc31b6eSAndy Yan .attached_layers_nr = 2, 5321ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 5322ecc31b6eSAndy Yan }, 5323ecc31b6eSAndy Yan 5324ecc31b6eSAndy Yan {/* second display */ 5325608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 5326ecc31b6eSAndy Yan .attached_layers_nr = 2, 5327ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 5328ecc31b6eSAndy Yan }, 5329ecc31b6eSAndy Yan 5330ecc31b6eSAndy Yan {/* third display */ 5331608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5332ecc31b6eSAndy Yan .attached_layers_nr = 2, 5333ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 5334ecc31b6eSAndy Yan }, 5335ecc31b6eSAndy Yan 5336ecc31b6eSAndy Yan {/* fourth display */ 5337608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 5338ecc31b6eSAndy Yan .attached_layers_nr = 2, 5339ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 5340ecc31b6eSAndy Yan }, 5341ecc31b6eSAndy Yan }, 5342ecc31b6eSAndy Yan 5343ecc31b6eSAndy Yan }; 5344ecc31b6eSAndy Yan 5345ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = { 5346ecc31b6eSAndy Yan { 5347ecc31b6eSAndy Yan .name = "Cluster0", 5348ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0, 5349ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER1, 5350ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5351ecc31b6eSAndy Yan .win_sel_port_offset = 0, 53525fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0 }, 5353ecc31b6eSAndy Yan .reg_offset = 0, 5354a33b790fSDamon Ding .axi_id = 0, 5355a33b790fSDamon Ding .axi_yrgb_id = 2, 5356a33b790fSDamon Ding .axi_uv_id = 3, 5357b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER0, 53585fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 53595fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53605fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 53615fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53624c765862SDamon Ding .max_upscale_factor = 4, 53634c765862SDamon Ding .max_downscale_factor = 4, 5364ecc31b6eSAndy Yan }, 5365ecc31b6eSAndy Yan 5366ecc31b6eSAndy Yan { 5367ecc31b6eSAndy Yan .name = "Cluster1", 5368ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1, 5369ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5370ecc31b6eSAndy Yan .win_sel_port_offset = 1, 53715fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 1 }, 5372ecc31b6eSAndy Yan .reg_offset = 0x200, 5373a33b790fSDamon Ding .axi_id = 0, 5374a33b790fSDamon Ding .axi_yrgb_id = 6, 5375a33b790fSDamon Ding .axi_uv_id = 7, 5376b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER1, 53775fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 53785fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53795fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 53805fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53814c765862SDamon Ding .max_upscale_factor = 4, 53824c765862SDamon Ding .max_downscale_factor = 4, 5383ecc31b6eSAndy Yan }, 5384ecc31b6eSAndy Yan 5385ecc31b6eSAndy Yan { 5386ecc31b6eSAndy Yan .name = "Cluster2", 5387ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2, 5388ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER3, 5389ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5390ecc31b6eSAndy Yan .win_sel_port_offset = 2, 53915fa6e665SDamon Ding .layer_sel_win_id = { 4, 4, 4, 4 }, 5392ecc31b6eSAndy Yan .reg_offset = 0x400, 5393a33b790fSDamon Ding .axi_id = 1, 5394a33b790fSDamon Ding .axi_yrgb_id = 2, 5395a33b790fSDamon Ding .axi_uv_id = 3, 5396b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER2, 53975fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 53985fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53995fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54005fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54014c765862SDamon Ding .max_upscale_factor = 4, 54024c765862SDamon Ding .max_downscale_factor = 4, 5403ecc31b6eSAndy Yan }, 5404ecc31b6eSAndy Yan 5405ecc31b6eSAndy Yan { 5406ecc31b6eSAndy Yan .name = "Cluster3", 5407ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3, 5408ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5409ecc31b6eSAndy Yan .win_sel_port_offset = 3, 54105fa6e665SDamon Ding .layer_sel_win_id = { 5, 5, 5, 5 }, 5411ecc31b6eSAndy Yan .reg_offset = 0x600, 5412a33b790fSDamon Ding .axi_id = 1, 5413a33b790fSDamon Ding .axi_yrgb_id = 6, 5414a33b790fSDamon Ding .axi_uv_id = 7, 5415b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER3, 54165fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 54175fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54185fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54195fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54204c765862SDamon Ding .max_upscale_factor = 4, 54214c765862SDamon Ding .max_downscale_factor = 4, 5422ecc31b6eSAndy Yan }, 5423ecc31b6eSAndy Yan 5424ecc31b6eSAndy Yan { 5425ecc31b6eSAndy Yan .name = "Esmart0", 5426ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0, 5427ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART1, 5428ecc31b6eSAndy Yan .type = ESMART_LAYER, 5429ecc31b6eSAndy Yan .win_sel_port_offset = 4, 54305fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 2 }, 5431ecc31b6eSAndy Yan .reg_offset = 0, 5432a33b790fSDamon Ding .axi_id = 0, 5433a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 5434a33b790fSDamon Ding .axi_uv_id = 0x0b, 54355fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 54365fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54375fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54385fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54394c765862SDamon Ding .max_upscale_factor = 8, 54404c765862SDamon Ding .max_downscale_factor = 8, 5441ecc31b6eSAndy Yan }, 5442ecc31b6eSAndy Yan 5443ecc31b6eSAndy Yan { 5444ecc31b6eSAndy Yan .name = "Esmart1", 5445ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1, 5446ecc31b6eSAndy Yan .type = ESMART_LAYER, 5447ecc31b6eSAndy Yan .win_sel_port_offset = 5, 54485fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 3 }, 5449ecc31b6eSAndy Yan .reg_offset = 0x200, 5450a33b790fSDamon Ding .axi_id = 0, 5451a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 5452a33b790fSDamon Ding .axi_uv_id = 0x0d, 5453b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 54545fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 54555fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54565fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54575fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54584c765862SDamon Ding .max_upscale_factor = 8, 54594c765862SDamon Ding .max_downscale_factor = 8, 5460ecc31b6eSAndy Yan }, 5461ecc31b6eSAndy Yan 5462ecc31b6eSAndy Yan { 5463ecc31b6eSAndy Yan .name = "Esmart2", 5464ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2, 5465ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART3, 5466ecc31b6eSAndy Yan .type = ESMART_LAYER, 5467ecc31b6eSAndy Yan .win_sel_port_offset = 6, 54685fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 6 }, 5469ecc31b6eSAndy Yan .reg_offset = 0x400, 5470a33b790fSDamon Ding .axi_id = 1, 5471a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 5472a33b790fSDamon Ding .axi_uv_id = 0x0b, 5473b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 54745fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 54755fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54765fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54775fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54784c765862SDamon Ding .max_upscale_factor = 8, 54794c765862SDamon Ding .max_downscale_factor = 8, 5480ecc31b6eSAndy Yan }, 5481ecc31b6eSAndy Yan 5482ecc31b6eSAndy Yan { 5483ecc31b6eSAndy Yan .name = "Esmart3", 5484ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3, 5485ecc31b6eSAndy Yan .type = ESMART_LAYER, 5486ecc31b6eSAndy Yan .win_sel_port_offset = 7, 54875fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 7 }, 5488ecc31b6eSAndy Yan .reg_offset = 0x600, 5489a33b790fSDamon Ding .axi_id = 1, 5490a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 5491a33b790fSDamon Ding .axi_uv_id = 0x0d, 5492b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 54935fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 54945fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54955fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54965fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54974c765862SDamon Ding .max_upscale_factor = 8, 54984c765862SDamon Ding .max_downscale_factor = 8, 5499ecc31b6eSAndy Yan }, 5500ecc31b6eSAndy Yan }; 5501ecc31b6eSAndy Yan 550212ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = { 550312ee5af0SDamon Ding {0x00000000, "no error detected by DSC encoder"}, 550412ee5af0SDamon Ding {0x0030ffff, "bits per component error"}, 550512ee5af0SDamon Ding {0x0040ffff, "multiple mode error"}, 550612ee5af0SDamon Ding {0x0050ffff, "line buffer depth error"}, 550712ee5af0SDamon Ding {0x0060ffff, "minor version error"}, 550812ee5af0SDamon Ding {0x0070ffff, "picture height error"}, 550912ee5af0SDamon Ding {0x0080ffff, "picture width error"}, 551012ee5af0SDamon Ding {0x0090ffff, "number of slices error"}, 551112ee5af0SDamon Ding {0x00c0ffff, "slice height Error "}, 551212ee5af0SDamon Ding {0x00d0ffff, "slice width error"}, 551312ee5af0SDamon Ding {0x00e0ffff, "second line BPG offset error"}, 551412ee5af0SDamon Ding {0x00f0ffff, "non second line BPG offset error"}, 551512ee5af0SDamon Ding {0x0100ffff, "PPS ID error"}, 551612ee5af0SDamon Ding {0x0110ffff, "bits per pixel (BPP) Error"}, 551712ee5af0SDamon Ding {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */ 551812ee5af0SDamon Ding 551912ee5af0SDamon Ding {0x01510001, "slice 0 RC buffer model overflow error"}, 552012ee5af0SDamon Ding {0x01510002, "slice 1 RC buffer model overflow error"}, 552112ee5af0SDamon Ding {0x01510004, "slice 2 RC buffer model overflow error"}, 552212ee5af0SDamon Ding {0x01510008, "slice 3 RC buffer model overflow error"}, 552312ee5af0SDamon Ding {0x01510010, "slice 4 RC buffer model overflow error"}, 552412ee5af0SDamon Ding {0x01510020, "slice 5 RC buffer model overflow error"}, 552512ee5af0SDamon Ding {0x01510040, "slice 6 RC buffer model overflow error"}, 552612ee5af0SDamon Ding {0x01510080, "slice 7 RC buffer model overflow error"}, 552712ee5af0SDamon Ding 552812ee5af0SDamon Ding {0x01610001, "slice 0 RC buffer model underflow error"}, 552912ee5af0SDamon Ding {0x01610002, "slice 1 RC buffer model underflow error"}, 553012ee5af0SDamon Ding {0x01610004, "slice 2 RC buffer model underflow error"}, 553112ee5af0SDamon Ding {0x01610008, "slice 3 RC buffer model underflow error"}, 553212ee5af0SDamon Ding {0x01610010, "slice 4 RC buffer model underflow error"}, 553312ee5af0SDamon Ding {0x01610020, "slice 5 RC buffer model underflow error"}, 553412ee5af0SDamon Ding {0x01610040, "slice 6 RC buffer model underflow error"}, 553512ee5af0SDamon Ding {0x01610080, "slice 7 RC buffer model underflow error"}, 553612ee5af0SDamon Ding 553712ee5af0SDamon Ding {0xffffffff, "unsuccessful RESET cycle status"}, 553812ee5af0SDamon Ding {0x00a0ffff, "ICH full error precision settings error"}, 553912ee5af0SDamon Ding {0x0020ffff, "native mode"}, 554012ee5af0SDamon Ding }; 554112ee5af0SDamon Ding 554212ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = { 554312ee5af0SDamon Ding {0x00000000, "rate buffer status"}, 554412ee5af0SDamon Ding {0x00000001, "line buffer status"}, 554512ee5af0SDamon Ding {0x00000002, "decoder model status"}, 554612ee5af0SDamon Ding {0x00000003, "pixel buffer status"}, 554712ee5af0SDamon Ding {0x00000004, "balance fifo buffer status"}, 554812ee5af0SDamon Ding {0x00000005, "syntax element fifo status"}, 554912ee5af0SDamon Ding }; 555012ee5af0SDamon Ding 555112ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = { 555212ee5af0SDamon Ding { 555312ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_8K, 555412ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_8K, 555512ee5af0SDamon Ding .max_slice_num = 8, 555612ee5af0SDamon Ding .max_linebuf_depth = 11, 5557b61227a3SDamon Ding .min_bits_per_pixel = 8, 555812ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src", 555912ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_8k_txp_clk", 556012ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_8k_pxl_clk", 556112ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_8k_cds_clk", 556212ee5af0SDamon Ding }, 556312ee5af0SDamon Ding 556412ee5af0SDamon Ding { 556512ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_4K, 556612ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_4K, 556712ee5af0SDamon Ding .max_slice_num = 2, 556812ee5af0SDamon Ding .max_linebuf_depth = 11, 5569b61227a3SDamon Ding .min_bits_per_pixel = 8, 557012ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src", 557112ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_4k_txp_clk", 557212ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_4k_pxl_clk", 557312ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_4k_cds_clk", 557412ee5af0SDamon Ding }, 557512ee5af0SDamon Ding }; 557612ee5af0SDamon Ding 5577ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = { 5578ecc31b6eSAndy Yan { 5579ee01dbb2SDamon Ding .splice_vp_id = 1, 5580ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5581b890760eSAlgea Cao .pre_scan_max_dly = 54, 5582ecc31b6eSAndy Yan .max_dclk = 600000, 5583ecc31b6eSAndy Yan .max_output = {7680, 4320}, 5584ecc31b6eSAndy Yan }, 5585ecc31b6eSAndy Yan { 5586ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5587ee01dbb2SDamon Ding .pre_scan_max_dly = 54, 5588ecc31b6eSAndy Yan .max_dclk = 600000, 5589ecc31b6eSAndy Yan .max_output = {4096, 2304}, 5590ecc31b6eSAndy Yan }, 5591ecc31b6eSAndy Yan { 5592ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5593ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 5594ecc31b6eSAndy Yan .max_dclk = 600000, 5595ecc31b6eSAndy Yan .max_output = {4096, 2304}, 5596ecc31b6eSAndy Yan }, 5597ecc31b6eSAndy Yan { 5598ecc31b6eSAndy Yan .feature = 0, 5599ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 5600ecc31b6eSAndy Yan .max_dclk = 200000, 5601ecc31b6eSAndy Yan .max_output = {1920, 1080}, 5602ecc31b6eSAndy Yan }, 5603ecc31b6eSAndy Yan }; 5604ecc31b6eSAndy Yan 5605b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = { 5606b6ba80b4SDamon Ding { 5607b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER0, 5608b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0), 5609b6ba80b4SDamon Ding }, 5610b6ba80b4SDamon Ding { 5611b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER1, 5612b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1), 5613b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5614b6ba80b4SDamon Ding }, 5615b6ba80b4SDamon Ding { 5616b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER2, 5617b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2), 5618b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5619b6ba80b4SDamon Ding }, 5620b6ba80b4SDamon Ding { 5621b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER3, 5622b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3), 5623b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5624b6ba80b4SDamon Ding }, 5625b6ba80b4SDamon Ding { 5626b6ba80b4SDamon Ding .id = VOP2_PD_ESMART, 5627b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) | 5628b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | 5629b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART3), 5630b6ba80b4SDamon Ding }, 5631b6ba80b4SDamon Ding { 5632b6ba80b4SDamon Ding .id = VOP2_PD_DSC_8K, 5633b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K), 5634b6ba80b4SDamon Ding }, 5635b6ba80b4SDamon Ding { 5636b6ba80b4SDamon Ding .id = VOP2_PD_DSC_4K, 5637b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K), 5638b6ba80b4SDamon Ding }, 5639b6ba80b4SDamon Ding }; 5640b6ba80b4SDamon Ding 5641ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = { 5642ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588, 5643ecc31b6eSAndy Yan .nr_vps = 4, 5644ecc31b6eSAndy Yan .vp_data = rk3588_vp_data, 5645ecc31b6eSAndy Yan .win_data = rk3588_win_data, 5646ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0], 5647ecc31b6eSAndy Yan .plane_table = rk3588_plane_table, 5648b6ba80b4SDamon Ding .pd = rk3588_vop_pd_data, 564912ee5af0SDamon Ding .dsc = rk3588_dsc_data, 565012ee5af0SDamon Ding .dsc_error_ecw = dsc_ecw, 565112ee5af0SDamon Ding .dsc_error_buffer_flow = dsc_buffer_flow, 5652337d1c13SDamon Ding .vp_primary_plane_order = rk3588_vp_primary_plane_order, 5653ecc31b6eSAndy Yan .nr_layers = 8, 5654ecc31b6eSAndy Yan .nr_mixers = 7, 5655ecc31b6eSAndy Yan .nr_gammas = 4, 5656b6ba80b4SDamon Ding .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data), 565712ee5af0SDamon Ding .nr_dscs = 2, 565812ee5af0SDamon Ding .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw), 565912ee5af0SDamon Ding .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow), 566072388c26SDamon Ding .dump_regs = rk3588_dump_regs, 566172388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs), 5662ecc31b6eSAndy Yan }; 5663ecc31b6eSAndy Yan 5664d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 5665d0408543SAndy Yan .preinit = rockchip_vop2_preinit, 5666d0408543SAndy Yan .prepare = rockchip_vop2_prepare, 5667d0408543SAndy Yan .init = rockchip_vop2_init, 5668d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane, 5669d0408543SAndy Yan .enable = rockchip_vop2_enable, 5670d0408543SAndy Yan .disable = rockchip_vop2_disable, 5671b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts, 5672820a5c17SDamon Ding .check = rockchip_vop2_check, 567322007755SDamon Ding .mode_valid = rockchip_vop2_mode_valid, 56744c765862SDamon Ding .plane_check = rockchip_vop2_plane_check, 567572388c26SDamon Ding .regs_dump = rockchip_vop2_regs_dump, 567672388c26SDamon Ding .active_regs_dump = rockchip_vop2_active_regs_dump, 56778e7ef808SDamon Ding .apply_soft_te = rockchip_vop2_apply_soft_te, 5678d0408543SAndy Yan }; 5679