1d0408543SAndy Yan // SPDX-License-Identifier: GPL-2.0-only 2d0408543SAndy Yan /* 3d0408543SAndy Yan * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 4d0408543SAndy Yan * 5d0408543SAndy Yan */ 6d0408543SAndy Yan 7d0408543SAndy Yan #include <config.h> 8d0408543SAndy Yan #include <common.h> 9d0408543SAndy Yan #include <errno.h> 10d0408543SAndy Yan #include <malloc.h> 11d0408543SAndy Yan #include <fdtdec.h> 12d0408543SAndy Yan #include <fdt_support.h> 13b890760eSAlgea Cao #include <regmap.h> 14feffd38eSSandy Huang #include <asm/arch/cpu.h> 15d0408543SAndy Yan #include <asm/unaligned.h> 16d0408543SAndy Yan #include <asm/io.h> 17d0408543SAndy Yan #include <linux/list.h> 18ecc31b6eSAndy Yan #include <linux/log2.h> 19d0408543SAndy Yan #include <linux/media-bus-format.h> 20d0408543SAndy Yan #include <clk.h> 21d0408543SAndy Yan #include <asm/arch/clock.h> 22d0408543SAndy Yan #include <linux/err.h> 231147facaSSandy Huang #include <linux/ioport.h> 24d0408543SAndy Yan #include <dm/device.h> 25d0408543SAndy Yan #include <dm/read.h> 265fa6e665SDamon Ding #include <dm/ofnode.h> 27ac500a1fSSandy Huang #include <fixp-arith.h> 28d0408543SAndy Yan #include <syscon.h> 2960e469f5SDamon Ding #include <linux/iopoll.h> 305f1357a2SZhang Yubing #include <dm/uclass-internal.h> 31452afb13SDamon Ding #include <stdlib.h> 32d0408543SAndy Yan 33d0408543SAndy Yan #include "rockchip_display.h" 34d0408543SAndy Yan #include "rockchip_crtc.h" 35d0408543SAndy Yan #include "rockchip_connector.h" 366027c871SZhang Yubing #include "rockchip_post_csc.h" 37d0408543SAndy Yan 38d0408543SAndy Yan /* System registers definition */ 39d0408543SAndy Yan #define RK3568_REG_CFG_DONE 0x000 40d0408543SAndy Yan #define CFG_DONE_EN BIT(15) 41d0408543SAndy Yan 42d0408543SAndy Yan #define RK3568_VERSION_INFO 0x004 43d0408543SAndy Yan #define EN_MASK 1 44d0408543SAndy Yan 4563cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL 0x008 4663cb669fSSandy Huang 476414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL 0x024 486414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT 0 49aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT 16 506414e3bcSSandy Huang 51d0408543SAndy Yan #define RK3568_DSP_IF_EN 0x028 52d0408543SAndy Yan #define RGB_EN_SHIFT 0 53ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT 0 54ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT 1 55ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT 8 56d0408543SAndy Yan #define HDMI0_EN_SHIFT 1 57d0408543SAndy Yan #define EDP0_EN_SHIFT 3 58ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT 2 59ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT 3 60d0408543SAndy Yan #define MIPI0_EN_SHIFT 4 61ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT 4 62ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT 5 63ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT 6 64d0408543SAndy Yan #define MIPI1_EN_SHIFT 20 65ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT 7 66d0408543SAndy Yan #define LVDS0_EN_SHIFT 5 67d0408543SAndy Yan #define LVDS1_EN_SHIFT 24 68d0408543SAndy Yan #define BT1120_EN_SHIFT 6 69d0408543SAndy Yan #define BT656_EN_SHIFT 7 70d0408543SAndy Yan #define IF_MUX_MASK 3 71d0408543SAndy Yan #define RGB_MUX_SHIFT 8 72d0408543SAndy Yan #define HDMI0_MUX_SHIFT 10 73ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT 12 74ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT 14 75d0408543SAndy Yan #define EDP0_MUX_SHIFT 14 76ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT 16 77ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT 18 78d0408543SAndy Yan #define MIPI0_MUX_SHIFT 16 79ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT 20 80d0408543SAndy Yan #define MIPI1_MUX_SHIFT 21 8111f53190SSandy Huang #define LVDS0_MUX_SHIFT 18 82d0408543SAndy Yan #define LVDS1_MUX_SHIFT 25 83d0408543SAndy Yan 84d0408543SAndy Yan #define RK3568_DSP_IF_CTRL 0x02c 85d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT 0 86d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 87d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT 2 885fa6e665SDamon Ding #define BT656_UV_SWAP 4 895fa6e665SDamon Ding #define BT656_YC_SWAP 5 905fa6e665SDamon Ding #define BT656_DCLK_POL 6 910a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT 8 920a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT 8 930a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT 9 9441874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT 10 9541874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11 9641874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12 9741874944SGuochun Huang 98d0408543SAndy Yan #define RK3568_DSP_IF_POL 0x030 99d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_MASK 1 100d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT 28 101d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 102d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT 15 103d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 10410ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 10510ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT 4 106ecc31b6eSAndy Yan 107452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT 15 108452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT 12 109452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK 0x7 110452afb13SDamon Ding 111ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT 8 112ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT 12 113ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK 0x7 114ecc31b6eSAndy Yan 115d0408543SAndy Yan #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT 3 116452afb13SDamon Ding #define IF_CRTL_RGB_LVDS_PIN_POL_SHIFT 0 117ecc31b6eSAndy Yan 118ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT 16 119ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 120ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT 20 121ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 122ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT 24 123ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT 26 124ecc31b6eSAndy Yan 125feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN 0x50 126feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT 0 1271147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL 0x58 1281147facaSSandy Huang #define GAMMA_PORT_SEL_MASK 0x3 1291147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT 0 130db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK 0x3 131db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT 12 132ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT 16 1335fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK 0x3 1345fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT 26 1351147facaSSandy Huang 136ecc31b6eSAndy Yan #define RK3568_SYS_PD_CTRL 0x034 137d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG 0x70 138d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG 0x74 139d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG 0x78 140d0408543SAndy Yan #define RK3568_SYS0_INT_EN 0x80 141d0408543SAndy Yan #define RK3568_SYS0_INT_CLR 0x84 142d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS 0x88 143d0408543SAndy Yan #define RK3568_SYS1_INT_EN 0x90 144d0408543SAndy Yan #define RK3568_SYS1_INT_CLR 0x94 145d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS 0x98 146d0408543SAndy Yan #define RK3568_VP0_INT_EN 0xA0 147d0408543SAndy Yan #define RK3568_VP0_INT_CLR 0xA4 148d0408543SAndy Yan #define RK3568_VP0_INT_STATUS 0xA8 149d0408543SAndy Yan #define RK3568_VP1_INT_EN 0xB0 150d0408543SAndy Yan #define RK3568_VP1_INT_CLR 0xB4 151d0408543SAndy Yan #define RK3568_VP1_INT_STATUS 0xB8 152d0408543SAndy Yan #define RK3568_VP2_INT_EN 0xC0 153d0408543SAndy Yan #define RK3568_VP2_INT_CLR 0xC4 154d0408543SAndy Yan #define RK3568_VP2_INT_STATUS 0xC8 15560e469f5SDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT 0 15660e469f5SDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT 1 15760e469f5SDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT 2 15860e469f5SDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT 3 159b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT 5 160b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT 6 16160e469f5SDamon Ding #define RK3588_ESMART_PD_EN_SHIFT 7 16260e469f5SDamon Ding 163cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL 0x038 164cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT 20 165cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT 24 166cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT 28 167cd6c85a9SDamon Ding 16860e469f5SDamon Ding #define RK3568_SYS_STATUS0 0x60 16960e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8 17060e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9 17160e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10 17260e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11 173b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT 13 174b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT 14 17560e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT 15 176d0408543SAndy Yan 17766724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0 0x70 17866724b9cSDamon Ding #define LINE_FLAG_NUM_MASK 0x1fff 17966724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0 18066724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16 18166724b9cSDamon Ding 18212ee5af0SDamon Ding /* DSC CTRL registers definition */ 18312ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL 0x200 18412ee5af0SDamon Ding #define DSC_PORT_SEL_MASK 0x3 18512ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT 0 18612ee5af0SDamon Ding #define DSC_MAN_MODE_MASK 0x1 18712ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT 2 18812ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK 0x3 18912ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT 4 19012ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK 0x3 19112ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT 6 19212ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK 0x1 19312ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT 8 19412ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK 0x3 19512ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT 12 19612ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK 0x3 19712ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT 14 19812ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK 0x1 19912ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT 16 20012ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT 17 20112ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT 18 20212ee5af0SDamon Ding 20312ee5af0SDamon Ding #define RK3588_DSC_8K_RST 0x204 20412ee5af0SDamon Ding #define RST_DEASSERT_MASK 0x1 20512ee5af0SDamon Ding #define RST_DEASSERT_SHIFT 0 20612ee5af0SDamon Ding 20712ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE 0x208 20812ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT 0 20912ee5af0SDamon Ding 21012ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY 0x20C 21112ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK 0xffff 21212ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT 0 21312ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16 21412ee5af0SDamon Ding 21512ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END 0x210 21612ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK 0xffffffff 21712ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT 0 21812ee5af0SDamon Ding 21912ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END 0x214 22012ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK 0xffffffff 22112ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT 0 22212ee5af0SDamon Ding 22312ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END 0x218 22412ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK 0xffffffff 22512ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT 0 22612ee5af0SDamon Ding 22712ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END 0x21C 22812ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK 0xffffffff 22912ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT 0 23012ee5af0SDamon Ding 23112ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS 0x220 23212ee5af0SDamon Ding 23363cb669fSSandy Huang /* Overlay registers definition */ 2345fa6e665SDamon Ding #define RK3528_OVL_SYS 0x500 2355fa6e665SDamon Ding #define RK3528_OVL_SYS_PORT_SEL_IMD 0x504 2365fa6e665SDamon Ding #define RK3528_OVL_SYS_GATING_EN_IMD 0x508 2375fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL 0x510 2385fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL 0x520 239452afb13SDamon Ding #define ESMART_DLY_NUM_MASK 0xff 240452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT 0 2415fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL 0x524 2425fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL 0x528 2435fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C 2445fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530 2455fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 2465fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 2475fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c 2485fa6e665SDamon Ding 2495fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL 0x600 25063cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600 251ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK 0x1 252ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT 0 25363cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 2545fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL 0x604 25563cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604 25663cb669fSSandy Huang #define LAYER_SEL_MASK 0xf 25763cb669fSSandy Huang 25863cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608 25963cb669fSSandy Huang #define PORT_MUX_MASK 0xf 26063cb669fSSandy Huang #define PORT_MUX_SHIFT 0 26163cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3 26263cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16 26363cb669fSSandy Huang 26463cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 26563cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 26663cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 26763cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 2685fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620 2695fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624 2705fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628 2715fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C 2725fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630 2735fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634 2745fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638 2755fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C 2765fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640 2775fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644 2785fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648 2795fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C 28063cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 28163cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654 28263cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 28363cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 2845fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL 0x660 2855fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL 0x664 2865fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL 0x668 2875fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL 0x66C 2885fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670 28963cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 29063cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 29163cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 29263cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 29363cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0 29463cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff 29563cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24 29663cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4 29763cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8 29863cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0 29963cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8 30063cb669fSSandy Huang 3015fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL 0x700 3025fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL 0x704 3035fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720 3045fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724 3055fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728 3065fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C 3075fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730 3085fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734 3095fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738 3105fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C 3115fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740 3125fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744 3135fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748 3145fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C 3155fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770 3165fa6e665SDamon Ding 317d0408543SAndy Yan /* Video Port registers definition */ 318d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00 319d0408543SAndy Yan #define OUT_MODE_MASK 0xf 320d0408543SAndy Yan #define OUT_MODE_SHIFT 0 32110ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f 32210ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8 32365747de7SDamon Ding #define DSP_BG_SWAP 0x1 32465747de7SDamon Ding #define DSP_RB_SWAP 0x2 32565747de7SDamon Ding #define DSP_RG_SWAP 0x4 32665747de7SDamon Ding #define DSP_DELTA_SWAP 0x8 32710ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4 328d0408543SAndy Yan #define P2I_EN_SHIFT 5 3297a20be36SSandy Huang #define DSP_FILED_POL 6 330d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7 331c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT 13 33210ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15 333d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16 334d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17 335452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT 20 336db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT 22 3371147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28 3381147facaSSandy Huang 339d0408543SAndy Yan #define STANDBY_EN_SHIFT 31 340d0408543SAndy Yan 341d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04 34210ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4 34310ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3 344d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20 345d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21 34641874944SGuochun Huang #define EDPI_TE_EN 28 34741874944SGuochun Huang #define EDPI_WMS_HOLD_EN 30 34841874944SGuochun Huang #define EDPI_WMS_FS 31 34941874944SGuochun Huang 350d0408543SAndy Yan 351d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 3525fa6e665SDamon Ding 3535fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL 0xC0C 3545fa6e665SDamon Ding 3556414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10 3566414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0 3576414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2 3586414e3bcSSandy Huang 359ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C 360ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0 361ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2 362ecc31b6eSAndy Yan 3636414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20 3646414e3bcSSandy Huang 365d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C 366d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 367d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 368d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 369d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 370d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40 371d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 372d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 373d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 374d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 375d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54 376d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 377d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 378d0408543SAndy Yan 379ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60 380ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0 381ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1 382ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 383ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 384ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4 385ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1 386ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 387ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 388ac500a1fSSandy Huang 389ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64 390ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0 391ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF 392ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8 393ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF 394ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20 395ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF 396ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30 397ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3 398ac500a1fSSandy Huang 399ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68 400ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0 401ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF 402ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16 403ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF 404ac500a1fSSandy Huang 405ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C 406ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31 407ac500a1fSSandy Huang #define BCSH_EN_MASK 1 408ac500a1fSSandy Huang 4096027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL 0xCD0 4106027c871SZhang Yubing #define POST_CSC_COE00_MASK 0xFFFF 4116027c871SZhang Yubing #define POST_CSC_COE00_SHIFT 16 4126027c871SZhang Yubing #define POST_R2Y_MODE_MASK 0x7 4136027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT 8 4146027c871SZhang Yubing #define POST_CSC_MODE_MASK 0x7 4156027c871SZhang Yubing #define POST_CSC_MODE_SHIFT 3 4166027c871SZhang Yubing #define POST_R2Y_EN_MASK 0x1 4176027c871SZhang Yubing #define POST_R2Y_EN_SHIFT 2 4186027c871SZhang Yubing #define POST_CSC_EN_MASK 0x1 4196027c871SZhang Yubing #define POST_CSC_EN_SHIFT 1 4206027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK 0x1 4216027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT 0 4226027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02 0xCD4 4236027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11 0xCD8 4246027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20 0xCDC 4256027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22 0xCE0 4266027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0 0xCE4 4276027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1 0xCE8 4286027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2 0xCEC 4296027c871SZhang Yubing 430d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00 431d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04 432d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 433d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 434d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 435d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 436d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 437d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40 438d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34 439d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38 440d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 441d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 442d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 443d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 444d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54 445d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 446d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 447d0408543SAndy Yan 448d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00 449d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04 450d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 451d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 452d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 453d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 454d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 455d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40 456d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34 457d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38 458d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 459d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 460d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 461d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 462d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54 463d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 464d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 465d0408543SAndy Yan 466d0408543SAndy Yan /* Cluster0 register definition */ 467d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 468ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8 469ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9 470ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10 471d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 4725fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12 4735fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 4745fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 4755fa6e665SDamon Ding #define AVG2_MASK 0x1 4765fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT 18 4775fa6e665SDamon Ding #define AVG4_MASK 0x1 4785fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT 19 4795fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22 4805fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT 24 4815fa6e665SDamon Ding #define XGT_MODE_MASK 0x3 4825fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT 25 4835fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT 27 484ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28 485ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29 486a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008 487a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK 0x1f 488a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT 0 489a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK 0x1f 490a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT 5 491a33b790fSDamon Ding 492d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 493d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 494d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018 495d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 496d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 497d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 498d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 499d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 500d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 501d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 502d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 503d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 504d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 505d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 506d0408543SAndy Yan 507d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 508d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 509d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 510d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 511d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098 512d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 513d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 514d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 515d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 516d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 517d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 518d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 519d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 520d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 521d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 522d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 523d0408543SAndy Yan 524d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100 525ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0 526a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK 0x1 527a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT 13 528d0408543SAndy Yan 529d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 530d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 531d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 532d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 533d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218 534d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 535d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 536d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 537d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 538d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 539d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 540d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 541d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 542d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 543d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 544d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 545d0408543SAndy Yan 546d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 547d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 548d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 549d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 550d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298 551d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 552d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 553d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 554d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 555d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 556d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 557d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 558d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 559d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 560d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 561d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 562d0408543SAndy Yan 563d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300 564d0408543SAndy Yan 565d0408543SAndy Yan /* Esmart register definition */ 566d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800 56710ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1 56810ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2 56910ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3 5705fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT 12 5715fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK 0x3 572d0408543SAndy Yan 573d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804 574a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK 0x1f 575a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT 4 576a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK 0x1f 577a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT 12 578d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31 579a33b790fSDamon Ding 580a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL 0x1808 581a33b790fSDamon Ding #define ESMART_AXI_ID_MASK 0x1 582a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT 1 583a33b790fSDamon Ding 584d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810 585d0408543SAndy Yan #define WIN_EN_SHIFT 0 586d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f 587d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1 5885fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT 14 5895fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT 20 5905fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT 21 5915fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT 22 592d0408543SAndy Yan 593d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 594d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 595d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C 596d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 597d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 598d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 599d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 6003e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3 6013e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0 6023e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3 6033e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2 6043e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3 6053e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4 6063e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3 6073e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6 6083e39a5a1SSandy Huang 609d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 610d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 611d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 612d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840 6133e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1 6143e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8 6153e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1 6163e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9 6173e39a5a1SSandy Huang 618d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 619d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 620d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C 621d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 622d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 623d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 624d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 625d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 626d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 627d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 628d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870 629d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 630d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 631d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C 632d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 633d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 634d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 635d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 636d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 637d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 638d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 639d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0 640d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 641d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 642d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC 643d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 644d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 645d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 646d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 647d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 648d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 649d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 650d0408543SAndy Yan 651d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00 652d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04 653d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10 654d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 655d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 656d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C 657d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 658d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 659d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 660d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 661d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 662d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 663d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 664d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40 665d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 666d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 667d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C 668d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 669d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 670d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 671d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 672d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 673d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 674d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 675d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70 676d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 677d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 678d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C 679d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 680d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 681d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 682d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 683d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 684d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 685d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 686d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 687d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 688d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 689d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC 690d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 691d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 692d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 693d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 694d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 695d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 696d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 697d0408543SAndy Yan 698d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00 699d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04 700d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10 701d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 702d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 703d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C 704d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 705d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 706d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 707d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 708d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 709d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 710d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 711d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40 712d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 713d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 714d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C 715d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 716d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 717d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 718d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 719d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 720d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 721d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 722d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70 723d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 724d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 725d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C 726d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 727d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 728d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 729d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 730d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 731d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 732d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 733d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0 734d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 735d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 736d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC 737d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 738d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 739d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 740d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 741d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 742d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 743d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 744d0408543SAndy Yan 745d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00 746d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04 747d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10 748d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 749d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 750d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C 751d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 752d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 753d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 754d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 755d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 756d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 757d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 758d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40 759d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 760d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 761d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C 762d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 763d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 764d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 765d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 766d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 767d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 768d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 769d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70 770d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 771d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 772d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C 773d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 774d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 775d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 776d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 777d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 778d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 779d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 780d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0 781d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 782d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 783d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC 784d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 785d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 786d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 787d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 788d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 789d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 790d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 791d0408543SAndy Yan 79212ee5af0SDamon Ding /* DSC 8K/4K register definition */ 79312ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3 0x4000 79412ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0 0x40A0 79512ee5af0SDamon Ding #define DSC_EN_SHIFT 0 79612ee5af0SDamon Ding #define DSC_RBIT_SHIFT 2 79712ee5af0SDamon Ding #define DSC_RBYT_SHIFT 3 79812ee5af0SDamon Ding #define DSC_FLAL_SHIFT 4 79912ee5af0SDamon Ding #define DSC_MER_SHIFT 5 80012ee5af0SDamon Ding #define DSC_EPB_SHIFT 6 80112ee5af0SDamon Ding #define DSC_EPL_SHIFT 7 8021ace1b6dSDamon Ding #define DSC_NSLC_MASK 0x7 80312ee5af0SDamon Ding #define DSC_NSLC_SHIFT 16 80412ee5af0SDamon Ding #define DSC_SBO_SHIFT 28 80512ee5af0SDamon Ding #define DSC_IFEP_SHIFT 29 80612ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT 31 807baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \ 808baf2c414SDamon Ding (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \ 809baf2c414SDamon Ding (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT)) 81012ee5af0SDamon Ding 81112ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1 0x40A4 81212ee5af0SDamon Ding #define RK3588_DSC_8K_STS0 0x40A8 81312ee5af0SDamon Ding #define RK3588_DSC_8K_ERS 0x40C4 81412ee5af0SDamon Ding 81512ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3 0x4100 81612ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0 0x41A0 81712ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1 0x41A4 81812ee5af0SDamon Ding #define RK3588_DSC_4K_STS0 0x41A8 81912ee5af0SDamon Ding #define RK3588_DSC_4K_ERS 0x41C4 82012ee5af0SDamon Ding 8216027c871SZhang Yubing /* RK3528 ACM register definition */ 8226027c871SZhang Yubing #define RK3528_ACM_CTRL 0x6400 8236027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE 0x6404 8246027c871SZhang Yubing #define RK3528_ACM_FETCH_START 0x6408 8256027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE 0x6420 8266027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500 8276027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760 8286027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764 8296027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4 8306027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8 8316027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8 8326027c871SZhang Yubing 833d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0 834d0408543SAndy Yan 835452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON 0x10500 83652ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364 83752ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1 83852ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2 83952ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3 84052ee18acSSandy Huang 841ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008 842ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 843ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 844ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 845ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 846ecc31b6eSAndy Yan 847b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0 0x0000 848b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK 0x3 849b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT 5 850b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT 7 851b890760eSAlgea Cao 85260e469f5SDamon Ding #define RK3588_PMU_BISR_CON3 0x20C 85360e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 85460e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 85560e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 85660e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 857b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13 858b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14 85960e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 86060e469f5SDamon Ding 86160e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5 0x294 86260e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 86360e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 86460e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 86560e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 866b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13 867b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14 86860e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 86960e469f5SDamon Ding 870d0408543SAndy Yan #define VOP2_LAYER_MAX 8 87163cb669fSSandy Huang 872ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH 4096 873ee01dbb2SDamon Ding 87463cb669fSSandy Huang #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 875d0408543SAndy Yan 876631ee99aSZhang Yubing /* KHz */ 877631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE 600000 878631ee99aSZhang Yubing 879b6ba80b4SDamon Ding /* 880b6ba80b4SDamon Ding * vop2 dsc id 881b6ba80b4SDamon Ding */ 882b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K 0 883b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K 1 884b6ba80b4SDamon Ding 885b6ba80b4SDamon Ding /* 886b6ba80b4SDamon Ding * vop2 internal power domain id, 887b6ba80b4SDamon Ding * should be all none zero, 0 will be 888b6ba80b4SDamon Ding * treat as invalid; 889b6ba80b4SDamon Ding */ 890b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0 BIT(0) 891b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1 BIT(1) 892b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2 BIT(2) 893b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3 BIT(3) 894b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K BIT(5) 895b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K BIT(6) 896b6ba80b4SDamon Ding #define VOP2_PD_ESMART BIT(7) 897b6ba80b4SDamon Ding 8984c765862SDamon Ding #define VOP2_PLANE_NO_SCALING BIT(16) 8994c765862SDamon Ding 9005fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 9015fa6e665SDamon Ding #define VOP_FEATURE_AFBDC BIT(1) 9025fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE BIT(2) 9035fa6e665SDamon Ding #define VOP_FEATURE_HDR10 BIT(3) 9045fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR BIT(4) 9055fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */ 9065fa6e665SDamon Ding #define VOP_FEATURE_SPLICE BIT(5) 9075fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN BIT(6) 9086027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR BIT(7) 9096027c871SZhang Yubing #define VOP_FEATURE_POST_ACM BIT(8) 9106027c871SZhang Yubing #define VOP_FEATURE_POST_CSC BIT(9) 9115fa6e665SDamon Ding 9125fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR BIT(0) 9135fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR BIT(1) 9145fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY BIT(2) 9155fa6e665SDamon Ding #define WIN_FEATURE_AFBDC BIT(3) 9165fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN BIT(4) 9175fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB BIT(5) 9185fa6e665SDamon Ding /* a mirror win can only get fb address 9195fa6e665SDamon Ding * from source win: 9205fa6e665SDamon Ding * Cluster1---->Cluster0 9215fa6e665SDamon Ding * Esmart1 ---->Esmart0 9225fa6e665SDamon Ding * Smart1 ---->Smart0 9235fa6e665SDamon Ding * This is a feather on rk3566 9245fa6e665SDamon Ding */ 9255fa6e665SDamon Ding #define WIN_FEATURE_MIRROR BIT(6) 9265fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA BIT(7) 9275fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8) 9285fa6e665SDamon Ding 9295fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F 0xfe 9305fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F 0xff 9315fa6e665SDamon Ding 9325fa6e665SDamon Ding enum vop_csc_format { 93310ee9f5bSAlgea Cao CSC_BT601L, 93410ee9f5bSAlgea Cao CSC_BT709L, 93510ee9f5bSAlgea Cao CSC_BT601F, 93610ee9f5bSAlgea Cao CSC_BT2020, 9375fa6e665SDamon Ding CSC_BT709L_13BIT, 9385fa6e665SDamon Ding CSC_BT709F_13BIT, 9395fa6e665SDamon Ding CSC_BT2020L_13BIT, 9405fa6e665SDamon Ding CSC_BT2020F_13BIT, 9415fa6e665SDamon Ding }; 9425fa6e665SDamon Ding 9435fa6e665SDamon Ding enum vop_csc_bit_depth { 9445fa6e665SDamon Ding CSC_10BIT_DEPTH, 9455fa6e665SDamon Ding CSC_13BIT_DEPTH, 94610ee9f5bSAlgea Cao }; 94710ee9f5bSAlgea Cao 94810ee9f5bSAlgea Cao enum vop2_pol { 94910ee9f5bSAlgea Cao HSYNC_POSITIVE = 0, 95010ee9f5bSAlgea Cao VSYNC_POSITIVE = 1, 95110ee9f5bSAlgea Cao DEN_NEGATIVE = 2, 95210ee9f5bSAlgea Cao DCLK_INVERT = 3 95310ee9f5bSAlgea Cao }; 95410ee9f5bSAlgea Cao 955ac500a1fSSandy Huang enum vop2_bcsh_out_mode { 956ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK, 957ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE, 958ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR, 959ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, 960ac500a1fSSandy Huang }; 961ac500a1fSSandy Huang 962d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \ 963d0408543SAndy Yan { \ 964d0408543SAndy Yan .offset = off, \ 965d0408543SAndy Yan .mask = _mask, \ 966d0408543SAndy Yan .shift = _shift, \ 967d0408543SAndy Yan .write_mask = _write_mask, \ 968d0408543SAndy Yan } 969d0408543SAndy Yan 970d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \ 971d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false) 972d0408543SAndy Yan enum dither_down_mode { 973d0408543SAndy Yan RGB888_TO_RGB565 = 0x0, 974d0408543SAndy Yan RGB888_TO_RGB666 = 0x1 975d0408543SAndy Yan }; 976d0408543SAndy Yan 977d0408543SAndy Yan enum vop2_video_ports_id { 978d0408543SAndy Yan VOP2_VP0, 979d0408543SAndy Yan VOP2_VP1, 980d0408543SAndy Yan VOP2_VP2, 981d0408543SAndy Yan VOP2_VP3, 982d0408543SAndy Yan VOP2_VP_MAX, 983d0408543SAndy Yan }; 984d0408543SAndy Yan 985ee008497SSandy Huang enum vop2_layer_type { 986ee008497SSandy Huang CLUSTER_LAYER = 0, 987ee008497SSandy Huang ESMART_LAYER = 1, 988ee008497SSandy Huang SMART_LAYER = 2, 989ee008497SSandy Huang }; 990ee008497SSandy Huang 991b0989546SSandy Huang /* This define must same with kernel win phy id */ 992b0989546SSandy Huang enum vop2_layer_phy_id { 993b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0, 994b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, 995b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0, 996b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 997b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 998b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 999b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2, 1000b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3, 1001b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2, 1002b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3, 1003ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX, 1004d0408543SAndy Yan }; 1005d0408543SAndy Yan 10063e39a5a1SSandy Huang enum vop2_scale_up_mode { 10073e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR, 10083e39a5a1SSandy Huang VOP2_SCALE_UP_BIL, 10093e39a5a1SSandy Huang VOP2_SCALE_UP_BIC, 10103e39a5a1SSandy Huang }; 10113e39a5a1SSandy Huang 10123e39a5a1SSandy Huang enum vop2_scale_down_mode { 10133e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR, 10143e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL, 10153e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG, 10163e39a5a1SSandy Huang }; 10173e39a5a1SSandy Huang 10183e39a5a1SSandy Huang enum scale_mode { 10193e39a5a1SSandy Huang SCALE_NONE = 0x0, 10203e39a5a1SSandy Huang SCALE_UP = 0x1, 10213e39a5a1SSandy Huang SCALE_DOWN = 0x2 10223e39a5a1SSandy Huang }; 10233e39a5a1SSandy Huang 102412ee5af0SDamon Ding enum vop_dsc_interface_mode { 102512ee5af0SDamon Ding VOP_DSC_IF_DISABLE = 0, 102612ee5af0SDamon Ding VOP_DSC_IF_HDMI = 1, 102712ee5af0SDamon Ding VOP_DSC_IF_MIPI_DS_MODE = 2, 102812ee5af0SDamon Ding VOP_DSC_IF_MIPI_VIDEO_MODE = 3, 102912ee5af0SDamon Ding }; 103012ee5af0SDamon Ding 10315fa6e665SDamon Ding enum vop3_pre_scale_down_mode { 10325fa6e665SDamon Ding VOP3_PRE_SCALE_UNSPPORT, 10335fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_GT, 10345fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_AVG, 10355fa6e665SDamon Ding }; 10365fa6e665SDamon Ding 10375fa6e665SDamon Ding enum vop3_esmart_lb_mode { 10385fa6e665SDamon Ding VOP3_ESMART_8K_MODE, 10395fa6e665SDamon Ding VOP3_ESMART_4K_4K_MODE, 10405fa6e665SDamon Ding VOP3_ESMART_4K_2K_2K_MODE, 10415fa6e665SDamon Ding VOP3_ESMART_2K_2K_2K_2K_MODE, 10425fa6e665SDamon Ding }; 10435fa6e665SDamon Ding 10443e39a5a1SSandy Huang struct vop2_layer { 10453e39a5a1SSandy Huang u8 id; 10463e39a5a1SSandy Huang /** 10473e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected. 10483e39a5a1SSandy Huang * Every layer must make sure to select different 10493e39a5a1SSandy Huang * windows of others. 10503e39a5a1SSandy Huang */ 10513e39a5a1SSandy Huang u8 win_phys_id; 10523e39a5a1SSandy Huang }; 10533e39a5a1SSandy Huang 105460e469f5SDamon Ding struct vop2_power_domain_data { 1055b6ba80b4SDamon Ding u8 id; 1056b6ba80b4SDamon Ding u8 parent_id; 1057b6ba80b4SDamon Ding /* 1058b6ba80b4SDamon Ding * @module_id_mask: module id of which module this power domain is belongs to. 1059b6ba80b4SDamon Ding * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 1060b6ba80b4SDamon Ding */ 1061b6ba80b4SDamon Ding u32 module_id_mask; 106260e469f5SDamon Ding }; 106360e469f5SDamon Ding 1064b0989546SSandy Huang struct vop2_win_data { 1065b0989546SSandy Huang char *name; 106663cb669fSSandy Huang u8 phys_id; 1067ecc31b6eSAndy Yan enum vop2_layer_type type; 1068b0989546SSandy Huang u8 win_sel_port_offset; 10695fa6e665SDamon Ding u8 layer_sel_win_id[VOP2_VP_MAX]; 1070a33b790fSDamon Ding u8 axi_id; 1071a33b790fSDamon Ding u8 axi_uv_id; 1072a33b790fSDamon Ding u8 axi_yrgb_id; 1073ee01dbb2SDamon Ding u8 splice_win_id; 1074b6ba80b4SDamon Ding u8 pd_id; 10755fa6e665SDamon Ding u8 hsu_filter_mode; 10765fa6e665SDamon Ding u8 hsd_filter_mode; 10775fa6e665SDamon Ding u8 vsu_filter_mode; 10785fa6e665SDamon Ding u8 vsd_filter_mode; 10795fa6e665SDamon Ding u8 hsd_pre_filter_mode; 10805fa6e665SDamon Ding u8 vsd_pre_filter_mode; 10815fa6e665SDamon Ding u8 scale_engine_num; 1082b0989546SSandy Huang u32 reg_offset; 10834c765862SDamon Ding u32 max_upscale_factor; 10844c765862SDamon Ding u32 max_downscale_factor; 1085ee01dbb2SDamon Ding bool splice_mode_right; 108663cb669fSSandy Huang }; 108763cb669fSSandy Huang 108863cb669fSSandy Huang struct vop2_vp_data { 108963cb669fSSandy Huang u32 feature; 109063cb669fSSandy Huang u8 pre_scan_max_dly; 1091452afb13SDamon Ding u8 layer_mix_dly; 1092452afb13SDamon Ding u8 hdr_mix_dly; 1093452afb13SDamon Ding u8 win_dly; 1094ee01dbb2SDamon Ding u8 splice_vp_id; 109563cb669fSSandy Huang struct vop_rect max_output; 1096ecc31b6eSAndy Yan u32 max_dclk; 1097d0408543SAndy Yan }; 1098d0408543SAndy Yan 1099ee008497SSandy Huang struct vop2_plane_table { 1100ee008497SSandy Huang enum vop2_layer_phy_id plane_id; 1101ee008497SSandy Huang enum vop2_layer_type plane_type; 1102ee008497SSandy Huang }; 1103ee008497SSandy Huang 1104b0989546SSandy Huang struct vop2_vp_plane_mask { 1105b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */ 1106b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */ 1107b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 1108b0989546SSandy Huang u32 plane_mask; 1109ee008497SSandy Huang int cursor_plane_id; 1110b0989546SSandy Huang }; 1111b0989546SSandy Huang 111212ee5af0SDamon Ding struct vop2_dsc_data { 111312ee5af0SDamon Ding u8 id; 111412ee5af0SDamon Ding u8 pd_id; 111512ee5af0SDamon Ding u8 max_slice_num; 111612ee5af0SDamon Ding u8 max_linebuf_depth; /* used to generate the bitstream */ 111712ee5af0SDamon Ding u8 min_bits_per_pixel; /* bit num after encoder compress */ 111812ee5af0SDamon Ding const char *dsc_txp_clk_src_name; 111912ee5af0SDamon Ding const char *dsc_txp_clk_name; 112012ee5af0SDamon Ding const char *dsc_pxl_clk_name; 112112ee5af0SDamon Ding const char *dsc_cds_clk_name; 112212ee5af0SDamon Ding }; 112312ee5af0SDamon Ding 112412ee5af0SDamon Ding struct dsc_error_info { 112512ee5af0SDamon Ding u32 dsc_error_val; 112612ee5af0SDamon Ding char dsc_error_info[50]; 112712ee5af0SDamon Ding }; 112812ee5af0SDamon Ding 1129d0408543SAndy Yan struct vop2_data { 113052ee18acSSandy Huang u32 version; 11315fa6e665SDamon Ding u32 esmart_lb_mode; 113263cb669fSSandy Huang struct vop2_vp_data *vp_data; 1133b0989546SSandy Huang struct vop2_win_data *win_data; 1134b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 1135ee008497SSandy Huang struct vop2_plane_table *plane_table; 1136b6ba80b4SDamon Ding struct vop2_power_domain_data *pd; 113712ee5af0SDamon Ding struct vop2_dsc_data *dsc; 113812ee5af0SDamon Ding struct dsc_error_info *dsc_error_ecw; 113912ee5af0SDamon Ding struct dsc_error_info *dsc_error_buffer_flow; 1140337d1c13SDamon Ding u8 *vp_primary_plane_order; 114163cb669fSSandy Huang u8 nr_vps; 114263cb669fSSandy Huang u8 nr_layers; 114363cb669fSSandy Huang u8 nr_mixers; 11441147facaSSandy Huang u8 nr_gammas; 1145b6ba80b4SDamon Ding u8 nr_pd; 114612ee5af0SDamon Ding u8 nr_dscs; 114712ee5af0SDamon Ding u8 nr_dsc_ecw; 114812ee5af0SDamon Ding u8 nr_dsc_buffer_flow; 1149ecc31b6eSAndy Yan u32 reg_len; 1150d0408543SAndy Yan }; 1151d0408543SAndy Yan 1152d0408543SAndy Yan struct vop2 { 1153d0408543SAndy Yan u32 *regsbak; 1154d0408543SAndy Yan void *regs; 1155d0408543SAndy Yan void *grf; 1156ecc31b6eSAndy Yan void *vop_grf; 1157ecc31b6eSAndy Yan void *vo1_grf; 115860e469f5SDamon Ding void *sys_pmu; 115952ee18acSSandy Huang u32 reg_len; 116052ee18acSSandy Huang u32 version; 11615fa6e665SDamon Ding u32 esmart_lb_mode; 116263cb669fSSandy Huang bool global_init; 1163d0408543SAndy Yan const struct vop2_data *data; 1164b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 1165d0408543SAndy Yan }; 1166d0408543SAndy Yan 1167d0408543SAndy Yan static struct vop2 *rockchip_vop2; 11685fa6e665SDamon Ding 11695fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2) 11705fa6e665SDamon Ding { 11715fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) 11725fa6e665SDamon Ding return false; 11735fa6e665SDamon Ding else 11745fa6e665SDamon Ding return true; 11755fa6e665SDamon Ding } 11765fa6e665SDamon Ding 11773e39a5a1SSandy Huang /* 11783e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12; 11793e39a5a1SSandy Huang * avg_sd_factor: 11803e39a5a1SSandy Huang * bli_su_factor: 11813e39a5a1SSandy Huang * bic_su_factor: 11823e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16; 11833e39a5a1SSandy Huang * 11845fa6e665SDamon Ding * ygt2 enable: dst get one line from two line of the src 11855fa6e665SDamon Ding * ygt4 enable: dst get one line from four line of the src. 11863e39a5a1SSandy Huang * 11873e39a5a1SSandy Huang */ 11883e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 11893e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 11903e39a5a1SSandy Huang 11913e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 11923e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1)) 11933e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 11943e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1)) 11955fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \ 11965fa6e665SDamon Ding (fac * (dst - 1) >> 16 < (src - 1)) 11973e39a5a1SSandy Huang 11983e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode, 11993e39a5a1SSandy Huang int32_t filter_mode, 12003e39a5a1SSandy Huang uint32_t src, uint32_t dst) 12013e39a5a1SSandy Huang { 12023e39a5a1SSandy Huang uint32_t fac = 0; 12033e39a5a1SSandy Huang int i = 0; 12043e39a5a1SSandy Huang 12053e39a5a1SSandy Huang if (mode == SCALE_NONE) 12063e39a5a1SSandy Huang return 0; 12073e39a5a1SSandy Huang 12083e39a5a1SSandy Huang /* 12093e39a5a1SSandy Huang * A workaround to avoid zero div. 12103e39a5a1SSandy Huang */ 12113e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) { 12123e39a5a1SSandy Huang dst = dst + 1; 12133e39a5a1SSandy Huang src = src + 1; 12143e39a5a1SSandy Huang } 12153e39a5a1SSandy Huang 12163e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 12173e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst); 12183e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 12193e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 12203e39a5a1SSandy Huang break; 12213e39a5a1SSandy Huang fac -= 1; 12223e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12233e39a5a1SSandy Huang } 12243e39a5a1SSandy Huang } else { 12253e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst); 12263e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 12273e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 12283e39a5a1SSandy Huang break; 12293e39a5a1SSandy Huang fac -= 1; 12303e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12313e39a5a1SSandy Huang } 12323e39a5a1SSandy Huang } 12333e39a5a1SSandy Huang 12343e39a5a1SSandy Huang return fac; 12353e39a5a1SSandy Huang } 12363e39a5a1SSandy Huang 12375fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor) 12385fa6e665SDamon Ding { 12395fa6e665SDamon Ding if (is_hor) 12405fa6e665SDamon Ding return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac); 12415fa6e665SDamon Ding return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac); 12425fa6e665SDamon Ding } 12435fa6e665SDamon Ding 12445fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode, 12455fa6e665SDamon Ding uint32_t src, uint32_t dst, bool is_hor) 12465fa6e665SDamon Ding { 12475fa6e665SDamon Ding uint32_t fac = 0; 12485fa6e665SDamon Ding int i = 0; 12495fa6e665SDamon Ding 12505fa6e665SDamon Ding if (mode == SCALE_NONE) 12515fa6e665SDamon Ding return 0; 12525fa6e665SDamon Ding 12535fa6e665SDamon Ding /* 12545fa6e665SDamon Ding * A workaround to avoid zero div. 12555fa6e665SDamon Ding */ 12565fa6e665SDamon Ding if ((dst == 1) || (src == 1)) { 12575fa6e665SDamon Ding dst = dst + 1; 12585fa6e665SDamon Ding src = src + 1; 12595fa6e665SDamon Ding } 12605fa6e665SDamon Ding 12615fa6e665SDamon Ding if (mode == SCALE_DOWN) { 12625fa6e665SDamon Ding fac = VOP2_BILI_SCL_DN(src, dst); 12635fa6e665SDamon Ding for (i = 0; i < 100; i++) { 12645fa6e665SDamon Ding if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 12655fa6e665SDamon Ding break; 12665fa6e665SDamon Ding fac -= 1; 12675fa6e665SDamon Ding printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12685fa6e665SDamon Ding } 12695fa6e665SDamon Ding } else { 12705fa6e665SDamon Ding fac = VOP2_COMMON_SCL(src, dst); 12715fa6e665SDamon Ding for (i = 0; i < 100; i++) { 12725fa6e665SDamon Ding if (vop3_scale_up_fac_check(src, dst, fac, is_hor)) 12735fa6e665SDamon Ding break; 12745fa6e665SDamon Ding fac -= 1; 12755fa6e665SDamon Ding printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12765fa6e665SDamon Ding } 12775fa6e665SDamon Ding } 12785fa6e665SDamon Ding 12795fa6e665SDamon Ding return fac; 12805fa6e665SDamon Ding } 12815fa6e665SDamon Ding 12823e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst) 12833e39a5a1SSandy Huang { 12843e39a5a1SSandy Huang if (src < dst) 12853e39a5a1SSandy Huang return SCALE_UP; 12863e39a5a1SSandy Huang else if (src > dst) 12873e39a5a1SSandy Huang return SCALE_DOWN; 12883e39a5a1SSandy Huang 12893e39a5a1SSandy Huang return SCALE_NONE; 12903e39a5a1SSandy Huang } 1291d0408543SAndy Yan 1292ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x) 1293ac500a1fSSandy Huang { 1294ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 1295ac500a1fSSandy Huang } 1296ac500a1fSSandy Huang 1297b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 1298b0989546SSandy Huang { 1299b0989546SSandy Huang int i = 0; 1300ecc31b6eSAndy Yan 1301337d1c13SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 1302337d1c13SDamon Ding if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i])) 1303337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[i]; 1304ecc31b6eSAndy Yan } 1305b0989546SSandy Huang 1306337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[0]; 1307b0989546SSandy Huang } 1308b0989546SSandy Huang 130963cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift) 1310d0408543SAndy Yan { 1311d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 1312d0408543SAndy Yan } 1313d0408543SAndy Yan 131463cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst) 1315d0408543SAndy Yan { 1316d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1); 1317d0408543SAndy Yan } 1318d0408543SAndy Yan 131952ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 1320d0408543SAndy Yan { 1321d0408543SAndy Yan writel(v, vop2->regs + offset); 1322d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1323d0408543SAndy Yan } 1324d0408543SAndy Yan 132552ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 1326d0408543SAndy Yan { 1327d0408543SAndy Yan return readl(vop2->regs + offset); 1328d0408543SAndy Yan } 1329d0408543SAndy Yan 133052ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 133152ee18acSSandy Huang u32 mask, u32 shift, u32 v, 1332d0408543SAndy Yan bool write_mask) 1333d0408543SAndy Yan { 1334d0408543SAndy Yan if (!mask) 1335d0408543SAndy Yan return; 1336d0408543SAndy Yan 1337d0408543SAndy Yan if (write_mask) { 1338d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16)); 1339d0408543SAndy Yan } else { 134052ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2]; 1341d0408543SAndy Yan 1342d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 1343d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1344d0408543SAndy Yan } 1345d0408543SAndy Yan 1346d0408543SAndy Yan writel(v, vop2->regs + offset); 1347d0408543SAndy Yan } 1348d0408543SAndy Yan 1349ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 135052ee18acSSandy Huang u32 mask, u32 shift, u32 v) 135152ee18acSSandy Huang { 135252ee18acSSandy Huang u32 val = 0; 135352ee18acSSandy Huang 135452ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16)); 1355ecc31b6eSAndy Yan writel(val, grf_base + offset); 135652ee18acSSandy Huang } 135752ee18acSSandy Huang 135860e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 135960e469f5SDamon Ding u32 mask, u32 shift) 136060e469f5SDamon Ding { 136160e469f5SDamon Ding return (readl(grf_base + offset) >> shift) & mask; 136260e469f5SDamon Ding } 136360e469f5SDamon Ding 13648895aec1SSandy Huang static char* get_output_if_name(u32 output_if, char *name) 13658895aec1SSandy Huang { 13668895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_RGB) 13678895aec1SSandy Huang strcat(name, " RGB"); 13688895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT1120) 13698895aec1SSandy Huang strcat(name, " BT1120"); 13708895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT656) 13718895aec1SSandy Huang strcat(name, " BT656"); 13728895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS0) 13738895aec1SSandy Huang strcat(name, " LVDS0"); 13748895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS1) 13758895aec1SSandy Huang strcat(name, " LVDS1"); 13768895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI0) 13778895aec1SSandy Huang strcat(name, " MIPI0"); 13788895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI1) 13798895aec1SSandy Huang strcat(name, " MIPI1"); 13808895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP0) 13818895aec1SSandy Huang strcat(name, " eDP0"); 13828895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP1) 13838895aec1SSandy Huang strcat(name, " eDP1"); 13848895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP0) 13858895aec1SSandy Huang strcat(name, " DP0"); 13868895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP1) 13878895aec1SSandy Huang strcat(name, " DP1"); 13888895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI0) 13898895aec1SSandy Huang strcat(name, " HDMI0"); 13908895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI1) 13918895aec1SSandy Huang strcat(name, " HDMI1"); 13928895aec1SSandy Huang 13938895aec1SSandy Huang return name; 13948895aec1SSandy Huang } 13958895aec1SSandy Huang 13968895aec1SSandy Huang static char *get_plane_name(int plane_id, char *name) 13978895aec1SSandy Huang { 13988895aec1SSandy Huang switch (plane_id) { 13998895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER0: 14008895aec1SSandy Huang strcat(name, "Cluster0"); 14018895aec1SSandy Huang break; 14028895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER1: 14038895aec1SSandy Huang strcat(name, "Cluster1"); 14048895aec1SSandy Huang break; 14058895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART0: 14068895aec1SSandy Huang strcat(name, "Esmart0"); 14078895aec1SSandy Huang break; 14088895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART1: 14098895aec1SSandy Huang strcat(name, "Esmart1"); 14108895aec1SSandy Huang break; 14118895aec1SSandy Huang case ROCKCHIP_VOP2_SMART0: 14128895aec1SSandy Huang strcat(name, "Smart0"); 14138895aec1SSandy Huang break; 14148895aec1SSandy Huang case ROCKCHIP_VOP2_SMART1: 14158895aec1SSandy Huang strcat(name, "Smart1"); 14168895aec1SSandy Huang break; 14178895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER2: 14188895aec1SSandy Huang strcat(name, "Cluster2"); 14198895aec1SSandy Huang break; 14208895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER3: 14218895aec1SSandy Huang strcat(name, "Cluster3"); 14228895aec1SSandy Huang break; 14238895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART2: 14248895aec1SSandy Huang strcat(name, "Esmart2"); 14258895aec1SSandy Huang break; 14268895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART3: 14278895aec1SSandy Huang strcat(name, "Esmart3"); 14288895aec1SSandy Huang break; 14298895aec1SSandy Huang } 14308895aec1SSandy Huang 14318895aec1SSandy Huang return name; 14328895aec1SSandy Huang } 14338895aec1SSandy Huang 143452ee18acSSandy Huang static bool is_yuv_output(u32 bus_format) 1435d0408543SAndy Yan { 1436d0408543SAndy Yan switch (bus_format) { 1437d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 1438d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 1439d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1440d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1441a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 1442a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 1443a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8: 1444a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8: 1445a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 1446a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 1447a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16: 1448a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16: 1449d0408543SAndy Yan return true; 1450d0408543SAndy Yan default: 1451d0408543SAndy Yan return false; 1452d0408543SAndy Yan } 1453d0408543SAndy Yan } 1454d0408543SAndy Yan 14555fa6e665SDamon Ding static int vop2_convert_csc_mode(int csc_mode, int bit_depth) 145610ee9f5bSAlgea Cao { 145710ee9f5bSAlgea Cao switch (csc_mode) { 145810ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE170M: 145910ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_M: 146010ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_BG: 146110ee9f5bSAlgea Cao return CSC_BT601L; 146210ee9f5bSAlgea Cao case V4L2_COLORSPACE_REC709: 146310ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE240M: 146410ee9f5bSAlgea Cao case V4L2_COLORSPACE_DEFAULT: 14655fa6e665SDamon Ding if (bit_depth == CSC_13BIT_DEPTH) 14665fa6e665SDamon Ding return CSC_BT709L_13BIT; 14675fa6e665SDamon Ding else 146810ee9f5bSAlgea Cao return CSC_BT709L; 146910ee9f5bSAlgea Cao case V4L2_COLORSPACE_JPEG: 147010ee9f5bSAlgea Cao return CSC_BT601F; 147110ee9f5bSAlgea Cao case V4L2_COLORSPACE_BT2020: 14725fa6e665SDamon Ding if (bit_depth == CSC_13BIT_DEPTH) 14735fa6e665SDamon Ding return CSC_BT2020L_13BIT; 14745fa6e665SDamon Ding else 147510ee9f5bSAlgea Cao return CSC_BT2020; 14765fa6e665SDamon Ding case V4L2_COLORSPACE_BT709F: 14775fa6e665SDamon Ding if (bit_depth == CSC_10BIT_DEPTH) { 14785fa6e665SDamon Ding printf("WARN: Unsupported bt709f at 10bit csc depth, use bt601f instead\n"); 14795fa6e665SDamon Ding return CSC_BT601F; 14805fa6e665SDamon Ding } else { 14815fa6e665SDamon Ding return CSC_BT709F_13BIT; 14825fa6e665SDamon Ding } 14835fa6e665SDamon Ding case V4L2_COLORSPACE_BT2020F: 14845fa6e665SDamon Ding if (bit_depth == CSC_10BIT_DEPTH) { 14855fa6e665SDamon Ding printf("WARN: Unsupported bt2020f at 10bit csc depth, use bt601f instead\n"); 14865fa6e665SDamon Ding return CSC_BT601F; 14875fa6e665SDamon Ding } else { 14885fa6e665SDamon Ding return CSC_BT2020F_13BIT; 14895fa6e665SDamon Ding } 149010ee9f5bSAlgea Cao default: 149110ee9f5bSAlgea Cao return CSC_BT709L; 149210ee9f5bSAlgea Cao } 149310ee9f5bSAlgea Cao } 149410ee9f5bSAlgea Cao 1495b0989546SSandy Huang static bool is_uv_swap(u32 bus_format, u32 output_mode) 1496d0408543SAndy Yan { 1497d0408543SAndy Yan /* 1498d0408543SAndy Yan * FIXME: 1499d0408543SAndy Yan * 1500d0408543SAndy Yan * There is no media type for YUV444 output, 1501d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on 1502d0408543SAndy Yan * yuv format. 1503d0408543SAndy Yan * 1504d0408543SAndy Yan * From H/W testing, YUV444 mode need a rb swap. 1505d0408543SAndy Yan */ 15063e59c137SSandy Huang if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || 15073e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || 15083e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || 15093e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || 15103e59c137SSandy Huang ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1511d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1512d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA || 15133e59c137SSandy Huang output_mode == ROCKCHIP_OUT_MODE_P888))) 1514d0408543SAndy Yan return true; 1515d0408543SAndy Yan else 1516d0408543SAndy Yan return false; 1517d0408543SAndy Yan } 1518d0408543SAndy Yan 1519b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type) 152063cb669fSSandy Huang { 1521b0989546SSandy Huang switch (output_type) { 1522b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA: 1523b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB: 1524b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV: 1525b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort: 1526b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA: 1527b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown: 1528b0989546SSandy Huang return true; 1529b0989546SSandy Huang default: 1530b0989546SSandy Huang return false; 153163cb669fSSandy Huang } 153263cb669fSSandy Huang } 153363cb669fSSandy Huang 1534ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1535ecc31b6eSAndy Yan { 1536ecc31b6eSAndy Yan int i = 0; 1537ecc31b6eSAndy Yan 1538ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) { 1539ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id) 1540ecc31b6eSAndy Yan return &vop2->data->win_data[i]; 1541ecc31b6eSAndy Yan } 1542ecc31b6eSAndy Yan 1543ecc31b6eSAndy Yan return NULL; 1544ecc31b6eSAndy Yan } 1545ecc31b6eSAndy Yan 1546b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id) 1547b6ba80b4SDamon Ding { 1548b6ba80b4SDamon Ding int i = 0; 1549b6ba80b4SDamon Ding 1550b6ba80b4SDamon Ding for (i = 0; i < vop2->data->nr_pd; i++) { 1551b6ba80b4SDamon Ding if (vop2->data->pd[i].id == pd_id) 1552b6ba80b4SDamon Ding return &vop2->data->pd[i]; 1553b6ba80b4SDamon Ding } 1554b6ba80b4SDamon Ding 1555b6ba80b4SDamon Ding return NULL; 1556b6ba80b4SDamon Ding } 1557b6ba80b4SDamon Ding 1558db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1559db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1560db328a0dSDamon Ding { 1561db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1562db328a0dSDamon Ding int i; 1563db328a0dSDamon Ding 1564db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1565db328a0dSDamon Ding GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 1566db328a0dSDamon Ding crtc_id, false); 1567db328a0dSDamon Ding 1568db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1569db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1570db328a0dSDamon Ding 1571db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1572db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1573db328a0dSDamon Ding } 1574db328a0dSDamon Ding 1575db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1576db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1577db328a0dSDamon Ding { 1578db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1579db328a0dSDamon Ding int i; 1580db328a0dSDamon Ding 1581db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1582db328a0dSDamon Ding GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT, 1583db328a0dSDamon Ding crtc_id, false); 1584db328a0dSDamon Ding 1585db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1586db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1587db328a0dSDamon Ding 1588db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1589db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1590db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1591db328a0dSDamon Ding EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false); 1592db328a0dSDamon Ding } 1593db328a0dSDamon Ding 15941147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1595d0408543SAndy Yan struct display_state *state) 1596d0408543SAndy Yan { 15971147facaSSandy Huang struct connector_state *conn_state = &state->conn_state; 15981147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state; 15991147facaSSandy Huang struct resource gamma_res; 16001147facaSSandy Huang fdt_size_t lut_size; 16011147facaSSandy Huang int i, lut_len, ret = 0; 16021147facaSSandy Huang u32 *lut_regs; 16031147facaSSandy Huang u32 *lut_val; 16041147facaSSandy Huang u32 r, g, b; 16051147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 16061147facaSSandy Huang static int gamma_lut_en_num = 1; 16071147facaSSandy Huang 16081147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) { 16091147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 16101147facaSSandy Huang return 0; 16111147facaSSandy Huang } 16121147facaSSandy Huang 16131147facaSSandy Huang if (!disp_info) 16141147facaSSandy Huang return 0; 16151147facaSSandy Huang 16161147facaSSandy Huang if (!disp_info->gamma_lut_data.size) 16171147facaSSandy Huang return 0; 16181147facaSSandy Huang 16191147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 16201147facaSSandy Huang if (ret) 16211147facaSSandy Huang printf("failed to get gamma lut res\n"); 16221147facaSSandy Huang lut_regs = (u32 *)gamma_res.start; 16231147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1; 16241147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 16251147facaSSandy Huang printf("failed to get gamma lut register\n"); 16261147facaSSandy Huang return 0; 16271147facaSSandy Huang } 16281147facaSSandy Huang lut_len = lut_size / 4; 16291147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) { 16301147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 16311147facaSSandy Huang return 0; 16321147facaSSandy Huang } 16331147facaSSandy Huang lut_val = (u32 *)calloc(1, lut_size); 16341147facaSSandy Huang for (i = 0; i < lut_len; i++) { 16351147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 16361147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 16371147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 16381147facaSSandy Huang 16391147facaSSandy Huang lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 16401147facaSSandy Huang } 16411147facaSSandy Huang 1642db328a0dSDamon Ding if (vop2->version == VOP_VERSION_RK3568) { 1643db328a0dSDamon Ding rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len); 16441147facaSSandy Huang gamma_lut_en_num++; 1645db328a0dSDamon Ding } else if (vop2->version == VOP_VERSION_RK3588) { 1646db328a0dSDamon Ding rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len); 1647db328a0dSDamon Ding if (cstate->splice_mode) { 1648db328a0dSDamon Ding rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, lut_val, lut_len); 1649db328a0dSDamon Ding gamma_lut_en_num++; 1650db328a0dSDamon Ding } 1651db328a0dSDamon Ding gamma_lut_en_num++; 1652db328a0dSDamon Ding } 16531147facaSSandy Huang 1654d0408543SAndy Yan return 0; 1655d0408543SAndy Yan } 1656d0408543SAndy Yan 16576414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 16586414e3bcSSandy Huang struct display_state *state) 16596414e3bcSSandy Huang { 16606414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state; 16616414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state; 16626414e3bcSSandy Huang int i, cubic_lut_len; 16636414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 16646414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 16656414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 16666414e3bcSSandy Huang u32 *cubic_lut_addr; 16676414e3bcSSandy Huang 16686414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 16696414e3bcSSandy Huang return 0; 16706414e3bcSSandy Huang 16716414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size) 16726414e3bcSSandy Huang return 0; 16736414e3bcSSandy Huang 16746414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 16756414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size; 16766414e3bcSSandy Huang 16776414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) { 16786414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 16796414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 16806414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 16816414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 16826414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) + 16836414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 16846414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28); 16856414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 16866414e3bcSSandy Huang *cubic_lut_addr++ = 0; 16876414e3bcSSandy Huang } 16886414e3bcSSandy Huang 16896414e3bcSSandy Huang if (cubic_lut_len % 2) { 16906414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 16916414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 16926414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 16936414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 16946414e3bcSSandy Huang *cubic_lut_addr++ = 0; 16956414e3bcSSandy Huang *cubic_lut_addr = 0; 16966414e3bcSSandy Huang } 16976414e3bcSSandy Huang 16986414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 16996414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id)); 17006414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 17016414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 17026414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 17036414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 17046414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 17056414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 17066414e3bcSSandy Huang 17076414e3bcSSandy Huang return 0; 17086414e3bcSSandy Huang } 17096414e3bcSSandy Huang 1710ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2, 1711ee01dbb2SDamon Ding struct bcsh_state *bcsh_state, int crtc_id) 1712ee01dbb2SDamon Ding { 1713ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1714ee01dbb2SDamon Ding u32 vp_offset = crtc_id * 0x100; 1715ee01dbb2SDamon Ding 1716ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 1717ee01dbb2SDamon Ding BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false); 1718ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 1719ee01dbb2SDamon Ding BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false); 1720ee01dbb2SDamon Ding 1721ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 1722ee01dbb2SDamon Ding BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1723ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 1724ee01dbb2SDamon Ding BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1725ee01dbb2SDamon Ding 1726ee01dbb2SDamon Ding if (!cstate->bcsh_en) { 1727ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1728ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 1729ee01dbb2SDamon Ding return; 1730ee01dbb2SDamon Ding } 1731ee01dbb2SDamon Ding 1732ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1733ee01dbb2SDamon Ding BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 1734ee01dbb2SDamon Ding bcsh_state->brightness, false); 1735ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1736ee01dbb2SDamon Ding BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false); 1737ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1738ee01dbb2SDamon Ding BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 1739ee01dbb2SDamon Ding bcsh_state->saturation * bcsh_state->contrast / 0x100, false); 1740ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1741ee01dbb2SDamon Ding BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false); 1742ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1743ee01dbb2SDamon Ding BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false); 1744ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1745ee01dbb2SDamon Ding BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 1746ee01dbb2SDamon Ding BCSH_OUT_MODE_NORMAL_VIDEO, false); 1747ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1748ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 1749ee01dbb2SDamon Ding } 1750ee01dbb2SDamon Ding 1751ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 1752ac500a1fSSandy Huang { 1753ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state; 1754ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info; 1755ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state; 1756ee01dbb2SDamon Ding struct bcsh_state bcsh_state; 1757ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue; 1758ac500a1fSSandy Huang 1759ac500a1fSSandy Huang if (!conn_state->disp_info) 1760ac500a1fSSandy Huang return; 1761ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info; 1762ac500a1fSSandy Huang if (!bcsh_info) 1763ac500a1fSSandy Huang return; 1764ac500a1fSSandy Huang 1765ac500a1fSSandy Huang if (bcsh_info->brightness != 50 || 1766ac500a1fSSandy Huang bcsh_info->contrast != 50 || 1767ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50) 1768ee01dbb2SDamon Ding cstate->bcsh_en = true; 1769ac500a1fSSandy Huang 1770ee01dbb2SDamon Ding if (cstate->bcsh_en) { 1771ac500a1fSSandy Huang if (!cstate->yuv_overlay) 1772ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1773ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format)) 1774ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1775ac500a1fSSandy Huang } else { 1776ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 1777ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1778ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 1779ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1780ac500a1fSSandy Huang } 1781ac500a1fSSandy Huang 17825fa6e665SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 1783ac500a1fSSandy Huang 1784ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 1785ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127, 1786ac500a1fSSandy Huang bcsh_info->brightness); 1787ac500a1fSSandy Huang else 1788ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31, 1789ac500a1fSSandy Huang bcsh_info->brightness); 1790ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 1791ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 1792ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 1793ac500a1fSSandy Huang 1794ac500a1fSSandy Huang 1795ac500a1fSSandy Huang /* 1796ac500a1fSSandy Huang * a:[-30~0): 1797ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256; 1798ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1799ac500a1fSSandy Huang * a:[0~30] 1800ac500a1fSSandy Huang * sin_hue = sin(a)*256; 1801ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1802ac500a1fSSandy Huang */ 1803ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23; 1804ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23; 1805ac500a1fSSandy Huang 1806ee01dbb2SDamon Ding bcsh_state.brightness = brightness; 1807ee01dbb2SDamon Ding bcsh_state.contrast = contrast; 1808ee01dbb2SDamon Ding bcsh_state.saturation = saturation; 1809ee01dbb2SDamon Ding bcsh_state.sin_hue = sin_hue; 1810ee01dbb2SDamon Ding bcsh_state.cos_hue = cos_hue; 1811ee01dbb2SDamon Ding 1812ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id); 1813ee01dbb2SDamon Ding if (cstate->splice_mode) 1814ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id); 1815ee01dbb2SDamon Ding } 1816ee01dbb2SDamon Ding 1817ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id) 1818ee01dbb2SDamon Ding { 1819ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 1820ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 1821ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1822ee01dbb2SDamon Ding u32 bg_ovl_dly, bg_dly, pre_scan_dly; 1823ee01dbb2SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 1824ee01dbb2SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1825ee01dbb2SDamon Ding 1826ee01dbb2SDamon Ding bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly; 1827ee01dbb2SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly; 1828ee01dbb2SDamon Ding bg_dly -= bg_ovl_dly; 1829ee01dbb2SDamon Ding 1830ee01dbb2SDamon Ding if (cstate->splice_mode) 1831ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 2) - 1; 1832ee01dbb2SDamon Ding else 1833ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1834ee01dbb2SDamon Ding 1835ee01dbb2SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 1836ee01dbb2SDamon Ding hsync_len = 8; 1837ee01dbb2SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1838ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4, 1839ee01dbb2SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1840ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 1841ac500a1fSSandy Huang } 1842ac500a1fSSandy Huang 1843452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id) 1844452afb13SDamon Ding { 1845452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 1846452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 1847452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1848452afb13SDamon Ding struct vop2_win_data *win_data; 1849452afb13SDamon Ding u32 bg_dly, pre_scan_dly; 1850452afb13SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 1851452afb13SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1852452afb13SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 1853452afb13SDamon Ding u8 win_id; 1854452afb13SDamon Ding 1855452afb13SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 1856452afb13SDamon Ding win_id = atoi(&win_data->name[strlen(win_data->name) - 1]); 1857452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL + win_id * 4, 1858452afb13SDamon Ding ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 0, false); 1859452afb13SDamon Ding 1860452afb13SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].win_dly + 1861452afb13SDamon Ding vop2->data->vp_data[crtc_id].layer_mix_dly + 1862452afb13SDamon Ding vop2->data->vp_data[crtc_id].hdr_mix_dly; 1863452afb13SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1864452afb13SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1865452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100, 1866452afb13SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1867452afb13SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 1868452afb13SDamon Ding } 1869452afb13SDamon Ding 1870d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 1871d0408543SAndy Yan { 1872d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 1873d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 187452ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state; 187552ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 1876d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal; 1877d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 1878d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 1879d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay; 1880d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay; 1881d0408543SAndy Yan u16 hsize = 1882d0408543SAndy Yan hdisplay * (conn_state->overscan.left_margin + 1883d0408543SAndy Yan conn_state->overscan.right_margin) / 200; 1884d0408543SAndy Yan u16 vsize = 1885d0408543SAndy Yan vdisplay * (conn_state->overscan.top_margin + 1886d0408543SAndy Yan conn_state->overscan.bottom_margin) / 200; 1887d0408543SAndy Yan u16 hact_end, vact_end; 1888d0408543SAndy Yan u32 val; 1889d0408543SAndy Yan 189074bd8269SSandy Huang hsize = round_down(hsize, 2); 1891d0408543SAndy Yan vsize = round_down(vsize, 2); 1892d0408543SAndy Yan 1893d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 1894d0408543SAndy Yan hact_end = hact_st + hsize; 1895d0408543SAndy Yan val = hact_st << 16; 1896d0408543SAndy Yan val |= hact_end; 1897d0408543SAndy Yan 189852ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 1899d0408543SAndy Yan vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 1900d0408543SAndy Yan vact_end = vact_st + vsize; 1901d0408543SAndy Yan val = vact_st << 16; 1902d0408543SAndy Yan val |= vact_end; 190352ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 1904d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16; 1905d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize); 190652ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 1907d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 1908d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 190952ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 1910d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 1911d0408543SAndy Yan POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 1912d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1913d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 1914d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize; 1915d0408543SAndy Yan 1916d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 191752ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 1918d0408543SAndy Yan } 1919d0408543SAndy Yan 1920452afb13SDamon Ding if (is_vop3(vop2)) { 1921452afb13SDamon Ding vop3_setup_pipe_dly(state, vop2, cstate->crtc_id); 1922452afb13SDamon Ding } else { 1923ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id); 1924ee01dbb2SDamon Ding if (cstate->splice_mode) 1925ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id); 1926d0408543SAndy Yan } 1927452afb13SDamon Ding } 1928d0408543SAndy Yan 19296027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2) 19306027c871SZhang Yubing { 19316027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 19326027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 19336027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 19346027c871SZhang Yubing struct drm_display_mode *mode = &conn_state->mode; 19356027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 19366027c871SZhang Yubing s16 *lut_y; 19376027c871SZhang Yubing s16 *lut_h; 19386027c871SZhang Yubing s16 *lut_s; 19396027c871SZhang Yubing u32 value; 19406027c871SZhang Yubing int i; 19416027c871SZhang Yubing 19426027c871SZhang Yubing if (!acm->acm_enable) { 19436027c871SZhang Yubing writel(0x2, vop2->regs + RK3528_ACM_CTRL); 19446027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 19456027c871SZhang Yubing POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 1, false); 19466027c871SZhang Yubing return; 19476027c871SZhang Yubing } 19486027c871SZhang Yubing 19496027c871SZhang Yubing printf("post acm enable\n"); 19506027c871SZhang Yubing 19516027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_START); 19526027c871SZhang Yubing 19536027c871SZhang Yubing value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) + 19546027c871SZhang Yubing ((mode->vdisplay & 0xfff) << 20); 19556027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_CTRL); 19566027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 19576027c871SZhang Yubing POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 19586027c871SZhang Yubing 19596027c871SZhang Yubing value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + 19606027c871SZhang Yubing ((acm->s_gain << 20) & 0x3ff00000); 19616027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE); 19626027c871SZhang Yubing 19636027c871SZhang Yubing lut_y = &acm->gain_lut_hy[0]; 19646027c871SZhang Yubing lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH]; 19656027c871SZhang Yubing lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2]; 19666027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) { 19676027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 19686027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 19696027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2)); 19706027c871SZhang Yubing } 19716027c871SZhang Yubing 19726027c871SZhang Yubing lut_y = &acm->gain_lut_hs[0]; 19736027c871SZhang Yubing lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH]; 19746027c871SZhang Yubing lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2]; 19756027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) { 19766027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 19776027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 19786027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2)); 19796027c871SZhang Yubing } 19806027c871SZhang Yubing 19816027c871SZhang Yubing lut_y = &acm->delta_lut_h[0]; 19826027c871SZhang Yubing lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH]; 19836027c871SZhang Yubing lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2]; 19846027c871SZhang Yubing for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) { 19856027c871SZhang Yubing value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) + 19866027c871SZhang Yubing ((lut_s[i] << 20) & 0x3ff00000); 19876027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2)); 19886027c871SZhang Yubing } 19896027c871SZhang Yubing 19906027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_DONE); 19916027c871SZhang Yubing } 19926027c871SZhang Yubing 19936027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2) 19946027c871SZhang Yubing { 19956027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 19966027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 19976027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 19986027c871SZhang Yubing struct csc_info *csc = &conn_state->disp_info->csc_info; 19996027c871SZhang Yubing struct post_csc_coef csc_coef; 20006027c871SZhang Yubing bool is_input_yuv = false; 20016027c871SZhang Yubing bool is_output_yuv = false; 20026027c871SZhang Yubing bool post_r2y_en = false; 20036027c871SZhang Yubing bool post_csc_en = false; 20046027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 20056027c871SZhang Yubing u32 value; 20066027c871SZhang Yubing int range_type; 20076027c871SZhang Yubing 20086027c871SZhang Yubing printf("post csc enable\n"); 20096027c871SZhang Yubing 20106027c871SZhang Yubing if (acm->acm_enable) { 20116027c871SZhang Yubing if (!cstate->yuv_overlay) 20126027c871SZhang Yubing post_r2y_en = true; 20136027c871SZhang Yubing 20146027c871SZhang Yubing /* do y2r in csc module */ 20156027c871SZhang Yubing if (!is_yuv_output(conn_state->bus_format)) 20166027c871SZhang Yubing post_csc_en = true; 20176027c871SZhang Yubing } else { 20186027c871SZhang Yubing if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 20196027c871SZhang Yubing post_r2y_en = true; 20206027c871SZhang Yubing 20216027c871SZhang Yubing /* do y2r in csc module */ 20226027c871SZhang Yubing if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 20236027c871SZhang Yubing post_csc_en = true; 20246027c871SZhang Yubing } 20256027c871SZhang Yubing 20266027c871SZhang Yubing if (csc->csc_enable) 20276027c871SZhang Yubing post_csc_en = true; 20286027c871SZhang Yubing 20296027c871SZhang Yubing if (cstate->yuv_overlay || post_r2y_en) 20306027c871SZhang Yubing is_input_yuv = true; 20316027c871SZhang Yubing 20326027c871SZhang Yubing if (is_yuv_output(conn_state->bus_format)) 20336027c871SZhang Yubing is_output_yuv = true; 20346027c871SZhang Yubing 20356027c871SZhang Yubing cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_13BIT_DEPTH); 20366027c871SZhang Yubing 20376027c871SZhang Yubing if (post_csc_en) { 20386027c871SZhang Yubing rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv, 20396027c871SZhang Yubing is_output_yuv); 20406027c871SZhang Yubing 20416027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20426027c871SZhang Yubing POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT, 20436027c871SZhang Yubing csc_coef.csc_coef00, false); 20446027c871SZhang Yubing value = (csc_coef.csc_coef02 << 16) | csc_coef.csc_coef01; 20456027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02); 20466027c871SZhang Yubing value = (csc_coef.csc_coef11 << 16) | csc_coef.csc_coef10; 20476027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11); 20486027c871SZhang Yubing value = (csc_coef.csc_coef20 << 16) | csc_coef.csc_coef12; 20496027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20); 20506027c871SZhang Yubing value = (csc_coef.csc_coef22 << 16) | csc_coef.csc_coef21; 20516027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22); 20526027c871SZhang Yubing writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0); 20536027c871SZhang Yubing writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1); 20546027c871SZhang Yubing writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2); 20556027c871SZhang Yubing 20566027c871SZhang Yubing range_type = csc_coef.range_type ? 0 : 1; 20576027c871SZhang Yubing range_type <<= is_input_yuv ? 0 : 1; 20586027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20596027c871SZhang Yubing POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false); 20606027c871SZhang Yubing } 20616027c871SZhang Yubing 20626027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20636027c871SZhang Yubing POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, post_r2y_en ? 1 : 0, false); 20646027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20656027c871SZhang Yubing POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false); 20666027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 20676027c871SZhang Yubing POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false); 20686027c871SZhang Yubing } 20696027c871SZhang Yubing 20706027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2) 20716027c871SZhang Yubing { 20726027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 20736027c871SZhang Yubing struct base2_disp_info *disp_info = conn_state->disp_info; 20746027c871SZhang Yubing const char *enable_flag; 20756027c871SZhang Yubing 20766027c871SZhang Yubing if (!disp_info) { 20776027c871SZhang Yubing printf("disp_info is empty\n"); 20786027c871SZhang Yubing return; 20796027c871SZhang Yubing } 20806027c871SZhang Yubing 20816027c871SZhang Yubing enable_flag = (const char *)&disp_info->cacm_header; 20826027c871SZhang Yubing if (strncasecmp(enable_flag, "CACM", 4)) { 20836027c871SZhang Yubing printf("acm and csc is not support\n"); 20846027c871SZhang Yubing return; 20856027c871SZhang Yubing } 20866027c871SZhang Yubing 20876027c871SZhang Yubing vop3_post_acm_config(state, vop2); 20886027c871SZhang Yubing vop3_post_csc_config(state, vop2); 20896027c871SZhang Yubing } 20906027c871SZhang Yubing 2091d2e91fdcSDamon Ding /* 2092d2e91fdcSDamon Ding * Read VOP internal power domain on/off status. 2093d2e91fdcSDamon Ding * We should query BISR_STS register in PMU for 2094d2e91fdcSDamon Ding * power up/down status when memory repair is enabled. 2095d2e91fdcSDamon Ding * Return value: 1 for power on, 0 for power off; 2096d2e91fdcSDamon Ding */ 209760e469f5SDamon Ding static int vop2_wait_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 209860e469f5SDamon Ding { 209960e469f5SDamon Ding int val = 0; 210060e469f5SDamon Ding int shift = 0; 2101b6ba80b4SDamon Ding int shift_factor = 0; 210260e469f5SDamon Ding bool is_bisr_en = false; 210360e469f5SDamon Ding 2104b6ba80b4SDamon Ding /* 2105b6ba80b4SDamon Ding * The order of pd status bits in BISR_STS register 2106b6ba80b4SDamon Ding * is different from that in VOP SYS_STS register. 2107b6ba80b4SDamon Ding */ 2108b6ba80b4SDamon Ding if (pd_data->id == VOP2_PD_DSC_8K || 2109b6ba80b4SDamon Ding pd_data->id == VOP2_PD_DSC_4K || 2110b6ba80b4SDamon Ding pd_data->id == VOP2_PD_ESMART) 2111b6ba80b4SDamon Ding shift_factor = 1; 2112b6ba80b4SDamon Ding 2113b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor; 2114b6ba80b4SDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift); 211560e469f5SDamon Ding if (is_bisr_en) { 2116b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor; 2117b6ba80b4SDamon Ding 211860e469f5SDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 2119d2e91fdcSDamon Ding ((val >> shift) & 0x1), 50 * 1000); 212060e469f5SDamon Ding } else { 2121b6ba80b4SDamon Ding shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1; 2122b6ba80b4SDamon Ding 212360e469f5SDamon Ding return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 212460e469f5SDamon Ding !((val >> shift) & 0x1), 50 * 1000); 212560e469f5SDamon Ding } 212660e469f5SDamon Ding } 212760e469f5SDamon Ding 2128b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id) 212960e469f5SDamon Ding { 213060e469f5SDamon Ding struct vop2_power_domain_data *pd_data; 213160e469f5SDamon Ding int ret = 0; 213260e469f5SDamon Ding 2133b6ba80b4SDamon Ding if (!pd_id) 2134b6ba80b4SDamon Ding return 0; 2135b6ba80b4SDamon Ding 2136b6ba80b4SDamon Ding pd_data = vop2_find_pd_data_by_id(vop2, pd_id); 2137b6ba80b4SDamon Ding if (!pd_data) { 2138b6ba80b4SDamon Ding printf("can't find pd_data by id\n"); 213960e469f5SDamon Ding return -EINVAL; 214060e469f5SDamon Ding } 21412c66af11SDamon Ding 2142b6ba80b4SDamon Ding if (pd_data->parent_id) { 2143b6ba80b4SDamon Ding ret = vop2_power_domain_on(vop2, pd_data->parent_id); 214460e469f5SDamon Ding if (ret) { 214560e469f5SDamon Ding printf("can't open parent power domain\n"); 214660e469f5SDamon Ding return -EINVAL; 214760e469f5SDamon Ding } 214860e469f5SDamon Ding } 214960e469f5SDamon Ding 2150b6ba80b4SDamon Ding vop2_mask_write(vop2, RK3568_SYS_PD_CTRL, EN_MASK, 2151b6ba80b4SDamon Ding RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_id) - 1, 0, false); 215260e469f5SDamon Ding ret = vop2_wait_power_domain_on(vop2, pd_data); 215360e469f5SDamon Ding if (ret) { 215460e469f5SDamon Ding printf("wait vop2 power domain timeout\n"); 215560e469f5SDamon Ding return ret; 215660e469f5SDamon Ding } 215760e469f5SDamon Ding 215860e469f5SDamon Ding return 0; 215960e469f5SDamon Ding } 216060e469f5SDamon Ding 2161ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2) 2162ecc31b6eSAndy Yan { 2163ecc31b6eSAndy Yan u32 *base = vop2->regs; 2164ecc31b6eSAndy Yan int i = 0; 2165ecc31b6eSAndy Yan 2166ecc31b6eSAndy Yan /* 2167ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 2168ecc31b6eSAndy Yan */ 2169ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++) 2170ecc31b6eSAndy Yan vop2->regsbak[i] = base[i]; 2171ecc31b6eSAndy Yan } 2172ecc31b6eSAndy Yan 21735fa6e665SDamon Ding static void vop3_overlay_init(struct vop2 *vop2, struct display_state *state) 21745fa6e665SDamon Ding { 21755fa6e665SDamon Ding struct vop2_win_data *win_data; 21765fa6e665SDamon Ding int layer_phy_id = 0; 21775fa6e665SDamon Ding int i, j; 21785fa6e665SDamon Ding u32 ovl_port_offset = 0; 21795fa6e665SDamon Ding u32 layer_nr = 0; 21805fa6e665SDamon Ding u8 shift = 0; 21815fa6e665SDamon Ding 21825fa6e665SDamon Ding /* layer sel win id */ 21835fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 21845fa6e665SDamon Ding shift = 0; 21855fa6e665SDamon Ding ovl_port_offset = 0x100 * i; 21865fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 21875fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 21885fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 21895fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 21905fa6e665SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + ovl_port_offset, LAYER_SEL_MASK, 21915fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 21925fa6e665SDamon Ding shift += 4; 21935fa6e665SDamon Ding } 21945fa6e665SDamon Ding } 21955fa6e665SDamon Ding 21965fa6e665SDamon Ding /* win sel port */ 21975fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 21985fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 21995fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22005fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 22015fa6e665SDamon Ding continue; 22025fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22035fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22045fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 22055fa6e665SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL_IMD, LAYER_SEL_PORT_MASK, 22065fa6e665SDamon Ding shift, i, false); 22075fa6e665SDamon Ding } 22085fa6e665SDamon Ding } 22095fa6e665SDamon Ding } 22105fa6e665SDamon Ding 22115fa6e665SDamon Ding static void vop2_overlay_init(struct vop2 *vop2, struct display_state *state) 22125fa6e665SDamon Ding { 22135fa6e665SDamon Ding struct crtc_state *cstate = &state->crtc_state; 22145fa6e665SDamon Ding struct vop2_win_data *win_data; 22155fa6e665SDamon Ding int layer_phy_id = 0; 22165fa6e665SDamon Ding int total_used_layer = 0; 22175fa6e665SDamon Ding int port_mux = 0; 22185fa6e665SDamon Ding int i, j; 22195fa6e665SDamon Ding u32 layer_nr = 0; 22205fa6e665SDamon Ding u8 shift = 0; 22215fa6e665SDamon Ding 22225fa6e665SDamon Ding /* layer sel win id */ 22235fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22245fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22255fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22265fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22275fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22285fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 22295fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 22305fa6e665SDamon Ding shift += 4; 22315fa6e665SDamon Ding } 22325fa6e665SDamon Ding } 22335fa6e665SDamon Ding 22345fa6e665SDamon Ding /* win sel port */ 22355fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22365fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22375fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22385fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 22395fa6e665SDamon Ding continue; 22405fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22415fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22425fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 22435fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 22445fa6e665SDamon Ding LAYER_SEL_PORT_SHIFT + shift, i, false); 22455fa6e665SDamon Ding } 22465fa6e665SDamon Ding } 22475fa6e665SDamon Ding 22485fa6e665SDamon Ding /** 22495fa6e665SDamon Ding * port mux config 22505fa6e665SDamon Ding */ 22515fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22525fa6e665SDamon Ding shift = i * 4; 22535fa6e665SDamon Ding if (vop2->vp_plane_mask[i].attached_layers_nr) { 22545fa6e665SDamon Ding total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 22555fa6e665SDamon Ding port_mux = total_used_layer - 1; 22565fa6e665SDamon Ding } else { 22575fa6e665SDamon Ding port_mux = 8; 22585fa6e665SDamon Ding } 22595fa6e665SDamon Ding 22605fa6e665SDamon Ding if (i == vop2->data->nr_vps - 1) 22615fa6e665SDamon Ding port_mux = vop2->data->nr_mixers; 22625fa6e665SDamon Ding 22635fa6e665SDamon Ding cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 22645fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 22655fa6e665SDamon Ding PORT_MUX_SHIFT + shift, port_mux, false); 22665fa6e665SDamon Ding } 22675fa6e665SDamon Ding } 22685fa6e665SDamon Ding 22695fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win) 22705fa6e665SDamon Ding { 22715fa6e665SDamon Ding if (!is_vop3(vop2)) 22725fa6e665SDamon Ding return false; 22735fa6e665SDamon Ding 22745fa6e665SDamon Ding if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE && 22755fa6e665SDamon Ding win->phys_id != ROCKCHIP_VOP2_ESMART0) 22765fa6e665SDamon Ding return true; 22775fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE && 22785fa6e665SDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) 22795fa6e665SDamon Ding return true; 22805fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && 22815fa6e665SDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART1) 22825fa6e665SDamon Ding return true; 22835fa6e665SDamon Ding else 22845fa6e665SDamon Ding return false; 22855fa6e665SDamon Ding } 22865fa6e665SDamon Ding 22875fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2) 22885fa6e665SDamon Ding { 22895fa6e665SDamon Ding struct vop2_win_data *win_data; 2290*fa4ecc32SDamon Ding int i; 22915fa6e665SDamon Ding u8 scale_engine_num = 0; 22925fa6e665SDamon Ding 22935fa6e665SDamon Ding /* store plane mask for vop2_fixup_dts */ 2294*fa4ecc32SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 2295*fa4ecc32SDamon Ding win_data = &vop2->data->win_data[i]; 22965fa6e665SDamon Ding if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data)) 22975fa6e665SDamon Ding continue; 22985fa6e665SDamon Ding 22995fa6e665SDamon Ding win_data->scale_engine_num = scale_engine_num++; 23005fa6e665SDamon Ding } 23015fa6e665SDamon Ding } 23025fa6e665SDamon Ding 2303b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 2304d0408543SAndy Yan { 2305b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 2306b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 23075fa6e665SDamon Ding int layer_phy_id = 0; 23085fa6e665SDamon Ding int i, j; 2309*fa4ecc32SDamon Ding int ret; 23105fa6e665SDamon Ding u32 layer_nr = 0; 2311d0408543SAndy Yan 231263cb669fSSandy Huang if (vop2->global_init) 2313d0408543SAndy Yan return; 231463cb669fSSandy Huang 2315b0989546SSandy Huang /* OTP must enable at the first time, otherwise mirror layer register is error */ 231663cb669fSSandy Huang if (soc_is_rk3566()) 231763cb669fSSandy Huang vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 231863cb669fSSandy Huang OTP_WIN_EN_SHIFT, 1, false); 2319b0989546SSandy Huang 2320b0989546SSandy Huang if (cstate->crtc->assign_plane) {/* dts assign plane */ 2321b0989546SSandy Huang u32 plane_mask; 2322b0989546SSandy Huang int primary_plane_id; 2323b0989546SSandy Huang 2324b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2325b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask; 2326b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2327b0989546SSandy Huang layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 2328b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 23295fc2b656SDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 2330337d1c13SDamon Ding if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX) 2331b0989546SSandy Huang primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 2332b0989546SSandy Huang vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 2333b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2334b0989546SSandy Huang 2335b0989546SSandy Huang /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 2336b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2337b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 2338b0989546SSandy Huang plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 233963cb669fSSandy Huang } 2340b0989546SSandy Huang } 2341b0989546SSandy Huang } else {/* need soft assign plane mask */ 2342b0989546SSandy Huang /* find the first unplug devices and set it as main display */ 2343b0989546SSandy Huang int main_vp_index = -1; 2344b0989546SSandy Huang int active_vp_num = 0; 2345b0989546SSandy Huang 2346b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2347b0989546SSandy Huang if (cstate->crtc->vps[i].enable) 2348b0989546SSandy Huang active_vp_num++; 2349b0989546SSandy Huang } 2350b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num); 2351b0989546SSandy Huang 2352b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2) 2353b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n"); 2354b0989546SSandy Huang plane_mask = vop2->data->plane_mask; 2355b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 23565fa6e665SDamon Ding /* 23575fa6e665SDamon Ding * For rk3528, one display policy for hdmi store in plane_mask[0], and the other 23585fa6e665SDamon Ding * for cvbs store in plane_mask[2]. 23595fa6e665SDamon Ding */ 23605fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 && 23615fa6e665SDamon Ding cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV) 23625fa6e665SDamon Ding plane_mask += 2 * VOP2_VP_MAX; 2363b0989546SSandy Huang 23645fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528) { 23655fa6e665SDamon Ding /* 23665fa6e665SDamon Ding * For rk3528, the plane mask of vp is limited, only esmart2 can be selected 23675fa6e665SDamon Ding * by both vp0 and vp1. 23685fa6e665SDamon Ding */ 23695fa6e665SDamon Ding j = 0; 23705fa6e665SDamon Ding } else { 2371b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2372b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 2373b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/ 2374b0989546SSandy Huang main_vp_index = i; 2375e007876dSSandy Huang break; 2376b0989546SSandy Huang } 2377b0989546SSandy Huang } 2378b0989546SSandy Huang 2379b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */ 2380b0989546SSandy Huang if (main_vp_index < 0) { 2381b0989546SSandy Huang main_vp_index = 0; 2382b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0]; 2383b0989546SSandy Huang } 2384b0989546SSandy Huang 2385b0989546SSandy Huang j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */ 23865fa6e665SDamon Ding } 2387b0989546SSandy Huang 2388b0989546SSandy Huang /* init other display except main display */ 2389b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2390b0989546SSandy Huang if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */ 2391b0989546SSandy Huang continue; 2392b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++]; 2393b0989546SSandy Huang } 2394b0989546SSandy Huang 2395b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */ 2396b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2397b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 2398b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2399b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 2400b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 2401b0989546SSandy Huang } 2402b0989546SSandy Huang } 2403b0989546SSandy Huang } 2404b0989546SSandy Huang 240560e469f5SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 240660e469f5SDamon Ding rk3588_vop2_regsbak(vop2); 240760e469f5SDamon Ding else 240860e469f5SDamon Ding memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 240960e469f5SDamon Ding 241060e469f5SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 241160e469f5SDamon Ding OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 241260e469f5SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 241360e469f5SDamon Ding IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 241460e469f5SDamon Ding 2415b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2416b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 2417b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 2418b0989546SSandy Huang printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]); 2419b0989546SSandy Huang printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id); 2420b0989546SSandy Huang } 2421b0989546SSandy Huang 24225fa6e665SDamon Ding if (is_vop3(vop2)) 24235fa6e665SDamon Ding vop3_overlay_init(vop2, state); 24245fa6e665SDamon Ding else 24255fa6e665SDamon Ding vop2_overlay_init(vop2, state); 2426b0989546SSandy Huang 24275fa6e665SDamon Ding if (is_vop3(vop2)) { 24285fa6e665SDamon Ding /* 24295fa6e665SDamon Ding * you can rewrite at dts vop node: 24305fa6e665SDamon Ding * 24315fa6e665SDamon Ding * VOP3_ESMART_8K_MODE = 0, 24325fa6e665SDamon Ding * VOP3_ESMART_4K_4K_MODE = 1, 24335fa6e665SDamon Ding * VOP3_ESMART_4K_2K_2K_MODE = 2, 24345fa6e665SDamon Ding * VOP3_ESMART_2K_2K_2K_2K_MODE = 3, 24355fa6e665SDamon Ding * 24365fa6e665SDamon Ding * &vop { 24375fa6e665SDamon Ding * esmart_lb_mode = /bits/ 8 <2>; 24385fa6e665SDamon Ding * }; 243963cb669fSSandy Huang */ 2440*fa4ecc32SDamon Ding ret = ofnode_read_u32(cstate->node, "esmart_lb_mode", &vop2->esmart_lb_mode); 2441*fa4ecc32SDamon Ding if (ret < 0) 24425fa6e665SDamon Ding vop2->esmart_lb_mode = vop2->data->esmart_lb_mode; 24435fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, ESMART_LB_MODE_SEL_MASK, 24445fa6e665SDamon Ding ESMART_LB_MODE_SEL_SHIFT, vop2->esmart_lb_mode, false); 2445d0408543SAndy Yan 24465fa6e665SDamon Ding vop3_init_esmart_scale_engine(vop2); 2447aa670293SDamon Ding 2448aa670293SDamon Ding vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK, 2449aa670293SDamon Ding DSP_VS_T_SEL_SHIFT, 0, false); 245063cb669fSSandy Huang } 245163cb669fSSandy Huang 2452ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568) 245363cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 245463cb669fSSandy Huang 245563cb669fSSandy Huang vop2->global_init = true; 2456d0408543SAndy Yan } 2457d0408543SAndy Yan 2458d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state) 2459d0408543SAndy Yan { 2460d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 246163cb669fSSandy Huang int ret; 2462d0408543SAndy Yan 2463d0408543SAndy Yan /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 2464d0408543SAndy Yan ret = clk_set_defaults(cstate->dev); 2465d0408543SAndy Yan if (ret) 2466d0408543SAndy Yan debug("%s clk_set_defaults failed %d\n", __func__, ret); 2467d0408543SAndy Yan 24681147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state); 24696414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state); 2470d0408543SAndy Yan 2471d0408543SAndy Yan return 0; 2472d0408543SAndy Yan } 2473d0408543SAndy Yan 2474d0408543SAndy Yan /* 2475d0408543SAndy Yan * VOP2 have multi video ports. 2476d0408543SAndy Yan * video port ------- crtc 2477d0408543SAndy Yan */ 2478d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state) 2479d0408543SAndy Yan { 2480d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2481d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data; 2482d0408543SAndy Yan 2483d0408543SAndy Yan if (!rockchip_vop2) { 24840d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2)); 2485d0408543SAndy Yan if (!rockchip_vop2) 2486d0408543SAndy Yan return -ENOMEM; 2487d0408543SAndy Yan rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 2488d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 2489d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG; 249063cb669fSSandy Huang rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2491d0408543SAndy Yan if (rockchip_vop2->grf <= 0) 249263cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 2493d0408543SAndy Yan rockchip_vop2->version = vop2_data->version; 2494d0408543SAndy Yan rockchip_vop2->data = vop2_data; 2495ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) { 2496b890760eSAlgea Cao struct regmap *map; 2497b890760eSAlgea Cao 2498ecc31b6eSAndy Yan rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF); 2499ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0) 2500ecc31b6eSAndy Yan printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf); 2501b890760eSAlgea Cao map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); 2502b890760eSAlgea Cao rockchip_vop2->vo1_grf = regmap_get_range(map, 0); 2503ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0) 2504ecc31b6eSAndy Yan printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf); 250560e469f5SDamon Ding rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); 2506b890760eSAlgea Cao if (rockchip_vop2->sys_pmu <= 0) 250760e469f5SDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu); 2508ecc31b6eSAndy Yan } 2509d0408543SAndy Yan } 2510d0408543SAndy Yan 2511d0408543SAndy Yan cstate->private = rockchip_vop2; 251263cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 251363cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 2514d0408543SAndy Yan 251589912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state); 251689912f2dSSandy Huang 2517d0408543SAndy Yan return 0; 2518d0408543SAndy Yan } 2519d0408543SAndy Yan 2520ecc31b6eSAndy Yan /* 2521ecc31b6eSAndy Yan * calc the dclk on rk3588 2522ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4 2523ecc31b6eSAndy Yan * 2524ecc31b6eSAndy Yan */ 2525ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 2526ecc31b6eSAndy Yan { 2527ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk) 2528ecc31b6eSAndy Yan return child_clk * 4; 2529ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk) 2530ecc31b6eSAndy Yan return child_clk * 2; 2531ecc31b6eSAndy Yan else if (child_clk <= max_dclk) 2532ecc31b6eSAndy Yan return child_clk; 2533ecc31b6eSAndy Yan else 2534ecc31b6eSAndy Yan return 0; 2535ecc31b6eSAndy Yan } 2536ecc31b6eSAndy Yan 2537ecc31b6eSAndy Yan /* 2538ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588 2539ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core 2540ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core 2541ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core 2542ecc31b6eSAndy Yan */ 2543ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state, 2544ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div, 2545ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div) 2546d0408543SAndy Yan { 2547d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2548d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 2549d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2550d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 25510a1fb152SZhang Yubing unsigned long v_pixclk = mode->crtc_clock; 2552ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2; 2553ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk; 2554ecc31b6eSAndy Yan unsigned long dclk_out_rate; 2555ecc31b6eSAndy Yan u64 if_dclk_rate; 2556ecc31b6eSAndy Yan u64 if_pixclk_rate; 2557ecc31b6eSAndy Yan int output_type = conn_state->type; 2558ecc31b6eSAndy Yan int output_mode = conn_state->output_mode; 2559ecc31b6eSAndy Yan int K = 1; 2560ecc31b6eSAndy Yan 25610a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE && 25620a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 25630a1fb152SZhang Yubing printf("Dual channel and YUV420 can't work together\n"); 25640a1fb152SZhang Yubing return -EINVAL; 25650a1fb152SZhang Yubing } 25660a1fb152SZhang Yubing 25670a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 25680a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) 25690a1fb152SZhang Yubing K = 2; 25700a1fb152SZhang Yubing 2571ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 2572ecc31b6eSAndy Yan /* 2573ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 2574ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 2575ecc31b6eSAndy Yan */ 25760a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 25770a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 2578b890760eSAlgea Cao dclk_rate = dclk_rate >> 1; 2579ecc31b6eSAndy Yan K = 2; 2580b890760eSAlgea Cao } 258112ee5af0SDamon Ding if (cstate->dsc_enable) { 258212ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate << 1; 258312ee5af0SDamon Ding if_dclk_rate = cstate->dsc_cds_clk_rate; 2584ecc31b6eSAndy Yan } else { 2585ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K; 2586ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K; 2587ecc31b6eSAndy Yan } 2588ecc31b6eSAndy Yan 2589631ee99aSZhang Yubing if (v_pixclk > VOP2_MAX_DCLK_RATE) 2590631ee99aSZhang Yubing dclk_rate = vop2_calc_dclk(dclk_core_rate, vop2->data->vp_data->max_dclk); 2591631ee99aSZhang Yubing 2592ecc31b6eSAndy Yan if (!dclk_rate) { 2593ecc31b6eSAndy Yan printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 2594ecc31b6eSAndy Yan vop2->data->vp_data->max_dclk, if_pixclk_rate); 2595ecc31b6eSAndy Yan return -EINVAL; 2596ecc31b6eSAndy Yan } 2597ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 2598ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate; 2599b890760eSAlgea Cao *dclk_core_div = dclk_rate / dclk_core_rate; 2600b890760eSAlgea Cao printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n", 2601b890760eSAlgea Cao dclk_rate, *if_pixclk_div, *if_dclk_div); 2602ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 2603ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */ 2604ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K; 2605ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K; 2606ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K; 2607ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2608ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 2609ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div; 2610ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 2611ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2; 26120a1fb152SZhang Yubing dclk_out_rate = dclk_out_rate / K; 2613ecc31b6eSAndy Yan 26146b2bd269SZhang Yubing dclk_rate = vop2_calc_dclk(dclk_out_rate, vop2->data->vp_data->max_dclk); 2615ecc31b6eSAndy Yan if (!dclk_rate) { 2616ecc31b6eSAndy Yan printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 2617ecc31b6eSAndy Yan vop2->data->vp_data->max_dclk, dclk_core_rate); 2618ecc31b6eSAndy Yan return -EINVAL; 2619ecc31b6eSAndy Yan } 2620ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 2621ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2622ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 2623ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2624ecc31b6eSAndy Yan K = 2; 262512ee5af0SDamon Ding if (cstate->dsc_enable) 262612ee5af0SDamon Ding /* dsc output is 96bit, dsi input is 192 bit */ 262712ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1; 2628ecc31b6eSAndy Yan else 2629ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K; 2630ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 263112ee5af0SDamon Ding dclk_out_rate = dclk_core_rate / K; 2632ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 26339f076eccSZhang Yubing dclk_rate = vop2_calc_dclk(dclk_out_rate, vop2->data->vp_data->max_dclk); 26349f076eccSZhang Yubing if (!dclk_rate) { 26359f076eccSZhang Yubing printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n", 26369f076eccSZhang Yubing vop2->data->vp_data->max_dclk, dclk_rate); 26379f076eccSZhang Yubing return -EINVAL; 26389f076eccSZhang Yubing } 263912ee5af0SDamon Ding 264012ee5af0SDamon Ding if (cstate->dsc_enable) 264112ee5af0SDamon Ding dclk_rate = dclk_rate >> 1; 264212ee5af0SDamon Ding 2643ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 2644ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2645ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 264612ee5af0SDamon Ding if (cstate->dsc_enable) 26471ace1b6dSDamon Ding *if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate; 2648ecc31b6eSAndy Yan 2649ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 2650ecc31b6eSAndy Yan dclk_rate = v_pixclk; 2651ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2652ecc31b6eSAndy Yan } 2653ecc31b6eSAndy Yan 2654ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div); 2655ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div); 2656ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div); 2657ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div); 2658ecc31b6eSAndy Yan 2659ecc31b6eSAndy Yan return dclk_rate; 2660ecc31b6eSAndy Yan } 2661ecc31b6eSAndy Yan 266212ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state) 2663ecc31b6eSAndy Yan { 266412ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 2665ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 266612ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 26671ace1b6dSDamon Ding u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */ 2668ecc31b6eSAndy Yan u8 k = 1; 2669ecc31b6eSAndy Yan 2670ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2671ecc31b6eSAndy Yan k = 2; 2672ecc31b6eSAndy Yan 267312ee5af0SDamon Ding cstate->dsc_txp_clk_rate = v_pixclk; 267412ee5af0SDamon Ding do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k)); 2675ecc31b6eSAndy Yan 267612ee5af0SDamon Ding cstate->dsc_pxl_clk_rate = v_pixclk; 267712ee5af0SDamon Ding do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k)); 2678ecc31b6eSAndy Yan 2679ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 2680ecc31b6eSAndy Yan * cds_dat_width = 96; 2681ecc31b6eSAndy Yan * bits_per_pixel = [8-12]; 2682b61227a3SDamon Ding * As cds clk is div from txp clk and only support 1/2/4 div, 2683b61227a3SDamon Ding * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4, 2684b61227a3SDamon Ding * otherwise dsc_cds = crtc_clock / 8; 2685ecc31b6eSAndy Yan */ 2686b61227a3SDamon Ding cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8); 2687ecc31b6eSAndy Yan 2688ecc31b6eSAndy Yan return 0; 2689ecc31b6eSAndy Yan } 2690ecc31b6eSAndy Yan 2691ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 2692ecc31b6eSAndy Yan { 2693ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2694ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2695ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 269612ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 2697ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 269852ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2699ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2700ecc31b6eSAndy Yan int output_if = conn_state->output_if; 2701ecc31b6eSAndy Yan int if_pixclk_div = 0; 2702ecc31b6eSAndy Yan int if_dclk_div = 0; 2703ecc31b6eSAndy Yan unsigned long dclk_rate; 2704d0408543SAndy Yan u32 val; 2705ecc31b6eSAndy Yan 2706b890760eSAlgea Cao if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 2707b890760eSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 2708b890760eSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 2709b890760eSAlgea Cao } else { 2710ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 2711ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2712b890760eSAlgea Cao } 2713ecc31b6eSAndy Yan 271412ee5af0SDamon Ding if (cstate->dsc_enable) { 271512ee5af0SDamon Ding int k = 1; 271612ee5af0SDamon Ding 2717ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) { 271812ee5af0SDamon Ding printf("Unsupported DSC\n"); 2719ecc31b6eSAndy Yan return 0; 2720ecc31b6eSAndy Yan } 272112ee5af0SDamon Ding 272212ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 272312ee5af0SDamon Ding k = 2; 272412ee5af0SDamon Ding 272512ee5af0SDamon Ding cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 272612ee5af0SDamon Ding cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k; 272712ee5af0SDamon Ding cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num; 272812ee5af0SDamon Ding 272912ee5af0SDamon Ding vop2_calc_dsc_clk(state); 273012ee5af0SDamon Ding printf("Enable DSC%d slice:%dx%d, slice num:%d\n", 273112ee5af0SDamon Ding cstate->dsc_id, dsc_sink_cap->slice_width, 273212ee5af0SDamon Ding dsc_sink_cap->slice_height, cstate->dsc_slice_num); 2733ecc31b6eSAndy Yan } 2734ecc31b6eSAndy Yan 2735b61227a3SDamon Ding dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div); 2736ecc31b6eSAndy Yan 2737ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) { 2738ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2739ecc31b6eSAndy Yan 4, false); 2740ecc31b6eSAndy Yan } 2741ecc31b6eSAndy Yan 2742ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) { 2743ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2744ecc31b6eSAndy Yan 3, false); 2745ecc31b6eSAndy Yan } 2746ecc31b6eSAndy Yan 2747ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) { 2748ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2749ecc31b6eSAndy Yan 2, false); 2750ecc31b6eSAndy Yan } 2751ecc31b6eSAndy Yan 2752ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) { 2753ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2754ecc31b6eSAndy Yan val = 0; 2755ecc31b6eSAndy Yan else 2756ecc31b6eSAndy Yan val = 1; 275741874944SGuochun Huang 27583df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 275941874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 276041874944SGuochun Huang RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 276141874944SGuochun Huang 2762ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 2763ecc31b6eSAndy Yan 1, false); 2764ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 2765ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 2766ecc31b6eSAndy Yan if_pixclk_div, false); 276741874944SGuochun Huang 276841874944SGuochun Huang if (conn_state->hold_mode) { 276941874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 277041874944SGuochun Huang EN_MASK, EDPI_TE_EN, 1, false); 277141874944SGuochun Huang 277241874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 277341874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 277441874944SGuochun Huang } 2775ecc31b6eSAndy Yan } 2776ecc31b6eSAndy Yan 2777ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) { 2778ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2779ecc31b6eSAndy Yan val = 0; 2780ecc31b6eSAndy Yan else if (cstate->crtc_id == 3) 2781ecc31b6eSAndy Yan val = 1; 2782ecc31b6eSAndy Yan else 2783ecc31b6eSAndy Yan val = 3; /*VP1*/ 27843df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 278541874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 278641874944SGuochun Huang RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 278741874944SGuochun Huang 2788ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 2789ecc31b6eSAndy Yan 1, false); 2790ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 2791ecc31b6eSAndy Yan val, false); 2792ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 2793ecc31b6eSAndy Yan if_pixclk_div, false); 279441874944SGuochun Huang 279541874944SGuochun Huang if (conn_state->hold_mode) { 279641874944SGuochun Huang /* UNDO: RK3588 VP1->DSC1->DSI1 only can support soft TE mode */ 279741874944SGuochun Huang if (vop2->version == VOP_VERSION_RK3588 && val == 3) 279841874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 279941874944SGuochun Huang EN_MASK, EDPI_TE_EN, 0, false); 280041874944SGuochun Huang else 280141874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 280241874944SGuochun Huang EN_MASK, EDPI_TE_EN, 1, false); 280341874944SGuochun Huang 280441874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 280541874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 280641874944SGuochun Huang } 2807ecc31b6eSAndy Yan } 2808ecc31b6eSAndy Yan 2809ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 28103df6e59eSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 28113df6e59eSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 2812ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2813ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2814ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 2815ecc31b6eSAndy Yan false); 28160a1fb152SZhang Yubing switch (conn_state->type) { 28170a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DisplayPort: 28180a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28190a1fb152SZhang Yubing RK3588_DP_DUAL_EN_SHIFT, 1, false); 28200a1fb152SZhang Yubing break; 28210a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_eDP: 28220a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28230a1fb152SZhang Yubing RK3588_EDP_DUAL_EN_SHIFT, 1, false); 28240a1fb152SZhang Yubing break; 28250a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_HDMIA: 28260a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28270a1fb152SZhang Yubing RK3588_HDMI_DUAL_EN_SHIFT, 1, false); 28280a1fb152SZhang Yubing break; 28290a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DSI: 28300a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28310a1fb152SZhang Yubing RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 28320a1fb152SZhang Yubing break; 28330a1fb152SZhang Yubing default: 28340a1fb152SZhang Yubing break; 28350a1fb152SZhang Yubing } 2836ecc31b6eSAndy Yan } 2837ecc31b6eSAndy Yan 2838ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) { 2839ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 2840ecc31b6eSAndy Yan 1, false); 2841ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2842ecc31b6eSAndy Yan cstate->crtc_id, false); 2843ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2844ecc31b6eSAndy Yan if_dclk_div, false); 2845ecc31b6eSAndy Yan 2846ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2847ecc31b6eSAndy Yan if_pixclk_div, false); 2848ecc31b6eSAndy Yan 2849ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2850ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 2851ecc31b6eSAndy Yan } 2852ecc31b6eSAndy Yan 2853ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) { 2854ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 2855ecc31b6eSAndy Yan 1, false); 2856ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2857ecc31b6eSAndy Yan cstate->crtc_id, false); 2858ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2859ecc31b6eSAndy Yan if_dclk_div, false); 2860ecc31b6eSAndy Yan 2861ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2862ecc31b6eSAndy Yan if_pixclk_div, false); 28631848455fSDamon Ding 28641848455fSDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 28651848455fSDamon Ding RK3588_GRF_EDP1_ENABLE_SHIFT, 1); 2866ecc31b6eSAndy Yan } 2867ecc31b6eSAndy Yan 2868ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) { 2869ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 2870ecc31b6eSAndy Yan 1, false); 2871ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2872ecc31b6eSAndy Yan cstate->crtc_id, false); 2873ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2874ecc31b6eSAndy Yan if_dclk_div, false); 2875ecc31b6eSAndy Yan 2876ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2877ecc31b6eSAndy Yan if_pixclk_div, false); 2878b890760eSAlgea Cao 2879b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2880b890760eSAlgea Cao RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1); 2881b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2882b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2883b890760eSAlgea Cao HDMI0_SYNC_POL_SHIFT, val); 2884ecc31b6eSAndy Yan } 2885ecc31b6eSAndy Yan 2886ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) { 2887ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 2888ecc31b6eSAndy Yan 1, false); 2889ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2890ecc31b6eSAndy Yan cstate->crtc_id, false); 2891ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2892ecc31b6eSAndy Yan if_dclk_div, false); 2893ecc31b6eSAndy Yan 2894ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2895ecc31b6eSAndy Yan if_pixclk_div, false); 2896b890760eSAlgea Cao 2897b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2898b890760eSAlgea Cao RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1); 2899b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2900b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2901b890760eSAlgea Cao HDMI1_SYNC_POL_SHIFT, val); 2902ecc31b6eSAndy Yan } 2903ecc31b6eSAndy Yan 2904ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) { 2905ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 2906ecc31b6eSAndy Yan 1, false); 2907ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 2908ecc31b6eSAndy Yan cstate->crtc_id, false); 2909ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2910ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false); 2911ecc31b6eSAndy Yan } 2912ecc31b6eSAndy Yan 2913ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) { 2914108c5f8bSZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT, 2915ecc31b6eSAndy Yan 1, false); 2916ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 2917ecc31b6eSAndy Yan cstate->crtc_id, false); 2918ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2919ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false); 2920ecc31b6eSAndy Yan } 2921ecc31b6eSAndy Yan 2922ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2923b61227a3SDamon Ding DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false); 2924ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2925b61227a3SDamon Ding DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false); 2926ecc31b6eSAndy Yan 2927ecc31b6eSAndy Yan return dclk_rate; 2928ecc31b6eSAndy Yan } 2929ecc31b6eSAndy Yan 2930ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 2931ecc31b6eSAndy Yan { 2932ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2933ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2934ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2935ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2936ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 2937d0408543SAndy Yan bool dclk_inv; 2938ecc31b6eSAndy Yan u32 val; 29398895aec1SSandy Huang 2940d0408543SAndy Yan dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 294110ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 294210ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2943d0408543SAndy Yan 2944d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 2945d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 2946d0408543SAndy Yan 1, false); 2947d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2948d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 2949ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 2950c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 2951d0408543SAndy Yan } 2952d0408543SAndy Yan 2953d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 295452ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 295552ee18acSSandy Huang 1, false); 2956d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 2957d0408543SAndy Yan BT1120_EN_SHIFT, 1, false); 2958d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2959d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 2960ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 296152ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 2962d0408543SAndy Yan } 2963d0408543SAndy Yan 2964d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 2965d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 2966d0408543SAndy Yan 1, false); 2967d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2968d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 2969ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 297052ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 2971d0408543SAndy Yan } 2972d0408543SAndy Yan 2973d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 2974d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 2975d0408543SAndy Yan 1, false); 2976d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2977d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false); 297811f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 297911f53190SSandy Huang IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 2980d0408543SAndy Yan } 2981d0408543SAndy Yan 2982d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 2983d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 2984d0408543SAndy Yan 1, false); 2985d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2986d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false); 298711f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 298811f53190SSandy Huang IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 2989d0408543SAndy Yan } 2990d0408543SAndy Yan 2991d0408543SAndy Yan if (conn_state->output_flags & 2992d0408543SAndy Yan (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 2993d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 2994d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2995d0408543SAndy Yan LVDS_DUAL_EN_SHIFT, 1, false); 2996d0408543SAndy Yan if (conn_state->output_flags & 2997d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2998d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2999d0408543SAndy Yan LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 3000d0408543SAndy Yan false); 3001d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3002d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3003d0408543SAndy Yan LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 3004d0408543SAndy Yan } 3005d0408543SAndy Yan 3006d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3007d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3008d0408543SAndy Yan 1, false); 3009d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3010d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3011d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3012c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3013d0408543SAndy Yan } 3014d0408543SAndy Yan 3015d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 3016d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 3017d0408543SAndy Yan 1, false); 3018d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3019d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false); 3020d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3021c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3022d0408543SAndy Yan } 3023d0408543SAndy Yan 3024d0408543SAndy Yan if (conn_state->output_flags & 3025d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 3026d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3027d0408543SAndy Yan MIPI_DUAL_EN_SHIFT, 1, false); 3028d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3029d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3030d0408543SAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 3031d0408543SAndy Yan false); 3032d0408543SAndy Yan } 3033d0408543SAndy Yan 3034d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 3035d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 3036d0408543SAndy Yan 1, false); 3037d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3038d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false); 3039c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3040c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 3041d0408543SAndy Yan } 3042d0408543SAndy Yan 3043d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 3044d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 3045d0408543SAndy Yan 1, false); 3046d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3047d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false); 304810ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 304910ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 305010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, 305110ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK, 305210ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 3053d0408543SAndy Yan } 305410ee9f5bSAlgea Cao 3055ecc31b6eSAndy Yan return mode->clock; 3056ecc31b6eSAndy Yan } 3057ecc31b6eSAndy Yan 30585fa6e665SDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state) 30595fa6e665SDamon Ding { 30605fa6e665SDamon Ding struct crtc_state *cstate = &state->crtc_state; 30615fa6e665SDamon Ding struct connector_state *conn_state = &state->conn_state; 30625fa6e665SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 30635fa6e665SDamon Ding struct vop2 *vop2 = cstate->private; 30645fa6e665SDamon Ding u32 val; 30655fa6e665SDamon Ding 30665fa6e665SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 30675fa6e665SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 30685fa6e665SDamon Ding 30695fa6e665SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 30705fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 30715fa6e665SDamon Ding 1, false); 30725fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 30735fa6e665SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 30745fa6e665SDamon Ding } 30755fa6e665SDamon Ding 30765fa6e665SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 30775fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 30785fa6e665SDamon Ding 1, false); 30795fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 30805fa6e665SDamon Ding HDMI0_MUX_SHIFT, cstate->crtc_id, false); 30815fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 30825fa6e665SDamon Ding IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 30835fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, 30845fa6e665SDamon Ding IF_CRTL_HDMI_PIN_POL_MASK, 30855fa6e665SDamon Ding IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 30865fa6e665SDamon Ding } 30875fa6e665SDamon Ding 30885fa6e665SDamon Ding return mode->crtc_clock; 30895fa6e665SDamon Ding } 30905fa6e665SDamon Ding 3091452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state) 3092452afb13SDamon Ding { 3093452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 3094452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 3095452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3096452afb13SDamon Ding struct vop2 *vop2 = cstate->private; 3097452afb13SDamon Ding bool dclk_inv; 3098452afb13SDamon Ding u32 val; 3099452afb13SDamon Ding 3100452afb13SDamon Ding dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 3101452afb13SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3102452afb13SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3103452afb13SDamon Ding 3104452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3105452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3106452afb13SDamon Ding 1, false); 3107452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3108452afb13SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 3109452afb13SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK, 3110452afb13SDamon Ding GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 3111452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 3112452afb13SDamon Ding IF_CRTL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3113452afb13SDamon Ding } 3114452afb13SDamon Ding 3115452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3116452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3117452afb13SDamon Ding 1, false); 3118452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3119452afb13SDamon Ding LVDS0_MUX_SHIFT, cstate->crtc_id, false); 3120452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3121452afb13SDamon Ding IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 3122452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 3123452afb13SDamon Ding IF_CRTL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3124452afb13SDamon Ding } 3125452afb13SDamon Ding 3126452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3127452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3128452afb13SDamon Ding 1, false); 3129452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3130452afb13SDamon Ding MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3131452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3132452afb13SDamon Ding RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false); 3133452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 3134452afb13SDamon Ding RK3562_MIPI_PIN_POL_SHIFT, val, false); 3135452afb13SDamon Ding } 3136452afb13SDamon Ding 3137452afb13SDamon Ding return mode->crtc_clock; 3138452afb13SDamon Ding } 3139452afb13SDamon Ding 314065747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state) 314165747de7SDamon Ding { 314265747de7SDamon Ding struct crtc_state *cstate = &state->crtc_state; 314365747de7SDamon Ding struct connector_state *conn_state = &state->conn_state; 314465747de7SDamon Ding struct vop2 *vop2 = cstate->private; 314565747de7SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 314665747de7SDamon Ding u32 output_type = conn_state->type; 314765747de7SDamon Ding u32 data_swap = 0; 314865747de7SDamon Ding 314965747de7SDamon Ding if (is_uv_swap(conn_state->bus_format, conn_state->output_mode)) 315065747de7SDamon Ding data_swap = DSP_RB_SWAP; 315165747de7SDamon Ding 315265747de7SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && 315365747de7SDamon Ding (output_type == DRM_MODE_CONNECTOR_HDMIA || 315465747de7SDamon Ding output_type == DRM_MODE_CONNECTOR_eDP) && 315565747de7SDamon Ding (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 315665747de7SDamon Ding conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 315765747de7SDamon Ding data_swap |= DSP_RG_SWAP; 315865747de7SDamon Ding 315965747de7SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 316065747de7SDamon Ding DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 316165747de7SDamon Ding } 316265747de7SDamon Ding 3163b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent) 3164b890760eSAlgea Cao { 3165b890760eSAlgea Cao int ret = 0; 3166b890760eSAlgea Cao 3167b890760eSAlgea Cao if (parent->dev) 3168b890760eSAlgea Cao ret = clk_set_parent(clk, parent); 3169b890760eSAlgea Cao if (ret < 0) 3170b890760eSAlgea Cao debug("failed to set %s as parent for %s\n", 3171b890760eSAlgea Cao parent->dev->name, clk->dev->name); 3172b890760eSAlgea Cao } 3173b890760eSAlgea Cao 3174b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate) 3175b890760eSAlgea Cao { 3176b890760eSAlgea Cao int ret = 0; 3177b890760eSAlgea Cao 3178b890760eSAlgea Cao if (clk->dev) 3179b890760eSAlgea Cao ret = clk_set_rate(clk, rate); 3180b890760eSAlgea Cao if (ret < 0) 3181b890760eSAlgea Cao debug("failed to set %s rate %lu \n", clk->dev->name, rate); 3182b890760eSAlgea Cao 3183b890760eSAlgea Cao return ret; 3184b890760eSAlgea Cao } 3185b890760eSAlgea Cao 318612ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state, 318712ee5af0SDamon Ding int *dsc_txp_clk_div, int *dsc_pxl_clk_div, 318812ee5af0SDamon Ding int *dsc_cds_clk_div, u64 dclk_rate) 318912ee5af0SDamon Ding { 319012ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 319112ee5af0SDamon Ding 319212ee5af0SDamon Ding *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate; 319312ee5af0SDamon Ding *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate; 319412ee5af0SDamon Ding *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate; 319512ee5af0SDamon Ding 319612ee5af0SDamon Ding *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div); 319712ee5af0SDamon Ding *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div); 319812ee5af0SDamon Ding *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div); 319912ee5af0SDamon Ding } 320012ee5af0SDamon Ding 320112ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id) 320212ee5af0SDamon Ding { 320312ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 320412ee5af0SDamon Ding struct drm_dsc_picture_parameter_set *pps = &cstate->pps; 320512ee5af0SDamon Ding struct drm_dsc_picture_parameter_set config_pps; 320612ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 320712ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 320812ee5af0SDamon Ding u32 *pps_val = (u32 *)&config_pps; 320912ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 321012ee5af0SDamon Ding int i = 0; 321112ee5af0SDamon Ding 321212ee5af0SDamon Ding memcpy(&config_pps, pps, sizeof(config_pps)); 321312ee5af0SDamon Ding 321412ee5af0SDamon Ding if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) { 321512ee5af0SDamon Ding config_pps.pps_3 &= 0xf0; 321612ee5af0SDamon Ding config_pps.pps_3 |= dsc_data->max_linebuf_depth; 321712ee5af0SDamon Ding printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n", 321812ee5af0SDamon Ding dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf); 321912ee5af0SDamon Ding } 322012ee5af0SDamon Ding 322112ee5af0SDamon Ding for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 322212ee5af0SDamon Ding config_pps.rc_range_parameters[i] = 322312ee5af0SDamon Ding (pps->rc_range_parameters[i] >> 3 & 0x1f) | 322412ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) | 322512ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) | 322612ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10); 322712ee5af0SDamon Ding } 322812ee5af0SDamon Ding 322912ee5af0SDamon Ding for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++) 323012ee5af0SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++); 323112ee5af0SDamon Ding } 323212ee5af0SDamon Ding 323312ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate) 323412ee5af0SDamon Ding { 323512ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 323612ee5af0SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 323712ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 323812ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 323912ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 324012ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 324112ee5af0SDamon Ding bool mipi_ds_mode = false; 324212ee5af0SDamon Ding u8 dsc_interface_mode = 0; 324312ee5af0SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 324412ee5af0SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 324512ee5af0SDamon Ding u16 htotal = mode->crtc_htotal; 324612ee5af0SDamon Ding u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 324712ee5af0SDamon Ding u16 vdisplay = mode->crtc_vdisplay; 324812ee5af0SDamon Ding u16 vtotal = mode->crtc_vtotal; 324912ee5af0SDamon Ding u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 325012ee5af0SDamon Ding u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 325112ee5af0SDamon Ding u16 vact_end = vact_st + vdisplay; 325212ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 325312ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 325412ee5af0SDamon Ding int dsc_txp_clk_div = 0; 325512ee5af0SDamon Ding int dsc_pxl_clk_div = 0; 325612ee5af0SDamon Ding int dsc_cds_clk_div = 0; 3257baf2c414SDamon Ding int val = 0; 325812ee5af0SDamon Ding 325912ee5af0SDamon Ding if (!vop2->data->nr_dscs) { 326012ee5af0SDamon Ding printf("Unsupported DSC\n"); 326112ee5af0SDamon Ding return; 326212ee5af0SDamon Ding } 326312ee5af0SDamon Ding 326412ee5af0SDamon Ding if (cstate->dsc_slice_num > dsc_data->max_slice_num) 326512ee5af0SDamon Ding printf("DSC%d supported max slice is: %d, current is: %d\n", 326612ee5af0SDamon Ding dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num); 326712ee5af0SDamon Ding 326812ee5af0SDamon Ding if (dsc_data->pd_id) { 326912ee5af0SDamon Ding if (vop2_power_domain_on(vop2, dsc_data->pd_id)) 327012ee5af0SDamon Ding printf("open dsc%d pd fail\n", dsc_id); 327112ee5af0SDamon Ding } 327212ee5af0SDamon Ding 327312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK, 327412ee5af0SDamon Ding SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false); 327512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK, 327612ee5af0SDamon Ding DSC_PORT_SEL_SHIFT, cstate->crtc_id, false); 327712ee5af0SDamon Ding if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 327812ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_HDMI; 327912ee5af0SDamon Ding } else { 328012ee5af0SDamon Ding mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE); 328112ee5af0SDamon Ding if (mipi_ds_mode) 328212ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE; 328312ee5af0SDamon Ding else 328412ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE; 328512ee5af0SDamon Ding } 328612ee5af0SDamon Ding 328712ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 328812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 328912ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 0, false); 329012ee5af0SDamon Ding else 329112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 329212ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 1, false); 329312ee5af0SDamon Ding 329412ee5af0SDamon Ding vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate); 329512ee5af0SDamon Ding 329612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK, 329712ee5af0SDamon Ding DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false); 329812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK, 329912ee5af0SDamon Ding DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false); 330012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK, 330112ee5af0SDamon Ding DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false); 330212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK, 330312ee5af0SDamon Ding DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false); 330412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 330512ee5af0SDamon Ding DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false); 330612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK, 330712ee5af0SDamon Ding DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false); 330812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 330912ee5af0SDamon Ding DSC_HALT_EN_SHIFT, mipi_ds_mode, false); 331012ee5af0SDamon Ding 331112ee5af0SDamon Ding if (!mipi_ds_mode) { 331212ee5af0SDamon Ding u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end; 331312ee5af0SDamon Ding u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16; 331412ee5af0SDamon Ding u64 dsc_cds_rate = cstate->dsc_cds_clk_rate; 331512ee5af0SDamon Ding u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */ 331612ee5af0SDamon Ding u32 dly_num, dsc_cds_rate_mhz, val = 0; 3317b61227a3SDamon Ding int k = 1; 3318b61227a3SDamon Ding 3319b61227a3SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3320b61227a3SDamon Ding k = 2; 332112ee5af0SDamon Ding 332212ee5af0SDamon Ding if (target_bpp >> 4 < dsc_data->min_bits_per_pixel) 332312ee5af0SDamon Ding printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel); 332412ee5af0SDamon Ding 332512ee5af0SDamon Ding /* 332612ee5af0SDamon Ding * dly_num = delay_line_num * T(one-line) / T (dsc_cds) 332712ee5af0SDamon Ding * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz 332812ee5af0SDamon Ding * T (dsc_cds) = 1 / dsc_cds_rate_mhz 33291ace1b6dSDamon Ding * 33301ace1b6dSDamon Ding * HDMI: 333112ee5af0SDamon Ding * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay 333212ee5af0SDamon Ding * delay_line_num = 4 - BPP / 8 333312ee5af0SDamon Ding * = (64 - target_bpp / 8) / 16 333412ee5af0SDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 33351ace1b6dSDamon Ding * 33361ace1b6dSDamon Ding * MIPI DSI[4320 and 9216 is buffer size for DSC]: 33371ace1b6dSDamon Ding * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size; 33381ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 33391ace1b6dSDamon Ding * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size; 33401ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 33411ace1b6dSDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num 334212ee5af0SDamon Ding */ 334312ee5af0SDamon Ding do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ 334412ee5af0SDamon Ding dsc_cds_rate_mhz = dsc_cds_rate; 33451ace1b6dSDamon Ding dsc_hsync = hsync_len / 2; 33461ace1b6dSDamon Ding if (dsc_interface_mode == VOP_DSC_IF_HDMI) { 334712ee5af0SDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 33481ace1b6dSDamon Ding } else { 33491ace1b6dSDamon Ding int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2; 33501ace1b6dSDamon Ding int delay_line_num = dsc_buf_size / cstate->dsc_slice_num / 33511ace1b6dSDamon Ding be16_to_cpu(cstate->pps.chunk_size); 33521ace1b6dSDamon Ding 33531ace1b6dSDamon Ding delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 33541ace1b6dSDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num; 33551ace1b6dSDamon Ding 33561ace1b6dSDamon Ding /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */ 33571ace1b6dSDamon Ding if (dsc_hsync < 8) 33581ace1b6dSDamon Ding dsc_hsync = 8; 33591ace1b6dSDamon Ding } 336012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK, 336112ee5af0SDamon Ding DSC_INIT_DLY_MODE_SHIFT, 0, false); 336212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK, 336312ee5af0SDamon Ding DSC_INIT_DLY_NUM_SHIFT, dly_num, false); 336412ee5af0SDamon Ding 3365b61227a3SDamon Ding /* 3366b61227a3SDamon Ding * htotal / dclk_core = dsc_htotal /cds_clk 3367b61227a3SDamon Ding * 3368b61227a3SDamon Ding * dclk_core = DCLK / (1 << dclk_core->div_val) 3369b61227a3SDamon Ding * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val) 3370b61227a3SDamon Ding * txp_clk = DCLK / (1 << dsc_txp_clk->div_val) 3371b61227a3SDamon Ding * 3372b61227a3SDamon Ding * dsc_htotal = htotal * (1 << dclk_core->div_val) / 3373b61227a3SDamon Ding * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val)) 3374b61227a3SDamon Ding */ 3375b61227a3SDamon Ding dsc_htotal = htotal * (1 << cstate->dclk_core_div) / 3376b61227a3SDamon Ding ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div)); 337712ee5af0SDamon Ding val = dsc_htotal << 16 | dsc_hsync; 337812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK, 337912ee5af0SDamon Ding DSC_HTOTAL_PW_SHIFT, val, false); 338012ee5af0SDamon Ding 338112ee5af0SDamon Ding dsc_hact_st = hact_st / 2; 3382b61227a3SDamon Ding dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st; 338312ee5af0SDamon Ding val = dsc_hact_end << 16 | dsc_hact_st; 338412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK, 338512ee5af0SDamon Ding DSC_HACT_ST_END_SHIFT, val, false); 338612ee5af0SDamon Ding 338712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK, 338812ee5af0SDamon Ding DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false); 338912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK, 339012ee5af0SDamon Ding DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false); 339112ee5af0SDamon Ding } 339212ee5af0SDamon Ding 339312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK, 339412ee5af0SDamon Ding RST_DEASSERT_SHIFT, 1, false); 339512ee5af0SDamon Ding udelay(10); 339612ee5af0SDamon Ding 3397baf2c414SDamon Ding val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) | 3398baf2c414SDamon Ding ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT); 3399baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 3400baf2c414SDamon Ding 340112ee5af0SDamon Ding vop2_load_pps(state, vop2, dsc_id); 340212ee5af0SDamon Ding 3403baf2c414SDamon Ding val |= (1 << DSC_PPS_UPD_SHIFT); 3404baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 340512ee5af0SDamon Ding 340612ee5af0SDamon Ding printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n", 340712ee5af0SDamon Ding dsc_id, 340812ee5af0SDamon Ding cstate->dsc_txp_clk_rate, dsc_txp_clk_div, 340912ee5af0SDamon Ding cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div, 341012ee5af0SDamon Ding cstate->dsc_cds_clk_rate, dsc_cds_clk_div); 341112ee5af0SDamon Ding } 341212ee5af0SDamon Ding 34135f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev) 34145f1357a2SZhang Yubing { 34155f1357a2SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 34165f1357a2SZhang Yubing struct vop2 *vop2 = cstate->private; 34175f1357a2SZhang Yubing struct udevice *vp_dev, *dev; 34185f1357a2SZhang Yubing struct ofnode_phandle_args args; 34195f1357a2SZhang Yubing char vp_name[10]; 34205f1357a2SZhang Yubing int ret; 34215f1357a2SZhang Yubing 34225f1357a2SZhang Yubing if (vop2->version != VOP_VERSION_RK3588) 34235f1357a2SZhang Yubing return false; 34245f1357a2SZhang Yubing 34255f1357a2SZhang Yubing sprintf(vp_name, "port@%d", cstate->crtc_id); 34265f1357a2SZhang Yubing if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) { 34275e85f4a7SZhang Yubing debug("warn: can't get vp device\n"); 34285f1357a2SZhang Yubing return false; 34295f1357a2SZhang Yubing } 34305f1357a2SZhang Yubing 34315f1357a2SZhang Yubing ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0, 34325f1357a2SZhang Yubing 0, &args); 34335f1357a2SZhang Yubing if (ret) { 34345e85f4a7SZhang Yubing debug("assigned-clock-parents's node not define\n"); 34355f1357a2SZhang Yubing return false; 34365f1357a2SZhang Yubing } 34375f1357a2SZhang Yubing 34385f1357a2SZhang Yubing if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) { 34395e85f4a7SZhang Yubing debug("warn: can't get clk device\n"); 34405f1357a2SZhang Yubing return false; 34415f1357a2SZhang Yubing } 34425f1357a2SZhang Yubing 34435f1357a2SZhang Yubing if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) { 34445f1357a2SZhang Yubing printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name); 34455f1357a2SZhang Yubing if (clk_dev) 34465f1357a2SZhang Yubing *clk_dev = dev; 34475f1357a2SZhang Yubing return true; 34485f1357a2SZhang Yubing } 34495f1357a2SZhang Yubing 34505f1357a2SZhang Yubing return false; 34515f1357a2SZhang Yubing } 34525f1357a2SZhang Yubing 3453ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state) 3454ecc31b6eSAndy Yan { 3455ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3456c2b1fe35SDamon Ding struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id]; 3457ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3458ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3459ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 3460ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 3461ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 3462ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal; 3463ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 3464ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay; 3465ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay; 3466ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal; 3467ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 3468ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 3469ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay; 3470ecc31b6eSAndy Yan bool yuv_overlay = false; 3471ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 347266724b9cSDamon Ding u32 line_flag_offset = (cstate->crtc_id * 4); 347366724b9cSDamon Ding u32 val, act_end; 3474ecc31b6eSAndy Yan u8 dither_down_en = 0; 3475452afb13SDamon Ding u8 dither_down_mode = 0; 3476ecc31b6eSAndy Yan u8 pre_dither_down_en = 0; 3477edfef528SDamon Ding u8 dclk_div_factor = 0; 3478ecc31b6eSAndy Yan char output_type_name[30] = {0}; 3479ecc31b6eSAndy Yan char dclk_name[9]; 3480ecc31b6eSAndy Yan struct clk dclk; 3481b890760eSAlgea Cao struct clk hdmi0_phy_pll; 3482b890760eSAlgea Cao struct clk hdmi1_phy_pll; 34835f1357a2SZhang Yubing struct clk hdmi_phy_pll; 34843e05a7b8SZhang Yubing struct udevice *disp_dev; 34855fa6e665SDamon Ding unsigned long dclk_rate = 0; 3486ecc31b6eSAndy Yan int ret; 3487ecc31b6eSAndy Yan 3488ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 348971ac76f7SDamon Ding mode->crtc_hdisplay, mode->vdisplay, 3490ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 34915e85f4a7SZhang Yubing mode->vrefresh, 3492ecc31b6eSAndy Yan get_output_if_name(conn_state->output_if, output_type_name), 3493ecc31b6eSAndy Yan cstate->crtc_id); 3494ecc31b6eSAndy Yan 3495ee01dbb2SDamon Ding if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { 3496ee01dbb2SDamon Ding cstate->splice_mode = true; 3497ee01dbb2SDamon Ding cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id; 3498ee01dbb2SDamon Ding if (!cstate->splice_crtc_id) { 3499ee01dbb2SDamon Ding printf("%s: Splice mode is unsupported by vp%d\n", 3500ee01dbb2SDamon Ding __func__, cstate->crtc_id); 3501ee01dbb2SDamon Ding return -EINVAL; 3502ee01dbb2SDamon Ding } 3503b70b2d79SDamon Ding 3504b70b2d79SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK, 3505b70b2d79SDamon Ding PORT_MERGE_EN_SHIFT, 1, false); 3506ee01dbb2SDamon Ding } 3507ee01dbb2SDamon Ding 3508cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 3509cd6c85a9SDamon Ding RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false); 3510cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 3511cd6c85a9SDamon Ding RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false); 3512cd6c85a9SDamon Ding 3513ecc31b6eSAndy Yan vop2_initial(vop2, state); 3514ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 3515ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state); 35165fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3568) 3517ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state); 35185fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3528) 35195fa6e665SDamon Ding dclk_rate = rk3528_vop2_if_cfg(state); 3520452afb13SDamon Ding else if (vop2->version == VOP_VERSION_RK3562) 3521452afb13SDamon Ding dclk_rate = rk3562_vop2_if_cfg(state); 3522ecc31b6eSAndy Yan 352363cb669fSSandy Huang if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 352463cb669fSSandy Huang !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) 35257bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 35267bdd0eb6SSandy Huang 352765747de7SDamon Ding vop2_post_color_swap(state); 352810ee9f5bSAlgea Cao 3529d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 3530d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false); 3531d0408543SAndy Yan 3532d0408543SAndy Yan switch (conn_state->bus_format) { 3533d0408543SAndy Yan case MEDIA_BUS_FMT_RGB565_1X16: 3534d0408543SAndy Yan dither_down_en = 1; 3535452afb13SDamon Ding dither_down_mode = RGB888_TO_RGB565; 3536452afb13SDamon Ding pre_dither_down_en = 1; 3537d0408543SAndy Yan break; 3538d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X18: 3539d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 3540d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 3541d0408543SAndy Yan case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: 3542d0408543SAndy Yan dither_down_en = 1; 3543452afb13SDamon Ding dither_down_mode = RGB888_TO_RGB666; 3544452afb13SDamon Ding pre_dither_down_en = 1; 3545d0408543SAndy Yan break; 3546d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 3547d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 3548d0408543SAndy Yan dither_down_en = 0; 3549d0408543SAndy Yan pre_dither_down_en = 1; 3550d0408543SAndy Yan break; 3551d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 3552d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 3553452afb13SDamon Ding dither_down_en = 0; 3554452afb13SDamon Ding pre_dither_down_en = 0; 3555452afb13SDamon Ding break; 3556d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X24: 3557d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 3558d0408543SAndy Yan case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 3559d0408543SAndy Yan default: 3560d0408543SAndy Yan dither_down_en = 0; 3561452afb13SDamon Ding pre_dither_down_en = 1; 3562d0408543SAndy Yan break; 3563d0408543SAndy Yan } 3564d0408543SAndy Yan 3565d0408543SAndy Yan if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA) 3566d0408543SAndy Yan pre_dither_down_en = 0; 3567d0408543SAndy Yan else 3568d0408543SAndy Yan pre_dither_down_en = 1; 3569d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3570d0408543SAndy Yan DITHER_DOWN_EN_SHIFT, dither_down_en, false); 3571d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3572d0408543SAndy Yan PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 3573452afb13SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3574452afb13SDamon Ding DITHER_DOWN_MODE_SHIFT, dither_down_mode, false); 3575d0408543SAndy Yan 3576d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 3577d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 3578d0408543SAndy Yan yuv_overlay, false); 3579d0408543SAndy Yan 3580d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay; 3581d0408543SAndy Yan 3582d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 3583d0408543SAndy Yan (htotal << 16) | hsync_len); 3584d0408543SAndy Yan val = hact_st << 16; 3585d0408543SAndy Yan val |= hact_end; 3586d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 3587d0408543SAndy Yan val = vact_st << 16; 3588d0408543SAndy Yan val |= vact_end; 3589d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 3590d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 3591d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 3592d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay; 3593d0408543SAndy Yan 3594d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 3595d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 3596d0408543SAndy Yan val); 3597d0408543SAndy Yan 3598d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len); 3599d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 3600d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3601d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false); 3602d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 36037a20be36SSandy Huang DSP_FILED_POL, 1, false); 36047a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3605d0408543SAndy Yan P2I_EN_SHIFT, 1, false); 3606d0408543SAndy Yan vtotal += vtotal + 1; 360766724b9cSDamon Ding act_end = vact_end_f1; 3608d0408543SAndy Yan } else { 3609d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3610d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false); 3611d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3612d0408543SAndy Yan P2I_EN_SHIFT, 0, false); 361366724b9cSDamon Ding act_end = vact_end; 3614d0408543SAndy Yan } 3615d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 3616d0408543SAndy Yan (vtotal << 16) | vsync_len); 361767be2ffcSDamon Ding 36185fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3528) { 361967be2ffcSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || 362067be2ffcSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 3621d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 362267be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 1, false); 362367be2ffcSDamon Ding else 362467be2ffcSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 362567be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 0, false); 362667be2ffcSDamon Ding } 362710ee9f5bSAlgea Cao 362810ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 362963cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 363063cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 363110ee9f5bSAlgea Cao else 363263cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 363363cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 363410ee9f5bSAlgea Cao 3635ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 3636ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false); 3637ee01dbb2SDamon Ding 363810ee9f5bSAlgea Cao if (yuv_overlay) 363910ee9f5bSAlgea Cao val = 0x20010200; 364010ee9f5bSAlgea Cao else 364110ee9f5bSAlgea Cao val = 0; 364210ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 3643b70b2d79SDamon Ding if (cstate->splice_mode) { 3644ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 3645ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id, 3646ee01dbb2SDamon Ding yuv_overlay, false); 3647ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val); 3648ee01dbb2SDamon Ding } 364910ee9f5bSAlgea Cao 365010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 365110ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 3652d0408543SAndy Yan 3653c2b1fe35SDamon Ding if (vp->xmirror_en) 3654c2b1fe35SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3655c2b1fe35SDamon Ding DSP_X_MIR_EN_SHIFT, 1, false); 3656c2b1fe35SDamon Ding 3657ac500a1fSSandy Huang vop2_tv_config_update(state, vop2); 3658d0408543SAndy Yan vop2_post_config(state, vop2); 36596027c871SZhang Yubing if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) 36606027c871SZhang Yubing vop3_post_config(state, vop2); 3661d0408543SAndy Yan 366212ee5af0SDamon Ding if (cstate->dsc_enable) { 366312ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 36641ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL); 36651ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL); 366612ee5af0SDamon Ding } else { 36671ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL); 366812ee5af0SDamon Ding } 366912ee5af0SDamon Ding } 367012ee5af0SDamon Ding 3671ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 3672ecc31b6eSAndy Yan ret = clk_get_by_name(cstate->dev, dclk_name, &dclk); 3673b890760eSAlgea Cao if (ret) { 3674b890760eSAlgea Cao printf("%s: Failed to get dclk ret=%d\n", __func__, ret); 3675b890760eSAlgea Cao return ret; 3676b890760eSAlgea Cao } 3677b890760eSAlgea Cao 36783e05a7b8SZhang Yubing ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev); 36793e05a7b8SZhang Yubing if (!ret) { 36803e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll); 36813e05a7b8SZhang Yubing if (ret) 36825e85f4a7SZhang Yubing debug("%s: hdmi0_phy_pll may not define\n", __func__); 36833e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll); 36843e05a7b8SZhang Yubing if (ret) 36855e85f4a7SZhang Yubing debug("%s: hdmi1_phy_pll may not define\n", __func__); 36863e05a7b8SZhang Yubing } else { 3687b890760eSAlgea Cao hdmi0_phy_pll.dev = NULL; 3688545a0218SAlgea Cao hdmi1_phy_pll.dev = NULL; 36895e85f4a7SZhang Yubing debug("%s: Faile to find display-subsystem node\n", __func__); 3690b890760eSAlgea Cao } 3691b890760eSAlgea Cao 3692ebbd144cSAlgea Cao if (vop2->version == VOP_VERSION_RK3528) { 3693ebbd144cSAlgea Cao struct ofnode_phandle_args args; 3694ebbd144cSAlgea Cao 3695ebbd144cSAlgea Cao ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents", 3696ebbd144cSAlgea Cao "#clock-cells", 0, 0, &args); 3697ebbd144cSAlgea Cao if (!ret) { 3698ebbd144cSAlgea Cao ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev); 3699ebbd144cSAlgea Cao if (ret) { 3700ebbd144cSAlgea Cao debug("warn: can't get clk device\n"); 3701ebbd144cSAlgea Cao return ret; 3702ebbd144cSAlgea Cao } 3703ebbd144cSAlgea Cao } else { 3704ebbd144cSAlgea Cao debug("assigned-clock-parents's node not define\n"); 3705ebbd144cSAlgea Cao } 3706ebbd144cSAlgea Cao } 3707ebbd144cSAlgea Cao 37080a1fb152SZhang Yubing if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) { 3709b890760eSAlgea Cao if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) 3710b890760eSAlgea Cao vop2_clk_set_parent(&dclk, &hdmi0_phy_pll); 3711b890760eSAlgea Cao else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1) 3712b890760eSAlgea Cao vop2_clk_set_parent(&dclk, &hdmi1_phy_pll); 3713b890760eSAlgea Cao 3714b890760eSAlgea Cao /* 3715b890760eSAlgea Cao * uboot clk driver won't set dclk parent's rate when use 3716b890760eSAlgea Cao * hdmi phypll as dclk source. 3717b890760eSAlgea Cao * So set dclk rate is meaningless. Set hdmi phypll rate 3718b890760eSAlgea Cao * directly. 3719b890760eSAlgea Cao */ 37205f1357a2SZhang Yubing if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) { 3721b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate * 1000); 37225f1357a2SZhang Yubing } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) { 3723b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate * 1000); 37245f1357a2SZhang Yubing } else { 37257efea85dSDamon Ding if (is_extend_pll(state, &hdmi_phy_pll.dev)) { 37265f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 37277efea85dSDamon Ding } else { 37287efea85dSDamon Ding /* 37297efea85dSDamon Ding * For RK3528, the path of CVBS output is like: 37307efea85dSDamon Ding * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC 37317efea85dSDamon Ding * The vop2 dclk should be four times crtc_clock for CVBS sampling 37327efea85dSDamon Ding * clock needs. 37337efea85dSDamon Ding */ 37347efea85dSDamon Ding if (vop2->version == VOP_VERSION_RK3528 && 37357efea85dSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 37367efea85dSDamon Ding ret = vop2_clk_set_rate(&dclk, 4 * dclk_rate * 1000); 3737b890760eSAlgea Cao else 3738b890760eSAlgea Cao ret = vop2_clk_set_rate(&dclk, dclk_rate * 1000); 37395f1357a2SZhang Yubing } 37407efea85dSDamon Ding } 3741631ee99aSZhang Yubing } else { 37425f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev)) 37435f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 37445f1357a2SZhang Yubing else 3745631ee99aSZhang Yubing ret = vop2_clk_set_rate(&dclk, dclk_rate * 1000); 3746edfef528SDamon Ding } 374763638f32SDamon Ding 374863638f32SDamon Ding if (IS_ERR_VALUE(ret)) { 374963638f32SDamon Ding printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 375063638f32SDamon Ding __func__, cstate->crtc_id, dclk_rate, ret); 375163638f32SDamon Ding return ret; 375263638f32SDamon Ding } else { 3753edfef528SDamon Ding dclk_div_factor = mode->clock / dclk_rate; 37545fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && 37555fa6e665SDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 37565fa6e665SDamon Ding mode->crtc_clock = ret / 4 / 1000; 37575fa6e665SDamon Ding else 3758edfef528SDamon Ding mode->crtc_clock = ret * dclk_div_factor / 1000; 3759edfef528SDamon Ding printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); 3760631ee99aSZhang Yubing } 3761ecc31b6eSAndy Yan 376266724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 3763e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false); 376466724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 3765e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false); 376666724b9cSDamon Ding 3767d0408543SAndy Yan return 0; 3768d0408543SAndy Yan } 3769d0408543SAndy Yan 3770ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 37713e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w, 37723e39a5a1SSandy Huang uint32_t dst_h) 37733e39a5a1SSandy Huang { 37743e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 37753e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode; 37765fa6e665SDamon Ding uint8_t xgt2 = 0, xgt4 = 0; 37775fa6e665SDamon Ding uint8_t ygt2 = 0, ygt4 = 0; 37783e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0; 3779ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 37805fa6e665SDamon Ding bool xgt_en = false; 37815fa6e665SDamon Ding bool xavg_en = false; 37823e39a5a1SSandy Huang 37835fa6e665SDamon Ding if (is_vop3(vop2)) { 37845fa6e665SDamon Ding if (src_w >= (4 * dst_w)) { 37855fa6e665SDamon Ding xgt4 = 1; 37865fa6e665SDamon Ding src_w >>= 2; 37875fa6e665SDamon Ding } else if (src_w >= (2 * dst_w)) { 37885fa6e665SDamon Ding xgt2 = 1; 37895fa6e665SDamon Ding src_w >>= 1; 37905fa6e665SDamon Ding } 37915fa6e665SDamon Ding } 37923e39a5a1SSandy Huang 37935fa6e665SDamon Ding if (src_h >= (4 * dst_h)) { 37945fa6e665SDamon Ding ygt4 = 1; 37953e39a5a1SSandy Huang src_h >>= 2; 37965fa6e665SDamon Ding } else if (src_h >= (2 * dst_h)) { 37975fa6e665SDamon Ding ygt2 = 1; 37983e39a5a1SSandy Huang src_h >>= 1; 37995fa6e665SDamon Ding } 38003e39a5a1SSandy Huang 38013e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 38023e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 38033e39a5a1SSandy Huang 38043e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP) 38055fa6e665SDamon Ding hscl_filter_mode = win->hsu_filter_mode; 38063e39a5a1SSandy Huang else 38075fa6e665SDamon Ding hscl_filter_mode = win->hsd_filter_mode; 38083e39a5a1SSandy Huang 38093e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP) 38105fa6e665SDamon Ding vscl_filter_mode = win->vsu_filter_mode; 38113e39a5a1SSandy Huang else 38125fa6e665SDamon Ding vscl_filter_mode = win->vsd_filter_mode; 38133e39a5a1SSandy Huang 38143e39a5a1SSandy Huang /* 38153e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel 38163e39a5a1SSandy Huang * at scale down mode 38173e39a5a1SSandy Huang */ 38185fa6e665SDamon Ding if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) { 38193e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 38203e39a5a1SSandy Huang dst_w += 1; 38213e39a5a1SSandy Huang } 38223e39a5a1SSandy Huang 38235fa6e665SDamon Ding if (is_vop3(vop2)) { 38245fa6e665SDamon Ding xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true); 38255fa6e665SDamon Ding yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false); 38265fa6e665SDamon Ding 38275fa6e665SDamon Ding if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG) 38285fa6e665SDamon Ding xavg_en = xgt2 || xgt4; 38295fa6e665SDamon Ding else 38305fa6e665SDamon Ding xgt_en = xgt2 || xgt4; 38315fa6e665SDamon Ding } else { 38323e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 38333e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 38345fa6e665SDamon Ding } 3835ecc31b6eSAndy Yan 3836ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) { 3837ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 3838ecc31b6eSAndy Yan yfac << 16 | xfac); 3839ecc31b6eSAndy Yan 38405fa6e665SDamon Ding if (is_vop3(vop2)) { 3841ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38425fa6e665SDamon Ding EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false); 3843ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38445fa6e665SDamon Ding EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false); 38455fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38465fa6e665SDamon Ding XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 3847ecc31b6eSAndy Yan 3848ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38495fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT, 38505fa6e665SDamon Ding yrgb_hor_scl_mode, false); 3851ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38525fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT, 38535fa6e665SDamon Ding yrgb_ver_scl_mode, false); 38545fa6e665SDamon Ding } else { 38555fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38565fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT, 38575fa6e665SDamon Ding yrgb_hor_scl_mode, false); 38585fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38595fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT, 38605fa6e665SDamon Ding yrgb_ver_scl_mode, false); 38615fa6e665SDamon Ding } 3862ecc31b6eSAndy Yan 38635fa6e665SDamon Ding if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) { 38645fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38655fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false); 38665fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38675fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false); 38685fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38695fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false); 38705fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38715fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false); 38725fa6e665SDamon Ding } else { 38735fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38745fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false); 38755fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38765fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false); 38775fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38785fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false); 38795fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 38805fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false); 38815fa6e665SDamon Ding } 3882ecc31b6eSAndy Yan } else { 38833e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 38843e39a5a1SSandy Huang yfac << 16 | xfac); 38853e39a5a1SSandy Huang 38865fa6e665SDamon Ding if (is_vop3(vop2)) { 388734a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 38885fa6e665SDamon Ding EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false); 388934a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 38905fa6e665SDamon Ding EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false); 38915fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 38925fa6e665SDamon Ding XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 38935fa6e665SDamon Ding } 38945fa6e665SDamon Ding 38955fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 38965fa6e665SDamon Ding YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false); 38975fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 38985fa6e665SDamon Ding YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false); 38993e39a5a1SSandy Huang 39003e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39013e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 39023e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39033e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 39043e39a5a1SSandy Huang 39053e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39063e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 39073e39a5a1SSandy Huang hscl_filter_mode, false); 39083e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 39093e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 39103e39a5a1SSandy Huang vscl_filter_mode, false); 39113e39a5a1SSandy Huang } 3912ecc31b6eSAndy Yan } 39133e39a5a1SSandy Huang 3914a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win) 3915a33b790fSDamon Ding { 3916a33b790fSDamon Ding u32 win_offset = win->reg_offset; 3917a33b790fSDamon Ding 3918a33b790fSDamon Ding if (win->type == CLUSTER_LAYER) { 3919a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK, 3920a33b790fSDamon Ding CLUSTER_AXI_ID_SHIFT, win->axi_id, false); 3921a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK, 3922a33b790fSDamon Ding CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 3923a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK, 3924a33b790fSDamon Ding CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 3925a33b790fSDamon Ding } else { 3926a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK, 3927a33b790fSDamon Ding ESMART_AXI_ID_SHIFT, win->axi_id, false); 3928a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK, 3929a33b790fSDamon Ding ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 3930a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK, 3931a33b790fSDamon Ding ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 3932a33b790fSDamon Ding } 3933a33b790fSDamon Ding } 3934a33b790fSDamon Ding 3935ecc31b6eSAndy Yan static void vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 3936d0408543SAndy Yan { 3937d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 3938d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 3939d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3940d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 3941ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 3942ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 3943ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 3944ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 3945ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 3946ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 3947d0408543SAndy Yan int xvir = cstate->xvir; 3948d0408543SAndy Yan int y_mirror = 0; 394910ee9f5bSAlgea Cao int csc_mode; 3950ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 3951ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 3952ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 3953ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 3954ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 3955ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 3956d0408543SAndy Yan 3957ee01dbb2SDamon Ding if (win->splice_mode_right) { 3958ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 3959ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 3960ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 3961ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 3962ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 3963ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 3964ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 3965ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 3966ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 3967ee01dbb2SDamon Ding } 3968ee01dbb2SDamon Ding 3969ecc31b6eSAndy Yan act_info = (src_h - 1) << 16; 3970ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff; 3971ecc31b6eSAndy Yan 3972ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16; 3973ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 3974ecc31b6eSAndy Yan 3975ecc31b6eSAndy Yan dsp_stx = crtc_x; 3976ecc31b6eSAndy Yan dsp_sty = crtc_y; 3977ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 3978ecc31b6eSAndy Yan 3979ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 3980ecc31b6eSAndy Yan y_mirror = 1; 3981ecc31b6eSAndy Yan else 3982ecc31b6eSAndy Yan y_mirror = 0; 3983ecc31b6eSAndy Yan 3984ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 3985ecc31b6eSAndy Yan 3986452afb13SDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 || 3987452afb13SDamon Ding vop2->version == VOP_VERSION_RK3562) 3988a33b790fSDamon Ding vop2_axi_config(vop2, win); 3989a33b790fSDamon Ding 3990ecc31b6eSAndy Yan if (y_mirror) 3991ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n"); 3992ecc31b6eSAndy Yan 3993ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 3994ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 3995ecc31b6eSAndy Yan false); 3996ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 3997ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, 3998ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 3999ecc31b6eSAndy Yan 4000ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 4001ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 4002ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 4003ecc31b6eSAndy Yan 4004ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 4005ecc31b6eSAndy Yan 40065fa6e665SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 4007ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 4008ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT, 4009ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false); 4010ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 4011ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 4012ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 4013ecc31b6eSAndy Yan 4014ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4015d0408543SAndy Yan } 4016d0408543SAndy Yan 4017ecc31b6eSAndy Yan static void vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 4018ecc31b6eSAndy Yan { 4019ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4020ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 4021ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 4022ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4023ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 4024ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 4025ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 4026ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 4027ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 4028ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 4029ecc31b6eSAndy Yan int xvir = cstate->xvir; 4030ecc31b6eSAndy Yan int y_mirror = 0; 4031ecc31b6eSAndy Yan int csc_mode; 4032ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 4033ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 4034ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 4035ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 4036ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 4037ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4038ecc31b6eSAndy Yan 4039ee01dbb2SDamon Ding if (win->splice_mode_right) { 4040ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 4041ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 4042ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 4043ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 4044ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 4045ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 4046ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 4047ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 4048ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4049ee01dbb2SDamon Ding } 4050ee01dbb2SDamon Ding 405174bd8269SSandy Huang /* 405274bd8269SSandy Huang * This is workaround solution for IC design: 405374bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1. 405474bd8269SSandy Huang */ 405574bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) { 405674bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 405774bd8269SSandy Huang src_w -= 1; 405874bd8269SSandy Huang } 405974bd8269SSandy Huang 4060d0408543SAndy Yan act_info = (src_h - 1) << 16; 4061d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff; 4062d0408543SAndy Yan 4063d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16; 4064d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 4065d0408543SAndy Yan 4066d0408543SAndy Yan dsp_stx = crtc_x; 4067d0408543SAndy Yan dsp_sty = crtc_y; 4068d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 4069d0408543SAndy Yan 4070d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 4071d0408543SAndy Yan y_mirror = 1; 4072d0408543SAndy Yan else 4073d0408543SAndy Yan y_mirror = 0; 4074d0408543SAndy Yan 40755fa6e665SDamon Ding if (is_vop3(vop2)) 40765fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, ESMART_LB_SELECT_MASK, 40775fa6e665SDamon Ding ESMART_LB_SELECT_SHIFT, win->scale_engine_num, false); 40785fa6e665SDamon Ding 4079ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 40803e39a5a1SSandy Huang 4081452afb13SDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 || 4082452afb13SDamon Ding vop2->version == VOP_VERSION_RK3562) 4083a33b790fSDamon Ding vop2_axi_config(vop2, win); 4084a33b790fSDamon Ding 4085d0408543SAndy Yan if (y_mirror) 4086d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4; 4087d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 4088d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false); 4089d0408543SAndy Yan 4090d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 4091d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 4092d0408543SAndy Yan false); 4093d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 4094d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 4095ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 4096d0408543SAndy Yan 4097d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 4098d0408543SAndy Yan act_info); 4099d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 4100d0408543SAndy Yan dsp_info); 4101d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 4102d0408543SAndy Yan 4103d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 4104d0408543SAndy Yan WIN_EN_SHIFT, 1, false); 4105d0408543SAndy Yan 41065fa6e665SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 410710ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 410810ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT, 410910ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false); 411010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 411110ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false); 411210ee9f5bSAlgea Cao 4113d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4114ecc31b6eSAndy Yan } 4115ecc31b6eSAndy Yan 4116ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state) 4117ee01dbb2SDamon Ding { 4118ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 4119ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 4120ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 4121ee01dbb2SDamon Ding struct display_rect *src_rect = &cstate->src_rect; 4122ee01dbb2SDamon Ding struct display_rect *dst_rect = &cstate->crtc_rect; 4123ee01dbb2SDamon Ding struct display_rect left_src, left_dst, right_src, right_dst; 4124ee01dbb2SDamon Ding u16 half_hdisplay = mode->crtc_hdisplay >> 1; 4125ee01dbb2SDamon Ding int left_src_w, left_dst_w, right_dst_w; 4126ee01dbb2SDamon Ding 4127ee01dbb2SDamon Ding left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x; 4128ee01dbb2SDamon Ding if (left_dst_w < 0) 4129ee01dbb2SDamon Ding left_dst_w = 0; 4130ee01dbb2SDamon Ding right_dst_w = dst_rect->w - left_dst_w; 4131ee01dbb2SDamon Ding 4132ee01dbb2SDamon Ding if (!right_dst_w) 4133ee01dbb2SDamon Ding left_src_w = src_rect->w; 4134ee01dbb2SDamon Ding else 41350df0fd39SSandy Huang left_src_w = src_rect->x + src_rect->w - src_rect->w / 2; 4136ee01dbb2SDamon Ding 4137ee01dbb2SDamon Ding left_src.x = src_rect->x; 4138ee01dbb2SDamon Ding left_src.w = left_src_w; 4139ee01dbb2SDamon Ding left_dst.x = dst_rect->x; 4140ee01dbb2SDamon Ding left_dst.w = left_dst_w; 4141ee01dbb2SDamon Ding right_src.x = left_src.x + left_src.w; 4142ee01dbb2SDamon Ding right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w; 4143ee01dbb2SDamon Ding right_dst.x = dst_rect->x + left_dst_w - half_hdisplay; 4144ee01dbb2SDamon Ding right_dst.w = right_dst_w; 4145ee01dbb2SDamon Ding 4146ee01dbb2SDamon Ding left_src.y = src_rect->y; 4147ee01dbb2SDamon Ding left_src.h = src_rect->h; 4148ee01dbb2SDamon Ding left_dst.y = dst_rect->y; 4149ee01dbb2SDamon Ding left_dst.h = dst_rect->h; 4150ee01dbb2SDamon Ding right_src.y = src_rect->y; 4151ee01dbb2SDamon Ding right_src.h = src_rect->h; 4152ee01dbb2SDamon Ding right_dst.y = dst_rect->y; 4153ee01dbb2SDamon Ding right_dst.h = dst_rect->h; 4154ee01dbb2SDamon Ding 4155ee01dbb2SDamon Ding memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect)); 4156ee01dbb2SDamon Ding memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect)); 4157ee01dbb2SDamon Ding memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect)); 4158ee01dbb2SDamon Ding memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect)); 4159ee01dbb2SDamon Ding } 4160ee01dbb2SDamon Ding 4161ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state) 4162ecc31b6eSAndy Yan { 4163ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4164ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4165ecc31b6eSAndy Yan struct vop2_win_data *win_data; 4166ee01dbb2SDamon Ding struct vop2_win_data *splice_win_data; 4167ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 4168ecc31b6eSAndy Yan char plane_name[10] = {0}; 4169ecc31b6eSAndy Yan 4170ee01dbb2SDamon Ding if (cstate->crtc_rect.w > cstate->max_output.width) { 4171ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n", 4172ee01dbb2SDamon Ding cstate->crtc_rect.w, cstate->max_output.width); 4173ecc31b6eSAndy Yan return -EINVAL; 4174ecc31b6eSAndy Yan } 4175ecc31b6eSAndy Yan 4176ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 4177ecc31b6eSAndy Yan if (!win_data) { 4178ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id); 4179ecc31b6eSAndy Yan return -ENODEV; 4180ecc31b6eSAndy Yan } 4181ecc31b6eSAndy Yan 41825fa6e665SDamon Ding /* ignore some plane register according vop3 esmart lb mode */ 41835fa6e665SDamon Ding if (vop3_ignore_plane(vop2, win_data)) 41845fa6e665SDamon Ding return -EACCES; 41855fa6e665SDamon Ding 4186b6ba80b4SDamon Ding if (vop2->version == VOP_VERSION_RK3588) { 4187b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, win_data->pd_id)) 4188b6ba80b4SDamon Ding printf("open vp%d plane pd fail\n", cstate->crtc_id); 4189b6ba80b4SDamon Ding } 4190b6ba80b4SDamon Ding 4191ee01dbb2SDamon Ding if (cstate->splice_mode) { 4192ee01dbb2SDamon Ding if (win_data->splice_win_id) { 4193ee01dbb2SDamon Ding splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id); 4194ee01dbb2SDamon Ding splice_win_data->splice_mode_right = true; 4195b6ba80b4SDamon Ding 4196b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, splice_win_data->pd_id)) 4197b6ba80b4SDamon Ding printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id); 4198b6ba80b4SDamon Ding 4199ee01dbb2SDamon Ding vop2_calc_display_rect_for_splice(state); 4200ee01dbb2SDamon Ding if (win_data->type == CLUSTER_LAYER) 4201ee01dbb2SDamon Ding vop2_set_cluster_win(state, splice_win_data); 4202ee01dbb2SDamon Ding else 4203ee01dbb2SDamon Ding vop2_set_smart_win(state, splice_win_data); 4204ee01dbb2SDamon Ding } else { 4205ee01dbb2SDamon Ding printf("ERROR: splice mode is unsupported by plane %s\n", 4206ee01dbb2SDamon Ding get_plane_name(primary_plane_id, plane_name)); 4207ee01dbb2SDamon Ding return -EINVAL; 4208ee01dbb2SDamon Ding } 4209ee01dbb2SDamon Ding } 4210ee01dbb2SDamon Ding 4211ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER) 4212ecc31b6eSAndy Yan vop2_set_cluster_win(state, win_data); 4213ecc31b6eSAndy Yan else 4214ecc31b6eSAndy Yan vop2_set_smart_win(state, win_data); 42158895aec1SSandy Huang 42168895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 42178895aec1SSandy Huang cstate->crtc_id, get_plane_name(primary_plane_id, plane_name), 4218ee01dbb2SDamon Ding cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h, 4219ee01dbb2SDamon Ding cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format, 42208895aec1SSandy Huang cstate->dma_addr); 42218895aec1SSandy Huang 4222d0408543SAndy Yan return 0; 4223d0408543SAndy Yan } 4224d0408543SAndy Yan 4225d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state) 4226d0408543SAndy Yan { 4227d0408543SAndy Yan return 0; 4228d0408543SAndy Yan } 4229d0408543SAndy Yan 423012ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state) 423112ee5af0SDamon Ding { 423212ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 423312ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 423412ee5af0SDamon Ding struct vop2 *vop2 = cstate->private; 423512ee5af0SDamon Ding u8 dsc_id = cstate->dsc_id; 423612ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 423712ee5af0SDamon Ding 423812ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 423912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK, 424012ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 424112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK, 424212ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 424312ee5af0SDamon Ding } else { 424412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK, 424512ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 424612ee5af0SDamon Ding } 424712ee5af0SDamon Ding } 424812ee5af0SDamon Ding 4249d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state) 4250d0408543SAndy Yan { 4251d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 4252d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 425352ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 4254ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4255d0408543SAndy Yan 4256d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4257d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false); 4258ee01dbb2SDamon Ding 4259ee01dbb2SDamon Ding if (cstate->splice_mode) 4260ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4261ee01dbb2SDamon Ding 4262d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4263d0408543SAndy Yan 426412ee5af0SDamon Ding if (cstate->dsc_enable) 426512ee5af0SDamon Ding vop2_dsc_cfg_done(state); 426612ee5af0SDamon Ding 4267d0408543SAndy Yan return 0; 4268d0408543SAndy Yan } 4269d0408543SAndy Yan 4270d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state) 4271d0408543SAndy Yan { 4272d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 4273d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 427452ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 4275ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4276d0408543SAndy Yan 4277d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4278d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false); 4279ee01dbb2SDamon Ding 4280ee01dbb2SDamon Ding if (cstate->splice_mode) 4281ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4282ee01dbb2SDamon Ding 4283d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4284d0408543SAndy Yan 4285d0408543SAndy Yan return 0; 4286d0408543SAndy Yan } 4287d0408543SAndy Yan 4288ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 4289ee008497SSandy Huang { 4290ee008497SSandy Huang struct crtc_state *cstate = &state->crtc_state; 4291ee008497SSandy Huang struct vop2 *vop2 = cstate->private; 4292ee008497SSandy Huang int i = 0; 4293ee008497SSandy Huang int correct_cursor_plane = -1; 4294ee008497SSandy Huang int plane_type = -1; 4295ee008497SSandy Huang 4296ee008497SSandy Huang if (cursor_plane < 0) 4297ee008497SSandy Huang return -1; 4298ee008497SSandy Huang 4299ee008497SSandy Huang if (plane_mask & (1 << cursor_plane)) 4300ee008497SSandy Huang return cursor_plane; 4301ee008497SSandy Huang 4302ee008497SSandy Huang /* Get current cursor plane type */ 4303ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 4304ee008497SSandy Huang if (vop2->data->plane_table[i].plane_id == cursor_plane) { 4305ee008497SSandy Huang plane_type = vop2->data->plane_table[i].plane_type; 4306ee008497SSandy Huang break; 4307ee008497SSandy Huang } 4308ee008497SSandy Huang } 4309ee008497SSandy Huang 4310ee008497SSandy Huang /* Get the other same plane type plane id */ 4311ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 4312ee008497SSandy Huang if (vop2->data->plane_table[i].plane_type == plane_type && 4313ee008497SSandy Huang vop2->data->plane_table[i].plane_id != cursor_plane) { 4314ee008497SSandy Huang correct_cursor_plane = vop2->data->plane_table[i].plane_id; 4315ee008497SSandy Huang break; 4316ee008497SSandy Huang } 4317ee008497SSandy Huang } 4318ee008497SSandy Huang 4319ee008497SSandy Huang /* To check whether the new correct_cursor_plane is attach to current vp */ 4320ee008497SSandy Huang if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 4321ee008497SSandy Huang printf("error: faild to find correct plane as cursor plane\n"); 4322ee008497SSandy Huang return -1; 4323ee008497SSandy Huang } 4324ee008497SSandy Huang 4325ee008497SSandy Huang printf("vp%d adjust cursor plane from %d to %d\n", 4326ee008497SSandy Huang cstate->crtc_id, cursor_plane, correct_cursor_plane); 4327ee008497SSandy Huang 4328ee008497SSandy Huang return correct_cursor_plane; 4329ee008497SSandy Huang } 4330ee008497SSandy Huang 4331b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 4332b0989546SSandy Huang { 4333b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 4334b0989546SSandy Huang struct vop2 *vop2 = cstate->private; 4335b0989546SSandy Huang ofnode vp_node; 4336b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node; 4337b0989546SSandy Huang static bool vop_fix_dts; 4338b0989546SSandy Huang const char *path; 4339b0989546SSandy Huang u32 plane_mask = 0; 4340b0989546SSandy Huang int vp_id = 0; 4341ee008497SSandy Huang int cursor_plane_id = -1; 4342b0989546SSandy Huang 43435fa6e665SDamon Ding if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528) 4344b0989546SSandy Huang return 0; 4345b0989546SSandy Huang 4346b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 4347b0989546SSandy Huang path = vp_node.np->full_name; 4348b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 4349b0989546SSandy Huang 43508b1fe597SSandy Huang if (cstate->crtc->assign_plane) 43518b1fe597SSandy Huang continue; 4352ee008497SSandy Huang cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 4353ee008497SSandy Huang cstate->crtc->vps[vp_id].cursor_plane); 4354ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 4355b0989546SSandy Huang vp_id, plane_mask, 4356ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 4357ee008497SSandy Huang cursor_plane_id); 4358b0989546SSandy Huang 4359b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 4360b0989546SSandy Huang plane_mask, 1); 4361b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 4362b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 4363ee008497SSandy Huang if (cursor_plane_id >= 0) 4364ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id", 4365ee008497SSandy Huang cursor_plane_id, 1); 4366b0989546SSandy Huang vp_id++; 4367b0989546SSandy Huang } 4368b0989546SSandy Huang 4369b0989546SSandy Huang vop_fix_dts = true; 4370b0989546SSandy Huang 4371b0989546SSandy Huang return 0; 4372b0989546SSandy Huang } 4373b0989546SSandy Huang 4374820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state) 4375820a5c17SDamon Ding { 4376820a5c17SDamon Ding struct crtc_state *cstate = &state->crtc_state; 4377820a5c17SDamon Ding struct rockchip_crtc *crtc = cstate->crtc; 4378820a5c17SDamon Ding 4379820a5c17SDamon Ding if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) { 4380820a5c17SDamon Ding printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id); 4381820a5c17SDamon Ding return -ENOTSUPP; 4382820a5c17SDamon Ding } 4383820a5c17SDamon Ding 4384820a5c17SDamon Ding if (cstate->splice_mode) { 4385820a5c17SDamon Ding crtc->splice_mode = true; 4386820a5c17SDamon Ding crtc->splice_crtc_id = cstate->splice_crtc_id; 4387820a5c17SDamon Ding } 4388820a5c17SDamon Ding 4389820a5c17SDamon Ding return 0; 4390820a5c17SDamon Ding } 4391820a5c17SDamon Ding 439222007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state) 439322007755SDamon Ding { 439422007755SDamon Ding struct connector_state *conn_state = &state->conn_state; 439522007755SDamon Ding struct crtc_state *cstate = &state->crtc_state; 439622007755SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 439722007755SDamon Ding struct videomode vm; 439822007755SDamon Ding 439922007755SDamon Ding drm_display_mode_to_videomode(mode, &vm); 440022007755SDamon Ding 440122007755SDamon Ding if (vm.hactive < 32 || vm.vactive < 32 || 440222007755SDamon Ding (vm.hfront_porch * vm.hsync_len * vm.hback_porch * 440322007755SDamon Ding vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) { 440422007755SDamon Ding printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id); 440522007755SDamon Ding return -EINVAL; 440622007755SDamon Ding } 440722007755SDamon Ding 440822007755SDamon Ding return 0; 440922007755SDamon Ding } 441022007755SDamon Ding 44114c765862SDamon Ding #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) 44124c765862SDamon Ding 44134c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state) 44144c765862SDamon Ding { 44154c765862SDamon Ding struct crtc_state *cstate = &state->crtc_state; 44164c765862SDamon Ding struct vop2 *vop2 = cstate->private; 44174c765862SDamon Ding struct display_rect *src = &cstate->src_rect; 44184c765862SDamon Ding struct display_rect *dst = &cstate->crtc_rect; 44194c765862SDamon Ding struct vop2_win_data *win_data; 44204c765862SDamon Ding int min_scale, max_scale; 44214c765862SDamon Ding int hscale, vscale; 44224c765862SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 44234c765862SDamon Ding 44244c765862SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 44254c765862SDamon Ding if (!win_data) { 44264c765862SDamon Ding printf("ERROR: invalid win id %d\n", primary_plane_id); 44274c765862SDamon Ding return -ENODEV; 44284c765862SDamon Ding } 44294c765862SDamon Ding 44304c765862SDamon Ding min_scale = FRAC_16_16(1, win_data->max_downscale_factor); 44314c765862SDamon Ding max_scale = FRAC_16_16(win_data->max_upscale_factor, 1); 44324c765862SDamon Ding 44334c765862SDamon Ding hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale); 44344c765862SDamon Ding vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale); 44354c765862SDamon Ding if (hscale < 0 || vscale < 0) { 44364c765862SDamon Ding printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name); 44374c765862SDamon Ding return -ERANGE; 44384c765862SDamon Ding } 44394c765862SDamon Ding 44404c765862SDamon Ding return 0; 44414c765862SDamon Ding } 4442337d1c13SDamon Ding 44435fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 44445fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, 44455fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART1, 44465fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, 44475fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART3, 44485fa6e665SDamon Ding }; 44495fa6e665SDamon Ding 44505fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 44515fa6e665SDamon Ding {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 44525fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 44535fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 44545fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 44555fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 44565fa6e665SDamon Ding }; 44575fa6e665SDamon Ding 44585fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 44595fa6e665SDamon Ding { /* one display policy for hdmi */ 44605fa6e665SDamon Ding {/* main display */ 4461ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 44625fa6e665SDamon Ding .attached_layers_nr = 4, 44635fa6e665SDamon Ding .attached_layers = { 44645fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 44655fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2 44665fa6e665SDamon Ding }, 44675fa6e665SDamon Ding }, 44685fa6e665SDamon Ding {/* second display */}, 44695fa6e665SDamon Ding {/* third display */}, 44705fa6e665SDamon Ding {/* fourth display */}, 44715fa6e665SDamon Ding }, 44725fa6e665SDamon Ding 44735fa6e665SDamon Ding { /* two display policy */ 44745fa6e665SDamon Ding {/* main display */ 4475ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 44765fa6e665SDamon Ding .attached_layers_nr = 3, 44775fa6e665SDamon Ding .attached_layers = { 44785fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 44795fa6e665SDamon Ding }, 44805fa6e665SDamon Ding }, 44815fa6e665SDamon Ding 44825fa6e665SDamon Ding {/* second display */ 44835fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 44845fa6e665SDamon Ding .attached_layers_nr = 2, 44855fa6e665SDamon Ding .attached_layers = { 44865fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 44875fa6e665SDamon Ding }, 44885fa6e665SDamon Ding }, 44895fa6e665SDamon Ding {/* third display */}, 44905fa6e665SDamon Ding {/* fourth display */}, 44915fa6e665SDamon Ding }, 44925fa6e665SDamon Ding 44935fa6e665SDamon Ding { /* one display policy for cvbs */ 44945fa6e665SDamon Ding {/* main display */ 44955fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 44965fa6e665SDamon Ding .attached_layers_nr = 2, 44975fa6e665SDamon Ding .attached_layers = { 44985fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 44995fa6e665SDamon Ding }, 45005fa6e665SDamon Ding }, 45015fa6e665SDamon Ding {/* second display */}, 45025fa6e665SDamon Ding {/* third display */}, 45035fa6e665SDamon Ding {/* fourth display */}, 45045fa6e665SDamon Ding }, 45055fa6e665SDamon Ding 45065fa6e665SDamon Ding {/* reserved */}, 45075fa6e665SDamon Ding }; 45085fa6e665SDamon Ding 45095fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = { 45105fa6e665SDamon Ding { 45115fa6e665SDamon Ding .name = "Esmart0", 45125fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 45135fa6e665SDamon Ding .type = ESMART_LAYER, 45145fa6e665SDamon Ding .win_sel_port_offset = 8, 45155fa6e665SDamon Ding .layer_sel_win_id = { 1, 0xff, 0xff, 0xff }, 45165fa6e665SDamon Ding .reg_offset = 0, 45175fa6e665SDamon Ding .axi_id = 0, 45185fa6e665SDamon Ding .axi_yrgb_id = 0x06, 45195fa6e665SDamon Ding .axi_uv_id = 0x07, 45205fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 45215fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45225fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 45235fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45245fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 45255fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 45265fa6e665SDamon Ding .max_upscale_factor = 8, 45275fa6e665SDamon Ding .max_downscale_factor = 8, 45285fa6e665SDamon Ding }, 45295fa6e665SDamon Ding 45305fa6e665SDamon Ding { 45315fa6e665SDamon Ding .name = "Esmart1", 45325fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 45335fa6e665SDamon Ding .type = ESMART_LAYER, 45345fa6e665SDamon Ding .win_sel_port_offset = 10, 45355fa6e665SDamon Ding .layer_sel_win_id = { 2, 0xff, 0xff, 0xff }, 45365fa6e665SDamon Ding .reg_offset = 0x200, 45375fa6e665SDamon Ding .axi_id = 0, 45385fa6e665SDamon Ding .axi_yrgb_id = 0x08, 45395fa6e665SDamon Ding .axi_uv_id = 0x09, 45405fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 45415fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45425fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 45435fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45445fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 45455fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 45465fa6e665SDamon Ding .max_upscale_factor = 8, 45475fa6e665SDamon Ding .max_downscale_factor = 8, 45485fa6e665SDamon Ding }, 45495fa6e665SDamon Ding 45505fa6e665SDamon Ding { 45515fa6e665SDamon Ding .name = "Esmart2", 45525fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 45535fa6e665SDamon Ding .type = ESMART_LAYER, 45545fa6e665SDamon Ding .win_sel_port_offset = 12, 45555fa6e665SDamon Ding .layer_sel_win_id = { 3, 0, 0xff, 0xff }, 45565fa6e665SDamon Ding .reg_offset = 0x400, 45575fa6e665SDamon Ding .axi_id = 0, 45585fa6e665SDamon Ding .axi_yrgb_id = 0x0a, 45595fa6e665SDamon Ding .axi_uv_id = 0x0b, 45605fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 45615fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45625fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 45635fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45645fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 45655fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 45665fa6e665SDamon Ding .max_upscale_factor = 8, 45675fa6e665SDamon Ding .max_downscale_factor = 8, 45685fa6e665SDamon Ding }, 45695fa6e665SDamon Ding 45705fa6e665SDamon Ding { 45715fa6e665SDamon Ding .name = "Esmart3", 45725fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 45735fa6e665SDamon Ding .type = ESMART_LAYER, 45745fa6e665SDamon Ding .win_sel_port_offset = 14, 45755fa6e665SDamon Ding .layer_sel_win_id = { 0xff, 1, 0xff, 0xff }, 45765fa6e665SDamon Ding .reg_offset = 0x600, 45775fa6e665SDamon Ding .axi_id = 0, 45785fa6e665SDamon Ding .axi_yrgb_id = 0x0c, 45795fa6e665SDamon Ding .axi_uv_id = 0x0d, 45805fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 45815fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45825fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 45835fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 45845fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 45855fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 45865fa6e665SDamon Ding .max_upscale_factor = 8, 45875fa6e665SDamon Ding .max_downscale_factor = 8, 45885fa6e665SDamon Ding }, 45895fa6e665SDamon Ding 45905fa6e665SDamon Ding { 45915fa6e665SDamon Ding .name = "Cluster0", 45925fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0, 45935fa6e665SDamon Ding .type = CLUSTER_LAYER, 45945fa6e665SDamon Ding .win_sel_port_offset = 0, 45955fa6e665SDamon Ding .layer_sel_win_id = { 0, 0xff, 0xff, 0xff }, 45965fa6e665SDamon Ding .reg_offset = 0, 45975fa6e665SDamon Ding .axi_id = 0, 45985fa6e665SDamon Ding .axi_yrgb_id = 0x02, 45995fa6e665SDamon Ding .axi_uv_id = 0x03, 46005fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 46015fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 46025fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 46035fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 46045fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 46055fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 46065fa6e665SDamon Ding .max_upscale_factor = 8, 46075fa6e665SDamon Ding .max_downscale_factor = 8, 46085fa6e665SDamon Ding }, 46095fa6e665SDamon Ding }; 46105fa6e665SDamon Ding 46115fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = { 46125fa6e665SDamon Ding { 46136027c871SZhang Yubing .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM | 46146027c871SZhang Yubing VOP_FEATURE_POST_CSC, 46155fa6e665SDamon Ding .max_output = {4096, 4096}, 4616b05105abSDamon Ding .layer_mix_dly = 6, 4617b05105abSDamon Ding .hdr_mix_dly = 2, 4618b05105abSDamon Ding .win_dly = 8, 46195fa6e665SDamon Ding }, 46205fa6e665SDamon Ding { 46215fa6e665SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 46225fa6e665SDamon Ding .max_output = {1920, 1080}, 4623b05105abSDamon Ding .layer_mix_dly = 2, 4624b05105abSDamon Ding .hdr_mix_dly = 0, 4625b05105abSDamon Ding .win_dly = 8, 46265fa6e665SDamon Ding }, 46275fa6e665SDamon Ding }; 46285fa6e665SDamon Ding 46295fa6e665SDamon Ding const struct vop2_data rk3528_vop = { 46305fa6e665SDamon Ding .version = VOP_VERSION_RK3528, 46315fa6e665SDamon Ding .nr_vps = 2, 46325fa6e665SDamon Ding .vp_data = rk3528_vp_data, 46335fa6e665SDamon Ding .win_data = rk3528_win_data, 46345fa6e665SDamon Ding .plane_mask = rk3528_vp_plane_mask[0], 46355fa6e665SDamon Ding .plane_table = rk3528_plane_table, 46365fa6e665SDamon Ding .vp_primary_plane_order = rk3528_vp_primary_plane_order, 46375fa6e665SDamon Ding .nr_layers = 5, 46385fa6e665SDamon Ding .nr_mixers = 3, 46395fa6e665SDamon Ding .nr_gammas = 2, 46405fa6e665SDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE, 46415fa6e665SDamon Ding }; 46425fa6e665SDamon Ding 4643452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 4644452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, 4645452afb13SDamon Ding ROCKCHIP_VOP2_ESMART1, 4646452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, 4647452afb13SDamon Ding ROCKCHIP_VOP2_ESMART3, 4648452afb13SDamon Ding }; 4649452afb13SDamon Ding 4650452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 4651452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 4652452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 4653452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 4654452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 4655452afb13SDamon Ding }; 4656452afb13SDamon Ding 4657452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 4658452afb13SDamon Ding { /* one display policy for hdmi */ 4659452afb13SDamon Ding {/* main display */ 4660452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 4661452afb13SDamon Ding .attached_layers_nr = 4, 4662452afb13SDamon Ding .attached_layers = { 4663452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, 4664452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 4665452afb13SDamon Ding }, 4666452afb13SDamon Ding }, 4667452afb13SDamon Ding {/* second display */}, 4668452afb13SDamon Ding {/* third display */}, 4669452afb13SDamon Ding {/* fourth display */}, 4670452afb13SDamon Ding }, 4671452afb13SDamon Ding 4672452afb13SDamon Ding { /* two display policy */ 4673452afb13SDamon Ding {/* main display */ 4674452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 4675452afb13SDamon Ding .attached_layers_nr = 2, 4676452afb13SDamon Ding .attached_layers = { 4677452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 4678452afb13SDamon Ding }, 4679452afb13SDamon Ding }, 4680452afb13SDamon Ding 4681452afb13SDamon Ding {/* second display */ 4682452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 4683452afb13SDamon Ding .attached_layers_nr = 2, 4684452afb13SDamon Ding .attached_layers = { 4685452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 4686452afb13SDamon Ding }, 4687452afb13SDamon Ding }, 4688452afb13SDamon Ding {/* third display */}, 4689452afb13SDamon Ding {/* fourth display */}, 4690452afb13SDamon Ding }, 4691452afb13SDamon Ding 4692452afb13SDamon Ding {/* reserved */}, 4693452afb13SDamon Ding }; 4694452afb13SDamon Ding 4695452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = { 4696452afb13SDamon Ding { 4697452afb13SDamon Ding .name = "Esmart0", 4698452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 4699452afb13SDamon Ding .type = ESMART_LAYER, 4700452afb13SDamon Ding .win_sel_port_offset = 8, 4701452afb13SDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 4702452afb13SDamon Ding .reg_offset = 0, 4703452afb13SDamon Ding .axi_id = 0, 4704452afb13SDamon Ding .axi_yrgb_id = 0x02, 4705452afb13SDamon Ding .axi_uv_id = 0x03, 4706452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4707452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4708452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4709452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4710452afb13SDamon Ding .max_upscale_factor = 8, 4711452afb13SDamon Ding .max_downscale_factor = 8, 4712452afb13SDamon Ding }, 4713452afb13SDamon Ding 4714452afb13SDamon Ding { 4715452afb13SDamon Ding .name = "Esmart1", 4716452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 4717452afb13SDamon Ding .type = ESMART_LAYER, 4718452afb13SDamon Ding .win_sel_port_offset = 10, 4719452afb13SDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 4720452afb13SDamon Ding .reg_offset = 0x200, 4721452afb13SDamon Ding .axi_id = 0, 4722452afb13SDamon Ding .axi_yrgb_id = 0x04, 4723452afb13SDamon Ding .axi_uv_id = 0x05, 4724452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4725452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4726452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4727452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4728452afb13SDamon Ding .max_upscale_factor = 8, 4729452afb13SDamon Ding .max_downscale_factor = 8, 4730452afb13SDamon Ding }, 4731452afb13SDamon Ding 4732452afb13SDamon Ding { 4733452afb13SDamon Ding .name = "Esmart2", 4734452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 4735452afb13SDamon Ding .type = ESMART_LAYER, 4736452afb13SDamon Ding .win_sel_port_offset = 12, 4737452afb13SDamon Ding .layer_sel_win_id = { 2, 2, 0xff, 0xff }, 4738452afb13SDamon Ding .reg_offset = 0x400, 4739452afb13SDamon Ding .axi_id = 0, 4740452afb13SDamon Ding .axi_yrgb_id = 0x06, 4741452afb13SDamon Ding .axi_uv_id = 0x07, 4742452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4743452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4744452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4745452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4746452afb13SDamon Ding .max_upscale_factor = 8, 4747452afb13SDamon Ding .max_downscale_factor = 8, 4748452afb13SDamon Ding }, 4749452afb13SDamon Ding 4750452afb13SDamon Ding { 4751452afb13SDamon Ding .name = "Esmart3", 4752452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 4753452afb13SDamon Ding .type = ESMART_LAYER, 4754452afb13SDamon Ding .win_sel_port_offset = 14, 4755452afb13SDamon Ding .layer_sel_win_id = { 3, 3, 0xff, 0xff }, 4756452afb13SDamon Ding .reg_offset = 0x600, 4757452afb13SDamon Ding .axi_id = 0, 4758452afb13SDamon Ding .axi_yrgb_id = 0x08, 4759452afb13SDamon Ding .axi_uv_id = 0x0d, 4760452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 4761452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4762452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 4763452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 4764452afb13SDamon Ding .max_upscale_factor = 8, 4765452afb13SDamon Ding .max_downscale_factor = 8, 4766452afb13SDamon Ding }, 4767452afb13SDamon Ding }; 4768452afb13SDamon Ding 4769452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = { 4770452afb13SDamon Ding { 4771452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 4772452afb13SDamon Ding .max_output = {2048, 4096}, 4773452afb13SDamon Ding .win_dly = 8, 4774452afb13SDamon Ding .layer_mix_dly = 8, 4775452afb13SDamon Ding }, 4776452afb13SDamon Ding { 4777452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 4778452afb13SDamon Ding .max_output = {2048, 1080}, 4779452afb13SDamon Ding .win_dly = 8, 4780452afb13SDamon Ding .layer_mix_dly = 8, 4781452afb13SDamon Ding }, 4782452afb13SDamon Ding }; 4783452afb13SDamon Ding 4784452afb13SDamon Ding const struct vop2_data rk3562_vop = { 4785452afb13SDamon Ding .version = VOP_VERSION_RK3562, 4786452afb13SDamon Ding .nr_vps = 2, 4787452afb13SDamon Ding .vp_data = rk3562_vp_data, 4788452afb13SDamon Ding .win_data = rk3562_win_data, 4789452afb13SDamon Ding .plane_mask = rk3562_vp_plane_mask[0], 4790452afb13SDamon Ding .plane_table = rk3562_plane_table, 4791452afb13SDamon Ding .vp_primary_plane_order = rk3562_vp_primary_plane_order, 4792452afb13SDamon Ding .nr_layers = 4, 4793452afb13SDamon Ding .nr_mixers = 3, 4794452afb13SDamon Ding .nr_gammas = 2, 4795452afb13SDamon Ding .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE, 4796452afb13SDamon Ding }; 4797452afb13SDamon Ding 4798337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 4799337d1c13SDamon Ding ROCKCHIP_VOP2_SMART0, 4800337d1c13SDamon Ding ROCKCHIP_VOP2_SMART1, 4801337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 4802337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 4803337d1c13SDamon Ding }; 4804337d1c13SDamon Ding 4805ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 4806ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 4807ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 4808ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 4809ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 4810ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 4811ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 4812ee008497SSandy Huang }; 4813ee008497SSandy Huang 4814b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 4815b0989546SSandy Huang { /* one display policy */ 4816b0989546SSandy Huang {/* main display */ 4817b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 4818b0989546SSandy Huang .attached_layers_nr = 6, 4819b0989546SSandy Huang .attached_layers = { 4820b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 4821b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 4822b0989546SSandy Huang }, 4823b0989546SSandy Huang }, 4824b0989546SSandy Huang {/* second display */}, 4825b0989546SSandy Huang {/* third display */}, 4826b0989546SSandy Huang {/* fourth display */}, 4827b0989546SSandy Huang }, 4828b0989546SSandy Huang 4829b0989546SSandy Huang { /* two display policy */ 4830b0989546SSandy Huang {/* main display */ 4831b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 4832b0989546SSandy Huang .attached_layers_nr = 3, 4833b0989546SSandy Huang .attached_layers = { 4834b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 4835b0989546SSandy Huang }, 4836b0989546SSandy Huang }, 4837b0989546SSandy Huang 4838b0989546SSandy Huang {/* second display */ 4839b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 4840b0989546SSandy Huang .attached_layers_nr = 3, 4841b0989546SSandy Huang .attached_layers = { 4842b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 4843b0989546SSandy Huang }, 4844b0989546SSandy Huang }, 4845b0989546SSandy Huang {/* third display */}, 4846b0989546SSandy Huang {/* fourth display */}, 4847b0989546SSandy Huang }, 4848b0989546SSandy Huang 4849b0989546SSandy Huang { /* three display policy */ 4850b0989546SSandy Huang {/* main display */ 4851b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 4852b0989546SSandy Huang .attached_layers_nr = 3, 4853b0989546SSandy Huang .attached_layers = { 4854b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 4855b0989546SSandy Huang }, 4856b0989546SSandy Huang }, 4857b0989546SSandy Huang 4858b0989546SSandy Huang {/* second display */ 4859b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 4860b0989546SSandy Huang .attached_layers_nr = 2, 4861b0989546SSandy Huang .attached_layers = { 4862b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 4863b0989546SSandy Huang }, 4864b0989546SSandy Huang }, 4865b0989546SSandy Huang 4866b0989546SSandy Huang {/* third display */ 4867b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 4868b0989546SSandy Huang .attached_layers_nr = 1, 4869b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 4870b0989546SSandy Huang }, 4871b0989546SSandy Huang 4872b0989546SSandy Huang {/* fourth display */}, 4873b0989546SSandy Huang }, 4874b0989546SSandy Huang 4875b0989546SSandy Huang {/* reserved for four display policy */}, 4876b0989546SSandy Huang }; 4877b0989546SSandy Huang 4878b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = { 4879b0989546SSandy Huang { 4880b0989546SSandy Huang .name = "Cluster0", 4881b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0, 4882ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 4883b0989546SSandy Huang .win_sel_port_offset = 0, 48845fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0xff }, 4885b0989546SSandy Huang .reg_offset = 0, 48865fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 48875fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 48885fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 48895fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 48904c765862SDamon Ding .max_upscale_factor = 4, 48914c765862SDamon Ding .max_downscale_factor = 4, 4892b0989546SSandy Huang }, 4893b0989546SSandy Huang 4894b0989546SSandy Huang { 4895b0989546SSandy Huang .name = "Cluster1", 4896b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1, 4897ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 4898b0989546SSandy Huang .win_sel_port_offset = 1, 48995fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 0xff }, 4900b0989546SSandy Huang .reg_offset = 0x200, 49015fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49025fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49035fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49045fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49054c765862SDamon Ding .max_upscale_factor = 4, 49064c765862SDamon Ding .max_downscale_factor = 4, 4907b0989546SSandy Huang }, 4908b0989546SSandy Huang 4909b0989546SSandy Huang { 4910b0989546SSandy Huang .name = "Esmart0", 4911b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0, 4912ecc31b6eSAndy Yan .type = ESMART_LAYER, 4913b0989546SSandy Huang .win_sel_port_offset = 4, 49145fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 0xff }, 4915b0989546SSandy Huang .reg_offset = 0, 49165fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49175fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49185fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49195fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49204c765862SDamon Ding .max_upscale_factor = 8, 49214c765862SDamon Ding .max_downscale_factor = 8, 4922b0989546SSandy Huang }, 4923b0989546SSandy Huang 4924b0989546SSandy Huang { 4925b0989546SSandy Huang .name = "Esmart1", 4926b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1, 4927ecc31b6eSAndy Yan .type = ESMART_LAYER, 4928b0989546SSandy Huang .win_sel_port_offset = 5, 49295fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 0xff }, 4930b0989546SSandy Huang .reg_offset = 0x200, 49315fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49325fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49335fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49345fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49354c765862SDamon Ding .max_upscale_factor = 8, 49364c765862SDamon Ding .max_downscale_factor = 8, 4937b0989546SSandy Huang }, 4938b0989546SSandy Huang 4939b0989546SSandy Huang { 4940b0989546SSandy Huang .name = "Smart0", 4941b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0, 4942ecc31b6eSAndy Yan .type = SMART_LAYER, 4943b0989546SSandy Huang .win_sel_port_offset = 6, 49445fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 0xff }, 4945b0989546SSandy Huang .reg_offset = 0x400, 49465fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49475fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49485fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49495fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49504c765862SDamon Ding .max_upscale_factor = 8, 49514c765862SDamon Ding .max_downscale_factor = 8, 4952b0989546SSandy Huang }, 4953b0989546SSandy Huang 4954b0989546SSandy Huang { 4955b0989546SSandy Huang .name = "Smart1", 4956b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1, 4957ecc31b6eSAndy Yan .type = SMART_LAYER, 4958b0989546SSandy Huang .win_sel_port_offset = 7, 49595fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 0xff }, 4960b0989546SSandy Huang .reg_offset = 0x600, 49615fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49625fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49635fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49645fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49654c765862SDamon Ding .max_upscale_factor = 8, 49664c765862SDamon Ding .max_downscale_factor = 8, 4967b0989546SSandy Huang }, 4968b0989546SSandy Huang }; 4969b0989546SSandy Huang 497063cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = { 497163cb669fSSandy Huang { 497263cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT, 497363cb669fSSandy Huang .pre_scan_max_dly = 42, 497463cb669fSSandy Huang .max_output = {4096, 2304}, 4975d0408543SAndy Yan }, 497663cb669fSSandy Huang { 497763cb669fSSandy Huang .feature = 0, 497863cb669fSSandy Huang .pre_scan_max_dly = 40, 497963cb669fSSandy Huang .max_output = {2048, 1536}, 498063cb669fSSandy Huang }, 498163cb669fSSandy Huang { 498263cb669fSSandy Huang .feature = 0, 498363cb669fSSandy Huang .pre_scan_max_dly = 40, 498463cb669fSSandy Huang .max_output = {1920, 1080}, 498563cb669fSSandy Huang }, 498663cb669fSSandy Huang }; 4987d0408543SAndy Yan 498863cb669fSSandy Huang const struct vop2_data rk3568_vop = { 4989ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568, 499063cb669fSSandy Huang .nr_vps = 3, 499163cb669fSSandy Huang .vp_data = rk3568_vp_data, 4992b0989546SSandy Huang .win_data = rk3568_win_data, 4993b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0], 4994ee008497SSandy Huang .plane_table = rk356x_plane_table, 4995337d1c13SDamon Ding .vp_primary_plane_order = rk3568_vp_primary_plane_order, 4996d0408543SAndy Yan .nr_layers = 6, 499763cb669fSSandy Huang .nr_mixers = 5, 49981147facaSSandy Huang .nr_gammas = 1, 4999d0408543SAndy Yan }; 5000d0408543SAndy Yan 5001337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 5002337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 5003337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 5004337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART2, 5005337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART3, 5006337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 5007337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER1, 5008337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER2, 5009337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER3, 5010337d1c13SDamon Ding }; 5011337d1c13SDamon Ding 5012ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 5013ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 5014ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 5015ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 5016ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 5017ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 5018ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 5019ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 5020ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 5021ecc31b6eSAndy Yan }; 5022ecc31b6eSAndy Yan 5023ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 5024ecc31b6eSAndy Yan { /* one display policy */ 5025ecc31b6eSAndy Yan {/* main display */ 5026ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 5027ecc31b6eSAndy Yan .attached_layers_nr = 8, 5028ecc31b6eSAndy Yan .attached_layers = { 5029ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, 5030ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, 5031ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 5032ecc31b6eSAndy Yan }, 5033ecc31b6eSAndy Yan }, 5034ecc31b6eSAndy Yan {/* second display */}, 5035ecc31b6eSAndy Yan {/* third display */}, 5036ecc31b6eSAndy Yan {/* fourth display */}, 5037ecc31b6eSAndy Yan }, 5038ecc31b6eSAndy Yan 5039ecc31b6eSAndy Yan { /* two display policy */ 5040ecc31b6eSAndy Yan {/* main display */ 5041ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 5042ecc31b6eSAndy Yan .attached_layers_nr = 4, 5043ecc31b6eSAndy Yan .attached_layers = { 5044ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 5045ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 5046ecc31b6eSAndy Yan }, 5047ecc31b6eSAndy Yan }, 5048ecc31b6eSAndy Yan 5049ecc31b6eSAndy Yan {/* second display */ 5050ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 5051ecc31b6eSAndy Yan .attached_layers_nr = 4, 5052ecc31b6eSAndy Yan .attached_layers = { 5053ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, 5054ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 5055ecc31b6eSAndy Yan }, 5056ecc31b6eSAndy Yan }, 5057ecc31b6eSAndy Yan {/* third display */}, 5058ecc31b6eSAndy Yan {/* fourth display */}, 5059ecc31b6eSAndy Yan }, 5060ecc31b6eSAndy Yan 5061ecc31b6eSAndy Yan { /* three display policy */ 5062ecc31b6eSAndy Yan {/* main display */ 5063ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 5064ecc31b6eSAndy Yan .attached_layers_nr = 3, 5065ecc31b6eSAndy Yan .attached_layers = { 5066ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 5067ecc31b6eSAndy Yan }, 5068ecc31b6eSAndy Yan }, 5069ecc31b6eSAndy Yan 5070ecc31b6eSAndy Yan {/* second display */ 5071ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 5072ecc31b6eSAndy Yan .attached_layers_nr = 3, 5073ecc31b6eSAndy Yan .attached_layers = { 5074ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 5075ecc31b6eSAndy Yan }, 5076ecc31b6eSAndy Yan }, 5077ecc31b6eSAndy Yan 5078ecc31b6eSAndy Yan {/* third display */ 5079ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5080ecc31b6eSAndy Yan .attached_layers_nr = 2, 5081ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 5082ecc31b6eSAndy Yan }, 5083ecc31b6eSAndy Yan 5084ecc31b6eSAndy Yan {/* fourth display */}, 5085ecc31b6eSAndy Yan }, 5086ecc31b6eSAndy Yan 5087ecc31b6eSAndy Yan { /* four display policy */ 5088ecc31b6eSAndy Yan {/* main display */ 5089ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 5090ecc31b6eSAndy Yan .attached_layers_nr = 2, 5091ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 5092ecc31b6eSAndy Yan }, 5093ecc31b6eSAndy Yan 5094ecc31b6eSAndy Yan {/* second display */ 5095ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER1, 5096ecc31b6eSAndy Yan .attached_layers_nr = 2, 5097ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 5098ecc31b6eSAndy Yan }, 5099ecc31b6eSAndy Yan 5100ecc31b6eSAndy Yan {/* third display */ 5101ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 5102ecc31b6eSAndy Yan .attached_layers_nr = 2, 5103ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 5104ecc31b6eSAndy Yan }, 5105ecc31b6eSAndy Yan 5106ecc31b6eSAndy Yan {/* fourth display */ 5107ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_CLUSTER3, 5108ecc31b6eSAndy Yan .attached_layers_nr = 2, 5109ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 5110ecc31b6eSAndy Yan }, 5111ecc31b6eSAndy Yan }, 5112ecc31b6eSAndy Yan 5113ecc31b6eSAndy Yan }; 5114ecc31b6eSAndy Yan 5115ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = { 5116ecc31b6eSAndy Yan { 5117ecc31b6eSAndy Yan .name = "Cluster0", 5118ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0, 5119ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER1, 5120ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5121ecc31b6eSAndy Yan .win_sel_port_offset = 0, 51225fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0 }, 5123ecc31b6eSAndy Yan .reg_offset = 0, 5124a33b790fSDamon Ding .axi_id = 0, 5125a33b790fSDamon Ding .axi_yrgb_id = 2, 5126a33b790fSDamon Ding .axi_uv_id = 3, 5127b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER0, 51285fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51295fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51305fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51315fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51324c765862SDamon Ding .max_upscale_factor = 4, 51334c765862SDamon Ding .max_downscale_factor = 4, 5134ecc31b6eSAndy Yan }, 5135ecc31b6eSAndy Yan 5136ecc31b6eSAndy Yan { 5137ecc31b6eSAndy Yan .name = "Cluster1", 5138ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1, 5139ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5140ecc31b6eSAndy Yan .win_sel_port_offset = 1, 51415fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 1 }, 5142ecc31b6eSAndy Yan .reg_offset = 0x200, 5143a33b790fSDamon Ding .axi_id = 0, 5144a33b790fSDamon Ding .axi_yrgb_id = 6, 5145a33b790fSDamon Ding .axi_uv_id = 7, 5146b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER1, 51475fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51485fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51495fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51505fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51514c765862SDamon Ding .max_upscale_factor = 4, 51524c765862SDamon Ding .max_downscale_factor = 4, 5153ecc31b6eSAndy Yan }, 5154ecc31b6eSAndy Yan 5155ecc31b6eSAndy Yan { 5156ecc31b6eSAndy Yan .name = "Cluster2", 5157ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2, 5158ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER3, 5159ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5160ecc31b6eSAndy Yan .win_sel_port_offset = 2, 51615fa6e665SDamon Ding .layer_sel_win_id = { 4, 4, 4, 4 }, 5162ecc31b6eSAndy Yan .reg_offset = 0x400, 5163a33b790fSDamon Ding .axi_id = 1, 5164a33b790fSDamon Ding .axi_yrgb_id = 2, 5165a33b790fSDamon Ding .axi_uv_id = 3, 5166b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER2, 51675fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51685fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51695fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51705fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51714c765862SDamon Ding .max_upscale_factor = 4, 51724c765862SDamon Ding .max_downscale_factor = 4, 5173ecc31b6eSAndy Yan }, 5174ecc31b6eSAndy Yan 5175ecc31b6eSAndy Yan { 5176ecc31b6eSAndy Yan .name = "Cluster3", 5177ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3, 5178ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5179ecc31b6eSAndy Yan .win_sel_port_offset = 3, 51805fa6e665SDamon Ding .layer_sel_win_id = { 5, 5, 5, 5 }, 5181ecc31b6eSAndy Yan .reg_offset = 0x600, 5182a33b790fSDamon Ding .axi_id = 1, 5183a33b790fSDamon Ding .axi_yrgb_id = 6, 5184a33b790fSDamon Ding .axi_uv_id = 7, 5185b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER3, 51865fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 51875fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51885fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 51895fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 51904c765862SDamon Ding .max_upscale_factor = 4, 51914c765862SDamon Ding .max_downscale_factor = 4, 5192ecc31b6eSAndy Yan }, 5193ecc31b6eSAndy Yan 5194ecc31b6eSAndy Yan { 5195ecc31b6eSAndy Yan .name = "Esmart0", 5196ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0, 5197ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART1, 5198ecc31b6eSAndy Yan .type = ESMART_LAYER, 5199ecc31b6eSAndy Yan .win_sel_port_offset = 4, 52005fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 2 }, 5201ecc31b6eSAndy Yan .reg_offset = 0, 5202a33b790fSDamon Ding .axi_id = 0, 5203a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 5204a33b790fSDamon Ding .axi_uv_id = 0x0b, 52055fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 52065fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52075fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 52085fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52094c765862SDamon Ding .max_upscale_factor = 8, 52104c765862SDamon Ding .max_downscale_factor = 8, 5211ecc31b6eSAndy Yan }, 5212ecc31b6eSAndy Yan 5213ecc31b6eSAndy Yan { 5214ecc31b6eSAndy Yan .name = "Esmart1", 5215ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1, 5216ecc31b6eSAndy Yan .type = ESMART_LAYER, 5217ecc31b6eSAndy Yan .win_sel_port_offset = 5, 52185fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 3 }, 5219ecc31b6eSAndy Yan .reg_offset = 0x200, 5220a33b790fSDamon Ding .axi_id = 0, 5221a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 5222a33b790fSDamon Ding .axi_uv_id = 0x0d, 5223b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 52245fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 52255fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52265fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 52275fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52284c765862SDamon Ding .max_upscale_factor = 8, 52294c765862SDamon Ding .max_downscale_factor = 8, 5230ecc31b6eSAndy Yan }, 5231ecc31b6eSAndy Yan 5232ecc31b6eSAndy Yan { 5233ecc31b6eSAndy Yan .name = "Esmart2", 5234ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2, 5235ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART3, 5236ecc31b6eSAndy Yan .type = ESMART_LAYER, 5237ecc31b6eSAndy Yan .win_sel_port_offset = 6, 52385fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 6 }, 5239ecc31b6eSAndy Yan .reg_offset = 0x400, 5240a33b790fSDamon Ding .axi_id = 1, 5241a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 5242a33b790fSDamon Ding .axi_uv_id = 0x0b, 5243b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 52445fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 52455fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52465fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 52475fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52484c765862SDamon Ding .max_upscale_factor = 8, 52494c765862SDamon Ding .max_downscale_factor = 8, 5250ecc31b6eSAndy Yan }, 5251ecc31b6eSAndy Yan 5252ecc31b6eSAndy Yan { 5253ecc31b6eSAndy Yan .name = "Esmart3", 5254ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3, 5255ecc31b6eSAndy Yan .type = ESMART_LAYER, 5256ecc31b6eSAndy Yan .win_sel_port_offset = 7, 52575fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 7 }, 5258ecc31b6eSAndy Yan .reg_offset = 0x600, 5259a33b790fSDamon Ding .axi_id = 1, 5260a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 5261a33b790fSDamon Ding .axi_uv_id = 0x0d, 5262b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 52635fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 52645fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52655fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 52665fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 52674c765862SDamon Ding .max_upscale_factor = 8, 52684c765862SDamon Ding .max_downscale_factor = 8, 5269ecc31b6eSAndy Yan }, 5270ecc31b6eSAndy Yan }; 5271ecc31b6eSAndy Yan 527212ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = { 527312ee5af0SDamon Ding {0x00000000, "no error detected by DSC encoder"}, 527412ee5af0SDamon Ding {0x0030ffff, "bits per component error"}, 527512ee5af0SDamon Ding {0x0040ffff, "multiple mode error"}, 527612ee5af0SDamon Ding {0x0050ffff, "line buffer depth error"}, 527712ee5af0SDamon Ding {0x0060ffff, "minor version error"}, 527812ee5af0SDamon Ding {0x0070ffff, "picture height error"}, 527912ee5af0SDamon Ding {0x0080ffff, "picture width error"}, 528012ee5af0SDamon Ding {0x0090ffff, "number of slices error"}, 528112ee5af0SDamon Ding {0x00c0ffff, "slice height Error "}, 528212ee5af0SDamon Ding {0x00d0ffff, "slice width error"}, 528312ee5af0SDamon Ding {0x00e0ffff, "second line BPG offset error"}, 528412ee5af0SDamon Ding {0x00f0ffff, "non second line BPG offset error"}, 528512ee5af0SDamon Ding {0x0100ffff, "PPS ID error"}, 528612ee5af0SDamon Ding {0x0110ffff, "bits per pixel (BPP) Error"}, 528712ee5af0SDamon Ding {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */ 528812ee5af0SDamon Ding 528912ee5af0SDamon Ding {0x01510001, "slice 0 RC buffer model overflow error"}, 529012ee5af0SDamon Ding {0x01510002, "slice 1 RC buffer model overflow error"}, 529112ee5af0SDamon Ding {0x01510004, "slice 2 RC buffer model overflow error"}, 529212ee5af0SDamon Ding {0x01510008, "slice 3 RC buffer model overflow error"}, 529312ee5af0SDamon Ding {0x01510010, "slice 4 RC buffer model overflow error"}, 529412ee5af0SDamon Ding {0x01510020, "slice 5 RC buffer model overflow error"}, 529512ee5af0SDamon Ding {0x01510040, "slice 6 RC buffer model overflow error"}, 529612ee5af0SDamon Ding {0x01510080, "slice 7 RC buffer model overflow error"}, 529712ee5af0SDamon Ding 529812ee5af0SDamon Ding {0x01610001, "slice 0 RC buffer model underflow error"}, 529912ee5af0SDamon Ding {0x01610002, "slice 1 RC buffer model underflow error"}, 530012ee5af0SDamon Ding {0x01610004, "slice 2 RC buffer model underflow error"}, 530112ee5af0SDamon Ding {0x01610008, "slice 3 RC buffer model underflow error"}, 530212ee5af0SDamon Ding {0x01610010, "slice 4 RC buffer model underflow error"}, 530312ee5af0SDamon Ding {0x01610020, "slice 5 RC buffer model underflow error"}, 530412ee5af0SDamon Ding {0x01610040, "slice 6 RC buffer model underflow error"}, 530512ee5af0SDamon Ding {0x01610080, "slice 7 RC buffer model underflow error"}, 530612ee5af0SDamon Ding 530712ee5af0SDamon Ding {0xffffffff, "unsuccessful RESET cycle status"}, 530812ee5af0SDamon Ding {0x00a0ffff, "ICH full error precision settings error"}, 530912ee5af0SDamon Ding {0x0020ffff, "native mode"}, 531012ee5af0SDamon Ding }; 531112ee5af0SDamon Ding 531212ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = { 531312ee5af0SDamon Ding {0x00000000, "rate buffer status"}, 531412ee5af0SDamon Ding {0x00000001, "line buffer status"}, 531512ee5af0SDamon Ding {0x00000002, "decoder model status"}, 531612ee5af0SDamon Ding {0x00000003, "pixel buffer status"}, 531712ee5af0SDamon Ding {0x00000004, "balance fifo buffer status"}, 531812ee5af0SDamon Ding {0x00000005, "syntax element fifo status"}, 531912ee5af0SDamon Ding }; 532012ee5af0SDamon Ding 532112ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = { 532212ee5af0SDamon Ding { 532312ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_8K, 532412ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_8K, 532512ee5af0SDamon Ding .max_slice_num = 8, 532612ee5af0SDamon Ding .max_linebuf_depth = 11, 5327b61227a3SDamon Ding .min_bits_per_pixel = 8, 532812ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src", 532912ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_8k_txp_clk", 533012ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_8k_pxl_clk", 533112ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_8k_cds_clk", 533212ee5af0SDamon Ding }, 533312ee5af0SDamon Ding 533412ee5af0SDamon Ding { 533512ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_4K, 533612ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_4K, 533712ee5af0SDamon Ding .max_slice_num = 2, 533812ee5af0SDamon Ding .max_linebuf_depth = 11, 5339b61227a3SDamon Ding .min_bits_per_pixel = 8, 534012ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src", 534112ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_4k_txp_clk", 534212ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_4k_pxl_clk", 534312ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_4k_cds_clk", 534412ee5af0SDamon Ding }, 534512ee5af0SDamon Ding }; 534612ee5af0SDamon Ding 5347ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = { 5348ecc31b6eSAndy Yan { 5349ee01dbb2SDamon Ding .splice_vp_id = 1, 5350ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5351b890760eSAlgea Cao .pre_scan_max_dly = 54, 5352ecc31b6eSAndy Yan .max_dclk = 600000, 5353ecc31b6eSAndy Yan .max_output = {7680, 4320}, 5354ecc31b6eSAndy Yan }, 5355ecc31b6eSAndy Yan { 5356ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5357ee01dbb2SDamon Ding .pre_scan_max_dly = 54, 5358ecc31b6eSAndy Yan .max_dclk = 600000, 5359ecc31b6eSAndy Yan .max_output = {4096, 2304}, 5360ecc31b6eSAndy Yan }, 5361ecc31b6eSAndy Yan { 5362ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5363ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 5364ecc31b6eSAndy Yan .max_dclk = 600000, 5365ecc31b6eSAndy Yan .max_output = {4096, 2304}, 5366ecc31b6eSAndy Yan }, 5367ecc31b6eSAndy Yan { 5368ecc31b6eSAndy Yan .feature = 0, 5369ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 5370ecc31b6eSAndy Yan .max_dclk = 200000, 5371ecc31b6eSAndy Yan .max_output = {1920, 1080}, 5372ecc31b6eSAndy Yan }, 5373ecc31b6eSAndy Yan }; 5374ecc31b6eSAndy Yan 5375b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = { 5376b6ba80b4SDamon Ding { 5377b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER0, 5378b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0), 5379b6ba80b4SDamon Ding }, 5380b6ba80b4SDamon Ding { 5381b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER1, 5382b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1), 5383b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5384b6ba80b4SDamon Ding }, 5385b6ba80b4SDamon Ding { 5386b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER2, 5387b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2), 5388b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5389b6ba80b4SDamon Ding }, 5390b6ba80b4SDamon Ding { 5391b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER3, 5392b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3), 5393b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5394b6ba80b4SDamon Ding }, 5395b6ba80b4SDamon Ding { 5396b6ba80b4SDamon Ding .id = VOP2_PD_ESMART, 5397b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) | 5398b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | 5399b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART3), 5400b6ba80b4SDamon Ding }, 5401b6ba80b4SDamon Ding { 5402b6ba80b4SDamon Ding .id = VOP2_PD_DSC_8K, 5403b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K), 5404b6ba80b4SDamon Ding }, 5405b6ba80b4SDamon Ding { 5406b6ba80b4SDamon Ding .id = VOP2_PD_DSC_4K, 5407b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K), 5408b6ba80b4SDamon Ding }, 5409b6ba80b4SDamon Ding }; 5410b6ba80b4SDamon Ding 5411ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = { 5412ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588, 5413ecc31b6eSAndy Yan .nr_vps = 4, 5414ecc31b6eSAndy Yan .vp_data = rk3588_vp_data, 5415ecc31b6eSAndy Yan .win_data = rk3588_win_data, 5416ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0], 5417ecc31b6eSAndy Yan .plane_table = rk3588_plane_table, 5418b6ba80b4SDamon Ding .pd = rk3588_vop_pd_data, 541912ee5af0SDamon Ding .dsc = rk3588_dsc_data, 542012ee5af0SDamon Ding .dsc_error_ecw = dsc_ecw, 542112ee5af0SDamon Ding .dsc_error_buffer_flow = dsc_buffer_flow, 5422337d1c13SDamon Ding .vp_primary_plane_order = rk3588_vp_primary_plane_order, 5423ecc31b6eSAndy Yan .nr_layers = 8, 5424ecc31b6eSAndy Yan .nr_mixers = 7, 5425ecc31b6eSAndy Yan .nr_gammas = 4, 5426b6ba80b4SDamon Ding .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data), 542712ee5af0SDamon Ding .nr_dscs = 2, 542812ee5af0SDamon Ding .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw), 542912ee5af0SDamon Ding .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow), 5430ecc31b6eSAndy Yan }; 5431ecc31b6eSAndy Yan 5432d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 5433d0408543SAndy Yan .preinit = rockchip_vop2_preinit, 5434d0408543SAndy Yan .prepare = rockchip_vop2_prepare, 5435d0408543SAndy Yan .init = rockchip_vop2_init, 5436d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane, 5437d0408543SAndy Yan .enable = rockchip_vop2_enable, 5438d0408543SAndy Yan .disable = rockchip_vop2_disable, 5439b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts, 5440820a5c17SDamon Ding .check = rockchip_vop2_check, 544122007755SDamon Ding .mode_valid = rockchip_vop2_mode_valid, 54424c765862SDamon Ding .plane_check = rockchip_vop2_plane_check, 5443d0408543SAndy Yan }; 5444