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