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