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