1d0408543SAndy Yan // SPDX-License-Identifier: GPL-2.0-only 2d0408543SAndy Yan /* 3d0408543SAndy Yan * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 4d0408543SAndy Yan * 5d0408543SAndy Yan */ 6d0408543SAndy Yan 7d0408543SAndy Yan #include <config.h> 8d0408543SAndy Yan #include <common.h> 9d0408543SAndy Yan #include <errno.h> 10d0408543SAndy Yan #include <malloc.h> 11d0408543SAndy Yan #include <fdtdec.h> 12d0408543SAndy Yan #include <fdt_support.h> 13b890760eSAlgea Cao #include <regmap.h> 14feffd38eSSandy Huang #include <asm/arch/cpu.h> 15d0408543SAndy Yan #include <asm/unaligned.h> 16d0408543SAndy Yan #include <asm/io.h> 17d0408543SAndy Yan #include <linux/list.h> 18ecc31b6eSAndy Yan #include <linux/log2.h> 19d0408543SAndy Yan #include <linux/media-bus-format.h> 20d0408543SAndy Yan #include <asm/arch/clock.h> 218e7ef808SDamon Ding #include <asm/gpio.h> 22d0408543SAndy Yan #include <linux/err.h> 231147facaSSandy Huang #include <linux/ioport.h> 24d0408543SAndy Yan #include <dm/device.h> 25d0408543SAndy Yan #include <dm/read.h> 265fa6e665SDamon Ding #include <dm/ofnode.h> 27ac500a1fSSandy Huang #include <fixp-arith.h> 28d0408543SAndy Yan #include <syscon.h> 2960e469f5SDamon Ding #include <linux/iopoll.h> 305f1357a2SZhang Yubing #include <dm/uclass-internal.h> 31452afb13SDamon Ding #include <stdlib.h> 32d0408543SAndy Yan 33d0408543SAndy Yan #include "rockchip_display.h" 34d0408543SAndy Yan #include "rockchip_crtc.h" 35d0408543SAndy Yan #include "rockchip_connector.h" 36d8e7f4a5SSandy Huang #include "rockchip_phy.h" 376027c871SZhang Yubing #include "rockchip_post_csc.h" 38d0408543SAndy Yan 39d0408543SAndy Yan /* System registers definition */ 40d0408543SAndy Yan #define RK3568_REG_CFG_DONE 0x000 41d0408543SAndy Yan #define CFG_DONE_EN BIT(15) 42d0408543SAndy Yan 43d0408543SAndy Yan #define RK3568_VERSION_INFO 0x004 44d0408543SAndy Yan #define EN_MASK 1 45d0408543SAndy Yan 4663cb669fSSandy Huang #define RK3568_AUTO_GATING_CTRL 0x008 470675a2a4SDamon Ding #define AUTO_GATING_EN_SHIFT 31 480675a2a4SDamon Ding #define PORT_DCLK_AUTO_GATING_EN_SHIFT 14 4963cb669fSSandy Huang 506414e3bcSSandy Huang #define RK3568_SYS_AXI_LUT_CTRL 0x024 516414e3bcSSandy Huang #define LUT_DMA_EN_SHIFT 0 52aa670293SDamon Ding #define DSP_VS_T_SEL_SHIFT 16 536414e3bcSSandy Huang 54d0408543SAndy Yan #define RK3568_DSP_IF_EN 0x028 55d0408543SAndy Yan #define RGB_EN_SHIFT 0 56ecc31b6eSAndy Yan #define RK3588_DP0_EN_SHIFT 0 57ecc31b6eSAndy Yan #define RK3588_DP1_EN_SHIFT 1 58ecc31b6eSAndy Yan #define RK3588_RGB_EN_SHIFT 8 59d0408543SAndy Yan #define HDMI0_EN_SHIFT 1 60d0408543SAndy Yan #define EDP0_EN_SHIFT 3 61ecc31b6eSAndy Yan #define RK3588_EDP0_EN_SHIFT 2 62ecc31b6eSAndy Yan #define RK3588_HDMI0_EN_SHIFT 3 63d0408543SAndy Yan #define MIPI0_EN_SHIFT 4 64ecc31b6eSAndy Yan #define RK3588_EDP1_EN_SHIFT 4 65ecc31b6eSAndy Yan #define RK3588_HDMI1_EN_SHIFT 5 66ecc31b6eSAndy Yan #define RK3588_MIPI0_EN_SHIFT 6 67d0408543SAndy Yan #define MIPI1_EN_SHIFT 20 68ecc31b6eSAndy Yan #define RK3588_MIPI1_EN_SHIFT 7 69d0408543SAndy Yan #define LVDS0_EN_SHIFT 5 70d0408543SAndy Yan #define LVDS1_EN_SHIFT 24 71d0408543SAndy Yan #define BT1120_EN_SHIFT 6 72d0408543SAndy Yan #define BT656_EN_SHIFT 7 73d0408543SAndy Yan #define IF_MUX_MASK 3 74d0408543SAndy Yan #define RGB_MUX_SHIFT 8 75d0408543SAndy Yan #define HDMI0_MUX_SHIFT 10 76ecc31b6eSAndy Yan #define RK3588_DP0_MUX_SHIFT 12 77ecc31b6eSAndy Yan #define RK3588_DP1_MUX_SHIFT 14 78d0408543SAndy Yan #define EDP0_MUX_SHIFT 14 79ecc31b6eSAndy Yan #define RK3588_HDMI_EDP0_MUX_SHIFT 16 80ecc31b6eSAndy Yan #define RK3588_HDMI_EDP1_MUX_SHIFT 18 81d0408543SAndy Yan #define MIPI0_MUX_SHIFT 16 82ecc31b6eSAndy Yan #define RK3588_MIPI0_MUX_SHIFT 20 83d0408543SAndy Yan #define MIPI1_MUX_SHIFT 21 8411f53190SSandy Huang #define LVDS0_MUX_SHIFT 18 85d0408543SAndy Yan #define LVDS1_MUX_SHIFT 25 86d0408543SAndy Yan 87d0408543SAndy Yan #define RK3568_DSP_IF_CTRL 0x02c 88d0408543SAndy Yan #define LVDS_DUAL_EN_SHIFT 0 89d0408543SAndy Yan #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 90d0408543SAndy Yan #define LVDS_DUAL_SWAP_EN_SHIFT 2 915fa6e665SDamon Ding #define BT656_UV_SWAP 4 925fa6e665SDamon Ding #define BT656_YC_SWAP 5 935fa6e665SDamon Ding #define BT656_DCLK_POL 6 940a1fb152SZhang Yubing #define RK3588_HDMI_DUAL_EN_SHIFT 8 950a1fb152SZhang Yubing #define RK3588_EDP_DUAL_EN_SHIFT 8 960a1fb152SZhang Yubing #define RK3588_DP_DUAL_EN_SHIFT 9 9741874944SGuochun Huang #define RK3568_MIPI_DUAL_EN_SHIFT 10 9841874944SGuochun Huang #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11 9941874944SGuochun Huang #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12 10041874944SGuochun Huang 101d0408543SAndy Yan #define RK3568_DSP_IF_POL 0x030 102d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_MASK 1 103d0408543SAndy Yan #define IF_CTRL_REG_DONE_IMD_SHIFT 28 104d0408543SAndy Yan #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 105d0408543SAndy Yan #define IF_CRTL_EDP_DCLK_POL_SHIT 15 1067bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_MASK 0x7 1077bcdc6eeSDamon Ding #define IF_CTRL_EDP_PIN_POL_SHIFT 12 108d0408543SAndy Yan #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 10910ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 11010ee9f5bSAlgea Cao #define IF_CRTL_HDMI_PIN_POL_SHIT 4 11115f69071SDamon Ding #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT 3 11215f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_MASK 0x7 11315f69071SDamon Ding #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT 0 114ecc31b6eSAndy Yan 115452afb13SDamon Ding #define RK3562_MIPI_DCLK_POL_SHIFT 15 116452afb13SDamon Ding #define RK3562_MIPI_PIN_POL_SHIFT 12 117452afb13SDamon Ding #define RK3562_IF_PIN_POL_MASK 0x7 118452afb13SDamon Ding 119ecc31b6eSAndy Yan #define RK3588_DP0_PIN_POL_SHIFT 8 120ecc31b6eSAndy Yan #define RK3588_DP1_PIN_POL_SHIFT 12 121ecc31b6eSAndy Yan #define RK3588_IF_PIN_POL_MASK 0x7 122ecc31b6eSAndy Yan 123ecc31b6eSAndy Yan #define HDMI_EDP0_DCLK_DIV_SHIFT 16 124ecc31b6eSAndy Yan #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 125ecc31b6eSAndy Yan #define HDMI_EDP1_DCLK_DIV_SHIFT 20 126ecc31b6eSAndy Yan #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 127ecc31b6eSAndy Yan #define MIPI0_PIXCLK_DIV_SHIFT 24 128ecc31b6eSAndy Yan #define MIPI1_PIXCLK_DIV_SHIFT 26 129ecc31b6eSAndy Yan 130feffd38eSSandy Huang #define RK3568_SYS_OTP_WIN_EN 0x50 131feffd38eSSandy Huang #define OTP_WIN_EN_SHIFT 0 1321147facaSSandy Huang #define RK3568_SYS_LUT_PORT_SEL 0x58 1331147facaSSandy Huang #define GAMMA_PORT_SEL_MASK 0x3 1341147facaSSandy Huang #define GAMMA_PORT_SEL_SHIFT 0 135db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_MASK 0x3 136db328a0dSDamon Ding #define GAMMA_AHB_WRITE_SEL_SHIFT 12 137ee01dbb2SDamon Ding #define PORT_MERGE_EN_SHIFT 16 1385fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_MASK 0x3 1395fa6e665SDamon Ding #define ESMART_LB_MODE_SEL_SHIFT 26 1401147facaSSandy Huang 141ecc31b6eSAndy Yan #define RK3568_SYS_PD_CTRL 0x034 142d0408543SAndy Yan #define RK3568_VP0_LINE_FLAG 0x70 143d0408543SAndy Yan #define RK3568_VP1_LINE_FLAG 0x74 144d0408543SAndy Yan #define RK3568_VP2_LINE_FLAG 0x78 145d0408543SAndy Yan #define RK3568_SYS0_INT_EN 0x80 146d0408543SAndy Yan #define RK3568_SYS0_INT_CLR 0x84 147d0408543SAndy Yan #define RK3568_SYS0_INT_STATUS 0x88 148d0408543SAndy Yan #define RK3568_SYS1_INT_EN 0x90 149d0408543SAndy Yan #define RK3568_SYS1_INT_CLR 0x94 150d0408543SAndy Yan #define RK3568_SYS1_INT_STATUS 0x98 151d0408543SAndy Yan #define RK3568_VP0_INT_EN 0xA0 152d0408543SAndy Yan #define RK3568_VP0_INT_CLR 0xA4 153d0408543SAndy Yan #define RK3568_VP0_INT_STATUS 0xA8 154d0408543SAndy Yan #define RK3568_VP1_INT_EN 0xB0 155d0408543SAndy Yan #define RK3568_VP1_INT_CLR 0xB4 156d0408543SAndy Yan #define RK3568_VP1_INT_STATUS 0xB8 157d0408543SAndy Yan #define RK3568_VP2_INT_EN 0xC0 158d0408543SAndy Yan #define RK3568_VP2_INT_CLR 0xC4 159d0408543SAndy Yan #define RK3568_VP2_INT_STATUS 0xC8 16060e469f5SDamon Ding #define RK3588_CLUSTER0_PD_EN_SHIFT 0 16160e469f5SDamon Ding #define RK3588_CLUSTER1_PD_EN_SHIFT 1 16260e469f5SDamon Ding #define RK3588_CLUSTER2_PD_EN_SHIFT 2 16360e469f5SDamon Ding #define RK3588_CLUSTER3_PD_EN_SHIFT 3 164b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_EN_SHIFT 5 165b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_EN_SHIFT 6 16660e469f5SDamon Ding #define RK3588_ESMART_PD_EN_SHIFT 7 16760e469f5SDamon Ding 168cd6c85a9SDamon Ding #define RK3588_SYS_VAR_FREQ_CTRL 0x038 169cd6c85a9SDamon Ding #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT 20 170cd6c85a9SDamon Ding #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT 24 171cd6c85a9SDamon Ding #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT 28 172cd6c85a9SDamon Ding 17360e469f5SDamon Ding #define RK3568_SYS_STATUS0 0x60 17460e469f5SDamon Ding #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8 17560e469f5SDamon Ding #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9 17660e469f5SDamon Ding #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10 17760e469f5SDamon Ding #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11 178b6ba80b4SDamon Ding #define RK3588_DSC_8K_PD_STATUS_SHIFT 13 179b6ba80b4SDamon Ding #define RK3588_DSC_4K_PD_STATUS_SHIFT 14 18060e469f5SDamon Ding #define RK3588_ESMART_PD_STATUS_SHIFT 15 181d0408543SAndy Yan 18266724b9cSDamon Ding #define RK3568_SYS_CTRL_LINE_FLAG0 0x70 18366724b9cSDamon Ding #define LINE_FLAG_NUM_MASK 0x1fff 18466724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0 18566724b9cSDamon Ding #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16 18666724b9cSDamon Ding 18712ee5af0SDamon Ding /* DSC CTRL registers definition */ 18812ee5af0SDamon Ding #define RK3588_DSC_8K_SYS_CTRL 0x200 18912ee5af0SDamon Ding #define DSC_PORT_SEL_MASK 0x3 19012ee5af0SDamon Ding #define DSC_PORT_SEL_SHIFT 0 19112ee5af0SDamon Ding #define DSC_MAN_MODE_MASK 0x1 19212ee5af0SDamon Ding #define DSC_MAN_MODE_SHIFT 2 19312ee5af0SDamon Ding #define DSC_INTERFACE_MODE_MASK 0x3 19412ee5af0SDamon Ding #define DSC_INTERFACE_MODE_SHIFT 4 19512ee5af0SDamon Ding #define DSC_PIXEL_NUM_MASK 0x3 19612ee5af0SDamon Ding #define DSC_PIXEL_NUM_SHIFT 6 19712ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_MASK 0x1 19812ee5af0SDamon Ding #define DSC_PXL_CLK_DIV_SHIFT 8 19912ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_MASK 0x3 20012ee5af0SDamon Ding #define DSC_CDS_CLK_DIV_SHIFT 12 20112ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_MASK 0x3 20212ee5af0SDamon Ding #define DSC_TXP_CLK_DIV_SHIFT 14 20312ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_MASK 0x1 20412ee5af0SDamon Ding #define DSC_INIT_DLY_MODE_SHIFT 16 20512ee5af0SDamon Ding #define DSC_SCAN_EN_SHIFT 17 20612ee5af0SDamon Ding #define DSC_HALT_EN_SHIFT 18 20712ee5af0SDamon Ding 20812ee5af0SDamon Ding #define RK3588_DSC_8K_RST 0x204 20912ee5af0SDamon Ding #define RST_DEASSERT_MASK 0x1 21012ee5af0SDamon Ding #define RST_DEASSERT_SHIFT 0 21112ee5af0SDamon Ding 21212ee5af0SDamon Ding #define RK3588_DSC_8K_CFG_DONE 0x208 21312ee5af0SDamon Ding #define DSC_CFG_DONE_SHIFT 0 21412ee5af0SDamon Ding 21512ee5af0SDamon Ding #define RK3588_DSC_8K_INIT_DLY 0x20C 21612ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_MASK 0xffff 21712ee5af0SDamon Ding #define DSC_INIT_DLY_NUM_SHIFT 0 21812ee5af0SDamon Ding #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16 21912ee5af0SDamon Ding 22012ee5af0SDamon Ding #define RK3588_DSC_8K_HTOTAL_HS_END 0x210 22112ee5af0SDamon Ding #define DSC_HTOTAL_PW_MASK 0xffffffff 22212ee5af0SDamon Ding #define DSC_HTOTAL_PW_SHIFT 0 22312ee5af0SDamon Ding 22412ee5af0SDamon Ding #define RK3588_DSC_8K_HACT_ST_END 0x214 22512ee5af0SDamon Ding #define DSC_HACT_ST_END_MASK 0xffffffff 22612ee5af0SDamon Ding #define DSC_HACT_ST_END_SHIFT 0 22712ee5af0SDamon Ding 22812ee5af0SDamon Ding #define RK3588_DSC_8K_VTOTAL_VS_END 0x218 22912ee5af0SDamon Ding #define DSC_VTOTAL_PW_MASK 0xffffffff 23012ee5af0SDamon Ding #define DSC_VTOTAL_PW_SHIFT 0 23112ee5af0SDamon Ding 23212ee5af0SDamon Ding #define RK3588_DSC_8K_VACT_ST_END 0x21C 23312ee5af0SDamon Ding #define DSC_VACT_ST_END_MASK 0xffffffff 23412ee5af0SDamon Ding #define DSC_VACT_ST_END_SHIFT 0 23512ee5af0SDamon Ding 23612ee5af0SDamon Ding #define RK3588_DSC_8K_STATUS 0x220 23712ee5af0SDamon Ding 23863cb669fSSandy Huang /* Overlay registers definition */ 2395fa6e665SDamon Ding #define RK3528_OVL_SYS 0x500 2405fa6e665SDamon Ding #define RK3528_OVL_SYS_PORT_SEL_IMD 0x504 2415fa6e665SDamon Ding #define RK3528_OVL_SYS_GATING_EN_IMD 0x508 2425fa6e665SDamon Ding #define RK3528_OVL_SYS_CLUSTER0_CTRL 0x510 2435fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART0_CTRL 0x520 244452afb13SDamon Ding #define ESMART_DLY_NUM_MASK 0xff 245452afb13SDamon Ding #define ESMART_DLY_NUM_SHIFT 0 2465fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART1_CTRL 0x524 2475fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART2_CTRL 0x528 2485fa6e665SDamon Ding #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C 2495fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530 2505fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 2515fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 2525fa6e665SDamon Ding #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c 2535fa6e665SDamon Ding 2545fa6e665SDamon Ding #define RK3528_OVL_PORT0_CTRL 0x600 25563cb669fSSandy Huang #define RK3568_OVL_CTRL 0x600 256ee01dbb2SDamon Ding #define OVL_MODE_SEL_MASK 0x1 257ee01dbb2SDamon Ding #define OVL_MODE_SEL_SHIFT 0 25863cb669fSSandy Huang #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 2595fa6e665SDamon Ding #define RK3528_OVL_PORT0_LAYER_SEL 0x604 26063cb669fSSandy Huang #define RK3568_OVL_LAYER_SEL 0x604 26163cb669fSSandy Huang #define LAYER_SEL_MASK 0xf 26263cb669fSSandy Huang 26363cb669fSSandy Huang #define RK3568_OVL_PORT_SEL 0x608 26463cb669fSSandy Huang #define PORT_MUX_MASK 0xf 26563cb669fSSandy Huang #define PORT_MUX_SHIFT 0 26663cb669fSSandy Huang #define LAYER_SEL_PORT_MASK 0x3 26763cb669fSSandy Huang #define LAYER_SEL_PORT_SHIFT 16 26863cb669fSSandy Huang 26963cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 27063cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 27163cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 27263cb669fSSandy Huang #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 2735fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620 2745fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624 2755fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628 2765fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C 2775fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630 2785fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634 2795fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638 2805fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C 2815fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640 2825fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644 2835fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648 2845fa6e665SDamon Ding #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C 28563cb669fSSandy Huang #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 28663cb669fSSandy Huang #define RK3568_MIX0_DST_COLOR_CTRL 0x654 28763cb669fSSandy Huang #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 28863cb669fSSandy Huang #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 2895fa6e665SDamon Ding #define RK3528_HDR_SRC_COLOR_CTRL 0x660 2905fa6e665SDamon Ding #define RK3528_HDR_DST_COLOR_CTRL 0x664 2915fa6e665SDamon Ding #define RK3528_HDR_SRC_ALPHA_CTRL 0x668 2925fa6e665SDamon Ding #define RK3528_HDR_DST_ALPHA_CTRL 0x66C 2935fa6e665SDamon Ding #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670 29463cb669fSSandy Huang #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 29563cb669fSSandy Huang #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 29663cb669fSSandy Huang #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 29763cb669fSSandy Huang #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 29863cb669fSSandy Huang #define RK3568_VP0_BG_MIX_CTRL 0x6E0 29963cb669fSSandy Huang #define BG_MIX_CTRL_MASK 0xff 30063cb669fSSandy Huang #define BG_MIX_CTRL_SHIFT 24 30163cb669fSSandy Huang #define RK3568_VP1_BG_MIX_CTRL 0x6E4 30263cb669fSSandy Huang #define RK3568_VP2_BG_MIX_CTRL 0x6E8 30363cb669fSSandy Huang #define RK3568_CLUSTER_DLY_NUM 0x6F0 30463cb669fSSandy Huang #define RK3568_SMART_DLY_NUM 0x6F8 30563cb669fSSandy Huang 3065fa6e665SDamon Ding #define RK3528_OVL_PORT1_CTRL 0x700 3075fa6e665SDamon Ding #define RK3528_OVL_PORT1_LAYER_SEL 0x704 3085fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720 3095fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724 3105fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728 3115fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C 3125fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730 3135fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734 3145fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738 3155fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C 3165fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740 3175fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744 3185fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748 3195fa6e665SDamon Ding #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C 3205fa6e665SDamon Ding #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770 3215fa6e665SDamon Ding 322d0408543SAndy Yan /* Video Port registers definition */ 323d0408543SAndy Yan #define RK3568_VP0_DSP_CTRL 0xC00 324d0408543SAndy Yan #define OUT_MODE_MASK 0xf 325d0408543SAndy Yan #define OUT_MODE_SHIFT 0 32610ee9f5bSAlgea Cao #define DATA_SWAP_MASK 0x1f 32710ee9f5bSAlgea Cao #define DATA_SWAP_SHIFT 8 32865747de7SDamon Ding #define DSP_BG_SWAP 0x1 32965747de7SDamon Ding #define DSP_RB_SWAP 0x2 33065747de7SDamon Ding #define DSP_RG_SWAP 0x4 33165747de7SDamon Ding #define DSP_DELTA_SWAP 0x8 33210ee9f5bSAlgea Cao #define CORE_DCLK_DIV_EN_SHIFT 4 333d0408543SAndy Yan #define P2I_EN_SHIFT 5 3347a20be36SSandy Huang #define DSP_FILED_POL 6 335d0408543SAndy Yan #define INTERLACE_EN_SHIFT 7 336c2b1fe35SDamon Ding #define DSP_X_MIR_EN_SHIFT 13 33710ee9f5bSAlgea Cao #define POST_DSP_OUT_R2Y_SHIFT 15 338d0408543SAndy Yan #define PRE_DITHER_DOWN_EN_SHIFT 16 339d0408543SAndy Yan #define DITHER_DOWN_EN_SHIFT 17 340452afb13SDamon Ding #define DITHER_DOWN_MODE_SHIFT 20 341db328a0dSDamon Ding #define GAMMA_UPDATE_EN_SHIFT 22 3421147facaSSandy Huang #define DSP_LUT_EN_SHIFT 28 3431147facaSSandy Huang 344d0408543SAndy Yan #define STANDBY_EN_SHIFT 31 345d0408543SAndy Yan 346d0408543SAndy Yan #define RK3568_VP0_MIPI_CTRL 0xC04 34710ee9f5bSAlgea Cao #define DCLK_DIV2_SHIFT 4 34810ee9f5bSAlgea Cao #define DCLK_DIV2_MASK 0x3 349d0408543SAndy Yan #define MIPI_DUAL_EN_SHIFT 20 350d0408543SAndy Yan #define MIPI_DUAL_SWAP_EN_SHIFT 21 35141874944SGuochun Huang #define EDPI_TE_EN 28 35241874944SGuochun Huang #define EDPI_WMS_HOLD_EN 30 35341874944SGuochun Huang #define EDPI_WMS_FS 31 35441874944SGuochun Huang 355d0408543SAndy Yan 356d0408543SAndy Yan #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 3575fa6e665SDamon Ding 3585fa6e665SDamon Ding #define RK3568_VP0_DCLK_SEL 0xC0C 3595fa6e665SDamon Ding 3606414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_CTRL 0xC10 3616414e3bcSSandy Huang #define VP0_3D_LUT_EN_SHIFT 0 3626414e3bcSSandy Huang #define VP0_3D_LUT_UPDATE_SHIFT 2 3636414e3bcSSandy Huang 364ecc31b6eSAndy Yan #define RK3588_VP0_CLK_CTRL 0xC0C 365ecc31b6eSAndy Yan #define DCLK_CORE_DIV_SHIFT 0 366ecc31b6eSAndy Yan #define DCLK_OUT_DIV_SHIFT 2 367ecc31b6eSAndy Yan 3686414e3bcSSandy Huang #define RK3568_VP0_3D_LUT_MST 0xC20 3696414e3bcSSandy Huang 370d0408543SAndy Yan #define RK3568_VP0_DSP_BG 0xC2C 371d0408543SAndy Yan #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 372d0408543SAndy Yan #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 373d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 374d0408543SAndy Yan #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 375d0408543SAndy Yan #define RK3568_VP0_POST_SCL_CTRL 0xC40 376d0408543SAndy Yan #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 377d0408543SAndy Yan #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 378d0408543SAndy Yan #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 379d0408543SAndy Yan #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 380d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END 0xC54 381d0408543SAndy Yan #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 382d0408543SAndy Yan #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 383d0408543SAndy Yan 384ac500a1fSSandy Huang #define RK3568_VP0_BCSH_CTRL 0xC60 385ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_SHIFT 0 386ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_MASK 0x1 387ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 388ac500a1fSSandy Huang #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 389ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_SHIFT 4 390ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_MASK 0x1 391ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 392ac500a1fSSandy Huang #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 393ac500a1fSSandy Huang 394ac500a1fSSandy Huang #define RK3568_VP0_BCSH_BCS 0xC64 395ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_SHIFT 0 396ac500a1fSSandy Huang #define BCSH_BRIGHTNESS_MASK 0xFF 397ac500a1fSSandy Huang #define BCSH_CONTRAST_SHIFT 8 398ac500a1fSSandy Huang #define BCSH_CONTRAST_MASK 0x1FF 399ac500a1fSSandy Huang #define BCSH_SATURATION_SHIFT 20 400ac500a1fSSandy Huang #define BCSH_SATURATION_MASK 0x3FF 401ac500a1fSSandy Huang #define BCSH_OUT_MODE_SHIFT 30 402ac500a1fSSandy Huang #define BCSH_OUT_MODE_MASK 0x3 403ac500a1fSSandy Huang 404ac500a1fSSandy Huang #define RK3568_VP0_BCSH_H 0xC68 405ac500a1fSSandy Huang #define BCSH_SIN_HUE_SHIFT 0 406ac500a1fSSandy Huang #define BCSH_SIN_HUE_MASK 0x1FF 407ac500a1fSSandy Huang #define BCSH_COS_HUE_SHIFT 16 408ac500a1fSSandy Huang #define BCSH_COS_HUE_MASK 0x1FF 409ac500a1fSSandy Huang 410ac500a1fSSandy Huang #define RK3568_VP0_BCSH_COLOR 0xC6C 411ac500a1fSSandy Huang #define BCSH_EN_SHIFT 31 412ac500a1fSSandy Huang #define BCSH_EN_MASK 1 413ac500a1fSSandy Huang 4146027c871SZhang Yubing #define RK3528_VP0_ACM_CTRL 0xCD0 4156027c871SZhang Yubing #define POST_CSC_COE00_MASK 0xFFFF 4166027c871SZhang Yubing #define POST_CSC_COE00_SHIFT 16 4176027c871SZhang Yubing #define POST_R2Y_MODE_MASK 0x7 4186027c871SZhang Yubing #define POST_R2Y_MODE_SHIFT 8 4196027c871SZhang Yubing #define POST_CSC_MODE_MASK 0x7 4206027c871SZhang Yubing #define POST_CSC_MODE_SHIFT 3 4216027c871SZhang Yubing #define POST_R2Y_EN_MASK 0x1 4226027c871SZhang Yubing #define POST_R2Y_EN_SHIFT 2 4236027c871SZhang Yubing #define POST_CSC_EN_MASK 0x1 4246027c871SZhang Yubing #define POST_CSC_EN_SHIFT 1 4256027c871SZhang Yubing #define POST_ACM_BYPASS_EN_MASK 0x1 4266027c871SZhang Yubing #define POST_ACM_BYPASS_EN_SHIFT 0 4276027c871SZhang Yubing #define RK3528_VP0_CSC_COE01_02 0xCD4 4286027c871SZhang Yubing #define RK3528_VP0_CSC_COE10_11 0xCD8 4296027c871SZhang Yubing #define RK3528_VP0_CSC_COE12_20 0xCDC 4306027c871SZhang Yubing #define RK3528_VP0_CSC_COE21_22 0xCE0 4316027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET0 0xCE4 4326027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET1 0xCE8 4336027c871SZhang Yubing #define RK3528_VP0_CSC_OFFSET2 0xCEC 4346027c871SZhang Yubing 4350675a2a4SDamon Ding #define RK3562_VP0_MCU_CTRL 0xCF8 4360675a2a4SDamon Ding #define MCU_TYPE_SHIFT 31 4370675a2a4SDamon Ding #define MCU_BYPASS_SHIFT 30 4380675a2a4SDamon Ding #define MCU_RS_SHIFT 29 4390675a2a4SDamon Ding #define MCU_FRAME_ST_SHIFT 28 4400675a2a4SDamon Ding #define MCU_HOLD_MODE_SHIFT 27 4410675a2a4SDamon Ding #define MCU_CLK_SEL_SHIFT 26 4420675a2a4SDamon Ding #define MCU_CLK_SEL_MASK 0x1 4430675a2a4SDamon Ding #define MCU_RW_PEND_SHIFT 20 4440675a2a4SDamon Ding #define MCU_RW_PEND_MASK 0x3F 4450675a2a4SDamon Ding #define MCU_RW_PST_SHIFT 16 4460675a2a4SDamon Ding #define MCU_RW_PST_MASK 0xF 4470675a2a4SDamon Ding #define MCU_CS_PEND_SHIFT 10 4480675a2a4SDamon Ding #define MCU_CS_PEND_MASK 0x3F 4490675a2a4SDamon Ding #define MCU_CS_PST_SHIFT 6 4500675a2a4SDamon Ding #define MCU_CS_PST_MASK 0xF 4510675a2a4SDamon Ding #define MCU_PIX_TOTAL_SHIFT 0 4520675a2a4SDamon Ding #define MCU_PIX_TOTAL_MASK 0x3F 4530675a2a4SDamon Ding 4540675a2a4SDamon Ding #define RK3562_VP0_MCU_RW_BYPASS_PORT 0xCFC 4550675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_SHIFT 0 4560675a2a4SDamon Ding #define MCU_WRITE_DATA_BYPASS_MASK 0xFFFFFFFF 4570675a2a4SDamon Ding 458d0408543SAndy Yan #define RK3568_VP1_DSP_CTRL 0xD00 459d0408543SAndy Yan #define RK3568_VP1_MIPI_CTRL 0xD04 460d0408543SAndy Yan #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 461d0408543SAndy Yan #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 462d0408543SAndy Yan #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 463d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 464d0408543SAndy Yan #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 465d0408543SAndy Yan #define RK3568_VP1_POST_SCL_CTRL 0xD40 466d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_INFO 0xD34 467d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_INFO 0xD38 468d0408543SAndy Yan #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 469d0408543SAndy Yan #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 470d0408543SAndy Yan #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 471d0408543SAndy Yan #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 472d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END 0xD54 473d0408543SAndy Yan #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 474d0408543SAndy Yan #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 475d0408543SAndy Yan 476d0408543SAndy Yan #define RK3568_VP2_DSP_CTRL 0xE00 477d0408543SAndy Yan #define RK3568_VP2_MIPI_CTRL 0xE04 478d0408543SAndy Yan #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 479d0408543SAndy Yan #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 480d0408543SAndy Yan #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 481d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 482d0408543SAndy Yan #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 483d0408543SAndy Yan #define RK3568_VP2_POST_SCL_CTRL 0xE40 484d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_INFO 0xE34 485d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_INFO 0xE38 486d0408543SAndy Yan #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 487d0408543SAndy Yan #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 488d0408543SAndy Yan #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 489d0408543SAndy Yan #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 490d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END 0xE54 491d0408543SAndy Yan #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 492d0408543SAndy Yan #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 493d0408543SAndy Yan 494d0408543SAndy Yan /* Cluster0 register definition */ 495d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 496ecc31b6eSAndy Yan #define CLUSTER_YUV2RGB_EN_SHIFT 8 497ecc31b6eSAndy Yan #define CLUSTER_RGB2YUV_EN_SHIFT 9 498ecc31b6eSAndy Yan #define CLUSTER_CSC_MODE_SHIFT 10 499840bf541SDamon Ding #define CLUSTER_DITHER_UP_EN_SHIFT 18 500d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 5015fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12 5025fa6e665SDamon Ding #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 5035fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 5045fa6e665SDamon Ding #define AVG2_MASK 0x1 5055fa6e665SDamon Ding #define CLUSTER_AVG2_SHIFT 18 5065fa6e665SDamon Ding #define AVG4_MASK 0x1 5075fa6e665SDamon Ding #define CLUSTER_AVG4_SHIFT 19 5085fa6e665SDamon Ding #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22 5095fa6e665SDamon Ding #define CLUSTER_XGT_EN_SHIFT 24 5105fa6e665SDamon Ding #define XGT_MODE_MASK 0x3 5115fa6e665SDamon Ding #define CLUSTER_XGT_MODE_SHIFT 25 5125fa6e665SDamon Ding #define CLUSTER_XAVG_EN_SHIFT 27 513ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT2_SHIFT 28 514ecc31b6eSAndy Yan #define CLUSTER_YRGB_GT4_SHIFT 29 515a33b790fSDamon Ding #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008 516a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_MASK 0x1f 517a33b790fSDamon Ding #define CLUSTER_AXI_YRGB_ID_SHIFT 0 518a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_MASK 0x1f 519a33b790fSDamon Ding #define CLUSTER_AXI_UV_ID_SHIFT 5 520a33b790fSDamon Ding 521d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 522d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 523d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_VIR 0x1018 524d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 525d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 526d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 527d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 528d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 529d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 530d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 531d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 532d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 533d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 534d0408543SAndy Yan #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 535a59754e1SDamon Ding #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT 7 536d0408543SAndy Yan 537d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 538d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 539d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 540d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 541d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_VIR 0x1098 542d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 543d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 544d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 545d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 546d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 547d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 548d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 549d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 550d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 551d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 552d0408543SAndy Yan #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 553d0408543SAndy Yan 554d0408543SAndy Yan #define RK3568_CLUSTER0_CTRL 0x1100 555ecc31b6eSAndy Yan #define CLUSTER_EN_SHIFT 0 556a33b790fSDamon Ding #define CLUSTER_AXI_ID_MASK 0x1 557a33b790fSDamon Ding #define CLUSTER_AXI_ID_SHIFT 13 558d0408543SAndy Yan 559d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 560d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 561d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 562d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 563d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_VIR 0x1218 564d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 565d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 566d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 567d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 568d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 569d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 570d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 571d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 572d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 573d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 574d0408543SAndy Yan #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 575d0408543SAndy Yan 576d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 577d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 578d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 579d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 580d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_VIR 0x1298 581d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 582d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 583d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 584d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 585d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 586d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 587d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 588d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 589d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 590d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 591d0408543SAndy Yan #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 592d0408543SAndy Yan 593d0408543SAndy Yan #define RK3568_CLUSTER1_CTRL 0x1300 594d0408543SAndy Yan 595d0408543SAndy Yan /* Esmart register definition */ 596d0408543SAndy Yan #define RK3568_ESMART0_CTRL0 0x1800 59710ee9f5bSAlgea Cao #define RGB2YUV_EN_SHIFT 1 59810ee9f5bSAlgea Cao #define CSC_MODE_SHIFT 2 59910ee9f5bSAlgea Cao #define CSC_MODE_MASK 0x3 6005fa6e665SDamon Ding #define ESMART_LB_SELECT_SHIFT 12 6015fa6e665SDamon Ding #define ESMART_LB_SELECT_MASK 0x3 602d0408543SAndy Yan 603d0408543SAndy Yan #define RK3568_ESMART0_CTRL1 0x1804 604a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_MASK 0x1f 605a33b790fSDamon Ding #define ESMART_AXI_YRGB_ID_SHIFT 4 606a33b790fSDamon Ding #define ESMART_AXI_UV_ID_MASK 0x1f 607a33b790fSDamon Ding #define ESMART_AXI_UV_ID_SHIFT 12 608d0408543SAndy Yan #define YMIRROR_EN_SHIFT 31 609a33b790fSDamon Ding 610a33b790fSDamon Ding #define RK3568_ESMART0_AXI_CTRL 0x1808 611a33b790fSDamon Ding #define ESMART_AXI_ID_MASK 0x1 612a33b790fSDamon Ding #define ESMART_AXI_ID_SHIFT 1 613a33b790fSDamon Ding 614d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CTRL 0x1810 615d0408543SAndy Yan #define WIN_EN_SHIFT 0 616d0408543SAndy Yan #define WIN_FORMAT_MASK 0x1f 617d0408543SAndy Yan #define WIN_FORMAT_SHIFT 1 618840bf541SDamon Ding #define REGION0_DITHER_UP_EN_SHIFT 12 6195fa6e665SDamon Ding #define REGION0_RB_SWAP_SHIFT 14 6205fa6e665SDamon Ding #define ESMART_XAVG_EN_SHIFT 20 6215fa6e665SDamon Ding #define ESMART_XGT_EN_SHIFT 21 6225fa6e665SDamon Ding #define ESMART_XGT_MODE_SHIFT 22 623d0408543SAndy Yan 624d0408543SAndy Yan #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 625d0408543SAndy Yan #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 626d0408543SAndy Yan #define RK3568_ESMART0_REGION0_VIR 0x181C 627d0408543SAndy Yan #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 628d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 629d0408543SAndy Yan #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 630d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 6313e39a5a1SSandy Huang #define YRGB_XSCL_MODE_MASK 0x3 6323e39a5a1SSandy Huang #define YRGB_XSCL_MODE_SHIFT 0 6333e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_MASK 0x3 6343e39a5a1SSandy Huang #define YRGB_XSCL_FILTER_MODE_SHIFT 2 6353e39a5a1SSandy Huang #define YRGB_YSCL_MODE_MASK 0x3 6363e39a5a1SSandy Huang #define YRGB_YSCL_MODE_SHIFT 4 6373e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_MASK 0x3 6383e39a5a1SSandy Huang #define YRGB_YSCL_FILTER_MODE_SHIFT 6 6393e39a5a1SSandy Huang 640d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 641d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 642d0408543SAndy Yan #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 643d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CTRL 0x1840 6443e39a5a1SSandy Huang #define YRGB_GT2_MASK 0x1 6453e39a5a1SSandy Huang #define YRGB_GT2_SHIFT 8 6463e39a5a1SSandy Huang #define YRGB_GT4_MASK 0x1 6473e39a5a1SSandy Huang #define YRGB_GT4_SHIFT 9 6483e39a5a1SSandy Huang 649d0408543SAndy Yan #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 650d0408543SAndy Yan #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 651d0408543SAndy Yan #define RK3568_ESMART0_REGION1_VIR 0x184C 652d0408543SAndy Yan #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 653d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 654d0408543SAndy Yan #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 655d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 656d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 657d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 658d0408543SAndy Yan #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 659d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CTRL 0x1870 660d0408543SAndy Yan #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 661d0408543SAndy Yan #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 662d0408543SAndy Yan #define RK3568_ESMART0_REGION2_VIR 0x187C 663d0408543SAndy Yan #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 664d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 665d0408543SAndy Yan #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 666d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 667d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 668d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 669d0408543SAndy Yan #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 670d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CTRL 0x18A0 671d0408543SAndy Yan #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 672d0408543SAndy Yan #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 673d0408543SAndy Yan #define RK3568_ESMART0_REGION3_VIR 0x18AC 674d0408543SAndy Yan #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 675d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 676d0408543SAndy Yan #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 677d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 678d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 679d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 680d0408543SAndy Yan #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 681d0408543SAndy Yan 682d0408543SAndy Yan #define RK3568_ESMART1_CTRL0 0x1A00 683d0408543SAndy Yan #define RK3568_ESMART1_CTRL1 0x1A04 684d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CTRL 0x1A10 685d0408543SAndy Yan #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 686d0408543SAndy Yan #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 687d0408543SAndy Yan #define RK3568_ESMART1_REGION0_VIR 0x1A1C 688d0408543SAndy Yan #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 689d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 690d0408543SAndy Yan #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 691d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 692d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 693d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 694d0408543SAndy Yan #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 695d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CTRL 0x1A40 696d0408543SAndy Yan #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 697d0408543SAndy Yan #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 698d0408543SAndy Yan #define RK3568_ESMART1_REGION1_VIR 0x1A4C 699d0408543SAndy Yan #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 700d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 701d0408543SAndy Yan #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 702d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 703d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 704d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 705d0408543SAndy Yan #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 706d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CTRL 0x1A70 707d0408543SAndy Yan #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 708d0408543SAndy Yan #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 709d0408543SAndy Yan #define RK3568_ESMART1_REGION2_VIR 0x1A7C 710d0408543SAndy Yan #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 711d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 712d0408543SAndy Yan #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 713d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 714d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 715d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 716d0408543SAndy Yan #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 717d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 718d0408543SAndy Yan #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 719d0408543SAndy Yan #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 720d0408543SAndy Yan #define RK3568_ESMART1_REGION3_VIR 0x1AAC 721d0408543SAndy Yan #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 722d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 723d0408543SAndy Yan #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 724d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 725d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 726d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 727d0408543SAndy Yan #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 728d0408543SAndy Yan 729d0408543SAndy Yan #define RK3568_SMART0_CTRL0 0x1C00 730d0408543SAndy Yan #define RK3568_SMART0_CTRL1 0x1C04 731d0408543SAndy Yan #define RK3568_SMART0_REGION0_CTRL 0x1C10 732d0408543SAndy Yan #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 733d0408543SAndy Yan #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 734d0408543SAndy Yan #define RK3568_SMART0_REGION0_VIR 0x1C1C 735d0408543SAndy Yan #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 736d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 737d0408543SAndy Yan #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 738d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 739d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 740d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 741d0408543SAndy Yan #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 742d0408543SAndy Yan #define RK3568_SMART0_REGION1_CTRL 0x1C40 743d0408543SAndy Yan #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 744d0408543SAndy Yan #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 745d0408543SAndy Yan #define RK3568_SMART0_REGION1_VIR 0x1C4C 746d0408543SAndy Yan #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 747d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 748d0408543SAndy Yan #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 749d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 750d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 751d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 752d0408543SAndy Yan #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 753d0408543SAndy Yan #define RK3568_SMART0_REGION2_CTRL 0x1C70 754d0408543SAndy Yan #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 755d0408543SAndy Yan #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 756d0408543SAndy Yan #define RK3568_SMART0_REGION2_VIR 0x1C7C 757d0408543SAndy Yan #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 758d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 759d0408543SAndy Yan #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 760d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 761d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 762d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 763d0408543SAndy Yan #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 764d0408543SAndy Yan #define RK3568_SMART0_REGION3_CTRL 0x1CA0 765d0408543SAndy Yan #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 766d0408543SAndy Yan #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 767d0408543SAndy Yan #define RK3568_SMART0_REGION3_VIR 0x1CAC 768d0408543SAndy Yan #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 769d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 770d0408543SAndy Yan #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 771d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 772d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 773d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 774d0408543SAndy Yan #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 775d0408543SAndy Yan 776d0408543SAndy Yan #define RK3568_SMART1_CTRL0 0x1E00 777d0408543SAndy Yan #define RK3568_SMART1_CTRL1 0x1E04 778d0408543SAndy Yan #define RK3568_SMART1_REGION0_CTRL 0x1E10 779d0408543SAndy Yan #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 780d0408543SAndy Yan #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 781d0408543SAndy Yan #define RK3568_SMART1_REGION0_VIR 0x1E1C 782d0408543SAndy Yan #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 783d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 784d0408543SAndy Yan #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 785d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 786d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 787d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 788d0408543SAndy Yan #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 789d0408543SAndy Yan #define RK3568_SMART1_REGION1_CTRL 0x1E40 790d0408543SAndy Yan #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 791d0408543SAndy Yan #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 792d0408543SAndy Yan #define RK3568_SMART1_REGION1_VIR 0x1E4C 793d0408543SAndy Yan #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 794d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 795d0408543SAndy Yan #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 796d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 797d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 798d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 799d0408543SAndy Yan #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 800d0408543SAndy Yan #define RK3568_SMART1_REGION2_CTRL 0x1E70 801d0408543SAndy Yan #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 802d0408543SAndy Yan #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 803d0408543SAndy Yan #define RK3568_SMART1_REGION2_VIR 0x1E7C 804d0408543SAndy Yan #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 805d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 806d0408543SAndy Yan #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 807d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 808d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 809d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 810d0408543SAndy Yan #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 811d0408543SAndy Yan #define RK3568_SMART1_REGION3_CTRL 0x1EA0 812d0408543SAndy Yan #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 813d0408543SAndy Yan #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 814d0408543SAndy Yan #define RK3568_SMART1_REGION3_VIR 0x1EAC 815d0408543SAndy Yan #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 816d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 817d0408543SAndy Yan #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 818d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 819d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 820d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 821d0408543SAndy Yan #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 822d0408543SAndy Yan 82372388c26SDamon Ding /* HDR register definition */ 82472388c26SDamon Ding #define RK3568_HDR_LUT_CTRL 0x2000 82572388c26SDamon Ding 82672388c26SDamon Ding #define RK3588_VP3_DSP_CTRL 0xF00 82772388c26SDamon Ding #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400 82872388c26SDamon Ding #define RK3588_CLUSTER3_WIN0_CTRL0 0x1600 82972388c26SDamon Ding 83012ee5af0SDamon Ding /* DSC 8K/4K register definition */ 83112ee5af0SDamon Ding #define RK3588_DSC_8K_PPS0_3 0x4000 83212ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL0 0x40A0 83312ee5af0SDamon Ding #define DSC_EN_SHIFT 0 83412ee5af0SDamon Ding #define DSC_RBIT_SHIFT 2 83512ee5af0SDamon Ding #define DSC_RBYT_SHIFT 3 83612ee5af0SDamon Ding #define DSC_FLAL_SHIFT 4 83712ee5af0SDamon Ding #define DSC_MER_SHIFT 5 83812ee5af0SDamon Ding #define DSC_EPB_SHIFT 6 83912ee5af0SDamon Ding #define DSC_EPL_SHIFT 7 8401ace1b6dSDamon Ding #define DSC_NSLC_MASK 0x7 84112ee5af0SDamon Ding #define DSC_NSLC_SHIFT 16 84212ee5af0SDamon Ding #define DSC_SBO_SHIFT 28 84312ee5af0SDamon Ding #define DSC_IFEP_SHIFT 29 84412ee5af0SDamon Ding #define DSC_PPS_UPD_SHIFT 31 845baf2c414SDamon Ding #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \ 846baf2c414SDamon Ding (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \ 847baf2c414SDamon Ding (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT)) 84812ee5af0SDamon Ding 84912ee5af0SDamon Ding #define RK3588_DSC_8K_CTRL1 0x40A4 85012ee5af0SDamon Ding #define RK3588_DSC_8K_STS0 0x40A8 85112ee5af0SDamon Ding #define RK3588_DSC_8K_ERS 0x40C4 85212ee5af0SDamon Ding 85312ee5af0SDamon Ding #define RK3588_DSC_4K_PPS0_3 0x4100 85412ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL0 0x41A0 85512ee5af0SDamon Ding #define RK3588_DSC_4K_CTRL1 0x41A4 85612ee5af0SDamon Ding #define RK3588_DSC_4K_STS0 0x41A8 85712ee5af0SDamon Ding #define RK3588_DSC_4K_ERS 0x41C4 85812ee5af0SDamon Ding 85972388c26SDamon Ding /* RK3528 HDR register definition */ 86072388c26SDamon Ding #define RK3528_HDR_LUT_CTRL 0x2000 86172388c26SDamon Ding 8626027c871SZhang Yubing /* RK3528 ACM register definition */ 8636027c871SZhang Yubing #define RK3528_ACM_CTRL 0x6400 8646027c871SZhang Yubing #define RK3528_ACM_DELTA_RANGE 0x6404 8656027c871SZhang Yubing #define RK3528_ACM_FETCH_START 0x6408 8666027c871SZhang Yubing #define RK3528_ACM_FETCH_DONE 0x6420 8676027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500 8686027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760 8696027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764 8706027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4 8716027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8 8726027c871SZhang Yubing #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8 8736027c871SZhang Yubing 874d0408543SAndy Yan #define RK3568_MAX_REG 0x1ED0 875d0408543SAndy Yan 876452afb13SDamon Ding #define RK3562_GRF_IOC_VO_IO_CON 0x10500 87752ee18acSSandy Huang #define RK3568_GRF_VO_CON1 0x0364 87852ee18acSSandy Huang #define GRF_BT656_CLK_INV_SHIFT 1 87952ee18acSSandy Huang #define GRF_BT1120_CLK_INV_SHIFT 2 88052ee18acSSandy Huang #define GRF_RGB_DCLK_INV_SHIFT 3 88152ee18acSSandy Huang 882ecc31b6eSAndy Yan #define RK3588_GRF_VOP_CON2 0x0008 883ecc31b6eSAndy Yan #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 884ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 885ecc31b6eSAndy Yan #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 886ecc31b6eSAndy Yan #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 887ecc31b6eSAndy Yan 888b890760eSAlgea Cao #define RK3588_GRF_VO1_CON0 0x0000 889b890760eSAlgea Cao #define HDMI_SYNC_POL_MASK 0x3 890b890760eSAlgea Cao #define HDMI0_SYNC_POL_SHIFT 5 891b890760eSAlgea Cao #define HDMI1_SYNC_POL_SHIFT 7 892b890760eSAlgea Cao 89360e469f5SDamon Ding #define RK3588_PMU_BISR_CON3 0x20C 89460e469f5SDamon Ding #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 89560e469f5SDamon Ding #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 89660e469f5SDamon Ding #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 89760e469f5SDamon Ding #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 898b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13 899b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14 90060e469f5SDamon Ding #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 90160e469f5SDamon Ding 90260e469f5SDamon Ding #define RK3588_PMU_BISR_STATUS5 0x294 90360e469f5SDamon Ding #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 90460e469f5SDamon Ding #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 90560e469f5SDamon Ding #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 90660e469f5SDamon Ding #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 907b6ba80b4SDamon Ding #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13 908b6ba80b4SDamon Ding #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14 90960e469f5SDamon Ding #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 91060e469f5SDamon Ding 911d0408543SAndy Yan #define VOP2_LAYER_MAX 8 91263cb669fSSandy Huang 913ee01dbb2SDamon Ding #define VOP2_MAX_VP_OUTPUT_WIDTH 4096 914ee01dbb2SDamon Ding 91563cb669fSSandy Huang #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 916d0408543SAndy Yan 917631ee99aSZhang Yubing /* KHz */ 918631ee99aSZhang Yubing #define VOP2_MAX_DCLK_RATE 600000 919631ee99aSZhang Yubing 920b6ba80b4SDamon Ding /* 921b6ba80b4SDamon Ding * vop2 dsc id 922b6ba80b4SDamon Ding */ 923b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_8K 0 924b6ba80b4SDamon Ding #define ROCKCHIP_VOP2_DSC_4K 1 925b6ba80b4SDamon Ding 926b6ba80b4SDamon Ding /* 927b6ba80b4SDamon Ding * vop2 internal power domain id, 928b6ba80b4SDamon Ding * should be all none zero, 0 will be 929b6ba80b4SDamon Ding * treat as invalid; 930b6ba80b4SDamon Ding */ 931b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER0 BIT(0) 932b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER1 BIT(1) 933b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER2 BIT(2) 934b6ba80b4SDamon Ding #define VOP2_PD_CLUSTER3 BIT(3) 935b6ba80b4SDamon Ding #define VOP2_PD_DSC_8K BIT(5) 936b6ba80b4SDamon Ding #define VOP2_PD_DSC_4K BIT(6) 937b6ba80b4SDamon Ding #define VOP2_PD_ESMART BIT(7) 938b6ba80b4SDamon Ding 9394c765862SDamon Ding #define VOP2_PLANE_NO_SCALING BIT(16) 9404c765862SDamon Ding 9415fa6e665SDamon Ding #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 9425fa6e665SDamon Ding #define VOP_FEATURE_AFBDC BIT(1) 9435fa6e665SDamon Ding #define VOP_FEATURE_ALPHA_SCALE BIT(2) 9445fa6e665SDamon Ding #define VOP_FEATURE_HDR10 BIT(3) 9455fa6e665SDamon Ding #define VOP_FEATURE_NEXT_HDR BIT(4) 9465fa6e665SDamon Ding /* a feature to splice two windows and two vps to support resolution > 4096 */ 9475fa6e665SDamon Ding #define VOP_FEATURE_SPLICE BIT(5) 9485fa6e665SDamon Ding #define VOP_FEATURE_OVERSCAN BIT(6) 9496027c871SZhang Yubing #define VOP_FEATURE_VIVID_HDR BIT(7) 9506027c871SZhang Yubing #define VOP_FEATURE_POST_ACM BIT(8) 9516027c871SZhang Yubing #define VOP_FEATURE_POST_CSC BIT(9) 9525fa6e665SDamon Ding 9535fa6e665SDamon Ding #define WIN_FEATURE_HDR2SDR BIT(0) 9545fa6e665SDamon Ding #define WIN_FEATURE_SDR2HDR BIT(1) 9555fa6e665SDamon Ding #define WIN_FEATURE_PRE_OVERLAY BIT(2) 9565fa6e665SDamon Ding #define WIN_FEATURE_AFBDC BIT(3) 9575fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_MAIN BIT(4) 9585fa6e665SDamon Ding #define WIN_FEATURE_CLUSTER_SUB BIT(5) 9595fa6e665SDamon Ding /* a mirror win can only get fb address 9605fa6e665SDamon Ding * from source win: 9615fa6e665SDamon Ding * Cluster1---->Cluster0 9625fa6e665SDamon Ding * Esmart1 ---->Esmart0 9635fa6e665SDamon Ding * Smart1 ---->Smart0 9645fa6e665SDamon Ding * This is a feather on rk3566 9655fa6e665SDamon Ding */ 9665fa6e665SDamon Ding #define WIN_FEATURE_MIRROR BIT(6) 9675fa6e665SDamon Ding #define WIN_FEATURE_MULTI_AREA BIT(7) 9685fa6e665SDamon Ding #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8) 9695fa6e665SDamon Ding 9705fa6e665SDamon Ding #define V4L2_COLORSPACE_BT709F 0xfe 9715fa6e665SDamon Ding #define V4L2_COLORSPACE_BT2020F 0xff 9725fa6e665SDamon Ding 9735fa6e665SDamon Ding enum vop_csc_format { 97410ee9f5bSAlgea Cao CSC_BT601L, 97510ee9f5bSAlgea Cao CSC_BT709L, 97610ee9f5bSAlgea Cao CSC_BT601F, 97710ee9f5bSAlgea Cao CSC_BT2020, 9785fa6e665SDamon Ding CSC_BT709L_13BIT, 9795fa6e665SDamon Ding CSC_BT709F_13BIT, 9805fa6e665SDamon Ding CSC_BT2020L_13BIT, 9815fa6e665SDamon Ding CSC_BT2020F_13BIT, 9825fa6e665SDamon Ding }; 9835fa6e665SDamon Ding 9845fa6e665SDamon Ding enum vop_csc_bit_depth { 9855fa6e665SDamon Ding CSC_10BIT_DEPTH, 9865fa6e665SDamon Ding CSC_13BIT_DEPTH, 98710ee9f5bSAlgea Cao }; 98810ee9f5bSAlgea Cao 98910ee9f5bSAlgea Cao enum vop2_pol { 99010ee9f5bSAlgea Cao HSYNC_POSITIVE = 0, 99110ee9f5bSAlgea Cao VSYNC_POSITIVE = 1, 99210ee9f5bSAlgea Cao DEN_NEGATIVE = 2, 99310ee9f5bSAlgea Cao DCLK_INVERT = 3 99410ee9f5bSAlgea Cao }; 99510ee9f5bSAlgea Cao 996ac500a1fSSandy Huang enum vop2_bcsh_out_mode { 997ac500a1fSSandy Huang BCSH_OUT_MODE_BLACK, 998ac500a1fSSandy Huang BCSH_OUT_MODE_BLUE, 999ac500a1fSSandy Huang BCSH_OUT_MODE_COLOR_BAR, 1000ac500a1fSSandy Huang BCSH_OUT_MODE_NORMAL_VIDEO, 1001ac500a1fSSandy Huang }; 1002ac500a1fSSandy Huang 1003d0408543SAndy Yan #define _VOP_REG(off, _mask, _shift, _write_mask) \ 1004d0408543SAndy Yan { \ 1005d0408543SAndy Yan .offset = off, \ 1006d0408543SAndy Yan .mask = _mask, \ 1007d0408543SAndy Yan .shift = _shift, \ 1008d0408543SAndy Yan .write_mask = _write_mask, \ 1009d0408543SAndy Yan } 1010d0408543SAndy Yan 1011d0408543SAndy Yan #define VOP_REG(off, _mask, _shift) \ 1012d0408543SAndy Yan _VOP_REG(off, _mask, _shift, false) 1013d0408543SAndy Yan enum dither_down_mode { 1014d0408543SAndy Yan RGB888_TO_RGB565 = 0x0, 1015d0408543SAndy Yan RGB888_TO_RGB666 = 0x1 1016d0408543SAndy Yan }; 1017d0408543SAndy Yan 1018d0408543SAndy Yan enum vop2_video_ports_id { 1019d0408543SAndy Yan VOP2_VP0, 1020d0408543SAndy Yan VOP2_VP1, 1021d0408543SAndy Yan VOP2_VP2, 1022d0408543SAndy Yan VOP2_VP3, 1023d0408543SAndy Yan VOP2_VP_MAX, 1024d0408543SAndy Yan }; 1025d0408543SAndy Yan 1026ee008497SSandy Huang enum vop2_layer_type { 1027ee008497SSandy Huang CLUSTER_LAYER = 0, 1028ee008497SSandy Huang ESMART_LAYER = 1, 1029ee008497SSandy Huang SMART_LAYER = 2, 1030ee008497SSandy Huang }; 1031ee008497SSandy Huang 1032b0989546SSandy Huang /* This define must same with kernel win phy id */ 1033b0989546SSandy Huang enum vop2_layer_phy_id { 1034b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0 = 0, 1035b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, 1036b0989546SSandy Huang ROCKCHIP_VOP2_ESMART0, 1037b0989546SSandy Huang ROCKCHIP_VOP2_ESMART1, 1038b0989546SSandy Huang ROCKCHIP_VOP2_SMART0, 1039b0989546SSandy Huang ROCKCHIP_VOP2_SMART1, 1040b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER2, 1041b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER3, 1042b0989546SSandy Huang ROCKCHIP_VOP2_ESMART2, 1043b0989546SSandy Huang ROCKCHIP_VOP2_ESMART3, 1044ee008497SSandy Huang ROCKCHIP_VOP2_LAYER_MAX, 1045d0408543SAndy Yan }; 1046d0408543SAndy Yan 10473e39a5a1SSandy Huang enum vop2_scale_up_mode { 10483e39a5a1SSandy Huang VOP2_SCALE_UP_NRST_NBOR, 10493e39a5a1SSandy Huang VOP2_SCALE_UP_BIL, 10503e39a5a1SSandy Huang VOP2_SCALE_UP_BIC, 10513e39a5a1SSandy Huang }; 10523e39a5a1SSandy Huang 10533e39a5a1SSandy Huang enum vop2_scale_down_mode { 10543e39a5a1SSandy Huang VOP2_SCALE_DOWN_NRST_NBOR, 10553e39a5a1SSandy Huang VOP2_SCALE_DOWN_BIL, 10563e39a5a1SSandy Huang VOP2_SCALE_DOWN_AVG, 10573e39a5a1SSandy Huang }; 10583e39a5a1SSandy Huang 10593e39a5a1SSandy Huang enum scale_mode { 10603e39a5a1SSandy Huang SCALE_NONE = 0x0, 10613e39a5a1SSandy Huang SCALE_UP = 0x1, 10623e39a5a1SSandy Huang SCALE_DOWN = 0x2 10633e39a5a1SSandy Huang }; 10643e39a5a1SSandy Huang 106512ee5af0SDamon Ding enum vop_dsc_interface_mode { 106612ee5af0SDamon Ding VOP_DSC_IF_DISABLE = 0, 106712ee5af0SDamon Ding VOP_DSC_IF_HDMI = 1, 106812ee5af0SDamon Ding VOP_DSC_IF_MIPI_DS_MODE = 2, 106912ee5af0SDamon Ding VOP_DSC_IF_MIPI_VIDEO_MODE = 3, 107012ee5af0SDamon Ding }; 107112ee5af0SDamon Ding 10725fa6e665SDamon Ding enum vop3_pre_scale_down_mode { 10735fa6e665SDamon Ding VOP3_PRE_SCALE_UNSPPORT, 10745fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_GT, 10755fa6e665SDamon Ding VOP3_PRE_SCALE_DOWN_AVG, 10765fa6e665SDamon Ding }; 10775fa6e665SDamon Ding 10785fa6e665SDamon Ding enum vop3_esmart_lb_mode { 10795fa6e665SDamon Ding VOP3_ESMART_8K_MODE, 10805fa6e665SDamon Ding VOP3_ESMART_4K_4K_MODE, 10815fa6e665SDamon Ding VOP3_ESMART_4K_2K_2K_MODE, 10825fa6e665SDamon Ding VOP3_ESMART_2K_2K_2K_2K_MODE, 10835fa6e665SDamon Ding }; 10845fa6e665SDamon Ding 10853e39a5a1SSandy Huang struct vop2_layer { 10863e39a5a1SSandy Huang u8 id; 10873e39a5a1SSandy Huang /** 10883e39a5a1SSandy Huang * @win_phys_id: window id of the layer selected. 10893e39a5a1SSandy Huang * Every layer must make sure to select different 10903e39a5a1SSandy Huang * windows of others. 10913e39a5a1SSandy Huang */ 10923e39a5a1SSandy Huang u8 win_phys_id; 10933e39a5a1SSandy Huang }; 10943e39a5a1SSandy Huang 109560e469f5SDamon Ding struct vop2_power_domain_data { 1096b6ba80b4SDamon Ding u8 id; 1097b6ba80b4SDamon Ding u8 parent_id; 1098b6ba80b4SDamon Ding /* 1099b6ba80b4SDamon Ding * @module_id_mask: module id of which module this power domain is belongs to. 1100b6ba80b4SDamon Ding * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 1101b6ba80b4SDamon Ding */ 1102b6ba80b4SDamon Ding u32 module_id_mask; 110360e469f5SDamon Ding }; 110460e469f5SDamon Ding 1105b0989546SSandy Huang struct vop2_win_data { 1106b0989546SSandy Huang char *name; 110763cb669fSSandy Huang u8 phys_id; 1108ecc31b6eSAndy Yan enum vop2_layer_type type; 1109b0989546SSandy Huang u8 win_sel_port_offset; 11105fa6e665SDamon Ding u8 layer_sel_win_id[VOP2_VP_MAX]; 1111a33b790fSDamon Ding u8 axi_id; 1112a33b790fSDamon Ding u8 axi_uv_id; 1113a33b790fSDamon Ding u8 axi_yrgb_id; 1114ee01dbb2SDamon Ding u8 splice_win_id; 1115b6ba80b4SDamon Ding u8 pd_id; 11165fa6e665SDamon Ding u8 hsu_filter_mode; 11175fa6e665SDamon Ding u8 hsd_filter_mode; 11185fa6e665SDamon Ding u8 vsu_filter_mode; 11195fa6e665SDamon Ding u8 vsd_filter_mode; 11205fa6e665SDamon Ding u8 hsd_pre_filter_mode; 11215fa6e665SDamon Ding u8 vsd_pre_filter_mode; 11225fa6e665SDamon Ding u8 scale_engine_num; 11231c9572c7SDamon Ding u8 source_win_id; 1124b0989546SSandy Huang u32 reg_offset; 11254c765862SDamon Ding u32 max_upscale_factor; 11264c765862SDamon Ding u32 max_downscale_factor; 11271c9572c7SDamon Ding u32 feature; 1128ee01dbb2SDamon Ding bool splice_mode_right; 112963cb669fSSandy Huang }; 113063cb669fSSandy Huang 113163cb669fSSandy Huang struct vop2_vp_data { 113263cb669fSSandy Huang u32 feature; 113363cb669fSSandy Huang u8 pre_scan_max_dly; 1134452afb13SDamon Ding u8 layer_mix_dly; 1135452afb13SDamon Ding u8 hdr_mix_dly; 1136452afb13SDamon Ding u8 win_dly; 1137ee01dbb2SDamon Ding u8 splice_vp_id; 113863cb669fSSandy Huang struct vop_rect max_output; 1139ecc31b6eSAndy Yan u32 max_dclk; 1140d0408543SAndy Yan }; 1141d0408543SAndy Yan 1142ee008497SSandy Huang struct vop2_plane_table { 1143ee008497SSandy Huang enum vop2_layer_phy_id plane_id; 1144ee008497SSandy Huang enum vop2_layer_type plane_type; 1145ee008497SSandy Huang }; 1146ee008497SSandy Huang 1147b0989546SSandy Huang struct vop2_vp_plane_mask { 1148b0989546SSandy Huang u8 primary_plane_id; /* use this win to show logo */ 1149b0989546SSandy Huang u8 attached_layers_nr; /* number layers attach to this vp */ 1150b0989546SSandy Huang u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 1151b0989546SSandy Huang u32 plane_mask; 1152ee008497SSandy Huang int cursor_plane_id; 1153b0989546SSandy Huang }; 1154b0989546SSandy Huang 115512ee5af0SDamon Ding struct vop2_dsc_data { 115612ee5af0SDamon Ding u8 id; 115712ee5af0SDamon Ding u8 pd_id; 115812ee5af0SDamon Ding u8 max_slice_num; 115912ee5af0SDamon Ding u8 max_linebuf_depth; /* used to generate the bitstream */ 116012ee5af0SDamon Ding u8 min_bits_per_pixel; /* bit num after encoder compress */ 116112ee5af0SDamon Ding const char *dsc_txp_clk_src_name; 116212ee5af0SDamon Ding const char *dsc_txp_clk_name; 116312ee5af0SDamon Ding const char *dsc_pxl_clk_name; 116412ee5af0SDamon Ding const char *dsc_cds_clk_name; 116512ee5af0SDamon Ding }; 116612ee5af0SDamon Ding 116712ee5af0SDamon Ding struct dsc_error_info { 116812ee5af0SDamon Ding u32 dsc_error_val; 116912ee5af0SDamon Ding char dsc_error_info[50]; 117012ee5af0SDamon Ding }; 117112ee5af0SDamon Ding 117272388c26SDamon Ding struct vop2_dump_regs { 117372388c26SDamon Ding u32 offset; 117472388c26SDamon Ding const char *name; 117572388c26SDamon Ding u32 state_base; 117672388c26SDamon Ding u32 state_mask; 117772388c26SDamon Ding u32 state_shift; 117872388c26SDamon Ding bool enable_state; 117972388c26SDamon Ding }; 118072388c26SDamon Ding 1181d0408543SAndy Yan struct vop2_data { 118252ee18acSSandy Huang u32 version; 11835fa6e665SDamon Ding u32 esmart_lb_mode; 118463cb669fSSandy Huang struct vop2_vp_data *vp_data; 1185b0989546SSandy Huang struct vop2_win_data *win_data; 1186b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 1187ee008497SSandy Huang struct vop2_plane_table *plane_table; 1188b6ba80b4SDamon Ding struct vop2_power_domain_data *pd; 118912ee5af0SDamon Ding struct vop2_dsc_data *dsc; 119012ee5af0SDamon Ding struct dsc_error_info *dsc_error_ecw; 119112ee5af0SDamon Ding struct dsc_error_info *dsc_error_buffer_flow; 119272388c26SDamon Ding struct vop2_dump_regs *dump_regs; 1193337d1c13SDamon Ding u8 *vp_primary_plane_order; 119463cb669fSSandy Huang u8 nr_vps; 119563cb669fSSandy Huang u8 nr_layers; 119663cb669fSSandy Huang u8 nr_mixers; 11971147facaSSandy Huang u8 nr_gammas; 1198b6ba80b4SDamon Ding u8 nr_pd; 119912ee5af0SDamon Ding u8 nr_dscs; 120012ee5af0SDamon Ding u8 nr_dsc_ecw; 120112ee5af0SDamon Ding u8 nr_dsc_buffer_flow; 1202ecc31b6eSAndy Yan u32 reg_len; 120372388c26SDamon Ding u32 dump_regs_size; 1204d0408543SAndy Yan }; 1205d0408543SAndy Yan 1206d0408543SAndy Yan struct vop2 { 1207d0408543SAndy Yan u32 *regsbak; 1208d0408543SAndy Yan void *regs; 1209d0408543SAndy Yan void *grf; 1210ecc31b6eSAndy Yan void *vop_grf; 1211ecc31b6eSAndy Yan void *vo1_grf; 121260e469f5SDamon Ding void *sys_pmu; 121352ee18acSSandy Huang u32 reg_len; 121452ee18acSSandy Huang u32 version; 12155fa6e665SDamon Ding u32 esmart_lb_mode; 121663cb669fSSandy Huang bool global_init; 1217d0408543SAndy Yan const struct vop2_data *data; 1218b0989546SSandy Huang struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 1219d0408543SAndy Yan }; 1220d0408543SAndy Yan 1221d0408543SAndy Yan static struct vop2 *rockchip_vop2; 12225fa6e665SDamon Ding 12235fa6e665SDamon Ding static inline bool is_vop3(struct vop2 *vop2) 12245fa6e665SDamon Ding { 12255fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) 12265fa6e665SDamon Ding return false; 12275fa6e665SDamon Ding else 12285fa6e665SDamon Ding return true; 12295fa6e665SDamon Ding } 12305fa6e665SDamon Ding 12313e39a5a1SSandy Huang /* 12323e39a5a1SSandy Huang * bli_sd_factor = (src - 1) / (dst - 1) << 12; 12333e39a5a1SSandy Huang * avg_sd_factor: 12343e39a5a1SSandy Huang * bli_su_factor: 12353e39a5a1SSandy Huang * bic_su_factor: 12363e39a5a1SSandy Huang * = (src - 1) / (dst - 1) << 16; 12373e39a5a1SSandy Huang * 12385fa6e665SDamon Ding * ygt2 enable: dst get one line from two line of the src 12395fa6e665SDamon Ding * ygt4 enable: dst get one line from four line of the src. 12403e39a5a1SSandy Huang * 12413e39a5a1SSandy Huang */ 12423e39a5a1SSandy Huang #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 12433e39a5a1SSandy Huang #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 12443e39a5a1SSandy Huang 12453e39a5a1SSandy Huang #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 12463e39a5a1SSandy Huang (fac * (dst - 1) >> 12 < (src - 1)) 12473e39a5a1SSandy Huang #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 12483e39a5a1SSandy Huang (fac * (dst - 1) >> 16 < (src - 1)) 12495fa6e665SDamon Ding #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \ 12505fa6e665SDamon Ding (fac * (dst - 1) >> 16 < (src - 1)) 12513e39a5a1SSandy Huang 12523e39a5a1SSandy Huang static uint16_t vop2_scale_factor(enum scale_mode mode, 12533e39a5a1SSandy Huang int32_t filter_mode, 12543e39a5a1SSandy Huang uint32_t src, uint32_t dst) 12553e39a5a1SSandy Huang { 12563e39a5a1SSandy Huang uint32_t fac = 0; 12573e39a5a1SSandy Huang int i = 0; 12583e39a5a1SSandy Huang 12593e39a5a1SSandy Huang if (mode == SCALE_NONE) 12603e39a5a1SSandy Huang return 0; 12613e39a5a1SSandy Huang 12623e39a5a1SSandy Huang /* 12633e39a5a1SSandy Huang * A workaround to avoid zero div. 12643e39a5a1SSandy Huang */ 12653e39a5a1SSandy Huang if ((dst == 1) || (src == 1)) { 12663e39a5a1SSandy Huang dst = dst + 1; 12673e39a5a1SSandy Huang src = src + 1; 12683e39a5a1SSandy Huang } 12693e39a5a1SSandy Huang 12703e39a5a1SSandy Huang if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 12713e39a5a1SSandy Huang fac = VOP2_BILI_SCL_DN(src, dst); 12723e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 12733e39a5a1SSandy Huang if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 12743e39a5a1SSandy Huang break; 12753e39a5a1SSandy Huang fac -= 1; 12763e39a5a1SSandy Huang printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12773e39a5a1SSandy Huang } 12783e39a5a1SSandy Huang } else { 12793e39a5a1SSandy Huang fac = VOP2_COMMON_SCL(src, dst); 12803e39a5a1SSandy Huang for (i = 0; i < 100; i++) { 12813e39a5a1SSandy Huang if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 12823e39a5a1SSandy Huang break; 12833e39a5a1SSandy Huang fac -= 1; 12843e39a5a1SSandy Huang printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 12853e39a5a1SSandy Huang } 12863e39a5a1SSandy Huang } 12873e39a5a1SSandy Huang 12883e39a5a1SSandy Huang return fac; 12893e39a5a1SSandy Huang } 12903e39a5a1SSandy Huang 12915fa6e665SDamon Ding static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor) 12925fa6e665SDamon Ding { 12935fa6e665SDamon Ding if (is_hor) 12945fa6e665SDamon Ding return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac); 12955fa6e665SDamon Ding return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac); 12965fa6e665SDamon Ding } 12975fa6e665SDamon Ding 12985fa6e665SDamon Ding static uint16_t vop3_scale_factor(enum scale_mode mode, 12995fa6e665SDamon Ding uint32_t src, uint32_t dst, bool is_hor) 13005fa6e665SDamon Ding { 13015fa6e665SDamon Ding uint32_t fac = 0; 13025fa6e665SDamon Ding int i = 0; 13035fa6e665SDamon Ding 13045fa6e665SDamon Ding if (mode == SCALE_NONE) 13055fa6e665SDamon Ding return 0; 13065fa6e665SDamon Ding 13075fa6e665SDamon Ding /* 13085fa6e665SDamon Ding * A workaround to avoid zero div. 13095fa6e665SDamon Ding */ 13105fa6e665SDamon Ding if ((dst == 1) || (src == 1)) { 13115fa6e665SDamon Ding dst = dst + 1; 13125fa6e665SDamon Ding src = src + 1; 13135fa6e665SDamon Ding } 13145fa6e665SDamon Ding 13155fa6e665SDamon Ding if (mode == SCALE_DOWN) { 13165fa6e665SDamon Ding fac = VOP2_BILI_SCL_DN(src, dst); 13175fa6e665SDamon Ding for (i = 0; i < 100; i++) { 13185fa6e665SDamon Ding if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 13195fa6e665SDamon Ding break; 13205fa6e665SDamon Ding fac -= 1; 13215fa6e665SDamon Ding printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 13225fa6e665SDamon Ding } 13235fa6e665SDamon Ding } else { 13245fa6e665SDamon Ding fac = VOP2_COMMON_SCL(src, dst); 13255fa6e665SDamon Ding for (i = 0; i < 100; i++) { 13265fa6e665SDamon Ding if (vop3_scale_up_fac_check(src, dst, fac, is_hor)) 13275fa6e665SDamon Ding break; 13285fa6e665SDamon Ding fac -= 1; 13295fa6e665SDamon Ding printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 13305fa6e665SDamon Ding } 13315fa6e665SDamon Ding } 13325fa6e665SDamon Ding 13335fa6e665SDamon Ding return fac; 13345fa6e665SDamon Ding } 13355fa6e665SDamon Ding 13363e39a5a1SSandy Huang static inline enum scale_mode scl_get_scl_mode(int src, int dst) 13373e39a5a1SSandy Huang { 13383e39a5a1SSandy Huang if (src < dst) 13393e39a5a1SSandy Huang return SCALE_UP; 13403e39a5a1SSandy Huang else if (src > dst) 13413e39a5a1SSandy Huang return SCALE_DOWN; 13423e39a5a1SSandy Huang 13433e39a5a1SSandy Huang return SCALE_NONE; 13443e39a5a1SSandy Huang } 1345d0408543SAndy Yan 1346ac500a1fSSandy Huang static inline int interpolate(int x1, int y1, int x2, int y2, int x) 1347ac500a1fSSandy Huang { 1348ac500a1fSSandy Huang return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 1349ac500a1fSSandy Huang } 1350ac500a1fSSandy Huang 1351b0989546SSandy Huang static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 1352b0989546SSandy Huang { 1353b0989546SSandy Huang int i = 0; 1354ecc31b6eSAndy Yan 1355337d1c13SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 1356337d1c13SDamon Ding if (plane_mask & BIT(vop2->data->vp_primary_plane_order[i])) 1357337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[i]; 1358ecc31b6eSAndy Yan } 1359b0989546SSandy Huang 1360337d1c13SDamon Ding return vop2->data->vp_primary_plane_order[0]; 1361b0989546SSandy Huang } 1362b0989546SSandy Huang 136363cb669fSSandy Huang static inline u16 scl_cal_scale(int src, int dst, int shift) 1364d0408543SAndy Yan { 1365d0408543SAndy Yan return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 1366d0408543SAndy Yan } 1367d0408543SAndy Yan 136863cb669fSSandy Huang static inline u16 scl_cal_scale2(int src, int dst) 1369d0408543SAndy Yan { 1370d0408543SAndy Yan return ((src - 1) << 12) / (dst - 1); 1371d0408543SAndy Yan } 1372d0408543SAndy Yan 137352ee18acSSandy Huang static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 1374d0408543SAndy Yan { 1375d0408543SAndy Yan writel(v, vop2->regs + offset); 1376d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1377d0408543SAndy Yan } 1378d0408543SAndy Yan 137952ee18acSSandy Huang static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 1380d0408543SAndy Yan { 1381d0408543SAndy Yan return readl(vop2->regs + offset); 1382d0408543SAndy Yan } 1383d0408543SAndy Yan 138452ee18acSSandy Huang static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 138552ee18acSSandy Huang u32 mask, u32 shift, u32 v, 1386d0408543SAndy Yan bool write_mask) 1387d0408543SAndy Yan { 1388d0408543SAndy Yan if (!mask) 1389d0408543SAndy Yan return; 1390d0408543SAndy Yan 1391d0408543SAndy Yan if (write_mask) { 1392d0408543SAndy Yan v = ((v & mask) << shift) | (mask << (shift + 16)); 1393d0408543SAndy Yan } else { 139452ee18acSSandy Huang u32 cached_val = vop2->regsbak[offset >> 2]; 1395d0408543SAndy Yan 1396d0408543SAndy Yan v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 1397d0408543SAndy Yan vop2->regsbak[offset >> 2] = v; 1398d0408543SAndy Yan } 1399d0408543SAndy Yan 1400d0408543SAndy Yan writel(v, vop2->regs + offset); 1401d0408543SAndy Yan } 1402d0408543SAndy Yan 1403ecc31b6eSAndy Yan static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 140452ee18acSSandy Huang u32 mask, u32 shift, u32 v) 140552ee18acSSandy Huang { 140652ee18acSSandy Huang u32 val = 0; 140752ee18acSSandy Huang 140852ee18acSSandy Huang val = (v << shift) | (mask << (shift + 16)); 1409ecc31b6eSAndy Yan writel(val, grf_base + offset); 141052ee18acSSandy Huang } 141152ee18acSSandy Huang 141260e469f5SDamon Ding static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 141360e469f5SDamon Ding u32 mask, u32 shift) 141460e469f5SDamon Ding { 141560e469f5SDamon Ding return (readl(grf_base + offset) >> shift) & mask; 141660e469f5SDamon Ding } 141760e469f5SDamon Ding 14188895aec1SSandy Huang static char* get_output_if_name(u32 output_if, char *name) 14198895aec1SSandy Huang { 14208895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_RGB) 14218895aec1SSandy Huang strcat(name, " RGB"); 14228895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT1120) 14238895aec1SSandy Huang strcat(name, " BT1120"); 14248895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_BT656) 14258895aec1SSandy Huang strcat(name, " BT656"); 14268895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS0) 14278895aec1SSandy Huang strcat(name, " LVDS0"); 14288895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_LVDS1) 14298895aec1SSandy Huang strcat(name, " LVDS1"); 14308895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI0) 14318895aec1SSandy Huang strcat(name, " MIPI0"); 14328895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_MIPI1) 14338895aec1SSandy Huang strcat(name, " MIPI1"); 14348895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP0) 14358895aec1SSandy Huang strcat(name, " eDP0"); 14368895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_eDP1) 14378895aec1SSandy Huang strcat(name, " eDP1"); 14388895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP0) 14398895aec1SSandy Huang strcat(name, " DP0"); 14408895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_DP1) 14418895aec1SSandy Huang strcat(name, " DP1"); 14428895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI0) 14438895aec1SSandy Huang strcat(name, " HDMI0"); 14448895aec1SSandy Huang if (output_if & VOP_OUTPUT_IF_HDMI1) 14458895aec1SSandy Huang strcat(name, " HDMI1"); 14468895aec1SSandy Huang 14478895aec1SSandy Huang return name; 14488895aec1SSandy Huang } 14498895aec1SSandy Huang 14508895aec1SSandy Huang static char *get_plane_name(int plane_id, char *name) 14518895aec1SSandy Huang { 14528895aec1SSandy Huang switch (plane_id) { 14538895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER0: 14548895aec1SSandy Huang strcat(name, "Cluster0"); 14558895aec1SSandy Huang break; 14568895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER1: 14578895aec1SSandy Huang strcat(name, "Cluster1"); 14588895aec1SSandy Huang break; 14598895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART0: 14608895aec1SSandy Huang strcat(name, "Esmart0"); 14618895aec1SSandy Huang break; 14628895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART1: 14638895aec1SSandy Huang strcat(name, "Esmart1"); 14648895aec1SSandy Huang break; 14658895aec1SSandy Huang case ROCKCHIP_VOP2_SMART0: 14668895aec1SSandy Huang strcat(name, "Smart0"); 14678895aec1SSandy Huang break; 14688895aec1SSandy Huang case ROCKCHIP_VOP2_SMART1: 14698895aec1SSandy Huang strcat(name, "Smart1"); 14708895aec1SSandy Huang break; 14718895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER2: 14728895aec1SSandy Huang strcat(name, "Cluster2"); 14738895aec1SSandy Huang break; 14748895aec1SSandy Huang case ROCKCHIP_VOP2_CLUSTER3: 14758895aec1SSandy Huang strcat(name, "Cluster3"); 14768895aec1SSandy Huang break; 14778895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART2: 14788895aec1SSandy Huang strcat(name, "Esmart2"); 14798895aec1SSandy Huang break; 14808895aec1SSandy Huang case ROCKCHIP_VOP2_ESMART3: 14818895aec1SSandy Huang strcat(name, "Esmart3"); 14828895aec1SSandy Huang break; 14838895aec1SSandy Huang } 14848895aec1SSandy Huang 14858895aec1SSandy Huang return name; 14868895aec1SSandy Huang } 14878895aec1SSandy Huang 148852ee18acSSandy Huang static bool is_yuv_output(u32 bus_format) 1489d0408543SAndy Yan { 1490d0408543SAndy Yan switch (bus_format) { 1491d0408543SAndy Yan case MEDIA_BUS_FMT_YUV8_1X24: 1492d0408543SAndy Yan case MEDIA_BUS_FMT_YUV10_1X30: 1493034a46b5SAlgea Cao case MEDIA_BUS_FMT_YUYV10_1X20: 1494d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1495d0408543SAndy Yan case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1496a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_2X8: 1497a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_2X8: 1498a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_2X8: 1499a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_2X8: 1500a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 1501a0ea2d92SDamon Ding case MEDIA_BUS_FMT_YVYU8_1X16: 1502a0ea2d92SDamon Ding case MEDIA_BUS_FMT_UYVY8_1X16: 1503a0ea2d92SDamon Ding case MEDIA_BUS_FMT_VYUY8_1X16: 1504d0408543SAndy Yan return true; 1505d0408543SAndy Yan default: 1506d0408543SAndy Yan return false; 1507d0408543SAndy Yan } 1508d0408543SAndy Yan } 1509d0408543SAndy Yan 15105fa6e665SDamon Ding static int vop2_convert_csc_mode(int csc_mode, int bit_depth) 151110ee9f5bSAlgea Cao { 151210ee9f5bSAlgea Cao switch (csc_mode) { 151310ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE170M: 151410ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_M: 151510ee9f5bSAlgea Cao case V4L2_COLORSPACE_470_SYSTEM_BG: 151610ee9f5bSAlgea Cao return CSC_BT601L; 151710ee9f5bSAlgea Cao case V4L2_COLORSPACE_REC709: 151810ee9f5bSAlgea Cao case V4L2_COLORSPACE_SMPTE240M: 151910ee9f5bSAlgea Cao case V4L2_COLORSPACE_DEFAULT: 15205fa6e665SDamon Ding if (bit_depth == CSC_13BIT_DEPTH) 15215fa6e665SDamon Ding return CSC_BT709L_13BIT; 15225fa6e665SDamon Ding else 152310ee9f5bSAlgea Cao return CSC_BT709L; 152410ee9f5bSAlgea Cao case V4L2_COLORSPACE_JPEG: 152510ee9f5bSAlgea Cao return CSC_BT601F; 152610ee9f5bSAlgea Cao case V4L2_COLORSPACE_BT2020: 15275fa6e665SDamon Ding if (bit_depth == CSC_13BIT_DEPTH) 15285fa6e665SDamon Ding return CSC_BT2020L_13BIT; 15295fa6e665SDamon Ding else 153010ee9f5bSAlgea Cao return CSC_BT2020; 15315fa6e665SDamon Ding case V4L2_COLORSPACE_BT709F: 15325fa6e665SDamon Ding if (bit_depth == CSC_10BIT_DEPTH) { 15335fa6e665SDamon Ding printf("WARN: Unsupported bt709f at 10bit csc depth, use bt601f instead\n"); 15345fa6e665SDamon Ding return CSC_BT601F; 15355fa6e665SDamon Ding } else { 15365fa6e665SDamon Ding return CSC_BT709F_13BIT; 15375fa6e665SDamon Ding } 15385fa6e665SDamon Ding case V4L2_COLORSPACE_BT2020F: 15395fa6e665SDamon Ding if (bit_depth == CSC_10BIT_DEPTH) { 15405fa6e665SDamon Ding printf("WARN: Unsupported bt2020f at 10bit csc depth, use bt601f instead\n"); 15415fa6e665SDamon Ding return CSC_BT601F; 15425fa6e665SDamon Ding } else { 15435fa6e665SDamon Ding return CSC_BT2020F_13BIT; 15445fa6e665SDamon Ding } 154510ee9f5bSAlgea Cao default: 154610ee9f5bSAlgea Cao return CSC_BT709L; 154710ee9f5bSAlgea Cao } 154810ee9f5bSAlgea Cao } 154910ee9f5bSAlgea Cao 1550b0989546SSandy Huang static bool is_uv_swap(u32 bus_format, u32 output_mode) 1551d0408543SAndy Yan { 1552d0408543SAndy Yan /* 1553d0408543SAndy Yan * FIXME: 1554d0408543SAndy Yan * 1555d0408543SAndy Yan * There is no media type for YUV444 output, 1556d0408543SAndy Yan * so when out_mode is AAAA or P888, assume output is YUV444 on 1557d0408543SAndy Yan * yuv format. 1558d0408543SAndy Yan * 1559d0408543SAndy Yan * From H/W testing, YUV444 mode need a rb swap. 1560d0408543SAndy Yan */ 15613e59c137SSandy Huang if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || 15623e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || 15633e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || 15643e59c137SSandy Huang bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || 15653e59c137SSandy Huang ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1566d0408543SAndy Yan bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1567d0408543SAndy Yan (output_mode == ROCKCHIP_OUT_MODE_AAAA || 15683e59c137SSandy Huang output_mode == ROCKCHIP_OUT_MODE_P888))) 1569d0408543SAndy Yan return true; 1570d0408543SAndy Yan else 1571d0408543SAndy Yan return false; 1572d0408543SAndy Yan } 1573d0408543SAndy Yan 15740675a2a4SDamon Ding static bool is_rb_swap(u32 bus_format, u32 output_mode) 15750675a2a4SDamon Ding { 15760675a2a4SDamon Ding /* 15770675a2a4SDamon Ding * The default component order of serial rgb3x8 formats 15780675a2a4SDamon Ding * is BGR. So it is needed to enable RB swap. 15790675a2a4SDamon Ding */ 1580b7b383ebSDamon Ding if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 || 1581b7b383ebSDamon Ding bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8) 15820675a2a4SDamon Ding return true; 15830675a2a4SDamon Ding else 15840675a2a4SDamon Ding return false; 15850675a2a4SDamon Ding } 15860675a2a4SDamon Ding 1587b0989546SSandy Huang static inline bool is_hot_plug_devices(int output_type) 158863cb669fSSandy Huang { 1589b0989546SSandy Huang switch (output_type) { 1590b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIA: 1591b0989546SSandy Huang case DRM_MODE_CONNECTOR_HDMIB: 1592b0989546SSandy Huang case DRM_MODE_CONNECTOR_TV: 1593b0989546SSandy Huang case DRM_MODE_CONNECTOR_DisplayPort: 1594b0989546SSandy Huang case DRM_MODE_CONNECTOR_VGA: 1595b0989546SSandy Huang case DRM_MODE_CONNECTOR_Unknown: 1596b0989546SSandy Huang return true; 1597b0989546SSandy Huang default: 1598b0989546SSandy Huang return false; 159963cb669fSSandy Huang } 160063cb669fSSandy Huang } 160163cb669fSSandy Huang 1602ecc31b6eSAndy Yan static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1603ecc31b6eSAndy Yan { 1604ecc31b6eSAndy Yan int i = 0; 1605ecc31b6eSAndy Yan 1606ecc31b6eSAndy Yan for (i = 0; i < vop2->data->nr_layers; i++) { 1607ecc31b6eSAndy Yan if (vop2->data->win_data[i].phys_id == phys_id) 1608ecc31b6eSAndy Yan return &vop2->data->win_data[i]; 1609ecc31b6eSAndy Yan } 1610ecc31b6eSAndy Yan 1611ecc31b6eSAndy Yan return NULL; 1612ecc31b6eSAndy Yan } 1613ecc31b6eSAndy Yan 1614b6ba80b4SDamon Ding static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id) 1615b6ba80b4SDamon Ding { 1616b6ba80b4SDamon Ding int i = 0; 1617b6ba80b4SDamon Ding 1618b6ba80b4SDamon Ding for (i = 0; i < vop2->data->nr_pd; i++) { 1619b6ba80b4SDamon Ding if (vop2->data->pd[i].id == pd_id) 1620b6ba80b4SDamon Ding return &vop2->data->pd[i]; 1621b6ba80b4SDamon Ding } 1622b6ba80b4SDamon Ding 1623b6ba80b4SDamon Ding return NULL; 1624b6ba80b4SDamon Ding } 1625b6ba80b4SDamon Ding 1626db328a0dSDamon Ding static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1627db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1628db328a0dSDamon Ding { 1629db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1630db328a0dSDamon Ding int i; 1631db328a0dSDamon Ding 1632db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1633db328a0dSDamon Ding GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 1634db328a0dSDamon Ding crtc_id, false); 1635db328a0dSDamon Ding 1636db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1637db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1638db328a0dSDamon Ding 1639db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1640db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1641db328a0dSDamon Ding } 1642db328a0dSDamon Ding 1643db328a0dSDamon Ding static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1644db328a0dSDamon Ding u32 *lut_regs, u32 *lut_val, int lut_len) 1645db328a0dSDamon Ding { 1646db328a0dSDamon Ding u32 vp_offset = crtc_id * 0x100; 1647db328a0dSDamon Ding int i; 1648db328a0dSDamon Ding 1649db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1650db328a0dSDamon Ding GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT, 1651db328a0dSDamon Ding crtc_id, false); 1652db328a0dSDamon Ding 1653db328a0dSDamon Ding for (i = 0; i < lut_len; i++) 1654db328a0dSDamon Ding writel(lut_val[i], lut_regs + i); 1655db328a0dSDamon Ding 1656db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1657db328a0dSDamon Ding EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1658db328a0dSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1659db328a0dSDamon Ding EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false); 1660db328a0dSDamon Ding } 1661db328a0dSDamon Ding 16621147facaSSandy Huang static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1663d0408543SAndy Yan struct display_state *state) 1664d0408543SAndy Yan { 16651147facaSSandy Huang struct connector_state *conn_state = &state->conn_state; 16661147facaSSandy Huang struct crtc_state *cstate = &state->crtc_state; 16671147facaSSandy Huang struct resource gamma_res; 16681147facaSSandy Huang fdt_size_t lut_size; 16691147facaSSandy Huang int i, lut_len, ret = 0; 16701147facaSSandy Huang u32 *lut_regs; 16711147facaSSandy Huang u32 *lut_val; 16721147facaSSandy Huang u32 r, g, b; 16731147facaSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 16741147facaSSandy Huang static int gamma_lut_en_num = 1; 16751147facaSSandy Huang 16761147facaSSandy Huang if (gamma_lut_en_num > vop2->data->nr_gammas) { 16771147facaSSandy Huang printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 16781147facaSSandy Huang return 0; 16791147facaSSandy Huang } 16801147facaSSandy Huang 16811147facaSSandy Huang if (!disp_info) 16821147facaSSandy Huang return 0; 16831147facaSSandy Huang 16841147facaSSandy Huang if (!disp_info->gamma_lut_data.size) 16851147facaSSandy Huang return 0; 16861147facaSSandy Huang 16871147facaSSandy Huang ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 16881147facaSSandy Huang if (ret) 16891147facaSSandy Huang printf("failed to get gamma lut res\n"); 16901147facaSSandy Huang lut_regs = (u32 *)gamma_res.start; 16911147facaSSandy Huang lut_size = gamma_res.end - gamma_res.start + 1; 16921147facaSSandy Huang if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 16931147facaSSandy Huang printf("failed to get gamma lut register\n"); 16941147facaSSandy Huang return 0; 16951147facaSSandy Huang } 16961147facaSSandy Huang lut_len = lut_size / 4; 16971147facaSSandy Huang if (lut_len != 256 && lut_len != 1024) { 16981147facaSSandy Huang printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 16991147facaSSandy Huang return 0; 17001147facaSSandy Huang } 17011147facaSSandy Huang lut_val = (u32 *)calloc(1, lut_size); 17021147facaSSandy Huang for (i = 0; i < lut_len; i++) { 17031147facaSSandy Huang r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 17041147facaSSandy Huang g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 17051147facaSSandy Huang b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 17061147facaSSandy Huang 17071147facaSSandy Huang lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 17081147facaSSandy Huang } 17091147facaSSandy Huang 1710db328a0dSDamon Ding if (vop2->version == VOP_VERSION_RK3568) { 1711db328a0dSDamon Ding rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len); 17121147facaSSandy Huang gamma_lut_en_num++; 1713db328a0dSDamon Ding } else if (vop2->version == VOP_VERSION_RK3588) { 1714db328a0dSDamon Ding rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, lut_val, lut_len); 1715db328a0dSDamon Ding if (cstate->splice_mode) { 1716db328a0dSDamon Ding rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, lut_val, lut_len); 1717db328a0dSDamon Ding gamma_lut_en_num++; 1718db328a0dSDamon Ding } 1719db328a0dSDamon Ding gamma_lut_en_num++; 1720db328a0dSDamon Ding } 17211147facaSSandy Huang 1722d0408543SAndy Yan return 0; 1723d0408543SAndy Yan } 1724d0408543SAndy Yan 17256414e3bcSSandy Huang static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 17266414e3bcSSandy Huang struct display_state *state) 17276414e3bcSSandy Huang { 17286414e3bcSSandy Huang struct connector_state *conn_state = &state->conn_state; 17296414e3bcSSandy Huang struct crtc_state *cstate = &state->crtc_state; 17306414e3bcSSandy Huang int i, cubic_lut_len; 17316414e3bcSSandy Huang u32 vp_offset = cstate->crtc_id * 0x100; 17326414e3bcSSandy Huang struct base2_disp_info *disp_info = conn_state->disp_info; 17336414e3bcSSandy Huang struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 17346414e3bcSSandy Huang u32 *cubic_lut_addr; 17356414e3bcSSandy Huang 17366414e3bcSSandy Huang if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 17376414e3bcSSandy Huang return 0; 17386414e3bcSSandy Huang 17396414e3bcSSandy Huang if (!disp_info->cubic_lut_data.size) 17406414e3bcSSandy Huang return 0; 17416414e3bcSSandy Huang 17426414e3bcSSandy Huang cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 17436414e3bcSSandy Huang cubic_lut_len = disp_info->cubic_lut_data.size; 17446414e3bcSSandy Huang 17456414e3bcSSandy Huang for (i = 0; i < cubic_lut_len / 2; i++) { 17466414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 17476414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 17486414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 17496414e3bcSSandy Huang *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 17506414e3bcSSandy Huang ((lut->lred[2 * i + 1] & 0xfff) << 4) + 17516414e3bcSSandy Huang ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 17526414e3bcSSandy Huang ((lut->lblue[2 * i + 1] & 0xf) << 28); 17536414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 17546414e3bcSSandy Huang *cubic_lut_addr++ = 0; 17556414e3bcSSandy Huang } 17566414e3bcSSandy Huang 17576414e3bcSSandy Huang if (cubic_lut_len % 2) { 17586414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 17596414e3bcSSandy Huang ((lut->lgreen[2 * i] & 0xfff) << 12) + 17606414e3bcSSandy Huang ((lut->lblue[2 * i] & 0xff) << 24); 17616414e3bcSSandy Huang *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 17626414e3bcSSandy Huang *cubic_lut_addr++ = 0; 17636414e3bcSSandy Huang *cubic_lut_addr = 0; 17646414e3bcSSandy Huang } 17656414e3bcSSandy Huang 17666414e3bcSSandy Huang vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 17676414e3bcSSandy Huang get_cubic_lut_buffer(cstate->crtc_id)); 17686414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 17696414e3bcSSandy Huang EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 17706414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 17716414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 17726414e3bcSSandy Huang vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 17736414e3bcSSandy Huang EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 17746414e3bcSSandy Huang 17756414e3bcSSandy Huang return 0; 17766414e3bcSSandy Huang } 17776414e3bcSSandy Huang 1778ee01dbb2SDamon Ding static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2, 1779ee01dbb2SDamon Ding struct bcsh_state *bcsh_state, int crtc_id) 1780ee01dbb2SDamon Ding { 1781ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1782ee01dbb2SDamon Ding u32 vp_offset = crtc_id * 0x100; 1783ee01dbb2SDamon Ding 1784ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 1785ee01dbb2SDamon Ding BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false); 1786ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 1787ee01dbb2SDamon Ding BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false); 1788ee01dbb2SDamon Ding 1789ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 1790ee01dbb2SDamon Ding BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1791ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 1792ee01dbb2SDamon Ding BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 1793ee01dbb2SDamon Ding 1794ee01dbb2SDamon Ding if (!cstate->bcsh_en) { 1795ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1796ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 1797ee01dbb2SDamon Ding return; 1798ee01dbb2SDamon Ding } 1799ee01dbb2SDamon Ding 1800ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1801ee01dbb2SDamon Ding BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 1802ee01dbb2SDamon Ding bcsh_state->brightness, false); 1803ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1804ee01dbb2SDamon Ding BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false); 1805ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1806ee01dbb2SDamon Ding BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 1807ee01dbb2SDamon Ding bcsh_state->saturation * bcsh_state->contrast / 0x100, false); 1808ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1809ee01dbb2SDamon Ding BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false); 1810ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1811ee01dbb2SDamon Ding BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false); 1812ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1813ee01dbb2SDamon Ding BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 1814ee01dbb2SDamon Ding BCSH_OUT_MODE_NORMAL_VIDEO, false); 1815ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1816ee01dbb2SDamon Ding BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 1817ee01dbb2SDamon Ding } 1818ee01dbb2SDamon Ding 1819ac500a1fSSandy Huang static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 1820ac500a1fSSandy Huang { 1821ac500a1fSSandy Huang struct connector_state *conn_state = &state->conn_state; 1822ac500a1fSSandy Huang struct base_bcsh_info *bcsh_info; 1823ac500a1fSSandy Huang struct crtc_state *cstate = &state->crtc_state; 1824ee01dbb2SDamon Ding struct bcsh_state bcsh_state; 1825ac500a1fSSandy Huang int brightness, contrast, saturation, hue, sin_hue, cos_hue; 1826ac500a1fSSandy Huang 1827ac500a1fSSandy Huang if (!conn_state->disp_info) 1828ac500a1fSSandy Huang return; 1829ac500a1fSSandy Huang bcsh_info = &conn_state->disp_info->bcsh_info; 1830ac500a1fSSandy Huang if (!bcsh_info) 1831ac500a1fSSandy Huang return; 1832ac500a1fSSandy Huang 1833ac500a1fSSandy Huang if (bcsh_info->brightness != 50 || 1834ac500a1fSSandy Huang bcsh_info->contrast != 50 || 1835ac500a1fSSandy Huang bcsh_info->saturation != 50 || bcsh_info->hue != 50) 1836ee01dbb2SDamon Ding cstate->bcsh_en = true; 1837ac500a1fSSandy Huang 1838ee01dbb2SDamon Ding if (cstate->bcsh_en) { 1839ac500a1fSSandy Huang if (!cstate->yuv_overlay) 1840ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1841ac500a1fSSandy Huang if (!is_yuv_output(conn_state->bus_format)) 1842ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1843ac500a1fSSandy Huang } else { 1844ac500a1fSSandy Huang if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 1845ee01dbb2SDamon Ding cstate->post_r2y_en = 1; 1846ac500a1fSSandy Huang if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 1847ee01dbb2SDamon Ding cstate->post_y2r_en = 1; 1848ac500a1fSSandy Huang } 1849ac500a1fSSandy Huang 18505fa6e665SDamon Ding cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 1851ac500a1fSSandy Huang 1852ac500a1fSSandy Huang if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 1853ac500a1fSSandy Huang brightness = interpolate(0, -128, 100, 127, 1854ac500a1fSSandy Huang bcsh_info->brightness); 1855ac500a1fSSandy Huang else 1856ac500a1fSSandy Huang brightness = interpolate(0, -32, 100, 31, 1857ac500a1fSSandy Huang bcsh_info->brightness); 1858ac500a1fSSandy Huang contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 1859ac500a1fSSandy Huang saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 1860ac500a1fSSandy Huang hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 1861ac500a1fSSandy Huang 1862ac500a1fSSandy Huang 1863ac500a1fSSandy Huang /* 1864ac500a1fSSandy Huang * a:[-30~0): 1865ac500a1fSSandy Huang * sin_hue = 0x100 - sin(a)*256; 1866ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1867ac500a1fSSandy Huang * a:[0~30] 1868ac500a1fSSandy Huang * sin_hue = sin(a)*256; 1869ac500a1fSSandy Huang * cos_hue = cos(a)*256; 1870ac500a1fSSandy Huang */ 1871ac500a1fSSandy Huang sin_hue = fixp_sin32(hue) >> 23; 1872ac500a1fSSandy Huang cos_hue = fixp_cos32(hue) >> 23; 1873ac500a1fSSandy Huang 1874ee01dbb2SDamon Ding bcsh_state.brightness = brightness; 1875ee01dbb2SDamon Ding bcsh_state.contrast = contrast; 1876ee01dbb2SDamon Ding bcsh_state.saturation = saturation; 1877ee01dbb2SDamon Ding bcsh_state.sin_hue = sin_hue; 1878ee01dbb2SDamon Ding bcsh_state.cos_hue = cos_hue; 1879ee01dbb2SDamon Ding 1880ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id); 1881ee01dbb2SDamon Ding if (cstate->splice_mode) 1882ee01dbb2SDamon Ding vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id); 1883ee01dbb2SDamon Ding } 1884ee01dbb2SDamon Ding 1885ee01dbb2SDamon Ding static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id) 1886ee01dbb2SDamon Ding { 1887ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 1888ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 1889ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1890ee01dbb2SDamon Ding u32 bg_ovl_dly, bg_dly, pre_scan_dly; 1891ee01dbb2SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 1892ee01dbb2SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1893ee01dbb2SDamon Ding 1894ee01dbb2SDamon Ding bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly; 1895ee01dbb2SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly; 1896ee01dbb2SDamon Ding bg_dly -= bg_ovl_dly; 1897ee01dbb2SDamon Ding 1898ee01dbb2SDamon Ding if (cstate->splice_mode) 1899ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 2) - 1; 1900ee01dbb2SDamon Ding else 1901ee01dbb2SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1902ee01dbb2SDamon Ding 1903ee01dbb2SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 1904ee01dbb2SDamon Ding hsync_len = 8; 1905ee01dbb2SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1906ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4, 1907ee01dbb2SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1908ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 1909ac500a1fSSandy Huang } 1910ac500a1fSSandy Huang 1911452afb13SDamon Ding static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id) 1912452afb13SDamon Ding { 1913452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 1914452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 1915452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 1916452afb13SDamon Ding struct vop2_win_data *win_data; 1917452afb13SDamon Ding u32 bg_dly, pre_scan_dly; 1918452afb13SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 1919452afb13SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1920452afb13SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 1921452afb13SDamon Ding u8 win_id; 1922452afb13SDamon Ding 1923452afb13SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 1924452afb13SDamon Ding win_id = atoi(&win_data->name[strlen(win_data->name) - 1]); 1925452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL + win_id * 4, 1926452afb13SDamon Ding ESMART_DLY_NUM_MASK, ESMART_DLY_NUM_SHIFT, 0, false); 1927452afb13SDamon Ding 1928452afb13SDamon Ding bg_dly = vop2->data->vp_data[crtc_id].win_dly + 1929452afb13SDamon Ding vop2->data->vp_data[crtc_id].layer_mix_dly + 1930452afb13SDamon Ding vop2->data->vp_data[crtc_id].hdr_mix_dly; 1931452afb13SDamon Ding pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1932452afb13SDamon Ding pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1933452afb13SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100, 1934452afb13SDamon Ding BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1935452afb13SDamon Ding vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 1936452afb13SDamon Ding } 1937452afb13SDamon Ding 1938d0408543SAndy Yan static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 1939d0408543SAndy Yan { 1940d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 1941d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 194252ee18acSSandy Huang struct crtc_state *cstate = &state->crtc_state; 194352ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 1944d0408543SAndy Yan u16 vtotal = mode->crtc_vtotal; 1945d0408543SAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 1946d0408543SAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 1947d0408543SAndy Yan u16 hdisplay = mode->crtc_hdisplay; 1948d0408543SAndy Yan u16 vdisplay = mode->crtc_vdisplay; 1949d0408543SAndy Yan u16 hsize = 1950d0408543SAndy Yan hdisplay * (conn_state->overscan.left_margin + 1951d0408543SAndy Yan conn_state->overscan.right_margin) / 200; 1952d0408543SAndy Yan u16 vsize = 1953d0408543SAndy Yan vdisplay * (conn_state->overscan.top_margin + 1954d0408543SAndy Yan conn_state->overscan.bottom_margin) / 200; 1955d0408543SAndy Yan u16 hact_end, vact_end; 1956d0408543SAndy Yan u32 val; 1957d0408543SAndy Yan 195874bd8269SSandy Huang hsize = round_down(hsize, 2); 1959d0408543SAndy Yan vsize = round_down(vsize, 2); 1960d0408543SAndy Yan 1961d0408543SAndy Yan hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 1962d0408543SAndy Yan hact_end = hact_st + hsize; 1963d0408543SAndy Yan val = hact_st << 16; 1964d0408543SAndy Yan val |= hact_end; 1965d0408543SAndy Yan 196652ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 1967d0408543SAndy Yan vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 1968d0408543SAndy Yan vact_end = vact_st + vsize; 1969d0408543SAndy Yan val = vact_st << 16; 1970d0408543SAndy Yan val |= vact_end; 197152ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 1972d0408543SAndy Yan val = scl_cal_scale2(vdisplay, vsize) << 16; 1973d0408543SAndy Yan val |= scl_cal_scale2(hdisplay, hsize); 197452ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 1975d0408543SAndy Yan #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 1976d0408543SAndy Yan #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 197752ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 1978d0408543SAndy Yan POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 1979d0408543SAndy Yan POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 1980d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1981d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 1982d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vsize; 1983d0408543SAndy Yan 1984d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 198552ee18acSSandy Huang vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 1986d0408543SAndy Yan } 1987d0408543SAndy Yan 1988452afb13SDamon Ding if (is_vop3(vop2)) { 1989452afb13SDamon Ding vop3_setup_pipe_dly(state, vop2, cstate->crtc_id); 1990452afb13SDamon Ding } else { 1991ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id); 1992ee01dbb2SDamon Ding if (cstate->splice_mode) 1993ee01dbb2SDamon Ding vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id); 1994d0408543SAndy Yan } 1995452afb13SDamon Ding } 1996d0408543SAndy Yan 19976027c871SZhang Yubing static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2) 19986027c871SZhang Yubing { 19996027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 20006027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 20016027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 20026027c871SZhang Yubing struct drm_display_mode *mode = &conn_state->mode; 20036027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 20046027c871SZhang Yubing s16 *lut_y; 20056027c871SZhang Yubing s16 *lut_h; 20066027c871SZhang Yubing s16 *lut_s; 20076027c871SZhang Yubing u32 value; 20086027c871SZhang Yubing int i; 20096027c871SZhang Yubing 20106027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2011b8db91d0SZhang Yubing POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 2012b8db91d0SZhang Yubing if (!acm->acm_enable) { 2013b8db91d0SZhang Yubing writel(0, vop2->regs + RK3528_ACM_CTRL); 20146027c871SZhang Yubing return; 20156027c871SZhang Yubing } 20166027c871SZhang Yubing 20176027c871SZhang Yubing printf("post acm enable\n"); 20186027c871SZhang Yubing 20196027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_START); 20206027c871SZhang Yubing 20216027c871SZhang Yubing value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) + 20226027c871SZhang Yubing ((mode->vdisplay & 0xfff) << 20); 20236027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_CTRL); 20246027c871SZhang Yubing 20256027c871SZhang Yubing value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + 20266027c871SZhang Yubing ((acm->s_gain << 20) & 0x3ff00000); 20276027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE); 20286027c871SZhang Yubing 20296027c871SZhang Yubing lut_y = &acm->gain_lut_hy[0]; 20306027c871SZhang Yubing lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH]; 20316027c871SZhang Yubing lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2]; 20326027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) { 20336027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 20346027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 20356027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2)); 20366027c871SZhang Yubing } 20376027c871SZhang Yubing 20386027c871SZhang Yubing lut_y = &acm->gain_lut_hs[0]; 20396027c871SZhang Yubing lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH]; 20406027c871SZhang Yubing lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2]; 20416027c871SZhang Yubing for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) { 20426027c871SZhang Yubing value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 20436027c871SZhang Yubing ((lut_s[i] << 16) & 0xff0000); 20446027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2)); 20456027c871SZhang Yubing } 20466027c871SZhang Yubing 20476027c871SZhang Yubing lut_y = &acm->delta_lut_h[0]; 20486027c871SZhang Yubing lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH]; 20496027c871SZhang Yubing lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2]; 20506027c871SZhang Yubing for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) { 20516027c871SZhang Yubing value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) + 20526027c871SZhang Yubing ((lut_s[i] << 20) & 0x3ff00000); 20536027c871SZhang Yubing writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2)); 20546027c871SZhang Yubing } 20556027c871SZhang Yubing 20566027c871SZhang Yubing writel(1, vop2->regs + RK3528_ACM_FETCH_DONE); 20576027c871SZhang Yubing } 20586027c871SZhang Yubing 20596027c871SZhang Yubing static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2) 20606027c871SZhang Yubing { 20616027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 20626027c871SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 20636027c871SZhang Yubing struct acm_data *acm = &conn_state->disp_info->acm_data; 20646027c871SZhang Yubing struct csc_info *csc = &conn_state->disp_info->csc_info; 20656027c871SZhang Yubing struct post_csc_coef csc_coef; 20666027c871SZhang Yubing bool is_input_yuv = false; 20676027c871SZhang Yubing bool is_output_yuv = false; 20686027c871SZhang Yubing bool post_r2y_en = false; 20696027c871SZhang Yubing bool post_csc_en = false; 20706027c871SZhang Yubing u32 vp_offset = (cstate->crtc_id * 0x100); 20716027c871SZhang Yubing u32 value; 20726027c871SZhang Yubing int range_type; 20736027c871SZhang Yubing 20746027c871SZhang Yubing printf("post csc enable\n"); 20756027c871SZhang Yubing 20766027c871SZhang Yubing if (acm->acm_enable) { 20776027c871SZhang Yubing if (!cstate->yuv_overlay) 20786027c871SZhang Yubing post_r2y_en = true; 20796027c871SZhang Yubing 20806027c871SZhang Yubing /* do y2r in csc module */ 20816027c871SZhang Yubing if (!is_yuv_output(conn_state->bus_format)) 20826027c871SZhang Yubing post_csc_en = true; 20836027c871SZhang Yubing } else { 20846027c871SZhang Yubing if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 20856027c871SZhang Yubing post_r2y_en = true; 20866027c871SZhang Yubing 20876027c871SZhang Yubing /* do y2r in csc module */ 20886027c871SZhang Yubing if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 20896027c871SZhang Yubing post_csc_en = true; 20906027c871SZhang Yubing } 20916027c871SZhang Yubing 20926027c871SZhang Yubing if (csc->csc_enable) 20936027c871SZhang Yubing post_csc_en = true; 20946027c871SZhang Yubing 20956027c871SZhang Yubing if (cstate->yuv_overlay || post_r2y_en) 20966027c871SZhang Yubing is_input_yuv = true; 20976027c871SZhang Yubing 20986027c871SZhang Yubing if (is_yuv_output(conn_state->bus_format)) 20996027c871SZhang Yubing is_output_yuv = true; 21006027c871SZhang Yubing 21016027c871SZhang Yubing cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_13BIT_DEPTH); 21026027c871SZhang Yubing 21036027c871SZhang Yubing if (post_csc_en) { 21046027c871SZhang Yubing rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv, 21056027c871SZhang Yubing is_output_yuv); 21066027c871SZhang Yubing 21076027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 21086027c871SZhang Yubing POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT, 21096027c871SZhang Yubing csc_coef.csc_coef00, false); 21105743c73eSZhang Yubing value = csc_coef.csc_coef01 & 0xffff; 21115743c73eSZhang Yubing value |= (csc_coef.csc_coef02 << 16) & 0xffff0000; 21126027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02); 21135743c73eSZhang Yubing value = csc_coef.csc_coef10 & 0xffff; 21145743c73eSZhang Yubing value |= (csc_coef.csc_coef11 << 16) & 0xffff0000; 21156027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11); 21165743c73eSZhang Yubing value = csc_coef.csc_coef12 & 0xffff; 21175743c73eSZhang Yubing value |= (csc_coef.csc_coef20 << 16) & 0xffff0000; 21186027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20); 21195743c73eSZhang Yubing value = csc_coef.csc_coef21 & 0xffff; 21205743c73eSZhang Yubing value |= (csc_coef.csc_coef22 << 16) & 0xffff0000; 21216027c871SZhang Yubing writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22); 21226027c871SZhang Yubing writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0); 21236027c871SZhang Yubing writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1); 21246027c871SZhang Yubing writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2); 21256027c871SZhang Yubing 21266027c871SZhang Yubing range_type = csc_coef.range_type ? 0 : 1; 21276027c871SZhang Yubing range_type <<= is_input_yuv ? 0 : 1; 21286027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 21296027c871SZhang Yubing POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false); 21306027c871SZhang Yubing } 21316027c871SZhang Yubing 21326027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 21335743c73eSZhang Yubing POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false); 21346027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 21356027c871SZhang Yubing POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false); 21366027c871SZhang Yubing vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 21376027c871SZhang Yubing POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false); 21386027c871SZhang Yubing } 21396027c871SZhang Yubing 21406027c871SZhang Yubing static void vop3_post_config(struct display_state *state, struct vop2 *vop2) 21416027c871SZhang Yubing { 21426027c871SZhang Yubing struct connector_state *conn_state = &state->conn_state; 21436027c871SZhang Yubing struct base2_disp_info *disp_info = conn_state->disp_info; 21446027c871SZhang Yubing const char *enable_flag; 21456027c871SZhang Yubing if (!disp_info) { 21466027c871SZhang Yubing printf("disp_info is empty\n"); 21476027c871SZhang Yubing return; 21486027c871SZhang Yubing } 21496027c871SZhang Yubing 21506027c871SZhang Yubing enable_flag = (const char *)&disp_info->cacm_header; 21516027c871SZhang Yubing if (strncasecmp(enable_flag, "CACM", 4)) { 21526027c871SZhang Yubing printf("acm and csc is not support\n"); 21536027c871SZhang Yubing return; 21546027c871SZhang Yubing } 21556027c871SZhang Yubing 21566027c871SZhang Yubing vop3_post_acm_config(state, vop2); 21576027c871SZhang Yubing vop3_post_csc_config(state, vop2); 21586027c871SZhang Yubing } 21596027c871SZhang Yubing 2160d2e91fdcSDamon Ding /* 2161d2e91fdcSDamon Ding * Read VOP internal power domain on/off status. 2162d2e91fdcSDamon Ding * We should query BISR_STS register in PMU for 2163d2e91fdcSDamon Ding * power up/down status when memory repair is enabled. 2164d2e91fdcSDamon Ding * Return value: 1 for power on, 0 for power off; 2165d2e91fdcSDamon Ding */ 216660e469f5SDamon Ding static int vop2_wait_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 216760e469f5SDamon Ding { 216860e469f5SDamon Ding int val = 0; 216960e469f5SDamon Ding int shift = 0; 2170b6ba80b4SDamon Ding int shift_factor = 0; 217160e469f5SDamon Ding bool is_bisr_en = false; 217260e469f5SDamon Ding 2173b6ba80b4SDamon Ding /* 2174b6ba80b4SDamon Ding * The order of pd status bits in BISR_STS register 2175b6ba80b4SDamon Ding * is different from that in VOP SYS_STS register. 2176b6ba80b4SDamon Ding */ 2177b6ba80b4SDamon Ding if (pd_data->id == VOP2_PD_DSC_8K || 2178b6ba80b4SDamon Ding pd_data->id == VOP2_PD_DSC_4K || 2179b6ba80b4SDamon Ding pd_data->id == VOP2_PD_ESMART) 2180b6ba80b4SDamon Ding shift_factor = 1; 2181b6ba80b4SDamon Ding 2182b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor; 2183b6ba80b4SDamon Ding is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift); 218460e469f5SDamon Ding if (is_bisr_en) { 2185b6ba80b4SDamon Ding shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor; 2186b6ba80b4SDamon Ding 218760e469f5SDamon Ding return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 2188d2e91fdcSDamon Ding ((val >> shift) & 0x1), 50 * 1000); 218960e469f5SDamon Ding } else { 2190b6ba80b4SDamon Ding shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1; 2191b6ba80b4SDamon Ding 219260e469f5SDamon Ding return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 219360e469f5SDamon Ding !((val >> shift) & 0x1), 50 * 1000); 219460e469f5SDamon Ding } 219560e469f5SDamon Ding } 219660e469f5SDamon Ding 2197b6ba80b4SDamon Ding static int vop2_power_domain_on(struct vop2 *vop2, int pd_id) 219860e469f5SDamon Ding { 219960e469f5SDamon Ding struct vop2_power_domain_data *pd_data; 220060e469f5SDamon Ding int ret = 0; 220160e469f5SDamon Ding 2202b6ba80b4SDamon Ding if (!pd_id) 2203b6ba80b4SDamon Ding return 0; 2204b6ba80b4SDamon Ding 2205b6ba80b4SDamon Ding pd_data = vop2_find_pd_data_by_id(vop2, pd_id); 2206b6ba80b4SDamon Ding if (!pd_data) { 2207b6ba80b4SDamon Ding printf("can't find pd_data by id\n"); 220860e469f5SDamon Ding return -EINVAL; 220960e469f5SDamon Ding } 22102c66af11SDamon Ding 2211b6ba80b4SDamon Ding if (pd_data->parent_id) { 2212b6ba80b4SDamon Ding ret = vop2_power_domain_on(vop2, pd_data->parent_id); 221360e469f5SDamon Ding if (ret) { 221460e469f5SDamon Ding printf("can't open parent power domain\n"); 221560e469f5SDamon Ding return -EINVAL; 221660e469f5SDamon Ding } 221760e469f5SDamon Ding } 221860e469f5SDamon Ding 2219b6ba80b4SDamon Ding vop2_mask_write(vop2, RK3568_SYS_PD_CTRL, EN_MASK, 2220b6ba80b4SDamon Ding RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_id) - 1, 0, false); 222160e469f5SDamon Ding ret = vop2_wait_power_domain_on(vop2, pd_data); 222260e469f5SDamon Ding if (ret) { 222360e469f5SDamon Ding printf("wait vop2 power domain timeout\n"); 222460e469f5SDamon Ding return ret; 222560e469f5SDamon Ding } 222660e469f5SDamon Ding 222760e469f5SDamon Ding return 0; 222860e469f5SDamon Ding } 222960e469f5SDamon Ding 2230ecc31b6eSAndy Yan static void rk3588_vop2_regsbak(struct vop2 *vop2) 2231ecc31b6eSAndy Yan { 2232ecc31b6eSAndy Yan u32 *base = vop2->regs; 2233ecc31b6eSAndy Yan int i = 0; 2234ecc31b6eSAndy Yan 2235ecc31b6eSAndy Yan /* 2236ecc31b6eSAndy Yan * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 2237ecc31b6eSAndy Yan */ 2238ecc31b6eSAndy Yan for (i = 0; i < (vop2->reg_len >> 2); i++) 2239ecc31b6eSAndy Yan vop2->regsbak[i] = base[i]; 2240ecc31b6eSAndy Yan } 2241ecc31b6eSAndy Yan 22425fa6e665SDamon Ding static void vop3_overlay_init(struct vop2 *vop2, struct display_state *state) 22435fa6e665SDamon Ding { 22445fa6e665SDamon Ding struct vop2_win_data *win_data; 22455fa6e665SDamon Ding int layer_phy_id = 0; 22465fa6e665SDamon Ding int i, j; 22475fa6e665SDamon Ding u32 ovl_port_offset = 0; 22485fa6e665SDamon Ding u32 layer_nr = 0; 22495fa6e665SDamon Ding u8 shift = 0; 22505fa6e665SDamon Ding 22515fa6e665SDamon Ding /* layer sel win id */ 22525fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22535fa6e665SDamon Ding shift = 0; 22545fa6e665SDamon Ding ovl_port_offset = 0x100 * i; 22555fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22565fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22575fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22585fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22595fa6e665SDamon Ding vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + ovl_port_offset, LAYER_SEL_MASK, 22605fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 22615fa6e665SDamon Ding shift += 4; 22625fa6e665SDamon Ding } 22635fa6e665SDamon Ding } 22645fa6e665SDamon Ding 22655fa6e665SDamon Ding /* win sel port */ 22665fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22675fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22685fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22695fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 22705fa6e665SDamon Ding continue; 22715fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22725fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22735fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 22745fa6e665SDamon Ding vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL_IMD, LAYER_SEL_PORT_MASK, 22755fa6e665SDamon Ding shift, i, false); 22765fa6e665SDamon Ding } 22775fa6e665SDamon Ding } 22785fa6e665SDamon Ding } 22795fa6e665SDamon Ding 22805fa6e665SDamon Ding static void vop2_overlay_init(struct vop2 *vop2, struct display_state *state) 22815fa6e665SDamon Ding { 22825fa6e665SDamon Ding struct crtc_state *cstate = &state->crtc_state; 22835fa6e665SDamon Ding struct vop2_win_data *win_data; 22845fa6e665SDamon Ding int layer_phy_id = 0; 22855fa6e665SDamon Ding int total_used_layer = 0; 22865fa6e665SDamon Ding int port_mux = 0; 22875fa6e665SDamon Ding int i, j; 22885fa6e665SDamon Ding u32 layer_nr = 0; 22895fa6e665SDamon Ding u8 shift = 0; 22905fa6e665SDamon Ding 22915fa6e665SDamon Ding /* layer sel win id */ 22925fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 22935fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 22945fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 22955fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 22965fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 22975fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 22985fa6e665SDamon Ding shift, win_data->layer_sel_win_id[i], false); 22995fa6e665SDamon Ding shift += 4; 23005fa6e665SDamon Ding } 23015fa6e665SDamon Ding } 23025fa6e665SDamon Ding 23035fa6e665SDamon Ding /* win sel port */ 23045fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 23055fa6e665SDamon Ding layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 23065fa6e665SDamon Ding for (j = 0; j < layer_nr; j++) { 23075fa6e665SDamon Ding if (!vop2->vp_plane_mask[i].attached_layers[j]) 23085fa6e665SDamon Ding continue; 23095fa6e665SDamon Ding layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 23105fa6e665SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 23115fa6e665SDamon Ding shift = win_data->win_sel_port_offset * 2; 23125fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 23135fa6e665SDamon Ding LAYER_SEL_PORT_SHIFT + shift, i, false); 23145fa6e665SDamon Ding } 23155fa6e665SDamon Ding } 23165fa6e665SDamon Ding 23175fa6e665SDamon Ding /** 23185fa6e665SDamon Ding * port mux config 23195fa6e665SDamon Ding */ 23205fa6e665SDamon Ding for (i = 0; i < vop2->data->nr_vps; i++) { 23215fa6e665SDamon Ding shift = i * 4; 23225fa6e665SDamon Ding if (vop2->vp_plane_mask[i].attached_layers_nr) { 23235fa6e665SDamon Ding total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 23245fa6e665SDamon Ding port_mux = total_used_layer - 1; 23255fa6e665SDamon Ding } else { 23265fa6e665SDamon Ding port_mux = 8; 23275fa6e665SDamon Ding } 23285fa6e665SDamon Ding 23295fa6e665SDamon Ding if (i == vop2->data->nr_vps - 1) 23305fa6e665SDamon Ding port_mux = vop2->data->nr_mixers; 23315fa6e665SDamon Ding 23325fa6e665SDamon Ding cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 23335fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 23345fa6e665SDamon Ding PORT_MUX_SHIFT + shift, port_mux, false); 23355fa6e665SDamon Ding } 23365fa6e665SDamon Ding } 23375fa6e665SDamon Ding 23385fa6e665SDamon Ding static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win) 23395fa6e665SDamon Ding { 23405fa6e665SDamon Ding if (!is_vop3(vop2)) 23415fa6e665SDamon Ding return false; 23425fa6e665SDamon Ding 23435fa6e665SDamon Ding if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE && 23445fa6e665SDamon Ding win->phys_id != ROCKCHIP_VOP2_ESMART0) 23455fa6e665SDamon Ding return true; 23465fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE && 23475fa6e665SDamon Ding (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) 23485fa6e665SDamon Ding return true; 23495fa6e665SDamon Ding else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && 23505fa6e665SDamon Ding win->phys_id == ROCKCHIP_VOP2_ESMART1) 23515fa6e665SDamon Ding return true; 23525fa6e665SDamon Ding else 23535fa6e665SDamon Ding return false; 23545fa6e665SDamon Ding } 23555fa6e665SDamon Ding 23565fa6e665SDamon Ding static void vop3_init_esmart_scale_engine(struct vop2 *vop2) 23575fa6e665SDamon Ding { 23585fa6e665SDamon Ding struct vop2_win_data *win_data; 2359fa4ecc32SDamon Ding int i; 23605fa6e665SDamon Ding u8 scale_engine_num = 0; 23615fa6e665SDamon Ding 23625fa6e665SDamon Ding /* store plane mask for vop2_fixup_dts */ 2363fa4ecc32SDamon Ding for (i = 0; i < vop2->data->nr_layers; i++) { 2364fa4ecc32SDamon Ding win_data = &vop2->data->win_data[i]; 23655fa6e665SDamon Ding if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data)) 23665fa6e665SDamon Ding continue; 23675fa6e665SDamon Ding 23685fa6e665SDamon Ding win_data->scale_engine_num = scale_engine_num++; 23695fa6e665SDamon Ding } 23705fa6e665SDamon Ding } 23715fa6e665SDamon Ding 2372b0989546SSandy Huang static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 2373d0408543SAndy Yan { 2374b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 2375b0989546SSandy Huang struct vop2_vp_plane_mask *plane_mask; 23765fa6e665SDamon Ding int layer_phy_id = 0; 23775fa6e665SDamon Ding int i, j; 2378fa4ecc32SDamon Ding int ret; 23795fa6e665SDamon Ding u32 layer_nr = 0; 2380d0408543SAndy Yan 238163cb669fSSandy Huang if (vop2->global_init) 2382d0408543SAndy Yan return; 238363cb669fSSandy Huang 2384b0989546SSandy Huang /* OTP must enable at the first time, otherwise mirror layer register is error */ 238563cb669fSSandy Huang if (soc_is_rk3566()) 238663cb669fSSandy Huang vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 238763cb669fSSandy Huang OTP_WIN_EN_SHIFT, 1, false); 2388b0989546SSandy Huang 2389b0989546SSandy Huang if (cstate->crtc->assign_plane) {/* dts assign plane */ 2390b0989546SSandy Huang u32 plane_mask; 2391b0989546SSandy Huang int primary_plane_id; 2392b0989546SSandy Huang 2393b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2394b0989546SSandy Huang plane_mask = cstate->crtc->vps[i].plane_mask; 2395b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2396b0989546SSandy Huang layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 2397b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 23985fc2b656SDamon Ding primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 2399337d1c13SDamon Ding if (primary_plane_id >= ROCKCHIP_VOP2_LAYER_MAX) 2400b0989546SSandy Huang primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 2401b0989546SSandy Huang vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 2402b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask = plane_mask; 2403b0989546SSandy Huang 2404b0989546SSandy Huang /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 2405b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2406b0989546SSandy Huang vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 2407b0989546SSandy Huang plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 240863cb669fSSandy Huang } 2409b0989546SSandy Huang } 2410b0989546SSandy Huang } else {/* need soft assign plane mask */ 2411b0989546SSandy Huang /* find the first unplug devices and set it as main display */ 2412b0989546SSandy Huang int main_vp_index = -1; 2413b0989546SSandy Huang int active_vp_num = 0; 2414b0989546SSandy Huang 2415b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2416b0989546SSandy Huang if (cstate->crtc->vps[i].enable) 2417b0989546SSandy Huang active_vp_num++; 2418b0989546SSandy Huang } 2419b0989546SSandy Huang printf("VOP have %d active VP\n", active_vp_num); 2420b0989546SSandy Huang 2421b0989546SSandy Huang if (soc_is_rk3566() && active_vp_num > 2) 2422b0989546SSandy Huang printf("ERROR: rk3566 only support 2 display output!!\n"); 2423b0989546SSandy Huang plane_mask = vop2->data->plane_mask; 2424b0989546SSandy Huang plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 24255fa6e665SDamon Ding /* 24265fa6e665SDamon Ding * For rk3528, one display policy for hdmi store in plane_mask[0], and the other 24275fa6e665SDamon Ding * for cvbs store in plane_mask[2]. 24285fa6e665SDamon Ding */ 24295fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && active_vp_num == 1 && 24305fa6e665SDamon Ding cstate->crtc->vps[1].output_type == DRM_MODE_CONNECTOR_TV) 24315fa6e665SDamon Ding plane_mask += 2 * VOP2_VP_MAX; 2432b0989546SSandy Huang 24335fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528) { 24345fa6e665SDamon Ding /* 24355fa6e665SDamon Ding * For rk3528, the plane mask of vp is limited, only esmart2 can be selected 24365fa6e665SDamon Ding * by both vp0 and vp1. 24375fa6e665SDamon Ding */ 24385fa6e665SDamon Ding j = 0; 24395fa6e665SDamon Ding } else { 2440b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2441b0989546SSandy Huang if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 2442b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/ 2443b0989546SSandy Huang main_vp_index = i; 2444e007876dSSandy Huang break; 2445b0989546SSandy Huang } 2446b0989546SSandy Huang } 2447b0989546SSandy Huang 2448b0989546SSandy Huang /* if no find unplug devices, use vp0 as main display */ 2449b0989546SSandy Huang if (main_vp_index < 0) { 2450b0989546SSandy Huang main_vp_index = 0; 2451b0989546SSandy Huang vop2->vp_plane_mask[0] = plane_mask[0]; 2452b0989546SSandy Huang } 2453b0989546SSandy Huang 2454b0989546SSandy Huang j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */ 24555fa6e665SDamon Ding } 2456b0989546SSandy Huang 2457b0989546SSandy Huang /* init other display except main display */ 2458b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2459b0989546SSandy Huang if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */ 2460b0989546SSandy Huang continue; 2461b0989546SSandy Huang vop2->vp_plane_mask[i] = plane_mask[j++]; 2462b0989546SSandy Huang } 2463b0989546SSandy Huang 2464b0989546SSandy Huang /* store plane mask for vop2_fixup_dts */ 2465b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2466b0989546SSandy Huang layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 2467b0989546SSandy Huang for (j = 0; j < layer_nr; j++) { 2468b0989546SSandy Huang layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 2469b0989546SSandy Huang vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 2470b0989546SSandy Huang } 2471b0989546SSandy Huang } 2472b0989546SSandy Huang } 2473b0989546SSandy Huang 247460e469f5SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 247560e469f5SDamon Ding rk3588_vop2_regsbak(vop2); 247660e469f5SDamon Ding else 247760e469f5SDamon Ding memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 247860e469f5SDamon Ding 247960e469f5SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 248060e469f5SDamon Ding OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 248160e469f5SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 248260e469f5SDamon Ding IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 248360e469f5SDamon Ding 2484b0989546SSandy Huang for (i = 0; i < vop2->data->nr_vps; i++) { 2485b0989546SSandy Huang printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 2486b0989546SSandy Huang for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 2487b0989546SSandy Huang printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]); 2488b0989546SSandy Huang printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id); 2489b0989546SSandy Huang } 2490b0989546SSandy Huang 24915fa6e665SDamon Ding if (is_vop3(vop2)) 24925fa6e665SDamon Ding vop3_overlay_init(vop2, state); 24935fa6e665SDamon Ding else 24945fa6e665SDamon Ding vop2_overlay_init(vop2, state); 2495b0989546SSandy Huang 24965fa6e665SDamon Ding if (is_vop3(vop2)) { 24975fa6e665SDamon Ding /* 24985fa6e665SDamon Ding * you can rewrite at dts vop node: 24995fa6e665SDamon Ding * 25005fa6e665SDamon Ding * VOP3_ESMART_8K_MODE = 0, 25015fa6e665SDamon Ding * VOP3_ESMART_4K_4K_MODE = 1, 25025fa6e665SDamon Ding * VOP3_ESMART_4K_2K_2K_MODE = 2, 25035fa6e665SDamon Ding * VOP3_ESMART_2K_2K_2K_2K_MODE = 3, 25045fa6e665SDamon Ding * 25055fa6e665SDamon Ding * &vop { 25065fa6e665SDamon Ding * esmart_lb_mode = /bits/ 8 <2>; 25075fa6e665SDamon Ding * }; 250863cb669fSSandy Huang */ 2509fa4ecc32SDamon Ding ret = ofnode_read_u32(cstate->node, "esmart_lb_mode", &vop2->esmart_lb_mode); 2510fa4ecc32SDamon Ding if (ret < 0) 25115fa6e665SDamon Ding vop2->esmart_lb_mode = vop2->data->esmart_lb_mode; 25125fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, ESMART_LB_MODE_SEL_MASK, 25135fa6e665SDamon Ding ESMART_LB_MODE_SEL_SHIFT, vop2->esmart_lb_mode, false); 2514d0408543SAndy Yan 25155fa6e665SDamon Ding vop3_init_esmart_scale_engine(vop2); 2516aa670293SDamon Ding 2517aa670293SDamon Ding vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK, 2518aa670293SDamon Ding DSP_VS_T_SEL_SHIFT, 0, false); 251963cb669fSSandy Huang } 252063cb669fSSandy Huang 2521ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3568) 252263cb669fSSandy Huang vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 252363cb669fSSandy Huang 252463cb669fSSandy Huang vop2->global_init = true; 2525d0408543SAndy Yan } 2526d0408543SAndy Yan 2527d0408543SAndy Yan static int vop2_initial(struct vop2 *vop2, struct display_state *state) 2528d0408543SAndy Yan { 25291147facaSSandy Huang rockchip_vop2_gamma_lut_init(vop2, state); 25306414e3bcSSandy Huang rockchip_vop2_cubic_lut_init(vop2, state); 2531d0408543SAndy Yan 2532d0408543SAndy Yan return 0; 2533d0408543SAndy Yan } 2534d0408543SAndy Yan 2535d0408543SAndy Yan /* 2536d0408543SAndy Yan * VOP2 have multi video ports. 2537d0408543SAndy Yan * video port ------- crtc 2538d0408543SAndy Yan */ 2539d0408543SAndy Yan static int rockchip_vop2_preinit(struct display_state *state) 2540d0408543SAndy Yan { 2541d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2542d0408543SAndy Yan const struct vop2_data *vop2_data = cstate->crtc->data; 2543d0408543SAndy Yan 2544d0408543SAndy Yan if (!rockchip_vop2) { 25450d2d6a97SSandy Huang rockchip_vop2 = calloc(1, sizeof(struct vop2)); 2546d0408543SAndy Yan if (!rockchip_vop2) 2547d0408543SAndy Yan return -ENOMEM; 2548d8e7f4a5SSandy Huang memset(rockchip_vop2, 0, sizeof(struct vop2)); 2549d0408543SAndy Yan rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 2550d0408543SAndy Yan rockchip_vop2->reg_len = RK3568_MAX_REG; 2551d8e7f4a5SSandy Huang #ifdef CONFIG_SPL_BUILD 2552d8e7f4a5SSandy Huang rockchip_vop2->regs = (void *)RK3528_VOP_BASE; 2553d8e7f4a5SSandy Huang #else 2554d8e7f4a5SSandy Huang rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 255563cb669fSSandy Huang rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2556d0408543SAndy Yan if (rockchip_vop2->grf <= 0) 255763cb669fSSandy Huang printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 2558d8e7f4a5SSandy Huang #endif 2559d0408543SAndy Yan rockchip_vop2->version = vop2_data->version; 2560d0408543SAndy Yan rockchip_vop2->data = vop2_data; 2561ecc31b6eSAndy Yan if (rockchip_vop2->version == VOP_VERSION_RK3588) { 2562b890760eSAlgea Cao struct regmap *map; 2563b890760eSAlgea Cao 2564ecc31b6eSAndy Yan rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF); 2565ecc31b6eSAndy Yan if (rockchip_vop2->vop_grf <= 0) 2566ecc31b6eSAndy Yan printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf); 2567b890760eSAlgea Cao map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); 2568b890760eSAlgea Cao rockchip_vop2->vo1_grf = regmap_get_range(map, 0); 2569ecc31b6eSAndy Yan if (rockchip_vop2->vo1_grf <= 0) 2570ecc31b6eSAndy Yan printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf); 257160e469f5SDamon Ding rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); 2572b890760eSAlgea Cao if (rockchip_vop2->sys_pmu <= 0) 257360e469f5SDamon Ding printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu); 2574ecc31b6eSAndy Yan } 2575d0408543SAndy Yan } 2576d0408543SAndy Yan 2577d0408543SAndy Yan cstate->private = rockchip_vop2; 257863cb669fSSandy Huang cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 257963cb669fSSandy Huang cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 2580d0408543SAndy Yan 258189912f2dSSandy Huang vop2_global_initial(rockchip_vop2, state); 258289912f2dSSandy Huang 2583d0408543SAndy Yan return 0; 2584d0408543SAndy Yan } 2585d0408543SAndy Yan 2586ecc31b6eSAndy Yan /* 2587ecc31b6eSAndy Yan * calc the dclk on rk3588 2588ecc31b6eSAndy Yan * the available div of dclk is 1, 2, 4 2589ecc31b6eSAndy Yan * 2590ecc31b6eSAndy Yan */ 2591ecc31b6eSAndy Yan static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 2592ecc31b6eSAndy Yan { 2593ecc31b6eSAndy Yan if (child_clk * 4 <= max_dclk) 2594ecc31b6eSAndy Yan return child_clk * 4; 2595ecc31b6eSAndy Yan else if (child_clk * 2 <= max_dclk) 2596ecc31b6eSAndy Yan return child_clk * 2; 2597ecc31b6eSAndy Yan else if (child_clk <= max_dclk) 2598ecc31b6eSAndy Yan return child_clk; 2599ecc31b6eSAndy Yan else 2600ecc31b6eSAndy Yan return 0; 2601ecc31b6eSAndy Yan } 2602ecc31b6eSAndy Yan 2603ecc31b6eSAndy Yan /* 2604ecc31b6eSAndy Yan * 4 pixclk/cycle on rk3588 2605ecc31b6eSAndy Yan * RGB/eDP/HDMI: if_pixclk >= dclk_core 2606ecc31b6eSAndy Yan * DP: dp_pixclk = dclk_out <= dclk_core 2607ecc31b6eSAndy Yan * DSI: mipi_pixclk <= dclk_out <= dclk_core 2608ecc31b6eSAndy Yan */ 2609ecc31b6eSAndy Yan static unsigned long vop2_calc_cru_cfg(struct display_state *state, 2610ecc31b6eSAndy Yan int *dclk_core_div, int *dclk_out_div, 2611ecc31b6eSAndy Yan int *if_pixclk_div, int *if_dclk_div) 2612d0408543SAndy Yan { 2613d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 2614d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 2615d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2616d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 26170a1fb152SZhang Yubing unsigned long v_pixclk = mode->crtc_clock; 2618ecc31b6eSAndy Yan unsigned long dclk_core_rate = v_pixclk >> 2; 2619ecc31b6eSAndy Yan unsigned long dclk_rate = v_pixclk; 2620ecc31b6eSAndy Yan unsigned long dclk_out_rate; 2621ecc31b6eSAndy Yan u64 if_dclk_rate; 2622ecc31b6eSAndy Yan u64 if_pixclk_rate; 2623ecc31b6eSAndy Yan int output_type = conn_state->type; 2624ecc31b6eSAndy Yan int output_mode = conn_state->output_mode; 2625ecc31b6eSAndy Yan int K = 1; 2626ecc31b6eSAndy Yan 26270a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE && 26280a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 26290a1fb152SZhang Yubing printf("Dual channel and YUV420 can't work together\n"); 26300a1fb152SZhang Yubing return -EINVAL; 26310a1fb152SZhang Yubing } 26320a1fb152SZhang Yubing 26330a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 26340a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) 26350a1fb152SZhang Yubing K = 2; 26360a1fb152SZhang Yubing 2637ecc31b6eSAndy Yan if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 2638ecc31b6eSAndy Yan /* 2639ecc31b6eSAndy Yan * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 2640ecc31b6eSAndy Yan * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 2641ecc31b6eSAndy Yan */ 26420a1fb152SZhang Yubing if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 26430a1fb152SZhang Yubing output_mode == ROCKCHIP_OUT_MODE_YUV420) { 2644b890760eSAlgea Cao dclk_rate = dclk_rate >> 1; 2645ecc31b6eSAndy Yan K = 2; 2646b890760eSAlgea Cao } 264712ee5af0SDamon Ding if (cstate->dsc_enable) { 264812ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate << 1; 264912ee5af0SDamon Ding if_dclk_rate = cstate->dsc_cds_clk_rate; 2650ecc31b6eSAndy Yan } else { 2651ecc31b6eSAndy Yan if_pixclk_rate = (dclk_core_rate << 1) / K; 2652ecc31b6eSAndy Yan if_dclk_rate = dclk_core_rate / K; 2653ecc31b6eSAndy Yan } 2654ecc31b6eSAndy Yan 2655631ee99aSZhang Yubing if (v_pixclk > VOP2_MAX_DCLK_RATE) 26564b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_core_rate, 26574b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 2658631ee99aSZhang Yubing 2659ecc31b6eSAndy Yan if (!dclk_rate) { 2660ecc31b6eSAndy Yan printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 26614b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, if_pixclk_rate); 2662ecc31b6eSAndy Yan return -EINVAL; 2663ecc31b6eSAndy Yan } 2664ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 2665ecc31b6eSAndy Yan *if_dclk_div = dclk_rate / if_dclk_rate; 2666b890760eSAlgea Cao *dclk_core_div = dclk_rate / dclk_core_rate; 2667b890760eSAlgea Cao printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n", 2668b890760eSAlgea Cao dclk_rate, *if_pixclk_div, *if_dclk_div); 2669ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 2670ecc31b6eSAndy Yan /* edp_pixclk = edp_dclk > dclk_core */ 2671ecc31b6eSAndy Yan if_pixclk_rate = v_pixclk / K; 2672ecc31b6eSAndy Yan if_dclk_rate = v_pixclk / K; 2673ecc31b6eSAndy Yan dclk_rate = if_pixclk_rate * K; 2674ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2675ecc31b6eSAndy Yan *if_pixclk_div = dclk_rate / if_pixclk_rate; 2676ecc31b6eSAndy Yan *if_dclk_div = *if_pixclk_div; 2677ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 2678ecc31b6eSAndy Yan dclk_out_rate = v_pixclk >> 2; 26790a1fb152SZhang Yubing dclk_out_rate = dclk_out_rate / K; 2680ecc31b6eSAndy Yan 26814b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 26824b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 2683ecc31b6eSAndy Yan if (!dclk_rate) { 2684ecc31b6eSAndy Yan printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 26854b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_core_rate); 2686ecc31b6eSAndy Yan return -EINVAL; 2687ecc31b6eSAndy Yan } 2688ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 2689ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2690ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 2691ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2692ecc31b6eSAndy Yan K = 2; 269312ee5af0SDamon Ding if (cstate->dsc_enable) 269412ee5af0SDamon Ding /* dsc output is 96bit, dsi input is 192 bit */ 269512ee5af0SDamon Ding if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1; 2696ecc31b6eSAndy Yan else 2697ecc31b6eSAndy Yan if_pixclk_rate = dclk_core_rate / K; 2698ecc31b6eSAndy Yan /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 269912ee5af0SDamon Ding dclk_out_rate = dclk_core_rate / K; 2700ecc31b6eSAndy Yan /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 27014b726cc6SDamon Ding dclk_rate = vop2_calc_dclk(dclk_out_rate, 27024b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk); 27039f076eccSZhang Yubing if (!dclk_rate) { 27049f076eccSZhang Yubing printf("MIPI dclk out of range(max_dclk: %d KHZ, dclk_rate: %ld KHZ)\n", 27054b726cc6SDamon Ding vop2->data->vp_data[cstate->crtc_id].max_dclk, dclk_rate); 27069f076eccSZhang Yubing return -EINVAL; 27079f076eccSZhang Yubing } 270812ee5af0SDamon Ding 270912ee5af0SDamon Ding if (cstate->dsc_enable) 2710d57af898SDamon Ding dclk_rate /= cstate->dsc_slice_num; 271112ee5af0SDamon Ding 2712ecc31b6eSAndy Yan *dclk_out_div = dclk_rate / dclk_out_rate; 2713ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2714ecc31b6eSAndy Yan *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 271512ee5af0SDamon Ding if (cstate->dsc_enable) 27161ace1b6dSDamon Ding *if_pixclk_div = dclk_out_rate * 1000LL / if_pixclk_rate; 2717ecc31b6eSAndy Yan 2718ecc31b6eSAndy Yan } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 2719ecc31b6eSAndy Yan dclk_rate = v_pixclk; 2720ecc31b6eSAndy Yan *dclk_core_div = dclk_rate / dclk_core_rate; 2721ecc31b6eSAndy Yan } 2722ecc31b6eSAndy Yan 2723ecc31b6eSAndy Yan *if_pixclk_div = ilog2(*if_pixclk_div); 2724ecc31b6eSAndy Yan *if_dclk_div = ilog2(*if_dclk_div); 2725ecc31b6eSAndy Yan *dclk_core_div = ilog2(*dclk_core_div); 2726ecc31b6eSAndy Yan *dclk_out_div = ilog2(*dclk_out_div); 2727ecc31b6eSAndy Yan 2728ecc31b6eSAndy Yan return dclk_rate; 2729ecc31b6eSAndy Yan } 2730ecc31b6eSAndy Yan 273112ee5af0SDamon Ding static int vop2_calc_dsc_clk(struct display_state *state) 2732ecc31b6eSAndy Yan { 273312ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 2734ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 273512ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 27361ace1b6dSDamon Ding u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */ 2737ecc31b6eSAndy Yan u8 k = 1; 2738ecc31b6eSAndy Yan 2739ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2740ecc31b6eSAndy Yan k = 2; 2741ecc31b6eSAndy Yan 274212ee5af0SDamon Ding cstate->dsc_txp_clk_rate = v_pixclk; 274312ee5af0SDamon Ding do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k)); 2744ecc31b6eSAndy Yan 274512ee5af0SDamon Ding cstate->dsc_pxl_clk_rate = v_pixclk; 274612ee5af0SDamon Ding do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k)); 2747ecc31b6eSAndy Yan 2748ecc31b6eSAndy Yan /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 2749ecc31b6eSAndy Yan * cds_dat_width = 96; 2750ecc31b6eSAndy Yan * bits_per_pixel = [8-12]; 2751b61227a3SDamon Ding * As cds clk is div from txp clk and only support 1/2/4 div, 2752b61227a3SDamon Ding * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4, 2753b61227a3SDamon Ding * otherwise dsc_cds = crtc_clock / 8; 2754ecc31b6eSAndy Yan */ 2755b61227a3SDamon Ding cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8); 2756ecc31b6eSAndy Yan 2757ecc31b6eSAndy Yan return 0; 2758ecc31b6eSAndy Yan } 2759ecc31b6eSAndy Yan 2760ecc31b6eSAndy Yan static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 2761ecc31b6eSAndy Yan { 2762ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2763ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2764ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 276512ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 2766ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 276752ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 2768ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 2769ecc31b6eSAndy Yan int output_if = conn_state->output_if; 2770ecc31b6eSAndy Yan int if_pixclk_div = 0; 2771ecc31b6eSAndy Yan int if_dclk_div = 0; 2772ecc31b6eSAndy Yan unsigned long dclk_rate; 2773d0408543SAndy Yan u32 val; 2774ecc31b6eSAndy Yan 2775b890760eSAlgea Cao if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 2776b890760eSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 2777b890760eSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 2778b890760eSAlgea Cao } else { 2779ecc31b6eSAndy Yan val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 2780ecc31b6eSAndy Yan val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2781b890760eSAlgea Cao } 2782ecc31b6eSAndy Yan 278312ee5af0SDamon Ding if (cstate->dsc_enable) { 278412ee5af0SDamon Ding int k = 1; 278512ee5af0SDamon Ding 2786ecc31b6eSAndy Yan if (!vop2->data->nr_dscs) { 278712ee5af0SDamon Ding printf("Unsupported DSC\n"); 2788ecc31b6eSAndy Yan return 0; 2789ecc31b6eSAndy Yan } 279012ee5af0SDamon Ding 279112ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 279212ee5af0SDamon Ding k = 2; 279312ee5af0SDamon Ding 279412ee5af0SDamon Ding cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 279512ee5af0SDamon Ding cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k; 279612ee5af0SDamon Ding cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num; 279712ee5af0SDamon Ding 279812ee5af0SDamon Ding vop2_calc_dsc_clk(state); 279912ee5af0SDamon Ding printf("Enable DSC%d slice:%dx%d, slice num:%d\n", 280012ee5af0SDamon Ding cstate->dsc_id, dsc_sink_cap->slice_width, 280112ee5af0SDamon Ding dsc_sink_cap->slice_height, cstate->dsc_slice_num); 2802ecc31b6eSAndy Yan } 2803ecc31b6eSAndy Yan 2804b61227a3SDamon Ding dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div); 2805ecc31b6eSAndy Yan 2806ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_RGB) { 2807ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2808ecc31b6eSAndy Yan 4, false); 2809ecc31b6eSAndy Yan } 2810ecc31b6eSAndy Yan 2811ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT1120) { 2812ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2813ecc31b6eSAndy Yan 3, false); 2814ecc31b6eSAndy Yan } 2815ecc31b6eSAndy Yan 2816ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_BT656) { 2817ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2818ecc31b6eSAndy Yan 2, false); 2819ecc31b6eSAndy Yan } 2820ecc31b6eSAndy Yan 2821ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI0) { 2822ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2823ecc31b6eSAndy Yan val = 0; 2824ecc31b6eSAndy Yan else 2825ecc31b6eSAndy Yan val = 1; 282641874944SGuochun Huang 28273df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 282841874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 282941874944SGuochun Huang RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 283041874944SGuochun Huang 2831ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 2832ecc31b6eSAndy Yan 1, false); 2833ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 2834ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 2835ecc31b6eSAndy Yan if_pixclk_div, false); 283641874944SGuochun Huang 283741874944SGuochun Huang if (conn_state->hold_mode) { 283841874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 28398e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 284041874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 284141874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 284241874944SGuochun Huang } 2843ecc31b6eSAndy Yan } 2844ecc31b6eSAndy Yan 2845ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_MIPI1) { 2846ecc31b6eSAndy Yan if (cstate->crtc_id == 2) 2847ecc31b6eSAndy Yan val = 0; 2848ecc31b6eSAndy Yan else if (cstate->crtc_id == 3) 2849ecc31b6eSAndy Yan val = 1; 2850ecc31b6eSAndy Yan else 2851ecc31b6eSAndy Yan val = 3; /*VP1*/ 28523df6e59eSDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 285341874944SGuochun Huang vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 285441874944SGuochun Huang RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 285541874944SGuochun Huang 2856ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 2857ecc31b6eSAndy Yan 1, false); 2858ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 2859ecc31b6eSAndy Yan val, false); 2860ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 2861ecc31b6eSAndy Yan if_pixclk_div, false); 286241874944SGuochun Huang 286341874944SGuochun Huang if (conn_state->hold_mode) { 286441874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 28658e7ef808SDamon Ding EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 286641874944SGuochun Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 286741874944SGuochun Huang EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 286841874944SGuochun Huang } 2869ecc31b6eSAndy Yan } 2870ecc31b6eSAndy Yan 2871ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 28723df6e59eSDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 28733df6e59eSDamon Ding MIPI_DUAL_EN_SHIFT, 1, false); 2874ecc31b6eSAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2875ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2876ecc31b6eSAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 2877ecc31b6eSAndy Yan false); 28780a1fb152SZhang Yubing switch (conn_state->type) { 28790a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DisplayPort: 28800a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28810a1fb152SZhang Yubing RK3588_DP_DUAL_EN_SHIFT, 1, false); 28820a1fb152SZhang Yubing break; 28830a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_eDP: 28840a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28850a1fb152SZhang Yubing RK3588_EDP_DUAL_EN_SHIFT, 1, false); 28860a1fb152SZhang Yubing break; 28870a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_HDMIA: 28880a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28890a1fb152SZhang Yubing RK3588_HDMI_DUAL_EN_SHIFT, 1, false); 28900a1fb152SZhang Yubing break; 28910a1fb152SZhang Yubing case DRM_MODE_CONNECTOR_DSI: 28920a1fb152SZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 28930a1fb152SZhang Yubing RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 28940a1fb152SZhang Yubing break; 28950a1fb152SZhang Yubing default: 28960a1fb152SZhang Yubing break; 28970a1fb152SZhang Yubing } 2898ecc31b6eSAndy Yan } 2899ecc31b6eSAndy Yan 2900ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP0) { 2901ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 2902ecc31b6eSAndy Yan 1, false); 2903ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2904ecc31b6eSAndy Yan cstate->crtc_id, false); 2905ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2906ecc31b6eSAndy Yan if_dclk_div, false); 2907ecc31b6eSAndy Yan 2908ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2909ecc31b6eSAndy Yan if_pixclk_div, false); 2910ecc31b6eSAndy Yan 2911ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2912ecc31b6eSAndy Yan RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 2913ecc31b6eSAndy Yan } 2914ecc31b6eSAndy Yan 2915ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_eDP1) { 2916ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 2917ecc31b6eSAndy Yan 1, false); 2918ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2919ecc31b6eSAndy Yan cstate->crtc_id, false); 2920ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2921ecc31b6eSAndy Yan if_dclk_div, false); 2922ecc31b6eSAndy Yan 2923ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2924ecc31b6eSAndy Yan if_pixclk_div, false); 29251848455fSDamon Ding 29261848455fSDamon Ding vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 29271848455fSDamon Ding RK3588_GRF_EDP1_ENABLE_SHIFT, 1); 2928ecc31b6eSAndy Yan } 2929ecc31b6eSAndy Yan 2930ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI0) { 2931ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 2932ecc31b6eSAndy Yan 1, false); 2933ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 2934ecc31b6eSAndy Yan cstate->crtc_id, false); 2935ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 2936ecc31b6eSAndy Yan if_dclk_div, false); 2937ecc31b6eSAndy Yan 2938ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 2939ecc31b6eSAndy Yan if_pixclk_div, false); 2940b890760eSAlgea Cao 2941b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2942b890760eSAlgea Cao RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1); 2943b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2944b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2945b890760eSAlgea Cao HDMI0_SYNC_POL_SHIFT, val); 2946ecc31b6eSAndy Yan } 2947ecc31b6eSAndy Yan 2948ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_HDMI1) { 2949ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 2950ecc31b6eSAndy Yan 1, false); 2951ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 2952ecc31b6eSAndy Yan cstate->crtc_id, false); 2953ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 2954ecc31b6eSAndy Yan if_dclk_div, false); 2955ecc31b6eSAndy Yan 2956ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 2957ecc31b6eSAndy Yan if_pixclk_div, false); 2958b890760eSAlgea Cao 2959b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 2960b890760eSAlgea Cao RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1); 2961b890760eSAlgea Cao vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 2962b890760eSAlgea Cao HDMI_SYNC_POL_MASK, 2963b890760eSAlgea Cao HDMI1_SYNC_POL_SHIFT, val); 2964ecc31b6eSAndy Yan } 2965ecc31b6eSAndy Yan 2966ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP0) { 2967ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 2968ecc31b6eSAndy Yan 1, false); 2969ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 2970ecc31b6eSAndy Yan cstate->crtc_id, false); 2971ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2972ecc31b6eSAndy Yan RK3588_DP0_PIN_POL_SHIFT, val, false); 2973ecc31b6eSAndy Yan } 2974ecc31b6eSAndy Yan 2975ecc31b6eSAndy Yan if (output_if & VOP_OUTPUT_IF_DP1) { 2976108c5f8bSZhang Yubing vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT, 2977ecc31b6eSAndy Yan 1, false); 2978ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 2979ecc31b6eSAndy Yan cstate->crtc_id, false); 2980ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2981ecc31b6eSAndy Yan RK3588_DP1_PIN_POL_SHIFT, val, false); 2982ecc31b6eSAndy Yan } 2983ecc31b6eSAndy Yan 2984ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2985b61227a3SDamon Ding DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false); 2986ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2987b61227a3SDamon Ding DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false); 2988ecc31b6eSAndy Yan 2989ecc31b6eSAndy Yan return dclk_rate; 2990ecc31b6eSAndy Yan } 2991ecc31b6eSAndy Yan 2992ecc31b6eSAndy Yan static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 2993ecc31b6eSAndy Yan { 2994ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 2995ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 2996ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 2997ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 2998ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 2999d0408543SAndy Yan bool dclk_inv; 3000ecc31b6eSAndy Yan u32 val; 30018895aec1SSandy Huang 300213f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 300310ee9f5bSAlgea Cao val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 300410ee9f5bSAlgea Cao val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3005d0408543SAndy Yan 3006d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3007d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3008d0408543SAndy Yan 1, false); 3009d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3010d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 301115f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 301215f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3013ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 3014c55d261eSSandy Huang GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 3015d0408543SAndy Yan } 3016d0408543SAndy Yan 3017d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 301852ee18acSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 301952ee18acSSandy Huang 1, false); 3020d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 3021d0408543SAndy Yan BT1120_EN_SHIFT, 1, false); 3022d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3023d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 3024ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 302552ee18acSSandy Huang GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 3026d0408543SAndy Yan } 3027d0408543SAndy Yan 3028d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 3029d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 3030d0408543SAndy Yan 1, false); 3031d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3032d0408543SAndy Yan RGB_MUX_SHIFT, cstate->crtc_id, false); 3033ecc31b6eSAndy Yan vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 303452ee18acSSandy Huang GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 3035d0408543SAndy Yan } 3036d0408543SAndy Yan 3037d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3038d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3039d0408543SAndy Yan 1, false); 3040d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3041d0408543SAndy Yan LVDS0_MUX_SHIFT, cstate->crtc_id, false); 304215f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 304315f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 304411f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 304515f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3046d0408543SAndy Yan } 3047d0408543SAndy Yan 3048d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 3049d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 3050d0408543SAndy Yan 1, false); 3051d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3052d0408543SAndy Yan LVDS1_MUX_SHIFT, cstate->crtc_id, false); 305315f69071SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 305415f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 305511f53190SSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 305615f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3057d0408543SAndy Yan } 3058d0408543SAndy Yan 3059d0408543SAndy Yan if (conn_state->output_flags & 3060d0408543SAndy Yan (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 3061d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 3062d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3063d0408543SAndy Yan LVDS_DUAL_EN_SHIFT, 1, false); 3064d0408543SAndy Yan if (conn_state->output_flags & 3065d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3066d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3067d0408543SAndy Yan LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 3068d0408543SAndy Yan false); 3069d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3070d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3071d0408543SAndy Yan LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 3072d0408543SAndy Yan } 3073d0408543SAndy Yan 3074d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3075d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3076d0408543SAndy Yan 1, false); 3077d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3078d0408543SAndy Yan MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3079d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3080c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3081d0408543SAndy Yan } 3082d0408543SAndy Yan 3083d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 3084d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 3085d0408543SAndy Yan 1, false); 3086d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3087d0408543SAndy Yan MIPI1_MUX_SHIFT, cstate->crtc_id, false); 3088d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3089c55d261eSSandy Huang IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 3090d0408543SAndy Yan } 3091d0408543SAndy Yan 3092d0408543SAndy Yan if (conn_state->output_flags & 3093d0408543SAndy Yan ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 3094d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3095d0408543SAndy Yan MIPI_DUAL_EN_SHIFT, 1, false); 3096d0408543SAndy Yan if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3097d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3098d0408543SAndy Yan EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 3099d0408543SAndy Yan false); 3100d0408543SAndy Yan } 3101d0408543SAndy Yan 3102d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 3103d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 3104d0408543SAndy Yan 1, false); 3105d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3106d0408543SAndy Yan EDP0_MUX_SHIFT, cstate->crtc_id, false); 3107c55d261eSSandy Huang vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3108c55d261eSSandy Huang IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 31097bcdc6eeSDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK, 31107bcdc6eeSDamon Ding IF_CTRL_EDP_PIN_POL_SHIFT, val, false); 3111d0408543SAndy Yan } 3112d0408543SAndy Yan 3113d0408543SAndy Yan if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 3114d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 3115d0408543SAndy Yan 1, false); 3116d0408543SAndy Yan vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3117d0408543SAndy Yan HDMI0_MUX_SHIFT, cstate->crtc_id, false); 311810ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 311910ee9f5bSAlgea Cao IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 312010ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_DSP_IF_POL, 312110ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_MASK, 312210ee9f5bSAlgea Cao IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 3123d0408543SAndy Yan } 312410ee9f5bSAlgea Cao 3125ecc31b6eSAndy Yan return mode->clock; 3126ecc31b6eSAndy Yan } 3127ecc31b6eSAndy Yan 31285fa6e665SDamon Ding static unsigned long rk3528_vop2_if_cfg(struct display_state *state) 31295fa6e665SDamon Ding { 31305fa6e665SDamon Ding struct crtc_state *cstate = &state->crtc_state; 31315fa6e665SDamon Ding struct connector_state *conn_state = &state->conn_state; 31325fa6e665SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 31335fa6e665SDamon Ding struct vop2 *vop2 = cstate->private; 31345fa6e665SDamon Ding u32 val; 31355fa6e665SDamon Ding 31365fa6e665SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 31375fa6e665SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 31385fa6e665SDamon Ding 31395fa6e665SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 31405fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 31415fa6e665SDamon Ding 1, false); 31425fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 31435fa6e665SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 31445fa6e665SDamon Ding } 31455fa6e665SDamon Ding 31465fa6e665SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 31475fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 31485fa6e665SDamon Ding 1, false); 31495fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 31505fa6e665SDamon Ding HDMI0_MUX_SHIFT, cstate->crtc_id, false); 31515fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 31525fa6e665SDamon Ding IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 31535fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, 31545fa6e665SDamon Ding IF_CRTL_HDMI_PIN_POL_MASK, 31555fa6e665SDamon Ding IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 31565fa6e665SDamon Ding } 31575fa6e665SDamon Ding 31585fa6e665SDamon Ding return mode->crtc_clock; 31595fa6e665SDamon Ding } 31605fa6e665SDamon Ding 3161452afb13SDamon Ding static unsigned long rk3562_vop2_if_cfg(struct display_state *state) 3162452afb13SDamon Ding { 3163452afb13SDamon Ding struct crtc_state *cstate = &state->crtc_state; 3164452afb13SDamon Ding struct connector_state *conn_state = &state->conn_state; 3165452afb13SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 3166452afb13SDamon Ding struct vop2 *vop2 = cstate->private; 3167452afb13SDamon Ding bool dclk_inv; 3168452afb13SDamon Ding u32 val; 3169452afb13SDamon Ding 317013f658dcSDamon Ding dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3171452afb13SDamon Ding val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3172452afb13SDamon Ding val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3173452afb13SDamon Ding 3174452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 3175452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 3176452afb13SDamon Ding 1, false); 3177452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3178452afb13SDamon Ding RGB_MUX_SHIFT, cstate->crtc_id, false); 3179452afb13SDamon Ding vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK, 3180452afb13SDamon Ding GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 3181452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 318215f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3183452afb13SDamon Ding } 3184452afb13SDamon Ding 3185452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 3186452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 3187452afb13SDamon Ding 1, false); 3188452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3189452afb13SDamon Ding LVDS0_MUX_SHIFT, cstate->crtc_id, false); 3190452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 319115f69071SDamon Ding IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 3192452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 319315f69071SDamon Ding IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 3194452afb13SDamon Ding } 3195452afb13SDamon Ding 3196452afb13SDamon Ding if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 3197452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 3198452afb13SDamon Ding 1, false); 3199452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 3200452afb13SDamon Ding MIPI0_MUX_SHIFT, cstate->crtc_id, false); 3201452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3202452afb13SDamon Ding RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false); 3203452afb13SDamon Ding vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 3204452afb13SDamon Ding RK3562_MIPI_PIN_POL_SHIFT, val, false); 3205452afb13SDamon Ding } 3206452afb13SDamon Ding 3207452afb13SDamon Ding return mode->crtc_clock; 3208452afb13SDamon Ding } 3209452afb13SDamon Ding 321065747de7SDamon Ding static void vop2_post_color_swap(struct display_state *state) 321165747de7SDamon Ding { 321265747de7SDamon Ding struct crtc_state *cstate = &state->crtc_state; 321365747de7SDamon Ding struct connector_state *conn_state = &state->conn_state; 321465747de7SDamon Ding struct vop2 *vop2 = cstate->private; 321565747de7SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 321665747de7SDamon Ding u32 output_type = conn_state->type; 321765747de7SDamon Ding u32 data_swap = 0; 321865747de7SDamon Ding 32190675a2a4SDamon Ding if (is_uv_swap(conn_state->bus_format, conn_state->output_mode) || 32200675a2a4SDamon Ding is_rb_swap(conn_state->bus_format, conn_state->output_mode)) 322165747de7SDamon Ding data_swap = DSP_RB_SWAP; 322265747de7SDamon Ding 322365747de7SDamon Ding if (vop2->version == VOP_VERSION_RK3588 && 322465747de7SDamon Ding (output_type == DRM_MODE_CONNECTOR_HDMIA || 322565747de7SDamon Ding output_type == DRM_MODE_CONNECTOR_eDP) && 322665747de7SDamon Ding (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 322765747de7SDamon Ding conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 322865747de7SDamon Ding data_swap |= DSP_RG_SWAP; 322965747de7SDamon Ding 323065747de7SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 323165747de7SDamon Ding DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 323265747de7SDamon Ding } 323365747de7SDamon Ding 3234b890760eSAlgea Cao static void vop2_clk_set_parent(struct clk *clk, struct clk *parent) 3235b890760eSAlgea Cao { 3236b890760eSAlgea Cao int ret = 0; 3237b890760eSAlgea Cao 3238b890760eSAlgea Cao if (parent->dev) 3239b890760eSAlgea Cao ret = clk_set_parent(clk, parent); 3240b890760eSAlgea Cao if (ret < 0) 3241b890760eSAlgea Cao debug("failed to set %s as parent for %s\n", 3242b890760eSAlgea Cao parent->dev->name, clk->dev->name); 3243b890760eSAlgea Cao } 3244b890760eSAlgea Cao 3245b890760eSAlgea Cao static ulong vop2_clk_set_rate(struct clk *clk, ulong rate) 3246b890760eSAlgea Cao { 3247b890760eSAlgea Cao int ret = 0; 3248b890760eSAlgea Cao 3249b890760eSAlgea Cao if (clk->dev) 3250b890760eSAlgea Cao ret = clk_set_rate(clk, rate); 3251b890760eSAlgea Cao if (ret < 0) 3252b890760eSAlgea Cao debug("failed to set %s rate %lu \n", clk->dev->name, rate); 3253b890760eSAlgea Cao 3254b890760eSAlgea Cao return ret; 3255b890760eSAlgea Cao } 3256b890760eSAlgea Cao 325712ee5af0SDamon Ding static void vop2_calc_dsc_cru_cfg(struct display_state *state, 325812ee5af0SDamon Ding int *dsc_txp_clk_div, int *dsc_pxl_clk_div, 325912ee5af0SDamon Ding int *dsc_cds_clk_div, u64 dclk_rate) 326012ee5af0SDamon Ding { 326112ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 326212ee5af0SDamon Ding 326312ee5af0SDamon Ding *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate; 326412ee5af0SDamon Ding *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate; 326512ee5af0SDamon Ding *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate; 326612ee5af0SDamon Ding 326712ee5af0SDamon Ding *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div); 326812ee5af0SDamon Ding *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div); 326912ee5af0SDamon Ding *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div); 327012ee5af0SDamon Ding } 327112ee5af0SDamon Ding 327212ee5af0SDamon Ding static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id) 327312ee5af0SDamon Ding { 327412ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 327512ee5af0SDamon Ding struct drm_dsc_picture_parameter_set *pps = &cstate->pps; 327612ee5af0SDamon Ding struct drm_dsc_picture_parameter_set config_pps; 327712ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 327812ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 327912ee5af0SDamon Ding u32 *pps_val = (u32 *)&config_pps; 328012ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 328112ee5af0SDamon Ding int i = 0; 328212ee5af0SDamon Ding 328312ee5af0SDamon Ding memcpy(&config_pps, pps, sizeof(config_pps)); 328412ee5af0SDamon Ding 328512ee5af0SDamon Ding if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) { 328612ee5af0SDamon Ding config_pps.pps_3 &= 0xf0; 328712ee5af0SDamon Ding config_pps.pps_3 |= dsc_data->max_linebuf_depth; 328812ee5af0SDamon Ding printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n", 328912ee5af0SDamon Ding dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf); 329012ee5af0SDamon Ding } 329112ee5af0SDamon Ding 329212ee5af0SDamon Ding for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 329312ee5af0SDamon Ding config_pps.rc_range_parameters[i] = 329412ee5af0SDamon Ding (pps->rc_range_parameters[i] >> 3 & 0x1f) | 329512ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) | 329612ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) | 329712ee5af0SDamon Ding ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10); 329812ee5af0SDamon Ding } 329912ee5af0SDamon Ding 330012ee5af0SDamon Ding for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++) 330112ee5af0SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++); 330212ee5af0SDamon Ding } 330312ee5af0SDamon Ding 330412ee5af0SDamon Ding static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate) 330512ee5af0SDamon Ding { 330612ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 330712ee5af0SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 330812ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 330912ee5af0SDamon Ding struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 331012ee5af0SDamon Ding const struct vop2_data *vop2_data = vop2->data; 331112ee5af0SDamon Ding const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 331212ee5af0SDamon Ding bool mipi_ds_mode = false; 331312ee5af0SDamon Ding u8 dsc_interface_mode = 0; 331412ee5af0SDamon Ding u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 331512ee5af0SDamon Ding u16 hdisplay = mode->crtc_hdisplay; 331612ee5af0SDamon Ding u16 htotal = mode->crtc_htotal; 331712ee5af0SDamon Ding u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 331812ee5af0SDamon Ding u16 vdisplay = mode->crtc_vdisplay; 331912ee5af0SDamon Ding u16 vtotal = mode->crtc_vtotal; 332012ee5af0SDamon Ding u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 332112ee5af0SDamon Ding u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 332212ee5af0SDamon Ding u16 vact_end = vact_st + vdisplay; 332312ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 332412ee5af0SDamon Ding u32 decoder_regs_offset = (dsc_id * 0x100); 332512ee5af0SDamon Ding int dsc_txp_clk_div = 0; 332612ee5af0SDamon Ding int dsc_pxl_clk_div = 0; 332712ee5af0SDamon Ding int dsc_cds_clk_div = 0; 3328baf2c414SDamon Ding int val = 0; 332912ee5af0SDamon Ding 333012ee5af0SDamon Ding if (!vop2->data->nr_dscs) { 333112ee5af0SDamon Ding printf("Unsupported DSC\n"); 333212ee5af0SDamon Ding return; 333312ee5af0SDamon Ding } 333412ee5af0SDamon Ding 333512ee5af0SDamon Ding if (cstate->dsc_slice_num > dsc_data->max_slice_num) 333612ee5af0SDamon Ding printf("DSC%d supported max slice is: %d, current is: %d\n", 333712ee5af0SDamon Ding dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num); 333812ee5af0SDamon Ding 333912ee5af0SDamon Ding if (dsc_data->pd_id) { 334012ee5af0SDamon Ding if (vop2_power_domain_on(vop2, dsc_data->pd_id)) 334112ee5af0SDamon Ding printf("open dsc%d pd fail\n", dsc_id); 334212ee5af0SDamon Ding } 334312ee5af0SDamon Ding 334412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK, 334512ee5af0SDamon Ding SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false); 334612ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK, 334712ee5af0SDamon Ding DSC_PORT_SEL_SHIFT, cstate->crtc_id, false); 334812ee5af0SDamon Ding if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 334912ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_HDMI; 335012ee5af0SDamon Ding } else { 335112ee5af0SDamon Ding mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE); 335212ee5af0SDamon Ding if (mipi_ds_mode) 335312ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE; 335412ee5af0SDamon Ding else 335512ee5af0SDamon Ding dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE; 335612ee5af0SDamon Ding } 335712ee5af0SDamon Ding 335812ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 335912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 336012ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 0, false); 336112ee5af0SDamon Ding else 336212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 336312ee5af0SDamon Ding DSC_MAN_MODE_SHIFT, 1, false); 336412ee5af0SDamon Ding 336512ee5af0SDamon Ding vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate); 336612ee5af0SDamon Ding 336712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK, 336812ee5af0SDamon Ding DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false); 336912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK, 337012ee5af0SDamon Ding DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false); 337112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK, 337212ee5af0SDamon Ding DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false); 337312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK, 337412ee5af0SDamon Ding DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false); 337512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 337612ee5af0SDamon Ding DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false); 337712ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK, 337812ee5af0SDamon Ding DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false); 337912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 338012ee5af0SDamon Ding DSC_HALT_EN_SHIFT, mipi_ds_mode, false); 338112ee5af0SDamon Ding 338212ee5af0SDamon Ding if (!mipi_ds_mode) { 338312ee5af0SDamon Ding u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end; 338412ee5af0SDamon Ding u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16; 338512ee5af0SDamon Ding u64 dsc_cds_rate = cstate->dsc_cds_clk_rate; 338612ee5af0SDamon Ding u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */ 338712ee5af0SDamon Ding u32 dly_num, dsc_cds_rate_mhz, val = 0; 3388b61227a3SDamon Ding int k = 1; 3389b61227a3SDamon Ding 3390b61227a3SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3391b61227a3SDamon Ding k = 2; 339212ee5af0SDamon Ding 339312ee5af0SDamon Ding if (target_bpp >> 4 < dsc_data->min_bits_per_pixel) 339412ee5af0SDamon Ding printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel); 339512ee5af0SDamon Ding 339612ee5af0SDamon Ding /* 339712ee5af0SDamon Ding * dly_num = delay_line_num * T(one-line) / T (dsc_cds) 339812ee5af0SDamon Ding * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz 339912ee5af0SDamon Ding * T (dsc_cds) = 1 / dsc_cds_rate_mhz 34001ace1b6dSDamon Ding * 34011ace1b6dSDamon Ding * HDMI: 340212ee5af0SDamon Ding * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay 340312ee5af0SDamon Ding * delay_line_num = 4 - BPP / 8 340412ee5af0SDamon Ding * = (64 - target_bpp / 8) / 16 340512ee5af0SDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 34061ace1b6dSDamon Ding * 34071ace1b6dSDamon Ding * MIPI DSI[4320 and 9216 is buffer size for DSC]: 34081ace1b6dSDamon Ding * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size; 34091ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 34101ace1b6dSDamon Ding * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size; 34111ace1b6dSDamon Ding * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 34121ace1b6dSDamon Ding * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num 341312ee5af0SDamon Ding */ 341412ee5af0SDamon Ding do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ 341512ee5af0SDamon Ding dsc_cds_rate_mhz = dsc_cds_rate; 34161ace1b6dSDamon Ding dsc_hsync = hsync_len / 2; 34171ace1b6dSDamon Ding if (dsc_interface_mode == VOP_DSC_IF_HDMI) { 341812ee5af0SDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 34191ace1b6dSDamon Ding } else { 34201ace1b6dSDamon Ding int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2; 34211ace1b6dSDamon Ding int delay_line_num = dsc_buf_size / cstate->dsc_slice_num / 34221ace1b6dSDamon Ding be16_to_cpu(cstate->pps.chunk_size); 34231ace1b6dSDamon Ding 34241ace1b6dSDamon Ding delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 34251ace1b6dSDamon Ding dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num; 34261ace1b6dSDamon Ding 34271ace1b6dSDamon Ding /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */ 34281ace1b6dSDamon Ding if (dsc_hsync < 8) 34291ace1b6dSDamon Ding dsc_hsync = 8; 34301ace1b6dSDamon Ding } 343112ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK, 343212ee5af0SDamon Ding DSC_INIT_DLY_MODE_SHIFT, 0, false); 343312ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK, 343412ee5af0SDamon Ding DSC_INIT_DLY_NUM_SHIFT, dly_num, false); 343512ee5af0SDamon Ding 3436b61227a3SDamon Ding /* 3437b61227a3SDamon Ding * htotal / dclk_core = dsc_htotal /cds_clk 3438b61227a3SDamon Ding * 3439b61227a3SDamon Ding * dclk_core = DCLK / (1 << dclk_core->div_val) 3440b61227a3SDamon Ding * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val) 3441b61227a3SDamon Ding * txp_clk = DCLK / (1 << dsc_txp_clk->div_val) 3442b61227a3SDamon Ding * 3443b61227a3SDamon Ding * dsc_htotal = htotal * (1 << dclk_core->div_val) / 3444b61227a3SDamon Ding * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val)) 3445b61227a3SDamon Ding */ 3446b61227a3SDamon Ding dsc_htotal = htotal * (1 << cstate->dclk_core_div) / 3447b61227a3SDamon Ding ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div)); 344812ee5af0SDamon Ding val = dsc_htotal << 16 | dsc_hsync; 344912ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK, 345012ee5af0SDamon Ding DSC_HTOTAL_PW_SHIFT, val, false); 345112ee5af0SDamon Ding 345212ee5af0SDamon Ding dsc_hact_st = hact_st / 2; 3453b61227a3SDamon Ding dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st; 345412ee5af0SDamon Ding val = dsc_hact_end << 16 | dsc_hact_st; 345512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK, 345612ee5af0SDamon Ding DSC_HACT_ST_END_SHIFT, val, false); 345712ee5af0SDamon Ding 345812ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK, 345912ee5af0SDamon Ding DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false); 346012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK, 346112ee5af0SDamon Ding DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false); 346212ee5af0SDamon Ding } 346312ee5af0SDamon Ding 346412ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK, 346512ee5af0SDamon Ding RST_DEASSERT_SHIFT, 1, false); 346612ee5af0SDamon Ding udelay(10); 346712ee5af0SDamon Ding 3468baf2c414SDamon Ding val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) | 3469baf2c414SDamon Ding ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT); 3470baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 3471baf2c414SDamon Ding 347212ee5af0SDamon Ding vop2_load_pps(state, vop2, dsc_id); 347312ee5af0SDamon Ding 3474baf2c414SDamon Ding val |= (1 << DSC_PPS_UPD_SHIFT); 3475baf2c414SDamon Ding vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 347612ee5af0SDamon Ding 347712ee5af0SDamon Ding printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n", 347812ee5af0SDamon Ding dsc_id, 347912ee5af0SDamon Ding cstate->dsc_txp_clk_rate, dsc_txp_clk_div, 348012ee5af0SDamon Ding cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div, 348112ee5af0SDamon Ding cstate->dsc_cds_clk_rate, dsc_cds_clk_div); 348212ee5af0SDamon Ding } 348312ee5af0SDamon Ding 34845f1357a2SZhang Yubing static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev) 34855f1357a2SZhang Yubing { 34865f1357a2SZhang Yubing struct crtc_state *cstate = &state->crtc_state; 34875f1357a2SZhang Yubing struct vop2 *vop2 = cstate->private; 34885f1357a2SZhang Yubing struct udevice *vp_dev, *dev; 34895f1357a2SZhang Yubing struct ofnode_phandle_args args; 34905f1357a2SZhang Yubing char vp_name[10]; 34915f1357a2SZhang Yubing int ret; 34925f1357a2SZhang Yubing 34935f1357a2SZhang Yubing if (vop2->version != VOP_VERSION_RK3588) 34945f1357a2SZhang Yubing return false; 34955f1357a2SZhang Yubing 34965f1357a2SZhang Yubing sprintf(vp_name, "port@%d", cstate->crtc_id); 34975f1357a2SZhang Yubing if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) { 34985e85f4a7SZhang Yubing debug("warn: can't get vp device\n"); 34995f1357a2SZhang Yubing return false; 35005f1357a2SZhang Yubing } 35015f1357a2SZhang Yubing 35025f1357a2SZhang Yubing ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0, 35035f1357a2SZhang Yubing 0, &args); 35045f1357a2SZhang Yubing if (ret) { 35055e85f4a7SZhang Yubing debug("assigned-clock-parents's node not define\n"); 35065f1357a2SZhang Yubing return false; 35075f1357a2SZhang Yubing } 35085f1357a2SZhang Yubing 35095f1357a2SZhang Yubing if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) { 35105e85f4a7SZhang Yubing debug("warn: can't get clk device\n"); 35115f1357a2SZhang Yubing return false; 35125f1357a2SZhang Yubing } 35135f1357a2SZhang Yubing 35145f1357a2SZhang Yubing if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) { 35155f1357a2SZhang Yubing printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name); 35165f1357a2SZhang Yubing if (clk_dev) 35175f1357a2SZhang Yubing *clk_dev = dev; 35185f1357a2SZhang Yubing return true; 35195f1357a2SZhang Yubing } 35205f1357a2SZhang Yubing 35215f1357a2SZhang Yubing return false; 35225f1357a2SZhang Yubing } 35235f1357a2SZhang Yubing 35240675a2a4SDamon Ding static void vop3_mcu_mode_setup(struct display_state *state) 35250675a2a4SDamon Ding { 35260675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 35270675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 35280675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 35290675a2a4SDamon Ding 35300675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 35310675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false); 35320675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 35330675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false); 35340675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 35350675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false); 35360675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 35370675a2a4SDamon Ding MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false); 35380675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 35390675a2a4SDamon Ding MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false); 35400675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 35410675a2a4SDamon Ding MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false); 35420675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 35430675a2a4SDamon Ding MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false); 35440675a2a4SDamon Ding } 35450675a2a4SDamon Ding 35460675a2a4SDamon Ding static void vop3_mcu_bypass_mode_setup(struct display_state *state) 35470675a2a4SDamon Ding { 35480675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 35490675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 35500675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 35510675a2a4SDamon Ding 35520675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 35530675a2a4SDamon Ding MCU_TYPE_SHIFT, 1, false); 35540675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 35550675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 1, false); 35560675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 35570675a2a4SDamon Ding MCU_PIX_TOTAL_SHIFT, 53, false); 35580675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 35590675a2a4SDamon Ding MCU_CS_PST_SHIFT, 6, false); 35600675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 35610675a2a4SDamon Ding MCU_CS_PEND_SHIFT, 48, false); 35620675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 35630675a2a4SDamon Ding MCU_RW_PST_SHIFT, 12, false); 35640675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 35650675a2a4SDamon Ding MCU_RW_PEND_SHIFT, 30, false); 35660675a2a4SDamon Ding } 35670675a2a4SDamon Ding 35680675a2a4SDamon Ding static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value) 35690675a2a4SDamon Ding { 35700675a2a4SDamon Ding struct crtc_state *cstate = &state->crtc_state; 35710675a2a4SDamon Ding struct connector_state *conn_state = &state->conn_state; 35720675a2a4SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 35730675a2a4SDamon Ding struct vop2 *vop2 = cstate->private; 35740675a2a4SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 35750675a2a4SDamon Ding u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 35760675a2a4SDamon Ding 35770675a2a4SDamon Ding /* 35780675a2a4SDamon Ding * 1.disable port dclk auto gating. 35790675a2a4SDamon Ding * 2.set mcu bypass mode timing to adapt to the mode of sending cmds. 35800675a2a4SDamon Ding * 3.make setting of output mode take effect. 35810675a2a4SDamon Ding * 4.set dclk rate to 150M, in order to sync with hclk in sending cmds. 35820675a2a4SDamon Ding */ 35830675a2a4SDamon Ding if (type == MCU_SETBYPASS && value) { 35840675a2a4SDamon Ding vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK, 35850675a2a4SDamon Ding AUTO_GATING_EN_SHIFT, 0, false); 35860675a2a4SDamon Ding vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK, 35870675a2a4SDamon Ding PORT_DCLK_AUTO_GATING_EN_SHIFT, 0, false); 35880675a2a4SDamon Ding vop3_mcu_bypass_mode_setup(state); 35890675a2a4SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 35900675a2a4SDamon Ding STANDBY_EN_SHIFT, 0, false); 35910675a2a4SDamon Ding vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 35920675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, 150000000); 35930675a2a4SDamon Ding } 35940675a2a4SDamon Ding 35950675a2a4SDamon Ding switch (type) { 35960675a2a4SDamon Ding case MCU_WRCMD: 35970675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 35980675a2a4SDamon Ding MCU_RS_SHIFT, 0, false); 35990675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 36000675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 36010675a2a4SDamon Ding value, false); 36020675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 36030675a2a4SDamon Ding MCU_RS_SHIFT, 1, false); 36040675a2a4SDamon Ding break; 36050675a2a4SDamon Ding case MCU_WRDATA: 36060675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 36070675a2a4SDamon Ding MCU_RS_SHIFT, 1, false); 36080675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 36090675a2a4SDamon Ding MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 36100675a2a4SDamon Ding value, false); 36110675a2a4SDamon Ding break; 36120675a2a4SDamon Ding case MCU_SETBYPASS: 36130675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 36140675a2a4SDamon Ding MCU_BYPASS_SHIFT, value ? 1 : 0, false); 36150675a2a4SDamon Ding break; 36160675a2a4SDamon Ding default: 36170675a2a4SDamon Ding break; 36180675a2a4SDamon Ding } 36190675a2a4SDamon Ding 36200675a2a4SDamon Ding /* 36210675a2a4SDamon Ding * 1.restore port dclk auto gating. 36220675a2a4SDamon Ding * 2.restore mcu data mode timing. 36230675a2a4SDamon Ding * 3.restore dclk rate to crtc_clock. 36240675a2a4SDamon Ding */ 36250675a2a4SDamon Ding if (type == MCU_SETBYPASS && !value) { 36260675a2a4SDamon Ding vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK, 36270675a2a4SDamon Ding AUTO_GATING_EN_SHIFT, 1, false); 36280675a2a4SDamon Ding vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK, 36290675a2a4SDamon Ding PORT_DCLK_AUTO_GATING_EN_SHIFT, 1, false); 36300675a2a4SDamon Ding vop3_mcu_mode_setup(state); 36310675a2a4SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 36320675a2a4SDamon Ding STANDBY_EN_SHIFT, 1, false); 36330675a2a4SDamon Ding vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000); 36340675a2a4SDamon Ding } 36350675a2a4SDamon Ding 36360675a2a4SDamon Ding return 0; 36370675a2a4SDamon Ding } 36380675a2a4SDamon Ding 363934d37ef0SDamon Ding static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id) 364034d37ef0SDamon Ding { 364134d37ef0SDamon Ding u32 vp_offset = crtc_id * 0x100; 364234d37ef0SDamon Ding u8 dither_down_mode = 0; 364334d37ef0SDamon Ding bool dither_down_en = false; 364434d37ef0SDamon Ding bool pre_dither_down_en = false; 364534d37ef0SDamon Ding 364634d37ef0SDamon Ding switch (bus_format) { 364734d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB565_1X16: 364834d37ef0SDamon Ding dither_down_en = true; 364934d37ef0SDamon Ding dither_down_mode = RGB888_TO_RGB565; 365034d37ef0SDamon Ding pre_dither_down_en = true; 365134d37ef0SDamon Ding break; 365234d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X18: 365334d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 365434d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 365534d37ef0SDamon Ding dither_down_en = true; 365634d37ef0SDamon Ding dither_down_mode = RGB888_TO_RGB666; 365734d37ef0SDamon Ding pre_dither_down_en = true; 365834d37ef0SDamon Ding break; 365934d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV8_1X16: 366034d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV8_1X24: 366134d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 366234d37ef0SDamon Ding dither_down_en = false; 366334d37ef0SDamon Ding pre_dither_down_en = true; 366434d37ef0SDamon Ding break; 366534d37ef0SDamon Ding case MEDIA_BUS_FMT_YUYV10_1X20: 366634d37ef0SDamon Ding case MEDIA_BUS_FMT_YUV10_1X30: 366734d37ef0SDamon Ding case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 366834d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB101010_1X30: 366934d37ef0SDamon Ding dither_down_en = false; 367034d37ef0SDamon Ding pre_dither_down_en = false; 367134d37ef0SDamon Ding break; 367234d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_3X8: 367334d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: 367434d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X24: 367534d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 367634d37ef0SDamon Ding case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 367734d37ef0SDamon Ding default: 367834d37ef0SDamon Ding dither_down_en = false; 367934d37ef0SDamon Ding pre_dither_down_en = true; 368034d37ef0SDamon Ding break; 368134d37ef0SDamon Ding } 368234d37ef0SDamon Ding 368334d37ef0SDamon Ding if (is_yuv_output(bus_format)) 368434d37ef0SDamon Ding pre_dither_down_en = false; 368534d37ef0SDamon Ding 368634d37ef0SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 368734d37ef0SDamon Ding PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 368834d37ef0SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 368934d37ef0SDamon Ding DITHER_DOWN_EN_SHIFT, dither_down_en, false); 369034d37ef0SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 369134d37ef0SDamon Ding DITHER_DOWN_MODE_SHIFT, dither_down_mode, false); 369234d37ef0SDamon Ding } 369334d37ef0SDamon Ding 3694ecc31b6eSAndy Yan static int rockchip_vop2_init(struct display_state *state) 3695ecc31b6eSAndy Yan { 3696ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 3697c2b1fe35SDamon Ding struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id]; 3698ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 3699ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 3700ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 3701ecc31b6eSAndy Yan u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 3702ecc31b6eSAndy Yan u16 hdisplay = mode->crtc_hdisplay; 3703ecc31b6eSAndy Yan u16 htotal = mode->crtc_htotal; 3704ecc31b6eSAndy Yan u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 3705ecc31b6eSAndy Yan u16 hact_end = hact_st + hdisplay; 3706ecc31b6eSAndy Yan u16 vdisplay = mode->crtc_vdisplay; 3707ecc31b6eSAndy Yan u16 vtotal = mode->crtc_vtotal; 3708ecc31b6eSAndy Yan u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 3709ecc31b6eSAndy Yan u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 3710ecc31b6eSAndy Yan u16 vact_end = vact_st + vdisplay; 3711ecc31b6eSAndy Yan bool yuv_overlay = false; 3712ecc31b6eSAndy Yan u32 vp_offset = (cstate->crtc_id * 0x100); 371366724b9cSDamon Ding u32 line_flag_offset = (cstate->crtc_id * 4); 371466724b9cSDamon Ding u32 val, act_end; 3715edfef528SDamon Ding u8 dclk_div_factor = 0; 3716ecc31b6eSAndy Yan char output_type_name[30] = {0}; 3717d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 3718ecc31b6eSAndy Yan char dclk_name[9]; 3719d8e7f4a5SSandy Huang #endif 3720b890760eSAlgea Cao struct clk hdmi0_phy_pll; 3721b890760eSAlgea Cao struct clk hdmi1_phy_pll; 37225f1357a2SZhang Yubing struct clk hdmi_phy_pll; 37233e05a7b8SZhang Yubing struct udevice *disp_dev; 37245fa6e665SDamon Ding unsigned long dclk_rate = 0; 3725ecc31b6eSAndy Yan int ret; 3726ecc31b6eSAndy Yan 3727ecc31b6eSAndy Yan printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 372871ac76f7SDamon Ding mode->crtc_hdisplay, mode->vdisplay, 3729ecc31b6eSAndy Yan mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 3730*4d64cedbSDamon Ding mode->vrefresh, 3731ecc31b6eSAndy Yan get_output_if_name(conn_state->output_if, output_type_name), 3732ecc31b6eSAndy Yan cstate->crtc_id); 3733ecc31b6eSAndy Yan 3734ee01dbb2SDamon Ding if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { 3735ee01dbb2SDamon Ding cstate->splice_mode = true; 3736ee01dbb2SDamon Ding cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id; 3737ee01dbb2SDamon Ding if (!cstate->splice_crtc_id) { 3738ee01dbb2SDamon Ding printf("%s: Splice mode is unsupported by vp%d\n", 3739ee01dbb2SDamon Ding __func__, cstate->crtc_id); 3740ee01dbb2SDamon Ding return -EINVAL; 3741ee01dbb2SDamon Ding } 3742b70b2d79SDamon Ding 3743b70b2d79SDamon Ding vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK, 3744b70b2d79SDamon Ding PORT_MERGE_EN_SHIFT, 1, false); 3745ee01dbb2SDamon Ding } 3746ee01dbb2SDamon Ding 3747cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 3748cd6c85a9SDamon Ding RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false); 3749cd6c85a9SDamon Ding vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 3750cd6c85a9SDamon Ding RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false); 3751cd6c85a9SDamon Ding 3752ecc31b6eSAndy Yan vop2_initial(vop2, state); 3753ecc31b6eSAndy Yan if (vop2->version == VOP_VERSION_RK3588) 3754ecc31b6eSAndy Yan dclk_rate = rk3588_vop2_if_cfg(state); 37555fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3568) 3756ecc31b6eSAndy Yan dclk_rate = rk3568_vop2_if_cfg(state); 37575fa6e665SDamon Ding else if (vop2->version == VOP_VERSION_RK3528) 37585fa6e665SDamon Ding dclk_rate = rk3528_vop2_if_cfg(state); 3759452afb13SDamon Ding else if (vop2->version == VOP_VERSION_RK3562) 3760452afb13SDamon Ding dclk_rate = rk3562_vop2_if_cfg(state); 3761ecc31b6eSAndy Yan 376263cb669fSSandy Huang if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 376363cb669fSSandy Huang !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) 37647bdd0eb6SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 37657bdd0eb6SSandy Huang 376665747de7SDamon Ding vop2_post_color_swap(state); 376710ee9f5bSAlgea Cao 3768d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 3769d0408543SAndy Yan OUT_MODE_SHIFT, conn_state->output_mode, false); 3770d0408543SAndy Yan 377134d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id); 377234d37ef0SDamon Ding if (cstate->splice_mode) 377334d37ef0SDamon Ding vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id); 3774d0408543SAndy Yan 3775d0408543SAndy Yan yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 3776d0408543SAndy Yan vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 3777d0408543SAndy Yan yuv_overlay, false); 3778d0408543SAndy Yan 3779d0408543SAndy Yan cstate->yuv_overlay = yuv_overlay; 3780d0408543SAndy Yan 3781d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 3782d0408543SAndy Yan (htotal << 16) | hsync_len); 3783d0408543SAndy Yan val = hact_st << 16; 3784d0408543SAndy Yan val |= hact_end; 3785d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 3786d0408543SAndy Yan val = vact_st << 16; 3787d0408543SAndy Yan val |= vact_end; 3788d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 3789d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 3790d0408543SAndy Yan u16 vact_st_f1 = vtotal + vact_st + 1; 3791d0408543SAndy Yan u16 vact_end_f1 = vact_st_f1 + vdisplay; 3792d0408543SAndy Yan 3793d0408543SAndy Yan val = vact_st_f1 << 16 | vact_end_f1; 3794d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 3795d0408543SAndy Yan val); 3796d0408543SAndy Yan 3797d0408543SAndy Yan val = vtotal << 16 | (vtotal + vsync_len); 3798d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 3799d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3800d0408543SAndy Yan INTERLACE_EN_SHIFT, 1, false); 3801d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 38027a20be36SSandy Huang DSP_FILED_POL, 1, false); 38037a20be36SSandy Huang vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3804d0408543SAndy Yan P2I_EN_SHIFT, 1, false); 3805d0408543SAndy Yan vtotal += vtotal + 1; 380666724b9cSDamon Ding act_end = vact_end_f1; 3807d0408543SAndy Yan } else { 3808d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3809d0408543SAndy Yan INTERLACE_EN_SHIFT, 0, false); 3810d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3811d0408543SAndy Yan P2I_EN_SHIFT, 0, false); 381266724b9cSDamon Ding act_end = vact_end; 3813d0408543SAndy Yan } 3814d0408543SAndy Yan vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 3815d0408543SAndy Yan (vtotal << 16) | vsync_len); 381667be2ffcSDamon Ding 381767be2ffcSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || 381867be2ffcSDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 3819d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 382067be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 1, false); 382167be2ffcSDamon Ding else 382267be2ffcSDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 382367be2ffcSDamon Ding CORE_DCLK_DIV_EN_SHIFT, 0, false); 382410ee9f5bSAlgea Cao 382510ee9f5bSAlgea Cao if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 382663cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 382763cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 382810ee9f5bSAlgea Cao else 382963cb669fSSandy Huang vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 383063cb669fSSandy Huang DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 383110ee9f5bSAlgea Cao 3832ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 3833ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false); 3834ee01dbb2SDamon Ding 383510ee9f5bSAlgea Cao if (yuv_overlay) 383610ee9f5bSAlgea Cao val = 0x20010200; 383710ee9f5bSAlgea Cao else 383810ee9f5bSAlgea Cao val = 0; 383910ee9f5bSAlgea Cao vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 3840b70b2d79SDamon Ding if (cstate->splice_mode) { 3841ee01dbb2SDamon Ding vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 3842ee01dbb2SDamon Ding OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id, 3843ee01dbb2SDamon Ding yuv_overlay, false); 3844ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val); 3845ee01dbb2SDamon Ding } 384610ee9f5bSAlgea Cao 384710ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 384810ee9f5bSAlgea Cao POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 3849d0408543SAndy Yan 3850c2b1fe35SDamon Ding if (vp->xmirror_en) 3851c2b1fe35SDamon Ding vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 3852c2b1fe35SDamon Ding DSP_X_MIR_EN_SHIFT, 1, false); 3853c2b1fe35SDamon Ding 3854ac500a1fSSandy Huang vop2_tv_config_update(state, vop2); 3855d0408543SAndy Yan vop2_post_config(state, vop2); 38566027c871SZhang Yubing if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) 38576027c871SZhang Yubing vop3_post_config(state, vop2); 3858d0408543SAndy Yan 385912ee5af0SDamon Ding if (cstate->dsc_enable) { 386012ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 38611ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL); 38621ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL); 386312ee5af0SDamon Ding } else { 38641ace1b6dSDamon Ding vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL); 386512ee5af0SDamon Ding } 386612ee5af0SDamon Ding } 386712ee5af0SDamon Ding 3868d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 3869ecc31b6eSAndy Yan snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 38700675a2a4SDamon Ding ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk); 3871b890760eSAlgea Cao if (ret) { 3872b890760eSAlgea Cao printf("%s: Failed to get dclk ret=%d\n", __func__, ret); 3873b890760eSAlgea Cao return ret; 3874b890760eSAlgea Cao } 3875d8e7f4a5SSandy Huang #endif 3876b890760eSAlgea Cao 38773e05a7b8SZhang Yubing ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev); 38783e05a7b8SZhang Yubing if (!ret) { 38793e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll); 38803e05a7b8SZhang Yubing if (ret) 38815e85f4a7SZhang Yubing debug("%s: hdmi0_phy_pll may not define\n", __func__); 38823e05a7b8SZhang Yubing ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll); 38833e05a7b8SZhang Yubing if (ret) 38845e85f4a7SZhang Yubing debug("%s: hdmi1_phy_pll may not define\n", __func__); 38853e05a7b8SZhang Yubing } else { 3886b890760eSAlgea Cao hdmi0_phy_pll.dev = NULL; 3887545a0218SAlgea Cao hdmi1_phy_pll.dev = NULL; 38885e85f4a7SZhang Yubing debug("%s: Faile to find display-subsystem node\n", __func__); 3889b890760eSAlgea Cao } 3890b890760eSAlgea Cao 3891ebbd144cSAlgea Cao if (vop2->version == VOP_VERSION_RK3528) { 3892ebbd144cSAlgea Cao struct ofnode_phandle_args args; 3893ebbd144cSAlgea Cao 3894ebbd144cSAlgea Cao ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents", 3895ebbd144cSAlgea Cao "#clock-cells", 0, 0, &args); 3896ebbd144cSAlgea Cao if (!ret) { 3897ebbd144cSAlgea Cao ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev); 3898ebbd144cSAlgea Cao if (ret) { 3899ebbd144cSAlgea Cao debug("warn: can't get clk device\n"); 3900ebbd144cSAlgea Cao return ret; 3901ebbd144cSAlgea Cao } 3902ebbd144cSAlgea Cao } else { 3903ebbd144cSAlgea Cao debug("assigned-clock-parents's node not define\n"); 3904ebbd144cSAlgea Cao } 3905ebbd144cSAlgea Cao } 3906ebbd144cSAlgea Cao 39070a1fb152SZhang Yubing if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) { 3908b890760eSAlgea Cao if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) 39090675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll); 3910b890760eSAlgea Cao else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1) 39110675a2a4SDamon Ding vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll); 3912b890760eSAlgea Cao 3913b890760eSAlgea Cao /* 3914b890760eSAlgea Cao * uboot clk driver won't set dclk parent's rate when use 3915b890760eSAlgea Cao * hdmi phypll as dclk source. 3916b890760eSAlgea Cao * So set dclk rate is meaningless. Set hdmi phypll rate 3917b890760eSAlgea Cao * directly. 3918b890760eSAlgea Cao */ 39195f1357a2SZhang Yubing if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) { 3920b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate * 1000); 39215f1357a2SZhang Yubing } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) { 3922b890760eSAlgea Cao ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate * 1000); 39235f1357a2SZhang Yubing } else { 39247efea85dSDamon Ding if (is_extend_pll(state, &hdmi_phy_pll.dev)) { 39255f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 39267efea85dSDamon Ding } else { 3927d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 39280675a2a4SDamon Ding ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate * 1000); 3929d8e7f4a5SSandy Huang #else 3930d8e7f4a5SSandy Huang if (vop2->version == VOP_VERSION_RK3528) { 3931d8e7f4a5SSandy Huang void *cru_base = (void *)RK3528_CRU_BASE; 3932d8e7f4a5SSandy Huang 3933d8e7f4a5SSandy Huang /* dclk src switch to hdmiphy pll */ 3934d8e7f4a5SSandy Huang writel((BIT(0) << 16) | BIT(0), cru_base + 0x450); 3935d8e7f4a5SSandy Huang rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000); 3936d8e7f4a5SSandy Huang ret = dclk_rate * 1000; 3937d8e7f4a5SSandy Huang } 3938d8e7f4a5SSandy Huang #endif 39395f1357a2SZhang Yubing } 39407efea85dSDamon Ding } 3941631ee99aSZhang Yubing } else { 39425f1357a2SZhang Yubing if (is_extend_pll(state, &hdmi_phy_pll.dev)) 39435f1357a2SZhang Yubing ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate * 1000); 39445f1357a2SZhang Yubing else 39450675a2a4SDamon Ding ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate * 1000); 3946edfef528SDamon Ding } 394763638f32SDamon Ding 394863638f32SDamon Ding if (IS_ERR_VALUE(ret)) { 394963638f32SDamon Ding printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 395063638f32SDamon Ding __func__, cstate->crtc_id, dclk_rate, ret); 395163638f32SDamon Ding return ret; 395263638f32SDamon Ding } else { 3953*4d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total) { 3954*4d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) / 1000; 3955*4d64cedbSDamon Ding } else { 3956edfef528SDamon Ding dclk_div_factor = mode->clock / dclk_rate; 39575fa6e665SDamon Ding if (vop2->version == VOP_VERSION_RK3528 && 39585fa6e665SDamon Ding conn_state->output_if & VOP_OUTPUT_IF_BT656) 3959*4d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) / 4 / 1000; 39605fa6e665SDamon Ding else 3961*4d64cedbSDamon Ding mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000; 3962*4d64cedbSDamon Ding } 3963edfef528SDamon Ding printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); 3964631ee99aSZhang Yubing } 3965ecc31b6eSAndy Yan 396666724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 3967e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false); 396866724b9cSDamon Ding vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 3969e24e9033SSandy Huang RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false); 397066724b9cSDamon Ding 39710675a2a4SDamon Ding if (cstate->mcu_timing.mcu_pix_total) 39720675a2a4SDamon Ding vop3_mcu_mode_setup(state); 39730675a2a4SDamon Ding 3974d0408543SAndy Yan return 0; 3975d0408543SAndy Yan } 3976d0408543SAndy Yan 3977ecc31b6eSAndy Yan static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 39783e39a5a1SSandy Huang uint32_t src_w, uint32_t src_h, uint32_t dst_w, 39793e39a5a1SSandy Huang uint32_t dst_h) 39803e39a5a1SSandy Huang { 39813e39a5a1SSandy Huang uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 39823e39a5a1SSandy Huang uint16_t hscl_filter_mode, vscl_filter_mode; 39835fa6e665SDamon Ding uint8_t xgt2 = 0, xgt4 = 0; 39845fa6e665SDamon Ding uint8_t ygt2 = 0, ygt4 = 0; 39853e39a5a1SSandy Huang uint32_t xfac = 0, yfac = 0; 3986ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 39875fa6e665SDamon Ding bool xgt_en = false; 39885fa6e665SDamon Ding bool xavg_en = false; 39893e39a5a1SSandy Huang 39905fa6e665SDamon Ding if (is_vop3(vop2)) { 39915fa6e665SDamon Ding if (src_w >= (4 * dst_w)) { 39925fa6e665SDamon Ding xgt4 = 1; 39935fa6e665SDamon Ding src_w >>= 2; 39945fa6e665SDamon Ding } else if (src_w >= (2 * dst_w)) { 39955fa6e665SDamon Ding xgt2 = 1; 39965fa6e665SDamon Ding src_w >>= 1; 39975fa6e665SDamon Ding } 39985fa6e665SDamon Ding } 39993e39a5a1SSandy Huang 40005fa6e665SDamon Ding if (src_h >= (4 * dst_h)) { 40015fa6e665SDamon Ding ygt4 = 1; 40023e39a5a1SSandy Huang src_h >>= 2; 40035fa6e665SDamon Ding } else if (src_h >= (2 * dst_h)) { 40045fa6e665SDamon Ding ygt2 = 1; 40053e39a5a1SSandy Huang src_h >>= 1; 40065fa6e665SDamon Ding } 40073e39a5a1SSandy Huang 40083e39a5a1SSandy Huang yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 40093e39a5a1SSandy Huang yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 40103e39a5a1SSandy Huang 40113e39a5a1SSandy Huang if (yrgb_hor_scl_mode == SCALE_UP) 40125fa6e665SDamon Ding hscl_filter_mode = win->hsu_filter_mode; 40133e39a5a1SSandy Huang else 40145fa6e665SDamon Ding hscl_filter_mode = win->hsd_filter_mode; 40153e39a5a1SSandy Huang 40163e39a5a1SSandy Huang if (yrgb_ver_scl_mode == SCALE_UP) 40175fa6e665SDamon Ding vscl_filter_mode = win->vsu_filter_mode; 40183e39a5a1SSandy Huang else 40195fa6e665SDamon Ding vscl_filter_mode = win->vsd_filter_mode; 40203e39a5a1SSandy Huang 40213e39a5a1SSandy Huang /* 40223e39a5a1SSandy Huang * RK3568 VOP Esmart/Smart dsp_w should be even pixel 40233e39a5a1SSandy Huang * at scale down mode 40243e39a5a1SSandy Huang */ 40255fa6e665SDamon Ding if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) { 40263e39a5a1SSandy Huang printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 40273e39a5a1SSandy Huang dst_w += 1; 40283e39a5a1SSandy Huang } 40293e39a5a1SSandy Huang 40305fa6e665SDamon Ding if (is_vop3(vop2)) { 40315fa6e665SDamon Ding xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true); 40325fa6e665SDamon Ding yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false); 40335fa6e665SDamon Ding 40345fa6e665SDamon Ding if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG) 40355fa6e665SDamon Ding xavg_en = xgt2 || xgt4; 40365fa6e665SDamon Ding else 40375fa6e665SDamon Ding xgt_en = xgt2 || xgt4; 40385fa6e665SDamon Ding } else { 40393e39a5a1SSandy Huang xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 40403e39a5a1SSandy Huang yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 40415fa6e665SDamon Ding } 4042ecc31b6eSAndy Yan 4043ecc31b6eSAndy Yan if (win->type == CLUSTER_LAYER) { 4044ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 4045ecc31b6eSAndy Yan yfac << 16 | xfac); 4046ecc31b6eSAndy Yan 40475fa6e665SDamon Ding if (is_vop3(vop2)) { 4048ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40495fa6e665SDamon Ding EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false); 4050ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40515fa6e665SDamon Ding EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false); 40525fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40535fa6e665SDamon Ding XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 4054ecc31b6eSAndy Yan 4055ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40565fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT, 40575fa6e665SDamon Ding yrgb_hor_scl_mode, false); 4058ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40595fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT, 40605fa6e665SDamon Ding yrgb_ver_scl_mode, false); 40615fa6e665SDamon Ding } else { 40625fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40635fa6e665SDamon Ding YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT, 40645fa6e665SDamon Ding yrgb_hor_scl_mode, false); 40655fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40665fa6e665SDamon Ding YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT, 40675fa6e665SDamon Ding yrgb_ver_scl_mode, false); 40685fa6e665SDamon Ding } 4069ecc31b6eSAndy Yan 40705fa6e665SDamon Ding if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) { 40715fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40725fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false); 40735fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40745fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false); 40755fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40765fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false); 40775fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40785fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false); 40795fa6e665SDamon Ding } else { 40805fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40815fa6e665SDamon Ding YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false); 40825fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40835fa6e665SDamon Ding YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false); 40845fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40855fa6e665SDamon Ding AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false); 40865fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 40875fa6e665SDamon Ding AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false); 40885fa6e665SDamon Ding } 4089ecc31b6eSAndy Yan } else { 40903e39a5a1SSandy Huang vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 40913e39a5a1SSandy Huang yfac << 16 | xfac); 40923e39a5a1SSandy Huang 40935fa6e665SDamon Ding if (is_vop3(vop2)) { 409434a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 40955fa6e665SDamon Ding EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false); 409634a72bf2SDing Ling Song vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 40975fa6e665SDamon Ding EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false); 40985fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 40995fa6e665SDamon Ding XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 41005fa6e665SDamon Ding } 41015fa6e665SDamon Ding 41025fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 41035fa6e665SDamon Ding YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false); 41045fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 41055fa6e665SDamon Ding YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false); 41063e39a5a1SSandy Huang 41073e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 41083e39a5a1SSandy Huang YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 41093e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 41103e39a5a1SSandy Huang YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 41113e39a5a1SSandy Huang 41123e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 41133e39a5a1SSandy Huang YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 41143e39a5a1SSandy Huang hscl_filter_mode, false); 41153e39a5a1SSandy Huang vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 41163e39a5a1SSandy Huang YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 41173e39a5a1SSandy Huang vscl_filter_mode, false); 41183e39a5a1SSandy Huang } 4119ecc31b6eSAndy Yan } 41203e39a5a1SSandy Huang 4121a33b790fSDamon Ding static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win) 4122a33b790fSDamon Ding { 4123a33b790fSDamon Ding u32 win_offset = win->reg_offset; 4124a33b790fSDamon Ding 4125a33b790fSDamon Ding if (win->type == CLUSTER_LAYER) { 4126a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK, 4127a33b790fSDamon Ding CLUSTER_AXI_ID_SHIFT, win->axi_id, false); 4128a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK, 4129a33b790fSDamon Ding CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 4130a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK, 4131a33b790fSDamon Ding CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 4132a33b790fSDamon Ding } else { 4133a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK, 4134a33b790fSDamon Ding ESMART_AXI_ID_SHIFT, win->axi_id, false); 4135a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK, 4136a33b790fSDamon Ding ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 4137a33b790fSDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK, 4138a33b790fSDamon Ding ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 4139a33b790fSDamon Ding } 4140a33b790fSDamon Ding } 4141a33b790fSDamon Ding 4142840bf541SDamon Ding static bool vop2_win_dither_up(uint32_t format) 4143840bf541SDamon Ding { 4144840bf541SDamon Ding switch (format) { 4145840bf541SDamon Ding case ROCKCHIP_FMT_RGB565: 4146840bf541SDamon Ding return true; 4147840bf541SDamon Ding default: 4148840bf541SDamon Ding return false; 4149840bf541SDamon Ding } 4150840bf541SDamon Ding } 4151840bf541SDamon Ding 41521c9572c7SDamon Ding static bool vop2_is_mirror_win(struct vop2_win_data *win) 41531c9572c7SDamon Ding { 41541c9572c7SDamon Ding return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR); 41551c9572c7SDamon Ding } 41561c9572c7SDamon Ding 41571c9572c7SDamon Ding static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 4158d0408543SAndy Yan { 4159d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 4160d0408543SAndy Yan struct connector_state *conn_state = &state->conn_state; 4161d0408543SAndy Yan struct drm_display_mode *mode = &conn_state->mode; 4162d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 4163ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 4164ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 4165ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 4166ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 4167ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 4168ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 4169d0408543SAndy Yan int xvir = cstate->xvir; 4170d0408543SAndy Yan int y_mirror = 0; 417110ee9f5bSAlgea Cao int csc_mode; 4172ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 4173ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 4174ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 4175ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 4176ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 4177ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4178840bf541SDamon Ding bool dither_up; 4179d0408543SAndy Yan 4180ee01dbb2SDamon Ding if (win->splice_mode_right) { 4181ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 4182ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 4183ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 4184ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 4185ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 4186ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 4187ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 4188ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 4189ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4190ee01dbb2SDamon Ding } 4191ee01dbb2SDamon Ding 4192ecc31b6eSAndy Yan act_info = (src_h - 1) << 16; 4193ecc31b6eSAndy Yan act_info |= (src_w - 1) & 0xffff; 4194ecc31b6eSAndy Yan 4195ecc31b6eSAndy Yan dsp_info = (crtc_h - 1) << 16; 4196ecc31b6eSAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 4197ecc31b6eSAndy Yan 4198ecc31b6eSAndy Yan dsp_stx = crtc_x; 4199ecc31b6eSAndy Yan dsp_sty = crtc_y; 4200ecc31b6eSAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 4201ecc31b6eSAndy Yan 4202ecc31b6eSAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 4203ecc31b6eSAndy Yan y_mirror = 1; 4204ecc31b6eSAndy Yan else 4205ecc31b6eSAndy Yan y_mirror = 0; 4206ecc31b6eSAndy Yan 4207ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 4208ecc31b6eSAndy Yan 4209452afb13SDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 || 4210452afb13SDamon Ding vop2->version == VOP_VERSION_RK3562) 4211a33b790fSDamon Ding vop2_axi_config(vop2, win); 4212a33b790fSDamon Ding 4213ecc31b6eSAndy Yan if (y_mirror) 4214ecc31b6eSAndy Yan printf("WARN: y mirror is unsupported by cluster window\n"); 4215ecc31b6eSAndy Yan 4216a59754e1SDamon Ding /* rk3588 should set half_blocK_en to 1 in line and tile mode */ 4217a59754e1SDamon Ding if (vop2->version == VOP_VERSION_RK3588) 4218a59754e1SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset, 4219a59754e1SDamon Ding EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false); 4220a59754e1SDamon Ding 4221ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 4222ecc31b6eSAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 4223ecc31b6eSAndy Yan false); 4224ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 4225ee01dbb2SDamon Ding vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, 4226ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 4227ecc31b6eSAndy Yan 4228ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 4229ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 4230ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 4231ecc31b6eSAndy Yan 4232ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 4233ecc31b6eSAndy Yan 42345fa6e665SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 4235ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 4236ecc31b6eSAndy Yan CLUSTER_RGB2YUV_EN_SHIFT, 4237ecc31b6eSAndy Yan is_yuv_output(conn_state->bus_format), false); 4238ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 4239ecc31b6eSAndy Yan CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 4240840bf541SDamon Ding 4241840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format); 4242840bf541SDamon Ding vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 4243840bf541SDamon Ding CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false); 4244840bf541SDamon Ding 4245ecc31b6eSAndy Yan vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 4246ecc31b6eSAndy Yan 4247ecc31b6eSAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 42481c9572c7SDamon Ding 42491c9572c7SDamon Ding return 0; 4250d0408543SAndy Yan } 4251d0408543SAndy Yan 42521c9572c7SDamon Ding static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 4253ecc31b6eSAndy Yan { 4254ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4255ecc31b6eSAndy Yan struct connector_state *conn_state = &state->conn_state; 4256ecc31b6eSAndy Yan struct drm_display_mode *mode = &conn_state->mode; 4257ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4258ee01dbb2SDamon Ding int src_w = cstate->src_rect.w; 4259ee01dbb2SDamon Ding int src_h = cstate->src_rect.h; 4260ee01dbb2SDamon Ding int crtc_x = cstate->crtc_rect.x; 4261ee01dbb2SDamon Ding int crtc_y = cstate->crtc_rect.y; 4262ee01dbb2SDamon Ding int crtc_w = cstate->crtc_rect.w; 4263ee01dbb2SDamon Ding int crtc_h = cstate->crtc_rect.h; 4264ecc31b6eSAndy Yan int xvir = cstate->xvir; 4265ecc31b6eSAndy Yan int y_mirror = 0; 4266ecc31b6eSAndy Yan int csc_mode; 4267ecc31b6eSAndy Yan u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 4268ee01dbb2SDamon Ding /* offset of the right window in splice mode */ 4269ee01dbb2SDamon Ding u32 splice_pixel_offset = 0; 4270ee01dbb2SDamon Ding u32 splice_yrgb_offset = 0; 4271ecc31b6eSAndy Yan u32 win_offset = win->reg_offset; 4272ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 42731c9572c7SDamon Ding u32 val; 4274840bf541SDamon Ding bool dither_up; 4275ecc31b6eSAndy Yan 42761c9572c7SDamon Ding if (vop2_is_mirror_win(win)) { 42771c9572c7SDamon Ding struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id); 42781c9572c7SDamon Ding 42791c9572c7SDamon Ding if (!source_win) { 42801c9572c7SDamon Ding printf("invalid source win id %d\n", win->source_win_id); 42811c9572c7SDamon Ding return -ENODEV; 42821c9572c7SDamon Ding } 42831c9572c7SDamon Ding 42841c9572c7SDamon Ding val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset); 42851c9572c7SDamon Ding if (!(val & BIT(WIN_EN_SHIFT))) { 42861c9572c7SDamon Ding printf("WARN: the source win should be enabled before mirror win\n"); 42871c9572c7SDamon Ding return -EAGAIN; 42881c9572c7SDamon Ding } 42891c9572c7SDamon Ding } 42901c9572c7SDamon Ding 4291ee01dbb2SDamon Ding if (win->splice_mode_right) { 4292ee01dbb2SDamon Ding src_w = cstate->right_src_rect.w; 4293ee01dbb2SDamon Ding src_h = cstate->right_src_rect.h; 4294ee01dbb2SDamon Ding crtc_x = cstate->right_crtc_rect.x; 4295ee01dbb2SDamon Ding crtc_y = cstate->right_crtc_rect.y; 4296ee01dbb2SDamon Ding crtc_w = cstate->right_crtc_rect.w; 4297ee01dbb2SDamon Ding crtc_h = cstate->right_crtc_rect.h; 4298ee01dbb2SDamon Ding splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 4299ee01dbb2SDamon Ding splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 4300ee01dbb2SDamon Ding cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4301ee01dbb2SDamon Ding } 4302ee01dbb2SDamon Ding 430374bd8269SSandy Huang /* 430474bd8269SSandy Huang * This is workaround solution for IC design: 430574bd8269SSandy Huang * esmart can't support scale down when actual_w % 16 == 1. 430674bd8269SSandy Huang */ 430774bd8269SSandy Huang if (src_w > crtc_w && (src_w & 0xf) == 1) { 430874bd8269SSandy Huang printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 430974bd8269SSandy Huang src_w -= 1; 431074bd8269SSandy Huang } 431174bd8269SSandy Huang 4312d0408543SAndy Yan act_info = (src_h - 1) << 16; 4313d0408543SAndy Yan act_info |= (src_w - 1) & 0xffff; 4314d0408543SAndy Yan 4315d0408543SAndy Yan dsp_info = (crtc_h - 1) << 16; 4316d0408543SAndy Yan dsp_info |= (crtc_w - 1) & 0xffff; 4317d0408543SAndy Yan 4318d0408543SAndy Yan dsp_stx = crtc_x; 4319d0408543SAndy Yan dsp_sty = crtc_y; 4320d0408543SAndy Yan dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 4321d0408543SAndy Yan 4322d0408543SAndy Yan if (mode->flags & DRM_MODE_FLAG_YMIRROR) 4323d0408543SAndy Yan y_mirror = 1; 4324d0408543SAndy Yan else 4325d0408543SAndy Yan y_mirror = 0; 4326d0408543SAndy Yan 43275fa6e665SDamon Ding if (is_vop3(vop2)) 43285fa6e665SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, ESMART_LB_SELECT_MASK, 43295fa6e665SDamon Ding ESMART_LB_SELECT_SHIFT, win->scale_engine_num, false); 43305fa6e665SDamon Ding 4331ecc31b6eSAndy Yan vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 43323e39a5a1SSandy Huang 4333452afb13SDamon Ding if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3528 || 4334452afb13SDamon Ding vop2->version == VOP_VERSION_RK3562) 4335a33b790fSDamon Ding vop2_axi_config(vop2, win); 4336a33b790fSDamon Ding 4337d0408543SAndy Yan if (y_mirror) 4338d0408543SAndy Yan cstate->dma_addr += (src_h - 1) * xvir * 4; 4339d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 4340d0408543SAndy Yan YMIRROR_EN_SHIFT, y_mirror, false); 4341d0408543SAndy Yan 4342d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 4343d0408543SAndy Yan WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 4344d0408543SAndy Yan false); 4345d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 4346d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 4347ee01dbb2SDamon Ding cstate->dma_addr + splice_yrgb_offset); 4348d0408543SAndy Yan 4349d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 4350d0408543SAndy Yan act_info); 4351d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 4352d0408543SAndy Yan dsp_info); 4353d0408543SAndy Yan vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 4354d0408543SAndy Yan 4355d0408543SAndy Yan vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 4356d0408543SAndy Yan WIN_EN_SHIFT, 1, false); 4357d0408543SAndy Yan 43585fa6e665SDamon Ding csc_mode = vop2_convert_csc_mode(conn_state->color_space, CSC_10BIT_DEPTH); 435910ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 436010ee9f5bSAlgea Cao RGB2YUV_EN_SHIFT, 436110ee9f5bSAlgea Cao is_yuv_output(conn_state->bus_format), false); 436210ee9f5bSAlgea Cao vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 436310ee9f5bSAlgea Cao CSC_MODE_SHIFT, csc_mode, false); 436410ee9f5bSAlgea Cao 4365840bf541SDamon Ding dither_up = vop2_win_dither_up(cstate->format); 4366840bf541SDamon Ding vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 4367840bf541SDamon Ding REGION0_DITHER_UP_EN_SHIFT, dither_up, false); 4368840bf541SDamon Ding 4369d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 43701c9572c7SDamon Ding 43711c9572c7SDamon Ding return 0; 4372ecc31b6eSAndy Yan } 4373ecc31b6eSAndy Yan 4374ee01dbb2SDamon Ding static void vop2_calc_display_rect_for_splice(struct display_state *state) 4375ee01dbb2SDamon Ding { 4376ee01dbb2SDamon Ding struct crtc_state *cstate = &state->crtc_state; 4377ee01dbb2SDamon Ding struct connector_state *conn_state = &state->conn_state; 4378ee01dbb2SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 4379ee01dbb2SDamon Ding struct display_rect *src_rect = &cstate->src_rect; 4380ee01dbb2SDamon Ding struct display_rect *dst_rect = &cstate->crtc_rect; 4381ee01dbb2SDamon Ding struct display_rect left_src, left_dst, right_src, right_dst; 4382ee01dbb2SDamon Ding u16 half_hdisplay = mode->crtc_hdisplay >> 1; 4383ee01dbb2SDamon Ding int left_src_w, left_dst_w, right_dst_w; 4384ee01dbb2SDamon Ding 4385ee01dbb2SDamon Ding left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x; 4386ee01dbb2SDamon Ding if (left_dst_w < 0) 4387ee01dbb2SDamon Ding left_dst_w = 0; 4388ee01dbb2SDamon Ding right_dst_w = dst_rect->w - left_dst_w; 4389ee01dbb2SDamon Ding 4390ee01dbb2SDamon Ding if (!right_dst_w) 4391ee01dbb2SDamon Ding left_src_w = src_rect->w; 4392ee01dbb2SDamon Ding else 43930df0fd39SSandy Huang left_src_w = src_rect->x + src_rect->w - src_rect->w / 2; 4394ee01dbb2SDamon Ding 4395ee01dbb2SDamon Ding left_src.x = src_rect->x; 4396ee01dbb2SDamon Ding left_src.w = left_src_w; 4397ee01dbb2SDamon Ding left_dst.x = dst_rect->x; 4398ee01dbb2SDamon Ding left_dst.w = left_dst_w; 4399ee01dbb2SDamon Ding right_src.x = left_src.x + left_src.w; 4400ee01dbb2SDamon Ding right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w; 4401ee01dbb2SDamon Ding right_dst.x = dst_rect->x + left_dst_w - half_hdisplay; 4402ee01dbb2SDamon Ding right_dst.w = right_dst_w; 4403ee01dbb2SDamon Ding 4404ee01dbb2SDamon Ding left_src.y = src_rect->y; 4405ee01dbb2SDamon Ding left_src.h = src_rect->h; 4406ee01dbb2SDamon Ding left_dst.y = dst_rect->y; 4407ee01dbb2SDamon Ding left_dst.h = dst_rect->h; 4408ee01dbb2SDamon Ding right_src.y = src_rect->y; 4409ee01dbb2SDamon Ding right_src.h = src_rect->h; 4410ee01dbb2SDamon Ding right_dst.y = dst_rect->y; 4411ee01dbb2SDamon Ding right_dst.h = dst_rect->h; 4412ee01dbb2SDamon Ding 4413ee01dbb2SDamon Ding memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect)); 4414ee01dbb2SDamon Ding memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect)); 4415ee01dbb2SDamon Ding memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect)); 4416ee01dbb2SDamon Ding memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect)); 4417ee01dbb2SDamon Ding } 4418ee01dbb2SDamon Ding 4419ecc31b6eSAndy Yan static int rockchip_vop2_set_plane(struct display_state *state) 4420ecc31b6eSAndy Yan { 4421ecc31b6eSAndy Yan struct crtc_state *cstate = &state->crtc_state; 4422ecc31b6eSAndy Yan struct vop2 *vop2 = cstate->private; 4423ecc31b6eSAndy Yan struct vop2_win_data *win_data; 4424ee01dbb2SDamon Ding struct vop2_win_data *splice_win_data; 4425ecc31b6eSAndy Yan u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 4426ecc31b6eSAndy Yan char plane_name[10] = {0}; 44271c9572c7SDamon Ding int ret; 4428ecc31b6eSAndy Yan 4429ee01dbb2SDamon Ding if (cstate->crtc_rect.w > cstate->max_output.width) { 4430ecc31b6eSAndy Yan printf("ERROR: output w[%d] exceeded max width[%d]\n", 4431ee01dbb2SDamon Ding cstate->crtc_rect.w, cstate->max_output.width); 4432ecc31b6eSAndy Yan return -EINVAL; 4433ecc31b6eSAndy Yan } 4434ecc31b6eSAndy Yan 4435ecc31b6eSAndy Yan win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 4436ecc31b6eSAndy Yan if (!win_data) { 4437ecc31b6eSAndy Yan printf("invalid win id %d\n", primary_plane_id); 4438ecc31b6eSAndy Yan return -ENODEV; 4439ecc31b6eSAndy Yan } 4440ecc31b6eSAndy Yan 44415fa6e665SDamon Ding /* ignore some plane register according vop3 esmart lb mode */ 44425fa6e665SDamon Ding if (vop3_ignore_plane(vop2, win_data)) 44435fa6e665SDamon Ding return -EACCES; 44445fa6e665SDamon Ding 4445b6ba80b4SDamon Ding if (vop2->version == VOP_VERSION_RK3588) { 4446b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, win_data->pd_id)) 4447b6ba80b4SDamon Ding printf("open vp%d plane pd fail\n", cstate->crtc_id); 4448b6ba80b4SDamon Ding } 4449b6ba80b4SDamon Ding 4450ee01dbb2SDamon Ding if (cstate->splice_mode) { 4451ee01dbb2SDamon Ding if (win_data->splice_win_id) { 4452ee01dbb2SDamon Ding splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id); 4453ee01dbb2SDamon Ding splice_win_data->splice_mode_right = true; 4454b6ba80b4SDamon Ding 4455b6ba80b4SDamon Ding if (vop2_power_domain_on(vop2, splice_win_data->pd_id)) 4456b6ba80b4SDamon Ding printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id); 4457b6ba80b4SDamon Ding 4458ee01dbb2SDamon Ding vop2_calc_display_rect_for_splice(state); 4459ee01dbb2SDamon Ding if (win_data->type == CLUSTER_LAYER) 4460ee01dbb2SDamon Ding vop2_set_cluster_win(state, splice_win_data); 4461ee01dbb2SDamon Ding else 4462ee01dbb2SDamon Ding vop2_set_smart_win(state, splice_win_data); 4463ee01dbb2SDamon Ding } else { 4464ee01dbb2SDamon Ding printf("ERROR: splice mode is unsupported by plane %s\n", 4465ee01dbb2SDamon Ding get_plane_name(primary_plane_id, plane_name)); 4466ee01dbb2SDamon Ding return -EINVAL; 4467ee01dbb2SDamon Ding } 4468ee01dbb2SDamon Ding } 4469ee01dbb2SDamon Ding 4470ecc31b6eSAndy Yan if (win_data->type == CLUSTER_LAYER) 44711c9572c7SDamon Ding ret = vop2_set_cluster_win(state, win_data); 4472ecc31b6eSAndy Yan else 44731c9572c7SDamon Ding ret = vop2_set_smart_win(state, win_data); 44741c9572c7SDamon Ding if (ret) 44751c9572c7SDamon Ding return ret; 44768895aec1SSandy Huang 44778895aec1SSandy Huang printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 44788895aec1SSandy Huang cstate->crtc_id, get_plane_name(primary_plane_id, plane_name), 4479ee01dbb2SDamon Ding cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h, 4480ee01dbb2SDamon Ding cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format, 44818895aec1SSandy Huang cstate->dma_addr); 44828895aec1SSandy Huang 4483d0408543SAndy Yan return 0; 4484d0408543SAndy Yan } 4485d0408543SAndy Yan 4486d0408543SAndy Yan static int rockchip_vop2_prepare(struct display_state *state) 4487d0408543SAndy Yan { 4488d0408543SAndy Yan return 0; 4489d0408543SAndy Yan } 4490d0408543SAndy Yan 449112ee5af0SDamon Ding static void vop2_dsc_cfg_done(struct display_state *state) 449212ee5af0SDamon Ding { 449312ee5af0SDamon Ding struct connector_state *conn_state = &state->conn_state; 449412ee5af0SDamon Ding struct crtc_state *cstate = &state->crtc_state; 449512ee5af0SDamon Ding struct vop2 *vop2 = cstate->private; 449612ee5af0SDamon Ding u8 dsc_id = cstate->dsc_id; 449712ee5af0SDamon Ding u32 ctrl_regs_offset = (dsc_id * 0x30); 449812ee5af0SDamon Ding 449912ee5af0SDamon Ding if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 450012ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK, 450112ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 450212ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK, 450312ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 450412ee5af0SDamon Ding } else { 450512ee5af0SDamon Ding vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK, 450612ee5af0SDamon Ding DSC_CFG_DONE_SHIFT, 1, false); 450712ee5af0SDamon Ding } 450812ee5af0SDamon Ding } 450912ee5af0SDamon Ding 4510d0408543SAndy Yan static int rockchip_vop2_enable(struct display_state *state) 4511d0408543SAndy Yan { 4512d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 4513d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 451452ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 4515ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4516d0408543SAndy Yan 4517d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4518d0408543SAndy Yan STANDBY_EN_SHIFT, 0, false); 4519ee01dbb2SDamon Ding 4520ee01dbb2SDamon Ding if (cstate->splice_mode) 4521ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4522ee01dbb2SDamon Ding 4523d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4524d0408543SAndy Yan 452512ee5af0SDamon Ding if (cstate->dsc_enable) 452612ee5af0SDamon Ding vop2_dsc_cfg_done(state); 452712ee5af0SDamon Ding 45280675a2a4SDamon Ding if (cstate->mcu_timing.mcu_pix_total) 45290675a2a4SDamon Ding vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 45300675a2a4SDamon Ding MCU_HOLD_MODE_SHIFT, 0, false); 45310675a2a4SDamon Ding 4532d0408543SAndy Yan return 0; 4533d0408543SAndy Yan } 4534d0408543SAndy Yan 4535d0408543SAndy Yan static int rockchip_vop2_disable(struct display_state *state) 4536d0408543SAndy Yan { 4537d0408543SAndy Yan struct crtc_state *cstate = &state->crtc_state; 4538d0408543SAndy Yan struct vop2 *vop2 = cstate->private; 453952ee18acSSandy Huang u32 vp_offset = (cstate->crtc_id * 0x100); 4540ecc31b6eSAndy Yan u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4541d0408543SAndy Yan 4542d0408543SAndy Yan vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4543d0408543SAndy Yan STANDBY_EN_SHIFT, 1, false); 4544ee01dbb2SDamon Ding 4545ee01dbb2SDamon Ding if (cstate->splice_mode) 4546ee01dbb2SDamon Ding cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 4547ee01dbb2SDamon Ding 4548d0408543SAndy Yan vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 4549d0408543SAndy Yan 4550d0408543SAndy Yan return 0; 4551d0408543SAndy Yan } 4552d0408543SAndy Yan 4553ee008497SSandy Huang static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 4554ee008497SSandy Huang { 4555ee008497SSandy Huang struct crtc_state *cstate = &state->crtc_state; 4556ee008497SSandy Huang struct vop2 *vop2 = cstate->private; 4557ee008497SSandy Huang int i = 0; 4558ee008497SSandy Huang int correct_cursor_plane = -1; 4559ee008497SSandy Huang int plane_type = -1; 4560ee008497SSandy Huang 4561ee008497SSandy Huang if (cursor_plane < 0) 4562ee008497SSandy Huang return -1; 4563ee008497SSandy Huang 4564ee008497SSandy Huang if (plane_mask & (1 << cursor_plane)) 4565ee008497SSandy Huang return cursor_plane; 4566ee008497SSandy Huang 4567ee008497SSandy Huang /* Get current cursor plane type */ 4568ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 4569ee008497SSandy Huang if (vop2->data->plane_table[i].plane_id == cursor_plane) { 4570ee008497SSandy Huang plane_type = vop2->data->plane_table[i].plane_type; 4571ee008497SSandy Huang break; 4572ee008497SSandy Huang } 4573ee008497SSandy Huang } 4574ee008497SSandy Huang 4575ee008497SSandy Huang /* Get the other same plane type plane id */ 4576ee008497SSandy Huang for (i = 0; i < vop2->data->nr_layers; i++) { 4577ee008497SSandy Huang if (vop2->data->plane_table[i].plane_type == plane_type && 4578ee008497SSandy Huang vop2->data->plane_table[i].plane_id != cursor_plane) { 4579ee008497SSandy Huang correct_cursor_plane = vop2->data->plane_table[i].plane_id; 4580ee008497SSandy Huang break; 4581ee008497SSandy Huang } 4582ee008497SSandy Huang } 4583ee008497SSandy Huang 4584ee008497SSandy Huang /* To check whether the new correct_cursor_plane is attach to current vp */ 4585ee008497SSandy Huang if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 4586ee008497SSandy Huang printf("error: faild to find correct plane as cursor plane\n"); 4587ee008497SSandy Huang return -1; 4588ee008497SSandy Huang } 4589ee008497SSandy Huang 4590ee008497SSandy Huang printf("vp%d adjust cursor plane from %d to %d\n", 4591ee008497SSandy Huang cstate->crtc_id, cursor_plane, correct_cursor_plane); 4592ee008497SSandy Huang 4593ee008497SSandy Huang return correct_cursor_plane; 4594ee008497SSandy Huang } 4595ee008497SSandy Huang 4596b0989546SSandy Huang static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 4597b0989546SSandy Huang { 4598b0989546SSandy Huang struct crtc_state *cstate = &state->crtc_state; 4599b0989546SSandy Huang struct vop2 *vop2 = cstate->private; 4600b0989546SSandy Huang ofnode vp_node; 4601b0989546SSandy Huang struct device_node *port_parent_node = cstate->ports_node; 4602b0989546SSandy Huang static bool vop_fix_dts; 4603b0989546SSandy Huang const char *path; 4604b0989546SSandy Huang u32 plane_mask = 0; 4605b0989546SSandy Huang int vp_id = 0; 4606ee008497SSandy Huang int cursor_plane_id = -1; 4607b0989546SSandy Huang 46085fa6e665SDamon Ding if (vop_fix_dts || vop2->version == VOP_VERSION_RK3528) 4609b0989546SSandy Huang return 0; 4610b0989546SSandy Huang 4611b0989546SSandy Huang ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 4612b0989546SSandy Huang path = vp_node.np->full_name; 4613b0989546SSandy Huang plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 4614b0989546SSandy Huang 46158b1fe597SSandy Huang if (cstate->crtc->assign_plane) 46168b1fe597SSandy Huang continue; 4617ee008497SSandy Huang cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 4618ee008497SSandy Huang cstate->crtc->vps[vp_id].cursor_plane); 4619ee008497SSandy Huang printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 4620b0989546SSandy Huang vp_id, plane_mask, 4621ee008497SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 4622ee008497SSandy Huang cursor_plane_id); 4623b0989546SSandy Huang 4624b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 4625b0989546SSandy Huang plane_mask, 1); 4626b0989546SSandy Huang do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 4627b0989546SSandy Huang vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 4628ee008497SSandy Huang if (cursor_plane_id >= 0) 4629ee008497SSandy Huang do_fixup_by_path_u32(blob, path, "cursor-win-id", 4630ee008497SSandy Huang cursor_plane_id, 1); 4631b0989546SSandy Huang vp_id++; 4632b0989546SSandy Huang } 4633b0989546SSandy Huang 4634b0989546SSandy Huang vop_fix_dts = true; 4635b0989546SSandy Huang 4636b0989546SSandy Huang return 0; 4637b0989546SSandy Huang } 4638b0989546SSandy Huang 4639820a5c17SDamon Ding static int rockchip_vop2_check(struct display_state *state) 4640820a5c17SDamon Ding { 4641820a5c17SDamon Ding struct crtc_state *cstate = &state->crtc_state; 4642820a5c17SDamon Ding struct rockchip_crtc *crtc = cstate->crtc; 4643820a5c17SDamon Ding 4644820a5c17SDamon Ding if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) { 4645820a5c17SDamon Ding printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id); 4646820a5c17SDamon Ding return -ENOTSUPP; 4647820a5c17SDamon Ding } 4648820a5c17SDamon Ding 4649820a5c17SDamon Ding if (cstate->splice_mode) { 4650820a5c17SDamon Ding crtc->splice_mode = true; 4651820a5c17SDamon Ding crtc->splice_crtc_id = cstate->splice_crtc_id; 4652820a5c17SDamon Ding } 4653820a5c17SDamon Ding 4654820a5c17SDamon Ding return 0; 4655820a5c17SDamon Ding } 4656820a5c17SDamon Ding 465722007755SDamon Ding static int rockchip_vop2_mode_valid(struct display_state *state) 465822007755SDamon Ding { 465922007755SDamon Ding struct connector_state *conn_state = &state->conn_state; 466022007755SDamon Ding struct crtc_state *cstate = &state->crtc_state; 466122007755SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 466222007755SDamon Ding struct videomode vm; 466322007755SDamon Ding 466422007755SDamon Ding drm_display_mode_to_videomode(mode, &vm); 466522007755SDamon Ding 466622007755SDamon Ding if (vm.hactive < 32 || vm.vactive < 32 || 466722007755SDamon Ding (vm.hfront_porch * vm.hsync_len * vm.hback_porch * 466822007755SDamon Ding vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) { 466922007755SDamon Ding printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id); 467022007755SDamon Ding return -EINVAL; 467122007755SDamon Ding } 467222007755SDamon Ding 467322007755SDamon Ding return 0; 467422007755SDamon Ding } 467522007755SDamon Ding 4676b02eb70bSDamon Ding static int rockchip_vop2_mode_fixup(struct display_state *state) 4677b02eb70bSDamon Ding { 4678b02eb70bSDamon Ding struct connector_state *conn_state = &state->conn_state; 4679b02eb70bSDamon Ding struct drm_display_mode *mode = &conn_state->mode; 4680b02eb70bSDamon Ding struct crtc_state *cstate = &state->crtc_state; 4681b02eb70bSDamon Ding struct vop2 *vop2 = cstate->private; 4682b02eb70bSDamon Ding 46831b5811e7SDamon Ding drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE); 4684b02eb70bSDamon Ding 4685b02eb70bSDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656) 4686b02eb70bSDamon Ding mode->crtc_clock *= 2; 4687b02eb70bSDamon Ding 4688b02eb70bSDamon Ding /* 4689b02eb70bSDamon Ding * For RK3528, the path of CVBS output is like: 4690b02eb70bSDamon Ding * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC 4691b02eb70bSDamon Ding * The vop2 dclk should be four times crtc_clock for CVBS sampling 4692b02eb70bSDamon Ding * clock needs. 4693b02eb70bSDamon Ding */ 4694b02eb70bSDamon Ding if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656) 4695b02eb70bSDamon Ding mode->crtc_clock *= 4; 4696b02eb70bSDamon Ding 4697*4d64cedbSDamon Ding mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format); 4698*4d64cedbSDamon Ding if (cstate->mcu_timing.mcu_pix_total) 4699*4d64cedbSDamon Ding mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1; 47000675a2a4SDamon Ding 4701b02eb70bSDamon Ding if (conn_state->secondary) { 4702b02eb70bSDamon Ding mode->crtc_clock *= 2; 4703b02eb70bSDamon Ding mode->crtc_hdisplay *= 2; 4704b02eb70bSDamon Ding mode->crtc_hsync_start *= 2; 4705b02eb70bSDamon Ding mode->crtc_hsync_end *= 2; 4706b02eb70bSDamon Ding mode->crtc_htotal *= 2; 4707b02eb70bSDamon Ding } 4708b02eb70bSDamon Ding 4709b02eb70bSDamon Ding return 0; 4710b02eb70bSDamon Ding } 4711b02eb70bSDamon Ding 47124c765862SDamon Ding #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) 47134c765862SDamon Ding 47144c765862SDamon Ding static int rockchip_vop2_plane_check(struct display_state *state) 47154c765862SDamon Ding { 47164c765862SDamon Ding struct crtc_state *cstate = &state->crtc_state; 47174c765862SDamon Ding struct vop2 *vop2 = cstate->private; 47184c765862SDamon Ding struct display_rect *src = &cstate->src_rect; 47194c765862SDamon Ding struct display_rect *dst = &cstate->crtc_rect; 47204c765862SDamon Ding struct vop2_win_data *win_data; 47214c765862SDamon Ding int min_scale, max_scale; 47224c765862SDamon Ding int hscale, vscale; 47234c765862SDamon Ding u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 47244c765862SDamon Ding 47254c765862SDamon Ding win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 47264c765862SDamon Ding if (!win_data) { 47274c765862SDamon Ding printf("ERROR: invalid win id %d\n", primary_plane_id); 47284c765862SDamon Ding return -ENODEV; 47294c765862SDamon Ding } 47304c765862SDamon Ding 47314c765862SDamon Ding min_scale = FRAC_16_16(1, win_data->max_downscale_factor); 47324c765862SDamon Ding max_scale = FRAC_16_16(win_data->max_upscale_factor, 1); 47334c765862SDamon Ding 47344c765862SDamon Ding hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale); 47354c765862SDamon Ding vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale); 47364c765862SDamon Ding if (hscale < 0 || vscale < 0) { 47374c765862SDamon Ding printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name); 47384c765862SDamon Ding return -ERANGE; 47394c765862SDamon Ding } 47404c765862SDamon Ding 47414c765862SDamon Ding return 0; 47424c765862SDamon Ding } 4743337d1c13SDamon Ding 47448e7ef808SDamon Ding static int rockchip_vop2_apply_soft_te(struct display_state *state) 47458e7ef808SDamon Ding { 4746d8e7f4a5SSandy Huang __maybe_unused struct connector_state *conn_state = &state->conn_state; 47478e7ef808SDamon Ding struct crtc_state *cstate = &state->crtc_state; 47488e7ef808SDamon Ding struct vop2 *vop2 = cstate->private; 47498e7ef808SDamon Ding u32 vp_offset = (cstate->crtc_id * 0x100); 47508e7ef808SDamon Ding int val = 0; 47518e7ef808SDamon Ding int ret = 0; 47528e7ef808SDamon Ding 47538e7ef808SDamon Ding ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val, 47548e7ef808SDamon Ding (val >> EDPI_WMS_FS) & 0x1, 50 * 1000); 47558e7ef808SDamon Ding if (!ret) { 4756d8e7f4a5SSandy Huang #ifndef CONFIG_SPL_BUILD 47578e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 47588e7ef808SDamon Ding !val, 50 * 1000); 47598e7ef808SDamon Ding if (!ret) { 47608e7ef808SDamon Ding ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 47618e7ef808SDamon Ding val, 50 * 1000); 47628e7ef808SDamon Ding if (!ret) { 47638e7ef808SDamon Ding vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 47648e7ef808SDamon Ding EN_MASK, EDPI_WMS_FS, 1, false); 47658e7ef808SDamon Ding } else { 47668e7ef808SDamon Ding printf("ERROR: vp%d wait for active TE signal timeout\n", 47678e7ef808SDamon Ding cstate->crtc_id); 47688e7ef808SDamon Ding return ret; 47698e7ef808SDamon Ding } 47708e7ef808SDamon Ding } else { 47718e7ef808SDamon Ding printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id); 47728e7ef808SDamon Ding return ret; 47738e7ef808SDamon Ding } 4774d8e7f4a5SSandy Huang #endif 47758e7ef808SDamon Ding } else { 47768e7ef808SDamon Ding printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id); 47778e7ef808SDamon Ding return ret; 47788e7ef808SDamon Ding } 47798e7ef808SDamon Ding 47808e7ef808SDamon Ding return 0; 47818e7ef808SDamon Ding } 47828e7ef808SDamon Ding 478372388c26SDamon Ding static int rockchip_vop2_regs_dump(struct display_state *state) 478472388c26SDamon Ding { 478572388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 478672388c26SDamon Ding struct vop2 *vop2 = cstate->private; 478772388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 478872388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 478972388c26SDamon Ding u32 n, i, j; 479072388c26SDamon Ding u32 base; 479172388c26SDamon Ding 479272388c26SDamon Ding if (!cstate->crtc->active) 479372388c26SDamon Ding return -EINVAL; 479472388c26SDamon Ding 479572388c26SDamon Ding n = vop2_data->dump_regs_size; 479672388c26SDamon Ding for (i = 0; i < n; i++) { 479772388c26SDamon Ding base = regs[i].offset; 479872388c26SDamon Ding printf("\n%s:\n", regs[i].name); 479972388c26SDamon Ding for (j = 0; j < 68;) { 480072388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 480172388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 480272388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 480372388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 480472388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 480572388c26SDamon Ding j += 4; 480672388c26SDamon Ding } 480772388c26SDamon Ding } 480872388c26SDamon Ding 480972388c26SDamon Ding return 0; 481072388c26SDamon Ding } 481172388c26SDamon Ding 481272388c26SDamon Ding static int rockchip_vop2_active_regs_dump(struct display_state *state) 481372388c26SDamon Ding { 481472388c26SDamon Ding struct crtc_state *cstate = &state->crtc_state; 481572388c26SDamon Ding struct vop2 *vop2 = cstate->private; 481672388c26SDamon Ding const struct vop2_data *vop2_data = vop2->data; 481772388c26SDamon Ding const struct vop2_dump_regs *regs = vop2_data->dump_regs; 481872388c26SDamon Ding u32 n, i, j; 481972388c26SDamon Ding u32 base; 482072388c26SDamon Ding bool enable_state; 482172388c26SDamon Ding 482272388c26SDamon Ding if (!cstate->crtc->active) 482372388c26SDamon Ding return -EINVAL; 482472388c26SDamon Ding 482572388c26SDamon Ding n = vop2_data->dump_regs_size; 482672388c26SDamon Ding for (i = 0; i < n; i++) { 482772388c26SDamon Ding if (regs[i].state_mask) { 482872388c26SDamon Ding enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) & 482972388c26SDamon Ding regs[i].state_mask; 483072388c26SDamon Ding if (enable_state != regs[i].enable_state) 483172388c26SDamon Ding continue; 483272388c26SDamon Ding } 483372388c26SDamon Ding 483472388c26SDamon Ding base = regs[i].offset; 483572388c26SDamon Ding printf("\n%s:\n", regs[i].name); 483672388c26SDamon Ding for (j = 0; j < 68;) { 483772388c26SDamon Ding printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 483872388c26SDamon Ding vop2_readl(vop2, base + (4 * j)), 483972388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 1))), 484072388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 2))), 484172388c26SDamon Ding vop2_readl(vop2, base + (4 * (j + 3)))); 484272388c26SDamon Ding j += 4; 484372388c26SDamon Ding } 484472388c26SDamon Ding } 484572388c26SDamon Ding 484672388c26SDamon Ding return 0; 484772388c26SDamon Ding } 484872388c26SDamon Ding 484972388c26SDamon Ding static struct vop2_dump_regs rk3528_dump_regs[] = { 485072388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 485172388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 485272388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 485372388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 485472388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 485572388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 485672388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 485772388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 485872388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 485972388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 486072388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 486172388c26SDamon Ding { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 486272388c26SDamon Ding { RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1}, 486372388c26SDamon Ding }; 486472388c26SDamon Ding 48655fa6e665SDamon Ding static u8 rk3528_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 48665fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, 48675fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART1, 48685fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, 48695fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART3, 48705fa6e665SDamon Ding }; 48715fa6e665SDamon Ding 48725fa6e665SDamon Ding static struct vop2_plane_table rk3528_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 48735fa6e665SDamon Ding {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 48745fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 48755fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 48765fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 48775fa6e665SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 48785fa6e665SDamon Ding }; 48795fa6e665SDamon Ding 48805fa6e665SDamon Ding static struct vop2_vp_plane_mask rk3528_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 48815fa6e665SDamon Ding { /* one display policy for hdmi */ 48825fa6e665SDamon Ding {/* main display */ 4883ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 48845fa6e665SDamon Ding .attached_layers_nr = 4, 48855fa6e665SDamon Ding .attached_layers = { 48865fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 48875fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART2 48885fa6e665SDamon Ding }, 48895fa6e665SDamon Ding }, 48905fa6e665SDamon Ding {/* second display */}, 48915fa6e665SDamon Ding {/* third display */}, 48925fa6e665SDamon Ding {/* fourth display */}, 48935fa6e665SDamon Ding }, 48945fa6e665SDamon Ding 48955fa6e665SDamon Ding { /* two display policy */ 48965fa6e665SDamon Ding {/* main display */ 4897ebbd144cSAlgea Cao .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 48985fa6e665SDamon Ding .attached_layers_nr = 3, 48995fa6e665SDamon Ding .attached_layers = { 49005fa6e665SDamon Ding ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 49015fa6e665SDamon Ding }, 49025fa6e665SDamon Ding }, 49035fa6e665SDamon Ding 49045fa6e665SDamon Ding {/* second display */ 49055fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 49065fa6e665SDamon Ding .attached_layers_nr = 2, 49075fa6e665SDamon Ding .attached_layers = { 49085fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 49095fa6e665SDamon Ding }, 49105fa6e665SDamon Ding }, 49115fa6e665SDamon Ding {/* third display */}, 49125fa6e665SDamon Ding {/* fourth display */}, 49135fa6e665SDamon Ding }, 49145fa6e665SDamon Ding 49155fa6e665SDamon Ding { /* one display policy for cvbs */ 49165fa6e665SDamon Ding {/* main display */ 49175fa6e665SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 49185fa6e665SDamon Ding .attached_layers_nr = 2, 49195fa6e665SDamon Ding .attached_layers = { 49205fa6e665SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 49215fa6e665SDamon Ding }, 49225fa6e665SDamon Ding }, 49235fa6e665SDamon Ding {/* second display */}, 49245fa6e665SDamon Ding {/* third display */}, 49255fa6e665SDamon Ding {/* fourth display */}, 49265fa6e665SDamon Ding }, 49275fa6e665SDamon Ding 49285fa6e665SDamon Ding {/* reserved */}, 49295fa6e665SDamon Ding }; 49305fa6e665SDamon Ding 49315fa6e665SDamon Ding static struct vop2_win_data rk3528_win_data[5] = { 49325fa6e665SDamon Ding { 49335fa6e665SDamon Ding .name = "Esmart0", 49345fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 49355fa6e665SDamon Ding .type = ESMART_LAYER, 49365fa6e665SDamon Ding .win_sel_port_offset = 8, 49375fa6e665SDamon Ding .layer_sel_win_id = { 1, 0xff, 0xff, 0xff }, 49385fa6e665SDamon Ding .reg_offset = 0, 49395fa6e665SDamon Ding .axi_id = 0, 49405fa6e665SDamon Ding .axi_yrgb_id = 0x06, 49415fa6e665SDamon Ding .axi_uv_id = 0x07, 49425fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49435fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49445fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49455fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49465fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 49475fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 49485fa6e665SDamon Ding .max_upscale_factor = 8, 49495fa6e665SDamon Ding .max_downscale_factor = 8, 49505fa6e665SDamon Ding }, 49515fa6e665SDamon Ding 49525fa6e665SDamon Ding { 49535fa6e665SDamon Ding .name = "Esmart1", 49545fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 49555fa6e665SDamon Ding .type = ESMART_LAYER, 49565fa6e665SDamon Ding .win_sel_port_offset = 10, 49575fa6e665SDamon Ding .layer_sel_win_id = { 2, 0xff, 0xff, 0xff }, 49585fa6e665SDamon Ding .reg_offset = 0x200, 49595fa6e665SDamon Ding .axi_id = 0, 49605fa6e665SDamon Ding .axi_yrgb_id = 0x08, 49615fa6e665SDamon Ding .axi_uv_id = 0x09, 49625fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49635fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49645fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49655fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49665fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 49675fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 49685fa6e665SDamon Ding .max_upscale_factor = 8, 49695fa6e665SDamon Ding .max_downscale_factor = 8, 49705fa6e665SDamon Ding }, 49715fa6e665SDamon Ding 49725fa6e665SDamon Ding { 49735fa6e665SDamon Ding .name = "Esmart2", 49745fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 49755fa6e665SDamon Ding .type = ESMART_LAYER, 49765fa6e665SDamon Ding .win_sel_port_offset = 12, 49775fa6e665SDamon Ding .layer_sel_win_id = { 3, 0, 0xff, 0xff }, 49785fa6e665SDamon Ding .reg_offset = 0x400, 49795fa6e665SDamon Ding .axi_id = 0, 49805fa6e665SDamon Ding .axi_yrgb_id = 0x0a, 49815fa6e665SDamon Ding .axi_uv_id = 0x0b, 49825fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 49835fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49845fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 49855fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 49865fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 49875fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 49885fa6e665SDamon Ding .max_upscale_factor = 8, 49895fa6e665SDamon Ding .max_downscale_factor = 8, 49905fa6e665SDamon Ding }, 49915fa6e665SDamon Ding 49925fa6e665SDamon Ding { 49935fa6e665SDamon Ding .name = "Esmart3", 49945fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 49955fa6e665SDamon Ding .type = ESMART_LAYER, 49965fa6e665SDamon Ding .win_sel_port_offset = 14, 49975fa6e665SDamon Ding .layer_sel_win_id = { 0xff, 1, 0xff, 0xff }, 49985fa6e665SDamon Ding .reg_offset = 0x600, 49995fa6e665SDamon Ding .axi_id = 0, 50005fa6e665SDamon Ding .axi_yrgb_id = 0x0c, 50015fa6e665SDamon Ding .axi_uv_id = 0x0d, 50025fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 50035fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 50045fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 50055fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 50065fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 50075fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 50085fa6e665SDamon Ding .max_upscale_factor = 8, 50095fa6e665SDamon Ding .max_downscale_factor = 8, 50105fa6e665SDamon Ding }, 50115fa6e665SDamon Ding 50125fa6e665SDamon Ding { 50135fa6e665SDamon Ding .name = "Cluster0", 50145fa6e665SDamon Ding .phys_id = ROCKCHIP_VOP2_CLUSTER0, 50155fa6e665SDamon Ding .type = CLUSTER_LAYER, 50165fa6e665SDamon Ding .win_sel_port_offset = 0, 50175fa6e665SDamon Ding .layer_sel_win_id = { 0, 0xff, 0xff, 0xff }, 50185fa6e665SDamon Ding .reg_offset = 0, 50195fa6e665SDamon Ding .axi_id = 0, 50205fa6e665SDamon Ding .axi_yrgb_id = 0x02, 50215fa6e665SDamon Ding .axi_uv_id = 0x03, 50225fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 50235fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 50245fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 50255fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 50265fa6e665SDamon Ding .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 50275fa6e665SDamon Ding .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 50285fa6e665SDamon Ding .max_upscale_factor = 8, 50295fa6e665SDamon Ding .max_downscale_factor = 8, 50305fa6e665SDamon Ding }, 50315fa6e665SDamon Ding }; 50325fa6e665SDamon Ding 50335fa6e665SDamon Ding static struct vop2_vp_data rk3528_vp_data[2] = { 50345fa6e665SDamon Ding { 50356027c871SZhang Yubing .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM | 50366027c871SZhang Yubing VOP_FEATURE_POST_CSC, 50375fa6e665SDamon Ding .max_output = {4096, 4096}, 5038b05105abSDamon Ding .layer_mix_dly = 6, 5039b05105abSDamon Ding .hdr_mix_dly = 2, 5040b05105abSDamon Ding .win_dly = 8, 50415fa6e665SDamon Ding }, 50425fa6e665SDamon Ding { 50435fa6e665SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 50445fa6e665SDamon Ding .max_output = {1920, 1080}, 5045b05105abSDamon Ding .layer_mix_dly = 2, 5046b05105abSDamon Ding .hdr_mix_dly = 0, 5047b05105abSDamon Ding .win_dly = 8, 50485fa6e665SDamon Ding }, 50495fa6e665SDamon Ding }; 50505fa6e665SDamon Ding 50515fa6e665SDamon Ding const struct vop2_data rk3528_vop = { 50525fa6e665SDamon Ding .version = VOP_VERSION_RK3528, 50535fa6e665SDamon Ding .nr_vps = 2, 50545fa6e665SDamon Ding .vp_data = rk3528_vp_data, 50555fa6e665SDamon Ding .win_data = rk3528_win_data, 50565fa6e665SDamon Ding .plane_mask = rk3528_vp_plane_mask[0], 50575fa6e665SDamon Ding .plane_table = rk3528_plane_table, 50585fa6e665SDamon Ding .vp_primary_plane_order = rk3528_vp_primary_plane_order, 50595fa6e665SDamon Ding .nr_layers = 5, 50605fa6e665SDamon Ding .nr_mixers = 3, 50615fa6e665SDamon Ding .nr_gammas = 2, 50625fa6e665SDamon Ding .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE, 506372388c26SDamon Ding .dump_regs = rk3528_dump_regs, 506472388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3528_dump_regs), 506572388c26SDamon Ding }; 506672388c26SDamon Ding 506772388c26SDamon Ding static struct vop2_dump_regs rk3562_dump_regs[] = { 506872388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 506972388c26SDamon Ding { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 507072388c26SDamon Ding { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 507172388c26SDamon Ding { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 507272388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 507372388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 507472388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 507572388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 507672388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 507772388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 50785fa6e665SDamon Ding }; 50795fa6e665SDamon Ding 5080452afb13SDamon Ding static u8 rk3562_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 5081452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, 5082452afb13SDamon Ding ROCKCHIP_VOP2_ESMART1, 5083452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, 5084452afb13SDamon Ding ROCKCHIP_VOP2_ESMART3, 5085452afb13SDamon Ding }; 5086452afb13SDamon Ding 5087452afb13SDamon Ding static struct vop2_plane_table rk3562_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 5088452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 5089452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 5090452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 5091452afb13SDamon Ding {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 5092452afb13SDamon Ding }; 5093452afb13SDamon Ding 5094452afb13SDamon Ding static struct vop2_vp_plane_mask rk3562_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 5095452afb13SDamon Ding { /* one display policy for hdmi */ 5096452afb13SDamon Ding {/* main display */ 5097452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5098452afb13SDamon Ding .attached_layers_nr = 4, 5099452afb13SDamon Ding .attached_layers = { 5100452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1, 5101452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 5102452afb13SDamon Ding }, 5103452afb13SDamon Ding }, 5104452afb13SDamon Ding {/* second display */}, 5105452afb13SDamon Ding {/* third display */}, 5106452afb13SDamon Ding {/* fourth display */}, 5107452afb13SDamon Ding }, 5108452afb13SDamon Ding 5109452afb13SDamon Ding { /* two display policy */ 5110452afb13SDamon Ding {/* main display */ 5111452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5112452afb13SDamon Ding .attached_layers_nr = 2, 5113452afb13SDamon Ding .attached_layers = { 5114452afb13SDamon Ding ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART1 5115452afb13SDamon Ding }, 5116452afb13SDamon Ding }, 5117452afb13SDamon Ding 5118452afb13SDamon Ding {/* second display */ 5119452afb13SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5120452afb13SDamon Ding .attached_layers_nr = 2, 5121452afb13SDamon Ding .attached_layers = { 5122452afb13SDamon Ding ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 5123452afb13SDamon Ding }, 5124452afb13SDamon Ding }, 5125452afb13SDamon Ding {/* third display */}, 5126452afb13SDamon Ding {/* fourth display */}, 5127452afb13SDamon Ding }, 5128452afb13SDamon Ding 5129452afb13SDamon Ding {/* reserved */}, 5130452afb13SDamon Ding }; 5131452afb13SDamon Ding 5132452afb13SDamon Ding static struct vop2_win_data rk3562_win_data[4] = { 5133452afb13SDamon Ding { 5134452afb13SDamon Ding .name = "Esmart0", 5135452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART0, 5136452afb13SDamon Ding .type = ESMART_LAYER, 5137452afb13SDamon Ding .win_sel_port_offset = 8, 5138452afb13SDamon Ding .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 5139452afb13SDamon Ding .reg_offset = 0, 5140452afb13SDamon Ding .axi_id = 0, 5141452afb13SDamon Ding .axi_yrgb_id = 0x02, 5142452afb13SDamon Ding .axi_uv_id = 0x03, 5143452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 5144452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5145452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 5146452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5147452afb13SDamon Ding .max_upscale_factor = 8, 5148452afb13SDamon Ding .max_downscale_factor = 8, 5149452afb13SDamon Ding }, 5150452afb13SDamon Ding 5151452afb13SDamon Ding { 5152452afb13SDamon Ding .name = "Esmart1", 5153452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART1, 5154452afb13SDamon Ding .type = ESMART_LAYER, 5155452afb13SDamon Ding .win_sel_port_offset = 10, 5156452afb13SDamon Ding .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 5157452afb13SDamon Ding .reg_offset = 0x200, 5158452afb13SDamon Ding .axi_id = 0, 5159452afb13SDamon Ding .axi_yrgb_id = 0x04, 5160452afb13SDamon Ding .axi_uv_id = 0x05, 5161452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 5162452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5163452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 5164452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5165452afb13SDamon Ding .max_upscale_factor = 8, 5166452afb13SDamon Ding .max_downscale_factor = 8, 5167452afb13SDamon Ding }, 5168452afb13SDamon Ding 5169452afb13SDamon Ding { 5170452afb13SDamon Ding .name = "Esmart2", 5171452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART2, 5172452afb13SDamon Ding .type = ESMART_LAYER, 5173452afb13SDamon Ding .win_sel_port_offset = 12, 5174452afb13SDamon Ding .layer_sel_win_id = { 2, 2, 0xff, 0xff }, 5175452afb13SDamon Ding .reg_offset = 0x400, 5176452afb13SDamon Ding .axi_id = 0, 5177452afb13SDamon Ding .axi_yrgb_id = 0x06, 5178452afb13SDamon Ding .axi_uv_id = 0x07, 5179452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 5180452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5181452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 5182452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5183452afb13SDamon Ding .max_upscale_factor = 8, 5184452afb13SDamon Ding .max_downscale_factor = 8, 5185452afb13SDamon Ding }, 5186452afb13SDamon Ding 5187452afb13SDamon Ding { 5188452afb13SDamon Ding .name = "Esmart3", 5189452afb13SDamon Ding .phys_id = ROCKCHIP_VOP2_ESMART3, 5190452afb13SDamon Ding .type = ESMART_LAYER, 5191452afb13SDamon Ding .win_sel_port_offset = 14, 5192452afb13SDamon Ding .layer_sel_win_id = { 3, 3, 0xff, 0xff }, 5193452afb13SDamon Ding .reg_offset = 0x600, 5194452afb13SDamon Ding .axi_id = 0, 5195452afb13SDamon Ding .axi_yrgb_id = 0x08, 5196452afb13SDamon Ding .axi_uv_id = 0x0d, 5197452afb13SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 5198452afb13SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5199452afb13SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 5200452afb13SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 5201452afb13SDamon Ding .max_upscale_factor = 8, 5202452afb13SDamon Ding .max_downscale_factor = 8, 5203452afb13SDamon Ding }, 5204452afb13SDamon Ding }; 5205452afb13SDamon Ding 5206452afb13SDamon Ding static struct vop2_vp_data rk3562_vp_data[2] = { 5207452afb13SDamon Ding { 5208452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 5209452afb13SDamon Ding .max_output = {2048, 4096}, 5210452afb13SDamon Ding .win_dly = 8, 5211452afb13SDamon Ding .layer_mix_dly = 8, 5212452afb13SDamon Ding }, 5213452afb13SDamon Ding { 5214452afb13SDamon Ding .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 5215452afb13SDamon Ding .max_output = {2048, 1080}, 5216452afb13SDamon Ding .win_dly = 8, 5217452afb13SDamon Ding .layer_mix_dly = 8, 5218452afb13SDamon Ding }, 5219452afb13SDamon Ding }; 5220452afb13SDamon Ding 5221452afb13SDamon Ding const struct vop2_data rk3562_vop = { 5222452afb13SDamon Ding .version = VOP_VERSION_RK3562, 5223452afb13SDamon Ding .nr_vps = 2, 5224452afb13SDamon Ding .vp_data = rk3562_vp_data, 5225452afb13SDamon Ding .win_data = rk3562_win_data, 5226452afb13SDamon Ding .plane_mask = rk3562_vp_plane_mask[0], 5227452afb13SDamon Ding .plane_table = rk3562_plane_table, 5228452afb13SDamon Ding .vp_primary_plane_order = rk3562_vp_primary_plane_order, 5229452afb13SDamon Ding .nr_layers = 4, 5230452afb13SDamon Ding .nr_mixers = 3, 5231452afb13SDamon Ding .nr_gammas = 2, 5232452afb13SDamon Ding .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE, 523372388c26SDamon Ding .dump_regs = rk3562_dump_regs, 523472388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3562_dump_regs), 523572388c26SDamon Ding }; 523672388c26SDamon Ding 523772388c26SDamon Ding static struct vop2_dump_regs rk3568_dump_regs[] = { 523872388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 523972388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 524072388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 524172388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 524272388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 524372388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 524472388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 524572388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 524672388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 524772388c26SDamon Ding { RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 524872388c26SDamon Ding { RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 524972388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 5250452afb13SDamon Ding }; 5251452afb13SDamon Ding 5252337d1c13SDamon Ding static u8 rk3568_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 5253337d1c13SDamon Ding ROCKCHIP_VOP2_SMART0, 5254337d1c13SDamon Ding ROCKCHIP_VOP2_SMART1, 5255337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 5256337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 5257337d1c13SDamon Ding }; 5258337d1c13SDamon Ding 5259ee008497SSandy Huang static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 5260ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 5261ee008497SSandy Huang {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 5262ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 5263ee008497SSandy Huang {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 5264ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 5265ee008497SSandy Huang {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 5266ee008497SSandy Huang }; 5267ee008497SSandy Huang 5268b0989546SSandy Huang static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 5269b0989546SSandy Huang { /* one display policy */ 5270b0989546SSandy Huang {/* main display */ 5271b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 5272b0989546SSandy Huang .attached_layers_nr = 6, 5273b0989546SSandy Huang .attached_layers = { 5274b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 5275b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 5276b0989546SSandy Huang }, 5277b0989546SSandy Huang }, 5278b0989546SSandy Huang {/* second display */}, 5279b0989546SSandy Huang {/* third display */}, 5280b0989546SSandy Huang {/* fourth display */}, 5281b0989546SSandy Huang }, 5282b0989546SSandy Huang 5283b0989546SSandy Huang { /* two display policy */ 5284b0989546SSandy Huang {/* main display */ 5285b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 5286b0989546SSandy Huang .attached_layers_nr = 3, 5287b0989546SSandy Huang .attached_layers = { 5288b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 5289b0989546SSandy Huang }, 5290b0989546SSandy Huang }, 5291b0989546SSandy Huang 5292b0989546SSandy Huang {/* second display */ 5293b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 5294b0989546SSandy Huang .attached_layers_nr = 3, 5295b0989546SSandy Huang .attached_layers = { 5296b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 5297b0989546SSandy Huang }, 5298b0989546SSandy Huang }, 5299b0989546SSandy Huang {/* third display */}, 5300b0989546SSandy Huang {/* fourth display */}, 5301b0989546SSandy Huang }, 5302b0989546SSandy Huang 5303b0989546SSandy Huang { /* three display policy */ 5304b0989546SSandy Huang {/* main display */ 5305b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART0, 5306b0989546SSandy Huang .attached_layers_nr = 3, 5307b0989546SSandy Huang .attached_layers = { 5308b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 5309b0989546SSandy Huang }, 5310b0989546SSandy Huang }, 5311b0989546SSandy Huang 5312b0989546SSandy Huang {/* second display */ 5313b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_SMART1, 5314b0989546SSandy Huang .attached_layers_nr = 2, 5315b0989546SSandy Huang .attached_layers = { 5316b0989546SSandy Huang ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 5317b0989546SSandy Huang }, 5318b0989546SSandy Huang }, 5319b0989546SSandy Huang 5320b0989546SSandy Huang {/* third display */ 5321b0989546SSandy Huang .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 5322b0989546SSandy Huang .attached_layers_nr = 1, 5323b0989546SSandy Huang .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 5324b0989546SSandy Huang }, 5325b0989546SSandy Huang 5326b0989546SSandy Huang {/* fourth display */}, 5327b0989546SSandy Huang }, 5328b0989546SSandy Huang 5329b0989546SSandy Huang {/* reserved for four display policy */}, 5330b0989546SSandy Huang }; 5331b0989546SSandy Huang 5332b0989546SSandy Huang static struct vop2_win_data rk3568_win_data[6] = { 5333b0989546SSandy Huang { 5334b0989546SSandy Huang .name = "Cluster0", 5335b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER0, 5336ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5337b0989546SSandy Huang .win_sel_port_offset = 0, 53385fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0xff }, 5339b0989546SSandy Huang .reg_offset = 0, 53405fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 53415fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53425fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 53435fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53444c765862SDamon Ding .max_upscale_factor = 4, 53454c765862SDamon Ding .max_downscale_factor = 4, 5346b0989546SSandy Huang }, 5347b0989546SSandy Huang 5348b0989546SSandy Huang { 5349b0989546SSandy Huang .name = "Cluster1", 5350b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_CLUSTER1, 5351ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5352b0989546SSandy Huang .win_sel_port_offset = 1, 53535fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 0xff }, 5354b0989546SSandy Huang .reg_offset = 0x200, 53555fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 53565fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53575fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 53585fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53594c765862SDamon Ding .max_upscale_factor = 4, 53604c765862SDamon Ding .max_downscale_factor = 4, 53611c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_CLUSTER0, 53621c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 5363b0989546SSandy Huang }, 5364b0989546SSandy Huang 5365b0989546SSandy Huang { 5366b0989546SSandy Huang .name = "Esmart0", 5367b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART0, 5368ecc31b6eSAndy Yan .type = ESMART_LAYER, 5369b0989546SSandy Huang .win_sel_port_offset = 4, 53705fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 0xff }, 5371b0989546SSandy Huang .reg_offset = 0, 53725fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 53735fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53745fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 53755fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53764c765862SDamon Ding .max_upscale_factor = 8, 53774c765862SDamon Ding .max_downscale_factor = 8, 5378b0989546SSandy Huang }, 5379b0989546SSandy Huang 5380b0989546SSandy Huang { 5381b0989546SSandy Huang .name = "Esmart1", 5382b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_ESMART1, 5383ecc31b6eSAndy Yan .type = ESMART_LAYER, 5384b0989546SSandy Huang .win_sel_port_offset = 5, 53855fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 0xff }, 5386b0989546SSandy Huang .reg_offset = 0x200, 53875fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 53885fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53895fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 53905fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 53914c765862SDamon Ding .max_upscale_factor = 8, 53924c765862SDamon Ding .max_downscale_factor = 8, 53931c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_ESMART0, 53941c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 5395b0989546SSandy Huang }, 5396b0989546SSandy Huang 5397b0989546SSandy Huang { 5398b0989546SSandy Huang .name = "Smart0", 5399b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART0, 5400ecc31b6eSAndy Yan .type = SMART_LAYER, 5401b0989546SSandy Huang .win_sel_port_offset = 6, 54025fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 0xff }, 5403b0989546SSandy Huang .reg_offset = 0x400, 54045fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 54055fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54065fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54075fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54084c765862SDamon Ding .max_upscale_factor = 8, 54094c765862SDamon Ding .max_downscale_factor = 8, 5410b0989546SSandy Huang }, 5411b0989546SSandy Huang 5412b0989546SSandy Huang { 5413b0989546SSandy Huang .name = "Smart1", 5414b0989546SSandy Huang .phys_id = ROCKCHIP_VOP2_SMART1, 5415ecc31b6eSAndy Yan .type = SMART_LAYER, 5416b0989546SSandy Huang .win_sel_port_offset = 7, 54175fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 0xff }, 5418b0989546SSandy Huang .reg_offset = 0x600, 54195fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 54205fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54215fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 54225fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 54234c765862SDamon Ding .max_upscale_factor = 8, 54244c765862SDamon Ding .max_downscale_factor = 8, 54251c9572c7SDamon Ding .source_win_id = ROCKCHIP_VOP2_SMART0, 54261c9572c7SDamon Ding .feature = WIN_FEATURE_MIRROR, 5427b0989546SSandy Huang }, 5428b0989546SSandy Huang }; 5429b0989546SSandy Huang 543063cb669fSSandy Huang static struct vop2_vp_data rk3568_vp_data[3] = { 543163cb669fSSandy Huang { 543263cb669fSSandy Huang .feature = VOP_FEATURE_OUTPUT_10BIT, 543363cb669fSSandy Huang .pre_scan_max_dly = 42, 543463cb669fSSandy Huang .max_output = {4096, 2304}, 5435d0408543SAndy Yan }, 543663cb669fSSandy Huang { 543763cb669fSSandy Huang .feature = 0, 543863cb669fSSandy Huang .pre_scan_max_dly = 40, 543963cb669fSSandy Huang .max_output = {2048, 1536}, 544063cb669fSSandy Huang }, 544163cb669fSSandy Huang { 544263cb669fSSandy Huang .feature = 0, 544363cb669fSSandy Huang .pre_scan_max_dly = 40, 544463cb669fSSandy Huang .max_output = {1920, 1080}, 544563cb669fSSandy Huang }, 544663cb669fSSandy Huang }; 5447d0408543SAndy Yan 544863cb669fSSandy Huang const struct vop2_data rk3568_vop = { 5449ecc31b6eSAndy Yan .version = VOP_VERSION_RK3568, 545063cb669fSSandy Huang .nr_vps = 3, 545163cb669fSSandy Huang .vp_data = rk3568_vp_data, 5452b0989546SSandy Huang .win_data = rk3568_win_data, 5453b0989546SSandy Huang .plane_mask = rk356x_vp_plane_mask[0], 5454ee008497SSandy Huang .plane_table = rk356x_plane_table, 5455337d1c13SDamon Ding .vp_primary_plane_order = rk3568_vp_primary_plane_order, 5456d0408543SAndy Yan .nr_layers = 6, 545763cb669fSSandy Huang .nr_mixers = 5, 54581147facaSSandy Huang .nr_gammas = 1, 545972388c26SDamon Ding .dump_regs = rk3568_dump_regs, 546072388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs), 5461d0408543SAndy Yan }; 5462d0408543SAndy Yan 5463337d1c13SDamon Ding static u8 rk3588_vp_primary_plane_order[ROCKCHIP_VOP2_LAYER_MAX] = { 5464337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART0, 5465337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART1, 5466337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART2, 5467337d1c13SDamon Ding ROCKCHIP_VOP2_ESMART3, 5468337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER0, 5469337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER1, 5470337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER2, 5471337d1c13SDamon Ding ROCKCHIP_VOP2_CLUSTER3, 5472337d1c13SDamon Ding }; 5473337d1c13SDamon Ding 5474ecc31b6eSAndy Yan static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 5475ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 5476ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 5477ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 5478ecc31b6eSAndy Yan {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 5479ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 5480ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 5481ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 5482ecc31b6eSAndy Yan {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 5483ecc31b6eSAndy Yan }; 5484ecc31b6eSAndy Yan 548572388c26SDamon Ding static struct vop2_dump_regs rk3588_dump_regs[] = { 548672388c26SDamon Ding { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 548772388c26SDamon Ding { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 548872388c26SDamon Ding { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 548972388c26SDamon Ding { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 549072388c26SDamon Ding { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 549172388c26SDamon Ding { RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 }, 549272388c26SDamon Ding { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 549372388c26SDamon Ding { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 549472388c26SDamon Ding { RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 }, 549572388c26SDamon Ding { RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 }, 549672388c26SDamon Ding { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 549772388c26SDamon Ding { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 549872388c26SDamon Ding { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 549972388c26SDamon Ding { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 550072388c26SDamon Ding { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 550172388c26SDamon Ding }; 550272388c26SDamon Ding 5503ecc31b6eSAndy Yan static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 5504ecc31b6eSAndy Yan { /* one display policy */ 5505ecc31b6eSAndy Yan {/* main display */ 5506608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5507ecc31b6eSAndy Yan .attached_layers_nr = 8, 5508ecc31b6eSAndy Yan .attached_layers = { 5509ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, 5510ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, 5511ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 5512ecc31b6eSAndy Yan }, 5513ecc31b6eSAndy Yan }, 5514ecc31b6eSAndy Yan {/* second display */}, 5515ecc31b6eSAndy Yan {/* third display */}, 5516ecc31b6eSAndy Yan {/* fourth display */}, 5517ecc31b6eSAndy Yan }, 5518ecc31b6eSAndy Yan 5519ecc31b6eSAndy Yan { /* two display policy */ 5520ecc31b6eSAndy Yan {/* main display */ 5521608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5522ecc31b6eSAndy Yan .attached_layers_nr = 4, 5523ecc31b6eSAndy Yan .attached_layers = { 5524ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 5525ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 5526ecc31b6eSAndy Yan }, 5527ecc31b6eSAndy Yan }, 5528ecc31b6eSAndy Yan 5529ecc31b6eSAndy Yan {/* second display */ 5530608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5531ecc31b6eSAndy Yan .attached_layers_nr = 4, 5532ecc31b6eSAndy Yan .attached_layers = { 5533ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, 5534ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 5535ecc31b6eSAndy Yan }, 5536ecc31b6eSAndy Yan }, 5537ecc31b6eSAndy Yan {/* third display */}, 5538ecc31b6eSAndy Yan {/* fourth display */}, 5539ecc31b6eSAndy Yan }, 5540ecc31b6eSAndy Yan 5541ecc31b6eSAndy Yan { /* three display policy */ 5542ecc31b6eSAndy Yan {/* main display */ 5543608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5544ecc31b6eSAndy Yan .attached_layers_nr = 3, 5545ecc31b6eSAndy Yan .attached_layers = { 5546ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 5547ecc31b6eSAndy Yan }, 5548ecc31b6eSAndy Yan }, 5549ecc31b6eSAndy Yan 5550ecc31b6eSAndy Yan {/* second display */ 5551608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 5552ecc31b6eSAndy Yan .attached_layers_nr = 3, 5553ecc31b6eSAndy Yan .attached_layers = { 5554ecc31b6eSAndy Yan ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 5555ecc31b6eSAndy Yan }, 5556ecc31b6eSAndy Yan }, 5557ecc31b6eSAndy Yan 5558ecc31b6eSAndy Yan {/* third display */ 5559ecc31b6eSAndy Yan .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5560ecc31b6eSAndy Yan .attached_layers_nr = 2, 5561ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 5562ecc31b6eSAndy Yan }, 5563ecc31b6eSAndy Yan 5564ecc31b6eSAndy Yan {/* fourth display */}, 5565ecc31b6eSAndy Yan }, 5566ecc31b6eSAndy Yan 5567ecc31b6eSAndy Yan { /* four display policy */ 5568ecc31b6eSAndy Yan {/* main display */ 5569608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 5570ecc31b6eSAndy Yan .attached_layers_nr = 2, 5571ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 5572ecc31b6eSAndy Yan }, 5573ecc31b6eSAndy Yan 5574ecc31b6eSAndy Yan {/* second display */ 5575608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 5576ecc31b6eSAndy Yan .attached_layers_nr = 2, 5577ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 5578ecc31b6eSAndy Yan }, 5579ecc31b6eSAndy Yan 5580ecc31b6eSAndy Yan {/* third display */ 5581608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 5582ecc31b6eSAndy Yan .attached_layers_nr = 2, 5583ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 5584ecc31b6eSAndy Yan }, 5585ecc31b6eSAndy Yan 5586ecc31b6eSAndy Yan {/* fourth display */ 5587608c9f66SDamon Ding .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 5588ecc31b6eSAndy Yan .attached_layers_nr = 2, 5589ecc31b6eSAndy Yan .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 5590ecc31b6eSAndy Yan }, 5591ecc31b6eSAndy Yan }, 5592ecc31b6eSAndy Yan 5593ecc31b6eSAndy Yan }; 5594ecc31b6eSAndy Yan 5595ecc31b6eSAndy Yan static struct vop2_win_data rk3588_win_data[8] = { 5596ecc31b6eSAndy Yan { 5597ecc31b6eSAndy Yan .name = "Cluster0", 5598ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER0, 5599ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER1, 5600ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5601ecc31b6eSAndy Yan .win_sel_port_offset = 0, 56025fa6e665SDamon Ding .layer_sel_win_id = { 0, 0, 0, 0 }, 5603ecc31b6eSAndy Yan .reg_offset = 0, 5604a33b790fSDamon Ding .axi_id = 0, 5605a33b790fSDamon Ding .axi_yrgb_id = 2, 5606a33b790fSDamon Ding .axi_uv_id = 3, 5607b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER0, 56085fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 56095fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56105fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 56115fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56124c765862SDamon Ding .max_upscale_factor = 4, 56134c765862SDamon Ding .max_downscale_factor = 4, 5614ecc31b6eSAndy Yan }, 5615ecc31b6eSAndy Yan 5616ecc31b6eSAndy Yan { 5617ecc31b6eSAndy Yan .name = "Cluster1", 5618ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER1, 5619ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5620ecc31b6eSAndy Yan .win_sel_port_offset = 1, 56215fa6e665SDamon Ding .layer_sel_win_id = { 1, 1, 1, 1 }, 5622ecc31b6eSAndy Yan .reg_offset = 0x200, 5623a33b790fSDamon Ding .axi_id = 0, 5624a33b790fSDamon Ding .axi_yrgb_id = 6, 5625a33b790fSDamon Ding .axi_uv_id = 7, 5626b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER1, 56275fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 56285fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56295fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 56305fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56314c765862SDamon Ding .max_upscale_factor = 4, 56324c765862SDamon Ding .max_downscale_factor = 4, 5633ecc31b6eSAndy Yan }, 5634ecc31b6eSAndy Yan 5635ecc31b6eSAndy Yan { 5636ecc31b6eSAndy Yan .name = "Cluster2", 5637ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER2, 5638ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_CLUSTER3, 5639ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5640ecc31b6eSAndy Yan .win_sel_port_offset = 2, 56415fa6e665SDamon Ding .layer_sel_win_id = { 4, 4, 4, 4 }, 5642ecc31b6eSAndy Yan .reg_offset = 0x400, 5643a33b790fSDamon Ding .axi_id = 1, 5644a33b790fSDamon Ding .axi_yrgb_id = 2, 5645a33b790fSDamon Ding .axi_uv_id = 3, 5646b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER2, 56475fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 56485fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56495fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 56505fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56514c765862SDamon Ding .max_upscale_factor = 4, 56524c765862SDamon Ding .max_downscale_factor = 4, 5653ecc31b6eSAndy Yan }, 5654ecc31b6eSAndy Yan 5655ecc31b6eSAndy Yan { 5656ecc31b6eSAndy Yan .name = "Cluster3", 5657ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_CLUSTER3, 5658ecc31b6eSAndy Yan .type = CLUSTER_LAYER, 5659ecc31b6eSAndy Yan .win_sel_port_offset = 3, 56605fa6e665SDamon Ding .layer_sel_win_id = { 5, 5, 5, 5 }, 5661ecc31b6eSAndy Yan .reg_offset = 0x600, 5662a33b790fSDamon Ding .axi_id = 1, 5663a33b790fSDamon Ding .axi_yrgb_id = 6, 5664a33b790fSDamon Ding .axi_uv_id = 7, 5665b6ba80b4SDamon Ding .pd_id = VOP2_PD_CLUSTER3, 56665fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 56675fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56685fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 56695fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56704c765862SDamon Ding .max_upscale_factor = 4, 56714c765862SDamon Ding .max_downscale_factor = 4, 5672ecc31b6eSAndy Yan }, 5673ecc31b6eSAndy Yan 5674ecc31b6eSAndy Yan { 5675ecc31b6eSAndy Yan .name = "Esmart0", 5676ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART0, 5677ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART1, 5678ecc31b6eSAndy Yan .type = ESMART_LAYER, 5679ecc31b6eSAndy Yan .win_sel_port_offset = 4, 56805fa6e665SDamon Ding .layer_sel_win_id = { 2, 2, 2, 2 }, 5681ecc31b6eSAndy Yan .reg_offset = 0, 5682a33b790fSDamon Ding .axi_id = 0, 5683a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 5684a33b790fSDamon Ding .axi_uv_id = 0x0b, 56855fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 56865fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56875fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 56885fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 56894c765862SDamon Ding .max_upscale_factor = 8, 56904c765862SDamon Ding .max_downscale_factor = 8, 5691ecc31b6eSAndy Yan }, 5692ecc31b6eSAndy Yan 5693ecc31b6eSAndy Yan { 5694ecc31b6eSAndy Yan .name = "Esmart1", 5695ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART1, 5696ecc31b6eSAndy Yan .type = ESMART_LAYER, 5697ecc31b6eSAndy Yan .win_sel_port_offset = 5, 56985fa6e665SDamon Ding .layer_sel_win_id = { 3, 3, 3, 3 }, 5699ecc31b6eSAndy Yan .reg_offset = 0x200, 5700a33b790fSDamon Ding .axi_id = 0, 5701a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 5702a33b790fSDamon Ding .axi_uv_id = 0x0d, 5703b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 57045fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 57055fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 57065fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 57075fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 57084c765862SDamon Ding .max_upscale_factor = 8, 57094c765862SDamon Ding .max_downscale_factor = 8, 5710ecc31b6eSAndy Yan }, 5711ecc31b6eSAndy Yan 5712ecc31b6eSAndy Yan { 5713ecc31b6eSAndy Yan .name = "Esmart2", 5714ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART2, 5715ee01dbb2SDamon Ding .splice_win_id = ROCKCHIP_VOP2_ESMART3, 5716ecc31b6eSAndy Yan .type = ESMART_LAYER, 5717ecc31b6eSAndy Yan .win_sel_port_offset = 6, 57185fa6e665SDamon Ding .layer_sel_win_id = { 6, 6, 6, 6 }, 5719ecc31b6eSAndy Yan .reg_offset = 0x400, 5720a33b790fSDamon Ding .axi_id = 1, 5721a33b790fSDamon Ding .axi_yrgb_id = 0x0a, 5722a33b790fSDamon Ding .axi_uv_id = 0x0b, 5723b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 57245fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 57255fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 57265fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 57275fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 57284c765862SDamon Ding .max_upscale_factor = 8, 57294c765862SDamon Ding .max_downscale_factor = 8, 5730ecc31b6eSAndy Yan }, 5731ecc31b6eSAndy Yan 5732ecc31b6eSAndy Yan { 5733ecc31b6eSAndy Yan .name = "Esmart3", 5734ecc31b6eSAndy Yan .phys_id = ROCKCHIP_VOP2_ESMART3, 5735ecc31b6eSAndy Yan .type = ESMART_LAYER, 5736ecc31b6eSAndy Yan .win_sel_port_offset = 7, 57375fa6e665SDamon Ding .layer_sel_win_id = { 7, 7, 7, 7 }, 5738ecc31b6eSAndy Yan .reg_offset = 0x600, 5739a33b790fSDamon Ding .axi_id = 1, 5740a33b790fSDamon Ding .axi_yrgb_id = 0x0c, 5741a33b790fSDamon Ding .axi_uv_id = 0x0d, 5742b6ba80b4SDamon Ding .pd_id = VOP2_PD_ESMART, 57435fa6e665SDamon Ding .hsu_filter_mode = VOP2_SCALE_UP_BIC, 57445fa6e665SDamon Ding .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 57455fa6e665SDamon Ding .vsu_filter_mode = VOP2_SCALE_UP_BIL, 57465fa6e665SDamon Ding .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 57474c765862SDamon Ding .max_upscale_factor = 8, 57484c765862SDamon Ding .max_downscale_factor = 8, 5749ecc31b6eSAndy Yan }, 5750ecc31b6eSAndy Yan }; 5751ecc31b6eSAndy Yan 575212ee5af0SDamon Ding static struct dsc_error_info dsc_ecw[] = { 575312ee5af0SDamon Ding {0x00000000, "no error detected by DSC encoder"}, 575412ee5af0SDamon Ding {0x0030ffff, "bits per component error"}, 575512ee5af0SDamon Ding {0x0040ffff, "multiple mode error"}, 575612ee5af0SDamon Ding {0x0050ffff, "line buffer depth error"}, 575712ee5af0SDamon Ding {0x0060ffff, "minor version error"}, 575812ee5af0SDamon Ding {0x0070ffff, "picture height error"}, 575912ee5af0SDamon Ding {0x0080ffff, "picture width error"}, 576012ee5af0SDamon Ding {0x0090ffff, "number of slices error"}, 576112ee5af0SDamon Ding {0x00c0ffff, "slice height Error "}, 576212ee5af0SDamon Ding {0x00d0ffff, "slice width error"}, 576312ee5af0SDamon Ding {0x00e0ffff, "second line BPG offset error"}, 576412ee5af0SDamon Ding {0x00f0ffff, "non second line BPG offset error"}, 576512ee5af0SDamon Ding {0x0100ffff, "PPS ID error"}, 576612ee5af0SDamon Ding {0x0110ffff, "bits per pixel (BPP) Error"}, 576712ee5af0SDamon Ding {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */ 576812ee5af0SDamon Ding 576912ee5af0SDamon Ding {0x01510001, "slice 0 RC buffer model overflow error"}, 577012ee5af0SDamon Ding {0x01510002, "slice 1 RC buffer model overflow error"}, 577112ee5af0SDamon Ding {0x01510004, "slice 2 RC buffer model overflow error"}, 577212ee5af0SDamon Ding {0x01510008, "slice 3 RC buffer model overflow error"}, 577312ee5af0SDamon Ding {0x01510010, "slice 4 RC buffer model overflow error"}, 577412ee5af0SDamon Ding {0x01510020, "slice 5 RC buffer model overflow error"}, 577512ee5af0SDamon Ding {0x01510040, "slice 6 RC buffer model overflow error"}, 577612ee5af0SDamon Ding {0x01510080, "slice 7 RC buffer model overflow error"}, 577712ee5af0SDamon Ding 577812ee5af0SDamon Ding {0x01610001, "slice 0 RC buffer model underflow error"}, 577912ee5af0SDamon Ding {0x01610002, "slice 1 RC buffer model underflow error"}, 578012ee5af0SDamon Ding {0x01610004, "slice 2 RC buffer model underflow error"}, 578112ee5af0SDamon Ding {0x01610008, "slice 3 RC buffer model underflow error"}, 578212ee5af0SDamon Ding {0x01610010, "slice 4 RC buffer model underflow error"}, 578312ee5af0SDamon Ding {0x01610020, "slice 5 RC buffer model underflow error"}, 578412ee5af0SDamon Ding {0x01610040, "slice 6 RC buffer model underflow error"}, 578512ee5af0SDamon Ding {0x01610080, "slice 7 RC buffer model underflow error"}, 578612ee5af0SDamon Ding 578712ee5af0SDamon Ding {0xffffffff, "unsuccessful RESET cycle status"}, 578812ee5af0SDamon Ding {0x00a0ffff, "ICH full error precision settings error"}, 578912ee5af0SDamon Ding {0x0020ffff, "native mode"}, 579012ee5af0SDamon Ding }; 579112ee5af0SDamon Ding 579212ee5af0SDamon Ding static struct dsc_error_info dsc_buffer_flow[] = { 579312ee5af0SDamon Ding {0x00000000, "rate buffer status"}, 579412ee5af0SDamon Ding {0x00000001, "line buffer status"}, 579512ee5af0SDamon Ding {0x00000002, "decoder model status"}, 579612ee5af0SDamon Ding {0x00000003, "pixel buffer status"}, 579712ee5af0SDamon Ding {0x00000004, "balance fifo buffer status"}, 579812ee5af0SDamon Ding {0x00000005, "syntax element fifo status"}, 579912ee5af0SDamon Ding }; 580012ee5af0SDamon Ding 580112ee5af0SDamon Ding static struct vop2_dsc_data rk3588_dsc_data[] = { 580212ee5af0SDamon Ding { 580312ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_8K, 580412ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_8K, 580512ee5af0SDamon Ding .max_slice_num = 8, 580612ee5af0SDamon Ding .max_linebuf_depth = 11, 5807b61227a3SDamon Ding .min_bits_per_pixel = 8, 580812ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src", 580912ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_8k_txp_clk", 581012ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_8k_pxl_clk", 581112ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_8k_cds_clk", 581212ee5af0SDamon Ding }, 581312ee5af0SDamon Ding 581412ee5af0SDamon Ding { 581512ee5af0SDamon Ding .id = ROCKCHIP_VOP2_DSC_4K, 581612ee5af0SDamon Ding .pd_id = VOP2_PD_DSC_4K, 581712ee5af0SDamon Ding .max_slice_num = 2, 581812ee5af0SDamon Ding .max_linebuf_depth = 11, 5819b61227a3SDamon Ding .min_bits_per_pixel = 8, 582012ee5af0SDamon Ding .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src", 582112ee5af0SDamon Ding .dsc_txp_clk_name = "dsc_4k_txp_clk", 582212ee5af0SDamon Ding .dsc_pxl_clk_name = "dsc_4k_pxl_clk", 582312ee5af0SDamon Ding .dsc_cds_clk_name = "dsc_4k_cds_clk", 582412ee5af0SDamon Ding }, 582512ee5af0SDamon Ding }; 582612ee5af0SDamon Ding 5827ecc31b6eSAndy Yan static struct vop2_vp_data rk3588_vp_data[4] = { 5828ecc31b6eSAndy Yan { 5829ee01dbb2SDamon Ding .splice_vp_id = 1, 5830ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5831b890760eSAlgea Cao .pre_scan_max_dly = 54, 5832ecc31b6eSAndy Yan .max_dclk = 600000, 5833ecc31b6eSAndy Yan .max_output = {7680, 4320}, 5834ecc31b6eSAndy Yan }, 5835ecc31b6eSAndy Yan { 5836ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5837ee01dbb2SDamon Ding .pre_scan_max_dly = 54, 5838ecc31b6eSAndy Yan .max_dclk = 600000, 5839ecc31b6eSAndy Yan .max_output = {4096, 2304}, 5840ecc31b6eSAndy Yan }, 5841ecc31b6eSAndy Yan { 5842ecc31b6eSAndy Yan .feature = VOP_FEATURE_OUTPUT_10BIT, 5843ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 5844ecc31b6eSAndy Yan .max_dclk = 600000, 5845ecc31b6eSAndy Yan .max_output = {4096, 2304}, 5846ecc31b6eSAndy Yan }, 5847ecc31b6eSAndy Yan { 5848ecc31b6eSAndy Yan .feature = 0, 5849ecc31b6eSAndy Yan .pre_scan_max_dly = 52, 5850ecc31b6eSAndy Yan .max_dclk = 200000, 5851ecc31b6eSAndy Yan .max_output = {1920, 1080}, 5852ecc31b6eSAndy Yan }, 5853ecc31b6eSAndy Yan }; 5854ecc31b6eSAndy Yan 5855b6ba80b4SDamon Ding static struct vop2_power_domain_data rk3588_vop_pd_data[] = { 5856b6ba80b4SDamon Ding { 5857b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER0, 5858b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0), 5859b6ba80b4SDamon Ding }, 5860b6ba80b4SDamon Ding { 5861b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER1, 5862b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1), 5863b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5864b6ba80b4SDamon Ding }, 5865b6ba80b4SDamon Ding { 5866b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER2, 5867b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2), 5868b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5869b6ba80b4SDamon Ding }, 5870b6ba80b4SDamon Ding { 5871b6ba80b4SDamon Ding .id = VOP2_PD_CLUSTER3, 5872b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3), 5873b6ba80b4SDamon Ding .parent_id = VOP2_PD_CLUSTER0, 5874b6ba80b4SDamon Ding }, 5875b6ba80b4SDamon Ding { 5876b6ba80b4SDamon Ding .id = VOP2_PD_ESMART, 5877b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) | 5878b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART2) | 5879b6ba80b4SDamon Ding BIT(ROCKCHIP_VOP2_ESMART3), 5880b6ba80b4SDamon Ding }, 5881b6ba80b4SDamon Ding { 5882b6ba80b4SDamon Ding .id = VOP2_PD_DSC_8K, 5883b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K), 5884b6ba80b4SDamon Ding }, 5885b6ba80b4SDamon Ding { 5886b6ba80b4SDamon Ding .id = VOP2_PD_DSC_4K, 5887b6ba80b4SDamon Ding .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K), 5888b6ba80b4SDamon Ding }, 5889b6ba80b4SDamon Ding }; 5890b6ba80b4SDamon Ding 5891ecc31b6eSAndy Yan const struct vop2_data rk3588_vop = { 5892ecc31b6eSAndy Yan .version = VOP_VERSION_RK3588, 5893ecc31b6eSAndy Yan .nr_vps = 4, 5894ecc31b6eSAndy Yan .vp_data = rk3588_vp_data, 5895ecc31b6eSAndy Yan .win_data = rk3588_win_data, 5896ecc31b6eSAndy Yan .plane_mask = rk3588_vp_plane_mask[0], 5897ecc31b6eSAndy Yan .plane_table = rk3588_plane_table, 5898b6ba80b4SDamon Ding .pd = rk3588_vop_pd_data, 589912ee5af0SDamon Ding .dsc = rk3588_dsc_data, 590012ee5af0SDamon Ding .dsc_error_ecw = dsc_ecw, 590112ee5af0SDamon Ding .dsc_error_buffer_flow = dsc_buffer_flow, 5902337d1c13SDamon Ding .vp_primary_plane_order = rk3588_vp_primary_plane_order, 5903ecc31b6eSAndy Yan .nr_layers = 8, 5904ecc31b6eSAndy Yan .nr_mixers = 7, 5905ecc31b6eSAndy Yan .nr_gammas = 4, 5906b6ba80b4SDamon Ding .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data), 590712ee5af0SDamon Ding .nr_dscs = 2, 590812ee5af0SDamon Ding .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw), 590912ee5af0SDamon Ding .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow), 591072388c26SDamon Ding .dump_regs = rk3588_dump_regs, 591172388c26SDamon Ding .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs), 5912ecc31b6eSAndy Yan }; 5913ecc31b6eSAndy Yan 5914d0408543SAndy Yan const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 5915d0408543SAndy Yan .preinit = rockchip_vop2_preinit, 5916d0408543SAndy Yan .prepare = rockchip_vop2_prepare, 5917d0408543SAndy Yan .init = rockchip_vop2_init, 5918d0408543SAndy Yan .set_plane = rockchip_vop2_set_plane, 5919d0408543SAndy Yan .enable = rockchip_vop2_enable, 5920d0408543SAndy Yan .disable = rockchip_vop2_disable, 5921b0989546SSandy Huang .fixup_dts = rockchip_vop2_fixup_dts, 59220675a2a4SDamon Ding .send_mcu_cmd = rockchip_vop2_send_mcu_cmd, 5923820a5c17SDamon Ding .check = rockchip_vop2_check, 592422007755SDamon Ding .mode_valid = rockchip_vop2_mode_valid, 5925b02eb70bSDamon Ding .mode_fixup = rockchip_vop2_mode_fixup, 59264c765862SDamon Ding .plane_check = rockchip_vop2_plane_check, 592772388c26SDamon Ding .regs_dump = rockchip_vop2_regs_dump, 592872388c26SDamon Ding .active_regs_dump = rockchip_vop2_active_regs_dump, 59298e7ef808SDamon Ding .apply_soft_te = rockchip_vop2_apply_soft_te, 5930d0408543SAndy Yan }; 5931