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/unaligned.h> 14 #include <asm/io.h> 15 #include <linux/list.h> 16 #include <linux/media-bus-format.h> 17 #include <clk.h> 18 #include <asm/arch/clock.h> 19 #include <linux/err.h> 20 #include <dm/device.h> 21 #include <dm/read.h> 22 #include <syscon.h> 23 24 #include "rockchip_display.h" 25 #include "rockchip_crtc.h" 26 #include "rockchip_connector.h" 27 28 /* System registers definition */ 29 #define RK3568_REG_CFG_DONE 0x000 30 #define CFG_DONE_EN BIT(15) 31 32 #define RK3568_VERSION_INFO 0x004 33 34 #define EN_MASK 1 35 36 #define RK3568_DSP_IF_EN 0x028 37 #define RGB_EN_SHIFT 0 38 #define HDMI0_EN_SHIFT 1 39 #define EDP0_EN_SHIFT 3 40 #define MIPI0_EN_SHIFT 4 41 #define MIPI1_EN_SHIFT 20 42 #define LVDS0_EN_SHIFT 5 43 #define LVDS1_EN_SHIFT 24 44 #define BT1120_EN_SHIFT 6 45 #define BT656_EN_SHIFT 7 46 #define IF_MUX_MASK 3 47 #define RGB_MUX_SHIFT 8 48 #define HDMI0_MUX_SHIFT 10 49 #define EDP0_MUX_SHIFT 14 50 #define MIPI0_MUX_SHIFT 16 51 #define MIPI1_MUX_SHIFT 21 52 #define LVDS0_MUX_SHIFT 5 53 #define LVDS1_MUX_SHIFT 25 54 55 #define RK3568_DSP_IF_CTRL 0x02c 56 #define LVDS_DUAL_EN_SHIFT 0 57 #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 58 #define LVDS_DUAL_SWAP_EN_SHIFT 2 59 #define RK3568_DSP_IF_POL 0x030 60 #define IF_CTRL_REG_DONE_IMD_MASK 1 61 #define IF_CTRL_REG_DONE_IMD_SHIFT 28 62 #define IF_CRTL_MIPI_DCLK_POL_SHIT 19 63 #define IF_CRTL_EDP_DCLK_POL_SHIT 15 64 #define IF_CRTL_HDMI_DCLK_POL_SHIT 7 65 #define IF_CRTL_HDMI_PIN_POL_MASK 0x7 66 #define IF_CRTL_HDMI_PIN_POL_SHIT 4 67 #define IF_CRTL_RGB_LVDS_DCLK_POL_SHIT 3 68 #define RK3568_VP0_LINE_FLAG 0x70 69 #define RK3568_VP1_LINE_FLAG 0x74 70 #define RK3568_VP2_LINE_FLAG 0x78 71 #define RK3568_SYS0_INT_EN 0x80 72 #define RK3568_SYS0_INT_CLR 0x84 73 #define RK3568_SYS0_INT_STATUS 0x88 74 #define RK3568_SYS1_INT_EN 0x90 75 #define RK3568_SYS1_INT_CLR 0x94 76 #define RK3568_SYS1_INT_STATUS 0x98 77 #define RK3568_VP0_INT_EN 0xA0 78 #define RK3568_VP0_INT_CLR 0xA4 79 #define RK3568_VP0_INT_STATUS 0xA8 80 #define RK3568_VP1_INT_EN 0xB0 81 #define RK3568_VP1_INT_CLR 0xB4 82 #define RK3568_VP1_INT_STATUS 0xB8 83 #define RK3568_VP2_INT_EN 0xC0 84 #define RK3568_VP2_INT_CLR 0xC4 85 #define RK3568_VP2_INT_STATUS 0xC8 86 87 /* Video Port registers definition */ 88 #define RK3568_VP0_DSP_CTRL 0xC00 89 #define OUT_MODE_MASK 0xf 90 #define OUT_MODE_SHIFT 0 91 #define DATA_SWAP_MASK 0x1f 92 #define DATA_SWAP_SHIFT 8 93 #define DSP_RB_SWAP 2 94 #define CORE_DCLK_DIV_EN_SHIFT 4 95 #define P2I_EN_SHIFT 5 96 #define INTERLACE_EN_SHIFT 7 97 #define POST_DSP_OUT_R2Y_SHIFT 15 98 #define PRE_DITHER_DOWN_EN_SHIFT 16 99 #define DITHER_DOWN_EN_SHIFT 17 100 #define STANDBY_EN_SHIFT 31 101 102 #define RK3568_VP0_MIPI_CTRL 0xC04 103 #define DCLK_DIV2_SHIFT 4 104 #define DCLK_DIV2_MASK 0x3 105 #define MIPI_DUAL_EN_SHIFT 20 106 #define MIPI_DUAL_SWAP_EN_SHIFT 21 107 108 #define RK3568_VP0_COLOR_BAR_CTRL 0xC08 109 #define RK3568_VP0_DSP_BG 0xC2C 110 #define RK3568_VP0_PRE_SCAN_HTIMING 0xC30 111 #define RK3568_VP0_POST_DSP_HACT_INFO 0xC34 112 #define RK3568_VP0_POST_DSP_VACT_INFO 0xC38 113 #define RK3568_VP0_POST_SCL_FACTOR_YRGB 0xC3C 114 #define RK3568_VP0_POST_SCL_CTRL 0xC40 115 #define RK3568_VP0_POST_DSP_VACT_INFO_F1 0xC44 116 #define RK3568_VP0_DSP_HTOTAL_HS_END 0xC48 117 #define RK3568_VP0_DSP_HACT_ST_END 0xC4C 118 #define RK3568_VP0_DSP_VTOTAL_VS_END 0xC50 119 #define RK3568_VP0_DSP_VACT_ST_END 0xC54 120 #define RK3568_VP0_DSP_VS_ST_END_F1 0xC58 121 #define RK3568_VP0_DSP_VACT_ST_END_F1 0xC5C 122 123 #define RK3568_VP1_DSP_CTRL 0xD00 124 #define RK3568_VP1_MIPI_CTRL 0xD04 125 #define RK3568_VP1_COLOR_BAR_CTRL 0xD08 126 #define RK3568_VP1_PRE_SCAN_HTIMING 0xD30 127 #define RK3568_VP1_POST_DSP_HACT_INFO 0xD34 128 #define RK3568_VP1_POST_DSP_VACT_INFO 0xD38 129 #define RK3568_VP1_POST_SCL_FACTOR_YRGB 0xD3C 130 #define RK3568_VP1_POST_SCL_CTRL 0xD40 131 #define RK3568_VP1_DSP_HACT_INFO 0xD34 132 #define RK3568_VP1_DSP_VACT_INFO 0xD38 133 #define RK3568_VP1_POST_DSP_VACT_INFO_F1 0xD44 134 #define RK3568_VP1_DSP_HTOTAL_HS_END 0xD48 135 #define RK3568_VP1_DSP_HACT_ST_END 0xD4C 136 #define RK3568_VP1_DSP_VTOTAL_VS_END 0xD50 137 #define RK3568_VP1_DSP_VACT_ST_END 0xD54 138 #define RK3568_VP1_DSP_VS_ST_END_F1 0xD58 139 #define RK3568_VP1_DSP_VACT_ST_END_F1 0xD5C 140 141 #define RK3568_VP2_DSP_CTRL 0xE00 142 #define RK3568_VP2_MIPI_CTRL 0xE04 143 #define RK3568_VP2_COLOR_BAR_CTRL 0xE08 144 #define RK3568_VP2_PRE_SCAN_HTIMING 0xE30 145 #define RK3568_VP2_POST_DSP_HACT_INFO 0xE34 146 #define RK3568_VP2_POST_DSP_VACT_INFO 0xE38 147 #define RK3568_VP2_POST_SCL_FACTOR_YRGB 0xE3C 148 #define RK3568_VP2_POST_SCL_CTRL 0xE40 149 #define RK3568_VP2_DSP_HACT_INFO 0xE34 150 #define RK3568_VP2_DSP_VACT_INFO 0xE38 151 #define RK3568_VP2_POST_DSP_VACT_INFO_F1 0xE44 152 #define RK3568_VP2_DSP_HTOTAL_HS_END 0xE48 153 #define RK3568_VP2_DSP_HACT_ST_END 0xE4C 154 #define RK3568_VP2_DSP_VTOTAL_VS_END 0xE50 155 #define RK3568_VP2_DSP_VACT_ST_END 0xE54 156 #define RK3568_VP2_DSP_VS_ST_END_F1 0xE58 157 #define RK3568_VP2_DSP_VACT_ST_END_F1 0xE5C 158 159 /* Overlay registers definition */ 160 #define RK3568_OVL_CTRL 0x600 161 #define OVL_PORT_MUX_REG_DONE_IMD_SHIFT 28 162 #define RK3568_OVL_LAYER_SEL 0x604 163 #define LAYER_SEL_MASK 0xf 164 165 #define RK3568_OVL_PORT_SEL 0x608 166 #define PORT_MUX_MASK 0xf 167 #define PORT_MUX_SHIFT 0 168 #define LAYER_SEL_PORT_MASK 0x3 169 #define LAYER_SEL_PORT_SHIFT 24 170 171 #define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 172 #define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 173 #define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 174 #define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C 175 #define RK3568_MIX0_SRC_COLOR_CTRL 0x650 176 #define RK3568_MIX0_DST_COLOR_CTRL 0x654 177 #define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 178 #define RK3568_MIX0_DST_ALPHA_CTRL 0x65C 179 #define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 180 #define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 181 #define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 182 #define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC 183 #define RK3568_VP0_BG_MIX_CTRL 0x6E0 184 #define RK3568_VP1_BG_MIX_CTRL 0x6E4 185 #define RK3568_VP2_BG_MIX_CTRL 0x6E8 186 #define RK3568_CLUSTER_DLY_NUM 0x6F0 187 #define RK3568_SMART_DLY_NUM 0x6F8 188 189 /* Cluster0 register definition */ 190 #define RK3568_CLUSTER0_WIN0_CTRL0 0x1000 191 #define RK3568_CLUSTER0_WIN0_CTRL1 0x1004 192 #define RK3568_CLUSTER0_WIN0_YRGB_MST 0x1010 193 #define RK3568_CLUSTER0_WIN0_CBR_MST 0x1014 194 #define RK3568_CLUSTER0_WIN0_VIR 0x1018 195 #define RK3568_CLUSTER0_WIN0_ACT_INFO 0x1020 196 #define RK3568_CLUSTER0_WIN0_DSP_INFO 0x1024 197 #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 198 #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 199 #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 200 #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 201 #define RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH 0x105C 202 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE 0x1060 203 #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 204 #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 205 #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C 206 207 #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 208 #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 209 #define RK3568_CLUSTER0_WIN1_YRGB_MST 0x1090 210 #define RK3568_CLUSTER0_WIN1_CBR_MST 0x1094 211 #define RK3568_CLUSTER0_WIN1_VIR 0x1098 212 #define RK3568_CLUSTER0_WIN1_ACT_INFO 0x10A0 213 #define RK3568_CLUSTER0_WIN1_DSP_INFO 0x10A4 214 #define RK3568_CLUSTER0_WIN1_DSP_ST 0x10A8 215 #define RK3568_CLUSTER0_WIN1_SCL_FACTOR_YRGB 0x10B0 216 #define RK3568_CLUSTER0_WIN1_AFBCD_ROTATE_MODE 0x10D4 217 #define RK3568_CLUSTER0_WIN1_AFBCD_HDR_PTR 0x10D8 218 #define RK3568_CLUSTER0_WIN1_AFBCD_VIR_WIDTH 0x10DC 219 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_SIZE 0x10E0 220 #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 221 #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 222 #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC 223 224 #define RK3568_CLUSTER0_CTRL 0x1100 225 226 #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 227 #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 228 #define RK3568_CLUSTER1_WIN0_YRGB_MST 0x1210 229 #define RK3568_CLUSTER1_WIN0_CBR_MST 0x1214 230 #define RK3568_CLUSTER1_WIN0_VIR 0x1218 231 #define RK3568_CLUSTER1_WIN0_ACT_INFO 0x1220 232 #define RK3568_CLUSTER1_WIN0_DSP_INFO 0x1224 233 #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 234 #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 235 #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 236 #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 237 #define RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH 0x125C 238 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE 0x1260 239 #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 240 #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 241 #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C 242 243 #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 244 #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 245 #define RK3568_CLUSTER1_WIN1_YRGB_MST 0x1290 246 #define RK3568_CLUSTER1_WIN1_CBR_MST 0x1294 247 #define RK3568_CLUSTER1_WIN1_VIR 0x1298 248 #define RK3568_CLUSTER1_WIN1_ACT_INFO 0x12A0 249 #define RK3568_CLUSTER1_WIN1_DSP_INFO 0x12A4 250 #define RK3568_CLUSTER1_WIN1_DSP_ST 0x12A8 251 #define RK3568_CLUSTER1_WIN1_SCL_FACTOR_YRGB 0x12B0 252 #define RK3568_CLUSTER1_WIN1_AFBCD_ROTATE_MODE 0x12D4 253 #define RK3568_CLUSTER1_WIN1_AFBCD_HDR_PTR 0x12D8 254 #define RK3568_CLUSTER1_WIN1_AFBCD_VIR_WIDTH 0x12DC 255 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_SIZE 0x12E0 256 #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 257 #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 258 #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC 259 260 #define RK3568_CLUSTER1_CTRL 0x1300 261 262 /* Esmart register definition */ 263 #define RK3568_ESMART0_CTRL0 0x1800 264 #define RGB2YUV_EN_SHIFT 1 265 #define CSC_MODE_SHIFT 2 266 #define CSC_MODE_MASK 0x3 267 268 #define RK3568_ESMART0_CTRL1 0x1804 269 #define YMIRROR_EN_SHIFT 31 270 #define RK3568_ESMART0_REGION0_CTRL 0x1810 271 #define REGION0_RB_SWAP_SHIFT 14 272 #define WIN_EN_SHIFT 0 273 #define WIN_FORMAT_MASK 0x1f 274 #define WIN_FORMAT_SHIFT 1 275 276 #define RK3568_ESMART0_REGION0_YRGB_MST 0x1814 277 #define RK3568_ESMART0_REGION0_CBR_MST 0x1818 278 #define RK3568_ESMART0_REGION0_VIR 0x181C 279 #define RK3568_ESMART0_REGION0_ACT_INFO 0x1820 280 #define RK3568_ESMART0_REGION0_DSP_INFO 0x1824 281 #define RK3568_ESMART0_REGION0_DSP_ST 0x1828 282 #define RK3568_ESMART0_REGION0_SCL_CTRL 0x1830 283 #define RK3568_ESMART0_REGION0_SCL_FACTOR_YRGB 0x1834 284 #define RK3568_ESMART0_REGION0_SCL_FACTOR_CBR 0x1838 285 #define RK3568_ESMART0_REGION0_SCL_OFFSET 0x183C 286 #define RK3568_ESMART0_REGION1_CTRL 0x1840 287 #define RK3568_ESMART0_REGION1_YRGB_MST 0x1844 288 #define RK3568_ESMART0_REGION1_CBR_MST 0x1848 289 #define RK3568_ESMART0_REGION1_VIR 0x184C 290 #define RK3568_ESMART0_REGION1_ACT_INFO 0x1850 291 #define RK3568_ESMART0_REGION1_DSP_INFO 0x1854 292 #define RK3568_ESMART0_REGION1_DSP_ST 0x1858 293 #define RK3568_ESMART0_REGION1_SCL_CTRL 0x1860 294 #define RK3568_ESMART0_REGION1_SCL_FACTOR_YRGB 0x1864 295 #define RK3568_ESMART0_REGION1_SCL_FACTOR_CBR 0x1868 296 #define RK3568_ESMART0_REGION1_SCL_OFFSET 0x186C 297 #define RK3568_ESMART0_REGION2_CTRL 0x1870 298 #define RK3568_ESMART0_REGION2_YRGB_MST 0x1874 299 #define RK3568_ESMART0_REGION2_CBR_MST 0x1878 300 #define RK3568_ESMART0_REGION2_VIR 0x187C 301 #define RK3568_ESMART0_REGION2_ACT_INFO 0x1880 302 #define RK3568_ESMART0_REGION2_DSP_INFO 0x1884 303 #define RK3568_ESMART0_REGION2_DSP_ST 0x1888 304 #define RK3568_ESMART0_REGION2_SCL_CTRL 0x1890 305 #define RK3568_ESMART0_REGION2_SCL_FACTOR_YRGB 0x1894 306 #define RK3568_ESMART0_REGION2_SCL_FACTOR_CBR 0x1898 307 #define RK3568_ESMART0_REGION2_SCL_OFFSET 0x189C 308 #define RK3568_ESMART0_REGION3_CTRL 0x18A0 309 #define RK3568_ESMART0_REGION3_YRGB_MST 0x18A4 310 #define RK3568_ESMART0_REGION3_CBR_MST 0x18A8 311 #define RK3568_ESMART0_REGION3_VIR 0x18AC 312 #define RK3568_ESMART0_REGION3_ACT_INFO 0x18B0 313 #define RK3568_ESMART0_REGION3_DSP_INFO 0x18B4 314 #define RK3568_ESMART0_REGION3_DSP_ST 0x18B8 315 #define RK3568_ESMART0_REGION3_SCL_CTRL 0x18C0 316 #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 317 #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 318 #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC 319 320 #define RK3568_ESMART1_CTRL0 0x1A00 321 #define RK3568_ESMART1_CTRL1 0x1A04 322 #define RK3568_ESMART1_REGION0_CTRL 0x1A10 323 #define RK3568_ESMART1_REGION0_YRGB_MST 0x1A14 324 #define RK3568_ESMART1_REGION0_CBR_MST 0x1A18 325 #define RK3568_ESMART1_REGION0_VIR 0x1A1C 326 #define RK3568_ESMART1_REGION0_ACT_INFO 0x1A20 327 #define RK3568_ESMART1_REGION0_DSP_INFO 0x1A24 328 #define RK3568_ESMART1_REGION0_DSP_ST 0x1A28 329 #define RK3568_ESMART1_REGION0_SCL_CTRL 0x1A30 330 #define RK3568_ESMART1_REGION0_SCL_FACTOR_YRGB 0x1A34 331 #define RK3568_ESMART1_REGION0_SCL_FACTOR_CBR 0x1A38 332 #define RK3568_ESMART1_REGION0_SCL_OFFSET 0x1A3C 333 #define RK3568_ESMART1_REGION1_CTRL 0x1A40 334 #define RK3568_ESMART1_REGION1_YRGB_MST 0x1A44 335 #define RK3568_ESMART1_REGION1_CBR_MST 0x1A48 336 #define RK3568_ESMART1_REGION1_VIR 0x1A4C 337 #define RK3568_ESMART1_REGION1_ACT_INFO 0x1A50 338 #define RK3568_ESMART1_REGION1_DSP_INFO 0x1A54 339 #define RK3568_ESMART1_REGION1_DSP_ST 0x1A58 340 #define RK3568_ESMART1_REGION1_SCL_CTRL 0x1A60 341 #define RK3568_ESMART1_REGION1_SCL_FACTOR_YRGB 0x1A64 342 #define RK3568_ESMART1_REGION1_SCL_FACTOR_CBR 0x1A68 343 #define RK3568_ESMART1_REGION1_SCL_OFFSET 0x1A6C 344 #define RK3568_ESMART1_REGION2_CTRL 0x1A70 345 #define RK3568_ESMART1_REGION2_YRGB_MST 0x1A74 346 #define RK3568_ESMART1_REGION2_CBR_MST 0x1A78 347 #define RK3568_ESMART1_REGION2_VIR 0x1A7C 348 #define RK3568_ESMART1_REGION2_ACT_INFO 0x1A80 349 #define RK3568_ESMART1_REGION2_DSP_INFO 0x1A84 350 #define RK3568_ESMART1_REGION2_DSP_ST 0x1A88 351 #define RK3568_ESMART1_REGION2_SCL_CTRL 0x1A90 352 #define RK3568_ESMART1_REGION2_SCL_FACTOR_YRGB 0x1A94 353 #define RK3568_ESMART1_REGION2_SCL_FACTOR_CBR 0x1A98 354 #define RK3568_ESMART1_REGION2_SCL_OFFSET 0x1A9C 355 #define RK3568_ESMART1_REGION3_CTRL 0x1AA0 356 #define RK3568_ESMART1_REGION3_YRGB_MST 0x1AA4 357 #define RK3568_ESMART1_REGION3_CBR_MST 0x1AA8 358 #define RK3568_ESMART1_REGION3_VIR 0x1AAC 359 #define RK3568_ESMART1_REGION3_ACT_INFO 0x1AB0 360 #define RK3568_ESMART1_REGION3_DSP_INFO 0x1AB4 361 #define RK3568_ESMART1_REGION3_DSP_ST 0x1AB8 362 #define RK3568_ESMART1_REGION3_SCL_CTRL 0x1AC0 363 #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 364 #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 365 #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC 366 367 #define RK3568_SMART0_CTRL0 0x1C00 368 #define RK3568_SMART0_CTRL1 0x1C04 369 #define RK3568_SMART0_REGION0_CTRL 0x1C10 370 #define RK3568_SMART0_REGION0_YRGB_MST 0x1C14 371 #define RK3568_SMART0_REGION0_CBR_MST 0x1C18 372 #define RK3568_SMART0_REGION0_VIR 0x1C1C 373 #define RK3568_SMART0_REGION0_ACT_INFO 0x1C20 374 #define RK3568_SMART0_REGION0_DSP_INFO 0x1C24 375 #define RK3568_SMART0_REGION0_DSP_ST 0x1C28 376 #define RK3568_SMART0_REGION0_SCL_CTRL 0x1C30 377 #define RK3568_SMART0_REGION0_SCL_FACTOR_YRGB 0x1C34 378 #define RK3568_SMART0_REGION0_SCL_FACTOR_CBR 0x1C38 379 #define RK3568_SMART0_REGION0_SCL_OFFSET 0x1C3C 380 #define RK3568_SMART0_REGION1_CTRL 0x1C40 381 #define RK3568_SMART0_REGION1_YRGB_MST 0x1C44 382 #define RK3568_SMART0_REGION1_CBR_MST 0x1C48 383 #define RK3568_SMART0_REGION1_VIR 0x1C4C 384 #define RK3568_SMART0_REGION1_ACT_INFO 0x1C50 385 #define RK3568_SMART0_REGION1_DSP_INFO 0x1C54 386 #define RK3568_SMART0_REGION1_DSP_ST 0x1C58 387 #define RK3568_SMART0_REGION1_SCL_CTRL 0x1C60 388 #define RK3568_SMART0_REGION1_SCL_FACTOR_YRGB 0x1C64 389 #define RK3568_SMART0_REGION1_SCL_FACTOR_CBR 0x1C68 390 #define RK3568_SMART0_REGION1_SCL_OFFSET 0x1C6C 391 #define RK3568_SMART0_REGION2_CTRL 0x1C70 392 #define RK3568_SMART0_REGION2_YRGB_MST 0x1C74 393 #define RK3568_SMART0_REGION2_CBR_MST 0x1C78 394 #define RK3568_SMART0_REGION2_VIR 0x1C7C 395 #define RK3568_SMART0_REGION2_ACT_INFO 0x1C80 396 #define RK3568_SMART0_REGION2_DSP_INFO 0x1C84 397 #define RK3568_SMART0_REGION2_DSP_ST 0x1C88 398 #define RK3568_SMART0_REGION2_SCL_CTRL 0x1C90 399 #define RK3568_SMART0_REGION2_SCL_FACTOR_YRGB 0x1C94 400 #define RK3568_SMART0_REGION2_SCL_FACTOR_CBR 0x1C98 401 #define RK3568_SMART0_REGION2_SCL_OFFSET 0x1C9C 402 #define RK3568_SMART0_REGION3_CTRL 0x1CA0 403 #define RK3568_SMART0_REGION3_YRGB_MST 0x1CA4 404 #define RK3568_SMART0_REGION3_CBR_MST 0x1CA8 405 #define RK3568_SMART0_REGION3_VIR 0x1CAC 406 #define RK3568_SMART0_REGION3_ACT_INFO 0x1CB0 407 #define RK3568_SMART0_REGION3_DSP_INFO 0x1CB4 408 #define RK3568_SMART0_REGION3_DSP_ST 0x1CB8 409 #define RK3568_SMART0_REGION3_SCL_CTRL 0x1CC0 410 #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 411 #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 412 #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC 413 414 #define RK3568_SMART1_CTRL0 0x1E00 415 #define RK3568_SMART1_CTRL1 0x1E04 416 #define RK3568_SMART1_REGION0_CTRL 0x1E10 417 #define RK3568_SMART1_REGION0_YRGB_MST 0x1E14 418 #define RK3568_SMART1_REGION0_CBR_MST 0x1E18 419 #define RK3568_SMART1_REGION0_VIR 0x1E1C 420 #define RK3568_SMART1_REGION0_ACT_INFO 0x1E20 421 #define RK3568_SMART1_REGION0_DSP_INFO 0x1E24 422 #define RK3568_SMART1_REGION0_DSP_ST 0x1E28 423 #define RK3568_SMART1_REGION0_SCL_CTRL 0x1E30 424 #define RK3568_SMART1_REGION0_SCL_FACTOR_YRGB 0x1E34 425 #define RK3568_SMART1_REGION0_SCL_FACTOR_CBR 0x1E38 426 #define RK3568_SMART1_REGION0_SCL_OFFSET 0x1E3C 427 #define RK3568_SMART1_REGION1_CTRL 0x1E40 428 #define RK3568_SMART1_REGION1_YRGB_MST 0x1E44 429 #define RK3568_SMART1_REGION1_CBR_MST 0x1E48 430 #define RK3568_SMART1_REGION1_VIR 0x1E4C 431 #define RK3568_SMART1_REGION1_ACT_INFO 0x1E50 432 #define RK3568_SMART1_REGION1_DSP_INFO 0x1E54 433 #define RK3568_SMART1_REGION1_DSP_ST 0x1E58 434 #define RK3568_SMART1_REGION1_SCL_CTRL 0x1E60 435 #define RK3568_SMART1_REGION1_SCL_FACTOR_YRGB 0x1E64 436 #define RK3568_SMART1_REGION1_SCL_FACTOR_CBR 0x1E68 437 #define RK3568_SMART1_REGION1_SCL_OFFSET 0x1E6C 438 #define RK3568_SMART1_REGION2_CTRL 0x1E70 439 #define RK3568_SMART1_REGION2_YRGB_MST 0x1E74 440 #define RK3568_SMART1_REGION2_CBR_MST 0x1E78 441 #define RK3568_SMART1_REGION2_VIR 0x1E7C 442 #define RK3568_SMART1_REGION2_ACT_INFO 0x1E80 443 #define RK3568_SMART1_REGION2_DSP_INFO 0x1E84 444 #define RK3568_SMART1_REGION2_DSP_ST 0x1E88 445 #define RK3568_SMART1_REGION2_SCL_CTRL 0x1E90 446 #define RK3568_SMART1_REGION2_SCL_FACTOR_YRGB 0x1E94 447 #define RK3568_SMART1_REGION2_SCL_FACTOR_CBR 0x1E98 448 #define RK3568_SMART1_REGION2_SCL_OFFSET 0x1E9C 449 #define RK3568_SMART1_REGION3_CTRL 0x1EA0 450 #define RK3568_SMART1_REGION3_YRGB_MST 0x1EA4 451 #define RK3568_SMART1_REGION3_CBR_MST 0x1EA8 452 #define RK3568_SMART1_REGION3_VIR 0x1EAC 453 #define RK3568_SMART1_REGION3_ACT_INFO 0x1EB0 454 #define RK3568_SMART1_REGION3_DSP_INFO 0x1EB4 455 #define RK3568_SMART1_REGION3_DSP_ST 0x1EB8 456 #define RK3568_SMART1_REGION3_SCL_CTRL 0x1EC0 457 #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 458 #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 459 #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC 460 461 #define RK3568_MAX_REG 0x1ED0 462 463 #define VOP2_LAYER_MAX 8 464 #define VOP2_MAX_VP 4 465 466 enum vop2_csc_format { 467 CSC_BT601L, 468 CSC_BT709L, 469 CSC_BT601F, 470 CSC_BT2020, 471 }; 472 473 enum vop2_pol { 474 HSYNC_POSITIVE = 0, 475 VSYNC_POSITIVE = 1, 476 DEN_NEGATIVE = 2, 477 DCLK_INVERT = 3 478 }; 479 480 #define _VOP_REG(off, _mask, _shift, _write_mask) \ 481 { \ 482 .offset = off, \ 483 .mask = _mask, \ 484 .shift = _shift, \ 485 .write_mask = _write_mask, \ 486 } 487 488 #define VOP_REG(off, _mask, _shift) \ 489 _VOP_REG(off, _mask, _shift, false) 490 enum dither_down_mode { 491 RGB888_TO_RGB565 = 0x0, 492 RGB888_TO_RGB666 = 0x1 493 }; 494 495 struct vop2_reg { 496 uint32_t mask; 497 uint32_t offset:12; 498 uint32_t shift:5; 499 uint32_t write_mask:1; 500 }; 501 502 struct vop2_grf_ctrl { 503 struct vop2_reg dclk_inv; 504 }; 505 506 enum vop2_video_ports_id { 507 VOP2_VP0, 508 VOP2_VP1, 509 VOP2_VP2, 510 VOP2_VP3, 511 VOP2_VP_MAX, 512 }; 513 514 struct vop2_layer { 515 uint8_t id; 516 /** 517 * @win_phys_id: window id of the layer selected. 518 * Every layer must make sure to select different 519 * windows of others. 520 */ 521 uint8_t win_phys_id; 522 }; 523 524 struct vop2_win { 525 uint8_t id; 526 uint8_t layer_id; 527 uint8_t phys_id; 528 }; 529 530 struct vop2_data { 531 uint32_t version; 532 struct vop_rect max_output[VOP2_MAX_VP]; 533 /** 534 * win_id: id of window attach to VP0,VP1,VP2,VP3, 535 * Only support one window for one VP in u-boot. 536 * 537 */ 538 uint8_t win_id[VOP2_MAX_VP]; 539 uint8_t nr_vps; 540 uint8_t nr_layers; 541 /** 542 * win_sel_id: from register LAYER_SEL 543 * 544 */ 545 uint8_t win_sel_id[VOP2_LAYER_MAX]; 546 struct vop2_grf_ctrl *grf_ctrl; 547 }; 548 549 struct vop2 { 550 u32 *regsbak; 551 void *regs; 552 void *grf; 553 uint32_t reg_len; 554 uint32_t version; 555 const struct vop2_data *data; 556 /** 557 * @nr_wins: active wins attached to the video port 558 */ 559 uint8_t nr_wins[VOP2_VP_MAX]; 560 struct vop2_win win[VOP2_LAYER_MAX]; 561 struct vop2_layer layer[VOP2_LAYER_MAX]; 562 }; 563 564 static struct vop2 *rockchip_vop2; 565 static void vop2_setup_win_for_vp(struct display_state *state); 566 567 static inline uint16_t scl_cal_scale(int src, int dst, int shift) 568 { 569 return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 570 } 571 572 static inline uint16_t scl_cal_scale2(int src, int dst) 573 { 574 return ((src - 1) << 12) / (dst - 1); 575 } 576 577 static inline void vop2_writel(struct vop2 *vop2, uint32_t offset, uint32_t v) 578 { 579 writel(v, vop2->regs + offset); 580 vop2->regsbak[offset >> 2] = v; 581 } 582 583 static inline uint32_t vop2_readl(struct vop2 *vop2, uint32_t offset) 584 { 585 return readl(vop2->regs + offset); 586 } 587 588 static inline void vop2_mask_write(struct vop2 *vop2, uint32_t offset, 589 uint32_t mask, uint32_t shift, uint32_t v, 590 bool write_mask) 591 { 592 if (!mask) 593 return; 594 595 if (write_mask) { 596 v = ((v & mask) << shift) | (mask << (shift + 16)); 597 } else { 598 uint32_t cached_val = vop2->regsbak[offset >> 2]; 599 600 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 601 vop2->regsbak[offset >> 2] = v; 602 } 603 604 writel(v, vop2->regs + offset); 605 } 606 607 static inline int us_to_vertical_line(struct drm_display_mode *mode, int us) 608 { 609 return us * mode->clock / mode->htotal / 1000; 610 } 611 612 static bool is_yuv_output(uint32_t bus_format) 613 { 614 switch (bus_format) { 615 case MEDIA_BUS_FMT_YUV8_1X24: 616 case MEDIA_BUS_FMT_YUV10_1X30: 617 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 618 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 619 return true; 620 default: 621 return false; 622 } 623 } 624 625 static int vop2_convert_csc_mode(int csc_mode) 626 { 627 switch (csc_mode) { 628 case V4L2_COLORSPACE_SMPTE170M: 629 case V4L2_COLORSPACE_470_SYSTEM_M: 630 case V4L2_COLORSPACE_470_SYSTEM_BG: 631 return CSC_BT601L; 632 case V4L2_COLORSPACE_REC709: 633 case V4L2_COLORSPACE_SMPTE240M: 634 case V4L2_COLORSPACE_DEFAULT: 635 return CSC_BT709L; 636 case V4L2_COLORSPACE_JPEG: 637 return CSC_BT601F; 638 case V4L2_COLORSPACE_BT2020: 639 return CSC_BT2020; 640 default: 641 return CSC_BT709L; 642 } 643 } 644 645 static __maybe_unused bool is_uv_swap(uint32_t bus_format, uint32_t output_mode) 646 { 647 /* 648 * FIXME: 649 * 650 * There is no media type for YUV444 output, 651 * so when out_mode is AAAA or P888, assume output is YUV444 on 652 * yuv format. 653 * 654 * From H/W testing, YUV444 mode need a rb swap. 655 */ 656 if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 657 bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 658 (output_mode == ROCKCHIP_OUT_MODE_AAAA || 659 output_mode == ROCKCHIP_OUT_MODE_P888)) 660 return true; 661 else 662 return false; 663 } 664 665 static int rockchip_vop2_init_gamma(struct vop2 *vop2, 666 struct display_state *state) 667 { 668 return 0; 669 } 670 671 static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 672 { 673 struct connector_state *conn_state = &state->conn_state; 674 struct drm_display_mode *mode = &conn_state->mode; 675 u16 vtotal = mode->crtc_vtotal; 676 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 677 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 678 u16 hdisplay = mode->crtc_hdisplay; 679 u16 vdisplay = mode->crtc_vdisplay; 680 u16 hsize = 681 hdisplay * (conn_state->overscan.left_margin + 682 conn_state->overscan.right_margin) / 200; 683 u16 vsize = 684 vdisplay * (conn_state->overscan.top_margin + 685 conn_state->overscan.bottom_margin) / 200; 686 u16 hact_end, vact_end; 687 u32 val; 688 u16 nr_mixers = 5, used_layer = 2, pre_scan_max_dly = 40; 689 u32 bg_ovl_dly, bg_dly, pre_scan_dly; 690 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 691 692 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 693 vsize = round_down(vsize, 2); 694 695 hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 696 hact_end = hact_st + hsize; 697 val = hact_st << 16; 698 val |= hact_end; 699 700 vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO, val); 701 vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 702 vact_end = vact_st + vsize; 703 val = vact_st << 16; 704 val |= vact_end; 705 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO, val); 706 val = scl_cal_scale2(vdisplay, vsize) << 16; 707 val |= scl_cal_scale2(hdisplay, hsize); 708 vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB, val); 709 #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 710 #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 711 vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL, 712 POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 713 POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 714 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 715 u16 vact_st_f1 = vtotal + vact_st + 1; 716 u16 vact_end_f1 = vact_st_f1 + vsize; 717 718 val = vact_st_f1 << 16 | vact_end_f1; 719 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1, val); 720 } 721 722 bg_ovl_dly = (nr_mixers - used_layer) << 1; 723 bg_dly = pre_scan_max_dly - bg_ovl_dly; 724 pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 725 pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 726 vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING, pre_scan_dly); 727 } 728 729 static void vop2_layer_map_initial(struct vop2 *vop2) 730 { 731 struct vop2_layer *layer; 732 struct vop2_win *win; 733 uint32_t layer_map, sel; 734 int i, j; 735 736 layer_map = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 737 738 for (i = 0; i < vop2->data->nr_layers; i++) { 739 sel = (layer_map >> (4 * i)) & 0xf; 740 layer = &vop2->layer[i]; 741 win = NULL; 742 for (j = 0; j < vop2->data->nr_layers; j++) { 743 if (sel == vop2->data->win_sel_id[j]) { 744 win = &vop2->win[j]; 745 break; 746 } 747 } 748 749 if (!win) { 750 printf("invalid layer map :0x%x\n", layer_map); 751 return; 752 } 753 754 layer->win_phys_id = j; 755 win->layer_id = i; 756 debug("layer%d select %d\n", i, j); 757 } 758 } 759 760 static int vop2_initial(struct vop2 *vop2, struct display_state *state) 761 { 762 struct crtc_state *cstate = &state->crtc_state; 763 struct connector_state *conn_state = &state->conn_state; 764 struct drm_display_mode *mode = &conn_state->mode; 765 char dclk_name[9]; 766 struct clk dclk; 767 uint8_t shift = 0; 768 int i, ret; 769 770 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 771 ret = clk_set_defaults(cstate->dev); 772 if (ret) 773 debug("%s clk_set_defaults failed %d\n", __func__, ret); 774 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 775 ret = clk_get_by_name(cstate->dev, dclk_name, &dclk); 776 if (!ret) 777 ret = clk_set_rate(&dclk, mode->clock * 1000); 778 779 if (IS_ERR_VALUE(ret)) { 780 printf("%s: Failed to set dclk: ret=%d\n", __func__, ret); 781 return ret; 782 } 783 784 memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 785 786 rockchip_vop2_init_gamma(vop2, state); 787 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 788 OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 789 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 790 IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 791 for (i = 0; i < vop2->data->nr_vps - 1; i++) { 792 shift = i * 4; 793 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, PORT_MUX_SHIFT + shift, 8, false); //todo 794 } 795 796 vop2_layer_map_initial(vop2); 797 798 return 0; 799 } 800 801 /* 802 * VOP2 have multi video ports. 803 * video port ------- crtc 804 */ 805 static int rockchip_vop2_preinit(struct display_state *state) 806 { 807 struct crtc_state *cstate = &state->crtc_state; 808 const struct vop2_data *vop2_data = cstate->crtc->data; 809 810 if (!rockchip_vop2) { 811 rockchip_vop2 = malloc(sizeof(struct vop2)); 812 if (!rockchip_vop2) 813 return -ENOMEM; 814 rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 815 rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 816 rockchip_vop2->reg_len = RK3568_MAX_REG; 817 rockchip_vop2->grf = 818 syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 819 if (rockchip_vop2->grf <= 0) 820 printf("%s: Get syscon grf failed (ret=%p)\n", __func__, 821 rockchip_vop2->grf); 822 823 rockchip_vop2->version = vop2_data->version; 824 rockchip_vop2->data = vop2_data; 825 } 826 827 cstate->private = rockchip_vop2; 828 cstate->max_output = vop2_data->max_output[cstate->crtc_id]; 829 830 return 0; 831 } 832 833 static int rockchip_vop2_init(struct display_state *state) 834 { 835 struct crtc_state *cstate = &state->crtc_state; 836 struct connector_state *conn_state = &state->conn_state; 837 struct drm_display_mode *mode = &conn_state->mode; 838 //const struct rockchip_crtc *crtc = cstate->crtc; 839 //const struct vop2_data *vop2_data = crtc->data; 840 struct vop2 *vop2 = cstate->private; 841 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 842 u16 hdisplay = mode->crtc_hdisplay; 843 u16 htotal = mode->crtc_htotal; 844 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 845 u16 hact_end = hact_st + hdisplay; 846 u16 vdisplay = mode->crtc_vdisplay; 847 u16 vtotal = mode->crtc_vtotal; 848 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 849 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 850 u16 vact_end = vact_st + vdisplay; 851 bool yuv_overlay = false; 852 //bool yuv_overlay = false, post_r2y_en = false, post_y2r_en = false; 853 uint32_t vp_offset = (cstate->crtc_id * 0x100); 854 //struct clk dclk; 855 //fdt_size_t len; 856 u32 val; 857 //int ret; 858 bool dclk_inv; 859 uint8_t dither_down_en = 0; 860 uint8_t pre_dither_down_en = 0; 861 //uint8_t dither_down_mode = RGB888_TO_RGB666; 862 863 vop2_initial(vop2, state); 864 865 dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 866 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 867 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 868 869 if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 870 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 871 1, false); 872 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 873 RGB_MUX_SHIFT, cstate->crtc_id, false); 874 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 875 IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, ! !dclk_inv, 876 false); 877 //VOP2_GRF_SET(vop2, dclk_inv, dclk_inv); 878 } 879 880 if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 881 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 882 BT1120_EN_SHIFT, 1, false); 883 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 884 RGB_MUX_SHIFT, cstate->crtc_id, false); 885 } 886 887 if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 888 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 889 1, false); 890 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 891 RGB_MUX_SHIFT, cstate->crtc_id, false); 892 } 893 894 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 895 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 896 1, false); 897 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 898 LVDS0_MUX_SHIFT, cstate->crtc_id, false); 899 } 900 901 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 902 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 903 1, false); 904 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 905 LVDS1_MUX_SHIFT, cstate->crtc_id, false); 906 } 907 908 if (conn_state->output_flags & 909 (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 910 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 911 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 912 LVDS_DUAL_EN_SHIFT, 1, false); 913 if (conn_state->output_flags & 914 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 915 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 916 LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 917 false); 918 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 919 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 920 LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 921 } 922 923 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 924 //cstate->crtc_id = 0; 925 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 926 1, false); 927 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 928 MIPI0_MUX_SHIFT, cstate->crtc_id, false); 929 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 930 IF_CRTL_MIPI_DCLK_POL_SHIT, ! !dclk_inv, false); 931 } 932 933 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 934 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 935 1, false); 936 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 937 MIPI1_MUX_SHIFT, cstate->crtc_id, false); 938 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 939 IF_CRTL_MIPI_DCLK_POL_SHIT, ! !dclk_inv, false); 940 } 941 942 if (conn_state->output_flags & 943 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 944 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 945 MIPI_DUAL_EN_SHIFT, 1, false); 946 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 947 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 948 EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 949 false); 950 } 951 952 if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 953 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 954 1, false); 955 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 956 EDP0_MUX_SHIFT, cstate->crtc_id, false); 957 } 958 959 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 960 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 961 1, false); 962 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 963 HDMI0_MUX_SHIFT, cstate->crtc_id, false); 964 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 965 IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 966 vop2_mask_write(vop2, RK3568_DSP_IF_POL, 967 IF_CRTL_HDMI_PIN_POL_MASK, 968 IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 969 } 970 971 if (is_uv_swap(conn_state->bus_format, conn_state->output_mode)) 972 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 973 DATA_SWAP_MASK, DATA_SWAP_SHIFT, DSP_RB_SWAP, 974 false); 975 else 976 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 977 DATA_SWAP_MASK, DATA_SWAP_SHIFT, 0, 978 false); 979 980 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 981 OUT_MODE_SHIFT, conn_state->output_mode, false); 982 983 switch (conn_state->bus_format) { 984 case MEDIA_BUS_FMT_RGB565_1X16: 985 dither_down_en = 1; 986 break; 987 case MEDIA_BUS_FMT_RGB666_1X18: 988 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 989 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 990 case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: 991 dither_down_en = 1; 992 break; 993 case MEDIA_BUS_FMT_YUV8_1X24: 994 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 995 dither_down_en = 0; 996 pre_dither_down_en = 1; 997 break; 998 case MEDIA_BUS_FMT_YUV10_1X30: 999 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1000 case MEDIA_BUS_FMT_RGB888_1X24: 1001 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 1002 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 1003 default: 1004 dither_down_en = 0; 1005 pre_dither_down_en = 0; 1006 break; 1007 } 1008 1009 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA) 1010 pre_dither_down_en = 0; 1011 else 1012 pre_dither_down_en = 1; 1013 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1014 DITHER_DOWN_EN_SHIFT, dither_down_en, false); 1015 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1016 PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 1017 1018 yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 1019 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 1020 yuv_overlay, false); 1021 1022 cstate->yuv_overlay = yuv_overlay; 1023 1024 vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 1025 (htotal << 16) | hsync_len); 1026 val = hact_st << 16; 1027 val |= hact_end; 1028 vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 1029 val = vact_st << 16; 1030 val |= vact_end; 1031 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 1032 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1033 u16 vact_st_f1 = vtotal + vact_st + 1; 1034 u16 vact_end_f1 = vact_st_f1 + vdisplay; 1035 1036 val = vact_st_f1 << 16 | vact_end_f1; 1037 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 1038 val); 1039 1040 val = vtotal << 16 | (vtotal + vsync_len); 1041 vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 1042 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1043 INTERLACE_EN_SHIFT, 1, false); 1044 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1045 P2I_EN_SHIFT, 1, false); 1046 vtotal += vtotal + 1; 1047 } else { 1048 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1049 INTERLACE_EN_SHIFT, 0, false); 1050 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1051 P2I_EN_SHIFT, 0, false); 1052 } 1053 vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 1054 (vtotal << 16) | vsync_len); 1055 val = ! !(mode->flags & DRM_MODE_FLAG_DBLCLK); 1056 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1057 CORE_DCLK_DIV_EN_SHIFT, val, false); 1058 1059 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 1060 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, DCLK_DIV2_MASK, 1061 DCLK_DIV2_SHIFT, 0x3, false); 1062 else 1063 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, DCLK_DIV2_MASK, 1064 DCLK_DIV2_SHIFT, 0, false); 1065 1066 if (yuv_overlay) 1067 val = 0x20010200; 1068 else 1069 val = 0; 1070 vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 1071 1072 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1073 POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 1074 1075 vop2_post_config(state, vop2); 1076 vop2_setup_win_for_vp(state); 1077 1078 return 0; 1079 } 1080 1081 static void vop2_setup_win_for_vp(struct display_state *state) 1082 { 1083 struct crtc_state *cstate = &state->crtc_state; 1084 const struct rockchip_crtc *crtc = cstate->crtc; 1085 const struct vop2_data *vop2_data = crtc->data; 1086 struct vop2 *vop2 = cstate->private; 1087 u8 port_id = cstate->crtc_id; 1088 struct vop2_win *win; 1089 struct vop2_layer *layer; 1090 u8 used_layers = 0; 1091 u8 layer_id, win_phys_id, win_sel_id; 1092 u8 shift; 1093 int i; 1094 1095 for (i = 0; i < port_id; i++) 1096 used_layers += vop2->nr_wins[i]; 1097 1098 vop2->nr_wins[port_id]++; 1099 /* 1100 * Win and layer must map one by one, if a win is selected 1101 * by two layers, unexpected error may happen. 1102 * So when we attach a new win to a layer, we also move the 1103 * old win of the layer to the layer where the new win comes from. 1104 * 1105 */ 1106 layer = &vop2->layer[used_layers]; 1107 win = &vop2->win[port_id]; 1108 shift = port_id * 2; 1109 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 1110 LAYER_SEL_PORT_SHIFT + shift, port_id, false); 1111 shift = used_layers * 4; 1112 win_phys_id = vop2->data->win_id[port_id]; 1113 win_sel_id = vop2->data->win_sel_id[win_phys_id]; 1114 vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_PORT_MASK, shift, 1115 win_sel_id, false); 1116 layer_id = win->layer_id; 1117 win_phys_id = layer->win_phys_id; 1118 win->layer_id = layer->id; 1119 layer->win_phys_id = win->phys_id; 1120 layer = &vop2->layer[layer_id]; 1121 win = &vop2->win[win_phys_id]; 1122 shift = layer_id * 4; 1123 win_sel_id = vop2->data->win_sel_id[win_phys_id]; 1124 vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_PORT_MASK, shift, 1125 win_sel_id, false); 1126 win->layer_id = layer_id; 1127 layer->win_phys_id = win_phys_id; 1128 1129 if (port_id == (vop2_data->nr_vps - 1)) 1130 used_layers = vop2_data->nr_layers; 1131 shift = port_id * 4; 1132 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, shift, 1133 used_layers, false); 1134 1135 vop2_writel(vop2, 0x604, 0x54760312); 1136 vop2_writel(vop2, 0x608, 0x84000781); 1137 vop2_writel(vop2, 0x6e0, 0x22000000); 1138 } 1139 1140 static int rockchip_vop2_set_plane(struct display_state *state) 1141 { 1142 struct crtc_state *cstate = &state->crtc_state; 1143 struct connector_state *conn_state = &state->conn_state; 1144 struct drm_display_mode *mode = &conn_state->mode; 1145 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 1146 struct vop2 *vop2 = cstate->private; 1147 int src_w = cstate->src_w; 1148 int src_h = cstate->src_h; 1149 int crtc_x = cstate->crtc_x; 1150 int crtc_y = cstate->crtc_y; 1151 int crtc_w = cstate->crtc_w; 1152 int crtc_h = cstate->crtc_h; 1153 int xvir = cstate->xvir; 1154 int y_mirror = 0; 1155 int csc_mode; 1156 uint32_t win_offset = cstate->crtc_id * 0x200; 1157 uint32_t cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id); 1158 1159 if (crtc_w > cstate->max_output.width) { 1160 printf("ERROR: output w[%d] exceeded max width[%d]\n", 1161 crtc_w, cstate->max_output.width); 1162 return -EINVAL; 1163 } 1164 1165 act_info = (src_h - 1) << 16; 1166 act_info |= (src_w - 1) & 0xffff; 1167 1168 dsp_info = (crtc_h - 1) << 16; 1169 dsp_info |= (crtc_w - 1) & 0xffff; 1170 1171 dsp_stx = crtc_x; 1172 dsp_sty = crtc_y; 1173 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 1174 1175 if (mode->flags & DRM_MODE_FLAG_YMIRROR) 1176 y_mirror = 1; 1177 else 1178 y_mirror = 0; 1179 1180 if (y_mirror) 1181 cstate->dma_addr += (src_h - 1) * xvir * 4; 1182 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 1183 YMIRROR_EN_SHIFT, y_mirror, false); 1184 1185 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 1186 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 1187 false); 1188 vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 1189 vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 1190 cstate->dma_addr); 1191 1192 vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 1193 act_info); 1194 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 1195 dsp_info); 1196 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 1197 1198 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 1199 WIN_EN_SHIFT, 1, false); 1200 1201 csc_mode = vop2_convert_csc_mode(conn_state->color_space); 1202 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 1203 RGB2YUV_EN_SHIFT, 1204 is_yuv_output(conn_state->bus_format), false); 1205 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 1206 CSC_MODE_SHIFT, csc_mode, false); 1207 1208 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 1209 return 0; 1210 } 1211 1212 static int rockchip_vop2_prepare(struct display_state *state) 1213 { 1214 return 0; 1215 } 1216 1217 static int rockchip_vop2_enable(struct display_state *state) 1218 { 1219 struct crtc_state *cstate = &state->crtc_state; 1220 struct vop2 *vop2 = cstate->private; 1221 uint32_t vp_offset = (cstate->crtc_id * 0x100); 1222 uint32_t cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id); 1223 1224 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1225 STANDBY_EN_SHIFT, 0, false); 1226 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 1227 1228 return 0; 1229 } 1230 1231 static int rockchip_vop2_disable(struct display_state *state) 1232 { 1233 struct crtc_state *cstate = &state->crtc_state; 1234 struct vop2 *vop2 = cstate->private; 1235 uint32_t vp_offset = (cstate->crtc_id * 0x100); 1236 uint32_t cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id); 1237 1238 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1239 STANDBY_EN_SHIFT, 1, false); 1240 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 1241 1242 return 0; 1243 } 1244 1245 const struct vop2_data rk3568_vop = { 1246 .nr_vps = 3, 1247 .max_output = { 1248 [VOP2_VP0] = {4096, 2304}, 1249 [VOP2_VP1] = {2048, 1536}, 1250 [VOP2_VP2] = {1920, 1080}, 1251 }, 1252 1253 /* 1254 * Cluster0-Win0: 0 1255 * Cluster1-Win0: 1 1256 * Esmart0-Win0: 2 1257 * Esmart1-Win0: 3 1258 * Smart0-Win0: 4 1259 * Smart1-Win0: 5 1260 */ 1261 .win_id = { 1262 [VOP2_VP0] = 2, 1263 [VOP2_VP1] = 3, 1264 [VOP2_VP2] = 4, 1265 }, 1266 1267 /** 1268 * Win select id: from register LAYER_SEL 1269 * 1270 * Cluster0-Win0: 0 1271 * Cluster1-Win0: 1 1272 * Esmart0-Win0: 2 1273 * Esmart1-Win0: 6 1274 * Smart0-Win0: 3 1275 * Smart1-Win0: 7 1276 */ 1277 .win_sel_id = {0, 1, 2, 6, 3, 7}, 1278 .nr_layers = 6, 1279 }; 1280 1281 const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 1282 .preinit = rockchip_vop2_preinit, 1283 .prepare = rockchip_vop2_prepare, 1284 .init = rockchip_vop2_init, 1285 .set_plane = rockchip_vop2_set_plane, 1286 .enable = rockchip_vop2_enable, 1287 .disable = rockchip_vop2_disable, 1288 }; 1289