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