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 <asm/arch/cpu.h> 14 #include <asm/unaligned.h> 15 #include <asm/io.h> 16 #include <linux/list.h> 17 #include <linux/log2.h> 18 #include <linux/media-bus-format.h> 19 #include <clk.h> 20 #include <asm/arch/clock.h> 21 #include <linux/err.h> 22 #include <linux/ioport.h> 23 #include <dm/device.h> 24 #include <dm/read.h> 25 #include <fixp-arith.h> 26 #include <syscon.h> 27 #include <linux/iopoll.h> 28 29 #include "rockchip_display.h" 30 #include "rockchip_crtc.h" 31 #include "rockchip_connector.h" 32 33 /* System registers definition */ 34 #define RK3568_REG_CFG_DONE 0x000 35 #define CFG_DONE_EN BIT(15) 36 37 #define RK3568_VERSION_INFO 0x004 38 #define EN_MASK 1 39 40 #define RK3568_AUTO_GATING_CTRL 0x008 41 42 #define RK3568_SYS_AXI_LUT_CTRL 0x024 43 #define LUT_DMA_EN_SHIFT 0 44 45 #define RK3568_DSP_IF_EN 0x028 46 #define RGB_EN_SHIFT 0 47 #define RK3588_DP0_EN_SHIFT 0 48 #define RK3588_DP1_EN_SHIFT 1 49 #define RK3588_RGB_EN_SHIFT 8 50 #define HDMI0_EN_SHIFT 1 51 #define EDP0_EN_SHIFT 3 52 #define RK3588_EDP0_EN_SHIFT 2 53 #define RK3588_HDMI0_EN_SHIFT 3 54 #define MIPI0_EN_SHIFT 4 55 #define RK3588_EDP1_EN_SHIFT 4 56 #define RK3588_HDMI1_EN_SHIFT 5 57 #define RK3588_MIPI0_EN_SHIFT 6 58 #define MIPI1_EN_SHIFT 20 59 #define RK3588_MIPI1_EN_SHIFT 7 60 #define LVDS0_EN_SHIFT 5 61 #define LVDS1_EN_SHIFT 24 62 #define BT1120_EN_SHIFT 6 63 #define BT656_EN_SHIFT 7 64 #define IF_MUX_MASK 3 65 #define RGB_MUX_SHIFT 8 66 #define HDMI0_MUX_SHIFT 10 67 #define RK3588_DP0_MUX_SHIFT 12 68 #define RK3588_DP1_MUX_SHIFT 14 69 #define EDP0_MUX_SHIFT 14 70 #define RK3588_HDMI_EDP0_MUX_SHIFT 16 71 #define RK3588_HDMI_EDP1_MUX_SHIFT 18 72 #define MIPI0_MUX_SHIFT 16 73 #define RK3588_MIPI0_MUX_SHIFT 20 74 #define MIPI1_MUX_SHIFT 21 75 #define LVDS0_MUX_SHIFT 18 76 #define LVDS1_MUX_SHIFT 25 77 78 #define RK3568_DSP_IF_CTRL 0x02c 79 #define LVDS_DUAL_EN_SHIFT 0 80 #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 81 #define LVDS_DUAL_SWAP_EN_SHIFT 2 82 #define RK3568_MIPI_DUAL_EN_SHIFT 10 83 #define RK3588_MIPI_DSI0_MODE_SEL_SHIFT 11 84 #define RK3588_MIPI_DSI1_MODE_SEL_SHIFT 12 85 86 #define RK3568_DSP_IF_POL 0x030 87 #define IF_CTRL_REG_DONE_IMD_MASK 1 88 #define IF_CTRL_REG_DONE_IMD_SHIFT 28 89 #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 90 #define IF_CRTL_EDP_DCLK_POL_SHIT 15 91 #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 92 #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 93 #define IF_CRTL_HDMI_PIN_POL_SHIT 4 94 95 #define RK3588_DP0_PIN_POL_SHIFT 8 96 #define RK3588_DP1_PIN_POL_SHIFT 12 97 #define RK3588_IF_PIN_POL_MASK 0x7 98 99 #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT 3 100 101 #define HDMI_EDP0_DCLK_DIV_SHIFT 16 102 #define HDMI_EDP0_PIXCLK_DIV_SHIFT 18 103 #define HDMI_EDP1_DCLK_DIV_SHIFT 20 104 #define HDMI_EDP1_PIXCLK_DIV_SHIFT 22 105 #define MIPI0_PIXCLK_DIV_SHIFT 24 106 #define MIPI1_PIXCLK_DIV_SHIFT 26 107 108 #define RK3568_SYS_OTP_WIN_EN 0x50 109 #define OTP_WIN_EN_SHIFT 0 110 #define RK3568_SYS_LUT_PORT_SEL 0x58 111 #define GAMMA_PORT_SEL_MASK 0x3 112 #define GAMMA_PORT_SEL_SHIFT 0 113 114 #define RK3568_SYS_PD_CTRL 0x034 115 #define RK3568_VP0_LINE_FLAG 0x70 116 #define RK3568_VP1_LINE_FLAG 0x74 117 #define RK3568_VP2_LINE_FLAG 0x78 118 #define RK3568_SYS0_INT_EN 0x80 119 #define RK3568_SYS0_INT_CLR 0x84 120 #define RK3568_SYS0_INT_STATUS 0x88 121 #define RK3568_SYS1_INT_EN 0x90 122 #define RK3568_SYS1_INT_CLR 0x94 123 #define RK3568_SYS1_INT_STATUS 0x98 124 #define RK3568_VP0_INT_EN 0xA0 125 #define RK3568_VP0_INT_CLR 0xA4 126 #define RK3568_VP0_INT_STATUS 0xA8 127 #define RK3568_VP1_INT_EN 0xB0 128 #define RK3568_VP1_INT_CLR 0xB4 129 #define RK3568_VP1_INT_STATUS 0xB8 130 #define RK3568_VP2_INT_EN 0xC0 131 #define RK3568_VP2_INT_CLR 0xC4 132 #define RK3568_VP2_INT_STATUS 0xC8 133 #define RK3588_CLUSTER0_PD_EN_SHIFT 0 134 #define RK3588_CLUSTER1_PD_EN_SHIFT 1 135 #define RK3588_CLUSTER2_PD_EN_SHIFT 2 136 #define RK3588_CLUSTER3_PD_EN_SHIFT 3 137 #define RK3588_ESMART_PD_EN_SHIFT 7 138 139 #define RK3568_SYS_STATUS0 0x60 140 #define RK3588_CLUSTER0_PD_STATUS_SHIFT 8 141 #define RK3588_CLUSTER1_PD_STATUS_SHIFT 9 142 #define RK3588_CLUSTER2_PD_STATUS_SHIFT 10 143 #define RK3588_CLUSTER3_PD_STATUS_SHIFT 11 144 #define RK3588_ESMART_PD_STATUS_SHIFT 15 145 146 #define RK3568_SYS_CTRL_LINE_FLAG0 0x70 147 #define LINE_FLAG_NUM_MASK 0x1fff 148 #define RK3568_DSP_LINE_FLAG_NUM0_SHIFT 0 149 #define RK3568_DSP_LINE_FLAG_NUM1_SHIFT 16 150 151 /* Overlay registers definition */ 152 #define RK3568_OVL_CTRL 0x600 153 #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 154 #define RK3568_OVL_LAYER_SEL 0x604 155 #define LAYER_SEL_MASK 0xf 156 157 #define RK3568_OVL_PORT_SEL 0x608 158 #define PORT_MUX_MASK 0xf 159 #define PORT_MUX_SHIFT 0 160 #define LAYER_SEL_PORT_MASK 0x3 161 #define LAYER_SEL_PORT_SHIFT 16 162 163 #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 164 #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 165 #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 166 #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 167 #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 168 #define RK3568_MIX0_DST_COLOR_CTRL 0x654 169 #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 170 #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 171 #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 172 #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 173 #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 174 #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 175 #define RK3568_VP0_BG_MIX_CTRL 0x6E0 176 #define BG_MIX_CTRL_MASK 0xff 177 #define BG_MIX_CTRL_SHIFT 24 178 #define RK3568_VP1_BG_MIX_CTRL 0x6E4 179 #define RK3568_VP2_BG_MIX_CTRL 0x6E8 180 #define RK3568_CLUSTER_DLY_NUM 0x6F0 181 #define RK3568_SMART_DLY_NUM 0x6F8 182 183 /* Video Port registers definition */ 184 #define RK3568_VP0_DSP_CTRL 0xC00 185 #define OUT_MODE_MASK 0xf 186 #define OUT_MODE_SHIFT 0 187 #define DATA_SWAP_MASK 0x1f 188 #define DATA_SWAP_SHIFT 8 189 #define DSP_BG_SWAP 0x1 190 #define DSP_RB_SWAP 0x2 191 #define DSP_RG_SWAP 0x4 192 #define DSP_DELTA_SWAP 0x8 193 #define CORE_DCLK_DIV_EN_SHIFT 4 194 #define P2I_EN_SHIFT 5 195 #define DSP_FILED_POL 6 196 #define INTERLACE_EN_SHIFT 7 197 #define POST_DSP_OUT_R2Y_SHIFT 15 198 #define PRE_DITHER_DOWN_EN_SHIFT 16 199 #define DITHER_DOWN_EN_SHIFT 17 200 #define DSP_LUT_EN_SHIFT 28 201 202 #define STANDBY_EN_SHIFT 31 203 204 #define RK3568_VP0_MIPI_CTRL 0xC04 205 #define DCLK_DIV2_SHIFT 4 206 #define DCLK_DIV2_MASK 0x3 207 #define MIPI_DUAL_EN_SHIFT 20 208 #define MIPI_DUAL_SWAP_EN_SHIFT 21 209 #define EDPI_TE_EN 28 210 #define EDPI_WMS_HOLD_EN 30 211 #define EDPI_WMS_FS 31 212 213 214 #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 215 #define RK3568_VP0_3D_LUT_CTRL 0xC10 216 #define VP0_3D_LUT_EN_SHIFT 0 217 #define VP0_3D_LUT_UPDATE_SHIFT 2 218 219 #define RK3588_VP0_CLK_CTRL 0xC0C 220 #define DCLK_CORE_DIV_SHIFT 0 221 #define DCLK_OUT_DIV_SHIFT 2 222 223 #define RK3568_VP0_3D_LUT_MST 0xC20 224 225 #define RK3568_VP0_DSP_BG 0xC2C 226 #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 227 #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 228 #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 229 #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 230 #define RK3568_VP0_POST_SCL_CTRL 0xC40 231 #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 232 #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 233 #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 234 #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 235 #define RK3568_VP0_DSP_VACT_ST_END 0xC54 236 #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 237 #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 238 239 #define RK3568_VP0_BCSH_CTRL 0xC60 240 #define BCSH_CTRL_Y2R_SHIFT 0 241 #define BCSH_CTRL_Y2R_MASK 0x1 242 #define BCSH_CTRL_Y2R_CSC_MODE_SHIFT 2 243 #define BCSH_CTRL_Y2R_CSC_MODE_MASK 0x3 244 #define BCSH_CTRL_R2Y_SHIFT 4 245 #define BCSH_CTRL_R2Y_MASK 0x1 246 #define BCSH_CTRL_R2Y_CSC_MODE_SHIFT 6 247 #define BCSH_CTRL_R2Y_CSC_MODE_MASK 0x3 248 249 #define RK3568_VP0_BCSH_BCS 0xC64 250 #define BCSH_BRIGHTNESS_SHIFT 0 251 #define BCSH_BRIGHTNESS_MASK 0xFF 252 #define BCSH_CONTRAST_SHIFT 8 253 #define BCSH_CONTRAST_MASK 0x1FF 254 #define BCSH_SATURATION_SHIFT 20 255 #define BCSH_SATURATION_MASK 0x3FF 256 #define BCSH_OUT_MODE_SHIFT 30 257 #define BCSH_OUT_MODE_MASK 0x3 258 259 #define RK3568_VP0_BCSH_H 0xC68 260 #define BCSH_SIN_HUE_SHIFT 0 261 #define BCSH_SIN_HUE_MASK 0x1FF 262 #define BCSH_COS_HUE_SHIFT 16 263 #define BCSH_COS_HUE_MASK 0x1FF 264 265 #define RK3568_VP0_BCSH_COLOR 0xC6C 266 #define BCSH_EN_SHIFT 31 267 #define BCSH_EN_MASK 1 268 269 #define RK3568_VP1_DSP_CTRL 0xD00 270 #define RK3568_VP1_MIPI_CTRL 0xD04 271 #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 272 #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 273 #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 274 #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 275 #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 276 #define RK3568_VP1_POST_SCL_CTRL 0xD40 277 #define RK3568_VP1_DSP_HACT_INFO 0xD34 278 #define RK3568_VP1_DSP_VACT_INFO 0xD38 279 #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 280 #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 281 #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 282 #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 283 #define RK3568_VP1_DSP_VACT_ST_END 0xD54 284 #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 285 #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 286 287 #define RK3568_VP2_DSP_CTRL 0xE00 288 #define RK3568_VP2_MIPI_CTRL 0xE04 289 #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 290 #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 291 #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 292 #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 293 #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 294 #define RK3568_VP2_POST_SCL_CTRL 0xE40 295 #define RK3568_VP2_DSP_HACT_INFO 0xE34 296 #define RK3568_VP2_DSP_VACT_INFO 0xE38 297 #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 298 #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 299 #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 300 #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 301 #define RK3568_VP2_DSP_VACT_ST_END 0xE54 302 #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 303 #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 304 305 /* Cluster0 register definition */ 306 #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 307 #define CLUSTER_YUV2RGB_EN_SHIFT 8 308 #define CLUSTER_RGB2YUV_EN_SHIFT 9 309 #define CLUSTER_CSC_MODE_SHIFT 10 310 #define CLUSTER_YRGB_XSCL_MODE_SHIFT 12 311 #define CLUSTER_YRGB_YSCL_MODE_SHIFT 14 312 #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 313 #define CLUSTER_YRGB_GT2_SHIFT 28 314 #define CLUSTER_YRGB_GT4_SHIFT 29 315 #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 316 #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 317 #define RK3568_CLUSTER0_WIN0_VIR 0x1018 318 #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 319 #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 320 #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 321 #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 322 #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 323 #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 324 #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 325 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 326 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 327 #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 328 #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 329 330 #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 331 #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 332 #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 333 #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 334 #define RK3568_CLUSTER0_WIN1_VIR 0x1098 335 #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 336 #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 337 #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 338 #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 339 #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 340 #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 341 #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 342 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 343 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 344 #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 345 #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 346 347 #define RK3568_CLUSTER0_CTRL 0x1100 348 #define CLUSTER_EN_SHIFT 0 349 350 #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 351 #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 352 #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 353 #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 354 #define RK3568_CLUSTER1_WIN0_VIR 0x1218 355 #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 356 #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 357 #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 358 #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 359 #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 360 #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 361 #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 362 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 363 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 364 #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 365 #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 366 367 #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 368 #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 369 #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 370 #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 371 #define RK3568_CLUSTER1_WIN1_VIR 0x1298 372 #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 373 #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 374 #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 375 #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 376 #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 377 #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 378 #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 379 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 380 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 381 #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 382 #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 383 384 #define RK3568_CLUSTER1_CTRL 0x1300 385 386 /* Esmart register definition */ 387 #define RK3568_ESMART0_CTRL0 0x1800 388 #define RGB2YUV_EN_SHIFT 1 389 #define CSC_MODE_SHIFT 2 390 #define CSC_MODE_MASK 0x3 391 392 #define RK3568_ESMART0_CTRL1 0x1804 393 #define YMIRROR_EN_SHIFT 31 394 #define RK3568_ESMART0_REGION0_CTRL 0x1810 395 #define REGION0_RB_SWAP_SHIFT 14 396 #define WIN_EN_SHIFT 0 397 #define WIN_FORMAT_MASK 0x1f 398 #define WIN_FORMAT_SHIFT 1 399 400 #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 401 #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 402 #define RK3568_ESMART0_REGION0_VIR 0x181C 403 #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 404 #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 405 #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 406 #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 407 #define YRGB_XSCL_MODE_MASK 0x3 408 #define YRGB_XSCL_MODE_SHIFT 0 409 #define YRGB_XSCL_FILTER_MODE_MASK 0x3 410 #define YRGB_XSCL_FILTER_MODE_SHIFT 2 411 #define YRGB_YSCL_MODE_MASK 0x3 412 #define YRGB_YSCL_MODE_SHIFT 4 413 #define YRGB_YSCL_FILTER_MODE_MASK 0x3 414 #define YRGB_YSCL_FILTER_MODE_SHIFT 6 415 416 #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 417 #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 418 #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 419 #define RK3568_ESMART0_REGION1_CTRL 0x1840 420 #define YRGB_GT2_MASK 0x1 421 #define YRGB_GT2_SHIFT 8 422 #define YRGB_GT4_MASK 0x1 423 #define YRGB_GT4_SHIFT 9 424 425 #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 426 #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 427 #define RK3568_ESMART0_REGION1_VIR 0x184C 428 #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 429 #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 430 #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 431 #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 432 #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 433 #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 434 #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 435 #define RK3568_ESMART0_REGION2_CTRL 0x1870 436 #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 437 #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 438 #define RK3568_ESMART0_REGION2_VIR 0x187C 439 #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 440 #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 441 #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 442 #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 443 #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 444 #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 445 #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 446 #define RK3568_ESMART0_REGION3_CTRL 0x18A0 447 #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 448 #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 449 #define RK3568_ESMART0_REGION3_VIR 0x18AC 450 #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 451 #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 452 #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 453 #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 454 #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 455 #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 456 #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 457 458 #define RK3568_ESMART1_CTRL0 0x1A00 459 #define RK3568_ESMART1_CTRL1 0x1A04 460 #define RK3568_ESMART1_REGION0_CTRL 0x1A10 461 #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 462 #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 463 #define RK3568_ESMART1_REGION0_VIR 0x1A1C 464 #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 465 #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 466 #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 467 #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 468 #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 469 #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 470 #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 471 #define RK3568_ESMART1_REGION1_CTRL 0x1A40 472 #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 473 #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 474 #define RK3568_ESMART1_REGION1_VIR 0x1A4C 475 #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 476 #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 477 #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 478 #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 479 #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 480 #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 481 #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 482 #define RK3568_ESMART1_REGION2_CTRL 0x1A70 483 #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 484 #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 485 #define RK3568_ESMART1_REGION2_VIR 0x1A7C 486 #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 487 #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 488 #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 489 #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 490 #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 491 #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 492 #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 493 #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 494 #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 495 #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 496 #define RK3568_ESMART1_REGION3_VIR 0x1AAC 497 #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 498 #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 499 #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 500 #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 501 #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 502 #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 503 #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 504 505 #define RK3568_SMART0_CTRL0 0x1C00 506 #define RK3568_SMART0_CTRL1 0x1C04 507 #define RK3568_SMART0_REGION0_CTRL 0x1C10 508 #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 509 #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 510 #define RK3568_SMART0_REGION0_VIR 0x1C1C 511 #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 512 #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 513 #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 514 #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 515 #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 516 #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 517 #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 518 #define RK3568_SMART0_REGION1_CTRL 0x1C40 519 #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 520 #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 521 #define RK3568_SMART0_REGION1_VIR 0x1C4C 522 #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 523 #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 524 #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 525 #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 526 #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 527 #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 528 #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 529 #define RK3568_SMART0_REGION2_CTRL 0x1C70 530 #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 531 #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 532 #define RK3568_SMART0_REGION2_VIR 0x1C7C 533 #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 534 #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 535 #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 536 #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 537 #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 538 #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 539 #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 540 #define RK3568_SMART0_REGION3_CTRL 0x1CA0 541 #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 542 #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 543 #define RK3568_SMART0_REGION3_VIR 0x1CAC 544 #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 545 #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 546 #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 547 #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 548 #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 549 #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 550 #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 551 552 #define RK3568_SMART1_CTRL0 0x1E00 553 #define RK3568_SMART1_CTRL1 0x1E04 554 #define RK3568_SMART1_REGION0_CTRL 0x1E10 555 #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 556 #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 557 #define RK3568_SMART1_REGION0_VIR 0x1E1C 558 #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 559 #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 560 #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 561 #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 562 #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 563 #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 564 #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 565 #define RK3568_SMART1_REGION1_CTRL 0x1E40 566 #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 567 #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 568 #define RK3568_SMART1_REGION1_VIR 0x1E4C 569 #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 570 #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 571 #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 572 #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 573 #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 574 #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 575 #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 576 #define RK3568_SMART1_REGION2_CTRL 0x1E70 577 #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 578 #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 579 #define RK3568_SMART1_REGION2_VIR 0x1E7C 580 #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 581 #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 582 #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 583 #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 584 #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 585 #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 586 #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 587 #define RK3568_SMART1_REGION3_CTRL 0x1EA0 588 #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 589 #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 590 #define RK3568_SMART1_REGION3_VIR 0x1EAC 591 #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 592 #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 593 #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 594 #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 595 #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 596 #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 597 #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 598 599 #define RK3568_MAX_REG 0x1ED0 600 601 #define RK3568_GRF_VO_CON1 0x0364 602 #define GRF_BT656_CLK_INV_SHIFT 1 603 #define GRF_BT1120_CLK_INV_SHIFT 2 604 #define GRF_RGB_DCLK_INV_SHIFT 3 605 606 #define RK3588_GRF_VOP_CON2 0x0008 607 #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 608 #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 609 #define RK3588_GRF_EDP1_ENABLE_SHIFT 3 610 #define RK3588_GRF_HDMITX1_ENABLE_SHIFT 4 611 612 #define RK3588_PMU_BISR_CON3 0x20C 613 #define RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT 9 614 #define RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT 10 615 #define RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT 11 616 #define RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT 12 617 #define RK3588_PD_ESMART_REPAIR_EN_SHIFT 15 618 619 #define RK3588_PMU_BISR_STATUS5 0x294 620 #define RK3588_PD_CLUSTER0_PWR_STAT_SHIFI 9 621 #define RK3588_PD_CLUSTER1_PWR_STAT_SHIFI 10 622 #define RK3588_PD_CLUSTER2_PWR_STAT_SHIFI 11 623 #define RK3588_PD_CLUSTER3_PWR_STAT_SHIFI 12 624 #define RK3588_PD_ESMART_PWR_STAT_SHIFI 15 625 626 #define VOP2_LAYER_MAX 8 627 628 #define VOP_FEATURE_OUTPUT_10BIT BIT(0) 629 630 enum vop2_csc_format { 631 CSC_BT601L, 632 CSC_BT709L, 633 CSC_BT601F, 634 CSC_BT2020, 635 }; 636 637 enum vop2_pol { 638 HSYNC_POSITIVE = 0, 639 VSYNC_POSITIVE = 1, 640 DEN_NEGATIVE = 2, 641 DCLK_INVERT = 3 642 }; 643 644 enum vop2_bcsh_out_mode { 645 BCSH_OUT_MODE_BLACK, 646 BCSH_OUT_MODE_BLUE, 647 BCSH_OUT_MODE_COLOR_BAR, 648 BCSH_OUT_MODE_NORMAL_VIDEO, 649 }; 650 651 #define _VOP_REG(off, _mask, _shift, _write_mask) \ 652 { \ 653 .offset = off, \ 654 .mask = _mask, \ 655 .shift = _shift, \ 656 .write_mask = _write_mask, \ 657 } 658 659 #define VOP_REG(off, _mask, _shift) \ 660 _VOP_REG(off, _mask, _shift, false) 661 enum dither_down_mode { 662 RGB888_TO_RGB565 = 0x0, 663 RGB888_TO_RGB666 = 0x1 664 }; 665 666 enum vop2_video_ports_id { 667 VOP2_VP0, 668 VOP2_VP1, 669 VOP2_VP2, 670 VOP2_VP3, 671 VOP2_VP_MAX, 672 }; 673 674 enum vop2_layer_type { 675 CLUSTER_LAYER = 0, 676 ESMART_LAYER = 1, 677 SMART_LAYER = 2, 678 }; 679 680 /* This define must same with kernel win phy id */ 681 enum vop2_layer_phy_id { 682 ROCKCHIP_VOP2_CLUSTER0 = 0, 683 ROCKCHIP_VOP2_CLUSTER1, 684 ROCKCHIP_VOP2_ESMART0, 685 ROCKCHIP_VOP2_ESMART1, 686 ROCKCHIP_VOP2_SMART0, 687 ROCKCHIP_VOP2_SMART1, 688 ROCKCHIP_VOP2_CLUSTER2, 689 ROCKCHIP_VOP2_CLUSTER3, 690 ROCKCHIP_VOP2_ESMART2, 691 ROCKCHIP_VOP2_ESMART3, 692 ROCKCHIP_VOP2_LAYER_MAX, 693 }; 694 695 enum vop2_scale_up_mode { 696 VOP2_SCALE_UP_NRST_NBOR, 697 VOP2_SCALE_UP_BIL, 698 VOP2_SCALE_UP_BIC, 699 }; 700 701 enum vop2_scale_down_mode { 702 VOP2_SCALE_DOWN_NRST_NBOR, 703 VOP2_SCALE_DOWN_BIL, 704 VOP2_SCALE_DOWN_AVG, 705 }; 706 707 enum scale_mode { 708 SCALE_NONE = 0x0, 709 SCALE_UP = 0x1, 710 SCALE_DOWN = 0x2 711 }; 712 713 struct vop2_layer { 714 u8 id; 715 /** 716 * @win_phys_id: window id of the layer selected. 717 * Every layer must make sure to select different 718 * windows of others. 719 */ 720 u8 win_phys_id; 721 }; 722 723 struct vop2_power_domain_data { 724 bool is_parent_needed; 725 u8 pd_en_shift; 726 u8 pd_status_shift; 727 u8 pmu_status_shift; 728 u8 bisr_en_status_shift; 729 u8 parent_phy_id; 730 }; 731 732 struct vop2_win_data { 733 char *name; 734 u8 phys_id; 735 enum vop2_layer_type type; 736 u8 win_sel_port_offset; 737 u8 layer_sel_win_id; 738 u32 reg_offset; 739 struct vop2_power_domain_data *pd_data; 740 }; 741 742 struct vop2_vp_data { 743 u32 feature; 744 u8 pre_scan_max_dly; 745 struct vop_rect max_output; 746 u32 max_dclk; 747 }; 748 749 struct vop2_plane_table { 750 enum vop2_layer_phy_id plane_id; 751 enum vop2_layer_type plane_type; 752 }; 753 754 struct vop2_vp_plane_mask { 755 u8 primary_plane_id; /* use this win to show logo */ 756 u8 attached_layers_nr; /* number layers attach to this vp */ 757 u8 attached_layers[VOP2_LAYER_MAX]; /* the layers attached to this vp */ 758 u32 plane_mask; 759 int cursor_plane_id; 760 }; 761 762 struct vop2_data { 763 u32 version; 764 struct vop2_vp_data *vp_data; 765 struct vop2_win_data *win_data; 766 struct vop2_vp_plane_mask *plane_mask; 767 struct vop2_plane_table *plane_table; 768 u8 nr_vps; 769 u8 nr_layers; 770 u8 nr_mixers; 771 u8 nr_gammas; 772 u8 nr_dscs; 773 u32 reg_len; 774 }; 775 776 struct vop2 { 777 u32 *regsbak; 778 void *regs; 779 void *grf; 780 void *vop_grf; 781 void *vo1_grf; 782 void *sys_pmu; 783 u32 reg_len; 784 u32 version; 785 bool global_init; 786 const struct vop2_data *data; 787 struct vop2_vp_plane_mask vp_plane_mask[VOP2_VP_MAX]; 788 }; 789 790 static struct vop2 *rockchip_vop2; 791 /* 792 * bli_sd_factor = (src - 1) / (dst - 1) << 12; 793 * avg_sd_factor: 794 * bli_su_factor: 795 * bic_su_factor: 796 * = (src - 1) / (dst - 1) << 16; 797 * 798 * gt2 enable: dst get one line from two line of the src 799 * gt4 enable: dst get one line from four line of the src. 800 * 801 */ 802 #define VOP2_BILI_SCL_DN(src, dst) (((src - 1) << 12) / (dst - 1)) 803 #define VOP2_COMMON_SCL(src, dst) (((src - 1) << 16) / (dst - 1)) 804 805 #define VOP2_BILI_SCL_FAC_CHECK(src, dst, fac) \ 806 (fac * (dst - 1) >> 12 < (src - 1)) 807 #define VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac) \ 808 (fac * (dst - 1) >> 16 < (src - 1)) 809 810 static uint16_t vop2_scale_factor(enum scale_mode mode, 811 int32_t filter_mode, 812 uint32_t src, uint32_t dst) 813 { 814 uint32_t fac = 0; 815 int i = 0; 816 817 if (mode == SCALE_NONE) 818 return 0; 819 820 /* 821 * A workaround to avoid zero div. 822 */ 823 if ((dst == 1) || (src == 1)) { 824 dst = dst + 1; 825 src = src + 1; 826 } 827 828 if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) { 829 fac = VOP2_BILI_SCL_DN(src, dst); 830 for (i = 0; i < 100; i++) { 831 if (VOP2_BILI_SCL_FAC_CHECK(src, dst, fac)) 832 break; 833 fac -= 1; 834 printf("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 835 } 836 } else { 837 fac = VOP2_COMMON_SCL(src, dst); 838 for (i = 0; i < 100; i++) { 839 if (VOP2_COMMON_SCL_FAC_CHECK(src, dst, fac)) 840 break; 841 fac -= 1; 842 printf("up fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac); 843 } 844 } 845 846 return fac; 847 } 848 849 static inline enum scale_mode scl_get_scl_mode(int src, int dst) 850 { 851 if (src < dst) 852 return SCALE_UP; 853 else if (src > dst) 854 return SCALE_DOWN; 855 856 return SCALE_NONE; 857 } 858 859 static u8 rk3588_vop2_vp_primary_plane_order[VOP2_VP_MAX] = { 860 ROCKCHIP_VOP2_ESMART0, 861 ROCKCHIP_VOP2_ESMART1, 862 ROCKCHIP_VOP2_ESMART2, 863 ROCKCHIP_VOP2_ESMART3, 864 }; 865 866 static u8 rk3568_vop2_vp_primary_plane_order[VOP2_VP_MAX] = { 867 ROCKCHIP_VOP2_SMART0, 868 ROCKCHIP_VOP2_SMART1, 869 ROCKCHIP_VOP2_ESMART1, 870 }; 871 872 static inline int interpolate(int x1, int y1, int x2, int y2, int x) 873 { 874 return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 875 } 876 877 static int vop2_get_primary_plane(struct vop2 *vop2, u32 plane_mask) 878 { 879 int i = 0; 880 u8 *vop2_vp_primary_plane_order; 881 u8 default_primary_plane; 882 883 if (vop2->version == VOP_VERSION_RK3588) { 884 vop2_vp_primary_plane_order = rk3588_vop2_vp_primary_plane_order; 885 default_primary_plane = ROCKCHIP_VOP2_ESMART0; 886 } else { 887 vop2_vp_primary_plane_order = rk3568_vop2_vp_primary_plane_order; 888 default_primary_plane = ROCKCHIP_VOP2_SMART0; 889 } 890 891 for (i = 0; i < vop2->data->nr_vps; i++) { 892 if (plane_mask & BIT(vop2_vp_primary_plane_order[i])) 893 return vop2_vp_primary_plane_order[i]; 894 } 895 896 return default_primary_plane; 897 } 898 899 static inline u16 scl_cal_scale(int src, int dst, int shift) 900 { 901 return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 902 } 903 904 static inline u16 scl_cal_scale2(int src, int dst) 905 { 906 return ((src - 1) << 12) / (dst - 1); 907 } 908 909 static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 910 { 911 writel(v, vop2->regs + offset); 912 vop2->regsbak[offset >> 2] = v; 913 } 914 915 static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 916 { 917 return readl(vop2->regs + offset); 918 } 919 920 static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 921 u32 mask, u32 shift, u32 v, 922 bool write_mask) 923 { 924 if (!mask) 925 return; 926 927 if (write_mask) { 928 v = ((v & mask) << shift) | (mask << (shift + 16)); 929 } else { 930 u32 cached_val = vop2->regsbak[offset >> 2]; 931 932 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 933 vop2->regsbak[offset >> 2] = v; 934 } 935 936 writel(v, vop2->regs + offset); 937 } 938 939 static inline void vop2_grf_writel(struct vop2 *vop, void *grf_base, u32 offset, 940 u32 mask, u32 shift, u32 v) 941 { 942 u32 val = 0; 943 944 val = (v << shift) | (mask << (shift + 16)); 945 writel(val, grf_base + offset); 946 } 947 948 static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, 949 u32 mask, u32 shift) 950 { 951 return (readl(grf_base + offset) >> shift) & mask; 952 } 953 954 static inline int us_to_vertical_line(struct drm_display_mode *mode, int us) 955 { 956 return us * mode->clock / mode->htotal / 1000; 957 } 958 959 static char* get_output_if_name(u32 output_if, char *name) 960 { 961 if (output_if & VOP_OUTPUT_IF_RGB) 962 strcat(name, " RGB"); 963 if (output_if & VOP_OUTPUT_IF_BT1120) 964 strcat(name, " BT1120"); 965 if (output_if & VOP_OUTPUT_IF_BT656) 966 strcat(name, " BT656"); 967 if (output_if & VOP_OUTPUT_IF_LVDS0) 968 strcat(name, " LVDS0"); 969 if (output_if & VOP_OUTPUT_IF_LVDS1) 970 strcat(name, " LVDS1"); 971 if (output_if & VOP_OUTPUT_IF_MIPI0) 972 strcat(name, " MIPI0"); 973 if (output_if & VOP_OUTPUT_IF_MIPI1) 974 strcat(name, " MIPI1"); 975 if (output_if & VOP_OUTPUT_IF_eDP0) 976 strcat(name, " eDP0"); 977 if (output_if & VOP_OUTPUT_IF_eDP1) 978 strcat(name, " eDP1"); 979 if (output_if & VOP_OUTPUT_IF_DP0) 980 strcat(name, " DP0"); 981 if (output_if & VOP_OUTPUT_IF_DP1) 982 strcat(name, " DP1"); 983 if (output_if & VOP_OUTPUT_IF_HDMI0) 984 strcat(name, " HDMI0"); 985 if (output_if & VOP_OUTPUT_IF_HDMI1) 986 strcat(name, " HDMI1"); 987 988 return name; 989 } 990 991 static char *get_plane_name(int plane_id, char *name) 992 { 993 switch (plane_id) { 994 case ROCKCHIP_VOP2_CLUSTER0: 995 strcat(name, "Cluster0"); 996 break; 997 case ROCKCHIP_VOP2_CLUSTER1: 998 strcat(name, "Cluster1"); 999 break; 1000 case ROCKCHIP_VOP2_ESMART0: 1001 strcat(name, "Esmart0"); 1002 break; 1003 case ROCKCHIP_VOP2_ESMART1: 1004 strcat(name, "Esmart1"); 1005 break; 1006 case ROCKCHIP_VOP2_SMART0: 1007 strcat(name, "Smart0"); 1008 break; 1009 case ROCKCHIP_VOP2_SMART1: 1010 strcat(name, "Smart1"); 1011 break; 1012 case ROCKCHIP_VOP2_CLUSTER2: 1013 strcat(name, "Cluster2"); 1014 break; 1015 case ROCKCHIP_VOP2_CLUSTER3: 1016 strcat(name, "Cluster3"); 1017 break; 1018 case ROCKCHIP_VOP2_ESMART2: 1019 strcat(name, "Esmart2"); 1020 break; 1021 case ROCKCHIP_VOP2_ESMART3: 1022 strcat(name, "Esmart3"); 1023 break; 1024 } 1025 1026 return name; 1027 } 1028 1029 static bool is_yuv_output(u32 bus_format) 1030 { 1031 switch (bus_format) { 1032 case MEDIA_BUS_FMT_YUV8_1X24: 1033 case MEDIA_BUS_FMT_YUV10_1X30: 1034 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1035 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1036 case MEDIA_BUS_FMT_YUYV8_2X8: 1037 case MEDIA_BUS_FMT_YVYU8_2X8: 1038 case MEDIA_BUS_FMT_UYVY8_2X8: 1039 case MEDIA_BUS_FMT_VYUY8_2X8: 1040 case MEDIA_BUS_FMT_YUYV8_1X16: 1041 case MEDIA_BUS_FMT_YVYU8_1X16: 1042 case MEDIA_BUS_FMT_UYVY8_1X16: 1043 case MEDIA_BUS_FMT_VYUY8_1X16: 1044 return true; 1045 default: 1046 return false; 1047 } 1048 } 1049 1050 static int vop2_convert_csc_mode(int csc_mode) 1051 { 1052 switch (csc_mode) { 1053 case V4L2_COLORSPACE_SMPTE170M: 1054 case V4L2_COLORSPACE_470_SYSTEM_M: 1055 case V4L2_COLORSPACE_470_SYSTEM_BG: 1056 return CSC_BT601L; 1057 case V4L2_COLORSPACE_REC709: 1058 case V4L2_COLORSPACE_SMPTE240M: 1059 case V4L2_COLORSPACE_DEFAULT: 1060 return CSC_BT709L; 1061 case V4L2_COLORSPACE_JPEG: 1062 return CSC_BT601F; 1063 case V4L2_COLORSPACE_BT2020: 1064 return CSC_BT2020; 1065 default: 1066 return CSC_BT709L; 1067 } 1068 } 1069 1070 static bool is_uv_swap(u32 bus_format, u32 output_mode) 1071 { 1072 /* 1073 * FIXME: 1074 * 1075 * There is no media type for YUV444 output, 1076 * so when out_mode is AAAA or P888, assume output is YUV444 on 1077 * yuv format. 1078 * 1079 * From H/W testing, YUV444 mode need a rb swap. 1080 */ 1081 if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 1082 bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 1083 (output_mode == ROCKCHIP_OUT_MODE_AAAA || 1084 output_mode == ROCKCHIP_OUT_MODE_P888)) 1085 return true; 1086 else 1087 return false; 1088 } 1089 1090 static inline bool is_hot_plug_devices(int output_type) 1091 { 1092 switch (output_type) { 1093 case DRM_MODE_CONNECTOR_HDMIA: 1094 case DRM_MODE_CONNECTOR_HDMIB: 1095 case DRM_MODE_CONNECTOR_TV: 1096 case DRM_MODE_CONNECTOR_DisplayPort: 1097 case DRM_MODE_CONNECTOR_VGA: 1098 case DRM_MODE_CONNECTOR_Unknown: 1099 return true; 1100 default: 1101 return false; 1102 } 1103 } 1104 1105 static struct vop2_win_data *vop2_find_win_by_phys_id(struct vop2 *vop2, int phys_id) 1106 { 1107 int i = 0; 1108 1109 for (i = 0; i < vop2->data->nr_layers; i++) { 1110 if (vop2->data->win_data[i].phys_id == phys_id) 1111 return &vop2->data->win_data[i]; 1112 } 1113 1114 return NULL; 1115 } 1116 1117 static int rockchip_vop2_gamma_lut_init(struct vop2 *vop2, 1118 struct display_state *state) 1119 { 1120 struct connector_state *conn_state = &state->conn_state; 1121 struct crtc_state *cstate = &state->crtc_state; 1122 struct resource gamma_res; 1123 fdt_size_t lut_size; 1124 int i, lut_len, ret = 0; 1125 u32 *lut_regs; 1126 u32 *lut_val; 1127 u32 r, g, b; 1128 u32 vp_offset = cstate->crtc_id * 0x100; 1129 struct base2_disp_info *disp_info = conn_state->disp_info; 1130 static int gamma_lut_en_num = 1; 1131 1132 if (gamma_lut_en_num > vop2->data->nr_gammas) { 1133 printf("warn: only %d vp support gamma\n", vop2->data->nr_gammas); 1134 return 0; 1135 } 1136 1137 if (!disp_info) 1138 return 0; 1139 1140 if (!disp_info->gamma_lut_data.size) 1141 return 0; 1142 1143 ret = ofnode_read_resource_byname(cstate->node, "gamma_lut", &gamma_res); 1144 if (ret) 1145 printf("failed to get gamma lut res\n"); 1146 lut_regs = (u32 *)gamma_res.start; 1147 lut_size = gamma_res.end - gamma_res.start + 1; 1148 if (lut_regs == (u32 *)FDT_ADDR_T_NONE) { 1149 printf("failed to get gamma lut register\n"); 1150 return 0; 1151 } 1152 lut_len = lut_size / 4; 1153 if (lut_len != 256 && lut_len != 1024) { 1154 printf("Warning: unsupport gamma lut table[%d]\n", lut_len); 1155 return 0; 1156 } 1157 lut_val = (u32 *)calloc(1, lut_size); 1158 for (i = 0; i < lut_len; i++) { 1159 r = disp_info->gamma_lut_data.lred[i] * (lut_len - 1) / 0xffff; 1160 g = disp_info->gamma_lut_data.lgreen[i] * (lut_len - 1) / 0xffff; 1161 b = disp_info->gamma_lut_data.lblue[i] * (lut_len - 1) / 0xffff; 1162 1163 lut_val[i] = b * lut_len * lut_len + g * lut_len + r; 1164 } 1165 1166 for (i = 0; i < lut_len; i++) 1167 writel(lut_val[i], lut_regs + i); 1168 1169 vop2_mask_write(vop2, RK3568_SYS_LUT_PORT_SEL, 1170 GAMMA_PORT_SEL_MASK, GAMMA_PORT_SEL_SHIFT, 1171 cstate->crtc_id , false); 1172 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 1173 EN_MASK, DSP_LUT_EN_SHIFT, 1, false); 1174 gamma_lut_en_num++; 1175 1176 return 0; 1177 } 1178 1179 static int rockchip_vop2_cubic_lut_init(struct vop2 *vop2, 1180 struct display_state *state) 1181 { 1182 struct connector_state *conn_state = &state->conn_state; 1183 struct crtc_state *cstate = &state->crtc_state; 1184 int i, cubic_lut_len; 1185 u32 vp_offset = cstate->crtc_id * 0x100; 1186 struct base2_disp_info *disp_info = conn_state->disp_info; 1187 struct base2_cubic_lut_data *lut = &conn_state->disp_info->cubic_lut_data; 1188 u32 *cubic_lut_addr; 1189 1190 if (!disp_info || CONFIG_ROCKCHIP_CUBIC_LUT_SIZE == 0) 1191 return 0; 1192 1193 if (!disp_info->cubic_lut_data.size) 1194 return 0; 1195 1196 cubic_lut_addr = (u32 *)get_cubic_lut_buffer(cstate->crtc_id); 1197 cubic_lut_len = disp_info->cubic_lut_data.size; 1198 1199 for (i = 0; i < cubic_lut_len / 2; i++) { 1200 *cubic_lut_addr++ = ((lut->lred[2 * i]) & 0xfff) + 1201 ((lut->lgreen[2 * i] & 0xfff) << 12) + 1202 ((lut->lblue[2 * i] & 0xff) << 24); 1203 *cubic_lut_addr++ = ((lut->lblue[2 * i] & 0xf00) >> 8) + 1204 ((lut->lred[2 * i + 1] & 0xfff) << 4) + 1205 ((lut->lgreen[2 * i + 1] & 0xfff) << 16) + 1206 ((lut->lblue[2 * i + 1] & 0xf) << 28); 1207 *cubic_lut_addr++ = (lut->lblue[2 * i + 1] & 0xff0) >> 4; 1208 *cubic_lut_addr++ = 0; 1209 } 1210 1211 if (cubic_lut_len % 2) { 1212 *cubic_lut_addr++ = (lut->lred[2 * i] & 0xfff) + 1213 ((lut->lgreen[2 * i] & 0xfff) << 12) + 1214 ((lut->lblue[2 * i] & 0xff) << 24); 1215 *cubic_lut_addr++ = (lut->lblue[2 * i] & 0xf00) >> 8; 1216 *cubic_lut_addr++ = 0; 1217 *cubic_lut_addr = 0; 1218 } 1219 1220 vop2_writel(vop2, RK3568_VP0_3D_LUT_MST + vp_offset, 1221 get_cubic_lut_buffer(cstate->crtc_id)); 1222 vop2_mask_write(vop2, RK3568_SYS_AXI_LUT_CTRL, 1223 EN_MASK, LUT_DMA_EN_SHIFT, 1, false); 1224 vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 1225 EN_MASK, VP0_3D_LUT_EN_SHIFT, 1, false); 1226 vop2_mask_write(vop2, RK3568_VP0_3D_LUT_CTRL + vp_offset, 1227 EN_MASK, VP0_3D_LUT_UPDATE_SHIFT, 1, false); 1228 1229 return 0; 1230 } 1231 1232 static void vop2_tv_config_update(struct display_state *state, struct vop2 *vop2) 1233 { 1234 struct connector_state *conn_state = &state->conn_state; 1235 struct base_bcsh_info *bcsh_info; 1236 struct crtc_state *cstate = &state->crtc_state; 1237 int brightness, contrast, saturation, hue, sin_hue, cos_hue; 1238 bool bcsh_en = false, post_r2y_en = false, post_y2r_en = false; 1239 u32 vp_offset = (cstate->crtc_id * 0x100); 1240 int post_csc_mode; 1241 1242 if (!conn_state->disp_info) 1243 return; 1244 bcsh_info = &conn_state->disp_info->bcsh_info; 1245 if (!bcsh_info) 1246 return; 1247 1248 if (bcsh_info->brightness != 50 || 1249 bcsh_info->contrast != 50 || 1250 bcsh_info->saturation != 50 || bcsh_info->hue != 50) 1251 bcsh_en = true; 1252 1253 if (bcsh_en) { 1254 if (!cstate->yuv_overlay) 1255 post_r2y_en = 1; 1256 if (!is_yuv_output(conn_state->bus_format)) 1257 post_y2r_en = 1; 1258 } else { 1259 if (!cstate->yuv_overlay && is_yuv_output(conn_state->bus_format)) 1260 post_r2y_en = 1; 1261 if (cstate->yuv_overlay && !is_yuv_output(conn_state->bus_format)) 1262 post_y2r_en = 1; 1263 } 1264 1265 post_csc_mode = vop2_convert_csc_mode(conn_state->color_space); 1266 1267 1268 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_MASK, 1269 BCSH_CTRL_R2Y_SHIFT, post_r2y_en, false); 1270 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_MASK, 1271 BCSH_CTRL_Y2R_SHIFT, post_y2r_en, false); 1272 1273 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_R2Y_CSC_MODE_MASK, 1274 BCSH_CTRL_R2Y_CSC_MODE_SHIFT, post_csc_mode, false); 1275 vop2_mask_write(vop2, RK3568_VP0_BCSH_CTRL + vp_offset, BCSH_CTRL_Y2R_CSC_MODE_MASK, 1276 BCSH_CTRL_Y2R_CSC_MODE_SHIFT, post_csc_mode, false); 1277 if (!bcsh_en) { 1278 vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1279 BCSH_EN_MASK, BCSH_EN_SHIFT, 0, false); 1280 return; 1281 } 1282 1283 if (cstate->feature & VOP_FEATURE_OUTPUT_10BIT) 1284 brightness = interpolate(0, -128, 100, 127, 1285 bcsh_info->brightness); 1286 else 1287 brightness = interpolate(0, -32, 100, 31, 1288 bcsh_info->brightness); 1289 contrast = interpolate(0, 0, 100, 511, bcsh_info->contrast); 1290 saturation = interpolate(0, 0, 100, 511, bcsh_info->saturation); 1291 hue = interpolate(0, -30, 100, 30, bcsh_info->hue); 1292 1293 1294 /* 1295 * a:[-30~0): 1296 * sin_hue = 0x100 - sin(a)*256; 1297 * cos_hue = cos(a)*256; 1298 * a:[0~30] 1299 * sin_hue = sin(a)*256; 1300 * cos_hue = cos(a)*256; 1301 */ 1302 sin_hue = fixp_sin32(hue) >> 23; 1303 cos_hue = fixp_cos32(hue) >> 23; 1304 1305 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1306 BCSH_BRIGHTNESS_MASK, BCSH_BRIGHTNESS_SHIFT, 1307 brightness, false); 1308 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1309 BCSH_CONTRAST_MASK, BCSH_CONTRAST_SHIFT, contrast, false); 1310 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1311 BCSH_SATURATION_MASK, BCSH_SATURATION_SHIFT, 1312 saturation * contrast / 0x100, false); 1313 vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1314 BCSH_SIN_HUE_MASK, BCSH_SIN_HUE_SHIFT, sin_hue, false); 1315 vop2_mask_write(vop2, RK3568_VP0_BCSH_H + vp_offset, 1316 BCSH_COS_HUE_MASK, BCSH_COS_HUE_SHIFT, cos_hue, false); 1317 vop2_mask_write(vop2, RK3568_VP0_BCSH_BCS + vp_offset, 1318 BCSH_OUT_MODE_MASK, BCSH_OUT_MODE_SHIFT, 1319 BCSH_OUT_MODE_NORMAL_VIDEO, false); 1320 vop2_mask_write(vop2, RK3568_VP0_BCSH_COLOR + vp_offset, 1321 BCSH_EN_MASK, BCSH_EN_SHIFT, 1, false); 1322 } 1323 1324 static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 1325 { 1326 struct connector_state *conn_state = &state->conn_state; 1327 struct drm_display_mode *mode = &conn_state->mode; 1328 struct crtc_state *cstate = &state->crtc_state; 1329 u32 vp_offset = (cstate->crtc_id * 0x100); 1330 u16 vtotal = mode->crtc_vtotal; 1331 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 1332 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 1333 u16 hdisplay = mode->crtc_hdisplay; 1334 u16 vdisplay = mode->crtc_vdisplay; 1335 u16 hsize = 1336 hdisplay * (conn_state->overscan.left_margin + 1337 conn_state->overscan.right_margin) / 200; 1338 u16 vsize = 1339 vdisplay * (conn_state->overscan.top_margin + 1340 conn_state->overscan.bottom_margin) / 200; 1341 u16 hact_end, vact_end; 1342 u32 val; 1343 u32 bg_ovl_dly, bg_dly, pre_scan_dly; 1344 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 1345 1346 hsize = round_down(hsize, 2); 1347 vsize = round_down(vsize, 2); 1348 1349 hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 1350 hact_end = hact_st + hsize; 1351 val = hact_st << 16; 1352 val |= hact_end; 1353 1354 vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 1355 vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 1356 vact_end = vact_st + vsize; 1357 val = vact_st << 16; 1358 val |= vact_end; 1359 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 1360 val = scl_cal_scale2(vdisplay, vsize) << 16; 1361 val |= scl_cal_scale2(hdisplay, hsize); 1362 vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 1363 #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 1364 #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 1365 vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 1366 POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 1367 POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 1368 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1369 u16 vact_st_f1 = vtotal + vact_st + 1; 1370 u16 vact_end_f1 = vact_st_f1 + vsize; 1371 1372 val = vact_st_f1 << 16 | vact_end_f1; 1373 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 1374 } 1375 1376 bg_ovl_dly = cstate->crtc->vps[cstate->crtc_id].bg_ovl_dly; 1377 bg_dly = vop2->data->vp_data[cstate->crtc_id].pre_scan_max_dly; 1378 bg_dly -= bg_ovl_dly; 1379 pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 1380 if (vop2->version == VOP_VERSION_RK3588 && hsync_len < 8) 1381 hsync_len = 8; 1382 pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 1383 vop2_mask_write(vop2, RK3568_VP0_BG_MIX_CTRL + cstate->crtc_id * 4, 1384 BG_MIX_CTRL_MASK, BG_MIX_CTRL_SHIFT, bg_dly, false); 1385 vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + vp_offset, pre_scan_dly); 1386 } 1387 1388 static int vop2_wait_power_domain_on(struct vop2 *vop2, struct vop2_power_domain_data *pd_data) 1389 { 1390 int val = 0; 1391 int shift = 0; 1392 bool is_bisr_en = false; 1393 1394 is_bisr_en = vop2_grf_readl(vop2, vop2->sys_pmu, RK3588_PMU_BISR_CON3, EN_MASK, 1395 pd_data->bisr_en_status_shift); 1396 if (is_bisr_en) { 1397 shift = pd_data->pmu_status_shift; 1398 return readl_poll_timeout(vop2->sys_pmu + RK3588_PMU_BISR_STATUS5, val, 1399 !((val >> shift) & 0x1), 50 * 1000); 1400 } else { 1401 shift = pd_data->pd_status_shift; 1402 return readl_poll_timeout(vop2->regs + RK3568_SYS_STATUS0, val, 1403 !((val >> shift) & 0x1), 50 * 1000); 1404 } 1405 } 1406 1407 static int vop2_power_domain_on(struct vop2 *vop2, int plane_id) 1408 { 1409 struct vop2_win_data *win_data; 1410 struct vop2_power_domain_data *pd_data; 1411 int ret = 0; 1412 1413 win_data = vop2_find_win_by_phys_id(vop2, plane_id); 1414 if (!win_data) { 1415 printf("can't find win_data by phys_id\n"); 1416 return -EINVAL; 1417 } 1418 pd_data = win_data->pd_data; 1419 if (pd_data->is_parent_needed) { 1420 ret = vop2_power_domain_on(vop2, pd_data->parent_phy_id); 1421 if (ret) { 1422 printf("can't open parent power domain\n"); 1423 return -EINVAL; 1424 } 1425 } 1426 1427 vop2_mask_write(vop2, RK3568_SYS_PD_CTRL, EN_MASK, pd_data->pd_en_shift, 0, false); 1428 ret = vop2_wait_power_domain_on(vop2, pd_data); 1429 if (ret) { 1430 printf("wait vop2 power domain timeout\n"); 1431 return ret; 1432 } 1433 1434 return 0; 1435 } 1436 1437 static void rk3588_vop2_regsbak(struct vop2 *vop2) 1438 { 1439 u32 *base = vop2->regs; 1440 int i = 0; 1441 1442 /* 1443 * No need to backup HDR/DSC/GAMMA_LUT/BPP_LUT/MMU 1444 */ 1445 for (i = 0; i < (vop2->reg_len >> 2); i++) 1446 vop2->regsbak[i] = base[i]; 1447 } 1448 1449 static void vop2_global_initial(struct vop2 *vop2, struct display_state *state) 1450 { 1451 struct crtc_state *cstate = &state->crtc_state; 1452 int i, j, port_mux = 0, total_used_layer = 0; 1453 u8 shift = 0; 1454 int layer_phy_id = 0; 1455 u32 layer_nr = 0; 1456 struct vop2_win_data *win_data; 1457 struct vop2_vp_plane_mask *plane_mask; 1458 1459 if (vop2->global_init) 1460 return; 1461 1462 /* OTP must enable at the first time, otherwise mirror layer register is error */ 1463 if (soc_is_rk3566()) 1464 vop2_mask_write(vop2, RK3568_SYS_OTP_WIN_EN, EN_MASK, 1465 OTP_WIN_EN_SHIFT, 1, false); 1466 1467 if (cstate->crtc->assign_plane) {/* dts assign plane */ 1468 u32 plane_mask; 1469 int primary_plane_id; 1470 1471 for (i = 0; i < vop2->data->nr_vps; i++) { 1472 plane_mask = cstate->crtc->vps[i].plane_mask; 1473 vop2->vp_plane_mask[i].plane_mask = plane_mask; 1474 layer_nr = hweight32(plane_mask); /* use bitmap to store plane mask */ 1475 vop2->vp_plane_mask[i].attached_layers_nr = layer_nr; 1476 primary_plane_id = vop2_get_primary_plane(vop2, plane_mask); 1477 vop2->vp_plane_mask[i].primary_plane_id = primary_plane_id; 1478 vop2->vp_plane_mask[i].plane_mask = plane_mask; 1479 1480 /* plane mask[bitmap] convert into layer phy id[enum vop2_layer_phy_id]*/ 1481 for (j = 0; j < layer_nr; j++) { 1482 vop2->vp_plane_mask[i].attached_layers[j] = ffs(plane_mask) - 1; 1483 plane_mask &= ~BIT(vop2->vp_plane_mask[i].attached_layers[j]); 1484 } 1485 } 1486 } else {/* need soft assign plane mask */ 1487 /* find the first unplug devices and set it as main display */ 1488 int main_vp_index = -1; 1489 int active_vp_num = 0; 1490 1491 for (i = 0; i < vop2->data->nr_vps; i++) { 1492 if (cstate->crtc->vps[i].enable) 1493 active_vp_num++; 1494 } 1495 printf("VOP have %d active VP\n", active_vp_num); 1496 1497 if (soc_is_rk3566() && active_vp_num > 2) 1498 printf("ERROR: rk3566 only support 2 display output!!\n"); 1499 plane_mask = vop2->data->plane_mask; 1500 plane_mask += (active_vp_num - 1) * VOP2_VP_MAX; 1501 1502 for (i = 0; i < vop2->data->nr_vps; i++) { 1503 if (!is_hot_plug_devices(cstate->crtc->vps[i].output_type)) { 1504 vop2->vp_plane_mask[i] = plane_mask[0]; /* the first store main display plane mask*/ 1505 main_vp_index = i; 1506 break; 1507 } 1508 } 1509 1510 /* if no find unplug devices, use vp0 as main display */ 1511 if (main_vp_index < 0) { 1512 main_vp_index = 0; 1513 vop2->vp_plane_mask[0] = plane_mask[0]; 1514 } 1515 1516 j = 1; /* plane_mask[0] store main display, so we from plane_mask[1] */ 1517 1518 /* init other display except main display */ 1519 for (i = 0; i < vop2->data->nr_vps; i++) { 1520 if (i == main_vp_index || !cstate->crtc->vps[i].enable) /* main display or no connect devices */ 1521 continue; 1522 vop2->vp_plane_mask[i] = plane_mask[j++]; 1523 } 1524 1525 /* store plane mask for vop2_fixup_dts */ 1526 for (i = 0; i < vop2->data->nr_vps; i++) { 1527 layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1528 /* rk3566 only support 3+3 policy */ 1529 if (soc_is_rk3566() && active_vp_num == 1) { 1530 if (cstate->crtc->vps[i].enable) { 1531 for (j = 0; j < 3; j++) { 1532 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1533 vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 1534 } 1535 } 1536 } else { 1537 for (j = 0; j < layer_nr; j++) { 1538 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1539 vop2->vp_plane_mask[i].plane_mask |= BIT(layer_phy_id); 1540 } 1541 } 1542 } 1543 } 1544 1545 if (vop2->version == VOP_VERSION_RK3588) { 1546 for (i = 0; i < vop2->data->nr_vps; i++) { 1547 if (cstate->crtc->vps[i].enable) { 1548 if (vop2_power_domain_on(vop2, vop2->vp_plane_mask[i].primary_plane_id)) 1549 printf("open vp[%d] plane pd fail\n", i); 1550 } 1551 } 1552 } 1553 1554 if (vop2->version == VOP_VERSION_RK3588) 1555 rk3588_vop2_regsbak(vop2); 1556 else 1557 memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 1558 1559 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 1560 OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 1561 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 1562 IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 1563 1564 for (i = 0; i < vop2->data->nr_vps; i++) { 1565 printf("vp%d have layer nr:%d[", i, vop2->vp_plane_mask[i].attached_layers_nr); 1566 for (j = 0; j < vop2->vp_plane_mask[i].attached_layers_nr; j++) 1567 printf("%d ", vop2->vp_plane_mask[i].attached_layers[j]); 1568 printf("], primary plane: %d\n", vop2->vp_plane_mask[i].primary_plane_id); 1569 } 1570 1571 shift = 0; 1572 /* layer sel win id */ 1573 for (i = 0; i < vop2->data->nr_vps; i++) { 1574 layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1575 for (j = 0; j < layer_nr; j++) { 1576 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1577 win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 1578 vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_MASK, 1579 shift, win_data->layer_sel_win_id, false); 1580 shift += 4; 1581 } 1582 } 1583 1584 /* win sel port */ 1585 for (i = 0; i < vop2->data->nr_vps; i++) { 1586 layer_nr = vop2->vp_plane_mask[i].attached_layers_nr; 1587 for (j = 0; j < layer_nr; j++) { 1588 if (!vop2->vp_plane_mask[i].attached_layers[j]) 1589 continue; 1590 layer_phy_id = vop2->vp_plane_mask[i].attached_layers[j]; 1591 win_data = vop2_find_win_by_phys_id(vop2, layer_phy_id); 1592 shift = win_data->win_sel_port_offset * 2; 1593 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 1594 LAYER_SEL_PORT_SHIFT + shift, i, false); 1595 } 1596 } 1597 1598 /** 1599 * port mux config 1600 */ 1601 for (i = 0; i < vop2->data->nr_vps; i++) { 1602 shift = i * 4; 1603 if (vop2->vp_plane_mask[i].attached_layers_nr) { 1604 total_used_layer += vop2->vp_plane_mask[i].attached_layers_nr; 1605 port_mux = total_used_layer - 1; 1606 } else { 1607 port_mux = 8; 1608 } 1609 1610 if (i == vop2->data->nr_vps - 1) 1611 port_mux = vop2->data->nr_mixers; 1612 1613 cstate->crtc->vps[i].bg_ovl_dly = (vop2->data->nr_mixers - port_mux) << 1; 1614 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, 1615 PORT_MUX_SHIFT + shift, port_mux, false); 1616 } 1617 1618 if (vop2->version == VOP_VERSION_RK3568) 1619 vop2_writel(vop2, RK3568_AUTO_GATING_CTRL, 0); 1620 1621 vop2->global_init = true; 1622 } 1623 1624 static int vop2_initial(struct vop2 *vop2, struct display_state *state) 1625 { 1626 struct crtc_state *cstate = &state->crtc_state; 1627 int ret; 1628 1629 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 1630 ret = clk_set_defaults(cstate->dev); 1631 if (ret) 1632 debug("%s clk_set_defaults failed %d\n", __func__, ret); 1633 1634 rockchip_vop2_gamma_lut_init(vop2, state); 1635 rockchip_vop2_cubic_lut_init(vop2, state); 1636 1637 return 0; 1638 } 1639 1640 /* 1641 * VOP2 have multi video ports. 1642 * video port ------- crtc 1643 */ 1644 static int rockchip_vop2_preinit(struct display_state *state) 1645 { 1646 struct crtc_state *cstate = &state->crtc_state; 1647 const struct vop2_data *vop2_data = cstate->crtc->data; 1648 1649 if (!rockchip_vop2) { 1650 rockchip_vop2 = calloc(1, sizeof(struct vop2)); 1651 if (!rockchip_vop2) 1652 return -ENOMEM; 1653 rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 1654 rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 1655 rockchip_vop2->reg_len = RK3568_MAX_REG; 1656 rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 1657 if (rockchip_vop2->grf <= 0) 1658 printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); 1659 rockchip_vop2->version = vop2_data->version; 1660 rockchip_vop2->data = vop2_data; 1661 if (rockchip_vop2->version == VOP_VERSION_RK3588) { 1662 rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF); 1663 if (rockchip_vop2->vop_grf <= 0) 1664 printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf); 1665 rockchip_vop2->vo1_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VO_GRF); 1666 if (rockchip_vop2->vo1_grf <= 0) 1667 printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf); 1668 rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); 1669 if (rockchip_vop2->vo1_grf <= 0) 1670 printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu); 1671 } 1672 } 1673 1674 cstate->private = rockchip_vop2; 1675 cstate->max_output = vop2_data->vp_data[cstate->crtc_id].max_output; 1676 cstate->feature = vop2_data->vp_data[cstate->crtc_id].feature; 1677 1678 vop2_global_initial(rockchip_vop2, state); 1679 1680 return 0; 1681 } 1682 1683 /* 1684 * calc the dclk on rk3588 1685 * the available div of dclk is 1, 2, 4 1686 * 1687 */ 1688 static unsigned long vop2_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 1689 { 1690 if (child_clk * 4 <= max_dclk) 1691 return child_clk * 4; 1692 else if (child_clk * 2 <= max_dclk) 1693 return child_clk * 2; 1694 else if (child_clk <= max_dclk) 1695 return child_clk; 1696 else 1697 return 0; 1698 } 1699 1700 /* 1701 * 4 pixclk/cycle on rk3588 1702 * RGB/eDP/HDMI: if_pixclk >= dclk_core 1703 * DP: dp_pixclk = dclk_out <= dclk_core 1704 * DSI: mipi_pixclk <= dclk_out <= dclk_core 1705 */ 1706 static unsigned long vop2_calc_cru_cfg(struct display_state *state, 1707 int *dclk_core_div, int *dclk_out_div, 1708 int *if_pixclk_div, int *if_dclk_div) 1709 { 1710 struct crtc_state *cstate = &state->crtc_state; 1711 struct connector_state *conn_state = &state->conn_state; 1712 struct drm_display_mode *mode = &conn_state->mode; 1713 struct vop2 *vop2 = cstate->private; 1714 unsigned long v_pixclk = mode->clock; 1715 unsigned long dclk_core_rate = v_pixclk >> 2; 1716 unsigned long dclk_rate = v_pixclk; 1717 unsigned long dclk_out_rate; 1718 u64 if_dclk_rate; 1719 u64 if_pixclk_rate; 1720 int output_type = conn_state->type; 1721 int output_mode = conn_state->output_mode; 1722 int K = 1; 1723 1724 if (output_type == DRM_MODE_CONNECTOR_HDMIA) { 1725 /* 1726 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 1727 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 1728 */ 1729 if (output_mode == ROCKCHIP_OUT_MODE_YUV420) 1730 K = 2; 1731 if (conn_state->dsc_enable) { 1732 if_pixclk_rate = conn_state->dsc_cds_clk << 1; 1733 if_dclk_rate = conn_state->dsc_cds_clk; 1734 } else { 1735 if_pixclk_rate = (dclk_core_rate << 1) / K; 1736 if_dclk_rate = dclk_core_rate / K; 1737 } 1738 1739 dclk_rate = vop2_calc_dclk(if_pixclk_rate, vop2->data->vp_data->max_dclk); 1740 if (!dclk_rate) { 1741 printf("DP if_pixclk_rate out of range(max_dclk: %d KHZ, dclk_core: %lld KHZ)\n", 1742 vop2->data->vp_data->max_dclk, if_pixclk_rate); 1743 return -EINVAL; 1744 } 1745 *if_pixclk_div = dclk_rate / if_pixclk_rate; 1746 *if_dclk_div = dclk_rate / if_dclk_rate; 1747 1748 } else if (output_type == DRM_MODE_CONNECTOR_eDP) { 1749 /* edp_pixclk = edp_dclk > dclk_core */ 1750 if_pixclk_rate = v_pixclk / K; 1751 if_dclk_rate = v_pixclk / K; 1752 dclk_rate = if_pixclk_rate * K; 1753 *dclk_core_div = dclk_rate / dclk_core_rate; 1754 *if_pixclk_div = dclk_rate / if_pixclk_rate; 1755 *if_dclk_div = *if_pixclk_div; 1756 } else if (output_type == DRM_MODE_CONNECTOR_DisplayPort) { 1757 if (output_mode == ROCKCHIP_OUT_MODE_YUV420) 1758 dclk_out_rate = v_pixclk >> 3; 1759 else 1760 dclk_out_rate = v_pixclk >> 2; 1761 1762 dclk_rate = vop2_calc_dclk(dclk_core_rate, vop2->data->vp_data->max_dclk); 1763 if (!dclk_rate) { 1764 printf("DP dclk_core out of range(max_dclk: %d KHZ, dclk_core: %ld KHZ)\n", 1765 vop2->data->vp_data->max_dclk, dclk_core_rate); 1766 return -EINVAL; 1767 } 1768 *dclk_out_div = dclk_rate / dclk_out_rate; 1769 *dclk_core_div = dclk_rate / dclk_core_rate; 1770 1771 } else if (output_type == DRM_MODE_CONNECTOR_DSI) { 1772 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 1773 K = 2; 1774 if (conn_state->dsc_enable) 1775 if_pixclk_rate = conn_state->dsc_cds_clk >> 1; 1776 else 1777 if_pixclk_rate = dclk_core_rate / K; 1778 /* dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 */ 1779 dclk_out_rate = if_pixclk_rate; 1780 /* dclk_rate = N * dclk_core_rate N = (1,2,4 ), we get a little factor here */ 1781 dclk_rate = dclk_core_rate; 1782 *dclk_out_div = dclk_rate / dclk_out_rate; 1783 *dclk_core_div = dclk_rate / dclk_core_rate; 1784 *if_pixclk_div = 1; /*mipi pixclk == dclk_out*/ 1785 1786 } else if (output_type == DRM_MODE_CONNECTOR_DPI) { 1787 dclk_rate = v_pixclk; 1788 *dclk_core_div = dclk_rate / dclk_core_rate; 1789 } 1790 1791 *if_pixclk_div = ilog2(*if_pixclk_div); 1792 *if_dclk_div = ilog2(*if_dclk_div); 1793 *dclk_core_div = ilog2(*dclk_core_div); 1794 *dclk_out_div = ilog2(*dclk_out_div); 1795 1796 return dclk_rate; 1797 } 1798 1799 static int vop2_calc_dsc_clk(struct connector_state *conn_state) 1800 { 1801 struct drm_display_mode *mode = &conn_state->mode; 1802 u64 v_pixclk = mode->clock * 1000LL; /* video timing pixclk */ 1803 u8 k = 1; 1804 1805 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 1806 k = 2; 1807 1808 conn_state->dsc_pxl_clk = v_pixclk; 1809 do_div(conn_state->dsc_pxl_clk, (conn_state->dsc_slice_num * k)); 1810 1811 conn_state->dsc_txp_clk = v_pixclk; 1812 do_div(conn_state->dsc_txp_clk, (conn_state->dsc_pixel_num * k)); 1813 1814 /* dsc_cds = crtc_clock / (cds_dat_width / bits_per_pixel) 1815 * cds_dat_width = 96; 1816 * bits_per_pixel = [8-12]; 1817 * As only support 1/2/4 div, so we set dsc_cds = crtc_clock / 8; 1818 */ 1819 conn_state->dsc_cds_clk = mode->crtc_clock / 8 * 1000; 1820 1821 return 0; 1822 } 1823 1824 static unsigned long rk3588_vop2_if_cfg(struct display_state *state) 1825 { 1826 struct crtc_state *cstate = &state->crtc_state; 1827 struct connector_state *conn_state = &state->conn_state; 1828 struct drm_display_mode *mode = &conn_state->mode; 1829 struct rockchip_dsc_sink_cap *dsc_sink_cap = &conn_state->dsc_sink_cap; 1830 struct vop2 *vop2 = cstate->private; 1831 u32 vp_offset = (cstate->crtc_id * 0x100); 1832 u16 hdisplay = mode->crtc_hdisplay; 1833 int output_if = conn_state->output_if; 1834 int dclk_core_div = 0; 1835 int dclk_out_div = 0; 1836 int if_pixclk_div = 0; 1837 int if_dclk_div = 0; 1838 unsigned long dclk_rate; 1839 u32 val; 1840 1841 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 1842 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 1843 1844 if (conn_state->dsc_enable) { 1845 if (!vop2->data->nr_dscs) { 1846 printf("No DSC\n"); 1847 return 0; 1848 } 1849 conn_state->dsc_id = output_if & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_HDMI0) ? 0 : 1; 1850 conn_state->dsc_slice_num = hdisplay / dsc_sink_cap->slice_width; 1851 conn_state->dsc_pixel_num = conn_state->dsc_slice_num >= 4 ? 1852 4 : conn_state->dsc_slice_num >= 2 ? 2 : 1; 1853 vop2_calc_dsc_clk(conn_state); 1854 } 1855 1856 dclk_rate = vop2_calc_cru_cfg(state, &dclk_core_div, &dclk_out_div, &if_pixclk_div, &if_dclk_div); 1857 1858 if (output_if & VOP_OUTPUT_IF_RGB) { 1859 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 1860 4, false); 1861 } 1862 1863 if (output_if & VOP_OUTPUT_IF_BT1120) { 1864 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 1865 3, false); 1866 } 1867 1868 if (output_if & VOP_OUTPUT_IF_BT656) { 1869 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 1870 2, false); 1871 } 1872 1873 if (output_if & VOP_OUTPUT_IF_MIPI0) { 1874 if (cstate->crtc_id == 2) 1875 val = 0; 1876 else 1877 val = 1; 1878 1879 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 1880 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 1881 RK3588_MIPI_DSI0_MODE_SEL_SHIFT, 1, false); 1882 1883 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI0_EN_SHIFT, 1884 1, false); 1885 vop2_mask_write(vop2, RK3568_DSP_IF_EN, 1, RK3588_MIPI0_MUX_SHIFT, val, false); 1886 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI0_PIXCLK_DIV_SHIFT, 1887 if_pixclk_div, false); 1888 1889 if (conn_state->hold_mode) { 1890 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1891 EN_MASK, EDPI_TE_EN, 1, false); 1892 1893 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1894 EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 1895 } 1896 } 1897 1898 if (output_if & VOP_OUTPUT_IF_MIPI1) { 1899 if (cstate->crtc_id == 2) 1900 val = 0; 1901 else if (cstate->crtc_id == 3) 1902 val = 1; 1903 else 1904 val = 3; /*VP1*/ 1905 if (conn_state->output_flags & ROCKCHIP_OUTPUT_MIPI_DS_MODE) 1906 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 1907 RK3588_MIPI_DSI1_MODE_SEL_SHIFT, 1, false); 1908 1909 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_MIPI1_EN_SHIFT, 1910 1, false); 1911 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, MIPI1_MUX_SHIFT, 1912 val, false); 1913 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, MIPI1_PIXCLK_DIV_SHIFT, 1914 if_pixclk_div, false); 1915 1916 if (conn_state->hold_mode) { 1917 /* UNDO: RK3588 VP1->DSC1->DSI1 only can support soft TE mode */ 1918 if (vop2->version == VOP_VERSION_RK3588 && val == 3) 1919 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1920 EN_MASK, EDPI_TE_EN, 0, false); 1921 else 1922 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1923 EN_MASK, EDPI_TE_EN, 1, false); 1924 1925 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1926 EN_MASK, EDPI_WMS_HOLD_EN, 1, false); 1927 } 1928 } 1929 1930 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 1931 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 1932 RK3568_MIPI_DUAL_EN_SHIFT, 1, false); 1933 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 1934 MIPI_DUAL_EN_SHIFT, 1, false); 1935 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 1936 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 1937 EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 1938 false); 1939 } 1940 1941 if (output_if & VOP_OUTPUT_IF_eDP0) { 1942 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP0_EN_SHIFT, 1943 1, false); 1944 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 1945 cstate->crtc_id, false); 1946 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 1947 if_dclk_div, false); 1948 1949 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 1950 if_pixclk_div, false); 1951 1952 vop2_grf_writel(vop2, vop2->vop_grf, RK3588_GRF_VOP_CON2, EN_MASK, 1953 RK3588_GRF_EDP0_ENABLE_SHIFT, 1); 1954 } 1955 1956 if (output_if & VOP_OUTPUT_IF_eDP1) { 1957 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_EDP1_EN_SHIFT, 1958 1, false); 1959 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 1960 cstate->crtc_id, false); 1961 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 1962 if_dclk_div, false); 1963 1964 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 1965 if_pixclk_div, false); 1966 } 1967 1968 if (output_if & VOP_OUTPUT_IF_HDMI0) { 1969 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI0_EN_SHIFT, 1970 1, false); 1971 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP0_MUX_SHIFT, 1972 cstate->crtc_id, false); 1973 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_DCLK_DIV_SHIFT, 1974 if_dclk_div, false); 1975 1976 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP0_PIXCLK_DIV_SHIFT, 1977 if_pixclk_div, false); 1978 } 1979 1980 if (output_if & VOP_OUTPUT_IF_HDMI1) { 1981 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 1982 1, false); 1983 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_HDMI_EDP1_MUX_SHIFT, 1984 cstate->crtc_id, false); 1985 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_DCLK_DIV_SHIFT, 1986 if_dclk_div, false); 1987 1988 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, 3, HDMI_EDP1_PIXCLK_DIV_SHIFT, 1989 if_pixclk_div, false); 1990 } 1991 1992 if (output_if & VOP_OUTPUT_IF_DP0) { 1993 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_DP0_EN_SHIFT, 1994 1, false); 1995 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP0_MUX_SHIFT, 1996 cstate->crtc_id, false); 1997 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 1998 RK3588_DP0_PIN_POL_SHIFT, val, false); 1999 } 2000 2001 if (output_if & VOP_OUTPUT_IF_DP1) { 2002 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RK3588_HDMI1_EN_SHIFT, 2003 1, false); 2004 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, RK3588_DP1_MUX_SHIFT, 2005 cstate->crtc_id, false); 2006 vop2_mask_write(vop2, RK3568_DSP_IF_POL, RK3588_IF_PIN_POL_MASK, 2007 RK3588_DP1_PIN_POL_SHIFT, val, false); 2008 } 2009 2010 vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2011 DCLK_CORE_DIV_SHIFT, dclk_core_div, false); 2012 vop2_mask_write(vop2, RK3588_VP0_CLK_CTRL + vp_offset, 0x3, 2013 DCLK_OUT_DIV_SHIFT, dclk_out_div, false); 2014 2015 return dclk_rate; 2016 } 2017 2018 static unsigned long rk3568_vop2_if_cfg(struct display_state *state) 2019 { 2020 struct crtc_state *cstate = &state->crtc_state; 2021 struct connector_state *conn_state = &state->conn_state; 2022 struct drm_display_mode *mode = &conn_state->mode; 2023 struct vop2 *vop2 = cstate->private; 2024 u32 vp_offset = (cstate->crtc_id * 0x100); 2025 bool dclk_inv; 2026 u32 val; 2027 2028 dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 2029 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 2030 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 2031 2032 if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 2033 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 2034 1, false); 2035 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2036 RGB_MUX_SHIFT, cstate->crtc_id, false); 2037 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 2038 GRF_RGB_DCLK_INV_SHIFT, dclk_inv); 2039 } 2040 2041 if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 2042 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 2043 1, false); 2044 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 2045 BT1120_EN_SHIFT, 1, false); 2046 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2047 RGB_MUX_SHIFT, cstate->crtc_id, false); 2048 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 2049 GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 2050 } 2051 2052 if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 2053 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 2054 1, false); 2055 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2056 RGB_MUX_SHIFT, cstate->crtc_id, false); 2057 vop2_grf_writel(vop2, vop2->grf, RK3568_GRF_VO_CON1, EN_MASK, 2058 GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 2059 } 2060 2061 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 2062 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 2063 1, false); 2064 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2065 LVDS0_MUX_SHIFT, cstate->crtc_id, false); 2066 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2067 IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 2068 } 2069 2070 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 2071 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 2072 1, false); 2073 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2074 LVDS1_MUX_SHIFT, cstate->crtc_id, false); 2075 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2076 IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, dclk_inv, false); 2077 } 2078 2079 if (conn_state->output_flags & 2080 (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 2081 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 2082 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2083 LVDS_DUAL_EN_SHIFT, 1, false); 2084 if (conn_state->output_flags & 2085 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 2086 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2087 LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 2088 false); 2089 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2090 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 2091 LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 2092 } 2093 2094 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 2095 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 2096 1, false); 2097 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2098 MIPI0_MUX_SHIFT, cstate->crtc_id, false); 2099 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2100 IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 2101 } 2102 2103 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 2104 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 2105 1, false); 2106 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2107 MIPI1_MUX_SHIFT, cstate->crtc_id, false); 2108 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2109 IF_CRTL_MIPI_DCLK_POL_SHIT, dclk_inv, false); 2110 } 2111 2112 if (conn_state->output_flags & 2113 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 2114 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 2115 MIPI_DUAL_EN_SHIFT, 1, false); 2116 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 2117 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2118 EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 2119 false); 2120 } 2121 2122 if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 2123 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 2124 1, false); 2125 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2126 EDP0_MUX_SHIFT, cstate->crtc_id, false); 2127 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2128 IF_CRTL_EDP_DCLK_POL_SHIT, dclk_inv, false); 2129 } 2130 2131 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 2132 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 2133 1, false); 2134 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 2135 HDMI0_MUX_SHIFT, cstate->crtc_id, false); 2136 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 2137 IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 2138 vop2_mask_write(vop2, RK3568_DSP_IF_POL, 2139 IF_CRTL_HDMI_PIN_POL_MASK, 2140 IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 2141 } 2142 2143 return mode->clock; 2144 } 2145 2146 static void vop2_post_color_swap(struct display_state *state) 2147 { 2148 struct crtc_state *cstate = &state->crtc_state; 2149 struct connector_state *conn_state = &state->conn_state; 2150 struct vop2 *vop2 = cstate->private; 2151 u32 vp_offset = (cstate->crtc_id * 0x100); 2152 u32 output_type = conn_state->type; 2153 u32 data_swap = 0; 2154 2155 if (is_uv_swap(conn_state->bus_format, conn_state->output_mode)) 2156 data_swap = DSP_RB_SWAP; 2157 2158 if (vop2->version == VOP_VERSION_RK3588 && 2159 (output_type == DRM_MODE_CONNECTOR_HDMIA || 2160 output_type == DRM_MODE_CONNECTOR_eDP) && 2161 (conn_state->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 2162 conn_state->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) 2163 data_swap |= DSP_RG_SWAP; 2164 2165 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 2166 DATA_SWAP_MASK, DATA_SWAP_SHIFT, data_swap, false); 2167 } 2168 2169 static int rockchip_vop2_init(struct display_state *state) 2170 { 2171 struct crtc_state *cstate = &state->crtc_state; 2172 struct connector_state *conn_state = &state->conn_state; 2173 struct drm_display_mode *mode = &conn_state->mode; 2174 struct vop2 *vop2 = cstate->private; 2175 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2176 u16 hdisplay = mode->crtc_hdisplay; 2177 u16 htotal = mode->crtc_htotal; 2178 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 2179 u16 hact_end = hact_st + hdisplay; 2180 u16 vdisplay = mode->crtc_vdisplay; 2181 u16 vtotal = mode->crtc_vtotal; 2182 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 2183 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 2184 u16 vact_end = vact_st + vdisplay; 2185 bool yuv_overlay = false; 2186 u32 vp_offset = (cstate->crtc_id * 0x100); 2187 u32 line_flag_offset = (cstate->crtc_id * 4); 2188 u32 val, act_end; 2189 u8 dither_down_en = 0; 2190 u8 pre_dither_down_en = 0; 2191 char output_type_name[30] = {0}; 2192 char dclk_name[9]; 2193 struct clk dclk; 2194 unsigned long dclk_rate; 2195 int ret; 2196 2197 printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", 2198 mode->hdisplay, mode->vdisplay, 2199 mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", 2200 mode->vscan, 2201 get_output_if_name(conn_state->output_if, output_type_name), 2202 cstate->crtc_id); 2203 2204 vop2_initial(vop2, state); 2205 if (vop2->version == VOP_VERSION_RK3588) 2206 dclk_rate = rk3588_vop2_if_cfg(state); 2207 else 2208 dclk_rate = rk3568_vop2_if_cfg(state); 2209 2210 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && 2211 !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) 2212 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 2213 2214 vop2_post_color_swap(state); 2215 2216 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 2217 OUT_MODE_SHIFT, conn_state->output_mode, false); 2218 2219 switch (conn_state->bus_format) { 2220 case MEDIA_BUS_FMT_RGB565_1X16: 2221 dither_down_en = 1; 2222 break; 2223 case MEDIA_BUS_FMT_RGB666_1X18: 2224 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 2225 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 2226 case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: 2227 dither_down_en = 1; 2228 break; 2229 case MEDIA_BUS_FMT_YUV8_1X24: 2230 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 2231 dither_down_en = 0; 2232 pre_dither_down_en = 1; 2233 break; 2234 case MEDIA_BUS_FMT_YUV10_1X30: 2235 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 2236 case MEDIA_BUS_FMT_RGB888_1X24: 2237 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 2238 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 2239 default: 2240 dither_down_en = 0; 2241 pre_dither_down_en = 0; 2242 break; 2243 } 2244 2245 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA) 2246 pre_dither_down_en = 0; 2247 else 2248 pre_dither_down_en = 1; 2249 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2250 DITHER_DOWN_EN_SHIFT, dither_down_en, false); 2251 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2252 PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 2253 2254 yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 2255 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 2256 yuv_overlay, false); 2257 2258 cstate->yuv_overlay = yuv_overlay; 2259 2260 vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 2261 (htotal << 16) | hsync_len); 2262 val = hact_st << 16; 2263 val |= hact_end; 2264 vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 2265 val = vact_st << 16; 2266 val |= vact_end; 2267 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 2268 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 2269 u16 vact_st_f1 = vtotal + vact_st + 1; 2270 u16 vact_end_f1 = vact_st_f1 + vdisplay; 2271 2272 val = vact_st_f1 << 16 | vact_end_f1; 2273 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 2274 val); 2275 2276 val = vtotal << 16 | (vtotal + vsync_len); 2277 vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 2278 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2279 INTERLACE_EN_SHIFT, 1, false); 2280 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2281 DSP_FILED_POL, 1, false); 2282 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2283 P2I_EN_SHIFT, 1, false); 2284 vtotal += vtotal + 1; 2285 act_end = vact_end_f1; 2286 } else { 2287 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2288 INTERLACE_EN_SHIFT, 0, false); 2289 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2290 P2I_EN_SHIFT, 0, false); 2291 act_end = vact_end; 2292 } 2293 vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 2294 (vtotal << 16) | vsync_len); 2295 2296 if (vop2->version == VOP_VERSION_RK3568) { 2297 if (mode->flags & DRM_MODE_FLAG_DBLCLK || 2298 conn_state->output_if & VOP_OUTPUT_IF_BT656) 2299 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2300 CORE_DCLK_DIV_EN_SHIFT, 1, false); 2301 else 2302 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2303 CORE_DCLK_DIV_EN_SHIFT, 0, false); 2304 } 2305 2306 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 2307 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2308 DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0x3, false); 2309 else 2310 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 2311 DCLK_DIV2_MASK, DCLK_DIV2_SHIFT, 0, false); 2312 2313 if (yuv_overlay) 2314 val = 0x20010200; 2315 else 2316 val = 0; 2317 vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 2318 2319 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2320 POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 2321 2322 vop2_tv_config_update(state, vop2); 2323 vop2_post_config(state, vop2); 2324 2325 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 2326 ret = clk_get_by_name(cstate->dev, dclk_name, &dclk); 2327 if (!ret) 2328 ret = clk_set_rate(&dclk, dclk_rate * 1000); 2329 if (IS_ERR_VALUE(ret)) { 2330 printf("%s: Failed to set vp%d dclk[%ld KHZ] ret=%d\n", 2331 __func__, cstate->crtc_id, dclk_rate, ret); 2332 return ret; 2333 } 2334 2335 vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 2336 RK3568_DSP_LINE_FLAG_NUM0_SHIFT, act_end - 3, false); 2337 vop2_mask_write(vop2, RK3568_SYS_CTRL_LINE_FLAG0 + line_flag_offset, LINE_FLAG_NUM_MASK, 2338 RK3568_DSP_LINE_FLAG_NUM1_SHIFT, act_end - us_to_vertical_line(mode, 1000), false); 2339 2340 return 0; 2341 } 2342 2343 static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, 2344 uint32_t src_w, uint32_t src_h, uint32_t dst_w, 2345 uint32_t dst_h) 2346 { 2347 uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode; 2348 uint16_t hscl_filter_mode, vscl_filter_mode; 2349 uint8_t gt2 = 0, gt4 = 0; 2350 uint32_t xfac = 0, yfac = 0; 2351 uint16_t hsu_filter_mode = VOP2_SCALE_UP_BIC; 2352 uint16_t hsd_filter_mode = VOP2_SCALE_DOWN_BIL; 2353 uint16_t vsu_filter_mode = VOP2_SCALE_UP_BIL; 2354 uint16_t vsd_filter_mode = VOP2_SCALE_DOWN_BIL; 2355 u32 win_offset = win->reg_offset; 2356 2357 if (src_h >= (4 * dst_h)) 2358 gt4 = 1; 2359 else if (src_h >= (2 * dst_h)) 2360 gt2 = 1; 2361 2362 if (gt4) 2363 src_h >>= 2; 2364 else if (gt2) 2365 src_h >>= 1; 2366 2367 yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); 2368 yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h); 2369 2370 if (yrgb_hor_scl_mode == SCALE_UP) 2371 hscl_filter_mode = hsu_filter_mode; 2372 else 2373 hscl_filter_mode = hsd_filter_mode; 2374 2375 if (yrgb_ver_scl_mode == SCALE_UP) 2376 vscl_filter_mode = vsu_filter_mode; 2377 else 2378 vscl_filter_mode = vsd_filter_mode; 2379 2380 /* 2381 * RK3568 VOP Esmart/Smart dsp_w should be even pixel 2382 * at scale down mode 2383 */ 2384 if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) { 2385 printf("win dst_w[%d] should align as 2 pixel\n", dst_w); 2386 dst_w += 1; 2387 } 2388 2389 xfac = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode, src_w, dst_w); 2390 yfac = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode, src_h, dst_h); 2391 2392 if (win->type == CLUSTER_LAYER) { 2393 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB + win_offset, 2394 yfac << 16 | xfac); 2395 2396 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2397 YRGB_GT2_MASK, CLUSTER_YRGB_GT2_SHIFT, gt2, false); 2398 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2399 YRGB_GT4_MASK, CLUSTER_YRGB_GT4_SHIFT, gt4, false); 2400 2401 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2402 YRGB_XSCL_MODE_MASK, CLUSTER_YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 2403 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL1 + win_offset, 2404 YRGB_YSCL_MODE_MASK, CLUSTER_YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 2405 2406 } else { 2407 vop2_writel(vop2, RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB + win_offset, 2408 yfac << 16 | xfac); 2409 2410 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 2411 YRGB_GT2_MASK, YRGB_GT2_SHIFT, gt2, false); 2412 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 2413 YRGB_GT4_MASK, YRGB_GT4_SHIFT, gt4, false); 2414 2415 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 2416 YRGB_XSCL_MODE_MASK, YRGB_XSCL_MODE_SHIFT, yrgb_hor_scl_mode, false); 2417 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 2418 YRGB_YSCL_MODE_MASK, YRGB_YSCL_MODE_SHIFT, yrgb_ver_scl_mode, false); 2419 2420 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 2421 YRGB_XSCL_FILTER_MODE_MASK, YRGB_XSCL_FILTER_MODE_SHIFT, 2422 hscl_filter_mode, false); 2423 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_SCL_CTRL + win_offset, 2424 YRGB_YSCL_FILTER_MODE_MASK, YRGB_YSCL_FILTER_MODE_SHIFT, 2425 vscl_filter_mode, false); 2426 } 2427 } 2428 2429 static void vop2_set_cluster_win(struct display_state *state, struct vop2_win_data *win) 2430 { 2431 struct crtc_state *cstate = &state->crtc_state; 2432 struct connector_state *conn_state = &state->conn_state; 2433 struct drm_display_mode *mode = &conn_state->mode; 2434 struct vop2 *vop2 = cstate->private; 2435 int src_w = cstate->src_w; 2436 int src_h = cstate->src_h; 2437 int crtc_x = cstate->crtc_x; 2438 int crtc_y = cstate->crtc_y; 2439 int crtc_w = cstate->crtc_w; 2440 int crtc_h = cstate->crtc_h; 2441 int xvir = cstate->xvir; 2442 int y_mirror = 0; 2443 int csc_mode; 2444 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 2445 u32 win_offset = win->reg_offset; 2446 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2447 2448 act_info = (src_h - 1) << 16; 2449 act_info |= (src_w - 1) & 0xffff; 2450 2451 dsp_info = (crtc_h - 1) << 16; 2452 dsp_info |= (crtc_w - 1) & 0xffff; 2453 2454 dsp_stx = crtc_x; 2455 dsp_sty = crtc_y; 2456 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 2457 2458 if (mode->flags & DRM_MODE_FLAG_YMIRROR) 2459 y_mirror = 1; 2460 else 2461 y_mirror = 0; 2462 2463 vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 2464 2465 if (y_mirror) 2466 printf("WARN: y mirror is unsupported by cluster window\n"); 2467 2468 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, 2469 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 2470 false); 2471 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_VIR + win_offset, xvir); 2472 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_YRGB_MST + win_offset, cstate->dma_addr); 2473 2474 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_ACT_INFO + win_offset, act_info); 2475 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_INFO + win_offset, dsp_info); 2476 vop2_writel(vop2, RK3568_CLUSTER0_WIN0_DSP_ST + win_offset, dsp_st); 2477 2478 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, WIN_EN_SHIFT, 1, false); 2479 2480 csc_mode = vop2_convert_csc_mode(conn_state->color_space); 2481 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, EN_MASK, 2482 CLUSTER_RGB2YUV_EN_SHIFT, 2483 is_yuv_output(conn_state->bus_format), false); 2484 vop2_mask_write(vop2, RK3568_CLUSTER0_WIN0_CTRL0 + win_offset, CSC_MODE_MASK, 2485 CLUSTER_CSC_MODE_SHIFT, csc_mode, false); 2486 vop2_mask_write(vop2, RK3568_CLUSTER0_CTRL + win_offset, EN_MASK, CLUSTER_EN_SHIFT, 1, false); 2487 2488 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2489 } 2490 2491 static void vop2_set_smart_win(struct display_state *state, struct vop2_win_data *win) 2492 { 2493 struct crtc_state *cstate = &state->crtc_state; 2494 struct connector_state *conn_state = &state->conn_state; 2495 struct drm_display_mode *mode = &conn_state->mode; 2496 struct vop2 *vop2 = cstate->private; 2497 int src_w = cstate->src_w; 2498 int src_h = cstate->src_h; 2499 int crtc_x = cstate->crtc_x; 2500 int crtc_y = cstate->crtc_y; 2501 int crtc_w = cstate->crtc_w; 2502 int crtc_h = cstate->crtc_h; 2503 int xvir = cstate->xvir; 2504 int y_mirror = 0; 2505 int csc_mode; 2506 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 2507 u32 win_offset = win->reg_offset; 2508 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2509 2510 /* 2511 * This is workaround solution for IC design: 2512 * esmart can't support scale down when actual_w % 16 == 1. 2513 */ 2514 if (src_w > crtc_w && (src_w & 0xf) == 1) { 2515 printf("WARN: vp%d unsupported act_w[%d] mode 16 = 1 when scale down\n", cstate->crtc_id, src_w); 2516 src_w -= 1; 2517 } 2518 2519 act_info = (src_h - 1) << 16; 2520 act_info |= (src_w - 1) & 0xffff; 2521 2522 dsp_info = (crtc_h - 1) << 16; 2523 dsp_info |= (crtc_w - 1) & 0xffff; 2524 2525 dsp_stx = crtc_x; 2526 dsp_sty = crtc_y; 2527 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 2528 2529 if (mode->flags & DRM_MODE_FLAG_YMIRROR) 2530 y_mirror = 1; 2531 else 2532 y_mirror = 0; 2533 2534 vop2_setup_scale(vop2, win, src_w, src_h, crtc_w, crtc_h); 2535 2536 if (y_mirror) 2537 cstate->dma_addr += (src_h - 1) * xvir * 4; 2538 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 2539 YMIRROR_EN_SHIFT, y_mirror, false); 2540 2541 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 2542 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 2543 false); 2544 vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 2545 vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 2546 cstate->dma_addr); 2547 2548 vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 2549 act_info); 2550 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 2551 dsp_info); 2552 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 2553 2554 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 2555 WIN_EN_SHIFT, 1, false); 2556 2557 csc_mode = vop2_convert_csc_mode(conn_state->color_space); 2558 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 2559 RGB2YUV_EN_SHIFT, 2560 is_yuv_output(conn_state->bus_format), false); 2561 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 2562 CSC_MODE_SHIFT, csc_mode, false); 2563 2564 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2565 } 2566 2567 static int rockchip_vop2_set_plane(struct display_state *state) 2568 { 2569 struct crtc_state *cstate = &state->crtc_state; 2570 struct vop2 *vop2 = cstate->private; 2571 struct vop2_win_data *win_data; 2572 u8 primary_plane_id = vop2->vp_plane_mask[cstate->crtc_id].primary_plane_id; 2573 char plane_name[10] = {0}; 2574 2575 if (cstate->crtc_w > cstate->max_output.width) { 2576 printf("ERROR: output w[%d] exceeded max width[%d]\n", 2577 cstate->crtc_w, cstate->max_output.width); 2578 return -EINVAL; 2579 } 2580 2581 win_data = vop2_find_win_by_phys_id(vop2, primary_plane_id); 2582 if (!win_data) { 2583 printf("invalid win id %d\n", primary_plane_id); 2584 return -ENODEV; 2585 } 2586 2587 if (win_data->type == CLUSTER_LAYER) 2588 vop2_set_cluster_win(state, win_data); 2589 else 2590 vop2_set_smart_win(state, win_data); 2591 2592 printf("VOP VP%d enable %s[%dx%d->%dx%d@%dx%d] fmt[%d] addr[0x%x]\n", 2593 cstate->crtc_id, get_plane_name(primary_plane_id, plane_name), 2594 cstate->src_w, cstate->src_h, cstate->crtc_w, cstate->crtc_h, 2595 cstate->crtc_x, cstate->crtc_y, cstate->format, 2596 cstate->dma_addr); 2597 2598 return 0; 2599 } 2600 2601 static int rockchip_vop2_prepare(struct display_state *state) 2602 { 2603 return 0; 2604 } 2605 2606 static int rockchip_vop2_enable(struct display_state *state) 2607 { 2608 struct crtc_state *cstate = &state->crtc_state; 2609 struct vop2 *vop2 = cstate->private; 2610 u32 vp_offset = (cstate->crtc_id * 0x100); 2611 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2612 2613 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2614 STANDBY_EN_SHIFT, 0, false); 2615 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2616 2617 return 0; 2618 } 2619 2620 static int rockchip_vop2_disable(struct display_state *state) 2621 { 2622 struct crtc_state *cstate = &state->crtc_state; 2623 struct vop2 *vop2 = cstate->private; 2624 u32 vp_offset = (cstate->crtc_id * 0x100); 2625 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id) | (BIT(cstate->crtc_id) << 16); 2626 2627 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 2628 STANDBY_EN_SHIFT, 1, false); 2629 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 2630 2631 return 0; 2632 } 2633 2634 static int rockchip_vop2_get_cursor_plane(struct display_state *state, u32 plane_mask, int cursor_plane) 2635 { 2636 struct crtc_state *cstate = &state->crtc_state; 2637 struct vop2 *vop2 = cstate->private; 2638 int i = 0; 2639 int correct_cursor_plane = -1; 2640 int plane_type = -1; 2641 2642 if (cursor_plane < 0) 2643 return -1; 2644 2645 if (plane_mask & (1 << cursor_plane)) 2646 return cursor_plane; 2647 2648 /* Get current cursor plane type */ 2649 for (i = 0; i < vop2->data->nr_layers; i++) { 2650 if (vop2->data->plane_table[i].plane_id == cursor_plane) { 2651 plane_type = vop2->data->plane_table[i].plane_type; 2652 break; 2653 } 2654 } 2655 2656 /* Get the other same plane type plane id */ 2657 for (i = 0; i < vop2->data->nr_layers; i++) { 2658 if (vop2->data->plane_table[i].plane_type == plane_type && 2659 vop2->data->plane_table[i].plane_id != cursor_plane) { 2660 correct_cursor_plane = vop2->data->plane_table[i].plane_id; 2661 break; 2662 } 2663 } 2664 2665 /* To check whether the new correct_cursor_plane is attach to current vp */ 2666 if (correct_cursor_plane < 0 || !(plane_mask & (1 << correct_cursor_plane))) { 2667 printf("error: faild to find correct plane as cursor plane\n"); 2668 return -1; 2669 } 2670 2671 printf("vp%d adjust cursor plane from %d to %d\n", 2672 cstate->crtc_id, cursor_plane, correct_cursor_plane); 2673 2674 return correct_cursor_plane; 2675 } 2676 2677 static int rockchip_vop2_fixup_dts(struct display_state *state, void *blob) 2678 { 2679 struct crtc_state *cstate = &state->crtc_state; 2680 struct vop2 *vop2 = cstate->private; 2681 ofnode vp_node; 2682 struct device_node *port_parent_node = cstate->ports_node; 2683 static bool vop_fix_dts; 2684 const char *path; 2685 u32 plane_mask = 0; 2686 int vp_id = 0; 2687 int cursor_plane_id = -1; 2688 2689 if (vop_fix_dts) 2690 return 0; 2691 2692 ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) { 2693 path = vp_node.np->full_name; 2694 plane_mask = vop2->vp_plane_mask[vp_id].plane_mask; 2695 2696 if (cstate->crtc->assign_plane) 2697 continue; 2698 cursor_plane_id = rockchip_vop2_get_cursor_plane(state, plane_mask, 2699 cstate->crtc->vps[vp_id].cursor_plane); 2700 printf("vp%d, plane_mask:0x%x, primary-id:%d, curser-id:%d\n", 2701 vp_id, plane_mask, 2702 vop2->vp_plane_mask[vp_id].primary_plane_id, 2703 cursor_plane_id); 2704 2705 do_fixup_by_path_u32(blob, path, "rockchip,plane-mask", 2706 plane_mask, 1); 2707 do_fixup_by_path_u32(blob, path, "rockchip,primary-plane", 2708 vop2->vp_plane_mask[vp_id].primary_plane_id, 1); 2709 if (cursor_plane_id >= 0) 2710 do_fixup_by_path_u32(blob, path, "cursor-win-id", 2711 cursor_plane_id, 1); 2712 vp_id++; 2713 } 2714 2715 vop_fix_dts = true; 2716 2717 return 0; 2718 } 2719 2720 static struct vop2_plane_table rk356x_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 2721 {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 2722 {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 2723 {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 2724 {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 2725 {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 2726 {ROCKCHIP_VOP2_SMART0, SMART_LAYER}, 2727 }; 2728 2729 static struct vop2_vp_plane_mask rk356x_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 2730 { /* one display policy */ 2731 {/* main display */ 2732 .primary_plane_id = ROCKCHIP_VOP2_SMART0, 2733 .attached_layers_nr = 6, 2734 .attached_layers = { 2735 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0, 2736 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 2737 }, 2738 }, 2739 {/* second display */}, 2740 {/* third display */}, 2741 {/* fourth display */}, 2742 }, 2743 2744 { /* two display policy */ 2745 {/* main display */ 2746 .primary_plane_id = ROCKCHIP_VOP2_SMART0, 2747 .attached_layers_nr = 3, 2748 .attached_layers = { 2749 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 2750 }, 2751 }, 2752 2753 {/* second display */ 2754 .primary_plane_id = ROCKCHIP_VOP2_SMART1, 2755 .attached_layers_nr = 3, 2756 .attached_layers = { 2757 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1 2758 }, 2759 }, 2760 {/* third display */}, 2761 {/* fourth display */}, 2762 }, 2763 2764 { /* three display policy */ 2765 {/* main display */ 2766 .primary_plane_id = ROCKCHIP_VOP2_SMART0, 2767 .attached_layers_nr = 3, 2768 .attached_layers = { 2769 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0 2770 }, 2771 }, 2772 2773 {/* second display */ 2774 .primary_plane_id = ROCKCHIP_VOP2_SMART1, 2775 .attached_layers_nr = 2, 2776 .attached_layers = { 2777 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_SMART1 2778 }, 2779 }, 2780 2781 {/* third display */ 2782 .primary_plane_id = ROCKCHIP_VOP2_ESMART1, 2783 .attached_layers_nr = 1, 2784 .attached_layers = { ROCKCHIP_VOP2_ESMART1 }, 2785 }, 2786 2787 {/* fourth display */}, 2788 }, 2789 2790 {/* reserved for four display policy */}, 2791 }; 2792 2793 static struct vop2_win_data rk3568_win_data[6] = { 2794 { 2795 .name = "Cluster0", 2796 .phys_id = ROCKCHIP_VOP2_CLUSTER0, 2797 .type = CLUSTER_LAYER, 2798 .win_sel_port_offset = 0, 2799 .layer_sel_win_id = 0, 2800 .reg_offset = 0, 2801 }, 2802 2803 { 2804 .name = "Cluster1", 2805 .phys_id = ROCKCHIP_VOP2_CLUSTER1, 2806 .type = CLUSTER_LAYER, 2807 .win_sel_port_offset = 1, 2808 .layer_sel_win_id = 1, 2809 .reg_offset = 0x200, 2810 }, 2811 2812 { 2813 .name = "Esmart0", 2814 .phys_id = ROCKCHIP_VOP2_ESMART0, 2815 .type = ESMART_LAYER, 2816 .win_sel_port_offset = 4, 2817 .layer_sel_win_id = 2, 2818 .reg_offset = 0, 2819 }, 2820 2821 { 2822 .name = "Esmart1", 2823 .phys_id = ROCKCHIP_VOP2_ESMART1, 2824 .type = ESMART_LAYER, 2825 .win_sel_port_offset = 5, 2826 .layer_sel_win_id = 6, 2827 .reg_offset = 0x200, 2828 }, 2829 2830 { 2831 .name = "Smart0", 2832 .phys_id = ROCKCHIP_VOP2_SMART0, 2833 .type = SMART_LAYER, 2834 .win_sel_port_offset = 6, 2835 .layer_sel_win_id = 3, 2836 .reg_offset = 0x400, 2837 }, 2838 2839 { 2840 .name = "Smart1", 2841 .phys_id = ROCKCHIP_VOP2_SMART1, 2842 .type = SMART_LAYER, 2843 .win_sel_port_offset = 7, 2844 .layer_sel_win_id = 7, 2845 .reg_offset = 0x600, 2846 }, 2847 }; 2848 2849 static struct vop2_vp_data rk3568_vp_data[3] = { 2850 { 2851 .feature = VOP_FEATURE_OUTPUT_10BIT, 2852 .pre_scan_max_dly = 42, 2853 .max_output = {4096, 2304}, 2854 }, 2855 { 2856 .feature = 0, 2857 .pre_scan_max_dly = 40, 2858 .max_output = {2048, 1536}, 2859 }, 2860 { 2861 .feature = 0, 2862 .pre_scan_max_dly = 40, 2863 .max_output = {1920, 1080}, 2864 }, 2865 }; 2866 2867 const struct vop2_data rk3568_vop = { 2868 .version = VOP_VERSION_RK3568, 2869 .nr_vps = 3, 2870 .vp_data = rk3568_vp_data, 2871 .win_data = rk3568_win_data, 2872 .plane_mask = rk356x_vp_plane_mask[0], 2873 .plane_table = rk356x_plane_table, 2874 .nr_layers = 6, 2875 .nr_mixers = 5, 2876 .nr_gammas = 1, 2877 }; 2878 2879 static struct vop2_plane_table rk3588_plane_table[ROCKCHIP_VOP2_LAYER_MAX] = { 2880 {ROCKCHIP_VOP2_CLUSTER0, CLUSTER_LAYER}, 2881 {ROCKCHIP_VOP2_CLUSTER1, CLUSTER_LAYER}, 2882 {ROCKCHIP_VOP2_CLUSTER2, CLUSTER_LAYER}, 2883 {ROCKCHIP_VOP2_CLUSTER3, CLUSTER_LAYER}, 2884 {ROCKCHIP_VOP2_ESMART0, ESMART_LAYER}, 2885 {ROCKCHIP_VOP2_ESMART1, ESMART_LAYER}, 2886 {ROCKCHIP_VOP2_ESMART2, ESMART_LAYER}, 2887 {ROCKCHIP_VOP2_ESMART3, ESMART_LAYER}, 2888 }; 2889 2890 static struct vop2_vp_plane_mask rk3588_vp_plane_mask[VOP2_VP_MAX][VOP2_VP_MAX] = { 2891 { /* one display policy */ 2892 {/* main display */ 2893 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2894 .attached_layers_nr = 8, 2895 .attached_layers = { 2896 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_ESMART2, 2897 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_ESMART3, 2898 ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3 2899 }, 2900 }, 2901 {/* second display */}, 2902 {/* third display */}, 2903 {/* fourth display */}, 2904 }, 2905 2906 { /* two display policy */ 2907 {/* main display */ 2908 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2909 .attached_layers_nr = 4, 2910 .attached_layers = { 2911 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0, 2912 ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 2913 }, 2914 }, 2915 2916 {/* second display */ 2917 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 2918 .attached_layers_nr = 4, 2919 .attached_layers = { 2920 ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2, 2921 ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 2922 }, 2923 }, 2924 {/* third display */}, 2925 {/* fourth display */}, 2926 }, 2927 2928 { /* three display policy */ 2929 {/* main display */ 2930 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2931 .attached_layers_nr = 3, 2932 .attached_layers = { 2933 ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART0 2934 }, 2935 }, 2936 2937 {/* second display */ 2938 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 2939 .attached_layers_nr = 3, 2940 .attached_layers = { 2941 ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART1 2942 }, 2943 }, 2944 2945 {/* third display */ 2946 .primary_plane_id = ROCKCHIP_VOP2_ESMART2, 2947 .attached_layers_nr = 2, 2948 .attached_layers = { ROCKCHIP_VOP2_ESMART2, ROCKCHIP_VOP2_ESMART3 }, 2949 }, 2950 2951 {/* fourth display */}, 2952 }, 2953 2954 { /* four display policy */ 2955 {/* main display */ 2956 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER0, 2957 .attached_layers_nr = 2, 2958 .attached_layers = { ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_ESMART0 }, 2959 }, 2960 2961 {/* second display */ 2962 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER1, 2963 .attached_layers_nr = 2, 2964 .attached_layers = { ROCKCHIP_VOP2_CLUSTER1, ROCKCHIP_VOP2_ESMART1 }, 2965 }, 2966 2967 {/* third display */ 2968 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER2, 2969 .attached_layers_nr = 2, 2970 .attached_layers = { ROCKCHIP_VOP2_CLUSTER2, ROCKCHIP_VOP2_ESMART2 }, 2971 }, 2972 2973 {/* fourth display */ 2974 .primary_plane_id = ROCKCHIP_VOP2_CLUSTER3, 2975 .attached_layers_nr = 2, 2976 .attached_layers = { ROCKCHIP_VOP2_CLUSTER3, ROCKCHIP_VOP2_ESMART3 }, 2977 }, 2978 }, 2979 2980 }; 2981 2982 static struct vop2_power_domain_data rk3588_cluster0_pd_data = { 2983 .pd_en_shift = RK3588_CLUSTER0_PD_EN_SHIFT, 2984 .pd_status_shift = RK3588_CLUSTER0_PD_STATUS_SHIFT, 2985 .pmu_status_shift = RK3588_PD_CLUSTER0_PWR_STAT_SHIFI, 2986 .bisr_en_status_shift = RK3588_PD_CLUSTER0_REPAIR_EN_SHIFT, 2987 }; 2988 2989 static struct vop2_power_domain_data rk3588_cluster1_pd_data = { 2990 .is_parent_needed = true, 2991 .pd_en_shift = RK3588_CLUSTER1_PD_EN_SHIFT, 2992 .pd_status_shift = RK3588_CLUSTER1_PD_STATUS_SHIFT, 2993 .pmu_status_shift = RK3588_PD_CLUSTER1_PWR_STAT_SHIFI, 2994 .bisr_en_status_shift = RK3588_PD_CLUSTER1_REPAIR_EN_SHIFT, 2995 .parent_phy_id = ROCKCHIP_VOP2_CLUSTER0, 2996 }; 2997 2998 static struct vop2_power_domain_data rk3588_cluster2_pd_data = { 2999 .is_parent_needed = true, 3000 .pd_en_shift = RK3588_CLUSTER2_PD_EN_SHIFT, 3001 .pd_status_shift = RK3588_CLUSTER2_PD_STATUS_SHIFT, 3002 .pmu_status_shift = RK3588_PD_CLUSTER2_PWR_STAT_SHIFI, 3003 .bisr_en_status_shift = RK3588_PD_CLUSTER2_REPAIR_EN_SHIFT, 3004 .parent_phy_id = ROCKCHIP_VOP2_CLUSTER0, 3005 }; 3006 3007 static struct vop2_power_domain_data rk3588_cluster3_pd_data = { 3008 .is_parent_needed = true, 3009 .pd_en_shift = RK3588_CLUSTER3_PD_EN_SHIFT, 3010 .pd_status_shift = RK3588_CLUSTER3_PD_STATUS_SHIFT, 3011 .pmu_status_shift = RK3588_PD_CLUSTER3_PWR_STAT_SHIFI, 3012 .bisr_en_status_shift = RK3588_PD_CLUSTER3_REPAIR_EN_SHIFT, 3013 .parent_phy_id = ROCKCHIP_VOP2_CLUSTER0, 3014 }; 3015 3016 static struct vop2_power_domain_data rk3588_esmart_pd_data = { 3017 .pd_en_shift = RK3588_ESMART_PD_EN_SHIFT, 3018 .pd_status_shift = RK3588_ESMART_PD_STATUS_SHIFT, 3019 .pmu_status_shift = RK3588_PD_ESMART_PWR_STAT_SHIFI, 3020 .bisr_en_status_shift = RK3588_PD_ESMART_REPAIR_EN_SHIFT, 3021 }; 3022 3023 static struct vop2_win_data rk3588_win_data[8] = { 3024 { 3025 .name = "Cluster0", 3026 .phys_id = ROCKCHIP_VOP2_CLUSTER0, 3027 .type = CLUSTER_LAYER, 3028 .win_sel_port_offset = 0, 3029 .layer_sel_win_id = 0, 3030 .reg_offset = 0, 3031 .pd_data = &rk3588_cluster0_pd_data, 3032 }, 3033 3034 { 3035 .name = "Cluster1", 3036 .phys_id = ROCKCHIP_VOP2_CLUSTER1, 3037 .type = CLUSTER_LAYER, 3038 .win_sel_port_offset = 1, 3039 .layer_sel_win_id = 1, 3040 .reg_offset = 0x200, 3041 .pd_data = &rk3588_cluster1_pd_data, 3042 }, 3043 3044 { 3045 .name = "Cluster2", 3046 .phys_id = ROCKCHIP_VOP2_CLUSTER2, 3047 .type = CLUSTER_LAYER, 3048 .win_sel_port_offset = 2, 3049 .layer_sel_win_id = 4, 3050 .reg_offset = 0x400, 3051 .pd_data = &rk3588_cluster2_pd_data, 3052 }, 3053 3054 { 3055 .name = "Cluster3", 3056 .phys_id = ROCKCHIP_VOP2_CLUSTER3, 3057 .type = CLUSTER_LAYER, 3058 .win_sel_port_offset = 3, 3059 .layer_sel_win_id = 5, 3060 .reg_offset = 0x600, 3061 .pd_data = &rk3588_cluster3_pd_data, 3062 }, 3063 3064 { 3065 .name = "Esmart0", 3066 .phys_id = ROCKCHIP_VOP2_ESMART0, 3067 .type = ESMART_LAYER, 3068 .win_sel_port_offset = 4, 3069 .layer_sel_win_id = 2, 3070 .reg_offset = 0, 3071 .pd_data = &rk3588_esmart_pd_data, 3072 }, 3073 3074 { 3075 .name = "Esmart1", 3076 .phys_id = ROCKCHIP_VOP2_ESMART1, 3077 .type = ESMART_LAYER, 3078 .win_sel_port_offset = 5, 3079 .layer_sel_win_id = 3, 3080 .reg_offset = 0x200, 3081 .pd_data = &rk3588_esmart_pd_data, 3082 }, 3083 3084 { 3085 .name = "Esmart2", 3086 .phys_id = ROCKCHIP_VOP2_ESMART2, 3087 .type = ESMART_LAYER, 3088 .win_sel_port_offset = 6, 3089 .layer_sel_win_id = 6, 3090 .reg_offset = 0x400, 3091 .pd_data = &rk3588_esmart_pd_data, 3092 }, 3093 3094 { 3095 .name = "Esmart3", 3096 .phys_id = ROCKCHIP_VOP2_ESMART3, 3097 .type = ESMART_LAYER, 3098 .win_sel_port_offset = 7, 3099 .layer_sel_win_id = 7, 3100 .reg_offset = 0x600, 3101 .pd_data = &rk3588_esmart_pd_data, 3102 }, 3103 }; 3104 3105 static struct vop2_vp_data rk3588_vp_data[4] = { 3106 { 3107 .feature = VOP_FEATURE_OUTPUT_10BIT, 3108 .pre_scan_max_dly = 42, 3109 .max_dclk = 600000, 3110 .max_output = {7680, 4320}, 3111 }, 3112 { 3113 .feature = VOP_FEATURE_OUTPUT_10BIT, 3114 .pre_scan_max_dly = 40, 3115 .max_dclk = 600000, 3116 .max_output = {4096, 2304}, 3117 }, 3118 { 3119 .feature = VOP_FEATURE_OUTPUT_10BIT, 3120 .pre_scan_max_dly = 52, 3121 .max_dclk = 600000, 3122 .max_output = {4096, 2304}, 3123 }, 3124 { 3125 .feature = 0, 3126 .pre_scan_max_dly = 52, 3127 .max_dclk = 200000, 3128 .max_output = {1920, 1080}, 3129 }, 3130 }; 3131 3132 const struct vop2_data rk3588_vop = { 3133 .version = VOP_VERSION_RK3588, 3134 .nr_vps = 4, 3135 .vp_data = rk3588_vp_data, 3136 .win_data = rk3588_win_data, 3137 .plane_mask = rk3588_vp_plane_mask[0], 3138 .plane_table = rk3588_plane_table, 3139 .nr_layers = 8, 3140 .nr_mixers = 7, 3141 .nr_gammas = 4, 3142 .nr_dscs = 2, 3143 }; 3144 3145 const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 3146 .preinit = rockchip_vop2_preinit, 3147 .prepare = rockchip_vop2_prepare, 3148 .init = rockchip_vop2_init, 3149 .set_plane = rockchip_vop2_set_plane, 3150 .enable = rockchip_vop2_enable, 3151 .disable = rockchip_vop2_disable, 3152 .fixup_dts = rockchip_vop2_fixup_dts, 3153 }; 3154