1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 4 * 5 */ 6 7 #include <config.h> 8 #include <common.h> 9 #include <errno.h> 10 #include <malloc.h> 11 #include <fdtdec.h> 12 #include <fdt_support.h> 13 #include <regmap.h> 14 #include <asm/arch/cpu.h> 15 #include <asm/unaligned.h> 16 #include <asm/io.h> 17 #include <linux/list.h> 18 #include <linux/log2.h> 19 #include <linux/media-bus-format.h> 20 #include <asm/arch/clock.h> 21 #include <asm/gpio.h> 22 #include <linux/err.h> 23 #include <linux/ioport.h> 24 #include <dm/device.h> 25 #include <dm/read.h> 26 #include <dm/ofnode.h> 27 #include <fixp-arith.h> 28 #include <syscon.h> 29 #include <linux/iopoll.h> 30 #include <dm/uclass-internal.h> 31 #include <stdlib.h> 32 #include <dm/of_access.h> 33 34 #include "rockchip_display.h" 35 #include "rockchip_crtc.h" 36 #include "rockchip_connector.h" 37 #include "rockchip_phy.h" 38 #include "rockchip_post_csc.h" 39 40 /* System registers definition */ 41 #define RK3568_REG_CFG_DONE 0x000 42 #define CFG_DONE_EN BIT(15) 43 44 #define RK3568_VERSION_INFO 0x004 45 #define EN_MASK 1 46 47 #define RK3568_AUTO_GATING_CTRL 0x008 48 #define AUTO_GATING_EN_SHIFT 31 49 #define PORT_DCLK_AUTO_GATING_EN_SHIFT 14 50 #define ACLK_PRE_AUTO_GATING_EN_SHIFT 7 51 52 #define RK3576_SYS_AXI_HURRY_CTRL0_IMD 0x014 53 #define AXI0_PORT_URGENCY_EN_SHIFT 24 54 55 #define RK3576_SYS_AXI_HURRY_CTRL1_IMD 0x018 56 #define AXI1_PORT_URGENCY_EN_SHIFT 24 57 58 #define RK3576_SYS_MMU_CTRL 0x020 59 #define RKMMU_V2_EN_SHIFT 0 60 #define RKMMU_V2_SEL_AXI_SHIFT 1 61 62 #define RK3568_SYS_AXI_LUT_CTRL 0x024 63 #define LUT_DMA_EN_SHIFT 0 64 #define DSP_VS_T_SEL_SHIFT 16 65 66 #define RK3568_DSP_IF_EN 0x028 67 #define RGB_EN_SHIFT 0 68 #define RK3588_DP0_EN_SHIFT 0 69 #define RK3588_DP1_EN_SHIFT 1 70 #define RK3588_RGB_EN_SHIFT 8 71 #define HDMI0_EN_SHIFT 1 72 #define EDP0_EN_SHIFT 3 73 #define RK3588_EDP0_EN_SHIFT 2 74 #define RK3588_HDMI0_EN_SHIFT 3 75 #define MIPI0_EN_SHIFT 4 76 #define RK3588_EDP1_EN_SHIFT 4 77 #define RK3588_HDMI1_EN_SHIFT 5 78 #define RK3588_MIPI0_EN_SHIFT 6 79 #define MIPI1_EN_SHIFT 20 80 #define RK3588_MIPI1_EN_SHIFT 7 81 #define LVDS0_EN_SHIFT 5 82 #define LVDS1_EN_SHIFT 24 83 #define BT1120_EN_SHIFT 6 84 #define BT656_EN_SHIFT 7 85 #define IF_MUX_MASK 3 86 #define RGB_MUX_SHIFT 8 87 #define HDMI0_MUX_SHIFT 10 88 #define RK3588_DP0_MUX_SHIFT 12 89 #define RK3588_DP1_MUX_SHIFT 14 90 #define EDP0_MUX_SHIFT 14 91 #define RK3588_HDMI_EDP0_MUX_SHIFT 16 92 #define RK3588_HDMI_EDP1_MUX_SHIFT 18 93 #define MIPI0_MUX_SHIFT 16 94 #define RK3588_MIPI0_MUX_SHIFT 20 95 #define MIPI1_MUX_SHIFT 21 96 #define LVDS0_MUX_SHIFT 18 97 #define LVDS1_MUX_SHIFT 25 98 99 #define RK3576_SYS_PORT_CTRL 0x028 100 #define VP_INTR_MERGE_EN_SHIFT 14 101 #define RK3576_DSP_VS_T_SEL_SHIFT 4 102 #define INTERLACE_FRM_REG_DONE_MASK 0x7 103 #define INTERLACE_FRM_REG_DONE_SHIFT 0 104 105 #define RK3568_DSP_IF_CTRL 0x02c 106 #define LVDS_DUAL_EN_SHIFT 0 107 #define RK3588_BT656_UV_SWAP_SHIFT 0 108 #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 109 #define RK3588_BT656_YC_SWAP_SHIFT 1 110 #define LVDS_DUAL_SWAP_EN_SHIFT 2 111 #define BT656_UV_SWAP 4 112 #define RK3588_BT1120_UV_SWAP_SHIFT 4 113 #define BT656_YC_SWAP 5 114 #define RK3588_BT1120_YC_SWAP_SHIFT 5 115 #define BT656_DCLK_POL 6 116 #define RK3588_HDMI_DUAL_EN_SHIFT 8 117 #define RK3588_EDP_DUAL_EN_SHIFT 8 118 #define RK3588_DP_DUAL_EN_SHIFT 9 119 #define RK3568_MIPI_DUAL_EN_SHIFT 10 120 #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11 121 #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12 122 123 #define RK3568_DSP_IF_POL 0x030 124 #define IF_CTRL_REG_DONE_IMD_SHIFT 28 125 #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 126 #define IF_CTRL_MIPI_PIN_POL_MASK 0x7 127 #define IF_CTRL_MIPI_PIN_POL_SHIFT 16 128 #define IF_CRTL_EDP_DCLK_POL_SHIT 15 129 #define IF_CTRL_EDP_PIN_POL_MASK 0x7 130 #define IF_CTRL_EDP_PIN_POL_SHIFT 12 131 #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 132 #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 133 #define IF_CRTL_HDMI_PIN_POL_SHIT 4 134 #define IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT 3 135 #define IF_CTRL_RGB_LVDS_PIN_POL_MASK 0x7 136 #define IF_CTRL_RGB_LVDS_PIN_POL_SHIFT 0 137 138 #define RK3562_MIPI_DCLK_POL_SHIFT 15 139 #define RK3562_MIPI_PIN_POL_SHIFT 12 140 #define RK3562_IF_PIN_POL_MASK 0x7 141 142 #define RK3588_DP0_PIN_POL_SHIFT 8 143 #define RK3588_DP1_PIN_POL_SHIFT 12 144 #define RK3588_IF_PIN_POL_MASK 0x7 145 146 #define HDMI_EDP0_DCLK_DIV_SHIFT 16 147 #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 148 #define HDMI_EDP1_DCLK_DIV_SHIFT 20 149 #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 150 #define MIPI0_PIXCLK_DIV_SHIFT 24 151 #define MIPI1_PIXCLK_DIV_SHIFT 26 152 153 #define RK3576_SYS_CLUSTER_PD_CTRL 0x030 154 #define RK3576_CLUSTER_PD_EN_SHIFT 0 155 156 #define RK3588_SYS_PD_CTRL 0x034 157 #define RK3588_CLUSTER0_PD_EN_SHIFT 0 158 #define RK3588_CLUSTER1_PD_EN_SHIFT 1 159 #define RK3588_CLUSTER2_PD_EN_SHIFT 2 160 #define RK3588_CLUSTER3_PD_EN_SHIFT 3 161 #define RK3588_DSC_8K_PD_EN_SHIFT 5 162 #define RK3588_DSC_4K_PD_EN_SHIFT 6 163 #define RK3588_ESMART_PD_EN_SHIFT 7 164 165 #define RK3576_SYS_ESMART_PD_CTRL 0x034 166 #define RK3576_ESMART_PD_EN_SHIFT 0 167 #define RK3576_ESMART_LB_MODE_SEL_SHIFT 6 168 #define RK3576_ESMART_LB_MODE_SEL_MASK 0x3 169 170 #define RK3568_SYS_OTP_WIN_EN 0x50 171 #define OTP_WIN_EN_SHIFT 0 172 #define RK3568_SYS_LUT_PORT_SEL 0x58 173 #define GAMMA_PORT_SEL_MASK 0x3 174 #define GAMMA_PORT_SEL_SHIFT 0 175 #define GAMMA_AHB_WRITE_SEL_MASK 0x3 176 #define GAMMA_AHB_WRITE_SEL_SHIFT 12 177 #define PORT_MERGE_EN_SHIFT 16 178 #define ESMART_LB_MODE_SEL_MASK 0x3 179 #define ESMART_LB_MODE_SEL_SHIFT 26 180 181 #define RK3568_VP0_LINE_FLAG 0x70 182 #define RK3568_VP1_LINE_FLAG 0x74 183 #define RK3568_VP2_LINE_FLAG 0x78 184 #define RK3568_SYS0_INT_EN 0x80 185 #define RK3568_SYS0_INT_CLR 0x84 186 #define RK3568_SYS0_INT_STATUS 0x88 187 #define RK3568_SYS1_INT_EN 0x90 188 #define RK3568_SYS1_INT_CLR 0x94 189 #define RK3568_SYS1_INT_STATUS 0x98 190 #define RK3568_VP0_INT_EN 0xA0 191 #define RK3568_VP0_INT_CLR 0xA4 192 #define RK3568_VP0_INT_STATUS 0xA8 193 #define RK3568_VP1_INT_EN 0xB0 194 #define RK3568_VP1_INT_CLR 0xB4 195 #define RK3568_VP1_INT_STATUS 0xB8 196 #define RK3568_VP2_INT_EN 0xC0 197 #define RK3568_VP2_INT_CLR 0xC4 198 #define RK3568_VP2_INT_STATUS 0xC8 199 #define RK3568_VP2_INT_RAW_STATUS 0xCC 200 #define RK3588_VP3_INT_EN 0xD0 201 #define RK3588_VP3_INT_CLR 0xD4 202 #define RK3588_VP3_INT_STATUS 0xD8 203 #define RK3576_WB_CTRL 0x100 204 #define RK3576_WB_XSCAL_FACTOR 0x104 205 #define RK3576_WB_YRGB_MST 0x108 206 #define RK3576_WB_CBR_MST 0x10C 207 #define RK3576_WB_VIR_STRIDE 0x110 208 #define RK3576_WB_TIMEOUT_CTRL 0x114 209 #define RK3576_MIPI0_IF_CTRL 0x180 210 #define RK3576_IF_OUT_EN_SHIFT 0 211 #define RK3576_IF_CLK_OUT_EN_SHIFT 1 212 #define RK3576_IF_PORT_SEL_SHIFT 2 213 #define RK3576_IF_PORT_SEL_MASK 0x3 214 #define RK3576_IF_PIN_POL_SHIFT 4 215 #define RK3576_IF_PIN_POL_MASK 0x7 216 #define RK3576_IF_SPLIT_EN_SHIFT 8 217 #define RK3576_IF_DATA1_SEL_SHIFT 9 218 #define RK3576_MIPI_CMD_MODE_SHIFT 11 219 #define RK3576_IF_DCLK_SEL_SHIFT 21 220 #define RK3576_IF_DCLK_SEL_MASK 0x1 221 #define RK3576_IF_PIX_CLK_SEL_SHIFT 20 222 #define RK3576_IF_PIX_CLK_SEL_MASK 0x1 223 #define RK3576_IF_REGDONE_IMD_EN_SHIFT 31 224 #define RK3576_HDMI0_IF_CTRL 0x184 225 #define RK3576_EDP0_IF_CTRL 0x188 226 #define RK3576_DP0_IF_CTRL 0x18C 227 #define RK3576_RGB_IF_CTRL 0x194 228 #define RK3576_BT656_OUT_EN_SHIFT 12 229 #define RK3576_BT656_UV_SWAP_SHIFT 13 230 #define RK3576_BT656_YC_SWAP_SHIFT 14 231 #define RK3576_BT1120_OUT_EN_SHIFT 16 232 #define RK3576_BT1120_UV_SWAP_SHIFT 17 233 #define RK3576_BT1120_YC_SWAP_SHIFT 18 234 #define RK3576_DP1_IF_CTRL 0x1A4 235 #define RK3576_DP2_IF_CTRL 0x1B0 236 237 #define RK3588_SYS_VAR_FREQ_CTRL 0x038 238 #define RK3588_VP0_LINE_FLAG_OR_EN_SHIFT 20 239 #define RK3588_VP0_DSP_HOLD_OR_EN_SHIFT 24 240 #define RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT 28 241 242 #define RK3568_SYS_STATUS0 0x60 243 #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8 244 #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9 245 #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10 246 #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11 247 #define RK3588_DSC_8K_PD_STATUS_SHIFT 13 248 #define RK3588_DSC_4K_PD_STATUS_SHIFT 14 249 #define RK3588_ESMART_PD_STATUS_SHIFT 15 250 251 #define RK3568_SYS_CTRL_LINE_FLAG0 0x70 252 #define LINE_FLAG_NUM_MASK 0x1fff 253 #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0 254 #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16 255 256 /* DSC CTRL registers definition */ 257 #define RK3588_DSC_8K_SYS_CTRL 0x200 258 #define DSC_PORT_SEL_MASK 0x3 259 #define DSC_PORT_SEL_SHIFT 0 260 #define DSC_MAN_MODE_MASK 0x1 261 #define DSC_MAN_MODE_SHIFT 2 262 #define DSC_INTERFACE_MODE_MASK 0x3 263 #define DSC_INTERFACE_MODE_SHIFT 4 264 #define DSC_PIXEL_NUM_MASK 0x3 265 #define DSC_PIXEL_NUM_SHIFT 6 266 #define DSC_PXL_CLK_DIV_MASK 0x1 267 #define DSC_PXL_CLK_DIV_SHIFT 8 268 #define DSC_CDS_CLK_DIV_MASK 0x3 269 #define DSC_CDS_CLK_DIV_SHIFT 12 270 #define DSC_TXP_CLK_DIV_MASK 0x3 271 #define DSC_TXP_CLK_DIV_SHIFT 14 272 #define DSC_INIT_DLY_MODE_MASK 0x1 273 #define DSC_INIT_DLY_MODE_SHIFT 16 274 #define DSC_SCAN_EN_SHIFT 17 275 #define DSC_HALT_EN_SHIFT 18 276 277 #define RK3588_DSC_8K_RST 0x204 278 #define RST_DEASSERT_MASK 0x1 279 #define RST_DEASSERT_SHIFT 0 280 281 #define RK3588_DSC_8K_CFG_DONE 0x208 282 #define DSC_CFG_DONE_SHIFT 0 283 284 #define RK3588_DSC_8K_INIT_DLY 0x20C 285 #define DSC_INIT_DLY_NUM_MASK 0xffff 286 #define DSC_INIT_DLY_NUM_SHIFT 0 287 #define SCAN_TIMING_PARA_IMD_EN_SHIFT 16 288 289 #define RK3588_DSC_8K_HTOTAL_HS_END 0x210 290 #define DSC_HTOTAL_PW_MASK 0xffffffff 291 #define DSC_HTOTAL_PW_SHIFT 0 292 293 #define RK3588_DSC_8K_HACT_ST_END 0x214 294 #define DSC_HACT_ST_END_MASK 0xffffffff 295 #define DSC_HACT_ST_END_SHIFT 0 296 297 #define RK3588_DSC_8K_VTOTAL_VS_END 0x218 298 #define DSC_VTOTAL_PW_MASK 0xffffffff 299 #define DSC_VTOTAL_PW_SHIFT 0 300 301 #define RK3588_DSC_8K_VACT_ST_END 0x21C 302 #define DSC_VACT_ST_END_MASK 0xffffffff 303 #define DSC_VACT_ST_END_SHIFT 0 304 305 #define RK3588_DSC_8K_STATUS 0x220 306 307 /* Overlay registers definition */ 308 #define RK3528_OVL_SYS 0x500 309 #define RK3528_OVL_SYS_PORT_SEL 0x504 310 #define RK3528_OVL_SYS_GATING_EN 0x508 311 #define RK3528_OVL_SYS_CLUSTER0_CTRL 0x510 312 #define CLUSTER_DLY_NUM_SHIFT 0 313 #define RK3528_OVL_SYS_ESMART0_CTRL 0x520 314 #define ESMART_DLY_NUM_MASK 0xff 315 #define ESMART_DLY_NUM_SHIFT 0 316 #define RK3528_OVL_SYS_ESMART1_CTRL 0x524 317 #define RK3528_OVL_SYS_ESMART2_CTRL 0x528 318 #define RK3528_OVL_SYS_ESMART3_CTRL 0x52C 319 #define RK3528_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530 320 #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 321 #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 322 #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c 323 #define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540 324 #define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544 325 #define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548 326 #define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c 327 328 #define RK3528_OVL_PORT0_CTRL 0x600 329 #define RK3568_OVL_CTRL 0x600 330 #define OVL_MODE_SEL_MASK 0x1 331 #define OVL_MODE_SEL_SHIFT 0 332 #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 333 #define RK3528_OVL_PORT0_LAYER_SEL 0x604 334 #define RK3568_OVL_LAYER_SEL 0x604 335 #define LAYER_SEL_MASK 0xf 336 337 #define RK3568_OVL_PORT_SEL 0x608 338 #define PORT_MUX_MASK 0xf 339 #define PORT_MUX_SHIFT 0 340 #define LAYER_SEL_PORT_MASK 0x3 341 #define LAYER_SEL_PORT_SHIFT 16 342 343 #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 344 #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 345 #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 346 #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 347 #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620 348 #define RK3528_OVL_PORT0_MIX0_DST_COLOR_CTRL 0x624 349 #define RK3528_OVL_PORT0_MIX0_SRC_ALPHA_CTRL 0x628 350 #define RK3528_OVL_PORT0_MIX0_DST_ALPHA_CTRL 0x62C 351 #define RK3528_OVL_PORT0_MIX1_SRC_COLOR_CTRL 0x630 352 #define RK3528_OVL_PORT0_MIX1_DST_COLOR_CTRL 0x634 353 #define RK3528_OVL_PORT0_MIX1_SRC_ALPHA_CTRL 0x638 354 #define RK3528_OVL_PORT0_MIX1_DST_ALPHA_CTRL 0x63C 355 #define RK3528_OVL_PORT0_MIX2_SRC_COLOR_CTRL 0x640 356 #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644 357 #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648 358 #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C 359 #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 360 #define RK3568_MIX0_DST_COLOR_CTRL 0x654 361 #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 362 #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 363 #define RK3576_EXTRA_SRC_COLOR_CTRL 0x650 364 #define RK3576_EXTRA_DST_COLOR_CTRL 0x654 365 #define RK3576_EXTRA_SRC_ALPHA_CTRL 0x658 366 #define RK3576_EXTRA_DST_ALPHA_CTRL 0x65C 367 #define RK3528_HDR_SRC_COLOR_CTRL 0x660 368 #define RK3528_HDR_DST_COLOR_CTRL 0x664 369 #define RK3528_HDR_SRC_ALPHA_CTRL 0x668 370 #define RK3528_HDR_DST_ALPHA_CTRL 0x66C 371 #define RK3528_OVL_PORT0_BG_MIX_CTRL 0x670 372 #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 373 #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 374 #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 375 #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 376 #define RK3568_VP0_BG_MIX_CTRL 0x6E0 377 #define BG_MIX_CTRL_MASK 0xff 378 #define BG_MIX_CTRL_SHIFT 24 379 #define RK3568_VP1_BG_MIX_CTRL 0x6E4 380 #define RK3568_VP2_BG_MIX_CTRL 0x6E8 381 #define RK3568_CLUSTER_DLY_NUM 0x6F0 382 #define RK3568_CLUSTER_DLY_NUM1 0x6F4 383 #define CLUSTER_DLY_NUM_MASK 0xffff 384 #define CLUSTER0_DLY_NUM_SHIFT 0 385 #define CLUSTER1_DLY_NUM_SHIFT 16 386 #define RK3568_SMART_DLY_NUM 0x6F8 387 #define SMART_DLY_NUM_MASK 0xff 388 #define ESMART0_DLY_NUM_SHIFT 0 389 #define ESMART1_DLY_NUM_SHIFT 8 390 #define SMART0_DLY_NUM_SHIFT 16 391 #define SMART1_DLY_NUM_SHIFT 24 392 393 #define RK3528_OVL_PORT1_CTRL 0x700 394 #define RK3528_OVL_PORT1_LAYER_SEL 0x704 395 #define RK3528_OVL_PORT1_MIX0_SRC_COLOR_CTRL 0x720 396 #define RK3528_OVL_PORT1_MIX0_DST_COLOR_CTRL 0x724 397 #define RK3528_OVL_PORT1_MIX0_SRC_ALPHA_CTRL 0x728 398 #define RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL 0x72C 399 #define RK3528_OVL_PORT1_MIX1_SRC_COLOR_CTRL 0x730 400 #define RK3528_OVL_PORT1_MIX1_DST_COLOR_CTRL 0x734 401 #define RK3528_OVL_PORT1_MIX1_SRC_ALPHA_CTRL 0x738 402 #define RK3528_OVL_PORT1_MIX1_DST_ALPHA_CTRL 0x73C 403 #define RK3528_OVL_PORT1_MIX2_SRC_COLOR_CTRL 0x740 404 #define RK3528_OVL_PORT1_MIX2_DST_COLOR_CTRL 0x744 405 #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748 406 #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C 407 #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770 408 #define RK3576_OVL_PORT2_CTRL 0x800 409 #define RK3576_OVL_PORT2_LAYER_SEL 0x804 410 #define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL 0x820 411 #define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL 0x824 412 #define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL 0x828 413 #define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL 0x82C 414 #define RK3576_OVL_PORT2_BG_MIX_CTRL 0x870 415 416 /* Video Port registers definition */ 417 #define RK3568_VP0_DSP_CTRL 0xC00 418 #define OUT_MODE_MASK 0xf 419 #define OUT_MODE_SHIFT 0 420 #define DATA_SWAP_MASK 0x1f 421 #define DATA_SWAP_SHIFT 8 422 #define DSP_BG_SWAP 0x1 423 #define DSP_RB_SWAP 0x2 424 #define DSP_RG_SWAP 0x4 425 #define DSP_DELTA_SWAP 0x8 426 #define CORE_DCLK_DIV_EN_SHIFT 4 427 #define P2I_EN_SHIFT 5 428 #define DSP_FILED_POL 6 429 #define INTERLACE_EN_SHIFT 7 430 #define DSP_X_MIR_EN_SHIFT 13 431 #define POST_DSP_OUT_R2Y_SHIFT 15 432 #define PRE_DITHER_DOWN_EN_SHIFT 16 433 #define DITHER_DOWN_EN_SHIFT 17 434 #define DITHER_DOWN_SEL_SHIFT 18 435 #define DITHER_DOWN_SEL_MASK 0x3 436 #define DITHER_DOWN_MODE_SHIFT 20 437 #define GAMMA_UPDATE_EN_SHIFT 22 438 #define DSP_LUT_EN_SHIFT 28 439 440 #define STANDBY_EN_SHIFT 31 441 442 #define RK3568_VP0_MIPI_CTRL 0xC04 443 #define DCLK_DIV2_SHIFT 4 444 #define DCLK_DIV2_MASK 0x3 445 #define MIPI_DUAL_EN_SHIFT 20 446 #define MIPI_DUAL_SWAP_EN_SHIFT 21 447 #define EDPI_TE_EN 28 448 #define EDPI_WMS_HOLD_EN 30 449 #define EDPI_WMS_FS 31 450 451 452 #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 453 #define POST_URGENCY_EN_SHIFT 8 454 #define POST_URGENCY_THL_SHIFT 16 455 #define POST_URGENCY_THL_MASK 0xf 456 #define POST_URGENCY_THH_SHIFT 20 457 #define POST_URGENCY_THH_MASK 0xf 458 459 #define RK3568_VP0_DCLK_SEL 0xC0C 460 #define RK3576_DCLK_CORE_SEL_SHIFT 0 461 #define RK3576_DCLK_OUT_SEL_SHIFT 2 462 463 #define RK3568_VP0_3D_LUT_CTRL 0xC10 464 #define VP0_3D_LUT_EN_SHIFT 0 465 #define VP0_3D_LUT_UPDATE_SHIFT 2 466 467 #define RK3588_VP0_CLK_CTRL 0xC0C 468 #define DCLK_CORE_DIV_SHIFT 0 469 #define DCLK_OUT_DIV_SHIFT 2 470 471 #define RK3568_VP0_3D_LUT_MST 0xC20 472 473 #define RK3568_VP0_DSP_BG 0xC2C 474 #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 475 #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 476 #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 477 #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 478 #define RK3568_VP0_POST_SCL_CTRL 0xC40 479 #define RK3568_VP0_POST_SCALE_MASK 0x3 480 #define RK3568_VP0_POST_SCALE_SHIFT 0 481 #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 482 #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 483 #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 484 #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 485 #define RK3568_VP0_DSP_VACT_ST_END 0xC54 486 #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 487 #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 488 489 #define RK3568_VP0_BCSH_CTRL 0xC60 490 #define BCSH_CTRL_Y2R_SHIFT 0 491 #define BCSH_CTRL_Y2R_MASK 0x1 492 #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 493 #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 494 #define BCSH_CTRL_R2Y_SHIFT 4 495 #define BCSH_CTRL_R2Y_MASK 0x1 496 #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 497 #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 498 499 #define RK3568_VP0_BCSH_BCS 0xC64 500 #define BCSH_BRIGHTNESS_SHIFT 0 501 #define BCSH_BRIGHTNESS_MASK 0xFF 502 #define BCSH_CONTRAST_SHIFT 8 503 #define BCSH_CONTRAST_MASK 0x1FF 504 #define BCSH_SATURATION_SHIFT 20 505 #define BCSH_SATURATION_MASK 0x3FF 506 #define BCSH_OUT_MODE_SHIFT 30 507 #define BCSH_OUT_MODE_MASK 0x3 508 509 #define RK3568_VP0_BCSH_H 0xC68 510 #define BCSH_SIN_HUE_SHIFT 0 511 #define BCSH_SIN_HUE_MASK 0x1FF 512 #define BCSH_COS_HUE_SHIFT 16 513 #define BCSH_COS_HUE_MASK 0x1FF 514 515 #define RK3568_VP0_BCSH_COLOR 0xC6C 516 #define BCSH_EN_SHIFT 31 517 #define BCSH_EN_MASK 1 518 519 #define RK3576_VP0_POST_DITHER_FRC_0 0xCA0 520 #define RK3576_VP0_POST_DITHER_FRC_1 0xCA4 521 #define RK3576_VP0_POST_DITHER_FRC_2 0xCA8 522 523 #define RK3528_VP0_ACM_CTRL 0xCD0 524 #define POST_CSC_COE00_MASK 0xFFFF 525 #define POST_CSC_COE00_SHIFT 16 526 #define POST_R2Y_MODE_MASK 0x7 527 #define POST_R2Y_MODE_SHIFT 8 528 #define POST_CSC_MODE_MASK 0x7 529 #define POST_CSC_MODE_SHIFT 3 530 #define POST_R2Y_EN_MASK 0x1 531 #define POST_R2Y_EN_SHIFT 2 532 #define POST_CSC_EN_MASK 0x1 533 #define POST_CSC_EN_SHIFT 1 534 #define POST_ACM_BYPASS_EN_MASK 0x1 535 #define POST_ACM_BYPASS_EN_SHIFT 0 536 #define RK3528_VP0_CSC_COE01_02 0xCD4 537 #define RK3528_VP0_CSC_COE10_11 0xCD8 538 #define RK3528_VP0_CSC_COE12_20 0xCDC 539 #define RK3528_VP0_CSC_COE21_22 0xCE0 540 #define RK3528_VP0_CSC_OFFSET0 0xCE4 541 #define RK3528_VP0_CSC_OFFSET1 0xCE8 542 #define RK3528_VP0_CSC_OFFSET2 0xCEC 543 544 #define RK3562_VP0_MCU_CTRL 0xCF8 545 #define MCU_TYPE_SHIFT 31 546 #define MCU_BYPASS_SHIFT 30 547 #define MCU_RS_SHIFT 29 548 #define MCU_FRAME_ST_SHIFT 28 549 #define MCU_HOLD_MODE_SHIFT 27 550 #define MCU_CLK_SEL_SHIFT 26 551 #define MCU_CLK_SEL_MASK 0x1 552 #define MCU_RW_PEND_SHIFT 20 553 #define MCU_RW_PEND_MASK 0x3F 554 #define MCU_RW_PST_SHIFT 16 555 #define MCU_RW_PST_MASK 0xF 556 #define MCU_CS_PEND_SHIFT 10 557 #define MCU_CS_PEND_MASK 0x3F 558 #define MCU_CS_PST_SHIFT 6 559 #define MCU_CS_PST_MASK 0xF 560 #define MCU_PIX_TOTAL_SHIFT 0 561 #define MCU_PIX_TOTAL_MASK 0x3F 562 563 #define RK3562_VP0_MCU_RW_BYPASS_PORT 0xCFC 564 #define MCU_WRITE_DATA_BYPASS_SHIFT 0 565 #define MCU_WRITE_DATA_BYPASS_MASK 0xFFFFFFFF 566 567 #define RK3568_VP1_DSP_CTRL 0xD00 568 #define RK3568_VP1_MIPI_CTRL 0xD04 569 #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 570 #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 571 #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 572 #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 573 #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 574 #define RK3568_VP1_POST_SCL_CTRL 0xD40 575 #define RK3568_VP1_DSP_HACT_INFO 0xD34 576 #define RK3568_VP1_DSP_VACT_INFO 0xD38 577 #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 578 #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 579 #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 580 #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 581 #define RK3568_VP1_DSP_VACT_ST_END 0xD54 582 #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 583 #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 584 585 #define RK3568_VP2_DSP_CTRL 0xE00 586 #define RK3568_VP2_MIPI_CTRL 0xE04 587 #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 588 #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 589 #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 590 #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 591 #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 592 #define RK3568_VP2_POST_SCL_CTRL 0xE40 593 #define RK3568_VP2_DSP_HACT_INFO 0xE34 594 #define RK3568_VP2_DSP_VACT_INFO 0xE38 595 #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 596 #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 597 #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 598 #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 599 #define RK3568_VP2_DSP_VACT_ST_END 0xE54 600 #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 601 #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 602 #define RK3568_VP2_BCSH_CTRL 0xE60 603 #define RK3568_VP2_BCSH_BCS 0xE64 604 #define RK3568_VP2_BCSH_H 0xE68 605 #define RK3568_VP2_BCSH_COLOR_BAR 0xE6C 606 #define RK3576_VP2_MCU_CTRL 0xEF8 607 #define RK3576_VP2_MCU_RW_BYPASS_PORT 0xEFC 608 609 /* Cluster0 register definition */ 610 #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 611 #define CLUSTER_YUV2RGB_EN_SHIFT 8 612 #define CLUSTER_RGB2YUV_EN_SHIFT 9 613 #define CLUSTER_CSC_MODE_SHIFT 10 614 #define CLUSTER_DITHER_UP_EN_SHIFT 18 615 #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 616 #define RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT 12 617 #define RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 618 #define RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT 14 619 #define AVG2_MASK 0x1 620 #define CLUSTER_AVG2_SHIFT 18 621 #define AVG4_MASK 0x1 622 #define CLUSTER_AVG4_SHIFT 19 623 #define RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT 22 624 #define CLUSTER_XGT_EN_SHIFT 24 625 #define XGT_MODE_MASK 0x3 626 #define CLUSTER_XGT_MODE_SHIFT 25 627 #define CLUSTER_XAVG_EN_SHIFT 27 628 #define CLUSTER_YRGB_GT2_SHIFT 28 629 #define CLUSTER_YRGB_GT4_SHIFT 29 630 #define RK3568_CLUSTER0_WIN0_CTRL2 0x1008 631 #define CLUSTER_AXI_YRGB_ID_MASK 0x1f 632 #define CLUSTER_AXI_YRGB_ID_SHIFT 0 633 #define CLUSTER_AXI_UV_ID_MASK 0x1f 634 #define CLUSTER_AXI_UV_ID_SHIFT 5 635 636 #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 637 #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 638 #define RK3568_CLUSTER0_WIN0_VIR 0x1018 639 #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 640 #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 641 #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 642 #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 643 #define RK3576_CLUSTER0_WIN0_ZME_CTRL 0x1040 644 #define WIN0_ZME_DERING_EN_SHIFT 3 645 #define WIN0_ZME_GATING_EN_SHIFT 31 646 #define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA 0x1044 647 #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 648 #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 649 #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 650 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 651 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 652 #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 653 #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 654 #define CLUSTER_AFBCD_HALF_BLOCK_SHIFT 7 655 #define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET 0x1078 656 #define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE 0x107C 657 658 #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 659 #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 660 #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 661 #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 662 #define RK3568_CLUSTER0_WIN1_VIR 0x1098 663 #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 664 #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 665 #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 666 #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 667 #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 668 #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 669 #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 670 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 671 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 672 #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 673 #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 674 #define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET 0x10F8 675 #define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE 0x10FC 676 677 #define RK3568_CLUSTER0_CTRL 0x1100 678 #define CLUSTER_EN_SHIFT 0 679 #define CLUSTER_AXI_ID_MASK 0x1 680 #define CLUSTER_AXI_ID_SHIFT 13 681 #define RK3576_CLUSTER0_PORT_SEL 0x11F4 682 #define CLUSTER_PORT_SEL_SHIFT 0 683 #define CLUSTER_PORT_SEL_MASK 0x3 684 #define RK3576_CLUSTER0_DLY_NUM 0x11F8 685 #define CLUSTER_WIN0_DLY_NUM_SHIFT 0 686 #define CLUSTER_WIN0_DLY_NUM_MASK 0xff 687 #define CLUSTER_WIN1_DLY_NUM_SHIFT 0 688 #define CLUSTER_WIN1_DLY_NUM_MASK 0xff 689 690 #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 691 #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 692 #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 693 #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 694 #define RK3568_CLUSTER1_WIN0_VIR 0x1218 695 #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 696 #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 697 #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 698 #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 699 #define RK3576_CLUSTER1_WIN0_ZME_CTRL 0x1240 700 #define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA 0x1244 701 #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 702 #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 703 #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 704 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 705 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 706 #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 707 #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 708 #define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET 0x1278 709 #define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE 0x127C 710 711 #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 712 #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 713 #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 714 #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 715 #define RK3568_CLUSTER1_WIN1_VIR 0x1298 716 #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 717 #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 718 #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 719 #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 720 #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 721 #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 722 #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 723 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 724 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 725 #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 726 #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 727 #define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET 0x12F8 728 #define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE 0x12FC 729 730 #define RK3568_CLUSTER1_CTRL 0x1300 731 #define RK3576_CLUSTER1_PORT_SEL 0x13F4 732 #define RK3576_CLUSTER1_DLY_NUM 0x13F8 733 734 /* Esmart register definition */ 735 #define RK3568_ESMART0_CTRL0 0x1800 736 #define RGB2YUV_EN_SHIFT 1 737 #define CSC_MODE_SHIFT 2 738 #define CSC_MODE_MASK 0x3 739 #define ESMART_LB_SELECT_SHIFT 12 740 #define ESMART_LB_SELECT_MASK 0x3 741 742 #define RK3568_ESMART0_CTRL1 0x1804 743 #define ESMART_AXI_YRGB_ID_MASK 0x1f 744 #define ESMART_AXI_YRGB_ID_SHIFT 4 745 #define ESMART_AXI_UV_ID_MASK 0x1f 746 #define ESMART_AXI_UV_ID_SHIFT 12 747 #define YMIRROR_EN_SHIFT 31 748 749 #define RK3568_ESMART0_AXI_CTRL 0x1808 750 #define ESMART_AXI_ID_MASK 0x1 751 #define ESMART_AXI_ID_SHIFT 1 752 753 #define RK3568_ESMART0_REGION0_CTRL 0x1810 754 #define WIN_EN_SHIFT 0 755 #define WIN_FORMAT_MASK 0x1f 756 #define WIN_FORMAT_SHIFT 1 757 #define REGION0_DITHER_UP_EN_SHIFT 12 758 #define REGION0_RB_SWAP_SHIFT 14 759 #define ESMART_XAVG_EN_SHIFT 20 760 #define ESMART_XGT_EN_SHIFT 21 761 #define ESMART_XGT_MODE_SHIFT 22 762 763 #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 764 #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 765 #define RK3568_ESMART0_REGION0_VIR 0x181C 766 #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 767 #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 768 #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 769 #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 770 #define YRGB_XSCL_MODE_MASK 0x3 771 #define YRGB_XSCL_MODE_SHIFT 0 772 #define YRGB_XSCL_FILTER_MODE_MASK 0x3 773 #define YRGB_XSCL_FILTER_MODE_SHIFT 2 774 #define YRGB_YSCL_MODE_MASK 0x3 775 #define YRGB_YSCL_MODE_SHIFT 4 776 #define YRGB_YSCL_FILTER_MODE_MASK 0x3 777 #define YRGB_YSCL_FILTER_MODE_SHIFT 6 778 779 #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 780 #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 781 #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 782 #define RK3568_ESMART0_REGION1_CTRL 0x1840 783 #define YRGB_GT2_MASK 0x1 784 #define YRGB_GT2_SHIFT 8 785 #define YRGB_GT4_MASK 0x1 786 #define YRGB_GT4_SHIFT 9 787 788 #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 789 #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 790 #define RK3568_ESMART0_REGION1_VIR 0x184C 791 #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 792 #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 793 #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 794 #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 795 #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 796 #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 797 #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 798 #define RK3568_ESMART0_REGION2_CTRL 0x1870 799 #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 800 #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 801 #define RK3568_ESMART0_REGION2_VIR 0x187C 802 #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 803 #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 804 #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 805 #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 806 #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 807 #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 808 #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 809 #define RK3568_ESMART0_REGION3_CTRL 0x18A0 810 #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 811 #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 812 #define RK3568_ESMART0_REGION3_VIR 0x18AC 813 #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 814 #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 815 #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 816 #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 817 #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 818 #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 819 #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 820 #define RK3568_ESMART0_COLOR_KEY_CTRL 0x18D0 821 #define RK3576_ESMART0_ALPHA_MAP 0x18D8 822 #define RK3576_ESMART0_PORT_SEL 0x18F4 823 #define ESMART_PORT_SEL_SHIFT 0 824 #define ESMART_PORT_SEL_MASK 0x3 825 #define RK3576_ESMART0_DLY_NUM 0x18F8 826 827 #define RK3568_ESMART1_CTRL0 0x1A00 828 #define RK3568_ESMART1_CTRL1 0x1A04 829 #define RK3568_ESMART1_REGION0_CTRL 0x1A10 830 #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 831 #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 832 #define RK3568_ESMART1_REGION0_VIR 0x1A1C 833 #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 834 #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 835 #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 836 #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 837 #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 838 #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 839 #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 840 #define RK3568_ESMART1_REGION1_CTRL 0x1A40 841 #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 842 #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 843 #define RK3568_ESMART1_REGION1_VIR 0x1A4C 844 #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 845 #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 846 #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 847 #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 848 #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 849 #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 850 #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 851 #define RK3568_ESMART1_REGION2_CTRL 0x1A70 852 #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 853 #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 854 #define RK3568_ESMART1_REGION2_VIR 0x1A7C 855 #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 856 #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 857 #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 858 #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 859 #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 860 #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 861 #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 862 #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 863 #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 864 #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 865 #define RK3568_ESMART1_REGION3_VIR 0x1AAC 866 #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 867 #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 868 #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 869 #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 870 #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 871 #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 872 #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 873 #define RK3576_ESMART1_ALPHA_MAP 0x1AD8 874 #define RK3576_ESMART1_PORT_SEL 0x1AF4 875 #define RK3576_ESMART1_DLY_NUM 0x1AF8 876 877 #define RK3568_SMART0_CTRL0 0x1C00 878 #define RK3568_SMART0_CTRL1 0x1C04 879 #define RK3568_SMART0_REGION0_CTRL 0x1C10 880 #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 881 #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 882 #define RK3568_SMART0_REGION0_VIR 0x1C1C 883 #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 884 #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 885 #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 886 #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 887 #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 888 #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 889 #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 890 #define RK3568_SMART0_REGION1_CTRL 0x1C40 891 #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 892 #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 893 #define RK3568_SMART0_REGION1_VIR 0x1C4C 894 #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 895 #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 896 #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 897 #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 898 #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 899 #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 900 #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 901 #define RK3568_SMART0_REGION2_CTRL 0x1C70 902 #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 903 #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 904 #define RK3568_SMART0_REGION2_VIR 0x1C7C 905 #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 906 #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 907 #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 908 #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 909 #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 910 #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 911 #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 912 #define RK3568_SMART0_REGION3_CTRL 0x1CA0 913 #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 914 #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 915 #define RK3568_SMART0_REGION3_VIR 0x1CAC 916 #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 917 #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 918 #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 919 #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 920 #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 921 #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 922 #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 923 #define RK3576_ESMART2_ALPHA_MAP 0x1CD8 924 #define RK3576_ESMART2_PORT_SEL 0x1CF4 925 #define RK3576_ESMART2_DLY_NUM 0x1CF8 926 927 #define RK3568_SMART1_CTRL0 0x1E00 928 #define RK3568_SMART1_CTRL1 0x1E04 929 #define RK3568_SMART1_REGION0_CTRL 0x1E10 930 #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 931 #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 932 #define RK3568_SMART1_REGION0_VIR 0x1E1C 933 #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 934 #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 935 #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 936 #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 937 #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 938 #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 939 #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 940 #define RK3568_SMART1_REGION1_CTRL 0x1E40 941 #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 942 #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 943 #define RK3568_SMART1_REGION1_VIR 0x1E4C 944 #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 945 #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 946 #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 947 #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 948 #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 949 #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 950 #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 951 #define RK3568_SMART1_REGION2_CTRL 0x1E70 952 #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 953 #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 954 #define RK3568_SMART1_REGION2_VIR 0x1E7C 955 #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 956 #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 957 #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 958 #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 959 #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 960 #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 961 #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 962 #define RK3568_SMART1_REGION3_CTRL 0x1EA0 963 #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 964 #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 965 #define RK3568_SMART1_REGION3_VIR 0x1EAC 966 #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 967 #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 968 #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 969 #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 970 #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 971 #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 972 #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 973 #define RK3576_ESMART3_ALPHA_MAP 0x1ED8 974 #define RK3576_ESMART3_PORT_SEL 0x1EF4 975 #define RK3576_ESMART3_DLY_NUM 0x1EF8 976 977 /* HDR register definition */ 978 #define RK3568_HDR_LUT_CTRL 0x2000 979 980 #define RK3588_VP3_DSP_CTRL 0xF00 981 #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400 982 #define RK3588_CLUSTER3_WIN0_CTRL0 0x1600 983 984 /* DSC 8K/4K register definition */ 985 #define RK3588_DSC_8K_PPS0_3 0x4000 986 #define RK3588_DSC_8K_CTRL0 0x40A0 987 #define DSC_EN_SHIFT 0 988 #define DSC_RBIT_SHIFT 2 989 #define DSC_RBYT_SHIFT 3 990 #define DSC_FLAL_SHIFT 4 991 #define DSC_MER_SHIFT 5 992 #define DSC_EPB_SHIFT 6 993 #define DSC_EPL_SHIFT 7 994 #define DSC_NSLC_MASK 0x7 995 #define DSC_NSLC_SHIFT 16 996 #define DSC_SBO_SHIFT 28 997 #define DSC_IFEP_SHIFT 29 998 #define DSC_PPS_UPD_SHIFT 31 999 #define DSC_CTRL0_DEF_CON ((1 << DSC_EN_SHIFT) | (1 << DSC_RBIT_SHIFT) | (0 << DSC_RBYT_SHIFT) | \ 1000 (1 << DSC_FLAL_SHIFT) | (1 << DSC_MER_SHIFT) | (0 << DSC_EPB_SHIFT) | \ 1001 (1 << DSC_EPL_SHIFT) | (1 << DSC_SBO_SHIFT)) 1002 1003 #define RK3588_DSC_8K_CTRL1 0x40A4 1004 #define RK3588_DSC_8K_STS0 0x40A8 1005 #define RK3588_DSC_8K_ERS 0x40C4 1006 1007 #define RK3588_DSC_4K_PPS0_3 0x4100 1008 #define RK3588_DSC_4K_CTRL0 0x41A0 1009 #define RK3588_DSC_4K_CTRL1 0x41A4 1010 #define RK3588_DSC_4K_STS0 0x41A8 1011 #define RK3588_DSC_4K_ERS 0x41C4 1012 1013 /* RK3528 HDR register definition */ 1014 #define RK3528_HDR_LUT_CTRL 0x2000 1015 1016 /* RK3528 ACM register definition */ 1017 #define RK3528_ACM_CTRL 0x6400 1018 #define RK3528_ACM_DELTA_RANGE 0x6404 1019 #define RK3528_ACM_FETCH_START 0x6408 1020 #define RK3528_ACM_FETCH_DONE 0x6420 1021 #define RK3528_ACM_YHS_DEL_HY_SEG0 0x6500 1022 #define RK3528_ACM_YHS_DEL_HY_SEG152 0x6760 1023 #define RK3528_ACM_YHS_DEL_HS_SEG0 0x6764 1024 #define RK3528_ACM_YHS_DEL_HS_SEG220 0x6ad4 1025 #define RK3528_ACM_YHS_DEL_HGAIN_SEG0 0x6ad8 1026 #define RK3528_ACM_YHS_DEL_HGAIN_SEG64 0x6bd8 1027 1028 /* RK3576 SHARP register definition */ 1029 #define RK3576_SHARP_CTRL 0x0000 1030 #define SW_SHARP_ENABLE_SHIFT 0 1031 1032 #define RK3568_MAX_REG 0x1ED0 1033 1034 #define RK3562_GRF_IOC_VO_IO_CON 0x10500 1035 #define RK3568_GRF_VO_CON1 0x0364 1036 #define GRF_BT656_CLK_INV_SHIFT 1 1037 #define GRF_BT1120_CLK_INV_SHIFT 2 1038 #define GRF_RGB_DCLK_INV_SHIFT 3 1039 1040 /* Base SYS_GRF: 0x2600a000*/ 1041 #define RK3576_SYS_GRF_MEMFAULT_STATUS0 0x0148 1042 1043 /* Base IOC_GRF: 0x26040000 */ 1044 #define RK3576_VCCIO_IOC_MISC_CON8 0x6420 1045 #define RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT 9 1046 #define RK3576_IOC_VOPLITE_SEL_SHIFT 11 1047 1048 /* Base PMU2: 0x27380000 */ 1049 #define RK3576_PMU_PWR_GATE_STS 0x0230 1050 #define PD_VOP_ESMART_DWN_STAT 12 1051 #define PD_VOP_CLUSTER_DWN_STAT 13 1052 #define RK3576_PMU_BISR_PDGEN_CON0 0x0510 1053 #define PD_VOP_ESMART_REPAIR_ENA_SHIFT 12 1054 #define PD_VOP_CLUSTER_REPAIR_ENA_SHIFT 13 1055 #define RK3576_PMU_BISR_PWR_REPAIR_STATUS0 0x0570 1056 #define PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT 12 1057 #define PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT 13 1058 1059 #define RK3588_GRF_SOC_CON1 0x0304 1060 #define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT 14 1061 1062 #define RK3588_GRF_VOP_CON2 0x0008 1063 #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 1064 #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 1065 #define RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT 2 1066 #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 1067 #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 1068 #define RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT 5 1069 1070 #define RK3588_GRF_VO1_CON0 0x0000 1071 #define HDMI_SYNC_POL_MASK 0x3 1072 #define HDMI0_SYNC_POL_SHIFT 5 1073 #define HDMI1_SYNC_POL_SHIFT 7 1074 1075 #define RK3588_PMU_BISR_CON3 0x20C 1076 #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 1077 #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 1078 #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 1079 #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 1080 #define RK3588_PD_DSC_8K_REPAIR_EN_SHIFT 13 1081 #define RK3588_PD_DSC_4K_REPAIR_EN_SHIFT 14 1082 #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 1083 1084 #define RK3588_PMU_BISR_STATUS5 0x294 1085 #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 1086 #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 1087 #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 1088 #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 1089 #define RK3588_PD_DSC_8K_PWR_STAT_SHIFI 13 1090 #define RK3588_PD_DSC_4K_PWR_STAT_SHIFI 14 1091 #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 1092 1093 #define VOP2_LAYER_MAX 8 1094 1095 #define VOP2_MAX_VP_OUTPUT_WIDTH 4096 1096 1097 /* KHz */ 1098 #define VOP2_MAX_DCLK_RATE 600000 1099 1100 /* 1101 * vop2 dsc id 1102 */ 1103 #define ROCKCHIP_VOP2_DSC_8K 0 1104 #define ROCKCHIP_VOP2_DSC_4K 1 1105 1106 /* 1107 * vop2 internal power domain id, 1108 * should be all none zero, 0 will be 1109 * treat as invalid; 1110 */ 1111 #define VOP2_PD_CLUSTER0 BIT(0) 1112 #define VOP2_PD_CLUSTER1 BIT(1) 1113 #define VOP2_PD_CLUSTER2 BIT(2) 1114 #define VOP2_PD_CLUSTER3 BIT(3) 1115 #define VOP2_PD_DSC_8K BIT(5) 1116 #define VOP2_PD_DSC_4K BIT(6) 1117 #define VOP2_PD_ESMART BIT(7) 1118 #define VOP2_PD_CLUSTER BIT(8) 1119 1120 #define VOP2_PLANE_NO_SCALING BIT(16) 1121 1122 #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 1123 #define VOP_FEATURE_AFBDC BIT(1) 1124 #define VOP_FEATURE_ALPHA_SCALE BIT(2) 1125 #define VOP_FEATURE_HDR10 BIT(3) 1126 #define VOP_FEATURE_NEXT_HDR BIT(4) 1127 /* a feature to splice two windows and two vps to support resolution > 4096 */ 1128 #define VOP_FEATURE_SPLICE BIT(5) 1129 #define VOP_FEATURE_OVERSCAN BIT(6) 1130 #define VOP_FEATURE_VIVID_HDR BIT(7) 1131 #define VOP_FEATURE_POST_ACM BIT(8) 1132 #define VOP_FEATURE_POST_CSC BIT(9) 1133 #define VOP_FEATURE_POST_FRC_V2 BIT(10) 1134 #define VOP_FEATURE_POST_SHARP BIT(11) 1135 1136 #define WIN_FEATURE_HDR2SDR BIT(0) 1137 #define WIN_FEATURE_SDR2HDR BIT(1) 1138 #define WIN_FEATURE_PRE_OVERLAY BIT(2) 1139 #define WIN_FEATURE_AFBDC BIT(3) 1140 #define WIN_FEATURE_CLUSTER_MAIN BIT(4) 1141 #define WIN_FEATURE_CLUSTER_SUB BIT(5) 1142 /* a mirror win can only get fb address 1143 * from source win: 1144 * Cluster1---->Cluster0 1145 * Esmart1 ---->Esmart0 1146 * Smart1 ---->Smart0 1147 * This is a feather on rk3566 1148 */ 1149 #define WIN_FEATURE_MIRROR BIT(6) 1150 #define WIN_FEATURE_MULTI_AREA BIT(7) 1151 #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8) 1152 #define WIN_FEATURE_DCI BIT(9) 1153 1154 #define V4L2_COLORSPACE_BT709F 0xfe 1155 #define V4L2_COLORSPACE_BT2020F 0xff 1156 1157 enum vop_csc_format { 1158 CSC_BT601L, 1159 CSC_BT709L, 1160 CSC_BT601F, 1161 CSC_BT2020L, 1162 CSC_BT709L_13BIT, 1163 CSC_BT709F_13BIT, 1164 CSC_BT2020L_13BIT, 1165 CSC_BT2020F_13BIT, 1166 }; 1167 1168 enum vop_csc_bit_depth { 1169 CSC_10BIT_DEPTH, 1170 CSC_13BIT_DEPTH, 1171 }; 1172 1173 enum vop2_pol { 1174 HSYNC_POSITIVE = 0, 1175 VSYNC_POSITIVE = 1, 1176 DEN_NEGATIVE = 2, 1177 DCLK_INVERT = 3 1178 }; 1179 1180 enum vop2_bcsh_out_mode { 1181 BCSH_OUT_MODE_BLACK, 1182 BCSH_OUT_MODE_BLUE, 1183 BCSH_OUT_MODE_COLOR_BAR, 1184 BCSH_OUT_MODE_NORMAL_VIDEO, 1185 }; 1186 1187 #define _VOP_REG(off, _mask, _shift, _write_mask) \ 1188 { \ 1189 .offset = off, \ 1190 .mask = _mask, \ 1191 .shift = _shift, \ 1192 .write_mask = _write_mask, \ 1193 } 1194 1195 #define VOP_REG(off, _mask, _shift) \ 1196 _VOP_REG(off, _mask, _shift, false) 1197 enum dither_down_mode { 1198 RGB888_TO_RGB565 = 0x0, 1199 RGB888_TO_RGB666 = 0x1 1200 }; 1201 1202 enum dither_down_mode_sel { 1203 DITHER_DOWN_ALLEGRO = 0x0, 1204 DITHER_DOWN_FRC = 0x1 1205 }; 1206 1207 enum vop2_video_ports_id { 1208 VOP2_VP0, 1209 VOP2_VP1, 1210 VOP2_VP2, 1211 VOP2_VP3, 1212 VOP2_VP_MAX, 1213 }; 1214 1215 enum vop2_layer_type { 1216 CLUSTER_LAYER = 0, 1217 ESMART_LAYER = 1, 1218 SMART_LAYER = 2, 1219 }; 1220 1221 enum vop2_plane_type { 1222 VOP2_PLANE_TYPE_OVERLAY = 0, 1223 VOP2_PLANE_TYPE_PRIMARY = 1, 1224 VOP2_PLANE_TYPE_CURSOR = 2, 1225 }; 1226 1227 /* This define must same with kernel win phy id */ 1228 enum vop2_layer_phy_id { 1229 ROCKCHIP_VOP2_CLUSTER0 = 0, 1230 ROCKCHIP_VOP2_CLUSTER1, 1231 ROCKCHIP_VOP2_ESMART0, 1232 ROCKCHIP_VOP2_ESMART1, 1233 ROCKCHIP_VOP2_SMART0, 1234 ROCKCHIP_VOP2_SMART1, 1235 ROCKCHIP_VOP2_CLUSTER2, 1236 ROCKCHIP_VOP2_CLUSTER3, 1237 ROCKCHIP_VOP2_ESMART2, 1238 ROCKCHIP_VOP2_ESMART3, 1239 ROCKCHIP_VOP2_LAYER_MAX, 1240 ROCKCHIP_VOP2_PHY_ID_INVALID = (u8)-1, 1241 }; 1242 1243 enum vop2_scale_up_mode { 1244 VOP2_SCALE_UP_NRST_NBOR, 1245 VOP2_SCALE_UP_BIL, 1246 VOP2_SCALE_UP_BIC, 1247 VOP2_SCALE_UP_ZME, 1248 }; 1249 1250 enum vop2_scale_down_mode { 1251 VOP2_SCALE_DOWN_NRST_NBOR, 1252 VOP2_SCALE_DOWN_BIL, 1253 VOP2_SCALE_DOWN_AVG, 1254 VOP2_SCALE_DOWN_ZME, 1255 }; 1256 1257 enum scale_mode { 1258 SCALE_NONE = 0x0, 1259 SCALE_UP = 0x1, 1260 SCALE_DOWN = 0x2 1261 }; 1262 1263 enum vop_dsc_interface_mode { 1264 VOP_DSC_IF_DISABLE = 0, 1265 VOP_DSC_IF_HDMI = 1, 1266 VOP_DSC_IF_MIPI_DS_MODE = 2, 1267 VOP_DSC_IF_MIPI_VIDEO_MODE = 3, 1268 }; 1269 1270 enum vop3_pre_scale_down_mode { 1271 VOP3_PRE_SCALE_UNSPPORT, 1272 VOP3_PRE_SCALE_DOWN_GT, 1273 VOP3_PRE_SCALE_DOWN_AVG, 1274 }; 1275 1276 /* 1277 * the delay number of a window in different mode. 1278 */ 1279 enum vop2_win_dly_mode { 1280 VOP2_DLY_MODE_DEFAULT, /* default mode */ 1281 VOP2_DLY_MODE_HISO_S, /* HDR in SDR out mode, as a SDR window */ 1282 VOP2_DLY_MODE_HIHO_H, /* HDR in HDR out mode, as a HDR window */ 1283 VOP2_DLY_MODE_DOVI_IN_CORE1, /* dovi video input, as dovi core1 */ 1284 VOP2_DLY_MODE_DOVI_IN_CORE2, /* dovi video input, as dovi core2 */ 1285 VOP2_DLY_MODE_NONDOVI_IN_CORE1, /* ndovi video input, as dovi core1 */ 1286 VOP2_DLY_MODE_NONDOVI_IN_CORE2, /* ndovi video input, as dovi core2 */ 1287 VOP2_DLY_MODE_MAX, 1288 }; 1289 1290 enum vop3_esmart_lb_mode { 1291 VOP3_ESMART_8K_MODE, 1292 VOP3_ESMART_4K_4K_MODE, 1293 VOP3_ESMART_4K_2K_2K_MODE, 1294 VOP3_ESMART_2K_2K_2K_2K_MODE, 1295 VOP3_ESMART_4K_4K_4K_MODE, 1296 VOP3_ESMART_4K_4K_2K_2K_MODE, 1297 }; 1298 1299 struct vop2_layer { 1300 u8 id; 1301 /** 1302 * @win_phys_id: window id of the layer selected. 1303 * Every layer must make sure to select different 1304 * windows of others. 1305 */ 1306 u8 win_phys_id; 1307 }; 1308 1309 struct vop2_power_domain_data { 1310 u16 id; 1311 u16 parent_id; 1312 /* 1313 * @module_id_mask: module id of which module this power domain is belongs to. 1314 * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 1315 */ 1316 u32 module_id_mask; 1317 }; 1318 1319 struct vop2_win_data { 1320 char *name; 1321 u8 phys_id; 1322 enum vop2_layer_type type; 1323 enum vop2_plane_type plane_type; 1324 u8 win_sel_port_offset; 1325 u8 layer_sel_win_id[VOP2_VP_MAX]; 1326 u8 axi_id; 1327 u8 axi_uv_id; 1328 u8 axi_yrgb_id; 1329 u8 splice_win_id; 1330 u8 hsu_filter_mode; 1331 u8 hsd_filter_mode; 1332 u8 vsu_filter_mode; 1333 u8 vsd_filter_mode; 1334 u8 hsd_pre_filter_mode; 1335 u8 vsd_pre_filter_mode; 1336 u8 scale_engine_num; 1337 u8 source_win_id; 1338 u8 possible_vp_mask; 1339 u8 dly[VOP2_DLY_MODE_MAX]; 1340 u16 pd_id; 1341 u32 reg_offset; 1342 u32 max_upscale_factor; 1343 u32 max_downscale_factor; 1344 u32 feature; 1345 u32 supported_rotations; 1346 bool splice_mode_right; 1347 }; 1348 1349 struct vop2_vp_data { 1350 u32 feature; 1351 u32 max_dclk; 1352 u8 pre_scan_max_dly; 1353 u8 layer_mix_dly; 1354 u8 hdrvivid_dly; 1355 u8 sdr2hdr_dly; 1356 u8 hdr_mix_dly; 1357 u8 win_dly; 1358 u8 splice_vp_id; 1359 u8 pixel_rate; 1360 struct vop_rect max_output; 1361 struct vop_urgency *urgency; 1362 }; 1363 1364 struct vop2_vp_plane_mask { 1365 u8 primary_plane_id; /* use this win to show logo */ 1366 u8 cursor_plane_id; 1367 u8 attached_layers_nr; /* number layers attach to this vp */ 1368 u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 1369 u32 plane_mask; 1370 }; 1371 1372 struct vop2_dsc_data { 1373 u8 id; 1374 u8 max_slice_num; 1375 u8 max_linebuf_depth; /* used to generate the bitstream */ 1376 u8 min_bits_per_pixel; /* bit num after encoder compress */ 1377 u16 pd_id; 1378 const char *dsc_txp_clk_src_name; 1379 const char *dsc_txp_clk_name; 1380 const char *dsc_pxl_clk_name; 1381 const char *dsc_cds_clk_name; 1382 }; 1383 1384 struct dsc_error_info { 1385 u32 dsc_error_val; 1386 char dsc_error_info[50]; 1387 }; 1388 1389 struct vop2_dump_regs { 1390 u32 offset; 1391 const char *name; 1392 u32 state_base; 1393 u32 state_mask; 1394 u32 state_shift; 1395 bool enable_state; 1396 u32 size; 1397 }; 1398 1399 struct vop2_esmart_lb_map { 1400 u8 lb_mode; 1401 u8 lb_map_value; 1402 }; 1403 1404 /** 1405 * struct vop2_ops - helper operations for vop2 hardware 1406 * 1407 * These hooks are used by the common part of the vop2 driver to 1408 * implement the proper behaviour of different variants. 1409 */ 1410 struct vop2_ops { 1411 void (*setup_win_dly)(struct display_state *state, int crtc_id); 1412 void (*setup_overlay)(struct display_state *state); 1413 }; 1414 1415 struct vop2_data { 1416 u32 version; 1417 u32 esmart_lb_mode; 1418 struct vop2_vp_data *vp_data; 1419 struct vop2_win_data *win_data; 1420 struct vop2_vp_plane_mask *plane_mask; 1421 struct vop2_power_domain_data *pd; 1422 struct vop2_dsc_data *dsc; 1423 struct dsc_error_info *dsc_error_ecw; 1424 struct dsc_error_info *dsc_error_buffer_flow; 1425 struct vop2_dump_regs *dump_regs; 1426 const struct vop2_esmart_lb_map *esmart_lb_mode_map; 1427 const struct vop2_ops *ops; 1428 u8 nr_vps; 1429 u8 nr_layers; 1430 u8 nr_mixers; 1431 u8 nr_gammas; 1432 u8 nr_pd; 1433 u8 nr_dscs; 1434 u8 nr_dsc_ecw; 1435 u8 nr_dsc_buffer_flow; 1436 u8 esmart_lb_mode_num; 1437 u32 reg_len; 1438 u32 dump_regs_size; 1439 u32 plane_mask_base; 1440 }; 1441 1442 struct vop2 { 1443 u32 *regsbak; 1444 void *regs; 1445 void *grf; 1446 void *vop_grf; 1447 void *vo1_grf; 1448 void *sys_pmu; 1449 void *ioc_grf; 1450 void *sharp_res; 1451 u32 reg_len; 1452 u32 version; 1453 u32 esmart_lb_mode; 1454 bool global_init; 1455 bool merge_irq; 1456 const struct vop2_data *data; 1457 struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 1458 }; 1459 1460 static struct vop2 *rockchip_vop2; 1461 1462 /* vop2_layer_phy_id */ 1463 static const char *const vop2_layer_name_list[] = { 1464 "Cluster0", 1465 "Cluster1", 1466 "Esmart0", 1467 "Esmart1", 1468 "Smart0", 1469 "Smart1", 1470 "Cluster2", 1471 "Cluster3", 1472 "Esmart2", 1473 "Esmart3", 1474 }; 1475 1476 static inline const char *vop2_plane_phys_id_to_string(u8 phys_id) 1477 { 1478 if (phys_id == ROCKCHIP_VOP2_PHY_ID_INVALID) 1479 return "INVALID"; 1480 1481 if (phys_id >= ARRAY_SIZE(vop2_layer_name_list)) 1482 return NULL; 1483 1484 return vop2_layer_name_list[phys_id]; 1485 } 1486 1487 static inline bool is_vop3(struct vop2 *vop2) 1488 { 1489 if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) 1490 return false; 1491 else 1492 return true; 1493 } 1494 1495 /* 1496 * bli_sd_factor = (src - 1) / (dst - 1) << 12; 1497 * avg_sd_factor: 1498 * bli_su_factor: 1499 * bic_su_factor: 1500 * = (src - 1) / (dst - 1) << 16; 1501 * 1502 * ygt2 enable: dst get one line from two line of the src 1503 * ygt4 enable: dst get one line from four line of the src. 1504 * 1505 */ 1506 #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 1507 #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 1508 1509 #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 1510 (fac * (dst - 1) >> 12 < (src - 1)) 1511 #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 1512 (fac * (dst - 1) >> 16 < (src - 1)) 1513 #define VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac) \ 1514 (fac * (dst - 1) >> 16 < (src - 1)) 1515 1516 static uint16_t vop2_scale_factor(enum scale_mode mode, 1517 int32_t filter_mode, 1518 uint32_t src, uint32_t dst) 1519 { 1520 uint32_t fac = 0; 1521 int i = 0; 1522 1523 if (mode == SCALE_NONE) 1524 return 0; 1525 1526 /* 1527 * A workaround to avoid zero div. 1528 */ 1529 if ((dst == 1) || (src == 1)) { 1530 dst = dst + 1; 1531 src = src + 1; 1532 } 1533 1534 if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 1535 fac = VOP2_BILI_SCL_DN(src, dst); 1536 for (i = 0; i < 100; i++) { 1537 if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 1538 break; 1539 fac -= 1; 1540 printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 1541 } 1542 } else { 1543 fac = VOP2_COMMON_SCL(src, dst); 1544 for (i = 0; i < 100; i++) { 1545 if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 1546 break; 1547 fac -= 1; 1548 printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 1549 } 1550 } 1551 1552 return fac; 1553 } 1554 1555 static bool vop3_scale_up_fac_check(uint32_t src, uint32_t dst, uint32_t fac, bool is_hor) 1556 { 1557 if (is_hor) 1558 return VOP3_COMMON_HOR_SCL_FAC_CHECK(src, dst, fac); 1559 return VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac); 1560 } 1561 1562 static uint16_t vop3_scale_factor(enum scale_mode mode, 1563 uint32_t src, uint32_t dst, bool is_hor) 1564 { 1565 uint32_t fac = 0; 1566 int i = 0; 1567 1568 if (mode == SCALE_NONE) 1569 return 0; 1570 1571 /* 1572 * A workaround to avoid zero div. 1573 */ 1574 if ((dst == 1) || (src == 1)) { 1575 dst = dst + 1; 1576 src = src + 1; 1577 } 1578 1579 if (mode == SCALE_DOWN) { 1580 fac = VOP2_BILI_SCL_DN(src, dst); 1581 for (i = 0; i < 100; i++) { 1582 if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 1583 break; 1584 fac -= 1; 1585 printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 1586 } 1587 } else { 1588 fac = VOP2_COMMON_SCL(src, dst); 1589 for (i = 0; i < 100; i++) { 1590 if (vop3_scale_up_fac_check(src, dst, fac, is_hor)) 1591 break; 1592 fac -= 1; 1593 printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 1594 } 1595 } 1596 1597 return fac; 1598 } 1599 1600 static inline enum scale_mode scl_get_scl_mode(int src, int dst) 1601 { 1602 if (src < dst) 1603 return SCALE_UP; 1604 else if (src > dst) 1605 return SCALE_DOWN; 1606 1607 return SCALE_NONE; 1608 } 1609 1610 static inline int interpolate(int x1, int y1, int x2, int y2, int x) 1611 { 1612 return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 1613 } 1614 1615 static inline bool vop2_win_can_attach_to_vp(struct vop2_win_data *win_data, u8 vp_id) 1616 { 1617 return win_data->possible_vp_mask & BIT(vp_id); 1618 } 1619 1620 static int vop2_vp_find_attachable_win(struct display_state *state, u8 vp_id) 1621 { 1622 struct crtc_state *cstate = &state->crtc_state; 1623 struct vop2 *vop2 = cstate->private; 1624 u32 plane_mask = cstate->crtc->vps[vp_id].plane_mask; 1625 int i = 0; 1626 1627 if (!plane_mask) 1628 return ROCKCHIP_VOP2_PHY_ID_INVALID; 1629 1630 for (i = 0; i < vop2->data->nr_layers; i++) { 1631 if (vop2_win_can_attach_to_vp(&vop2->data->win_data[i], vp_id)) 1632 break; 1633 } 1634 1635 return vop2->data->win_data[i].phys_id; 1636 } 1637 1638 static inline u16 scl_cal_scale(int src, int dst, int shift) 1639 { 1640 return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 1641 } 1642 1643 static inline u16 scl_cal_scale2(int src, int dst) 1644 { 1645 return ((src - 1) << 12) / (dst - 1); 1646 } 1647 1648 static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 1649 { 1650 writel(v, vop2->regs + offset); 1651 vop2->regsbak[offset >> 2] = v; 1652 } 1653 1654 static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 1655 { 1656 return readl(vop2->regs + offset); 1657 } 1658 1659 static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 1660 u32 mask, u32 shift, u32 v, 1661 bool write_mask) 1662 { 1663 if (!mask) 1664 return; 1665 1666 if (write_mask) { 1667 v = ((v & mask) << shift) | (mask << (shift + 16)); 1668 } else { 1669 u32 cached_val = vop2->regsbak[offset >> 2]; 1670 1671 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 1672 vop2->regsbak[offset >> 2] = v; 1673 } 1674 1675 writel(v, vop2->regs + offset); 1676 } 1677 1678 static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 1679 u32 mask, u32 shift, u32 v) 1680 { 1681 u32 val = 0; 1682 1683 val = (v << shift) | (mask << (shift + 16)); 1684 writel(val, grf_base + offset); 1685 } 1686 1687 static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 1688 u32 mask, u32 shift) 1689 { 1690 return (readl(grf_base + offset) >> shift) & mask; 1691 } 1692 1693 static bool is_yuv_output(u32 bus_format) 1694 { 1695 switch (bus_format) { 1696 case MEDIA_BUS_FMT_YUV8_1X24: 1697 case MEDIA_BUS_FMT_YUV10_1X30: 1698 case MEDIA_BUS_FMT_YUYV10_1X20: 1699 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1700 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1701 case MEDIA_BUS_FMT_YUYV8_2X8: 1702 case MEDIA_BUS_FMT_YVYU8_2X8: 1703 case MEDIA_BUS_FMT_UYVY8_2X8: 1704 case MEDIA_BUS_FMT_VYUY8_2X8: 1705 case MEDIA_BUS_FMT_YUYV8_1X16: 1706 case MEDIA_BUS_FMT_YVYU8_1X16: 1707 case MEDIA_BUS_FMT_UYVY8_1X16: 1708 case MEDIA_BUS_FMT_VYUY8_1X16: 1709 return true; 1710 default: 1711 return false; 1712 } 1713 } 1714 1715 static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_encoding, 1716 enum drm_color_range color_range, 1717 int bit_depth) 1718 { 1719 bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; 1720 enum vop_csc_format csc_mode = CSC_BT709L; 1721 1722 1723 switch (color_encoding) { 1724 case DRM_COLOR_YCBCR_BT601: 1725 if (full_range) 1726 csc_mode = CSC_BT601F; 1727 else 1728 csc_mode = CSC_BT601L; 1729 break; 1730 1731 case DRM_COLOR_YCBCR_BT709: 1732 if (full_range) { 1733 csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT709F_13BIT : CSC_BT601F; 1734 if (bit_depth != CSC_13BIT_DEPTH) 1735 printf("Unsupported bt709f at 10bit csc depth, use bt601f instead\n"); 1736 } else { 1737 csc_mode = CSC_BT709L; 1738 } 1739 break; 1740 1741 case DRM_COLOR_YCBCR_BT2020: 1742 if (full_range) { 1743 csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020F_13BIT : CSC_BT601F; 1744 if (bit_depth != CSC_13BIT_DEPTH) 1745 printf("Unsupported bt2020f at 10bit csc depth, use bt601f instead\n"); 1746 } else { 1747 csc_mode = bit_depth == CSC_13BIT_DEPTH ? CSC_BT2020L_13BIT : CSC_BT2020L; 1748 } 1749 break; 1750 1751 default: 1752 printf("Unsuport color_encoding:%d\n", color_encoding); 1753 } 1754 1755 return csc_mode; 1756 } 1757 1758 static bool is_uv_swap(struct display_state *state) 1759 { 1760 struct connector_state *conn_state = &state->conn_state; 1761 u32 bus_format = conn_state->bus_format; 1762 u32 output_mode = conn_state->output_mode; 1763 u32 output_type = conn_state->type; 1764 1765 /* 1766 * FIXME: 1767 * 1768 * There is no media type for YUV444 output, 1769 * so when out_mode is AAAA or P888, assume output is YUV444 on 1770 * yuv format. 1771 * 1772 * From H/W testing, YUV444 mode need a rb swap except eDP. 1773 */ 1774 if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || 1775 bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || 1776 bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || 1777 bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || 1778 ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1779 bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1780 (output_mode == ROCKCHIP_OUT_MODE_AAAA || 1781 output_mode == ROCKCHIP_OUT_MODE_P888) && 1782 !(output_type == DRM_MODE_CONNECTOR_eDP))) 1783 return true; 1784 else 1785 return false; 1786 } 1787 1788 static bool is_rb_swap(struct display_state *state) 1789 { 1790 struct connector_state *conn_state = &state->conn_state; 1791 u32 bus_format = conn_state->bus_format; 1792 1793 /* 1794 * The default component order of serial rgb3x8 formats 1795 * is BGR. So it is needed to enable RB swap. 1796 */ 1797 if (bus_format == MEDIA_BUS_FMT_RGB888_3X8 || 1798 bus_format == MEDIA_BUS_FMT_RGB888_DUMMY_4X8) 1799 return true; 1800 else 1801 return false; 1802 } 1803 1804 static bool is_yc_swap(u32 bus_format) 1805 { 1806 switch (bus_format) { 1807 case MEDIA_BUS_FMT_YUYV8_1X16: 1808 case MEDIA_BUS_FMT_YVYU8_1X16: 1809 case MEDIA_BUS_FMT_YUYV8_2X8: 1810 case MEDIA_BUS_FMT_YVYU8_2X8: 1811 return true; 1812 default: 1813 return false; 1814 } 1815 } 1816 1817 static inline bool is_hot_plug_devices(int output_type) 1818 { 1819 switch (output_type) { 1820 case DRM_MODE_CONNECTOR_HDMIA: 1821 case DRM_MODE_CONNECTOR_HDMIB: 1822 case DRM_MODE_CONNECTOR_TV: 1823 case DRM_MODE_CONNECTOR_DisplayPort: 1824 case DRM_MODE_CONNECTOR_VGA: 1825 case DRM_MODE_CONNECTOR_Unknown: 1826 return true; 1827 default: 1828 return false; 1829 } 1830 } 1831 1832 static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1833 { 1834 int i = 0; 1835 1836 for (i = 0; i < vop2->data->nr_layers; i++) { 1837 if (vop2->data->win_data[i].phys_id == phys_id) 1838 return &vop2->data->win_data[i]; 1839 } 1840 1841 return NULL; 1842 } 1843 1844 static struct vop2_power_domain_data *vop2_find_pd_data_by_id(struct vop2 *vop2, int pd_id) 1845 { 1846 int i = 0; 1847 1848 for (i = 0; i < vop2->data->nr_pd; i++) { 1849 if (vop2->data->pd[i].id == pd_id) 1850 return &vop2->data->pd[i]; 1851 } 1852 1853 return NULL; 1854 } 1855 1856 static void rk3568_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1857 u32 *lut_regs, u32 *lut_val, int lut_len) 1858 { 1859 u32 vp_offset = crtc_id * 0x100; 1860 int i; 1861 1862 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1863 GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 1864 crtc_id, false); 1865 1866 for (i = 0; i < lut_len; i++) 1867 writel(lut_val[i], lut_regs + i); 1868 1869 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1870 EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1871 } 1872 1873 static void rk3588_vop2_load_lut(struct vop2 *vop2, int crtc_id, 1874 u32 *lut_regs, u32 *lut_val, int lut_len) 1875 { 1876 u32 vp_offset = crtc_id * 0x100; 1877 int i; 1878 1879 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1880 GAMMA_AHB_WRITE_SEL_MASK, GAMMA_AHB_WRITE_SEL_SHIFT, 1881 crtc_id, false); 1882 1883 for (i = 0; i < lut_len; i++) 1884 writel(lut_val[i], lut_regs + i); 1885 1886 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1887 EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1888 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1889 EN_MASK, GAMMA_UPDATE_EN_SHIFT, 1, false); 1890 } 1891 1892 static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1893 struct display_state *state) 1894 { 1895 struct connector_state *conn_state = &state->conn_state; 1896 struct crtc_state *cstate = &state->crtc_state; 1897 struct resource gamma_res; 1898 fdt_size_t lut_size; 1899 int i, lut_len, ret = 0; 1900 u32 *lut_regs; 1901 u32 r, g, b; 1902 struct base2_disp_info *disp_info = conn_state->disp_info; 1903 static int gamma_lut_en_num = 1; 1904 1905 if (gamma_lut_en_num > vop2->data->nr_gammas) { 1906 printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 1907 return 0; 1908 } 1909 1910 ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 1911 if (ret) 1912 printf("failed to get gamma lut res\n"); 1913 lut_regs = (u32 *)gamma_res.start; 1914 lut_size = gamma_res.end - gamma_res.start + 1; 1915 if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 1916 printf("failed to get gamma lut register\n"); 1917 return 0; 1918 } 1919 lut_len = lut_size / 4; 1920 if (lut_len != 256 && lut_len != 1024) { 1921 printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 1922 return 0; 1923 } 1924 1925 if (!cstate->lut_val) { 1926 if (!disp_info) 1927 return 0; 1928 1929 if (!disp_info->gamma_lut_data.size) 1930 return 0; 1931 1932 cstate->lut_val = (u32 *)calloc(1, lut_size); 1933 for (i = 0; i < lut_len; i++) { 1934 r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 1935 g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 1936 b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 1937 1938 cstate->lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 1939 } 1940 } 1941 1942 if (vop2->version == VOP_VERSION_RK3568) { 1943 rk3568_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, 1944 cstate->lut_val, lut_len); 1945 gamma_lut_en_num++; 1946 } else { 1947 rk3588_vop2_load_lut(vop2, cstate->crtc_id, lut_regs, 1948 cstate->lut_val, lut_len); 1949 if (cstate->splice_mode) { 1950 rk3588_vop2_load_lut(vop2, cstate->splice_crtc_id, lut_regs, 1951 cstate->lut_val, lut_len); 1952 gamma_lut_en_num++; 1953 } 1954 gamma_lut_en_num++; 1955 } 1956 1957 free(cstate->lut_val); 1958 1959 return 0; 1960 } 1961 1962 static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 1963 struct display_state *state) 1964 { 1965 struct connector_state *conn_state = &state->conn_state; 1966 struct crtc_state *cstate = &state->crtc_state; 1967 int i, cubic_lut_len; 1968 u32 vp_offset = cstate->crtc_id * 0x100; 1969 struct base2_disp_info *disp_info = conn_state->disp_info; 1970 struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 1971 u32 *cubic_lut_addr; 1972 1973 if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 1974 return 0; 1975 1976 if (!disp_info->cubic_lut_data.size) 1977 return 0; 1978 1979 cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 1980 cubic_lut_len = disp_info->cubic_lut_data.size; 1981 1982 for (i = 0; i < cubic_lut_len / 2; i++) { 1983 *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 1984 ((lut->lgreen[2 * i] & 0xfff) << 12) + 1985 ((lut->lblue[2 * i] & 0xff) << 24); 1986 *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 1987 ((lut->lred[2 * i + 1] & 0xfff) << 4) + 1988 ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 1989 ((lut->lblue[2 * i + 1] & 0xf) << 28); 1990 *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 1991 *cubic_lut_addr++ = 0; 1992 } 1993 1994 if (cubic_lut_len % 2) { 1995 *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 1996 ((lut->lgreen[2 * i] & 0xfff) << 12) + 1997 ((lut->lblue[2 * i] & 0xff) << 24); 1998 *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 1999 *cubic_lut_addr++ = 0; 2000 *cubic_lut_addr = 0; 2001 } 2002 2003 vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 2004 get_cubic_lut_buffer(cstate->crtc_id)); 2005 vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 2006 EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 2007 vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 2008 EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 2009 vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 2010 EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 2011 2012 return 0; 2013 } 2014 2015 static void vop2_bcsh_reg_update(struct display_state *state, struct vop2 *vop2, 2016 struct bcsh_state *bcsh_state, int crtc_id) 2017 { 2018 struct crtc_state *cstate = &state->crtc_state; 2019 u32 vp_offset = crtc_id * 0x100; 2020 2021 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 2022 BCSH_CTRL_R2Y_SHIFT, cstate->post_r2y_en, false); 2023 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 2024 BCSH_CTRL_Y2R_SHIFT, cstate->post_y2r_en, false); 2025 2026 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 2027 BCSH_CTRL_R2Y_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 2028 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 2029 BCSH_CTRL_Y2R_CSC_MODE_SHIFT, cstate->post_csc_mode, false); 2030 2031 if (!cstate->bcsh_en) { 2032 vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 2033 BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 2034 return; 2035 } 2036 2037 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2038 BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 2039 bcsh_state->brightness, false); 2040 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2041 BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, bcsh_state->contrast, false); 2042 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2043 BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 2044 bcsh_state->saturation * bcsh_state->contrast / 0x100, false); 2045 vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 2046 BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, bcsh_state->sin_hue, false); 2047 vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 2048 BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, bcsh_state->cos_hue, false); 2049 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 2050 BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 2051 BCSH_OUT_MODE_NORMAL_VIDEO, false); 2052 vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 2053 BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 2054 } 2055 2056 static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 2057 { 2058 struct connector_state *conn_state = &state->conn_state; 2059 struct base_bcsh_info *bcsh_info; 2060 struct crtc_state *cstate = &state->crtc_state; 2061 struct bcsh_state bcsh_state; 2062 int brightness, contrast, saturation, hue, sin_hue, cos_hue; 2063 2064 if (!conn_state->disp_info) 2065 return; 2066 bcsh_info = &conn_state->disp_info->bcsh_info; 2067 if (!bcsh_info) 2068 return; 2069 2070 if (bcsh_info->brightness != 50 || 2071 bcsh_info->contrast != 50 || 2072 bcsh_info->saturation != 50 || bcsh_info->hue != 50) 2073 cstate->bcsh_en = true; 2074 2075 if (cstate->bcsh_en) { 2076 if (!cstate->yuv_overlay) 2077 cstate->post_r2y_en = 1; 2078 if (!is_yuv_output(conn_state->bus_format)) 2079 cstate->post_y2r_en = 1; 2080 } else { 2081 if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 2082 cstate->post_r2y_en = 1; 2083 if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 2084 cstate->post_y2r_en = 1; 2085 } 2086 2087 cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, 2088 conn_state->color_range, 2089 CSC_10BIT_DEPTH); 2090 2091 if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 2092 brightness = interpolate(0, -128, 100, 127, 2093 bcsh_info->brightness); 2094 else 2095 brightness = interpolate(0, -32, 100, 31, 2096 bcsh_info->brightness); 2097 contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 2098 saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 2099 hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 2100 2101 2102 /* 2103 * a:[-30~0): 2104 * sin_hue = 0x100 - sin(a)*256; 2105 * cos_hue = cos(a)*256; 2106 * a:[0~30] 2107 * sin_hue = sin(a)*256; 2108 * cos_hue = cos(a)*256; 2109 */ 2110 sin_hue = fixp_sin32(hue) >> 23; 2111 cos_hue = fixp_cos32(hue) >> 23; 2112 2113 bcsh_state.brightness = brightness; 2114 bcsh_state.contrast = contrast; 2115 bcsh_state.saturation = saturation; 2116 bcsh_state.sin_hue = sin_hue; 2117 bcsh_state.cos_hue = cos_hue; 2118 2119 vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->crtc_id); 2120 if (cstate->splice_mode) 2121 vop2_bcsh_reg_update(state, vop2, &bcsh_state, cstate->splice_crtc_id); 2122 } 2123 2124 static void vop2_setup_dly_for_vp(struct display_state *state, struct vop2 *vop2, int crtc_id) 2125 { 2126 struct connector_state *conn_state = &state->conn_state; 2127 struct drm_display_mode *mode = &conn_state->mode; 2128 struct crtc_state *cstate = &state->crtc_state; 2129 u32 bg_ovl_dly, bg_dly, pre_scan_dly; 2130 u16 hdisplay = mode->crtc_hdisplay; 2131 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2132 2133 bg_ovl_dly = cstate->crtc->vps[crtc_id].bg_ovl_dly; 2134 bg_dly = vop2->data->vp_data[crtc_id].pre_scan_max_dly; 2135 bg_dly -= bg_ovl_dly; 2136 2137 /* 2138 * splice mode: hdisplay must roundup as 4 pixel, 2139 * no splice mode: hdisplay must roundup as 2 pixel. 2140 */ 2141 if (cstate->splice_mode) 2142 pre_scan_dly = bg_dly + (roundup(hdisplay, 4) >> 2) - 1; 2143 else 2144 pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1; 2145 2146 if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 2147 hsync_len = 8; 2148 pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 2149 vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + crtc_id * 4, 2150 BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 2151 vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 2152 } 2153 2154 static void vop3_setup_pipe_dly(struct display_state *state, struct vop2 *vop2, int crtc_id) 2155 { 2156 struct connector_state *conn_state = &state->conn_state; 2157 struct drm_display_mode *mode = &conn_state->mode; 2158 u32 bg_dly, pre_scan_dly; 2159 u16 hdisplay = mode->crtc_hdisplay; 2160 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2161 2162 bg_dly = vop2->data->vp_data[crtc_id].win_dly + 2163 vop2->data->vp_data[crtc_id].layer_mix_dly + 2164 vop2->data->vp_data[crtc_id].hdr_mix_dly; 2165 /* hdisplay must roundup as 2 pixel */ 2166 pre_scan_dly = bg_dly + (roundup(hdisplay, 2) >> 1) - 1; 2167 /** 2168 * pre_scan_hblank minimum value is 8, otherwise the win reset signal will 2169 * lead to first line data be zero. 2170 */ 2171 pre_scan_dly = (pre_scan_dly << 16) | (hsync_len < 8 ? 8 : hsync_len); 2172 vop2_mask_write(vop2, RK3528_OVL_PORT0_BG_MIX_CTRL + crtc_id * 0x100, 2173 BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 2174 vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + (crtc_id * 0x100), pre_scan_dly); 2175 } 2176 2177 static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 2178 { 2179 struct connector_state *conn_state = &state->conn_state; 2180 struct drm_display_mode *mode = &conn_state->mode; 2181 struct crtc_state *cstate = &state->crtc_state; 2182 const struct vop2_data *vop2_data = vop2->data; 2183 const struct vop2_ops *vop2_ops = vop2_data->ops; 2184 u32 vp_offset = (cstate->crtc_id * 0x100); 2185 u16 vtotal = mode->crtc_vtotal; 2186 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 2187 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 2188 u16 hdisplay = mode->crtc_hdisplay; 2189 u16 vdisplay = mode->crtc_vdisplay; 2190 u16 hsize; 2191 u16 vsize; 2192 u16 hact_end, vact_end; 2193 u32 val; 2194 2195 /* 2196 * For RK3576, use the win scale instead of the post scale to configure 2197 * overscan parameters, because the sharp/post scale/split functions are 2198 * mutually exclusice. 2199 */ 2200 if (vop2->version == VOP_VERSION_RK3576) { 2201 hsize = hdisplay; 2202 vsize = vdisplay; 2203 2204 cstate->overscan_by_win_scale = true; 2205 } else { 2206 hsize = hdisplay * (conn_state->overscan.left_margin + 2207 conn_state->overscan.right_margin) / 200; 2208 vsize = vdisplay * (conn_state->overscan.top_margin + 2209 conn_state->overscan.bottom_margin) / 200; 2210 hsize = round_down(hsize, 2); 2211 vsize = round_down(vsize, 2); 2212 2213 hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 2214 vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 2215 } 2216 2217 hact_end = hact_st + hsize; 2218 val = hact_st << 16; 2219 val |= hact_end; 2220 vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 2221 vact_end = vact_st + vsize; 2222 val = vact_st << 16; 2223 val |= vact_end; 2224 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 2225 val = scl_cal_scale2(vdisplay, vsize) << 16; 2226 val |= scl_cal_scale2(hdisplay, hsize); 2227 vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 2228 #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 2229 #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 2230 vop2_mask_write(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 2231 RK3568_VP0_POST_SCALE_MASK, RK3568_VP0_POST_SCALE_SHIFT, 2232 POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 2233 POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize), false); 2234 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 2235 u16 vact_st_f1 = vtotal + vact_st + 1; 2236 u16 vact_end_f1 = vact_st_f1 + vsize; 2237 2238 val = vact_st_f1 << 16 | vact_end_f1; 2239 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 2240 } 2241 2242 if (is_vop3(vop2)) { 2243 vop3_setup_pipe_dly(state, vop2, cstate->crtc_id); 2244 } else { 2245 vop2_setup_dly_for_vp(state, vop2, cstate->crtc_id); 2246 vop2_ops->setup_win_dly(state, cstate->crtc_id); 2247 if (cstate->splice_mode) { 2248 vop2_setup_dly_for_vp(state, vop2, cstate->splice_crtc_id); 2249 vop2_ops->setup_win_dly(state, cstate->splice_crtc_id); 2250 } 2251 } 2252 } 2253 2254 static void vop3_post_acm_config(struct display_state *state, struct vop2 *vop2) 2255 { 2256 struct connector_state *conn_state = &state->conn_state; 2257 struct crtc_state *cstate = &state->crtc_state; 2258 struct acm_data *acm = &conn_state->disp_info->acm_data; 2259 struct drm_display_mode *mode = &conn_state->mode; 2260 u32 vp_offset = (cstate->crtc_id * 0x100); 2261 s16 *lut_y; 2262 s16 *lut_h; 2263 s16 *lut_s; 2264 u32 value; 2265 int i; 2266 2267 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2268 POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 2269 if (!acm->acm_enable) { 2270 writel(0, vop2->regs + RK3528_ACM_CTRL); 2271 return; 2272 } 2273 2274 printf("post acm enable\n"); 2275 2276 writel(1, vop2->regs + RK3528_ACM_FETCH_START); 2277 2278 value = (acm->acm_enable & 0x1) + ((mode->hdisplay & 0xfff) << 8) + 2279 ((mode->vdisplay & 0xfff) << 20); 2280 writel(value, vop2->regs + RK3528_ACM_CTRL); 2281 2282 value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + 2283 ((acm->s_gain << 20) & 0x3ff00000); 2284 writel(value, vop2->regs + RK3528_ACM_DELTA_RANGE); 2285 2286 lut_y = &acm->gain_lut_hy[0]; 2287 lut_h = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH]; 2288 lut_s = &acm->gain_lut_hy[ACM_GAIN_LUT_HY_LENGTH * 2]; 2289 for (i = 0; i < ACM_GAIN_LUT_HY_LENGTH; i++) { 2290 value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 2291 ((lut_s[i] << 16) & 0xff0000); 2292 writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HY_SEG0 + (i << 2)); 2293 } 2294 2295 lut_y = &acm->gain_lut_hs[0]; 2296 lut_h = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH]; 2297 lut_s = &acm->gain_lut_hs[ACM_GAIN_LUT_HS_LENGTH * 2]; 2298 for (i = 0; i < ACM_GAIN_LUT_HS_LENGTH; i++) { 2299 value = (lut_y[i] & 0xff) + ((lut_h[i] << 8) & 0xff00) + 2300 ((lut_s[i] << 16) & 0xff0000); 2301 writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HS_SEG0 + (i << 2)); 2302 } 2303 2304 lut_y = &acm->delta_lut_h[0]; 2305 lut_h = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH]; 2306 lut_s = &acm->delta_lut_h[ACM_DELTA_LUT_H_LENGTH * 2]; 2307 for (i = 0; i < ACM_DELTA_LUT_H_LENGTH; i++) { 2308 value = (lut_y[i] & 0x3ff) + ((lut_h[i] << 12) & 0xff000) + 2309 ((lut_s[i] << 20) & 0x3ff00000); 2310 writel(value, vop2->regs + RK3528_ACM_YHS_DEL_HGAIN_SEG0 + (i << 2)); 2311 } 2312 2313 writel(1, vop2->regs + RK3528_ACM_FETCH_DONE); 2314 } 2315 2316 static void vop3_post_csc_config(struct display_state *state, struct vop2 *vop2) 2317 { 2318 struct connector_state *conn_state = &state->conn_state; 2319 struct crtc_state *cstate = &state->crtc_state; 2320 struct acm_data *acm = &conn_state->disp_info->acm_data; 2321 struct csc_info *csc = &conn_state->disp_info->csc_info; 2322 struct post_csc_coef csc_coef; 2323 bool is_input_yuv = false; 2324 bool is_output_yuv = false; 2325 bool post_r2y_en = false; 2326 bool post_csc_en = false; 2327 u32 vp_offset = (cstate->crtc_id * 0x100); 2328 u32 value; 2329 int range_type; 2330 2331 printf("post csc enable\n"); 2332 2333 if (acm->acm_enable) { 2334 if (!cstate->yuv_overlay) 2335 post_r2y_en = true; 2336 2337 /* do y2r in csc module */ 2338 if (!is_yuv_output(conn_state->bus_format)) 2339 post_csc_en = true; 2340 } else { 2341 if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 2342 post_r2y_en = true; 2343 2344 /* do y2r in csc module */ 2345 if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 2346 post_csc_en = true; 2347 } 2348 2349 if (csc->csc_enable) 2350 post_csc_en = true; 2351 2352 if (cstate->yuv_overlay || post_r2y_en) 2353 is_input_yuv = true; 2354 2355 if (is_yuv_output(conn_state->bus_format)) 2356 is_output_yuv = true; 2357 2358 cstate->post_csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, 2359 conn_state->color_range, 2360 CSC_13BIT_DEPTH); 2361 2362 if (post_csc_en) { 2363 rockchip_calc_post_csc(csc, &csc_coef, cstate->post_csc_mode, is_input_yuv, 2364 is_output_yuv); 2365 2366 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2367 POST_CSC_COE00_MASK, POST_CSC_COE00_SHIFT, 2368 csc_coef.csc_coef00, false); 2369 value = csc_coef.csc_coef01 & 0xffff; 2370 value |= (csc_coef.csc_coef02 << 16) & 0xffff0000; 2371 writel(value, vop2->regs + RK3528_VP0_CSC_COE01_02); 2372 value = csc_coef.csc_coef10 & 0xffff; 2373 value |= (csc_coef.csc_coef11 << 16) & 0xffff0000; 2374 writel(value, vop2->regs + RK3528_VP0_CSC_COE10_11); 2375 value = csc_coef.csc_coef12 & 0xffff; 2376 value |= (csc_coef.csc_coef20 << 16) & 0xffff0000; 2377 writel(value, vop2->regs + RK3528_VP0_CSC_COE12_20); 2378 value = csc_coef.csc_coef21 & 0xffff; 2379 value |= (csc_coef.csc_coef22 << 16) & 0xffff0000; 2380 writel(value, vop2->regs + RK3528_VP0_CSC_COE21_22); 2381 writel(csc_coef.csc_dc0, vop2->regs + RK3528_VP0_CSC_OFFSET0); 2382 writel(csc_coef.csc_dc1, vop2->regs + RK3528_VP0_CSC_OFFSET1); 2383 writel(csc_coef.csc_dc2, vop2->regs + RK3528_VP0_CSC_OFFSET2); 2384 2385 range_type = csc_coef.range_type ? 0 : 1; 2386 range_type <<= is_input_yuv ? 0 : 1; 2387 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2388 POST_CSC_MODE_MASK, POST_CSC_MODE_SHIFT, range_type, false); 2389 } 2390 2391 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2392 POST_R2Y_EN_MASK, POST_R2Y_EN_SHIFT, post_r2y_en ? 1 : 0, false); 2393 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2394 POST_CSC_EN_MASK, POST_CSC_EN_SHIFT, post_csc_en ? 1 : 0, false); 2395 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 2396 POST_R2Y_MODE_MASK, POST_R2Y_MODE_SHIFT, cstate->post_csc_mode, false); 2397 } 2398 2399 static void vop3_post_config(struct display_state *state, struct vop2 *vop2) 2400 { 2401 struct connector_state *conn_state = &state->conn_state; 2402 struct base2_disp_info *disp_info = conn_state->disp_info; 2403 const char *enable_flag; 2404 if (!disp_info) { 2405 printf("disp_info is empty\n"); 2406 return; 2407 } 2408 2409 enable_flag = (const char *)&disp_info->cacm_header; 2410 if (strncasecmp(enable_flag, "CACM", 4)) { 2411 printf("acm and csc is not support\n"); 2412 return; 2413 } 2414 2415 vop3_post_acm_config(state, vop2); 2416 vop3_post_csc_config(state, vop2); 2417 } 2418 2419 static int rk3576_vop2_wait_power_domain_on(struct vop2 *vop2, 2420 struct vop2_power_domain_data *pd_data) 2421 { 2422 int val = 0; 2423 bool is_bisr_en, is_otp_bisr_en; 2424 2425 if (pd_data->id == VOP2_PD_CLUSTER) { 2426 is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0, 2427 EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT); 2428 is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0, 2429 EN_MASK, PD_VOP_CLUSTER_REPAIR_ENA_SHIFT); 2430 if (is_bisr_en && is_otp_bisr_en) 2431 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 2432 val, ((val >> PD_VOP_CLUSTER_PWR_REPAIR_STAT_SHIFT) & 0x1), 2433 50 * 1000); 2434 else 2435 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS, 2436 val, !((val >> PD_VOP_CLUSTER_DWN_STAT) & 0x1), 2437 50 * 1000); 2438 } else { 2439 is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3576_PMU_BISR_PDGEN_CON0, 2440 EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT); 2441 is_otp_bisr_en = vop2_grf_readl(vop2, vop2->grf, RK3576_SYS_GRF_MEMFAULT_STATUS0, 2442 EN_MASK, PD_VOP_ESMART_REPAIR_ENA_SHIFT); 2443 if (is_bisr_en && is_otp_bisr_en) 2444 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 2445 val, ((val >> PD_VOP_ESMART_PWR_REPAIR_STAT_SHIFT) & 0x1), 2446 50 * 1000); 2447 else 2448 return readl_poll_timeout(vop2->sys_pmu + RK3576_PMU_PWR_GATE_STS, 2449 val, !((val >> PD_VOP_ESMART_DWN_STAT) & 0x1), 2450 50 * 1000); 2451 } 2452 } 2453 2454 static int rk3576_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 2455 { 2456 int ret = 0; 2457 2458 if (pd_data->id == VOP2_PD_CLUSTER) 2459 vop2_mask_write(vop2, RK3576_SYS_CLUSTER_PD_CTRL, EN_MASK, 2460 RK3576_CLUSTER_PD_EN_SHIFT, 0, true); 2461 else 2462 vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, EN_MASK, 2463 RK3576_ESMART_PD_EN_SHIFT, 0, true); 2464 ret = rk3576_vop2_wait_power_domain_on(vop2, pd_data); 2465 if (ret) { 2466 printf("wait vop2 power domain timeout\n"); 2467 return ret; 2468 } 2469 2470 return 0; 2471 } 2472 2473 static int rk3588_vop2_wait_power_domain_on(struct vop2 *vop2, 2474 struct vop2_power_domain_data *pd_data) 2475 { 2476 int val = 0; 2477 int shift = 0; 2478 int shift_factor = 0; 2479 bool is_bisr_en = false; 2480 2481 /* 2482 * The order of pd status bits in BISR_STS register 2483 * is different from that in VOP SYS_STS register. 2484 */ 2485 if (pd_data->id == VOP2_PD_DSC_8K || 2486 pd_data->id == VOP2_PD_DSC_4K || 2487 pd_data->id == VOP2_PD_ESMART) 2488 shift_factor = 1; 2489 2490 shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT + generic_ffs(pd_data->id) - 1 - shift_factor; 2491 is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, shift); 2492 if (is_bisr_en) { 2493 shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI + generic_ffs(pd_data->id) - 1 - shift_factor; 2494 2495 return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 2496 ((val >> shift) & 0x1), 50 * 1000); 2497 } else { 2498 shift = RK3588_CLUSTER0_PD_STATUS_SHIFT + generic_ffs(pd_data->id) - 1; 2499 2500 return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 2501 !((val >> shift) & 0x1), 50 * 1000); 2502 } 2503 } 2504 2505 static int rk3588_vop2_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 2506 { 2507 int ret = 0; 2508 2509 vop2_mask_write(vop2, RK3588_SYS_PD_CTRL, EN_MASK, 2510 RK3588_CLUSTER0_PD_EN_SHIFT + generic_ffs(pd_data->id) - 1, 0, false); 2511 ret = rk3588_vop2_wait_power_domain_on(vop2, pd_data); 2512 if (ret) { 2513 printf("wait vop2 power domain timeout\n"); 2514 return ret; 2515 } 2516 2517 return 0; 2518 } 2519 2520 static int vop2_power_domain_on(struct vop2 *vop2, int pd_id) 2521 { 2522 struct vop2_power_domain_data *pd_data; 2523 int ret = 0; 2524 2525 if (!pd_id) 2526 return 0; 2527 2528 pd_data = vop2_find_pd_data_by_id(vop2, pd_id); 2529 if (!pd_data) { 2530 printf("can't find pd_data by id\n"); 2531 return -EINVAL; 2532 } 2533 2534 if (pd_data->parent_id) { 2535 ret = vop2_power_domain_on(vop2, pd_data->parent_id); 2536 if (ret) { 2537 printf("can't open parent power domain\n"); 2538 return -EINVAL; 2539 } 2540 } 2541 2542 /* 2543 * Read VOP internal power domain on/off status. 2544 * We should query BISR_STS register in PMU for 2545 * power up/down status when memory repair is enabled. 2546 * Return value: 1 for power on, 0 for power off; 2547 */ 2548 if (vop2->version == VOP_VERSION_RK3576) 2549 ret = rk3576_vop2_power_domain_on(vop2, pd_data); 2550 else 2551 ret = rk3588_vop2_power_domain_on(vop2, pd_data); 2552 2553 return ret; 2554 } 2555 2556 static void rk3588_vop2_regsbak(struct vop2 *vop2) 2557 { 2558 u32 *base = vop2->regs; 2559 int i = 0; 2560 2561 /* 2562 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 2563 */ 2564 for (i = 0; i < (vop2->reg_len >> 2); i++) 2565 vop2->regsbak[i] = base[i]; 2566 } 2567 2568 static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win_data *win) 2569 { 2570 if (!is_vop3(vop2)) 2571 return false; 2572 2573 if (vop2->esmart_lb_mode == VOP3_ESMART_8K_MODE && 2574 win->phys_id != ROCKCHIP_VOP2_ESMART0) 2575 return true; 2576 else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_MODE && 2577 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) 2578 return true; 2579 else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && 2580 win->phys_id == ROCKCHIP_VOP2_ESMART1) 2581 return true; 2582 else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE && 2583 win->phys_id == ROCKCHIP_VOP2_ESMART3) 2584 return true; 2585 else 2586 return false; 2587 } 2588 2589 static void vop3_init_esmart_scale_engine(struct vop2 *vop2) 2590 { 2591 struct vop2_win_data *win_data; 2592 int i; 2593 u8 scale_engine_num = 0; 2594 2595 /* store plane mask for vop2_fixup_dts */ 2596 for (i = 0; i < vop2->data->nr_layers; i++) { 2597 win_data = &vop2->data->win_data[i]; 2598 if (win_data->type == CLUSTER_LAYER || vop3_ignore_plane(vop2, win_data)) 2599 continue; 2600 2601 win_data->scale_engine_num = scale_engine_num++; 2602 } 2603 } 2604 2605 static int vop3_get_esmart_lb_mode(struct vop2 *vop2) 2606 { 2607 const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map; 2608 int i; 2609 2610 if (!esmart_lb_mode_map) 2611 return vop2->esmart_lb_mode; 2612 2613 for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) { 2614 if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode) 2615 return esmart_lb_mode_map->lb_map_value; 2616 esmart_lb_mode_map++; 2617 } 2618 2619 if (i == vop2->data->esmart_lb_mode_num) 2620 printf("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode); 2621 2622 return vop2->data->esmart_lb_mode_map[0].lb_map_value; 2623 } 2624 2625 static inline void vop2_plane_mask_to_possible_vp_mask(struct display_state *state) 2626 { 2627 struct crtc_state *cstate = &state->crtc_state; 2628 struct vop2 *vop2 = cstate->private; 2629 const struct vop2_data *vop2_data = vop2->data; 2630 struct vop2_win_data *win_data; 2631 u32 plane_mask; 2632 u32 nr_planes; 2633 u32 phys_id; 2634 int i, j; 2635 2636 for (i = 0; i < vop2_data->nr_layers; i++) { 2637 win_data = &vop2_data->win_data[i]; 2638 win_data->possible_vp_mask = 0; 2639 } 2640 2641 for (i = 0; i < vop2_data->nr_vps; i++) { 2642 plane_mask = cstate->crtc->vps[i].plane_mask; 2643 nr_planes = hweight32(plane_mask); 2644 2645 for (j = 0; j < nr_planes; j++) { 2646 phys_id = ffs(plane_mask) - 1; 2647 win_data = vop2_find_win_by_phys_id(vop2, phys_id); 2648 win_data->possible_vp_mask |= BIT(i); 2649 plane_mask &= ~BIT(phys_id); 2650 } 2651 } 2652 } 2653 2654 /* 2655 * The function checks whether the 'rockchip,plane-mask' property assigned 2656 * in DTS is valid. 2657 */ 2658 static bool vop2_plane_mask_check(struct display_state *state) 2659 { 2660 struct crtc_state *cstate = &state->crtc_state; 2661 struct vop2 *vop2 = cstate->private; 2662 struct vop2_win_data *win_data; 2663 u32 assigned_plane_mask = 0, plane_mask = 0; 2664 u32 phys_id; 2665 u32 nr_planes; 2666 u8 primary_plane_id, cursor_plane_id; 2667 int i, j; 2668 2669 /* 2670 * If plane mask is assigned in DTS, then every plane need to be assigned to 2671 * one of all the VPs, and no single plane can be assigned to more than one 2672 * VP. 2673 */ 2674 for (i = 0; i < vop2->data->nr_vps; i++) { 2675 plane_mask = cstate->crtc->vps[i].plane_mask; 2676 primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 2677 cursor_plane_id = cstate->crtc->vps[i].cursor_plane_id; 2678 nr_planes = hweight32(plane_mask); 2679 2680 /* 2681 * If the plane mask and primary plane both are assigned in DTS, the 2682 * primary plane should be included in the plane mask of VPx. 2683 */ 2684 if (plane_mask && primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID && 2685 !(BIT(primary_plane_id) & plane_mask)) { 2686 printf("Invalid primary plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n", 2687 vop2_plane_phys_id_to_string(primary_plane_id), 2688 BIT(primary_plane_id), i, plane_mask); 2689 return false; 2690 } 2691 2692 if (cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID && 2693 cursor_plane_id == primary_plane_id) { 2694 printf("Assigned cursor plane of VP%d [%s] has been assigned as its pirmary plane\n", 2695 i, vop2_plane_phys_id_to_string(cursor_plane_id)); 2696 return false; 2697 } 2698 2699 /* 2700 * If the plane mask and cursor plane both are assigned in DTS, the 2701 * cursor plane should be included in the plane mask of VPx. 2702 */ 2703 if (plane_mask && cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID && 2704 !(BIT(cursor_plane_id) & plane_mask)) { 2705 printf("Invalid cursor plane %s[0x%lx] for VP%d[plane mask: 0x%08x]\n", 2706 vop2_plane_phys_id_to_string(cursor_plane_id), 2707 BIT(cursor_plane_id), i, plane_mask); 2708 return false; 2709 } 2710 2711 /* 2712 * Every plane assigned to the specific VP should follow the constraints 2713 * of default &vop2_win_data.possible_vp_mask. 2714 */ 2715 for (j = 0; j < nr_planes; j++) { 2716 phys_id = ffs(plane_mask) - 1; 2717 win_data = vop2_find_win_by_phys_id(vop2, phys_id); 2718 if (!win_data) { 2719 printf("Invalid plane id %d in VP%d assigned plane mask\n", 2720 phys_id, i); 2721 return false; 2722 } 2723 2724 if (!(vop2_win_can_attach_to_vp(win_data, i))) { 2725 printf("%s can not attach to VP%d\n", 2726 vop2_plane_phys_id_to_string(phys_id), i); 2727 return false; 2728 } 2729 2730 plane_mask &= ~BIT(phys_id); 2731 } 2732 2733 if (assigned_plane_mask & cstate->crtc->vps[i].plane_mask) { 2734 printf("the same window can't be assigned to two vp\n"); 2735 return false; 2736 } 2737 assigned_plane_mask |= cstate->crtc->vps[i].plane_mask; 2738 } 2739 2740 if (assigned_plane_mask != vop2->data->plane_mask_base) { 2741 printf("all windows should be assigned, full plane mask: [0x%08x], current plane mask: [0x%08x]\n", 2742 vop2->data->plane_mask_base, assigned_plane_mask); 2743 return false; 2744 } 2745 2746 /* 2747 * If plane_mask assigned in DTS is valid, then convert it to &vop2_win_data.possible_vp_mask 2748 * and replace the default one with it. 2749 */ 2750 vop2_plane_mask_to_possible_vp_mask(state); 2751 2752 return true; 2753 } 2754 2755 static void rockchip_cursor_plane_assign(struct display_state *state, u8 vp_id) 2756 { 2757 struct crtc_state *cstate = &state->crtc_state; 2758 struct vop2 *vop2 = cstate->private; 2759 struct vop2_win_data *win_data; 2760 int i, j; 2761 2762 if (cstate->crtc->vps[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { 2763 win_data = vop2_find_win_by_phys_id(vop2, cstate->crtc->vps[vp_id].cursor_plane_id); 2764 if (win_data) { 2765 if (vop2_win_can_attach_to_vp(win_data, vp_id)) 2766 vop2->vp_plane_mask[vp_id].cursor_plane_id = 2767 cstate->crtc->vps[vp_id].cursor_plane_id; 2768 return; 2769 } 2770 } 2771 2772 for (i = 0; i < vop2->data->nr_layers; i++) { 2773 win_data = &vop2->data->win_data[i]; 2774 2775 if (win_data->plane_type != VOP2_PLANE_TYPE_CURSOR) 2776 continue; 2777 2778 if (!vop2_win_can_attach_to_vp(win_data, vp_id)) 2779 continue; 2780 2781 for (j = 0; j < vop2->data->nr_vps; j++) { 2782 if (win_data->phys_id == vop2->vp_plane_mask[j].cursor_plane_id) 2783 break; 2784 } 2785 2786 /* The win has been used as the cursor plane for other VPs */ 2787 if (j < vop2->data->nr_vps) 2788 continue; 2789 2790 vop2->vp_plane_mask[vp_id].cursor_plane_id = win_data->phys_id; 2791 return; 2792 } 2793 2794 vop2->vp_plane_mask[vp_id].cursor_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID; 2795 } 2796 2797 static void vop2_plane_mask_assign(struct display_state *state) 2798 { 2799 struct crtc_state *cstate = &state->crtc_state; 2800 struct vop2 *vop2 = cstate->private; 2801 struct vop2_vp_plane_mask *plane_mask; 2802 struct vop2_win_data *win_data; 2803 u32 nr_planes = 0; 2804 int active_vp_num = 0; 2805 int main_vp_index = -1; 2806 int layer_phy_id = 0; 2807 int i, j, k; 2808 2809 printf("Assign default plane mask\n"); 2810 2811 /* 2812 * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in 2813 * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched 2814 * between different CRTCs flexibly and the userspace do not need 2815 * the plane_mask to restrict the binding between the crtc and plane. 2816 * We just find a expected plane for logo display. 2817 */ 2818 if (is_vop3(vop2)) { 2819 for (i = 0; i < vop2->data->nr_vps; i++) { 2820 /* 2821 * mark the primary plane id of the VP that is 2822 * not enabled to invalid. 2823 */ 2824 vop2->vp_plane_mask[i].primary_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID; 2825 if (!cstate->crtc->vps[i].enable) 2826 continue; 2827 2828 rockchip_cursor_plane_assign(state, i); 2829 for (j = 0; j < vop2->data->nr_layers; j++) { 2830 win_data = &vop2->data->win_data[j]; 2831 2832 if (win_data->plane_type != VOP2_PLANE_TYPE_PRIMARY) 2833 continue; 2834 2835 if (!vop2_win_can_attach_to_vp(win_data, i)) 2836 continue; 2837 2838 for (k = 0; k < vop2->data->nr_vps; k++) { 2839 if (win_data->phys_id == vop2->vp_plane_mask[k].primary_plane_id) 2840 break; 2841 } 2842 2843 /* The win has been used as the primary plane for other VPs */ 2844 if (k < vop2->data->nr_vps) 2845 continue; 2846 2847 vop2->vp_plane_mask[i].attached_layers_nr = 1; 2848 vop2->vp_plane_mask[i].primary_plane_id = win_data->phys_id; 2849 vop2->vp_plane_mask[i].attached_layers[0] = win_data->phys_id; 2850 vop2->vp_plane_mask[i].plane_mask |= BIT(win_data->phys_id); 2851 active_vp_num++; 2852 break; 2853 } 2854 2855 if (vop2->vp_plane_mask[i].primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID) 2856 printf("ERROR: No primary plane find for video_port%d\n", i); 2857 } 2858 printf("VOP have %d active VP\n", active_vp_num); 2859 } else { 2860 for (i = 0; i < vop2->data->nr_vps; i++) { 2861 /* 2862 * mark the primary plane id of the VP that is 2863 * not enabled to invalid. 2864 */ 2865 vop2->vp_plane_mask[i].primary_plane_id = ROCKCHIP_VOP2_PHY_ID_INVALID; 2866 if (cstate->crtc->vps[i].enable) { 2867 rockchip_cursor_plane_assign(state, i); 2868 active_vp_num++; 2869 } 2870 } 2871 printf("VOP have %d active VP\n", active_vp_num); 2872 2873 if (soc_is_rk3566() && active_vp_num > 2) 2874 printf("ERROR: rk3566 only support 2 display output!!\n"); 2875 plane_mask = vop2->data->plane_mask; 2876 plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 2877 2878 /* 2879 * For RK3566, the main planes should be enabled before the mirror planes. 2880 * The devices that support hot plug may be disconnected initially, so we 2881 * assign the main planes to the first device that does not support hot 2882 * plug, in order to ensure that the mirror planes are not enabled first. 2883 */ 2884 if (soc_is_rk3566()) { 2885 for (i = 0; i < vop2->data->nr_vps; i++) { 2886 if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 2887 /* the first store main display plane mask */ 2888 vop2->vp_plane_mask[i] = plane_mask[0]; 2889 main_vp_index = i; 2890 break; 2891 } 2892 } 2893 2894 /* if no find unplug devices, use vp0 as main display */ 2895 if (main_vp_index < 0) { 2896 main_vp_index = 0; 2897 vop2->vp_plane_mask[0] = plane_mask[0]; 2898 } 2899 2900 /* plane_mask[0] store main display, so we from plane_mask[1] */ 2901 j = 1; 2902 } else { 2903 /* 2904 * For the platforms except RK3566, we assign the plane mask of 2905 * VPx according to the &vop2_data.plane_mask[active_vp_num][x]. 2906 */ 2907 j = 0; 2908 } 2909 2910 /* init other display except main display */ 2911 for (i = 0; i < vop2->data->nr_vps; i++) { 2912 /* main display or no connect devices */ 2913 if (i == main_vp_index || !cstate->crtc->vps[i].enable) 2914 continue; 2915 vop2->vp_plane_mask[i] = plane_mask[j++]; 2916 /* 2917 * For rk3588, the main window should attach to the VP0 while 2918 * the splice window should attach to the VP1 when the display 2919 * mode is over 4k. 2920 * If only one VP is enabled and the plane mask is not assigned 2921 * in DTS, all main windows will be assigned to the enabled VPx, 2922 * and all splice windows will be assigned to the VPx+1, in order 2923 * to ensure that the splice mode work well. 2924 */ 2925 if (vop2->version == VOP_VERSION_RK3588 && active_vp_num == 1) 2926 vop2->vp_plane_mask[(i + 1) % vop2->data->nr_vps] = plane_mask[j++]; 2927 } 2928 2929 /* store plane mask for vop2_fixup_dts */ 2930 for (i = 0; i < vop2->data->nr_vps; i++) { 2931 nr_planes = vop2->vp_plane_mask[i].attached_layers_nr; 2932 for (j = 0; j < nr_planes; j++) { 2933 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 2934 vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 2935 } 2936 } 2937 } 2938 } 2939 2940 static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 2941 { 2942 struct crtc_state *cstate = &state->crtc_state; 2943 const struct vop2_data *vop2_data = vop2->data; 2944 const struct vop2_ops *vop2_ops = vop2_data->ops; 2945 u32 nr_planes = 0; 2946 u32 plane_mask; 2947 u8 primary_plane_id; 2948 const u8 *tmp; 2949 int i, j; 2950 2951 if (vop2->global_init) 2952 return; 2953 2954 /* OTP must enable at the first time, otherwise mirror layer register is error */ 2955 if (soc_is_rk3566()) 2956 vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 2957 OTP_WIN_EN_SHIFT, 1, false); 2958 2959 /* The plane mask is assigned in DTS */ 2960 if (cstate->crtc->assign_plane) { 2961 /* check whether plane mask and primary plane are valid */ 2962 if (vop2_plane_mask_check(state)) { 2963 for (i = 0; i < vop2->data->nr_vps; i++) { 2964 plane_mask = cstate->crtc->vps[i].plane_mask; 2965 nr_planes = hweight32(plane_mask); /* use bitmap to store plane mask */ 2966 vop2->vp_plane_mask[i].attached_layers_nr = nr_planes; 2967 primary_plane_id = cstate->crtc->vps[i].primary_plane_id; 2968 /* 2969 * If the primary plane of specific VP is not assigned 2970 * in DTS, find a proper primary plane according to the 2971 * &vop2_win_data.possible_vp_mask. 2972 */ 2973 if (primary_plane_id == ROCKCHIP_VOP2_PHY_ID_INVALID) 2974 primary_plane_id = vop2_vp_find_attachable_win(state, i); 2975 vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 2976 vop2->vp_plane_mask[i].plane_mask = plane_mask; 2977 2978 /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id] */ 2979 for (j = 0; j < nr_planes; j++) { 2980 vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 2981 plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 2982 } 2983 } 2984 } else { 2985 vop2_plane_mask_assign(state); 2986 } 2987 } else { 2988 /* 2989 * If no plane mask assignment, plane mask and primary plane will be 2990 * assigned automatically. 2991 */ 2992 vop2_plane_mask_assign(state); 2993 } 2994 2995 if (vop2->version == VOP_VERSION_RK3588) 2996 rk3588_vop2_regsbak(vop2); 2997 else 2998 memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 2999 3000 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 3001 OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 3002 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 3003 IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 3004 3005 for (i = 0; i < vop2->data->nr_vps; i++) { 3006 printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 3007 for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 3008 printf("%s ", 3009 vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].attached_layers[j])); 3010 printf("], primary plane: %s\n", 3011 vop2_plane_phys_id_to_string(vop2->vp_plane_mask[i].primary_plane_id)); 3012 } 3013 3014 vop2_ops->setup_overlay(state); 3015 3016 if (is_vop3(vop2)) { 3017 /* 3018 * you can rewrite at dts vop node: 3019 * 3020 * VOP3_ESMART_8K_MODE = 0, 3021 * VOP3_ESMART_4K_4K_MODE = 1, 3022 * VOP3_ESMART_4K_2K_2K_MODE = 2, 3023 * VOP3_ESMART_2K_2K_2K_2K_MODE = 3, 3024 * 3025 * &vop { 3026 * esmart_lb_mode = /bits/ 8 <2>; 3027 * }; 3028 */ 3029 tmp = dev_read_u8_array_ptr(cstate->dev, "esmart_lb_mode", 1); 3030 if (tmp) 3031 vop2->esmart_lb_mode = *tmp; 3032 else 3033 vop2->esmart_lb_mode = vop2->data->esmart_lb_mode; 3034 if (vop2->version == VOP_VERSION_RK3576) 3035 vop2_mask_write(vop2, RK3576_SYS_ESMART_PD_CTRL, 3036 RK3576_ESMART_LB_MODE_SEL_MASK, 3037 RK3576_ESMART_LB_MODE_SEL_SHIFT, 3038 vop3_get_esmart_lb_mode(vop2), true); 3039 else 3040 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 3041 ESMART_LB_MODE_SEL_MASK, 3042 ESMART_LB_MODE_SEL_SHIFT, 3043 vop3_get_esmart_lb_mode(vop2), false); 3044 3045 vop3_init_esmart_scale_engine(vop2); 3046 3047 if (vop2->version == VOP_VERSION_RK3576) 3048 vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK, 3049 RK3576_DSP_VS_T_SEL_SHIFT, 0, true); 3050 else 3051 vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, EN_MASK, 3052 DSP_VS_T_SEL_SHIFT, 0, false); 3053 3054 /* 3055 * This is a workaround for RK3528/RK3562/RK3576: 3056 * 3057 * The aclk pre auto gating function may disable the aclk 3058 * in some unexpected cases, which detected by hardware 3059 * automatically. 3060 * 3061 * For example, if the above function is enabled, the post 3062 * scale function will be affected, resulting in abnormal 3063 * display. 3064 */ 3065 if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562 || 3066 vop2->version == VOP_VERSION_RK3576) 3067 vop2_mask_write(vop2, RK3568_AUTO_GATING_CTRL, EN_MASK, 3068 ACLK_PRE_AUTO_GATING_EN_SHIFT, 0, false); 3069 } 3070 3071 if (vop2->version == VOP_VERSION_RK3568) 3072 vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 3073 3074 if (vop2->version == VOP_VERSION_RK3576) { 3075 vop2->merge_irq = ofnode_read_bool(cstate->node, "rockchip,vop-merge-irq"); 3076 3077 /* Default use rkiommu 2.0 for axi0 */ 3078 vop2_mask_write(vop2, RK3576_SYS_MMU_CTRL, EN_MASK, RKMMU_V2_EN_SHIFT, 1, true); 3079 3080 /* Init frc2.0 config */ 3081 vop2_writel(vop2, 0xca0, 0xc8); 3082 vop2_writel(vop2, 0xca4, 0x01000100); 3083 vop2_writel(vop2, 0xca8, 0x03ff0100); 3084 vop2_writel(vop2, 0xda0, 0xc8); 3085 vop2_writel(vop2, 0xda4, 0x01000100); 3086 vop2_writel(vop2, 0xda8, 0x03ff0100); 3087 3088 if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true) 3089 vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, EN_MASK, 3090 VP_INTR_MERGE_EN_SHIFT, 1, true); 3091 3092 /* Set reg done every field for interlace */ 3093 vop2_mask_write(vop2, RK3576_SYS_PORT_CTRL, INTERLACE_FRM_REG_DONE_MASK, 3094 INTERLACE_FRM_REG_DONE_SHIFT, 0, false); 3095 } 3096 3097 vop2->global_init = true; 3098 } 3099 3100 static void rockchip_vop2_sharp_init(struct vop2 *vop2, struct display_state *state) 3101 { 3102 struct crtc_state *cstate = &state->crtc_state; 3103 const struct vop2_data *vop2_data = vop2->data; 3104 const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id]; 3105 struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id]; 3106 struct resource sharp_regs; 3107 int ret; 3108 3109 if (!(vp_data->feature & VOP_FEATURE_POST_SHARP) || !vp->sharp_en) 3110 return; 3111 3112 ret = ofnode_read_resource_byname(cstate->node, "sharp_regs", &sharp_regs); 3113 if (ret) { 3114 printf("failed to get sharp regs\n"); 3115 return; 3116 } 3117 vop2->sharp_res = (void *)sharp_regs.start; 3118 3119 /* 3120 * After vop initialization, keep sw_sharp_enable always on. 3121 * Only enable/disable sharp submodule to avoid black screen. 3122 */ 3123 writel(true << SW_SHARP_ENABLE_SHIFT, vop2->sharp_res + RK3576_SHARP_CTRL); 3124 } 3125 3126 static void rockchip_vop2_acm_init(struct vop2 *vop2, struct display_state *state) 3127 { 3128 struct crtc_state *cstate = &state->crtc_state; 3129 const struct vop2_data *vop2_data = vop2->data; 3130 const struct vop2_vp_data *vp_data = &vop2_data->vp_data[cstate->crtc_id]; 3131 struct resource acm_regs; 3132 u32 *acm_reg_base; 3133 u32 vp_offset = (cstate->crtc_id * 0x100); 3134 int ret; 3135 3136 if (!(vp_data->feature & VOP_FEATURE_POST_ACM)) 3137 return; 3138 3139 ret = ofnode_read_resource_byname(cstate->node, "acm_regs", &acm_regs); 3140 if (ret) { 3141 printf("failed to get acm regs\n"); 3142 return; 3143 } 3144 acm_reg_base = (u32 *)acm_regs.start; 3145 3146 /* 3147 * Black screen is displayed when acm bypass switched 3148 * between enable and disable. Therefore, disable acm 3149 * bypass by default after system boot. 3150 */ 3151 vop2_mask_write(vop2, RK3528_VP0_ACM_CTRL + vp_offset, 3152 POST_ACM_BYPASS_EN_MASK, POST_ACM_BYPASS_EN_SHIFT, 0, false); 3153 3154 writel(0, acm_reg_base + 0); 3155 } 3156 3157 static int rockchip_vop2_of_get_gamma_lut(struct display_state *state, 3158 struct device_node *dsp_lut_node) 3159 { 3160 struct crtc_state *cstate = &state->crtc_state; 3161 struct resource gamma_res; 3162 fdt_size_t lut_size; 3163 u32 *lut_regs; 3164 u32 *lut; 3165 u32 r, g, b; 3166 int lut_len; 3167 int length; 3168 int i, j; 3169 int ret = 0; 3170 3171 of_get_property(dsp_lut_node, "gamma-lut", &length); 3172 if (!length) 3173 return -EINVAL; 3174 3175 ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 3176 if (ret) 3177 printf("failed to get gamma lut res\n"); 3178 lut_regs = (u32 *)gamma_res.start; 3179 lut_size = gamma_res.end - gamma_res.start + 1; 3180 if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 3181 printf("failed to get gamma lut register\n"); 3182 return -EINVAL; 3183 } 3184 lut_len = lut_size / 4; 3185 3186 cstate->lut_val = (u32 *)calloc(1, lut_size); 3187 if (!cstate->lut_val) 3188 return -ENOMEM; 3189 3190 length >>= 2; 3191 if (length != lut_len) { 3192 lut = (u32 *)calloc(1, lut_len); 3193 if (!lut) { 3194 free(cstate->lut_val); 3195 return -ENOMEM; 3196 } 3197 3198 ret = of_read_u32_array(dsp_lut_node, "gamma-lut", lut, length); 3199 if (ret) { 3200 printf("Failed to load gamma-lut for vp%d\n", cstate->crtc_id); 3201 free(cstate->lut_val); 3202 free(lut); 3203 return -EINVAL; 3204 } 3205 3206 /* 3207 * In order to achieve the same gamma correction effect in different 3208 * platforms, the following conversion helps to translate from 8bit 3209 * gamma table with 256 parameters to 10bit gamma with 1024 parameters. 3210 */ 3211 for (i = 0; i < lut_len; i++) { 3212 j = i * length / lut_len; 3213 r = lut[j] / length / length * lut_len / length; 3214 g = lut[j] / length % length * lut_len / length; 3215 b = lut[j] % length * lut_len / length; 3216 3217 cstate->lut_val[i] = r * lut_len * lut_len + g * lut_len + b; 3218 } 3219 free(lut); 3220 } else { 3221 of_read_u32_array(dsp_lut_node, "gamma-lut", cstate->lut_val, lut_len); 3222 } 3223 3224 return 0; 3225 } 3226 3227 static void rockchip_vop2_of_get_dsp_lut(struct vop2 *vop2, struct display_state *state) 3228 { 3229 struct crtc_state *cstate = &state->crtc_state; 3230 struct device_node *dsp_lut_node; 3231 int phandle; 3232 int ret = 0; 3233 3234 phandle = ofnode_read_u32_default(np_to_ofnode(cstate->port_node), "dsp-lut", -1); 3235 if (phandle < 0) 3236 return; 3237 3238 dsp_lut_node = of_find_node_by_phandle(phandle); 3239 if (!dsp_lut_node) 3240 return; 3241 3242 ret = rockchip_vop2_of_get_gamma_lut(state, dsp_lut_node); 3243 if (ret) 3244 printf("failed to load vp%d gamma-lut from dts\n", cstate->crtc_id); 3245 } 3246 3247 static int vop2_initial(struct vop2 *vop2, struct display_state *state) 3248 { 3249 rockchip_vop2_of_get_dsp_lut(vop2, state); 3250 3251 rockchip_vop2_gamma_lut_init(vop2, state); 3252 rockchip_vop2_cubic_lut_init(vop2, state); 3253 rockchip_vop2_sharp_init(vop2, state); 3254 rockchip_vop2_acm_init(vop2, state); 3255 3256 return 0; 3257 } 3258 3259 /* 3260 * VOP2 have multi video ports. 3261 * video port ------- crtc 3262 */ 3263 static int rockchip_vop2_preinit(struct display_state *state) 3264 { 3265 struct crtc_state *cstate = &state->crtc_state; 3266 const struct vop2_data *vop2_data = cstate->crtc->data; 3267 struct regmap *map; 3268 char dclk_name[16]; 3269 int ret; 3270 3271 if (!rockchip_vop2) { 3272 rockchip_vop2 = calloc(1, sizeof(struct vop2)); 3273 if (!rockchip_vop2) 3274 return -ENOMEM; 3275 memset(rockchip_vop2, 0, sizeof(struct vop2)); 3276 rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 3277 rockchip_vop2->reg_len = RK3568_MAX_REG; 3278 #ifdef CONFIG_SPL_BUILD 3279 rockchip_vop2->regs = (void *)RK3528_VOP_BASE; 3280 #else 3281 rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 3282 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf"); 3283 rockchip_vop2->grf = regmap_get_range(map, 0); 3284 if (rockchip_vop2->grf <= 0) 3285 printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 3286 #endif 3287 rockchip_vop2->version = vop2_data->version; 3288 rockchip_vop2->data = vop2_data; 3289 if (rockchip_vop2->version == VOP_VERSION_RK3588) { 3290 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf"); 3291 rockchip_vop2->vop_grf = regmap_get_range(map, 0); 3292 if (rockchip_vop2->vop_grf <= 0) 3293 printf("%s: Get syscon vop_grf failed (ret=%p)\n", 3294 __func__, rockchip_vop2->vop_grf); 3295 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); 3296 rockchip_vop2->vo1_grf = regmap_get_range(map, 0); 3297 if (rockchip_vop2->vo1_grf <= 0) 3298 printf("%s: Get syscon vo1_grf failed (ret=%p)\n", 3299 __func__, rockchip_vop2->vo1_grf); 3300 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu"); 3301 rockchip_vop2->sys_pmu = regmap_get_range(map, 0); 3302 if (rockchip_vop2->sys_pmu <= 0) 3303 printf("%s: Get syscon sys_pmu failed (ret=%p)\n", 3304 __func__, rockchip_vop2->sys_pmu); 3305 } else if (rockchip_vop2->version == VOP_VERSION_RK3576) { 3306 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,ioc-grf"); 3307 rockchip_vop2->ioc_grf = regmap_get_range(map, 0); 3308 if (rockchip_vop2->ioc_grf <= 0) 3309 printf("%s: Get syscon ioc_grf failed (ret=%p)\n", 3310 __func__, rockchip_vop2->ioc_grf); 3311 map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu"); 3312 rockchip_vop2->sys_pmu = regmap_get_range(map, 0); 3313 if (rockchip_vop2->sys_pmu <= 0) 3314 printf("%s: Get syscon sys_pmu failed (ret=%p)\n", 3315 __func__, rockchip_vop2->sys_pmu); 3316 } 3317 } 3318 3319 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 3320 if (dev_read_stringlist_search(cstate->dev, "reset-names", dclk_name) > 0) { 3321 ret = reset_get_by_name(cstate->dev, dclk_name, &cstate->dclk_rst); 3322 if (ret < 0) { 3323 printf("%s: failed to get dclk reset: %d\n", __func__, ret); 3324 cstate->dclk_rst.dev = NULL; 3325 } 3326 } 3327 3328 cstate->private = rockchip_vop2; 3329 cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 3330 cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 3331 3332 vop2_global_initial(rockchip_vop2, state); 3333 3334 return 0; 3335 } 3336 3337 /* 3338 * calc the dclk on rk3588 3339 * the available div of dclk is 1, 2, 4 3340 * 3341 */ 3342 static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 3343 { 3344 if (child_clk * 4 <= max_dclk) 3345 return child_clk * 4; 3346 else if (child_clk * 2 <= max_dclk) 3347 return child_clk * 2; 3348 else if (child_clk <= max_dclk) 3349 return child_clk; 3350 else 3351 return 0; 3352 } 3353 3354 /* 3355 * 4 pixclk/cycle on rk3588 3356 * RGB/eDP/HDMI: if_pixclk >= dclk_core 3357 * DP: dp_pixclk = dclk_out <= dclk_core 3358 * DSI: mipi_pixclk <= dclk_out <= dclk_core 3359 */ 3360 static unsigned long vop2_calc_cru_cfg(struct display_state *state, 3361 int *dclk_core_div, int *dclk_out_div, 3362 int *if_pixclk_div, int *if_dclk_div) 3363 { 3364 struct crtc_state *cstate = &state->crtc_state; 3365 struct connector_state *conn_state = &state->conn_state; 3366 struct drm_display_mode *mode = &conn_state->mode; 3367 struct vop2 *vop2 = cstate->private; 3368 unsigned long v_pixclk = mode->crtc_clock * 1000L; 3369 unsigned long dclk_core_rate = v_pixclk >> 2; 3370 unsigned long dclk_rate = v_pixclk; 3371 unsigned long dclk_out_rate; 3372 u64 if_dclk_rate; 3373 u64 if_pixclk_rate; 3374 int output_type = conn_state->type; 3375 int output_mode = conn_state->output_mode; 3376 int K = 1; 3377 3378 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE && 3379 output_mode == ROCKCHIP_OUT_MODE_YUV420) { 3380 printf("Dual channel and YUV420 can't work together\n"); 3381 return -EINVAL; 3382 } 3383 3384 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 3385 output_mode == ROCKCHIP_OUT_MODE_YUV420) 3386 K = 2; 3387 3388 if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 3389 /* 3390 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 3391 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 3392 */ 3393 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 3394 output_mode == ROCKCHIP_OUT_MODE_YUV420) { 3395 dclk_rate = dclk_rate >> 1; 3396 K = 2; 3397 } 3398 if (cstate->dsc_enable) { 3399 if_pixclk_rate = cstate->dsc_cds_clk_rate << 1; 3400 if_dclk_rate = cstate->dsc_cds_clk_rate; 3401 } else { 3402 if_pixclk_rate = (dclk_core_rate << 1) / K; 3403 if_dclk_rate = dclk_core_rate / K; 3404 } 3405 3406 if (v_pixclk > VOP2_MAX_DCLK_RATE * 1000L) 3407 dclk_rate = vop2_calc_dclk(dclk_core_rate, 3408 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L); 3409 3410 if (!dclk_rate) { 3411 printf("HDMI if_pixclk_rate out of range(max_dclk: %ld HZ, dclk_core: %lld HZ)\n", 3412 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, if_pixclk_rate); 3413 return -EINVAL; 3414 } 3415 *if_pixclk_div = dclk_rate / if_pixclk_rate; 3416 *if_dclk_div = dclk_rate / if_dclk_rate; 3417 *dclk_core_div = dclk_rate / dclk_core_rate; 3418 /* For HDMI DSC mode, the dclk_out_div should be the same as dclk_core_div */ 3419 if (cstate->dsc_enable) 3420 *dclk_out_div = *dclk_core_div; 3421 printf("dclk:%lu,if_pixclk_div;%d,if_dclk_div:%d\n", 3422 dclk_rate, *if_pixclk_div, *if_dclk_div); 3423 } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 3424 /* edp_pixclk = edp_dclk > dclk_core */ 3425 if_pixclk_rate = v_pixclk / K; 3426 if_dclk_rate = v_pixclk / K; 3427 dclk_rate = if_pixclk_rate * K; 3428 *dclk_core_div = dclk_rate / dclk_core_rate; 3429 *if_pixclk_div = dclk_rate / if_pixclk_rate; 3430 *if_dclk_div = *if_pixclk_div; 3431 } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 3432 dclk_out_rate = v_pixclk >> 2; 3433 dclk_out_rate = dclk_out_rate / K; 3434 3435 dclk_rate = vop2_calc_dclk(dclk_out_rate, 3436 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L); 3437 if (!dclk_rate) { 3438 printf("DP dclk_core out of range(max_dclk: %ld HZ, dclk_core: %ld HZ)\n", 3439 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_core_rate); 3440 return -EINVAL; 3441 } 3442 *dclk_out_div = dclk_rate / dclk_out_rate; 3443 *dclk_core_div = dclk_rate / dclk_core_rate; 3444 } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 3445 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3446 K = 2; 3447 if (cstate->dsc_enable) 3448 /* dsc output is 96bit, dsi input is 192 bit */ 3449 if_pixclk_rate = cstate->dsc_cds_clk_rate >> 1; 3450 else 3451 if_pixclk_rate = dclk_core_rate / K; 3452 /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 3453 dclk_out_rate = dclk_core_rate / K; 3454 /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 3455 dclk_rate = vop2_calc_dclk(dclk_out_rate, 3456 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L); 3457 if (!dclk_rate) { 3458 printf("MIPI dclk out of range(max_dclk: %ld HZ, dclk_rate: %ld HZ)\n", 3459 vop2->data->vp_data[cstate->crtc_id].max_dclk * 1000L, dclk_rate); 3460 return -EINVAL; 3461 } 3462 3463 if (cstate->dsc_enable) 3464 dclk_rate /= cstate->dsc_slice_num; 3465 3466 *dclk_out_div = dclk_rate / dclk_out_rate; 3467 *dclk_core_div = dclk_rate / dclk_core_rate; 3468 *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 3469 if (cstate->dsc_enable) 3470 *if_pixclk_div = dclk_out_rate / if_pixclk_rate; 3471 3472 } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 3473 dclk_rate = v_pixclk; 3474 *dclk_core_div = dclk_rate / dclk_core_rate; 3475 } 3476 3477 *if_pixclk_div = ilog2(*if_pixclk_div); 3478 *if_dclk_div = ilog2(*if_dclk_div); 3479 *dclk_core_div = ilog2(*dclk_core_div); 3480 /* 3481 * For RK3588, dclk_out is designed for DP, MIPI(both DSC and non-DSC mode) 3482 * and HDMI in DSC mode. 3483 */ 3484 if (output_type == DRM_MODE_CONNECTOR_DisplayPort || 3485 output_type == DRM_MODE_CONNECTOR_DSI || 3486 (output_type == DRM_MODE_CONNECTOR_HDMIA && cstate->dsc_enable)) 3487 *dclk_out_div = ilog2(*dclk_out_div); 3488 else 3489 *dclk_out_div = 0; 3490 3491 return dclk_rate; 3492 } 3493 3494 static int vop2_calc_dsc_clk(struct display_state *state) 3495 { 3496 struct connector_state *conn_state = &state->conn_state; 3497 struct drm_display_mode *mode = &conn_state->mode; 3498 struct crtc_state *cstate = &state->crtc_state; 3499 u64 v_pixclk = mode->crtc_clock * 1000LL; /* video timing pixclk */ 3500 u8 k = 1; 3501 3502 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3503 k = 2; 3504 3505 cstate->dsc_txp_clk_rate = v_pixclk; 3506 do_div(cstate->dsc_txp_clk_rate, (cstate->dsc_pixel_num * k)); 3507 3508 cstate->dsc_pxl_clk_rate = v_pixclk; 3509 do_div(cstate->dsc_pxl_clk_rate, (cstate->dsc_slice_num * k)); 3510 3511 /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 3512 * cds_dat_width = 96; 3513 * bits_per_pixel = [8-12]; 3514 * As cds clk is div from txp clk and only support 1/2/4 div, 3515 * so when txp_clk is equal to v_pixclk, we set dsc_cds = crtc_clock / 4, 3516 * otherwise dsc_cds = crtc_clock / 8; 3517 */ 3518 cstate->dsc_cds_clk_rate = v_pixclk / (cstate->dsc_txp_clk_rate == v_pixclk ? 4 : 8); 3519 3520 return 0; 3521 } 3522 3523 static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 3524 { 3525 struct crtc_state *cstate = &state->crtc_state; 3526 struct connector_state *conn_state = &state->conn_state; 3527 struct drm_display_mode *mode = &conn_state->mode; 3528 struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 3529 struct vop2 *vop2 = cstate->private; 3530 u32 vp_offset = (cstate->crtc_id * 0x100); 3531 u16 hdisplay = mode->crtc_hdisplay; 3532 int output_if = conn_state->output_if; 3533 int if_pixclk_div = 0; 3534 int if_dclk_div = 0; 3535 unsigned long dclk_rate; 3536 bool dclk_inv, yc_swap = false; 3537 u32 val; 3538 3539 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3540 if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 3541 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 3542 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 3543 } else { 3544 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3545 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3546 } 3547 3548 if (cstate->dsc_enable) { 3549 int k = 1; 3550 3551 if (!vop2->data->nr_dscs) { 3552 printf("Unsupported DSC\n"); 3553 return 0; 3554 } 3555 3556 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 3557 k = 2; 3558 3559 cstate->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 3560 cstate->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width / k; 3561 cstate->dsc_pixel_num = cstate->dsc_slice_num > 4 ? 4 : cstate->dsc_slice_num; 3562 3563 vop2_calc_dsc_clk(state); 3564 printf("Enable DSC%d slice:%dx%d, slice num:%d\n", 3565 cstate->dsc_id, dsc_sink_cap->slice_width, 3566 dsc_sink_cap->slice_height, cstate->dsc_slice_num); 3567 } 3568 3569 dclk_rate = vop2_calc_cru_cfg(state, &cstate->dclk_core_div, &cstate->dclk_out_div, &if_pixclk_div, &if_dclk_div); 3570 3571 if (output_if & VOP_OUTPUT_IF_RGB) { 3572 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3573 4, false); 3574 vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 3575 RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3576 } 3577 3578 if (output_if & VOP_OUTPUT_IF_BT1120) { 3579 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3580 3, false); 3581 vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 3582 RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3583 yc_swap = is_yc_swap(conn_state->bus_format); 3584 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT, 3585 yc_swap, false); 3586 } 3587 3588 if (output_if & VOP_OUTPUT_IF_BT656) { 3589 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3590 2, false); 3591 vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, 3592 RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3593 yc_swap = is_yc_swap(conn_state->bus_format); 3594 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT, 3595 yc_swap, false); 3596 } 3597 3598 if (output_if & VOP_OUTPUT_IF_MIPI0) { 3599 if (cstate->crtc_id == 2) 3600 val = 0; 3601 else 3602 val = 1; 3603 3604 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 3605 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3606 RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 3607 3608 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 3609 1, false); 3610 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 3611 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 3612 if_pixclk_div, false); 3613 3614 if (conn_state->hold_mode) { 3615 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3616 EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 3617 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3618 EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 3619 } 3620 } 3621 3622 if (output_if & VOP_OUTPUT_IF_MIPI1) { 3623 if (cstate->crtc_id == 2) 3624 val = 0; 3625 else if (cstate->crtc_id == 3) 3626 val = 1; 3627 else 3628 val = 3; /*VP1*/ 3629 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 3630 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3631 RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 3632 3633 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 3634 1, false); 3635 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 3636 val, false); 3637 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 3638 if_pixclk_div, false); 3639 3640 if (conn_state->hold_mode) { 3641 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3642 EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 3643 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3644 EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 3645 } 3646 } 3647 3648 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 3649 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3650 MIPI_DUAL_EN_SHIFT, 1, false); 3651 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3652 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 3653 EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 3654 false); 3655 switch (conn_state->type) { 3656 case DRM_MODE_CONNECTOR_DisplayPort: 3657 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3658 RK3588_DP_DUAL_EN_SHIFT, 1, false); 3659 break; 3660 case DRM_MODE_CONNECTOR_eDP: 3661 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3662 RK3588_EDP_DUAL_EN_SHIFT, 1, false); 3663 break; 3664 case DRM_MODE_CONNECTOR_HDMIA: 3665 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3666 RK3588_HDMI_DUAL_EN_SHIFT, 1, false); 3667 break; 3668 case DRM_MODE_CONNECTOR_DSI: 3669 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 3670 RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 3671 break; 3672 default: 3673 break; 3674 } 3675 } 3676 3677 if (output_if & VOP_OUTPUT_IF_eDP0) { 3678 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 3679 1, false); 3680 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 3681 cstate->crtc_id, false); 3682 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 3683 if_dclk_div, false); 3684 3685 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 3686 if_pixclk_div, false); 3687 3688 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3689 RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 3690 } 3691 3692 if (output_if & VOP_OUTPUT_IF_eDP1) { 3693 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 3694 1, false); 3695 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 3696 cstate->crtc_id, false); 3697 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 3698 if_dclk_div, false); 3699 3700 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 3701 if_pixclk_div, false); 3702 3703 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3704 RK3588_GRF_EDP1_ENABLE_SHIFT, 1); 3705 } 3706 3707 if (output_if & VOP_OUTPUT_IF_HDMI0) { 3708 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 3709 1, false); 3710 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 3711 cstate->crtc_id, false); 3712 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 3713 if_dclk_div, false); 3714 3715 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 3716 if_pixclk_div, false); 3717 3718 if (cstate->dsc_enable) 3719 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3720 RK3588_GRF_HDMITX0_COMPRESS_MODE_SHIFT, 1); 3721 3722 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3723 RK3588_GRF_HDMITX0_ENABLE_SHIFT, 1); 3724 vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 3725 HDMI_SYNC_POL_MASK, 3726 HDMI0_SYNC_POL_SHIFT, val); 3727 } 3728 3729 if (output_if & VOP_OUTPUT_IF_HDMI1) { 3730 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 3731 1, false); 3732 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 3733 cstate->crtc_id, false); 3734 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 3735 if_dclk_div, false); 3736 3737 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 3738 if_pixclk_div, false); 3739 3740 if (cstate->dsc_enable) 3741 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3742 RK3588_GRF_HDMITX1_COMPRESS_MODE_SHIFT, 1); 3743 3744 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 3745 RK3588_GRF_HDMITX1_ENABLE_SHIFT, 1); 3746 vop2_grf_writel(vop2, vop2->vo1_grf, RK3588_GRF_VO1_CON0, 3747 HDMI_SYNC_POL_MASK, 3748 HDMI1_SYNC_POL_SHIFT, val); 3749 } 3750 3751 if (output_if & VOP_OUTPUT_IF_DP0) { 3752 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 3753 cstate->crtc_id, false); 3754 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 3755 RK3588_DP0_PIN_POL_SHIFT, val, false); 3756 } 3757 3758 if (output_if & VOP_OUTPUT_IF_DP1) { 3759 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 3760 cstate->crtc_id, false); 3761 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 3762 RK3588_DP1_PIN_POL_SHIFT, val, false); 3763 } 3764 3765 vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 3766 DCLK_CORE_DIV_SHIFT, cstate->dclk_core_div, false); 3767 vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 3768 DCLK_OUT_DIV_SHIFT, cstate->dclk_out_div, false); 3769 3770 return dclk_rate / 1000; 3771 } 3772 3773 static unsigned long rk3576_vop2_if_cfg(struct display_state *state) 3774 { 3775 struct crtc_state *cstate = &state->crtc_state; 3776 struct connector_state *conn_state = &state->conn_state; 3777 struct drm_display_mode *mode = &conn_state->mode; 3778 struct vop2 *vop2 = cstate->private; 3779 u32 vp_offset = (cstate->crtc_id * 0x100); 3780 u8 port_pix_rate = vop2->data->vp_data[cstate->crtc_id].pixel_rate; 3781 int output_if = conn_state->output_if; 3782 bool dclk_inv, yc_swap = false; 3783 bool split_mode = !!(conn_state->output_flags & 3784 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE); 3785 bool post_dclk_core_sel = false, pix_half_rate = false, post_dclk_out_sel = false; 3786 bool interface_dclk_sel, interface_pix_clk_sel = false; 3787 bool double_pixel = mode->flags & DRM_MODE_FLAG_DBLCLK || 3788 conn_state->output_if & VOP_OUTPUT_IF_BT656; 3789 unsigned long dclk_in_rate, dclk_core_rate; 3790 u32 val; 3791 3792 if (split_mode) { 3793 printf("WARN: split is enabled, post-scaler shouldn't be set\n"); 3794 conn_state->overscan.left_margin = 100; 3795 conn_state->overscan.right_margin = 100; 3796 conn_state->overscan.top_margin = 100; 3797 conn_state->overscan.bottom_margin = 100; 3798 3799 /* 3800 * VOP split and sharp use the same line buffer. If enable 3801 * split, sharp must be disabled completely. 3802 */ 3803 if (vop2->data->vp_data[cstate->crtc_id].feature & VOP_FEATURE_POST_SHARP) 3804 writel(false << SW_SHARP_ENABLE_SHIFT, 3805 vop2->sharp_res + RK3576_SHARP_CTRL); 3806 } 3807 3808 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 3809 if (output_if & VOP_OUTPUT_IF_MIPI0) { 3810 /* 3811 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update, 3812 * so set VOP hsync/vsync polarity as positive by default. 3813 */ 3814 val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE); 3815 } else { 3816 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 3817 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 3818 } 3819 3820 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420 || 3821 mode->crtc_clock > VOP2_MAX_DCLK_RATE || (cstate->crtc_id == 0 && split_mode)) 3822 cstate->crtc->vps[cstate->crtc_id].dclk_div = 2; /* div2 */ 3823 else 3824 cstate->crtc->vps[cstate->crtc_id].dclk_div = 1; /* no div */ 3825 dclk_in_rate = mode->crtc_clock / cstate->crtc->vps[cstate->crtc_id].dclk_div; 3826 3827 if (double_pixel) 3828 dclk_core_rate = mode->crtc_clock / 2; 3829 else 3830 dclk_core_rate = mode->crtc_clock / port_pix_rate; 3831 post_dclk_core_sel = dclk_in_rate > dclk_core_rate ? 1 : 0; /* 0: no div, 1: div2 */ 3832 3833 if (split_mode || conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 3834 pix_half_rate = true; 3835 post_dclk_out_sel = true; 3836 } 3837 3838 if (output_if & VOP_OUTPUT_IF_RGB) { 3839 interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3840 /* 3841 * RGB interface_pix_clk_sel will auto config according 3842 * to rgb_en/bt1120_en/bt656_en. 3843 */ 3844 } else if (output_if & VOP_OUTPUT_IF_eDP0) { 3845 interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3846 interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0; 3847 } else { 3848 interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; 3849 interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0; 3850 } 3851 3852 /* dclk_core */ 3853 vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK, 3854 RK3576_DCLK_CORE_SEL_SHIFT, post_dclk_core_sel, false); 3855 /* dclk_out */ 3856 vop2_mask_write(vop2, RK3568_VP0_DCLK_SEL + vp_offset, EN_MASK, 3857 RK3576_DCLK_OUT_SEL_SHIFT, post_dclk_out_sel, false); 3858 3859 if (output_if & VOP_OUTPUT_IF_RGB) { 3860 /* 0: dclk_core, 1: dclk_out */ 3861 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3862 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3863 3864 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3865 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3866 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3867 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3868 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3869 RK3576_IF_OUT_EN_SHIFT, 1, false); 3870 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3871 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3872 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3873 RK3576_IF_PIN_POL_SHIFT, val, false); 3874 vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3875 RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, dclk_inv); 3876 } 3877 3878 if (output_if & VOP_OUTPUT_IF_BT1120) { 3879 /* 0: dclk_core, 1: dclk_out */ 3880 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3881 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3882 3883 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3884 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3885 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3886 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3887 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3888 RK3576_IF_OUT_EN_SHIFT, 1, false); 3889 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3890 RK3576_BT1120_OUT_EN_SHIFT, 1, false); 3891 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3892 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3893 vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3894 RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3895 yc_swap = is_yc_swap(conn_state->bus_format); 3896 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3897 RK3576_BT1120_YC_SWAP_SHIFT, yc_swap, false); 3898 } 3899 3900 if (output_if & VOP_OUTPUT_IF_BT656) { 3901 /* 0: dclk_core, 1: dclk_out */ 3902 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3903 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3904 3905 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3906 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3907 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3908 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3909 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3910 RK3576_IF_OUT_EN_SHIFT, 1, false); 3911 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3912 RK3576_BT656_OUT_EN_SHIFT, 1, false); 3913 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3914 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3915 vop2_grf_writel(vop2, vop2->ioc_grf, RK3576_VCCIO_IOC_MISC_CON8, EN_MASK, 3916 RK3576_IOC_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); 3917 yc_swap = is_yc_swap(conn_state->bus_format); 3918 vop2_mask_write(vop2, RK3576_RGB_IF_CTRL, EN_MASK, 3919 RK3576_BT656_YC_SWAP_SHIFT, yc_swap, false); 3920 } 3921 3922 if (output_if & VOP_OUTPUT_IF_MIPI0) { 3923 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3924 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3925 /* 0: div2, 1: div4 */ 3926 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3927 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3928 3929 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3930 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3931 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3932 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3933 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3934 RK3576_IF_OUT_EN_SHIFT, 1, false); 3935 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 3936 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 3937 /* 3938 * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update, 3939 * so set VOP hsync/vsync polarity as positive by default. 3940 */ 3941 if (vop2->version == VOP_VERSION_RK3576) 3942 val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE); 3943 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 3944 RK3576_IF_PIN_POL_SHIFT, val, false); 3945 3946 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 3947 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3948 RK3576_MIPI_CMD_MODE_SHIFT, 1, false); 3949 3950 if (conn_state->hold_mode) { 3951 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3952 EDPI_TE_EN, !cstate->soft_te, false); 3953 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3954 EDPI_WMS_HOLD_EN, 1, false); 3955 } 3956 } 3957 3958 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 3959 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3960 MIPI_DUAL_EN_SHIFT, 1, false); 3961 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 3962 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 3963 MIPI_DUAL_SWAP_EN_SHIFT, 1, false); 3964 switch (conn_state->type) { 3965 case DRM_MODE_CONNECTOR_DisplayPort: 3966 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 3967 RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3968 break; 3969 case DRM_MODE_CONNECTOR_eDP: 3970 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3971 RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3972 break; 3973 case DRM_MODE_CONNECTOR_HDMIA: 3974 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 3975 RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3976 break; 3977 case DRM_MODE_CONNECTOR_DSI: 3978 vop2_mask_write(vop2, RK3576_MIPI0_IF_CTRL, EN_MASK, 3979 RK3576_IF_SPLIT_EN_SHIFT, 1, false); 3980 break; 3981 default: 3982 break; 3983 } 3984 } 3985 3986 if (output_if & VOP_OUTPUT_IF_eDP0) { 3987 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 3988 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 3989 /* 0: dclk, 1: port0_dclk */ 3990 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 3991 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 3992 3993 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3994 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 3995 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3996 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 3997 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, EN_MASK, 3998 RK3576_IF_OUT_EN_SHIFT, 1, false); 3999 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 4000 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 4001 vop2_mask_write(vop2, RK3576_EDP0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 4002 RK3576_IF_PIN_POL_SHIFT, val, false); 4003 } 4004 4005 if (output_if & VOP_OUTPUT_IF_HDMI0) { 4006 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 4007 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 4008 /* 0: div2, 1: div4 */ 4009 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 4010 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 4011 4012 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 4013 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 4014 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 4015 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 4016 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, EN_MASK, 4017 RK3576_IF_OUT_EN_SHIFT, 1, false); 4018 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 4019 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 4020 vop2_mask_write(vop2, RK3576_HDMI0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 4021 RK3576_IF_PIN_POL_SHIFT, val, false); 4022 } 4023 4024 if (output_if & VOP_OUTPUT_IF_DP0) { 4025 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 4026 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 4027 /* 0: no div, 1: div2 */ 4028 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 4029 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 4030 4031 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 4032 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 4033 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 4034 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 4035 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 4036 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 4037 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, RK3576_IF_PIN_POL_MASK, 4038 RK3576_IF_PIN_POL_SHIFT, val, false); 4039 } 4040 4041 if (output_if & VOP_OUTPUT_IF_DP1) { 4042 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 4043 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 4044 /* 0: no div, 1: div2 */ 4045 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 4046 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 4047 4048 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 4049 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 4050 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 4051 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 4052 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 4053 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 4054 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, RK3576_IF_PIN_POL_MASK, 4055 RK3576_IF_PIN_POL_SHIFT, val, false); 4056 } 4057 4058 if (output_if & VOP_OUTPUT_IF_DP2) { 4059 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_DCLK_SEL_MASK, 4060 RK3576_IF_DCLK_SEL_SHIFT, interface_dclk_sel, false); 4061 /* 0: no div, 1: div2 */ 4062 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIX_CLK_SEL_MASK, 4063 RK3576_IF_PIX_CLK_SEL_SHIFT, interface_pix_clk_sel, false); 4064 4065 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 4066 RK3576_IF_REGDONE_IMD_EN_SHIFT, 1, false); 4067 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 4068 RK3576_IF_CLK_OUT_EN_SHIFT, 1, false); 4069 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PORT_SEL_MASK, 4070 RK3576_IF_PORT_SEL_SHIFT, cstate->crtc_id, false); 4071 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, RK3576_IF_PIN_POL_MASK, 4072 RK3576_IF_PIN_POL_SHIFT, val, false); 4073 } 4074 4075 return mode->crtc_clock; 4076 } 4077 4078 static void rk3568_vop2_setup_dual_channel_if(struct display_state *state) 4079 { 4080 struct crtc_state *cstate = &state->crtc_state; 4081 struct connector_state *conn_state = &state->conn_state; 4082 struct vop2 *vop2 = cstate->private; 4083 u32 vp_offset = (cstate->crtc_id * 0x100); 4084 4085 if (conn_state->output_flags & 4086 ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) { 4087 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 4088 LVDS_DUAL_EN_SHIFT, 1, false); 4089 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 4090 LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false); 4091 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 4092 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 4093 LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 4094 4095 return; 4096 } 4097 4098 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 4099 MIPI_DUAL_EN_SHIFT, 1, false); 4100 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) { 4101 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 4102 MIPI_DUAL_SWAP_EN_SHIFT, 1, false); 4103 } 4104 4105 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 4106 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 4107 LVDS_DUAL_EN_SHIFT, 1, false); 4108 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 4109 LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false); 4110 } 4111 } 4112 4113 static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 4114 { 4115 struct crtc_state *cstate = &state->crtc_state; 4116 struct connector_state *conn_state = &state->conn_state; 4117 struct drm_display_mode *mode = &conn_state->mode; 4118 struct vop2 *vop2 = cstate->private; 4119 bool dclk_inv; 4120 u32 val; 4121 4122 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 4123 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 4124 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 4125 4126 if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 4127 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 4128 1, false); 4129 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4130 RGB_MUX_SHIFT, cstate->crtc_id, false); 4131 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 4132 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 4133 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 4134 GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 4135 } 4136 4137 if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 4138 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 4139 1, false); 4140 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 4141 BT1120_EN_SHIFT, 1, false); 4142 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4143 RGB_MUX_SHIFT, cstate->crtc_id, false); 4144 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 4145 GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 4146 } 4147 4148 if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 4149 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 4150 1, false); 4151 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4152 RGB_MUX_SHIFT, cstate->crtc_id, false); 4153 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 4154 GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 4155 } 4156 4157 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 4158 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 4159 1, false); 4160 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4161 LVDS0_MUX_SHIFT, cstate->crtc_id, false); 4162 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 4163 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 4164 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4165 IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 4166 } 4167 4168 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 4169 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 4170 1, false); 4171 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4172 LVDS1_MUX_SHIFT, cstate->crtc_id, false); 4173 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_RGB_LVDS_PIN_POL_MASK, 4174 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 4175 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4176 IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 4177 } 4178 4179 4180 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 4181 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 4182 1, false); 4183 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4184 MIPI0_MUX_SHIFT, cstate->crtc_id, false); 4185 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4186 IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 4187 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK, 4188 IF_CTRL_MIPI_PIN_POL_SHIFT, val, false); 4189 } 4190 4191 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 4192 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 4193 1, false); 4194 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4195 MIPI1_MUX_SHIFT, cstate->crtc_id, false); 4196 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4197 IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 4198 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_MIPI_PIN_POL_MASK, 4199 IF_CTRL_MIPI_PIN_POL_SHIFT, val, false); 4200 } 4201 4202 if (conn_state->output_flags & 4203 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || 4204 conn_state->output_flags & 4205 ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) 4206 rk3568_vop2_setup_dual_channel_if(state); 4207 4208 if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 4209 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 4210 1, false); 4211 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4212 EDP0_MUX_SHIFT, cstate->crtc_id, false); 4213 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4214 IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 4215 vop2_mask_write(vop2, RK3568_DSP_IF_POL, IF_CTRL_EDP_PIN_POL_MASK, 4216 IF_CTRL_EDP_PIN_POL_SHIFT, val, false); 4217 } 4218 4219 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 4220 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 4221 1, false); 4222 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4223 HDMI0_MUX_SHIFT, cstate->crtc_id, false); 4224 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4225 IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 4226 vop2_mask_write(vop2, RK3568_DSP_IF_POL, 4227 IF_CRTL_HDMI_PIN_POL_MASK, 4228 IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 4229 } 4230 4231 return mode->crtc_clock; 4232 } 4233 4234 static unsigned long rk3562_vop2_if_cfg(struct display_state *state) 4235 { 4236 struct crtc_state *cstate = &state->crtc_state; 4237 struct connector_state *conn_state = &state->conn_state; 4238 struct drm_display_mode *mode = &conn_state->mode; 4239 struct vop2 *vop2 = cstate->private; 4240 bool dclk_inv; 4241 u32 vp_offset = (cstate->crtc_id * 0x100); 4242 u32 val; 4243 4244 dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; 4245 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 4246 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 4247 4248 if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 4249 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 4250 1, false); 4251 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4252 RGB_MUX_SHIFT, cstate->crtc_id, false); 4253 vop2_grf_writel(vop2, vop2->grf, RK3562_GRF_IOC_VO_IO_CON, EN_MASK, 4254 GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 4255 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 4256 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 4257 } 4258 4259 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 4260 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 4261 1, false); 4262 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4263 LVDS0_MUX_SHIFT, cstate->crtc_id, false); 4264 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4265 IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); 4266 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 4267 IF_CTRL_RGB_LVDS_PIN_POL_SHIFT, val, false); 4268 } 4269 4270 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 4271 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 4272 1, false); 4273 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4274 MIPI0_MUX_SHIFT, cstate->crtc_id, false); 4275 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4276 RK3562_MIPI_DCLK_POL_SHIFT, dclk_inv, false); 4277 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3562_IF_PIN_POL_MASK, 4278 RK3562_MIPI_PIN_POL_SHIFT, val, false); 4279 4280 if (conn_state->hold_mode) { 4281 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 4282 EN_MASK, EDPI_TE_EN, !cstate->soft_te, false); 4283 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 4284 EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 4285 } 4286 } 4287 4288 return mode->crtc_clock; 4289 } 4290 4291 static unsigned long rk3528_vop2_if_cfg(struct display_state *state) 4292 { 4293 struct crtc_state *cstate = &state->crtc_state; 4294 struct connector_state *conn_state = &state->conn_state; 4295 struct drm_display_mode *mode = &conn_state->mode; 4296 struct vop2 *vop2 = cstate->private; 4297 u32 val; 4298 4299 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 4300 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 4301 4302 if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 4303 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 4304 1, false); 4305 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4306 RGB_MUX_SHIFT, cstate->crtc_id, false); 4307 } 4308 4309 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 4310 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 4311 1, false); 4312 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 4313 HDMI0_MUX_SHIFT, cstate->crtc_id, false); 4314 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 4315 IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 4316 vop2_mask_write(vop2, RK3568_DSP_IF_POL, 4317 IF_CRTL_HDMI_PIN_POL_MASK, 4318 IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 4319 } 4320 4321 return mode->crtc_clock; 4322 } 4323 4324 static void vop2_post_color_swap(struct display_state *state) 4325 { 4326 struct crtc_state *cstate = &state->crtc_state; 4327 struct connector_state *conn_state = &state->conn_state; 4328 struct vop2 *vop2 = cstate->private; 4329 u32 vp_offset = (cstate->crtc_id * 0x100); 4330 u32 output_type = conn_state->type; 4331 u32 data_swap = 0; 4332 4333 if (is_uv_swap(state) || is_rb_swap(state)) 4334 data_swap = DSP_RB_SWAP; 4335 4336 if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576)) { 4337 if ((output_type == DRM_MODE_CONNECTOR_HDMIA || 4338 output_type == DRM_MODE_CONNECTOR_DisplayPort) && 4339 (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 4340 conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 4341 data_swap |= DSP_RG_SWAP; 4342 } 4343 4344 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 4345 DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 4346 } 4347 4348 static void vop2_clk_set_parent(struct clk *clk, struct clk *parent) 4349 { 4350 int ret = 0; 4351 4352 if (parent->dev) 4353 ret = clk_set_parent(clk, parent); 4354 if (ret < 0) 4355 debug("failed to set %s as parent for %s\n", 4356 parent->dev->name, clk->dev->name); 4357 } 4358 4359 static ulong vop2_clk_set_rate(struct clk *clk, ulong rate) 4360 { 4361 int ret = 0; 4362 4363 if (clk->dev) 4364 ret = clk_set_rate(clk, rate); 4365 if (ret < 0) 4366 debug("failed to set %s rate %lu \n", clk->dev->name, rate); 4367 4368 return ret; 4369 } 4370 4371 static void vop2_calc_dsc_cru_cfg(struct display_state *state, 4372 int *dsc_txp_clk_div, int *dsc_pxl_clk_div, 4373 int *dsc_cds_clk_div, u64 dclk_rate) 4374 { 4375 struct crtc_state *cstate = &state->crtc_state; 4376 4377 *dsc_txp_clk_div = dclk_rate / cstate->dsc_txp_clk_rate; 4378 *dsc_pxl_clk_div = dclk_rate / cstate->dsc_pxl_clk_rate; 4379 *dsc_cds_clk_div = dclk_rate / cstate->dsc_cds_clk_rate; 4380 4381 *dsc_txp_clk_div = ilog2(*dsc_txp_clk_div); 4382 *dsc_pxl_clk_div = ilog2(*dsc_pxl_clk_div); 4383 *dsc_cds_clk_div = ilog2(*dsc_cds_clk_div); 4384 } 4385 4386 static void vop2_load_pps(struct display_state *state, struct vop2 *vop2, u8 dsc_id) 4387 { 4388 struct crtc_state *cstate = &state->crtc_state; 4389 struct drm_dsc_picture_parameter_set *pps = &cstate->pps; 4390 struct drm_dsc_picture_parameter_set config_pps; 4391 const struct vop2_data *vop2_data = vop2->data; 4392 const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 4393 u32 *pps_val = (u32 *)&config_pps; 4394 u32 decoder_regs_offset = (dsc_id * 0x100); 4395 int i = 0; 4396 4397 memcpy(&config_pps, pps, sizeof(config_pps)); 4398 4399 if ((config_pps.pps_3 & 0xf) > dsc_data->max_linebuf_depth) { 4400 config_pps.pps_3 &= 0xf0; 4401 config_pps.pps_3 |= dsc_data->max_linebuf_depth; 4402 printf("DSC%d max_linebuf_depth is: %d, current set value is: %d\n", 4403 dsc_id, dsc_data->max_linebuf_depth, config_pps.pps_3 & 0xf); 4404 } 4405 4406 for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 4407 config_pps.rc_range_parameters[i] = 4408 (pps->rc_range_parameters[i] >> 3 & 0x1f) | 4409 ((pps->rc_range_parameters[i] >> 14 & 0x3) << 5) | 4410 ((pps->rc_range_parameters[i] >> 0 & 0x7) << 7) | 4411 ((pps->rc_range_parameters[i] >> 8 & 0x3f) << 10); 4412 } 4413 4414 for (i = 0; i < ROCKCHIP_DSC_PPS_SIZE_BYTE / 4; i++) 4415 vop2_writel(vop2, RK3588_DSC_8K_PPS0_3 + decoder_regs_offset + i * 4, *pps_val++); 4416 } 4417 4418 static void vop2_dsc_enable(struct display_state *state, struct vop2 *vop2, u8 dsc_id, u64 dclk_rate) 4419 { 4420 struct connector_state *conn_state = &state->conn_state; 4421 struct drm_display_mode *mode = &conn_state->mode; 4422 struct crtc_state *cstate = &state->crtc_state; 4423 struct rockchip_dsc_sink_cap *dsc_sink_cap = &cstate->dsc_sink_cap; 4424 const struct vop2_data *vop2_data = vop2->data; 4425 const struct vop2_dsc_data *dsc_data = &vop2_data->dsc[dsc_id]; 4426 bool mipi_ds_mode = false; 4427 u8 dsc_interface_mode = 0; 4428 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 4429 u16 hdisplay = mode->crtc_hdisplay; 4430 u16 htotal = mode->crtc_htotal; 4431 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 4432 u16 vdisplay = mode->crtc_vdisplay; 4433 u16 vtotal = mode->crtc_vtotal; 4434 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 4435 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 4436 u16 vact_end = vact_st + vdisplay; 4437 u32 ctrl_regs_offset = (dsc_id * 0x30); 4438 u32 decoder_regs_offset = (dsc_id * 0x100); 4439 int dsc_txp_clk_div = 0; 4440 int dsc_pxl_clk_div = 0; 4441 int dsc_cds_clk_div = 0; 4442 int val = 0; 4443 4444 if (!vop2->data->nr_dscs) { 4445 printf("Unsupported DSC\n"); 4446 return; 4447 } 4448 4449 if (cstate->dsc_slice_num > dsc_data->max_slice_num) 4450 printf("DSC%d supported max slice is: %d, current is: %d\n", 4451 dsc_data->id, dsc_data->max_slice_num, cstate->dsc_slice_num); 4452 4453 if (dsc_data->pd_id) { 4454 if (vop2_power_domain_on(vop2, dsc_data->pd_id)) 4455 printf("open dsc%d pd fail\n", dsc_id); 4456 } 4457 4458 vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, EN_MASK, 4459 SCAN_TIMING_PARA_IMD_EN_SHIFT, 1, false); 4460 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PORT_SEL_MASK, 4461 DSC_PORT_SEL_SHIFT, cstate->crtc_id, false); 4462 if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 4463 dsc_interface_mode = VOP_DSC_IF_HDMI; 4464 } else { 4465 mipi_ds_mode = !!(conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE); 4466 if (mipi_ds_mode) 4467 dsc_interface_mode = VOP_DSC_IF_MIPI_DS_MODE; 4468 else 4469 dsc_interface_mode = VOP_DSC_IF_MIPI_VIDEO_MODE; 4470 } 4471 4472 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 4473 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 4474 DSC_MAN_MODE_SHIFT, 0, false); 4475 else 4476 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_MAN_MODE_MASK, 4477 DSC_MAN_MODE_SHIFT, 1, false); 4478 4479 vop2_calc_dsc_cru_cfg(state, &dsc_txp_clk_div, &dsc_pxl_clk_div, &dsc_cds_clk_div, dclk_rate); 4480 4481 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_INTERFACE_MODE_MASK, 4482 DSC_INTERFACE_MODE_SHIFT, dsc_interface_mode, false); 4483 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PIXEL_NUM_MASK, 4484 DSC_PIXEL_NUM_SHIFT, cstate->dsc_pixel_num >> 1, false); 4485 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_TXP_CLK_DIV_MASK, 4486 DSC_TXP_CLK_DIV_SHIFT, dsc_txp_clk_div, false); 4487 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_PXL_CLK_DIV_MASK, 4488 DSC_PXL_CLK_DIV_SHIFT, dsc_pxl_clk_div, false); 4489 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 4490 DSC_CDS_CLK_DIV_SHIFT, dsc_cds_clk_div, false); 4491 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, EN_MASK, 4492 DSC_SCAN_EN_SHIFT, !mipi_ds_mode, false); 4493 vop2_mask_write(vop2, RK3588_DSC_8K_SYS_CTRL + ctrl_regs_offset, DSC_CDS_CLK_DIV_MASK, 4494 DSC_HALT_EN_SHIFT, mipi_ds_mode, false); 4495 4496 if (!mipi_ds_mode) { 4497 u16 dsc_hsync, dsc_htotal, dsc_hact_st, dsc_hact_end; 4498 u32 target_bpp = dsc_sink_cap->target_bits_per_pixel_x16; 4499 u64 dsc_cds_rate = cstate->dsc_cds_clk_rate; 4500 u32 v_pixclk_mhz = mode->crtc_clock / 1000; /* video timing pixclk */ 4501 u32 dly_num, dsc_cds_rate_mhz, val = 0; 4502 int k = 1; 4503 4504 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 4505 k = 2; 4506 4507 if (target_bpp >> 4 < dsc_data->min_bits_per_pixel) 4508 printf("Unsupported bpp less than: %d\n", dsc_data->min_bits_per_pixel); 4509 4510 /* 4511 * dly_num = delay_line_num * T(one-line) / T (dsc_cds) 4512 * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz 4513 * T (dsc_cds) = 1 / dsc_cds_rate_mhz 4514 * 4515 * HDMI: 4516 * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay 4517 * delay_line_num = 4 - BPP / 8 4518 * = (64 - target_bpp / 8) / 16 4519 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 4520 * 4521 * MIPI DSI[4320 and 9216 is buffer size for DSC]: 4522 * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size; 4523 * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 4524 * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size; 4525 * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 4526 * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num 4527 */ 4528 do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ 4529 dsc_cds_rate_mhz = dsc_cds_rate; 4530 dsc_hsync = hsync_len / 2; 4531 if (dsc_interface_mode == VOP_DSC_IF_HDMI) { 4532 dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; 4533 } else { 4534 int dsc_buf_size = dsc_id == 0 ? 4320 * 8 : 9216 * 2; 4535 int delay_line_num = dsc_buf_size / cstate->dsc_slice_num / 4536 be16_to_cpu(cstate->pps.chunk_size); 4537 4538 delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; 4539 dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num; 4540 4541 /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */ 4542 if (dsc_hsync < 8) 4543 dsc_hsync = 8; 4544 } 4545 vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_MODE_MASK, 4546 DSC_INIT_DLY_MODE_SHIFT, 0, false); 4547 vop2_mask_write(vop2, RK3588_DSC_8K_INIT_DLY + ctrl_regs_offset, DSC_INIT_DLY_NUM_MASK, 4548 DSC_INIT_DLY_NUM_SHIFT, dly_num, false); 4549 4550 /* 4551 * htotal / dclk_core = dsc_htotal /cds_clk 4552 * 4553 * dclk_core = DCLK / (1 << dclk_core->div_val) 4554 * cds_clk = txp_clk / (1 << dsc_cds_clk->div_val) 4555 * txp_clk = DCLK / (1 << dsc_txp_clk->div_val) 4556 * 4557 * dsc_htotal = htotal * (1 << dclk_core->div_val) / 4558 * ((1 << dsc_txp_clk->div_val) * (1 << dsc_cds_clk->div_val)) 4559 */ 4560 dsc_htotal = htotal * (1 << cstate->dclk_core_div) / 4561 ((1 << dsc_txp_clk_div) * (1 << dsc_cds_clk_div)); 4562 val = dsc_htotal << 16 | dsc_hsync; 4563 vop2_mask_write(vop2, RK3588_DSC_8K_HTOTAL_HS_END + ctrl_regs_offset, DSC_HTOTAL_PW_MASK, 4564 DSC_HTOTAL_PW_SHIFT, val, false); 4565 4566 dsc_hact_st = hact_st / 2; 4567 dsc_hact_end = (hdisplay / k * target_bpp >> 4) / 24 + dsc_hact_st; 4568 val = dsc_hact_end << 16 | dsc_hact_st; 4569 vop2_mask_write(vop2, RK3588_DSC_8K_HACT_ST_END + ctrl_regs_offset, DSC_HACT_ST_END_MASK, 4570 DSC_HACT_ST_END_SHIFT, val, false); 4571 4572 vop2_mask_write(vop2, RK3588_DSC_8K_VTOTAL_VS_END + ctrl_regs_offset, DSC_VTOTAL_PW_MASK, 4573 DSC_VTOTAL_PW_SHIFT, vtotal << 16 | vsync_len, false); 4574 vop2_mask_write(vop2, RK3588_DSC_8K_VACT_ST_END + ctrl_regs_offset, DSC_VACT_ST_END_MASK, 4575 DSC_VACT_ST_END_SHIFT, vact_end << 16 | vact_st, false); 4576 } 4577 4578 vop2_mask_write(vop2, RK3588_DSC_8K_RST + ctrl_regs_offset, RST_DEASSERT_MASK, 4579 RST_DEASSERT_SHIFT, 1, false); 4580 udelay(10); 4581 4582 val |= DSC_CTRL0_DEF_CON | (ilog2(cstate->dsc_slice_num) << DSC_NSLC_SHIFT) | 4583 ((dsc_sink_cap->version_minor == 2 ? 1 : 0) << DSC_IFEP_SHIFT); 4584 vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 4585 4586 vop2_load_pps(state, vop2, dsc_id); 4587 4588 val |= (1 << DSC_PPS_UPD_SHIFT); 4589 vop2_writel(vop2, RK3588_DSC_8K_CTRL0 + decoder_regs_offset, val); 4590 4591 printf("DSC%d: txp:%lld div:%d, pxl:%lld div:%d, dsc:%lld div:%d\n", 4592 dsc_id, 4593 cstate->dsc_txp_clk_rate, dsc_txp_clk_div, 4594 cstate->dsc_pxl_clk_rate, dsc_pxl_clk_div, 4595 cstate->dsc_cds_clk_rate, dsc_cds_clk_div); 4596 } 4597 4598 static bool is_extend_pll(struct display_state *state, struct udevice **clk_dev) 4599 { 4600 struct crtc_state *cstate = &state->crtc_state; 4601 struct vop2 *vop2 = cstate->private; 4602 struct udevice *vp_dev, *dev; 4603 struct ofnode_phandle_args args; 4604 char vp_name[10]; 4605 int ret; 4606 4607 if (vop2->version != VOP_VERSION_RK3588 && vop2->version != VOP_VERSION_RK3576) 4608 return false; 4609 4610 sprintf(vp_name, "port@%d", cstate->crtc_id); 4611 if (uclass_find_device_by_name(UCLASS_VIDEO_CRTC, vp_name, &vp_dev)) { 4612 debug("warn: can't get vp device\n"); 4613 return false; 4614 } 4615 4616 ret = dev_read_phandle_with_args(vp_dev, "assigned-clock-parents", "#clock-cells", 0, 4617 0, &args); 4618 if (ret) { 4619 debug("assigned-clock-parents's node not define\n"); 4620 return false; 4621 } 4622 4623 if (uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &dev)) { 4624 debug("warn: can't get clk device\n"); 4625 return false; 4626 } 4627 4628 if (!strcmp(dev->name, "hdmiphypll_clk0") || !strcmp(dev->name, "hdmiphypll_clk1")) { 4629 printf("%s: clk dev :%s: vp port:%s\n", __func__, dev->name, vp_dev->name); 4630 if (clk_dev) 4631 *clk_dev = dev; 4632 return true; 4633 } 4634 4635 return false; 4636 } 4637 4638 static void vop3_mcu_mode_setup(struct display_state *state) 4639 { 4640 struct crtc_state *cstate = &state->crtc_state; 4641 struct vop2 *vop2 = cstate->private; 4642 u32 vp_offset = (cstate->crtc_id * 0x100); 4643 4644 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4645 MCU_TYPE_SHIFT, 1, false); 4646 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4647 MCU_HOLD_MODE_SHIFT, 1, false); 4648 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 4649 MCU_PIX_TOTAL_SHIFT, cstate->mcu_timing.mcu_pix_total, false); 4650 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 4651 MCU_CS_PST_SHIFT, cstate->mcu_timing.mcu_cs_pst, false); 4652 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 4653 MCU_CS_PEND_SHIFT, cstate->mcu_timing.mcu_cs_pend, false); 4654 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 4655 MCU_RW_PST_SHIFT, cstate->mcu_timing.mcu_rw_pst, false); 4656 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 4657 MCU_RW_PEND_SHIFT, cstate->mcu_timing.mcu_rw_pend, false); 4658 } 4659 4660 static void vop3_mcu_bypass_mode_setup(struct display_state *state) 4661 { 4662 struct crtc_state *cstate = &state->crtc_state; 4663 struct vop2 *vop2 = cstate->private; 4664 u32 vp_offset = (cstate->crtc_id * 0x100); 4665 4666 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4667 MCU_TYPE_SHIFT, 1, false); 4668 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4669 MCU_HOLD_MODE_SHIFT, 1, false); 4670 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_PIX_TOTAL_MASK, 4671 MCU_PIX_TOTAL_SHIFT, 53, false); 4672 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PST_MASK, 4673 MCU_CS_PST_SHIFT, 6, false); 4674 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_CS_PEND_MASK, 4675 MCU_CS_PEND_SHIFT, 48, false); 4676 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PST_MASK, 4677 MCU_RW_PST_SHIFT, 12, false); 4678 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, MCU_RW_PEND_MASK, 4679 MCU_RW_PEND_SHIFT, 30, false); 4680 } 4681 4682 static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 value) 4683 { 4684 struct crtc_state *cstate = &state->crtc_state; 4685 struct connector_state *conn_state = &state->conn_state; 4686 struct drm_display_mode *mode = &conn_state->mode; 4687 struct vop2 *vop2 = cstate->private; 4688 u32 vp_offset = (cstate->crtc_id * 0x100); 4689 4690 /* 4691 * 1.set mcu bypass mode timing. 4692 * 2.set dclk rate to 150M. 4693 */ 4694 if (type == MCU_SETBYPASS && value) { 4695 vop3_mcu_bypass_mode_setup(state); 4696 vop2_clk_set_rate(&cstate->dclk, 150000000); 4697 } 4698 4699 switch (type) { 4700 case MCU_WRCMD: 4701 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4702 MCU_RS_SHIFT, 0, false); 4703 vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 4704 MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 4705 value, false); 4706 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4707 MCU_RS_SHIFT, 1, false); 4708 break; 4709 case MCU_WRDATA: 4710 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4711 MCU_RS_SHIFT, 1, false); 4712 vop2_mask_write(vop2, RK3562_VP0_MCU_RW_BYPASS_PORT + vp_offset, 4713 MCU_WRITE_DATA_BYPASS_MASK, MCU_WRITE_DATA_BYPASS_SHIFT, 4714 value, false); 4715 break; 4716 case MCU_SETBYPASS: 4717 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 4718 MCU_BYPASS_SHIFT, value ? 1 : 0, false); 4719 break; 4720 default: 4721 break; 4722 } 4723 4724 /* 4725 * 1.restore mcu data mode timing. 4726 * 2.restore dclk rate to crtc_clock. 4727 */ 4728 if (type == MCU_SETBYPASS && !value) { 4729 vop3_mcu_mode_setup(state); 4730 vop2_clk_set_rate(&cstate->dclk, mode->crtc_clock * 1000); 4731 } 4732 4733 return 0; 4734 } 4735 4736 static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id) 4737 { 4738 const struct vop2_data *vop2_data = vop2->data; 4739 const struct vop2_vp_data *vp_data = &vop2_data->vp_data[crtc_id]; 4740 u32 vp_offset = crtc_id * 0x100; 4741 bool pre_dither_down_en = false; 4742 4743 switch (bus_format) { 4744 case MEDIA_BUS_FMT_RGB565_1X16: 4745 case MEDIA_BUS_FMT_RGB565_2X8_LE: 4746 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4747 PRE_DITHER_DOWN_EN_SHIFT, true, false); 4748 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4749 DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB565, false); 4750 pre_dither_down_en = true; 4751 break; 4752 case MEDIA_BUS_FMT_RGB666_1X18: 4753 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 4754 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 4755 case MEDIA_BUS_FMT_RGB666_3X6: 4756 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4757 PRE_DITHER_DOWN_EN_SHIFT, true, false); 4758 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4759 DITHER_DOWN_MODE_SHIFT, RGB888_TO_RGB666, false); 4760 pre_dither_down_en = true; 4761 break; 4762 case MEDIA_BUS_FMT_YUYV8_1X16: 4763 case MEDIA_BUS_FMT_YUV8_1X24: 4764 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 4765 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4766 PRE_DITHER_DOWN_EN_SHIFT, false, false); 4767 pre_dither_down_en = true; 4768 break; 4769 case MEDIA_BUS_FMT_YUYV10_1X20: 4770 case MEDIA_BUS_FMT_YUV10_1X30: 4771 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 4772 case MEDIA_BUS_FMT_RGB101010_1X30: 4773 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4774 PRE_DITHER_DOWN_EN_SHIFT, false, false); 4775 pre_dither_down_en = false; 4776 break; 4777 case MEDIA_BUS_FMT_RGB888_3X8: 4778 case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: 4779 case MEDIA_BUS_FMT_RGB888_1X24: 4780 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 4781 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 4782 default: 4783 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4784 PRE_DITHER_DOWN_EN_SHIFT, false, false); 4785 pre_dither_down_en = true; 4786 break; 4787 } 4788 4789 if (is_yuv_output(bus_format) && (vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0) 4790 pre_dither_down_en = false; 4791 4792 if ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) && pre_dither_down_en) { 4793 if (vop2->version == VOP_VERSION_RK3576) { 4794 vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_0 + vp_offset, 0x00000000); 4795 vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_1 + vp_offset, 0x01000100); 4796 vop2_writel(vop2, RK3576_VP0_POST_DITHER_FRC_2 + vp_offset, 0x04030100); 4797 } 4798 4799 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4800 PRE_DITHER_DOWN_EN_SHIFT, 0, false); 4801 /* enable frc2.0 do 10->8 */ 4802 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4803 DITHER_DOWN_EN_SHIFT, 1, false); 4804 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK, 4805 DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_FRC, false); 4806 } else { 4807 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4808 PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 4809 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, DITHER_DOWN_SEL_MASK, 4810 DITHER_DOWN_SEL_SHIFT, DITHER_DOWN_ALLEGRO, false); 4811 } 4812 } 4813 4814 static int rockchip_vop2_init(struct display_state *state) 4815 { 4816 struct crtc_state *cstate = &state->crtc_state; 4817 struct rockchip_vp *vp = &cstate->crtc->vps[cstate->crtc_id]; 4818 struct connector_state *conn_state = &state->conn_state; 4819 struct drm_display_mode *mode = &conn_state->mode; 4820 struct vop2 *vop2 = cstate->private; 4821 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 4822 u16 hdisplay = mode->crtc_hdisplay; 4823 u16 htotal = mode->crtc_htotal; 4824 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 4825 u16 hact_end = hact_st + hdisplay; 4826 u16 vdisplay = mode->crtc_vdisplay; 4827 u16 vtotal = mode->crtc_vtotal; 4828 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 4829 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 4830 u16 vact_end = vact_st + vdisplay; 4831 bool yuv_overlay = false; 4832 u32 vp_offset = (cstate->crtc_id * 0x100); 4833 u32 line_flag_offset = (cstate->crtc_id * 4); 4834 u32 val, act_end; 4835 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 4836 u8 dclk_div_factor = 0; 4837 u8 vp_dclk_div = 1; 4838 char output_type_name[30] = {0}; 4839 #ifndef CONFIG_SPL_BUILD 4840 char dclk_name[9]; 4841 #endif 4842 struct clk hdmi0_phy_pll; 4843 struct clk hdmi1_phy_pll; 4844 struct clk hdmi_phy_pll; 4845 struct udevice *disp_dev; 4846 unsigned long dclk_rate = 0; 4847 int ret; 4848 4849 printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 4850 mode->crtc_hdisplay, mode->vdisplay, 4851 mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 4852 mode->vrefresh, 4853 rockchip_get_output_if_name(conn_state->output_if, output_type_name), 4854 cstate->crtc_id); 4855 4856 if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { 4857 cstate->splice_mode = true; 4858 cstate->splice_crtc_id = vop2->data->vp_data[cstate->crtc_id].splice_vp_id; 4859 if (!cstate->splice_crtc_id) { 4860 printf("%s: Splice mode is unsupported by vp%d\n", 4861 __func__, cstate->crtc_id); 4862 return -EINVAL; 4863 } 4864 4865 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, EN_MASK, 4866 PORT_MERGE_EN_SHIFT, 1, false); 4867 } 4868 4869 vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 4870 RK3588_VP0_LINE_FLAG_OR_EN_SHIFT + cstate->crtc_id, 1, false); 4871 vop2_mask_write(vop2, RK3588_SYS_VAR_FREQ_CTRL, EN_MASK, 4872 RK3588_VP0_ALMOST_FULL_OR_EN_SHIFT + cstate->crtc_id, 1, false); 4873 4874 if (vop2->data->vp_data[cstate->crtc_id].urgency) { 4875 u8 urgen_thl = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thl; 4876 u8 urgen_thh = vop2->data->vp_data[cstate->crtc_id].urgency->urgen_thh; 4877 4878 vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL0_IMD, EN_MASK, 4879 AXI0_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false); 4880 vop2_mask_write(vop2, RK3576_SYS_AXI_HURRY_CTRL1_IMD, EN_MASK, 4881 AXI1_PORT_URGENCY_EN_SHIFT + cstate->crtc_id, 1, false); 4882 vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, EN_MASK, 4883 POST_URGENCY_EN_SHIFT, 1, false); 4884 vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THL_MASK, 4885 POST_URGENCY_THL_SHIFT, urgen_thl, false); 4886 vop2_mask_write(vop2, RK3568_VP0_COLOR_BAR_CTRL + vp_offset, POST_URGENCY_THH_MASK, 4887 POST_URGENCY_THH_SHIFT, urgen_thh, false); 4888 } 4889 4890 vop2_initial(vop2, state); 4891 if (vop2->version == VOP_VERSION_RK3588) 4892 dclk_rate = rk3588_vop2_if_cfg(state); 4893 else if (vop2->version == VOP_VERSION_RK3576) 4894 dclk_rate = rk3576_vop2_if_cfg(state); 4895 else if (vop2->version == VOP_VERSION_RK3568) 4896 dclk_rate = rk3568_vop2_if_cfg(state); 4897 else if (vop2->version == VOP_VERSION_RK3562) 4898 dclk_rate = rk3562_vop2_if_cfg(state); 4899 else if (vop2->version == VOP_VERSION_RK3528) 4900 dclk_rate = rk3528_vop2_if_cfg(state); 4901 4902 if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 4903 !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) || 4904 conn_state->output_if & VOP_OUTPUT_IF_BT656) 4905 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 4906 4907 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 4908 if (vop2->version == VOP_VERSION_RK3588 && 4909 conn_state->type == DRM_MODE_CONNECTOR_DisplayPort) 4910 conn_state->output_mode = RK3588_DP_OUT_MODE_YUV420; 4911 } else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV422) { 4912 if (vop2->version == VOP_VERSION_RK3576 && 4913 conn_state->type == DRM_MODE_CONNECTOR_eDP) 4914 conn_state->output_mode = RK3576_EDP_OUT_MODE_YUV422; 4915 else if (vop2->version == VOP_VERSION_RK3588 && 4916 conn_state->type == DRM_MODE_CONNECTOR_eDP) 4917 conn_state->output_mode = RK3588_EDP_OUTPUT_MODE_YUV422; 4918 else if (vop2->version == VOP_VERSION_RK3576 && 4919 conn_state->type == DRM_MODE_CONNECTOR_HDMIA) 4920 conn_state->output_mode = RK3576_HDMI_OUT_MODE_YUV422; 4921 else if (conn_state->type == DRM_MODE_CONNECTOR_DisplayPort) 4922 conn_state->output_mode = RK3588_DP_OUT_MODE_YUV422; 4923 } 4924 4925 vop2_post_color_swap(state); 4926 4927 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 4928 OUT_MODE_SHIFT, conn_state->output_mode, false); 4929 4930 vop2_dither_setup(vop2, conn_state->bus_format, cstate->crtc_id); 4931 if (cstate->splice_mode) 4932 vop2_dither_setup(vop2, conn_state->bus_format, cstate->splice_crtc_id); 4933 4934 yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 4935 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 4936 yuv_overlay, false); 4937 4938 cstate->yuv_overlay = yuv_overlay; 4939 4940 vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 4941 (htotal << 16) | hsync_len); 4942 val = hact_st << 16; 4943 val |= hact_end; 4944 vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 4945 val = vact_st << 16; 4946 val |= vact_end; 4947 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 4948 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 4949 u16 vact_st_f1 = vtotal + vact_st + 1; 4950 u16 vact_end_f1 = vact_st_f1 + vdisplay; 4951 4952 val = vact_st_f1 << 16 | vact_end_f1; 4953 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 4954 val); 4955 4956 val = vtotal << 16 | (vtotal + vsync_len); 4957 vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 4958 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4959 INTERLACE_EN_SHIFT, 1, false); 4960 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4961 DSP_FILED_POL, 1, false); 4962 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4963 P2I_EN_SHIFT, 1, false); 4964 vtotal += vtotal + 1; 4965 act_end = vact_end_f1; 4966 } else { 4967 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4968 INTERLACE_EN_SHIFT, 0, false); 4969 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4970 P2I_EN_SHIFT, 0, false); 4971 act_end = vact_end; 4972 } 4973 vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 4974 (vtotal << 16) | vsync_len); 4975 4976 if (vop2->version == VOP_VERSION_RK3528 || 4977 vop2->version == VOP_VERSION_RK3562 || 4978 vop2->version == VOP_VERSION_RK3568) { 4979 if (mode->flags & DRM_MODE_FLAG_DBLCLK || 4980 conn_state->output_if & VOP_OUTPUT_IF_BT656) 4981 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4982 CORE_DCLK_DIV_EN_SHIFT, 1, false); 4983 else 4984 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 4985 CORE_DCLK_DIV_EN_SHIFT, 0, false); 4986 4987 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 4988 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 4989 DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 4990 else 4991 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 4992 DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 4993 } 4994 4995 vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 4996 OVL_MODE_SEL_SHIFT + cstate->crtc_id, yuv_overlay, false); 4997 4998 if (yuv_overlay) 4999 val = 0x20010200; 5000 else 5001 val = 0; 5002 vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 5003 if (cstate->splice_mode) { 5004 vop2_mask_write(vop2, RK3568_OVL_CTRL, OVL_MODE_SEL_MASK, 5005 OVL_MODE_SEL_SHIFT + cstate->splice_crtc_id, 5006 yuv_overlay, false); 5007 vop2_writel(vop2, RK3568_VP0_DSP_BG + (cstate->splice_crtc_id * 0x100), val); 5008 } 5009 5010 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5011 POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 5012 5013 if (vp->xmirror_en) 5014 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5015 DSP_X_MIR_EN_SHIFT, 1, false); 5016 5017 vop2_tv_config_update(state, vop2); 5018 vop2_post_config(state, vop2); 5019 if (cstate->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) 5020 vop3_post_config(state, vop2); 5021 5022 if (cstate->dsc_enable) { 5023 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 5024 vop2_dsc_enable(state, vop2, 0, dclk_rate * 1000LL); 5025 vop2_dsc_enable(state, vop2, 1, dclk_rate * 1000LL); 5026 } else { 5027 vop2_dsc_enable(state, vop2, cstate->dsc_id, dclk_rate * 1000LL); 5028 } 5029 } 5030 5031 #ifndef CONFIG_SPL_BUILD 5032 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 5033 ret = clk_get_by_name(cstate->dev, dclk_name, &cstate->dclk); 5034 if (ret) { 5035 printf("%s: Failed to get dclk ret=%d\n", __func__, ret); 5036 return ret; 5037 } 5038 #endif 5039 5040 ret = uclass_get_device_by_name(UCLASS_VIDEO, "display-subsystem", &disp_dev); 5041 if (!ret) { 5042 ret = clk_get_by_name(disp_dev, "hdmi0_phy_pll", &hdmi0_phy_pll); 5043 if (ret) 5044 debug("%s: hdmi0_phy_pll may not define\n", __func__); 5045 ret = clk_get_by_name(disp_dev, "hdmi1_phy_pll", &hdmi1_phy_pll); 5046 if (ret) 5047 debug("%s: hdmi1_phy_pll may not define\n", __func__); 5048 } else { 5049 hdmi0_phy_pll.dev = NULL; 5050 hdmi1_phy_pll.dev = NULL; 5051 debug("%s: Faile to find display-subsystem node\n", __func__); 5052 } 5053 5054 if (vop2->version == VOP_VERSION_RK3528) { 5055 struct ofnode_phandle_args args; 5056 5057 ret = dev_read_phandle_with_args(cstate->dev, "assigned-clock-parents", 5058 "#clock-cells", 0, 0, &args); 5059 if (!ret) { 5060 ret = uclass_find_device_by_ofnode(UCLASS_CLK, args.node, &hdmi0_phy_pll.dev); 5061 if (ret) { 5062 debug("warn: can't get clk device\n"); 5063 return ret; 5064 } 5065 } else { 5066 debug("assigned-clock-parents's node not define\n"); 5067 } 5068 } 5069 5070 if (vop2->version == VOP_VERSION_RK3576) 5071 vp_dclk_div = cstate->crtc->vps[cstate->crtc_id].dclk_div; 5072 5073 if (mode->crtc_clock < VOP2_MAX_DCLK_RATE) { 5074 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) 5075 vop2_clk_set_parent(&cstate->dclk, &hdmi0_phy_pll); 5076 else if (conn_state->output_if & VOP_OUTPUT_IF_HDMI1) 5077 vop2_clk_set_parent(&cstate->dclk, &hdmi1_phy_pll); 5078 5079 /* 5080 * uboot clk driver won't set dclk parent's rate when use 5081 * hdmi phypll as dclk source. 5082 * So set dclk rate is meaningless. Set hdmi phypll rate 5083 * directly. 5084 */ 5085 if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI0) && hdmi0_phy_pll.dev) { 5086 ret = vop2_clk_set_rate(&hdmi0_phy_pll, dclk_rate / vp_dclk_div * 1000); 5087 } else if ((conn_state->output_if & VOP_OUTPUT_IF_HDMI1) && hdmi1_phy_pll.dev) { 5088 ret = vop2_clk_set_rate(&hdmi1_phy_pll, dclk_rate / vp_dclk_div * 1000); 5089 } else { 5090 if (is_extend_pll(state, &hdmi_phy_pll.dev)) { 5091 ret = vop2_clk_set_rate(&hdmi_phy_pll, 5092 dclk_rate / vp_dclk_div * 1000); 5093 } else { 5094 #ifndef CONFIG_SPL_BUILD 5095 ret = vop2_clk_set_rate(&cstate->dclk, 5096 dclk_rate / vp_dclk_div * 1000); 5097 #else 5098 if (vop2->version == VOP_VERSION_RK3528) { 5099 void *cru_base = (void *)RK3528_CRU_BASE; 5100 5101 /* dclk src switch to hdmiphy pll */ 5102 writel((BIT(0) << 16) | BIT(0), cru_base + 0x450); 5103 rockchip_phy_set_pll(conn_state->connector->phy, dclk_rate * 1000); 5104 ret = dclk_rate * 1000; 5105 } 5106 #endif 5107 } 5108 } 5109 } else { 5110 if (is_extend_pll(state, &hdmi_phy_pll.dev)) 5111 ret = vop2_clk_set_rate(&hdmi_phy_pll, dclk_rate / vp_dclk_div * 1000); 5112 else 5113 ret = vop2_clk_set_rate(&cstate->dclk, dclk_rate / vp_dclk_div * 1000); 5114 } 5115 5116 if (IS_ERR_VALUE(ret)) { 5117 printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 5118 __func__, cstate->crtc_id, dclk_rate, ret); 5119 return ret; 5120 } else { 5121 if (cstate->mcu_timing.mcu_pix_total) { 5122 mode->crtc_clock = roundup(ret, 1000) / 1000; 5123 } else { 5124 dclk_div_factor = mode->crtc_clock / dclk_rate; 5125 mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000; 5126 } 5127 printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); 5128 } 5129 5130 vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 5131 RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end, false); 5132 vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 5133 RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end, false); 5134 5135 if (cstate->mcu_timing.mcu_pix_total) { 5136 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5137 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5138 STANDBY_EN_SHIFT, 0, false); 5139 vop3_mcu_mode_setup(state); 5140 } 5141 5142 return 0; 5143 } 5144 5145 static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 5146 uint32_t src_w, uint32_t src_h, uint32_t dst_w, 5147 uint32_t dst_h) 5148 { 5149 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 5150 uint16_t hscl_filter_mode, vscl_filter_mode; 5151 uint8_t xgt2 = 0, xgt4 = 0; 5152 uint8_t ygt2 = 0, ygt4 = 0; 5153 uint32_t xfac = 0, yfac = 0; 5154 u32 win_offset = win->reg_offset; 5155 bool xgt_en = false; 5156 bool xavg_en = false; 5157 5158 if (is_vop3(vop2)) { 5159 if (vop2->version == VOP_VERSION_RK3576 && win->type == CLUSTER_LAYER) { 5160 if (src_w >= (8 * dst_w)) { 5161 xgt4 = 1; 5162 src_w >>= 2; 5163 } else if (src_w >= (4 * dst_w)) { 5164 xgt2 = 1; 5165 src_w >>= 1; 5166 } 5167 } else { 5168 if (src_w >= (4 * dst_w)) { 5169 xgt4 = 1; 5170 src_w >>= 2; 5171 } else if (src_w >= (2 * dst_w)) { 5172 xgt2 = 1; 5173 src_w >>= 1; 5174 } 5175 } 5176 } 5177 5178 /** 5179 * The rk3528 is processed as 2 pixel/cycle, 5180 * so ygt2/ygt4 needs to be triggered in advance to improve performance 5181 * when src_w is bigger than 1920. 5182 * dst_h / src_h is at [1, 0.65) ygt2=0; ygt4=0; 5183 * dst_h / src_h is at [0.65, 0.35) ygt2=1; ygt4=0; 5184 * dst_h / src_h is at [0.35, 0) ygt2=0; ygt4=1; 5185 */ 5186 if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) { 5187 if (src_h >= (100 * dst_h / 35)) { 5188 ygt4 = 1; 5189 src_h >>= 2; 5190 } else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) { 5191 ygt2 = 1; 5192 src_h >>= 1; 5193 } 5194 } else { 5195 if (win->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { 5196 if (src_h >= (8 * dst_h)) { 5197 ygt4 = 1; 5198 src_h >>= 2; 5199 } else if (src_h >= (4 * dst_h)) { 5200 ygt2 = 1; 5201 src_h >>= 1; 5202 } 5203 } else { 5204 if (src_h >= (4 * dst_h)) { 5205 ygt4 = 1; 5206 src_h >>= 2; 5207 } else if (src_h >= (2 * dst_h)) { 5208 ygt2 = 1; 5209 src_h >>= 1; 5210 } 5211 } 5212 } 5213 5214 yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 5215 yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 5216 5217 if (yrgb_hor_scl_mode == SCALE_UP) 5218 hscl_filter_mode = win->hsu_filter_mode; 5219 else 5220 hscl_filter_mode = win->hsd_filter_mode; 5221 5222 if (yrgb_ver_scl_mode == SCALE_UP) 5223 vscl_filter_mode = win->vsu_filter_mode; 5224 else 5225 vscl_filter_mode = win->vsd_filter_mode; 5226 5227 /* 5228 * RK3568 VOP Esmart/Smart dsp_w should be even pixel 5229 * at scale down mode 5230 */ 5231 if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1) && !is_vop3(vop2)) { 5232 printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 5233 dst_w += 1; 5234 } 5235 5236 if (is_vop3(vop2)) { 5237 xfac = vop3_scale_factor(yrgb_hor_scl_mode, src_w, dst_w, true); 5238 yfac = vop3_scale_factor(yrgb_ver_scl_mode, src_h, dst_h, false); 5239 5240 if (win->hsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_AVG) 5241 xavg_en = xgt2 || xgt4; 5242 else 5243 xgt_en = xgt2 || xgt4; 5244 5245 if (vop2->version == VOP_VERSION_RK3576) { 5246 bool zme_dering_en = false; 5247 5248 if ((yrgb_hor_scl_mode == SCALE_UP && 5249 hscl_filter_mode == VOP2_SCALE_UP_ZME) || 5250 (yrgb_ver_scl_mode == SCALE_UP && 5251 vscl_filter_mode == VOP2_SCALE_UP_ZME)) 5252 zme_dering_en = true; 5253 5254 /* Recommended configuration from the algorithm */ 5255 vop2_writel(vop2, RK3576_CLUSTER0_WIN0_ZME_DERING_PARA + win_offset, 5256 0x04100d10); 5257 vop2_mask_write(vop2, RK3576_CLUSTER0_WIN0_ZME_CTRL + win_offset, 5258 EN_MASK, WIN0_ZME_DERING_EN_SHIFT, zme_dering_en, false); 5259 } 5260 } else { 5261 xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 5262 yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 5263 } 5264 5265 if (win->type == CLUSTER_LAYER) { 5266 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 5267 yfac << 16 | xfac); 5268 5269 if (is_vop3(vop2)) { 5270 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5271 EN_MASK, CLUSTER_XGT_EN_SHIFT, xgt_en, false); 5272 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5273 EN_MASK, CLUSTER_XAVG_EN_SHIFT, xavg_en, false); 5274 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5275 XGT_MODE_MASK, CLUSTER_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 5276 5277 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5278 YRGB_XSCL_MODE_MASK, RK3528_CLUSTER_YRGB_XSCL_MODE_SHIFT, 5279 yrgb_hor_scl_mode, false); 5280 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5281 YRGB_YSCL_MODE_MASK, RK3528_CLUSTER_YRGB_YSCL_MODE_SHIFT, 5282 yrgb_ver_scl_mode, false); 5283 } else { 5284 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5285 YRGB_XSCL_MODE_MASK, RK3568_CLUSTER_YRGB_XSCL_MODE_SHIFT, 5286 yrgb_hor_scl_mode, false); 5287 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5288 YRGB_YSCL_MODE_MASK, RK3568_CLUSTER_YRGB_YSCL_MODE_SHIFT, 5289 yrgb_ver_scl_mode, false); 5290 } 5291 5292 if (!is_vop3(vop2) || win->vsd_pre_filter_mode == VOP3_PRE_SCALE_DOWN_GT) { 5293 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5294 YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, ygt2, false); 5295 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5296 YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, ygt4, false); 5297 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5298 AVG2_MASK, CLUSTER_AVG2_SHIFT, 0, false); 5299 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5300 AVG4_MASK, CLUSTER_AVG4_SHIFT, 0, false); 5301 } else { 5302 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5303 YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, 0, false); 5304 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5305 YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, 0, false); 5306 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5307 AVG2_MASK, CLUSTER_AVG2_SHIFT, ygt2, false); 5308 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 5309 AVG4_MASK, CLUSTER_AVG4_SHIFT, ygt4, false); 5310 } 5311 } else { 5312 vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 5313 yfac << 16 | xfac); 5314 5315 if (is_vop3(vop2)) { 5316 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5317 EN_MASK, ESMART_XGT_EN_SHIFT, xgt_en, false); 5318 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5319 EN_MASK, ESMART_XAVG_EN_SHIFT, xavg_en, false); 5320 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5321 XGT_MODE_MASK, ESMART_XGT_MODE_SHIFT, xgt2 ? 0 : 1, false); 5322 } 5323 5324 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5325 YRGB_GT2_MASK, YRGB_GT2_SHIFT, ygt2, false); 5326 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5327 YRGB_GT4_MASK, YRGB_GT4_SHIFT, ygt4, false); 5328 5329 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 5330 YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 5331 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 5332 YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 5333 5334 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 5335 YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 5336 hscl_filter_mode, false); 5337 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 5338 YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 5339 vscl_filter_mode, false); 5340 } 5341 } 5342 5343 static void vop2_axi_config(struct vop2 *vop2, struct vop2_win_data *win) 5344 { 5345 u32 win_offset = win->reg_offset; 5346 5347 if (win->type == CLUSTER_LAYER) { 5348 vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, CLUSTER_AXI_ID_MASK, 5349 CLUSTER_AXI_ID_SHIFT, win->axi_id, false); 5350 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_YRGB_ID_MASK, 5351 CLUSTER_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 5352 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL2 + win_offset, CLUSTER_AXI_UV_ID_MASK, 5353 CLUSTER_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 5354 } else { 5355 vop2_mask_write(vop2, RK3568_ESMART0_AXI_CTRL + win_offset, ESMART_AXI_ID_MASK, 5356 ESMART_AXI_ID_SHIFT, win->axi_id, false); 5357 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_YRGB_ID_MASK, 5358 ESMART_AXI_YRGB_ID_SHIFT, win->axi_yrgb_id, false); 5359 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, ESMART_AXI_UV_ID_MASK, 5360 ESMART_AXI_UV_ID_SHIFT, win->axi_uv_id, false); 5361 } 5362 } 5363 5364 static bool vop2_win_dither_up(uint32_t format) 5365 { 5366 switch (format) { 5367 case ROCKCHIP_FMT_RGB565: 5368 return true; 5369 default: 5370 return false; 5371 } 5372 } 5373 5374 static bool vop2_is_mirror_win(struct vop2_win_data *win) 5375 { 5376 return soc_is_rk3566() && (win->feature & WIN_FEATURE_MIRROR); 5377 } 5378 5379 static int vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 5380 { 5381 struct crtc_state *cstate = &state->crtc_state; 5382 struct connector_state *conn_state = &state->conn_state; 5383 struct drm_display_mode *mode = &conn_state->mode; 5384 struct vop2 *vop2 = cstate->private; 5385 const struct vop2_data *vop2_data = vop2->data; 5386 const struct vop2_ops *vop2_ops = vop2_data->ops; 5387 int src_w = cstate->src_rect.w; 5388 int src_h = cstate->src_rect.h; 5389 int crtc_x = cstate->crtc_rect.x; 5390 int crtc_y = cstate->crtc_rect.y; 5391 int crtc_w = cstate->crtc_rect.w; 5392 int crtc_h = cstate->crtc_rect.h; 5393 int xvir = cstate->xvir; 5394 int y_mirror = 0; 5395 int csc_mode; 5396 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 5397 /* offset of the right window in splice mode */ 5398 u32 splice_pixel_offset = 0; 5399 u32 splice_yrgb_offset = 0; 5400 u32 win_offset = win->reg_offset; 5401 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5402 bool dither_up; 5403 5404 if (win->splice_mode_right) { 5405 src_w = cstate->right_src_rect.w; 5406 src_h = cstate->right_src_rect.h; 5407 crtc_x = cstate->right_crtc_rect.x; 5408 crtc_y = cstate->right_crtc_rect.y; 5409 crtc_w = cstate->right_crtc_rect.w; 5410 crtc_h = cstate->right_crtc_rect.h; 5411 splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 5412 splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 5413 cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5414 } 5415 5416 act_info = (src_h - 1) << 16; 5417 act_info |= (src_w - 1) & 0xffff; 5418 5419 dsp_info = (crtc_h - 1) << 16; 5420 dsp_info |= (crtc_w - 1) & 0xffff; 5421 5422 dsp_stx = crtc_x; 5423 dsp_sty = crtc_y; 5424 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 5425 5426 if (mode->flags & DRM_MODE_FLAG_YMIRROR) 5427 y_mirror = 1; 5428 else 5429 y_mirror = 0; 5430 5431 vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 5432 5433 if (vop2->version != VOP_VERSION_RK3568) 5434 vop2_axi_config(vop2, win); 5435 5436 if (y_mirror) 5437 printf("WARN: y mirror is unsupported by cluster window\n"); 5438 5439 if (is_vop3(vop2)) { 5440 vop2_mask_write(vop2, RK3576_CLUSTER0_PORT_SEL + win_offset, 5441 CLUSTER_PORT_SEL_MASK, CLUSTER_PORT_SEL_SHIFT, 5442 cstate->crtc_id, false); 5443 vop2_ops->setup_win_dly(state, cstate->crtc_id); 5444 } 5445 5446 /* 5447 * rk3588 and later platforms should set half_blocK_en to 1 in line and tile mode. 5448 */ 5449 if (vop2->version >= VOP_VERSION_RK3588) 5450 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_AFBCD_CTRL + win_offset, 5451 EN_MASK, CLUSTER_AFBCD_HALF_BLOCK_SHIFT, 1, false); 5452 5453 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 5454 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 5455 false); 5456 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 5457 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, 5458 cstate->dma_addr + splice_yrgb_offset); 5459 5460 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 5461 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 5462 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 5463 5464 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 5465 5466 csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range, 5467 CSC_10BIT_DEPTH); 5468 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 5469 CLUSTER_RGB2YUV_EN_SHIFT, 5470 is_yuv_output(conn_state->bus_format), false); 5471 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 5472 CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 5473 5474 dither_up = vop2_win_dither_up(cstate->format); 5475 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 5476 CLUSTER_DITHER_UP_EN_SHIFT, dither_up, false); 5477 5478 vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 5479 5480 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5481 5482 return 0; 5483 } 5484 5485 static int vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 5486 { 5487 struct crtc_state *cstate = &state->crtc_state; 5488 struct connector_state *conn_state = &state->conn_state; 5489 struct drm_display_mode *mode = &conn_state->mode; 5490 struct vop2 *vop2 = cstate->private; 5491 const struct vop2_data *vop2_data = vop2->data; 5492 const struct vop2_ops *vop2_ops = vop2_data->ops; 5493 int src_w = cstate->src_rect.w; 5494 int src_h = cstate->src_rect.h; 5495 int crtc_x = cstate->crtc_rect.x; 5496 int crtc_y = cstate->crtc_rect.y; 5497 int crtc_w = cstate->crtc_rect.w; 5498 int crtc_h = cstate->crtc_rect.h; 5499 int xvir = cstate->xvir; 5500 int y_mirror = 0; 5501 int csc_mode; 5502 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 5503 /* offset of the right window in splice mode */ 5504 u32 splice_pixel_offset = 0; 5505 u32 splice_yrgb_offset = 0; 5506 u32 win_offset = win->reg_offset; 5507 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5508 u32 val; 5509 bool dither_up; 5510 5511 if (vop2_is_mirror_win(win)) { 5512 struct vop2_win_data *source_win = vop2_find_win_by_phys_id(vop2, win->source_win_id); 5513 5514 if (!source_win) { 5515 printf("invalid source win id %d\n", win->source_win_id); 5516 return -ENODEV; 5517 } 5518 5519 val = vop2_readl(vop2, RK3568_ESMART0_REGION0_CTRL + source_win->reg_offset); 5520 if (!(val & BIT(WIN_EN_SHIFT))) { 5521 printf("WARN: the source win should be enabled before mirror win\n"); 5522 return -EAGAIN; 5523 } 5524 } 5525 5526 if (win->splice_mode_right) { 5527 src_w = cstate->right_src_rect.w; 5528 src_h = cstate->right_src_rect.h; 5529 crtc_x = cstate->right_crtc_rect.x; 5530 crtc_y = cstate->right_crtc_rect.y; 5531 crtc_w = cstate->right_crtc_rect.w; 5532 crtc_h = cstate->right_crtc_rect.h; 5533 splice_pixel_offset = cstate->right_src_rect.x - cstate->src_rect.x; 5534 splice_yrgb_offset = splice_pixel_offset * (state->logo.bpp >> 3); 5535 cfg_done = CFG_DONE_EN | BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5536 } 5537 5538 /* 5539 * This is workaround solution for IC design: 5540 * esmart can't support scale down when actual_w % 16 == 1. 5541 */ 5542 if (src_w > crtc_w && (src_w & 0xf) == 1) { 5543 printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 5544 src_w -= 1; 5545 } 5546 5547 act_info = (src_h - 1) << 16; 5548 act_info |= (src_w - 1) & 0xffff; 5549 5550 dsp_info = (crtc_h - 1) << 16; 5551 dsp_info |= (crtc_w - 1) & 0xffff; 5552 5553 dsp_stx = crtc_x; 5554 dsp_sty = crtc_y; 5555 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 5556 5557 if (mode->flags & DRM_MODE_FLAG_YMIRROR) 5558 y_mirror = 1; 5559 else 5560 y_mirror = 0; 5561 5562 if (is_vop3(vop2)) { 5563 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, 5564 ESMART_LB_SELECT_MASK, ESMART_LB_SELECT_SHIFT, 5565 win->scale_engine_num, false); 5566 vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset, 5567 ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT, 5568 cstate->crtc_id, false); 5569 vop2_ops->setup_win_dly(state, cstate->crtc_id); 5570 5571 /* Merge esmart1/3 from vp1 post to vp0 */ 5572 if (vop2->version == VOP_VERSION_RK3576 && cstate->crtc_id == 0 && 5573 (win->phys_id == ROCKCHIP_VOP2_ESMART1 || 5574 win->phys_id == ROCKCHIP_VOP2_ESMART3)) 5575 vop2_mask_write(vop2, RK3576_ESMART0_PORT_SEL + win_offset, 5576 ESMART_PORT_SEL_MASK, ESMART_PORT_SEL_SHIFT, 5577 1, false); 5578 } 5579 5580 vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 5581 5582 if (vop2->version != VOP_VERSION_RK3568) 5583 vop2_axi_config(vop2, win); 5584 5585 if (y_mirror) 5586 cstate->dma_addr += (src_h - 1) * xvir * 4; 5587 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 5588 YMIRROR_EN_SHIFT, y_mirror, false); 5589 5590 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 5591 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 5592 false); 5593 5594 if (vop2->version == VOP_VERSION_RK3576) 5595 vop2_writel(vop2, RK3576_ESMART0_ALPHA_MAP + win_offset, 0x8000ff00); 5596 5597 vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 5598 vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 5599 cstate->dma_addr + splice_yrgb_offset); 5600 5601 vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 5602 act_info); 5603 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 5604 dsp_info); 5605 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 5606 5607 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 5608 WIN_EN_SHIFT, 1, false); 5609 5610 csc_mode = vop2_convert_csc_mode(conn_state->color_encoding, conn_state->color_range, 5611 CSC_10BIT_DEPTH); 5612 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 5613 RGB2YUV_EN_SHIFT, 5614 is_yuv_output(conn_state->bus_format), false); 5615 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 5616 CSC_MODE_SHIFT, csc_mode, false); 5617 5618 dither_up = vop2_win_dither_up(cstate->format); 5619 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 5620 REGION0_DITHER_UP_EN_SHIFT, dither_up, false); 5621 5622 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5623 5624 return 0; 5625 } 5626 5627 static void vop2_calc_display_rect_for_splice(struct display_state *state) 5628 { 5629 struct crtc_state *cstate = &state->crtc_state; 5630 struct connector_state *conn_state = &state->conn_state; 5631 struct drm_display_mode *mode = &conn_state->mode; 5632 struct display_rect *src_rect = &cstate->src_rect; 5633 struct display_rect *dst_rect = &cstate->crtc_rect; 5634 struct display_rect left_src, left_dst, right_src, right_dst; 5635 u16 half_hdisplay = mode->crtc_hdisplay >> 1; 5636 int left_src_w, left_dst_w, right_dst_w; 5637 5638 left_dst_w = min_t(u16, half_hdisplay, dst_rect->x + dst_rect->w) - dst_rect->x; 5639 if (left_dst_w < 0) 5640 left_dst_w = 0; 5641 right_dst_w = dst_rect->w - left_dst_w; 5642 5643 if (!right_dst_w) 5644 left_src_w = src_rect->w; 5645 else 5646 left_src_w = src_rect->x + src_rect->w - src_rect->w / 2; 5647 5648 left_src.x = src_rect->x; 5649 left_src.w = left_src_w; 5650 left_dst.x = dst_rect->x; 5651 left_dst.w = left_dst_w; 5652 right_src.x = left_src.x + left_src.w; 5653 right_src.w = src_rect->x + src_rect->w - left_src.x - left_src.w; 5654 right_dst.x = dst_rect->x + left_dst_w - half_hdisplay; 5655 right_dst.w = right_dst_w; 5656 5657 left_src.y = src_rect->y; 5658 left_src.h = src_rect->h; 5659 left_dst.y = dst_rect->y; 5660 left_dst.h = dst_rect->h; 5661 right_src.y = src_rect->y; 5662 right_src.h = src_rect->h; 5663 right_dst.y = dst_rect->y; 5664 right_dst.h = dst_rect->h; 5665 5666 memcpy(&cstate->src_rect, &left_src, sizeof(struct display_rect)); 5667 memcpy(&cstate->crtc_rect, &left_dst, sizeof(struct display_rect)); 5668 memcpy(&cstate->right_src_rect, &right_src, sizeof(struct display_rect)); 5669 memcpy(&cstate->right_crtc_rect, &right_dst, sizeof(struct display_rect)); 5670 } 5671 5672 static int rockchip_vop2_set_plane(struct display_state *state) 5673 { 5674 struct crtc_state *cstate = &state->crtc_state; 5675 struct vop2 *vop2 = cstate->private; 5676 struct vop2_win_data *win_data; 5677 struct vop2_win_data *splice_win_data; 5678 u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 5679 int ret; 5680 5681 if (cstate->crtc_rect.w > cstate->max_output.width) { 5682 printf("ERROR: output w[%d] exceeded max width[%d]\n", 5683 cstate->crtc_rect.w, cstate->max_output.width); 5684 return -EINVAL; 5685 } 5686 5687 win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 5688 if (!win_data) { 5689 printf("invalid win id %d\n", primary_plane_id); 5690 return -ENODEV; 5691 } 5692 5693 /* ignore some plane register according vop3 esmart lb mode */ 5694 if (vop3_ignore_plane(vop2, win_data)) 5695 return -EACCES; 5696 5697 if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) { 5698 if (vop2_power_domain_on(vop2, win_data->pd_id)) 5699 printf("open vp%d plane pd fail\n", cstate->crtc_id); 5700 } 5701 5702 if (cstate->splice_mode) { 5703 if (win_data->splice_win_id) { 5704 splice_win_data = vop2_find_win_by_phys_id(vop2, win_data->splice_win_id); 5705 splice_win_data->splice_mode_right = true; 5706 5707 if (vop2_power_domain_on(vop2, splice_win_data->pd_id)) 5708 printf("splice mode: open vp%d plane pd fail\n", cstate->splice_crtc_id); 5709 5710 vop2_calc_display_rect_for_splice(state); 5711 if (win_data->type == CLUSTER_LAYER) 5712 vop2_set_cluster_win(state, splice_win_data); 5713 else 5714 vop2_set_smart_win(state, splice_win_data); 5715 } else { 5716 printf("ERROR: splice mode is unsupported by plane %s\n", 5717 vop2_plane_phys_id_to_string(primary_plane_id)); 5718 return -EINVAL; 5719 } 5720 } 5721 5722 if (win_data->type == CLUSTER_LAYER) 5723 ret = vop2_set_cluster_win(state, win_data); 5724 else 5725 ret = vop2_set_smart_win(state, win_data); 5726 if (ret) 5727 return ret; 5728 5729 printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 5730 cstate->crtc_id, vop2_plane_phys_id_to_string(primary_plane_id), 5731 cstate->src_rect.w, cstate->src_rect.h, cstate->crtc_rect.w, cstate->crtc_rect.h, 5732 cstate->crtc_rect.x, cstate->crtc_rect.y, cstate->format, 5733 cstate->dma_addr); 5734 5735 return 0; 5736 } 5737 5738 static int rockchip_vop2_prepare(struct display_state *state) 5739 { 5740 return 0; 5741 } 5742 5743 static void vop2_dsc_cfg_done(struct display_state *state) 5744 { 5745 struct connector_state *conn_state = &state->conn_state; 5746 struct crtc_state *cstate = &state->crtc_state; 5747 struct vop2 *vop2 = cstate->private; 5748 u8 dsc_id = cstate->dsc_id; 5749 u32 ctrl_regs_offset = (dsc_id * 0x30); 5750 5751 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 5752 vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE, EN_MASK, 5753 DSC_CFG_DONE_SHIFT, 1, false); 5754 vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + 0x30, EN_MASK, 5755 DSC_CFG_DONE_SHIFT, 1, false); 5756 } else { 5757 vop2_mask_write(vop2, RK3588_DSC_8K_CFG_DONE + ctrl_regs_offset, EN_MASK, 5758 DSC_CFG_DONE_SHIFT, 1, false); 5759 } 5760 } 5761 5762 static int rockchip_vop2_enable(struct display_state *state) 5763 { 5764 struct crtc_state *cstate = &state->crtc_state; 5765 struct vop2 *vop2 = cstate->private; 5766 u32 vp_offset = (cstate->crtc_id * 0x100); 5767 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5768 5769 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5770 STANDBY_EN_SHIFT, 0, false); 5771 5772 if (cstate->splice_mode) 5773 cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5774 5775 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5776 5777 if (cstate->dsc_enable) 5778 vop2_dsc_cfg_done(state); 5779 5780 if (cstate->mcu_timing.mcu_pix_total) 5781 vop2_mask_write(vop2, RK3562_VP0_MCU_CTRL + vp_offset, EN_MASK, 5782 MCU_HOLD_MODE_SHIFT, 0, false); 5783 5784 return 0; 5785 } 5786 5787 static int rk3588_vop2_post_enable(struct display_state *state) 5788 { 5789 struct connector_state *conn_state = &state->conn_state; 5790 struct crtc_state *cstate = &state->crtc_state; 5791 struct vop2 *vop2 = cstate->private; 5792 int output_if = conn_state->output_if; 5793 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5794 int ret, val; 5795 5796 if (output_if & VOP_OUTPUT_IF_DP0) 5797 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 5798 1, false); 5799 5800 if (output_if & VOP_OUTPUT_IF_DP1) 5801 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP1_EN_SHIFT, 5802 1, false); 5803 5804 if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) { 5805 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5806 ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val, 5807 val & BIT(cstate->crtc_id), 50 * 1000); 5808 if (ret) 5809 printf("%s wait cfg done timeout\n", __func__); 5810 5811 if (cstate->dclk_rst.dev) { 5812 reset_assert(&cstate->dclk_rst); 5813 udelay(20); 5814 reset_deassert(&cstate->dclk_rst); 5815 } 5816 } 5817 5818 return 0; 5819 } 5820 5821 static int rk3576_vop2_post_enable(struct display_state *state) 5822 { 5823 struct connector_state *conn_state = &state->conn_state; 5824 struct crtc_state *cstate = &state->crtc_state; 5825 struct vop2 *vop2 = cstate->private; 5826 int output_if = conn_state->output_if; 5827 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5828 int ret, val; 5829 5830 if (output_if & VOP_OUTPUT_IF_DP0) 5831 vop2_mask_write(vop2, RK3576_DP0_IF_CTRL, EN_MASK, 5832 RK3576_IF_OUT_EN_SHIFT, 1, false); 5833 5834 if (output_if & VOP_OUTPUT_IF_DP1) 5835 vop2_mask_write(vop2, RK3576_DP1_IF_CTRL, EN_MASK, 5836 RK3576_IF_OUT_EN_SHIFT, 1, false); 5837 5838 if (output_if & VOP_OUTPUT_IF_DP2) 5839 vop2_mask_write(vop2, RK3576_DP2_IF_CTRL, EN_MASK, 5840 RK3576_IF_OUT_EN_SHIFT, 1, false); 5841 5842 if (output_if & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) { 5843 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5844 ret = readl_poll_timeout(vop2->regs + RK3568_REG_CFG_DONE, val, 5845 val & BIT(cstate->crtc_id), 50 * 1000); 5846 if (ret) 5847 printf("%s wait cfg done timeout\n", __func__); 5848 5849 if (cstate->dclk_rst.dev) { 5850 reset_assert(&cstate->dclk_rst); 5851 udelay(20); 5852 reset_deassert(&cstate->dclk_rst); 5853 } 5854 } 5855 5856 return 0; 5857 } 5858 5859 static int rockchip_vop2_post_enable(struct display_state *state) 5860 { 5861 struct crtc_state *cstate = &state->crtc_state; 5862 struct vop2 *vop2 = cstate->private; 5863 5864 if (vop2->version == VOP_VERSION_RK3588) 5865 rk3588_vop2_post_enable(state); 5866 else if (vop2->version == VOP_VERSION_RK3576) 5867 rk3576_vop2_post_enable(state); 5868 5869 return 0; 5870 } 5871 5872 static int rockchip_vop2_disable(struct display_state *state) 5873 { 5874 struct crtc_state *cstate = &state->crtc_state; 5875 struct vop2 *vop2 = cstate->private; 5876 u32 vp_offset = (cstate->crtc_id * 0x100); 5877 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 5878 5879 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 5880 STANDBY_EN_SHIFT, 1, false); 5881 5882 if (cstate->splice_mode) 5883 cfg_done |= BIT(cstate->splice_crtc_id) | (BIT(cstate->splice_crtc_id) << 16); 5884 5885 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 5886 5887 return 0; 5888 } 5889 5890 static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 5891 { 5892 struct crtc_state *cstate = &state->crtc_state; 5893 struct vop2 *vop2 = cstate->private; 5894 ofnode vp_node; 5895 struct device_node *port_parent_node = cstate->ports_node; 5896 static bool vop_fix_dts; 5897 const char *path; 5898 u32 plane_mask = 0; 5899 int vp_id = 0; 5900 5901 /* 5902 * For vop3, &vop2_vp_plane_mask.plane_mask will not be fixup in 5903 * &rockchip_crtc_funcs.fixup_dts(), because planes can be switched 5904 * between different CRTCs flexibly and the userspace do not need 5905 * the plane_mask to restrict the binding between the crtc and plane. 5906 * We just find a expected plane for logo display. 5907 */ 5908 if (vop_fix_dts || is_vop3(vop2)) 5909 return 0; 5910 5911 ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 5912 path = vp_node.np->full_name; 5913 plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 5914 5915 if (cstate->crtc->assign_plane) 5916 continue; 5917 5918 printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 5919 vp_id, plane_mask, 5920 vop2->vp_plane_mask[vp_id].primary_plane_id, 5921 vop2->vp_plane_mask[vp_id].cursor_plane_id); 5922 5923 do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 5924 plane_mask, 1); 5925 do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 5926 vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 5927 if (vop2->vp_plane_mask[vp_id].cursor_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) 5928 do_fixup_by_path_u32(blob, path, "cursor-win-id", 5929 vop2->vp_plane_mask[vp_id].cursor_plane_id, 1); 5930 vp_id++; 5931 } 5932 5933 vop_fix_dts = true; 5934 5935 return 0; 5936 } 5937 5938 static int rockchip_vop2_check(struct display_state *state) 5939 { 5940 struct crtc_state *cstate = &state->crtc_state; 5941 struct rockchip_crtc *crtc = cstate->crtc; 5942 5943 if (crtc->splice_mode && cstate->crtc_id == crtc->splice_crtc_id) { 5944 printf("WARN: VP%d is busy in splice mode\n", cstate->crtc_id); 5945 return -ENOTSUPP; 5946 } 5947 5948 if (cstate->splice_mode) { 5949 crtc->splice_mode = true; 5950 crtc->splice_crtc_id = cstate->splice_crtc_id; 5951 } 5952 5953 return 0; 5954 } 5955 5956 static int rockchip_vop2_mode_valid(struct display_state *state) 5957 { 5958 struct connector_state *conn_state = &state->conn_state; 5959 struct crtc_state *cstate = &state->crtc_state; 5960 struct drm_display_mode *mode = &conn_state->mode; 5961 struct videomode vm; 5962 5963 drm_display_mode_to_videomode(mode, &vm); 5964 5965 if (vm.hactive < 32 || vm.vactive < 32 || 5966 (vm.hfront_porch * vm.hsync_len * vm.hback_porch * 5967 vm.vfront_porch * vm.vsync_len * vm.vback_porch == 0)) { 5968 printf("ERROR: VP%d: unsupported display timing\n", cstate->crtc_id); 5969 return -EINVAL; 5970 } 5971 5972 return 0; 5973 } 5974 5975 static int rockchip_vop2_mode_fixup(struct display_state *state) 5976 { 5977 struct connector_state *conn_state = &state->conn_state; 5978 struct rockchip_connector *conn = conn_state->connector; 5979 struct drm_display_mode *mode = &conn_state->mode; 5980 struct crtc_state *cstate = &state->crtc_state; 5981 struct vop2 *vop2 = cstate->private; 5982 5983 if (conn_state->secondary) { 5984 if (!(conn->dual_channel_mode && 5985 conn_state->secondary->type == DRM_MODE_CONNECTOR_eDP) && 5986 conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS) 5987 drm_mode_convert_to_split_mode(mode); 5988 } 5989 5990 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE); 5991 5992 /* 5993 * For RK3568 and RK3588, the hactive of video timing must 5994 * be 4-pixel aligned. 5995 */ 5996 if (vop2->version == VOP_VERSION_RK3568 || vop2->version == VOP_VERSION_RK3588) { 5997 if (mode->crtc_hdisplay % 4) { 5998 int old_hdisplay = mode->crtc_hdisplay; 5999 int align = 4 - (mode->crtc_hdisplay % 4); 6000 6001 mode->crtc_hdisplay += align; 6002 mode->crtc_hsync_start += align; 6003 mode->crtc_hsync_end += align; 6004 mode->crtc_htotal += align; 6005 6006 printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n", 6007 old_hdisplay, mode->hdisplay); 6008 } 6009 } 6010 6011 /* 6012 * When the dsc bpp is less than 9, hdmi output will flash on TV. 6013 * It is speculated that the reason is that pixel rate of sink 6014 * decoding is not enough. 6015 * Taking 8bpp as an example, dsc clk needs to be 1/3 of the input 6016 * clk. the theoretical calculation of DEN compression 1/3, at this 6017 * time, the clk of vop dsc to hdmi tx can be reduced to about 260M 6018 * to meet the 8bpp transmission. 6019 * RK3588 dsc clk only supports 1/2 frequency division, so dsc clk 6020 * is 1/2 input clk, which needs to increase blank, which is 6021 * equivalent to compressing the absolute DEN time. TV is likely to 6022 * decode at a decoding rate of around 260M. DEN absolute time 6023 * shortening results in abnormal TV decoding. 6024 * So the value of hblank needs to be reduced when bpp is below 9. 6025 * The measurement can be displayed normally on TV, but reducing 6026 * the hblank will result in non-standard timing of the hdmi output. 6027 * This may cause compatibility issues and hdmi cts certification 6028 * may fail. 6029 */ 6030 if (vop2->version == VOP_VERSION_RK3588) { 6031 if (conn_state->output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { 6032 if (cstate->dsc_sink_cap.target_bits_per_pixel_x16 < 0x90 && 6033 cstate->dsc_enable) { 6034 u8 vrefresh = drm_mode_vrefresh(mode); 6035 6036 mode->crtc_hsync_start = mode->hdisplay + 10; 6037 mode->crtc_hsync_end = mode->crtc_hsync_start + 10; 6038 mode->crtc_htotal = mode->crtc_hsync_end + 10; 6039 mode->crtc_clock = (u32)mode->crtc_htotal * mode->crtc_vtotal * 6040 vrefresh / 1000; 6041 } 6042 } 6043 } 6044 6045 if (vop2->version == VOP_VERSION_RK3576) { 6046 /* 6047 * For RK3576 YUV420 output, hden signal introduce one cycle delay, 6048 * so we need to adjust hfp and hbp to compatible with this design. 6049 */ 6050 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 6051 mode->crtc_hsync_start += 2; 6052 mode->crtc_hsync_end += 2; 6053 } 6054 /* 6055 * For RK3576 DP output, vp send 2 pixels 1 cycle. So the hactive, 6056 * hfp, hsync, hbp should be 2-pixel aligned. 6057 */ 6058 if (conn_state->output_if & 6059 (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) { 6060 mode->crtc_hdisplay += mode->crtc_hdisplay % 2; 6061 mode->crtc_hsync_start += mode->crtc_hsync_start % 2; 6062 mode->crtc_hsync_end += mode->crtc_hsync_end % 2; 6063 mode->crtc_htotal += mode->crtc_htotal % 2; 6064 } 6065 } 6066 6067 if (mode->flags & DRM_MODE_FLAG_DBLCLK || conn_state->output_if & VOP_OUTPUT_IF_BT656) 6068 mode->crtc_clock *= 2; 6069 6070 /* 6071 * For RK3528, the path of CVBS output is like: 6072 * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC 6073 * The vop2 dclk should be four times crtc_clock for CVBS sampling 6074 * clock needs. 6075 */ 6076 if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656) 6077 mode->crtc_clock *= 4; 6078 6079 mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format); 6080 if (cstate->mcu_timing.mcu_pix_total) 6081 mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1; 6082 6083 return 0; 6084 } 6085 6086 #define FRAC_16_16(mult, div) (((mult) << 16) / (div)) 6087 6088 static int rockchip_vop2_plane_check(struct display_state *state) 6089 { 6090 struct crtc_state *cstate = &state->crtc_state; 6091 struct vop2 *vop2 = cstate->private; 6092 struct display_rect *src = &cstate->src_rect; 6093 struct display_rect *dst = &cstate->crtc_rect; 6094 struct vop2_win_data *win_data; 6095 int min_scale, max_scale; 6096 int hscale, vscale; 6097 u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 6098 6099 win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 6100 if (!win_data) { 6101 printf("ERROR: invalid win id %d\n", primary_plane_id); 6102 return -ENODEV; 6103 } 6104 6105 min_scale = FRAC_16_16(1, win_data->max_downscale_factor); 6106 max_scale = FRAC_16_16(win_data->max_upscale_factor, 1); 6107 6108 hscale = display_rect_calc_hscale(src, dst, min_scale, max_scale); 6109 vscale = display_rect_calc_vscale(src, dst, min_scale, max_scale); 6110 if (hscale < 0 || vscale < 0) { 6111 printf("ERROR: VP%d %s: scale factor is out of range\n", cstate->crtc_id, win_data->name); 6112 return -ERANGE; 6113 } 6114 6115 return 0; 6116 } 6117 6118 static int rockchip_vop2_apply_soft_te(struct display_state *state) 6119 { 6120 __maybe_unused struct connector_state *conn_state = &state->conn_state; 6121 struct crtc_state *cstate = &state->crtc_state; 6122 struct vop2 *vop2 = cstate->private; 6123 u32 vp_offset = (cstate->crtc_id * 0x100); 6124 int val = 0; 6125 int ret = 0; 6126 6127 ret = readl_poll_timeout(vop2->regs + RK3568_VP0_MIPI_CTRL + vp_offset, val, 6128 (val >> EDPI_WMS_FS) & 0x1, 50 * 1000); 6129 if (!ret) { 6130 #ifndef CONFIG_SPL_BUILD 6131 ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 6132 !val, 50 * 1000); 6133 if (!ret) { 6134 ret = readx_poll_timeout(dm_gpio_get_value, conn_state->te_gpio, val, 6135 val, 50 * 1000); 6136 if (!ret) { 6137 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 6138 EN_MASK, EDPI_WMS_FS, 1, false); 6139 } else { 6140 printf("ERROR: vp%d wait for active TE signal timeout\n", 6141 cstate->crtc_id); 6142 return ret; 6143 } 6144 } else { 6145 printf("ERROR: vp%d TE signal maybe always high\n", cstate->crtc_id); 6146 return ret; 6147 } 6148 #endif 6149 } else { 6150 printf("ERROR: vp%d wait vop2 frame start timeout in hold mode\n", cstate->crtc_id); 6151 return ret; 6152 } 6153 6154 return 0; 6155 } 6156 6157 static int rockchip_vop2_regs_dump(struct display_state *state) 6158 { 6159 struct crtc_state *cstate = &state->crtc_state; 6160 struct vop2 *vop2 = cstate->private; 6161 const struct vop2_data *vop2_data = vop2->data; 6162 const struct vop2_dump_regs *regs = vop2_data->dump_regs; 6163 u32 len = 128; 6164 u32 n, i, j; 6165 u32 base; 6166 6167 if (!cstate->crtc->active) 6168 return -EINVAL; 6169 6170 n = vop2_data->dump_regs_size; 6171 for (i = 0; i < n; i++) { 6172 base = regs[i].offset; 6173 len = 128; 6174 if (regs[i].size) 6175 len = min(len, regs[i].size >> 2); 6176 printf("\n%s:\n", regs[i].name); 6177 for (j = 0; j < len;) { 6178 printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 6179 vop2_readl(vop2, base + (4 * j)), 6180 vop2_readl(vop2, base + (4 * (j + 1))), 6181 vop2_readl(vop2, base + (4 * (j + 2))), 6182 vop2_readl(vop2, base + (4 * (j + 3)))); 6183 j += 4; 6184 } 6185 } 6186 6187 return 0; 6188 } 6189 6190 static int rockchip_vop2_active_regs_dump(struct display_state *state) 6191 { 6192 struct crtc_state *cstate = &state->crtc_state; 6193 struct vop2 *vop2 = cstate->private; 6194 const struct vop2_data *vop2_data = vop2->data; 6195 const struct vop2_dump_regs *regs = vop2_data->dump_regs; 6196 u32 len = 128; 6197 u32 n, i, j; 6198 u32 base; 6199 bool enable_state; 6200 6201 if (!cstate->crtc->active) 6202 return -EINVAL; 6203 6204 n = vop2_data->dump_regs_size; 6205 for (i = 0; i < n; i++) { 6206 if (regs[i].state_mask) { 6207 enable_state = (vop2_readl(vop2, regs[i].state_base) >> regs[i].state_shift) & 6208 regs[i].state_mask; 6209 if (enable_state != regs[i].enable_state) 6210 continue; 6211 } 6212 6213 base = regs[i].offset; 6214 len = 128; 6215 if (regs[i].size) 6216 len = min(len, regs[i].size >> 2); 6217 printf("\n%s:\n", regs[i].name); 6218 for (j = 0; j < len;) { 6219 printf("%08lx: %08x %08x %08x %08x\n", (uintptr_t)vop2->regs + base + j * 4, 6220 vop2_readl(vop2, base + (4 * j)), 6221 vop2_readl(vop2, base + (4 * (j + 1))), 6222 vop2_readl(vop2, base + (4 * (j + 2))), 6223 vop2_readl(vop2, base + (4 * (j + 3)))); 6224 j += 4; 6225 } 6226 } 6227 6228 return 0; 6229 } 6230 6231 static void rk3528_setup_win_dly(struct display_state *state, int crtc_id) 6232 { 6233 struct crtc_state *cstate = &state->crtc_state; 6234 struct vop2 *vop2 = cstate->private; 6235 struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id]; 6236 uint32_t dly = 0; /* For vop3, the default window delay is 0 */ 6237 6238 switch (plane_mask->primary_plane_id) { 6239 case ROCKCHIP_VOP2_CLUSTER0: 6240 vop2_mask_write(vop2, RK3528_OVL_SYS_CLUSTER0_CTRL, CLUSTER_DLY_NUM_MASK, 6241 CLUSTER_DLY_NUM_SHIFT, dly, false); 6242 break; 6243 case ROCKCHIP_VOP2_ESMART0: 6244 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART0_CTRL, ESMART_DLY_NUM_MASK, 6245 ESMART_DLY_NUM_SHIFT, dly, false); 6246 break; 6247 case ROCKCHIP_VOP2_ESMART1: 6248 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART1_CTRL, ESMART_DLY_NUM_MASK, 6249 ESMART_DLY_NUM_SHIFT, dly, false); 6250 break; 6251 case ROCKCHIP_VOP2_ESMART2: 6252 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART2_CTRL, ESMART_DLY_NUM_MASK, 6253 ESMART_DLY_NUM_SHIFT, dly, false); 6254 break; 6255 case ROCKCHIP_VOP2_ESMART3: 6256 vop2_mask_write(vop2, RK3528_OVL_SYS_ESMART3_CTRL, ESMART_DLY_NUM_MASK, 6257 ESMART_DLY_NUM_SHIFT, dly, false); 6258 break; 6259 } 6260 } 6261 6262 static void rk3528_setup_overlay(struct display_state *state) 6263 { 6264 struct crtc_state *cstate = &state->crtc_state; 6265 struct vop2 *vop2 = cstate->private; 6266 struct vop2_win_data *win_data; 6267 int i; 6268 u32 offset = 0; 6269 u8 shift = 0; 6270 6271 /* init the layer sel value to 0xff(Disable layer) */ 6272 for (i = 0; i < vop2->data->nr_vps; i++) { 6273 offset = 0x100 * i; 6274 vop2_writel(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 0xffffffff); 6275 } 6276 6277 /* layer sel win id */ 6278 for (i = 0; i < vop2->data->nr_vps; i++) { 6279 if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { 6280 offset = 0x100 * i; 6281 win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id); 6282 vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, 6283 LAYER_SEL_MASK, 0, win_data->layer_sel_win_id[i], false); 6284 } 6285 } 6286 6287 /* win sel port */ 6288 for (i = 0; i < vop2->data->nr_vps; i++) { 6289 if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { 6290 win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id); 6291 shift = win_data->win_sel_port_offset * 2; 6292 vop2_mask_write(vop2, RK3528_OVL_SYS_PORT_SEL, 6293 LAYER_SEL_PORT_MASK, shift, i, false); 6294 } 6295 } 6296 } 6297 6298 static void rk3568_setup_win_dly(struct display_state *state, int crtc_id) 6299 { 6300 struct crtc_state *cstate = &state->crtc_state; 6301 struct vop2 *vop2 = cstate->private; 6302 struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id]; 6303 struct vop2_win_data *win_data; 6304 uint32_t dly; 6305 6306 win_data = vop2_find_win_by_phys_id(vop2, plane_mask->primary_plane_id); 6307 dly = win_data->dly[VOP2_DLY_MODE_DEFAULT]; 6308 if (win_data->type == CLUSTER_LAYER) 6309 dly |= dly << 8; 6310 6311 switch (plane_mask->primary_plane_id) { 6312 case ROCKCHIP_VOP2_CLUSTER0: 6313 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK, 6314 CLUSTER0_DLY_NUM_SHIFT, dly, false); 6315 break; 6316 case ROCKCHIP_VOP2_CLUSTER1: 6317 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM, CLUSTER_DLY_NUM_MASK, 6318 CLUSTER1_DLY_NUM_SHIFT, dly, false); 6319 break; 6320 case ROCKCHIP_VOP2_CLUSTER2: 6321 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK, 6322 CLUSTER0_DLY_NUM_SHIFT, dly, false); 6323 break; 6324 case ROCKCHIP_VOP2_CLUSTER3: 6325 vop2_mask_write(vop2, RK3568_CLUSTER_DLY_NUM1, CLUSTER_DLY_NUM_MASK, 6326 CLUSTER1_DLY_NUM_SHIFT, dly, false); 6327 break; 6328 case ROCKCHIP_VOP2_ESMART0: 6329 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 6330 ESMART0_DLY_NUM_SHIFT, dly, false); 6331 break; 6332 case ROCKCHIP_VOP2_ESMART1: 6333 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 6334 ESMART1_DLY_NUM_SHIFT, dly, false); 6335 break; 6336 case ROCKCHIP_VOP2_SMART0: 6337 case ROCKCHIP_VOP2_ESMART2: 6338 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 6339 SMART0_DLY_NUM_SHIFT, dly, false); 6340 break; 6341 case ROCKCHIP_VOP2_SMART1: 6342 case ROCKCHIP_VOP2_ESMART3: 6343 vop2_mask_write(vop2, RK3568_SMART_DLY_NUM, SMART_DLY_NUM_MASK, 6344 SMART1_DLY_NUM_SHIFT, dly, false); 6345 break; 6346 } 6347 } 6348 6349 static void rk3568_setup_overlay(struct display_state *state) 6350 { 6351 struct crtc_state *cstate = &state->crtc_state; 6352 struct vop2 *vop2 = cstate->private; 6353 struct vop2_win_data *win_data; 6354 int layer_phy_id = 0; 6355 int total_used_layer = 0; 6356 int port_mux = 0; 6357 int i, j; 6358 u32 layer_nr = 0; 6359 u8 shift = 0; 6360 6361 /* layer sel win id */ 6362 for (i = 0; i < vop2->data->nr_vps; i++) { 6363 layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 6364 for (j = 0; j < layer_nr; j++) { 6365 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 6366 win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 6367 vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 6368 shift, win_data->layer_sel_win_id[i], false); 6369 shift += 4; 6370 } 6371 } 6372 6373 /* win sel port */ 6374 for (i = 0; i < vop2->data->nr_vps; i++) { 6375 layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 6376 for (j = 0; j < layer_nr; j++) { 6377 if (!vop2->vp_plane_mask[i].attached_layers[j]) 6378 continue; 6379 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 6380 win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 6381 shift = win_data->win_sel_port_offset * 2; 6382 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 6383 LAYER_SEL_PORT_SHIFT + shift, i, false); 6384 } 6385 } 6386 6387 /** 6388 * port mux config 6389 */ 6390 for (i = 0; i < vop2->data->nr_vps; i++) { 6391 shift = i * 4; 6392 if (vop2->vp_plane_mask[i].attached_layers_nr) { 6393 total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 6394 port_mux = total_used_layer - 1; 6395 } else { 6396 port_mux = 8; 6397 } 6398 6399 if (i == vop2->data->nr_vps - 1) 6400 port_mux = vop2->data->nr_mixers; 6401 6402 cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 6403 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 6404 PORT_MUX_SHIFT + shift, port_mux, false); 6405 } 6406 } 6407 6408 static void rk3576_setup_win_dly(struct display_state *state, int crtc_id) 6409 { 6410 struct crtc_state *cstate = &state->crtc_state; 6411 struct vop2 *vop2 = cstate->private; 6412 struct vop2_vp_plane_mask *plane_mask = &vop2->vp_plane_mask[crtc_id]; 6413 uint32_t dly = 0; /* For vop3, the default window delay is 0 */ 6414 6415 switch (plane_mask->primary_plane_id) { 6416 case ROCKCHIP_VOP2_CLUSTER0: 6417 vop2_mask_write(vop2, RK3576_CLUSTER0_DLY_NUM, CLUSTER_DLY_NUM_MASK, 6418 CLUSTER_DLY_NUM_SHIFT, dly, false); 6419 break; 6420 case ROCKCHIP_VOP2_CLUSTER1: 6421 vop2_mask_write(vop2, RK3576_CLUSTER1_DLY_NUM, CLUSTER_DLY_NUM_MASK, 6422 CLUSTER_DLY_NUM_SHIFT, dly, false); 6423 break; 6424 case ROCKCHIP_VOP2_ESMART0: 6425 vop2_mask_write(vop2, RK3576_ESMART0_DLY_NUM, ESMART_DLY_NUM_MASK, 6426 ESMART_DLY_NUM_SHIFT, dly, false); 6427 break; 6428 case ROCKCHIP_VOP2_ESMART1: 6429 vop2_mask_write(vop2, RK3576_ESMART1_DLY_NUM, ESMART_DLY_NUM_MASK, 6430 ESMART_DLY_NUM_SHIFT, dly, false); 6431 break; 6432 case ROCKCHIP_VOP2_ESMART2: 6433 vop2_mask_write(vop2, RK3576_ESMART2_DLY_NUM, ESMART_DLY_NUM_MASK, 6434 ESMART_DLY_NUM_SHIFT, dly, false); 6435 break; 6436 case ROCKCHIP_VOP2_ESMART3: 6437 vop2_mask_write(vop2, RK3576_ESMART3_DLY_NUM, ESMART_DLY_NUM_MASK, 6438 ESMART_DLY_NUM_SHIFT, dly, false); 6439 break; 6440 } 6441 } 6442 6443 static void rk3576_setup_overlay(struct display_state *state) 6444 { 6445 struct crtc_state *cstate = &state->crtc_state; 6446 struct vop2 *vop2 = cstate->private; 6447 struct vop2_win_data *win_data; 6448 int i; 6449 u32 offset = 0; 6450 6451 /* layer sel win id */ 6452 for (i = 0; i < vop2->data->nr_vps; i++) { 6453 if (vop2->vp_plane_mask[i].primary_plane_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { 6454 offset = 0x100 * i; 6455 win_data = vop2_find_win_by_phys_id(vop2, vop2->vp_plane_mask[i].primary_plane_id); 6456 vop2_mask_write(vop2, RK3528_OVL_PORT0_LAYER_SEL + offset, LAYER_SEL_MASK, 6457 0, win_data->layer_sel_win_id[i], false); 6458 } 6459 } 6460 } 6461 6462 static struct vop2_dump_regs rk3528_dump_regs[] = { 6463 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 6464 { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 6465 { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 6466 { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 6467 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 6468 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 6469 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 6470 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 6471 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 6472 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 6473 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 6474 { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 6475 { RK3528_ACM_CTRL, "ACM", RK3528_ACM_CTRL, 0x1, 0, 1}, 6476 }; 6477 6478 #define RK3528_PLANE_MASK_BASE \ 6479 (BIT(ROCKCHIP_VOP2_CLUSTER0) | \ 6480 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \ 6481 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3)) 6482 6483 static struct vop2_win_data rk3528_win_data[5] = { 6484 { 6485 .name = "Esmart0", 6486 .phys_id = ROCKCHIP_VOP2_ESMART0, 6487 .type = ESMART_LAYER, 6488 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 6489 .win_sel_port_offset = 8, 6490 .layer_sel_win_id = { 1, 0xff, 0xff, 0xff }, 6491 .reg_offset = 0, 6492 .axi_id = 0, 6493 .axi_yrgb_id = 0x06, 6494 .axi_uv_id = 0x07, 6495 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6496 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6497 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6498 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6499 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 6500 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6501 .possible_vp_mask = BIT(VOP2_VP0), 6502 .max_upscale_factor = 8, 6503 .max_downscale_factor = 8, 6504 }, 6505 6506 { 6507 .name = "Esmart1", 6508 .phys_id = ROCKCHIP_VOP2_ESMART1, 6509 .type = ESMART_LAYER, 6510 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 6511 .win_sel_port_offset = 10, 6512 .layer_sel_win_id = { 2, 0xff, 0xff, 0xff }, 6513 .reg_offset = 0x200, 6514 .axi_id = 0, 6515 .axi_yrgb_id = 0x08, 6516 .axi_uv_id = 0x09, 6517 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6518 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6519 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6520 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6521 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 6522 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6523 .possible_vp_mask = BIT(VOP2_VP0), 6524 .max_upscale_factor = 8, 6525 .max_downscale_factor = 8, 6526 }, 6527 6528 { 6529 .name = "Esmart2", 6530 .phys_id = ROCKCHIP_VOP2_ESMART2, 6531 .type = ESMART_LAYER, 6532 .plane_type = VOP2_PLANE_TYPE_CURSOR, 6533 .win_sel_port_offset = 12, 6534 .layer_sel_win_id = { 3, 0, 0xff, 0xff }, 6535 .reg_offset = 0x400, 6536 .axi_id = 0, 6537 .axi_yrgb_id = 0x0a, 6538 .axi_uv_id = 0x0b, 6539 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6540 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6541 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6542 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6543 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 6544 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6545 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1), 6546 .max_upscale_factor = 8, 6547 .max_downscale_factor = 8, 6548 }, 6549 6550 { 6551 .name = "Esmart3", 6552 .phys_id = ROCKCHIP_VOP2_ESMART3, 6553 .type = ESMART_LAYER, 6554 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 6555 .win_sel_port_offset = 14, 6556 .layer_sel_win_id = { 0xff, 1, 0xff, 0xff }, 6557 .reg_offset = 0x600, 6558 .axi_id = 0, 6559 .axi_yrgb_id = 0x0c, 6560 .axi_uv_id = 0x0d, 6561 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6562 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6563 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6564 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6565 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 6566 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT, /* gt only */ 6567 .possible_vp_mask = BIT(VOP2_VP1), 6568 .max_upscale_factor = 8, 6569 .max_downscale_factor = 8, 6570 }, 6571 6572 { 6573 .name = "Cluster0", 6574 .phys_id = ROCKCHIP_VOP2_CLUSTER0, 6575 .type = CLUSTER_LAYER, 6576 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 6577 .win_sel_port_offset = 0, 6578 .layer_sel_win_id = { 0, 0xff, 0xff, 0xff }, 6579 .reg_offset = 0, 6580 .axi_id = 0, 6581 .axi_yrgb_id = 0x02, 6582 .axi_uv_id = 0x03, 6583 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6584 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6585 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6586 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6587 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 6588 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG, /* gt or avg */ 6589 .possible_vp_mask = BIT(VOP2_VP0), 6590 .max_upscale_factor = 8, 6591 .max_downscale_factor = 8, 6592 }, 6593 }; 6594 6595 static struct vop2_vp_data rk3528_vp_data[2] = { 6596 { 6597 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_POST_ACM | 6598 VOP_FEATURE_POST_CSC, 6599 .max_output = {4096, 4096}, 6600 .layer_mix_dly = 6, 6601 .hdr_mix_dly = 2, 6602 .win_dly = 8, 6603 }, 6604 { 6605 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6606 .max_output = {1920, 1080}, 6607 .layer_mix_dly = 2, 6608 .hdr_mix_dly = 0, 6609 .win_dly = 8, 6610 }, 6611 }; 6612 6613 static const struct vop2_ops rk3528_vop_ops = { 6614 .setup_win_dly = rk3528_setup_win_dly, 6615 .setup_overlay = rk3528_setup_overlay, 6616 }; 6617 6618 const struct vop2_data rk3528_vop = { 6619 .version = VOP_VERSION_RK3528, 6620 .nr_vps = 2, 6621 .vp_data = rk3528_vp_data, 6622 .win_data = rk3528_win_data, 6623 .plane_mask_base = RK3528_PLANE_MASK_BASE, 6624 .nr_layers = 5, 6625 .nr_mixers = 3, 6626 .nr_gammas = 2, 6627 .esmart_lb_mode = VOP3_ESMART_4K_2K_2K_MODE, 6628 .dump_regs = rk3528_dump_regs, 6629 .dump_regs_size = ARRAY_SIZE(rk3528_dump_regs), 6630 .ops = &rk3528_vop_ops, 6631 6632 }; 6633 6634 static struct vop2_dump_regs rk3562_dump_regs[] = { 6635 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 6636 { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0 }, 6637 { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 6638 { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 6639 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 6640 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 6641 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 6642 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 6643 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1 }, 6644 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1 }, 6645 }; 6646 6647 #define RK3562_PLANE_MASK_BASE \ 6648 (BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \ 6649 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3)) 6650 6651 static struct vop2_win_data rk3562_win_data[4] = { 6652 { 6653 .name = "Esmart0", 6654 .phys_id = ROCKCHIP_VOP2_ESMART0, 6655 .type = ESMART_LAYER, 6656 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 6657 .win_sel_port_offset = 8, 6658 .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 6659 .reg_offset = 0, 6660 .axi_id = 0, 6661 .axi_yrgb_id = 0x02, 6662 .axi_uv_id = 0x03, 6663 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6664 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6665 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6666 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6667 .possible_vp_mask = BIT(VOP2_VP0), 6668 .max_upscale_factor = 8, 6669 .max_downscale_factor = 8, 6670 }, 6671 6672 { 6673 .name = "Esmart1", 6674 .phys_id = ROCKCHIP_VOP2_ESMART1, 6675 .type = ESMART_LAYER, 6676 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 6677 .win_sel_port_offset = 10, 6678 .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 6679 .reg_offset = 0x200, 6680 .axi_id = 0, 6681 .axi_yrgb_id = 0x04, 6682 .axi_uv_id = 0x05, 6683 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6684 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6685 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6686 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6687 .possible_vp_mask = BIT(VOP2_VP0), 6688 .max_upscale_factor = 8, 6689 .max_downscale_factor = 8, 6690 }, 6691 6692 { 6693 .name = "Esmart2", 6694 .phys_id = ROCKCHIP_VOP2_ESMART2, 6695 .type = ESMART_LAYER, 6696 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 6697 .win_sel_port_offset = 12, 6698 .layer_sel_win_id = { 2, 2, 0xff, 0xff }, 6699 .reg_offset = 0x400, 6700 .axi_id = 0, 6701 .axi_yrgb_id = 0x06, 6702 .axi_uv_id = 0x07, 6703 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6704 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6705 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6706 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6707 .possible_vp_mask = BIT(VOP2_VP0), 6708 .max_upscale_factor = 8, 6709 .max_downscale_factor = 8, 6710 }, 6711 6712 { 6713 .name = "Esmart3", 6714 .phys_id = ROCKCHIP_VOP2_ESMART3, 6715 .type = ESMART_LAYER, 6716 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 6717 .win_sel_port_offset = 14, 6718 .layer_sel_win_id = { 3, 3, 0xff, 0xff }, 6719 .reg_offset = 0x600, 6720 .axi_id = 0, 6721 .axi_yrgb_id = 0x08, 6722 .axi_uv_id = 0x0d, 6723 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6724 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6725 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6726 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6727 .possible_vp_mask = BIT(VOP2_VP0), 6728 .max_upscale_factor = 8, 6729 .max_downscale_factor = 8, 6730 }, 6731 }; 6732 6733 static struct vop2_vp_data rk3562_vp_data[2] = { 6734 { 6735 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6736 .max_output = {2048, 4096}, 6737 .win_dly = 6, 6738 .layer_mix_dly = 8, 6739 }, 6740 { 6741 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 6742 .max_output = {2048, 1080}, 6743 .win_dly = 8, 6744 .layer_mix_dly = 8, 6745 }, 6746 }; 6747 6748 static const struct vop2_ops rk3562_vop_ops = { 6749 .setup_win_dly = rk3528_setup_win_dly, 6750 .setup_overlay = rk3528_setup_overlay, 6751 }; 6752 6753 const struct vop2_data rk3562_vop = { 6754 .version = VOP_VERSION_RK3562, 6755 .nr_vps = 2, 6756 .vp_data = rk3562_vp_data, 6757 .win_data = rk3562_win_data, 6758 .plane_mask_base = RK3562_PLANE_MASK_BASE, 6759 .nr_layers = 4, 6760 .nr_mixers = 3, 6761 .nr_gammas = 2, 6762 .esmart_lb_mode = VOP3_ESMART_2K_2K_2K_2K_MODE, 6763 .dump_regs = rk3562_dump_regs, 6764 .dump_regs_size = ARRAY_SIZE(rk3562_dump_regs), 6765 .ops = &rk3562_vop_ops, 6766 }; 6767 6768 static struct vop2_dump_regs rk3568_dump_regs[] = { 6769 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 6770 { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 6771 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 6772 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 6773 { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 6774 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 6775 { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 6776 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 6777 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 6778 { RK3568_SMART0_CTRL0, "Smart0", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 6779 { RK3568_SMART1_CTRL0, "Smart1", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 6780 { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 6781 }; 6782 6783 static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 6784 { /* one display policy */ 6785 {/* main display */ 6786 .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6787 .attached_layers_nr = 6, 6788 .attached_layers = { 6789 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 6790 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 6791 }, 6792 }, 6793 {/* second display */}, 6794 {/* third display */}, 6795 {/* fourth display */}, 6796 }, 6797 6798 { /* two display policy */ 6799 {/* main display */ 6800 .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6801 .attached_layers_nr = 3, 6802 .attached_layers = { 6803 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 6804 }, 6805 }, 6806 6807 {/* second display */ 6808 .primary_plane_id = ROCKCHIP_VOP2_SMART1, 6809 .attached_layers_nr = 3, 6810 .attached_layers = { 6811 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 6812 }, 6813 }, 6814 {/* third display */}, 6815 {/* fourth display */}, 6816 }, 6817 6818 { /* three display policy */ 6819 {/* main display */ 6820 .primary_plane_id = ROCKCHIP_VOP2_SMART0, 6821 .attached_layers_nr = 3, 6822 .attached_layers = { 6823 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 6824 }, 6825 }, 6826 6827 {/* second display */ 6828 .primary_plane_id = ROCKCHIP_VOP2_SMART1, 6829 .attached_layers_nr = 2, 6830 .attached_layers = { 6831 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 6832 }, 6833 }, 6834 6835 {/* third display */ 6836 .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 6837 .attached_layers_nr = 1, 6838 .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 6839 }, 6840 6841 {/* fourth display */}, 6842 }, 6843 6844 {/* reserved for four display policy */}, 6845 }; 6846 6847 #define RK3568_PLANE_MASK_BASE \ 6848 (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \ 6849 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \ 6850 BIT(ROCKCHIP_VOP2_SMART0) | BIT(ROCKCHIP_VOP2_SMART1)) 6851 6852 static struct vop2_win_data rk3568_win_data[6] = { 6853 { 6854 .name = "Cluster0", 6855 .phys_id = ROCKCHIP_VOP2_CLUSTER0, 6856 .type = CLUSTER_LAYER, 6857 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 6858 .win_sel_port_offset = 0, 6859 .layer_sel_win_id = { 0, 0, 0, 0xff }, 6860 .reg_offset = 0, 6861 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6862 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6863 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6864 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6865 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 6866 .max_upscale_factor = 4, 6867 .max_downscale_factor = 4, 6868 .dly = { 0, 27, 21 }, 6869 }, 6870 6871 { 6872 .name = "Cluster1", 6873 .phys_id = ROCKCHIP_VOP2_CLUSTER1, 6874 .type = CLUSTER_LAYER, 6875 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 6876 .win_sel_port_offset = 1, 6877 .layer_sel_win_id = { 1, 1, 1, 0xff }, 6878 .reg_offset = 0x200, 6879 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6880 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6881 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6882 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6883 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 6884 .max_upscale_factor = 4, 6885 .max_downscale_factor = 4, 6886 .source_win_id = ROCKCHIP_VOP2_CLUSTER0, 6887 .feature = WIN_FEATURE_MIRROR, 6888 .dly = { 0, 27, 21 }, 6889 }, 6890 6891 { 6892 .name = "Esmart0", 6893 .phys_id = ROCKCHIP_VOP2_ESMART0, 6894 .type = ESMART_LAYER, 6895 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 6896 .win_sel_port_offset = 4, 6897 .layer_sel_win_id = { 2, 2, 2, 0xff }, 6898 .reg_offset = 0, 6899 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6900 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6901 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6902 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6903 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 6904 .max_upscale_factor = 8, 6905 .max_downscale_factor = 8, 6906 .dly = { 20, 47, 41 }, 6907 }, 6908 6909 { 6910 .name = "Esmart1", 6911 .phys_id = ROCKCHIP_VOP2_ESMART1, 6912 .type = ESMART_LAYER, 6913 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 6914 .win_sel_port_offset = 5, 6915 .layer_sel_win_id = { 6, 6, 6, 0xff }, 6916 .reg_offset = 0x200, 6917 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6918 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6919 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6920 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6921 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 6922 .max_upscale_factor = 8, 6923 .max_downscale_factor = 8, 6924 .dly = { 20, 47, 41 }, 6925 .source_win_id = ROCKCHIP_VOP2_ESMART0, 6926 .feature = WIN_FEATURE_MIRROR, 6927 }, 6928 6929 { 6930 .name = "Smart0", 6931 .phys_id = ROCKCHIP_VOP2_SMART0, 6932 .type = SMART_LAYER, 6933 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 6934 .win_sel_port_offset = 6, 6935 .layer_sel_win_id = { 3, 3, 3, 0xff }, 6936 .reg_offset = 0x400, 6937 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6938 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6939 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6940 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6941 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 6942 .max_upscale_factor = 8, 6943 .max_downscale_factor = 8, 6944 .dly = { 20, 47, 41 }, 6945 }, 6946 6947 { 6948 .name = "Smart1", 6949 .phys_id = ROCKCHIP_VOP2_SMART1, 6950 .type = SMART_LAYER, 6951 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 6952 .win_sel_port_offset = 7, 6953 .layer_sel_win_id = { 7, 7, 7, 0xff }, 6954 .reg_offset = 0x600, 6955 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 6956 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6957 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 6958 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 6959 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2), 6960 .max_upscale_factor = 8, 6961 .max_downscale_factor = 8, 6962 .dly = { 20, 47, 41 }, 6963 .source_win_id = ROCKCHIP_VOP2_SMART0, 6964 .feature = WIN_FEATURE_MIRROR, 6965 }, 6966 }; 6967 6968 static struct vop2_vp_data rk3568_vp_data[3] = { 6969 { 6970 .feature = VOP_FEATURE_OUTPUT_10BIT, 6971 .pre_scan_max_dly = 42, 6972 .max_output = {4096, 2304}, 6973 }, 6974 { 6975 .feature = 0, 6976 .pre_scan_max_dly = 40, 6977 .max_output = {2048, 1536}, 6978 }, 6979 { 6980 .feature = 0, 6981 .pre_scan_max_dly = 40, 6982 .max_output = {1920, 1080}, 6983 }, 6984 }; 6985 6986 static const struct vop2_ops rk3568_vop_ops = { 6987 .setup_win_dly = rk3568_setup_win_dly, 6988 .setup_overlay = rk3568_setup_overlay, 6989 }; 6990 6991 const struct vop2_data rk3568_vop = { 6992 .version = VOP_VERSION_RK3568, 6993 .nr_vps = 3, 6994 .vp_data = rk3568_vp_data, 6995 .win_data = rk3568_win_data, 6996 .plane_mask = rk356x_vp_plane_mask[0], 6997 .plane_mask_base = RK3568_PLANE_MASK_BASE, 6998 .nr_layers = 6, 6999 .nr_mixers = 5, 7000 .nr_gammas = 1, 7001 .dump_regs = rk3568_dump_regs, 7002 .dump_regs_size = ARRAY_SIZE(rk3568_dump_regs), 7003 .ops = &rk3568_vop_ops, 7004 }; 7005 7006 #define RK3576_PLANE_MASK_BASE \ 7007 (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \ 7008 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \ 7009 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3)) 7010 7011 static struct vop2_dump_regs rk3576_dump_regs[] = { 7012 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0, 0x200 }, 7013 { RK3528_OVL_SYS, "OVL_SYS", 0, 0, 0, 0, 0x50 }, 7014 { RK3528_OVL_PORT0_CTRL, "OVL_VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x80 }, 7015 { RK3528_OVL_PORT1_CTRL, "OVL_VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0, 0x80 }, 7016 { RK3576_OVL_PORT2_CTRL, "OVL_VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0, 0x80 }, 7017 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 7018 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 7019 { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP0_DSP_CTRL, 0x1, 31, 0, 0x100 }, 7020 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1, 0x200 }, 7021 { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1, 0x200 }, 7022 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1, 0x100 }, 7023 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1, 0x100 }, 7024 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_CTRL0, 0x1, 0, 1, 0x100 }, 7025 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_CTRL0, 0x1, 0, 1, 0x100 }, 7026 { RK3528_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0, 0x100 }, 7027 }; 7028 7029 /* 7030 * RK3576 VOP with 2 Cluster win and 4 Esmart win. 7031 * Every Esmart win support 4 multi-region. 7032 * VP0 can use Cluster0/1 and Esmart0/2 7033 * VP1 can use Cluster0/1 and Esmart1/3 7034 * VP2 can use Esmart0/1/2/3 7035 * 7036 * Scale filter mode: 7037 * 7038 * * Cluster: 7039 * * Support prescale down: 7040 * * H/V: gt2/avg2 or gt4/avg4 7041 * * After prescale down: 7042 * * nearest-neighbor/bilinear/multi-phase filter for scale up 7043 * * nearest-neighbor/bilinear/multi-phase filter for scale down 7044 * 7045 * * Esmart: 7046 * * Support prescale down: 7047 * * H: gt2/avg2 or gt4/avg4 7048 * * V: gt2 or gt4 7049 * * After prescale down: 7050 * * nearest-neighbor/bilinear/bicubic for scale up 7051 * * nearest-neighbor/bilinear for scale down 7052 * 7053 * AXI config:: 7054 * 7055 * * Cluster0 win0: 0xa, 0xb [AXI0] 7056 * * Cluster0 win1: 0xc, 0xd [AXI0] 7057 * * Cluster1 win0: 0x6, 0x7 [AXI0] 7058 * * Cluster1 win1: 0x8, 0x9 [AXI0] 7059 * * Esmart0: 0x10, 0x11 [AXI0] 7060 * * Esmart1: 0x12, 0x13 [AXI0] 7061 * * Esmart2: 0xa, 0xb [AXI1] 7062 * * Esmart3: 0xc, 0xd [AXI1] 7063 * * Lut dma rid: 0x1, 0x2, 0x3 [AXI0] 7064 * * DCI dma rid: 0x4 [AXI0] 7065 * * Metadata rid: 0x5 [AXI0] 7066 * 7067 * * Limit: 7068 * * (1) 0x0 and 0xf can't be used; 7069 * * (2) cluster and lut/dci/metadata rid must smaller than 0xf, If Cluster rid is bigger than 0xf, 7070 * * VOP will dead at the system bandwidth very terrible scene. 7071 */ 7072 static struct vop2_win_data rk3576_win_data[6] = { 7073 { 7074 .name = "Esmart0", 7075 .phys_id = ROCKCHIP_VOP2_ESMART0, 7076 .type = ESMART_LAYER, 7077 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 7078 .layer_sel_win_id = { 2, 0xff, 0, 0xff }, 7079 .reg_offset = 0x0, 7080 .supported_rotations = DRM_MODE_REFLECT_Y, 7081 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7082 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7083 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7084 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7085 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7086 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 7087 .pd_id = VOP2_PD_ESMART, 7088 .axi_id = 0, 7089 .axi_yrgb_id = 0x10, 7090 .axi_uv_id = 0x11, 7091 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2), 7092 .max_upscale_factor = 8, 7093 .max_downscale_factor = 8, 7094 .feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH, 7095 }, 7096 { 7097 .name = "Esmart1", 7098 .phys_id = ROCKCHIP_VOP2_ESMART1, 7099 .type = ESMART_LAYER, 7100 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 7101 .layer_sel_win_id = { 0xff, 2, 1, 0xff }, 7102 .reg_offset = 0x200, 7103 .supported_rotations = DRM_MODE_REFLECT_Y, 7104 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7105 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7106 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7107 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7108 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7109 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 7110 .pd_id = VOP2_PD_ESMART, 7111 .axi_id = 0, 7112 .axi_yrgb_id = 0x12, 7113 .axi_uv_id = 0x13, 7114 .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2), 7115 .max_upscale_factor = 8, 7116 .max_downscale_factor = 8, 7117 .feature = WIN_FEATURE_MULTI_AREA, 7118 }, 7119 7120 { 7121 .name = "Esmart2", 7122 .phys_id = ROCKCHIP_VOP2_ESMART2, 7123 .type = ESMART_LAYER, 7124 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 7125 .layer_sel_win_id = { 3, 0xff, 2, 0xff }, 7126 .reg_offset = 0x400, 7127 .supported_rotations = DRM_MODE_REFLECT_Y, 7128 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7129 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7130 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7131 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7132 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7133 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 7134 .pd_id = VOP2_PD_ESMART, 7135 .axi_id = 1, 7136 .axi_yrgb_id = 0x0a, 7137 .axi_uv_id = 0x0b, 7138 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP2), 7139 .max_upscale_factor = 8, 7140 .max_downscale_factor = 8, 7141 .feature = WIN_FEATURE_MULTI_AREA, 7142 }, 7143 7144 { 7145 .name = "Esmart3", 7146 .phys_id = ROCKCHIP_VOP2_ESMART3, 7147 .type = ESMART_LAYER, 7148 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 7149 .layer_sel_win_id = { 0xff, 3, 3, 0xff }, 7150 .reg_offset = 0x600, 7151 .supported_rotations = DRM_MODE_REFLECT_Y, 7152 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7153 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7154 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7155 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7156 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7157 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ 7158 .pd_id = VOP2_PD_ESMART, 7159 .axi_id = 1, 7160 .axi_yrgb_id = 0x0c, 7161 .axi_uv_id = 0x0d, 7162 .possible_vp_mask = BIT(VOP2_VP1) | BIT(VOP2_VP2), 7163 .max_upscale_factor = 8, 7164 .max_downscale_factor = 8, 7165 .feature = WIN_FEATURE_MULTI_AREA, 7166 }, 7167 7168 { 7169 .name = "Cluster0", 7170 .phys_id = ROCKCHIP_VOP2_CLUSTER0, 7171 .type = CLUSTER_LAYER, 7172 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 7173 .layer_sel_win_id = { 0, 0, 0xff, 0xff }, 7174 .reg_offset = 0x0, 7175 .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, 7176 .hsu_filter_mode = VOP2_SCALE_UP_BIL, 7177 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7178 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7179 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7180 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7181 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7182 .pd_id = VOP2_PD_CLUSTER, 7183 .axi_yrgb_id = 0x0a, 7184 .axi_uv_id = 0x0b, 7185 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1), 7186 .max_upscale_factor = 8, 7187 .max_downscale_factor = 8, 7188 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | 7189 WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI, 7190 }, 7191 7192 { 7193 .name = "Cluster1", 7194 .phys_id = ROCKCHIP_VOP2_CLUSTER1, 7195 .type = CLUSTER_LAYER, 7196 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 7197 .layer_sel_win_id = { 1, 1, 0xff, 0xff }, 7198 .reg_offset = 0x200, 7199 .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, 7200 .hsu_filter_mode = VOP2_SCALE_UP_BIL, 7201 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7202 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7203 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7204 .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7205 .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ 7206 .pd_id = VOP2_PD_CLUSTER, 7207 .axi_yrgb_id = 0x06, 7208 .axi_uv_id = 0x07, 7209 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1), 7210 .max_upscale_factor = 8, 7211 .max_downscale_factor = 8, 7212 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | 7213 WIN_FEATURE_Y2R_13BIT_DEPTH, 7214 }, 7215 }; 7216 7217 /* 7218 * RK3576 VP0 has 8 lines post linebuffer, when full post line buffer is less 4, 7219 * the urgency signal will be set to 1, when full post line buffer is over 6, the 7220 * urgency signal will be set to 0. 7221 */ 7222 static struct vop_urgency rk3576_vp0_urgency = { 7223 .urgen_thl = 4, 7224 .urgen_thh = 6, 7225 }; 7226 7227 static struct vop2_vp_data rk3576_vp_data[3] = { 7228 { 7229 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR | 7230 VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT | 7231 VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP, 7232 .max_output = { 4096, 4096 }, 7233 .hdrvivid_dly = 21, 7234 .sdr2hdr_dly = 21, 7235 .layer_mix_dly = 8, 7236 .hdr_mix_dly = 2, 7237 .win_dly = 10, 7238 .pixel_rate = 2, 7239 .urgency = &rk3576_vp0_urgency, 7240 }, 7241 { 7242 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | 7243 VOP_FEATURE_OUTPUT_10BIT | VOP_FEATURE_POST_FRC_V2, 7244 .max_output = { 2560, 2560 }, 7245 .hdrvivid_dly = 0, 7246 .sdr2hdr_dly = 0, 7247 .layer_mix_dly = 6, 7248 .hdr_mix_dly = 0, 7249 .win_dly = 10, 7250 .pixel_rate = 1, 7251 }, 7252 { 7253 .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, 7254 .max_output = { 1920, 1920 }, 7255 .hdrvivid_dly = 0, 7256 .sdr2hdr_dly = 0, 7257 .layer_mix_dly = 6, 7258 .hdr_mix_dly = 0, 7259 .win_dly = 10, 7260 .pixel_rate = 1, 7261 }, 7262 }; 7263 7264 static struct vop2_power_domain_data rk3576_vop_pd_data[] = { 7265 { 7266 .id = VOP2_PD_CLUSTER, 7267 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1), 7268 }, 7269 { 7270 .id = VOP2_PD_ESMART, 7271 .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | 7272 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3), 7273 }, 7274 }; 7275 7276 static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = { 7277 {VOP3_ESMART_4K_4K_4K_MODE, 2}, 7278 {VOP3_ESMART_4K_4K_2K_2K_MODE, 3} 7279 }; 7280 7281 static const struct vop2_ops rk3576_vop_ops = { 7282 .setup_win_dly = rk3576_setup_win_dly, 7283 .setup_overlay = rk3576_setup_overlay, 7284 }; 7285 7286 const struct vop2_data rk3576_vop = { 7287 .version = VOP_VERSION_RK3576, 7288 .nr_vps = 3, 7289 .nr_mixers = 4, 7290 .nr_layers = 6, 7291 .nr_gammas = 3, 7292 .esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE, 7293 .esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map), 7294 .esmart_lb_mode_map = rk3576_esmart_lb_mode_map, 7295 .vp_data = rk3576_vp_data, 7296 .win_data = rk3576_win_data, 7297 .plane_mask_base = RK3576_PLANE_MASK_BASE, 7298 .pd = rk3576_vop_pd_data, 7299 .nr_pd = ARRAY_SIZE(rk3576_vop_pd_data), 7300 .dump_regs = rk3576_dump_regs, 7301 .dump_regs_size = ARRAY_SIZE(rk3576_dump_regs), 7302 .ops = &rk3576_vop_ops, 7303 }; 7304 7305 static struct vop2_dump_regs rk3588_dump_regs[] = { 7306 { RK3568_REG_CFG_DONE, "SYS", 0, 0, 0, 0 }, 7307 { RK3568_OVL_CTRL, "OVL", 0, 0, 0, 0 }, 7308 { RK3568_VP0_DSP_CTRL, "VP0", RK3568_VP0_DSP_CTRL, 0x1, 31, 0 }, 7309 { RK3568_VP1_DSP_CTRL, "VP1", RK3568_VP1_DSP_CTRL, 0x1, 31, 0 }, 7310 { RK3568_VP2_DSP_CTRL, "VP2", RK3568_VP2_DSP_CTRL, 0x1, 31, 0 }, 7311 { RK3588_VP3_DSP_CTRL, "VP3", RK3588_VP3_DSP_CTRL, 0x1, 31, 0 }, 7312 { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0, 1 }, 7313 { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0, 1 }, 7314 { RK3588_CLUSTER2_WIN0_CTRL0, "Cluster2", RK3588_CLUSTER2_WIN0_CTRL0, 0x1, 0, 1 }, 7315 { RK3588_CLUSTER3_WIN0_CTRL0, "Cluster3", RK3588_CLUSTER3_WIN0_CTRL0, 0x1, 0, 1 }, 7316 { RK3568_ESMART0_CTRL0, "Esmart0", RK3568_ESMART0_REGION0_CTRL, 0x1, 0, 1 }, 7317 { RK3568_ESMART1_CTRL0, "Esmart1", RK3568_ESMART1_REGION0_CTRL, 0x1, 0, 1 }, 7318 { RK3568_SMART0_CTRL0, "Esmart2", RK3568_SMART0_REGION0_CTRL, 0x1, 0, 1 }, 7319 { RK3568_SMART1_CTRL0, "Esmart3", RK3568_SMART1_REGION0_CTRL, 0x1, 0, 1 }, 7320 { RK3568_HDR_LUT_CTRL, "HDR", 0, 0, 0, 0 }, 7321 }; 7322 7323 static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 7324 { /* one display policy */ 7325 {/* main display */ 7326 .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 7327 .attached_layers_nr = 4, 7328 .attached_layers = { 7329 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 7330 ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 7331 }, 7332 }, 7333 7334 {/* planes for the splice mode */ 7335 .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 7336 .attached_layers_nr = 4, 7337 .attached_layers = { 7338 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, 7339 ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 7340 }, 7341 }, 7342 {/* third display */}, 7343 {/* fourth display */}, 7344 }, 7345 7346 { /* two display policy */ 7347 {/* main display */ 7348 .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 7349 .attached_layers_nr = 4, 7350 .attached_layers = { 7351 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 7352 ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 7353 }, 7354 }, 7355 7356 {/* second display */ 7357 .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 7358 .attached_layers_nr = 4, 7359 .attached_layers = { 7360 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, 7361 ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 7362 }, 7363 }, 7364 {/* third display */}, 7365 {/* fourth display */}, 7366 }, 7367 7368 { /* three display policy */ 7369 {/* main display */ 7370 .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 7371 .attached_layers_nr = 3, 7372 .attached_layers = { 7373 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER2, 7374 ROCKCHIP_VOP2_ESMART0 7375 }, 7376 }, 7377 7378 {/* second display */ 7379 .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 7380 .attached_layers_nr = 3, 7381 .attached_layers = { 7382 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_CLUSTER3, 7383 ROCKCHIP_VOP2_ESMART1 7384 }, 7385 }, 7386 7387 {/* third display */ 7388 .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 7389 .attached_layers_nr = 2, 7390 .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 7391 }, 7392 7393 {/* fourth display */}, 7394 }, 7395 7396 { /* four display policy */ 7397 {/* main display */ 7398 .primary_plane_id = ROCKCHIP_VOP2_ESMART0, 7399 .attached_layers_nr = 2, 7400 .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 7401 }, 7402 7403 {/* second display */ 7404 .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 7405 .attached_layers_nr = 2, 7406 .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 7407 }, 7408 7409 {/* third display */ 7410 .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 7411 .attached_layers_nr = 2, 7412 .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 7413 }, 7414 7415 {/* fourth display */ 7416 .primary_plane_id = ROCKCHIP_VOP2_ESMART3, 7417 .attached_layers_nr = 2, 7418 .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 7419 }, 7420 }, 7421 7422 }; 7423 7424 #define RK3588_PLANE_MASK_BASE \ 7425 (BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1) | \ 7426 BIT(ROCKCHIP_VOP2_CLUSTER2) | BIT(ROCKCHIP_VOP2_CLUSTER3) | \ 7427 BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | \ 7428 BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3)) 7429 7430 static struct vop2_win_data rk3588_win_data[8] = { 7431 { 7432 .name = "Cluster0", 7433 .phys_id = ROCKCHIP_VOP2_CLUSTER0, 7434 .splice_win_id = ROCKCHIP_VOP2_CLUSTER1, 7435 .type = CLUSTER_LAYER, 7436 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 7437 .win_sel_port_offset = 0, 7438 .layer_sel_win_id = { 0, 0, 0, 0 }, 7439 .reg_offset = 0, 7440 .axi_id = 0, 7441 .axi_yrgb_id = 2, 7442 .axi_uv_id = 3, 7443 .pd_id = VOP2_PD_CLUSTER0, 7444 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7445 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7446 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7447 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7448 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7449 .max_upscale_factor = 4, 7450 .max_downscale_factor = 4, 7451 .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7452 }, 7453 7454 { 7455 .name = "Cluster1", 7456 .phys_id = ROCKCHIP_VOP2_CLUSTER1, 7457 .type = CLUSTER_LAYER, 7458 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 7459 .win_sel_port_offset = 1, 7460 .layer_sel_win_id = { 1, 1, 1, 1 }, 7461 .reg_offset = 0x200, 7462 .axi_id = 0, 7463 .axi_yrgb_id = 6, 7464 .axi_uv_id = 7, 7465 .pd_id = VOP2_PD_CLUSTER1, 7466 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7467 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7468 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7469 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7470 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7471 .max_upscale_factor = 4, 7472 .max_downscale_factor = 4, 7473 .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7474 }, 7475 7476 { 7477 .name = "Cluster2", 7478 .phys_id = ROCKCHIP_VOP2_CLUSTER2, 7479 .splice_win_id = ROCKCHIP_VOP2_CLUSTER3, 7480 .type = CLUSTER_LAYER, 7481 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 7482 .win_sel_port_offset = 2, 7483 .layer_sel_win_id = { 4, 4, 4, 4 }, 7484 .reg_offset = 0x400, 7485 .axi_id = 1, 7486 .axi_yrgb_id = 2, 7487 .axi_uv_id = 3, 7488 .pd_id = VOP2_PD_CLUSTER2, 7489 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7490 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7491 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7492 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7493 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7494 .max_upscale_factor = 4, 7495 .max_downscale_factor = 4, 7496 .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7497 }, 7498 7499 { 7500 .name = "Cluster3", 7501 .phys_id = ROCKCHIP_VOP2_CLUSTER3, 7502 .type = CLUSTER_LAYER, 7503 .plane_type = VOP2_PLANE_TYPE_OVERLAY, 7504 .win_sel_port_offset = 3, 7505 .layer_sel_win_id = { 5, 5, 5, 5 }, 7506 .reg_offset = 0x600, 7507 .axi_id = 1, 7508 .axi_yrgb_id = 6, 7509 .axi_uv_id = 7, 7510 .pd_id = VOP2_PD_CLUSTER3, 7511 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7512 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7513 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7514 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7515 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7516 .max_upscale_factor = 4, 7517 .max_downscale_factor = 4, 7518 .dly = { 4, 26, 29, 4, 35, 3, 5 }, 7519 }, 7520 7521 { 7522 .name = "Esmart0", 7523 .phys_id = ROCKCHIP_VOP2_ESMART0, 7524 .splice_win_id = ROCKCHIP_VOP2_ESMART1, 7525 .type = ESMART_LAYER, 7526 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 7527 .win_sel_port_offset = 4, 7528 .layer_sel_win_id = { 2, 2, 2, 2 }, 7529 .reg_offset = 0, 7530 .axi_id = 0, 7531 .axi_yrgb_id = 0x0a, 7532 .axi_uv_id = 0x0b, 7533 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7534 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7535 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7536 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7537 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7538 .max_upscale_factor = 8, 7539 .max_downscale_factor = 8, 7540 .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7541 }, 7542 7543 { 7544 .name = "Esmart1", 7545 .phys_id = ROCKCHIP_VOP2_ESMART1, 7546 .type = ESMART_LAYER, 7547 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 7548 .win_sel_port_offset = 5, 7549 .layer_sel_win_id = { 3, 3, 3, 3 }, 7550 .reg_offset = 0x200, 7551 .axi_id = 0, 7552 .axi_yrgb_id = 0x0c, 7553 .axi_uv_id = 0x0d, 7554 .pd_id = VOP2_PD_ESMART, 7555 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7556 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7557 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7558 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7559 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7560 .max_upscale_factor = 8, 7561 .max_downscale_factor = 8, 7562 .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7563 }, 7564 7565 { 7566 .name = "Esmart2", 7567 .phys_id = ROCKCHIP_VOP2_ESMART2, 7568 .splice_win_id = ROCKCHIP_VOP2_ESMART3, 7569 .type = ESMART_LAYER, 7570 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 7571 .win_sel_port_offset = 6, 7572 .layer_sel_win_id = { 6, 6, 6, 6 }, 7573 .reg_offset = 0x400, 7574 .axi_id = 1, 7575 .axi_yrgb_id = 0x0a, 7576 .axi_uv_id = 0x0b, 7577 .pd_id = VOP2_PD_ESMART, 7578 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7579 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7580 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7581 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7582 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7583 .max_upscale_factor = 8, 7584 .max_downscale_factor = 8, 7585 .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7586 }, 7587 7588 { 7589 .name = "Esmart3", 7590 .phys_id = ROCKCHIP_VOP2_ESMART3, 7591 .type = ESMART_LAYER, 7592 .plane_type = VOP2_PLANE_TYPE_PRIMARY, 7593 .win_sel_port_offset = 7, 7594 .layer_sel_win_id = { 7, 7, 7, 7 }, 7595 .reg_offset = 0x600, 7596 .axi_id = 1, 7597 .axi_yrgb_id = 0x0c, 7598 .axi_uv_id = 0x0d, 7599 .pd_id = VOP2_PD_ESMART, 7600 .hsu_filter_mode = VOP2_SCALE_UP_BIC, 7601 .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7602 .vsu_filter_mode = VOP2_SCALE_UP_BIL, 7603 .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, 7604 .possible_vp_mask = BIT(VOP2_VP0) | BIT(VOP2_VP1) | BIT(VOP2_VP2) | BIT(VOP2_VP3), 7605 .max_upscale_factor = 8, 7606 .max_downscale_factor = 8, 7607 .dly = { 23, 45, 48, 23, 54, 22, 24 }, 7608 }, 7609 }; 7610 7611 static struct dsc_error_info dsc_ecw[] = { 7612 {0x00000000, "no error detected by DSC encoder"}, 7613 {0x0030ffff, "bits per component error"}, 7614 {0x0040ffff, "multiple mode error"}, 7615 {0x0050ffff, "line buffer depth error"}, 7616 {0x0060ffff, "minor version error"}, 7617 {0x0070ffff, "picture height error"}, 7618 {0x0080ffff, "picture width error"}, 7619 {0x0090ffff, "number of slices error"}, 7620 {0x00c0ffff, "slice height Error "}, 7621 {0x00d0ffff, "slice width error"}, 7622 {0x00e0ffff, "second line BPG offset error"}, 7623 {0x00f0ffff, "non second line BPG offset error"}, 7624 {0x0100ffff, "PPS ID error"}, 7625 {0x0110ffff, "bits per pixel (BPP) Error"}, 7626 {0x0120ffff, "buffer flow error"}, /* dsc_buffer_flow */ 7627 7628 {0x01510001, "slice 0 RC buffer model overflow error"}, 7629 {0x01510002, "slice 1 RC buffer model overflow error"}, 7630 {0x01510004, "slice 2 RC buffer model overflow error"}, 7631 {0x01510008, "slice 3 RC buffer model overflow error"}, 7632 {0x01510010, "slice 4 RC buffer model overflow error"}, 7633 {0x01510020, "slice 5 RC buffer model overflow error"}, 7634 {0x01510040, "slice 6 RC buffer model overflow error"}, 7635 {0x01510080, "slice 7 RC buffer model overflow error"}, 7636 7637 {0x01610001, "slice 0 RC buffer model underflow error"}, 7638 {0x01610002, "slice 1 RC buffer model underflow error"}, 7639 {0x01610004, "slice 2 RC buffer model underflow error"}, 7640 {0x01610008, "slice 3 RC buffer model underflow error"}, 7641 {0x01610010, "slice 4 RC buffer model underflow error"}, 7642 {0x01610020, "slice 5 RC buffer model underflow error"}, 7643 {0x01610040, "slice 6 RC buffer model underflow error"}, 7644 {0x01610080, "slice 7 RC buffer model underflow error"}, 7645 7646 {0xffffffff, "unsuccessful RESET cycle status"}, 7647 {0x00a0ffff, "ICH full error precision settings error"}, 7648 {0x0020ffff, "native mode"}, 7649 }; 7650 7651 static struct dsc_error_info dsc_buffer_flow[] = { 7652 {0x00000000, "rate buffer status"}, 7653 {0x00000001, "line buffer status"}, 7654 {0x00000002, "decoder model status"}, 7655 {0x00000003, "pixel buffer status"}, 7656 {0x00000004, "balance fifo buffer status"}, 7657 {0x00000005, "syntax element fifo status"}, 7658 }; 7659 7660 static struct vop2_dsc_data rk3588_dsc_data[] = { 7661 { 7662 .id = ROCKCHIP_VOP2_DSC_8K, 7663 .pd_id = VOP2_PD_DSC_8K, 7664 .max_slice_num = 8, 7665 .max_linebuf_depth = 11, 7666 .min_bits_per_pixel = 8, 7667 .dsc_txp_clk_src_name = "dsc_8k_txp_clk_src", 7668 .dsc_txp_clk_name = "dsc_8k_txp_clk", 7669 .dsc_pxl_clk_name = "dsc_8k_pxl_clk", 7670 .dsc_cds_clk_name = "dsc_8k_cds_clk", 7671 }, 7672 7673 { 7674 .id = ROCKCHIP_VOP2_DSC_4K, 7675 .pd_id = VOP2_PD_DSC_4K, 7676 .max_slice_num = 2, 7677 .max_linebuf_depth = 11, 7678 .min_bits_per_pixel = 8, 7679 .dsc_txp_clk_src_name = "dsc_4k_txp_clk_src", 7680 .dsc_txp_clk_name = "dsc_4k_txp_clk", 7681 .dsc_pxl_clk_name = "dsc_4k_pxl_clk", 7682 .dsc_cds_clk_name = "dsc_4k_cds_clk", 7683 }, 7684 }; 7685 7686 static struct vop2_vp_data rk3588_vp_data[4] = { 7687 { 7688 .splice_vp_id = 1, 7689 .feature = VOP_FEATURE_OUTPUT_10BIT, 7690 .pre_scan_max_dly = 54, 7691 .max_dclk = 600000, 7692 .max_output = {7680, 4320}, 7693 }, 7694 { 7695 .feature = VOP_FEATURE_OUTPUT_10BIT, 7696 .pre_scan_max_dly = 54, 7697 .max_dclk = 600000, 7698 .max_output = {4096, 2304}, 7699 }, 7700 { 7701 .feature = VOP_FEATURE_OUTPUT_10BIT, 7702 .pre_scan_max_dly = 52, 7703 .max_dclk = 600000, 7704 .max_output = {4096, 2304}, 7705 }, 7706 { 7707 .feature = 0, 7708 .pre_scan_max_dly = 52, 7709 .max_dclk = 200000, 7710 .max_output = {1920, 1080}, 7711 }, 7712 }; 7713 7714 static struct vop2_power_domain_data rk3588_vop_pd_data[] = { 7715 { 7716 .id = VOP2_PD_CLUSTER0, 7717 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0), 7718 }, 7719 { 7720 .id = VOP2_PD_CLUSTER1, 7721 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER1), 7722 .parent_id = VOP2_PD_CLUSTER0, 7723 }, 7724 { 7725 .id = VOP2_PD_CLUSTER2, 7726 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER2), 7727 .parent_id = VOP2_PD_CLUSTER0, 7728 }, 7729 { 7730 .id = VOP2_PD_CLUSTER3, 7731 .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER3), 7732 .parent_id = VOP2_PD_CLUSTER0, 7733 }, 7734 { 7735 .id = VOP2_PD_ESMART, 7736 .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART1) | 7737 BIT(ROCKCHIP_VOP2_ESMART2) | 7738 BIT(ROCKCHIP_VOP2_ESMART3), 7739 }, 7740 { 7741 .id = VOP2_PD_DSC_8K, 7742 .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_8K), 7743 }, 7744 { 7745 .id = VOP2_PD_DSC_4K, 7746 .module_id_mask = BIT(ROCKCHIP_VOP2_DSC_4K), 7747 }, 7748 }; 7749 7750 static const struct vop2_ops rk3588_vop_ops = { 7751 .setup_win_dly = rk3568_setup_win_dly, 7752 .setup_overlay = rk3568_setup_overlay, 7753 }; 7754 7755 const struct vop2_data rk3588_vop = { 7756 .version = VOP_VERSION_RK3588, 7757 .nr_vps = 4, 7758 .vp_data = rk3588_vp_data, 7759 .win_data = rk3588_win_data, 7760 .plane_mask = rk3588_vp_plane_mask[0], 7761 .plane_mask_base = RK3588_PLANE_MASK_BASE, 7762 .pd = rk3588_vop_pd_data, 7763 .dsc = rk3588_dsc_data, 7764 .dsc_error_ecw = dsc_ecw, 7765 .dsc_error_buffer_flow = dsc_buffer_flow, 7766 .nr_layers = 8, 7767 .nr_mixers = 7, 7768 .nr_gammas = 4, 7769 .nr_pd = ARRAY_SIZE(rk3588_vop_pd_data), 7770 .nr_dscs = 2, 7771 .nr_dsc_ecw = ARRAY_SIZE(dsc_ecw), 7772 .nr_dsc_buffer_flow = ARRAY_SIZE(dsc_buffer_flow), 7773 .dump_regs = rk3588_dump_regs, 7774 .dump_regs_size = ARRAY_SIZE(rk3588_dump_regs), 7775 .ops = &rk3588_vop_ops, 7776 }; 7777 7778 const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 7779 .preinit = rockchip_vop2_preinit, 7780 .prepare = rockchip_vop2_prepare, 7781 .init = rockchip_vop2_init, 7782 .set_plane = rockchip_vop2_set_plane, 7783 .enable = rockchip_vop2_enable, 7784 .post_enable = rockchip_vop2_post_enable, 7785 .disable = rockchip_vop2_disable, 7786 .fixup_dts = rockchip_vop2_fixup_dts, 7787 .send_mcu_cmd = rockchip_vop2_send_mcu_cmd, 7788 .check = rockchip_vop2_check, 7789 .mode_valid = rockchip_vop2_mode_valid, 7790 .mode_fixup = rockchip_vop2_mode_fixup, 7791 .plane_check = rockchip_vop2_plane_check, 7792 .regs_dump = rockchip_vop2_regs_dump, 7793 .active_regs_dump = rockchip_vop2_active_regs_dump, 7794 .apply_soft_te = rockchip_vop2_apply_soft_te, 7795 }; 7796