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