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 RK3568_GRF_VO_CON1 0x0364 464 #define GRF_BT656_CLK_INV_SHIFT 1 465 #define GRF_BT1120_CLK_INV_SHIFT 2 466 #define GRF_RGB_DCLK_INV_SHIFT 3 467 468 #define VOP2_LAYER_MAX 8 469 #define VOP2_MAX_VP 4 470 471 enum vop2_csc_format { 472 CSC_BT601L, 473 CSC_BT709L, 474 CSC_BT601F, 475 CSC_BT2020, 476 }; 477 478 enum vop2_pol { 479 HSYNC_POSITIVE = 0, 480 VSYNC_POSITIVE = 1, 481 DEN_NEGATIVE = 2, 482 DCLK_INVERT = 3 483 }; 484 485 #define _VOP_REG(off, _mask, _shift, _write_mask) \ 486 { \ 487 .offset = off, \ 488 .mask = _mask, \ 489 .shift = _shift, \ 490 .write_mask = _write_mask, \ 491 } 492 493 #define VOP_REG(off, _mask, _shift) \ 494 _VOP_REG(off, _mask, _shift, false) 495 enum dither_down_mode { 496 RGB888_TO_RGB565 = 0x0, 497 RGB888_TO_RGB666 = 0x1 498 }; 499 500 enum vop2_video_ports_id { 501 VOP2_VP0, 502 VOP2_VP1, 503 VOP2_VP2, 504 VOP2_VP3, 505 VOP2_VP_MAX, 506 }; 507 508 struct vop2_layer { 509 uint8_t id; 510 /** 511 * @win_phys_id: window id of the layer selected. 512 * Every layer must make sure to select different 513 * windows of others. 514 */ 515 uint8_t win_phys_id; 516 }; 517 518 struct vop2_win { 519 uint8_t id; 520 uint8_t layer_id; 521 uint8_t phys_id; 522 }; 523 524 struct vop2_data { 525 u32 version; 526 struct vop_rect max_output[VOP2_MAX_VP]; 527 /** 528 * win_id: id of window attach to VP0,VP1,VP2,VP3, 529 * Only support one window for one VP in u-boot. 530 * 531 */ 532 uint8_t win_id[VOP2_MAX_VP]; 533 uint8_t nr_vps; 534 uint8_t nr_layers; 535 /** 536 * win_sel_id: from register LAYER_SEL 537 * 538 */ 539 uint8_t win_sel_id[VOP2_LAYER_MAX]; 540 }; 541 542 struct vop2 { 543 u32 *regsbak; 544 void *regs; 545 void *grf; 546 u32 reg_len; 547 u32 version; 548 const struct vop2_data *data; 549 /** 550 * @nr_wins: active wins attached to the video port 551 */ 552 uint8_t nr_wins[VOP2_VP_MAX]; 553 struct vop2_win win[VOP2_LAYER_MAX]; 554 struct vop2_layer layer[VOP2_LAYER_MAX]; 555 }; 556 557 static struct vop2 *rockchip_vop2; 558 static void vop2_setup_win_for_vp(struct display_state *state); 559 560 static inline uint16_t scl_cal_scale(int src, int dst, int shift) 561 { 562 return ((src * 2 - 3) << (shift - 1)) / (dst - 1); 563 } 564 565 static inline uint16_t scl_cal_scale2(int src, int dst) 566 { 567 return ((src - 1) << 12) / (dst - 1); 568 } 569 570 static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) 571 { 572 writel(v, vop2->regs + offset); 573 vop2->regsbak[offset >> 2] = v; 574 } 575 576 static inline u32 vop2_readl(struct vop2 *vop2, u32 offset) 577 { 578 return readl(vop2->regs + offset); 579 } 580 581 static inline void vop2_mask_write(struct vop2 *vop2, u32 offset, 582 u32 mask, u32 shift, u32 v, 583 bool write_mask) 584 { 585 if (!mask) 586 return; 587 588 if (write_mask) { 589 v = ((v & mask) << shift) | (mask << (shift + 16)); 590 } else { 591 u32 cached_val = vop2->regsbak[offset >> 2]; 592 593 v = (cached_val & ~(mask << shift)) | ((v & mask) << shift); 594 vop2->regsbak[offset >> 2] = v; 595 } 596 597 writel(v, vop2->regs + offset); 598 } 599 600 static inline void vop2_grf_writel(struct vop2 *vop, u32 offset, 601 u32 mask, u32 shift, u32 v) 602 { 603 u32 val = 0; 604 605 val = (v << shift) | (mask << (shift + 16)); 606 writel(val, vop->grf + offset); 607 } 608 609 static inline int us_to_vertical_line(struct drm_display_mode *mode, int us) 610 { 611 return us * mode->clock / mode->htotal / 1000; 612 } 613 614 static bool is_yuv_output(u32 bus_format) 615 { 616 switch (bus_format) { 617 case MEDIA_BUS_FMT_YUV8_1X24: 618 case MEDIA_BUS_FMT_YUV10_1X30: 619 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 620 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 621 return true; 622 default: 623 return false; 624 } 625 } 626 627 static int vop2_convert_csc_mode(int csc_mode) 628 { 629 switch (csc_mode) { 630 case V4L2_COLORSPACE_SMPTE170M: 631 case V4L2_COLORSPACE_470_SYSTEM_M: 632 case V4L2_COLORSPACE_470_SYSTEM_BG: 633 return CSC_BT601L; 634 case V4L2_COLORSPACE_REC709: 635 case V4L2_COLORSPACE_SMPTE240M: 636 case V4L2_COLORSPACE_DEFAULT: 637 return CSC_BT709L; 638 case V4L2_COLORSPACE_JPEG: 639 return CSC_BT601F; 640 case V4L2_COLORSPACE_BT2020: 641 return CSC_BT2020; 642 default: 643 return CSC_BT709L; 644 } 645 } 646 647 static __maybe_unused bool is_uv_swap(u32 bus_format, u32 output_mode) 648 { 649 /* 650 * FIXME: 651 * 652 * There is no media type for YUV444 output, 653 * so when out_mode is AAAA or P888, assume output is YUV444 on 654 * yuv format. 655 * 656 * From H/W testing, YUV444 mode need a rb swap. 657 */ 658 if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || 659 bus_format == MEDIA_BUS_FMT_YUV10_1X30) && 660 (output_mode == ROCKCHIP_OUT_MODE_AAAA || 661 output_mode == ROCKCHIP_OUT_MODE_P888)) 662 return true; 663 else 664 return false; 665 } 666 667 static int rockchip_vop2_init_gamma(struct vop2 *vop2, 668 struct display_state *state) 669 { 670 return 0; 671 } 672 673 static void vop2_post_config(struct display_state *state, struct vop2 *vop2) 674 { 675 struct connector_state *conn_state = &state->conn_state; 676 struct drm_display_mode *mode = &conn_state->mode; 677 struct crtc_state *cstate = &state->crtc_state; 678 u32 vp_offset = (cstate->crtc_id * 0x100); 679 u16 vtotal = mode->crtc_vtotal; 680 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 681 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 682 u16 hdisplay = mode->crtc_hdisplay; 683 u16 vdisplay = mode->crtc_vdisplay; 684 u16 hsize = 685 hdisplay * (conn_state->overscan.left_margin + 686 conn_state->overscan.right_margin) / 200; 687 u16 vsize = 688 vdisplay * (conn_state->overscan.top_margin + 689 conn_state->overscan.bottom_margin) / 200; 690 u16 hact_end, vact_end; 691 u32 val; 692 u16 nr_mixers = 5, used_layer = 2, pre_scan_max_dly; 693 u32 bg_ovl_dly, bg_dly, pre_scan_dly; 694 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 695 696 if (cstate->crtc_id == 0) 697 pre_scan_max_dly = 69; 698 else 699 pre_scan_max_dly = 40; 700 701 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 702 vsize = round_down(vsize, 2); 703 704 hact_st += hdisplay * (100 - conn_state->overscan.left_margin) / 200; 705 hact_end = hact_st + hsize; 706 val = hact_st << 16; 707 val |= hact_end; 708 709 vop2_writel(vop2, RK3568_VP0_POST_DSP_HACT_INFO + vp_offset, val); 710 vact_st += vdisplay * (100 - conn_state->overscan.top_margin) / 200; 711 vact_end = vact_st + vsize; 712 val = vact_st << 16; 713 val |= vact_end; 714 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO + vp_offset, val); 715 val = scl_cal_scale2(vdisplay, vsize) << 16; 716 val |= scl_cal_scale2(hdisplay, hsize); 717 vop2_writel(vop2, RK3568_VP0_POST_SCL_FACTOR_YRGB + vp_offset, val); 718 #define POST_HORIZONTAL_SCALEDOWN_EN(x) ((x) << 0) 719 #define POST_VERTICAL_SCALEDOWN_EN(x) ((x) << 1) 720 vop2_writel(vop2, RK3568_VP0_POST_SCL_CTRL + vp_offset, 721 POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) | 722 POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize)); 723 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 724 u16 vact_st_f1 = vtotal + vact_st + 1; 725 u16 vact_end_f1 = vact_st_f1 + vsize; 726 727 val = vact_st_f1 << 16 | vact_end_f1; 728 vop2_writel(vop2, RK3568_VP0_POST_DSP_VACT_INFO_F1 + vp_offset, val); 729 } 730 731 bg_ovl_dly = (nr_mixers - used_layer) << 1; 732 bg_dly = pre_scan_max_dly - bg_ovl_dly; 733 pre_scan_dly = bg_dly + (hdisplay >> 1) - 1; 734 pre_scan_dly = (pre_scan_dly << 16) | hsync_len; 735 vop2_writel(vop2, RK3568_VP0_PRE_SCAN_HTIMING + vp_offset, pre_scan_dly); 736 } 737 738 static void vop2_layer_map_initial(struct vop2 *vop2) 739 { 740 struct vop2_layer *layer; 741 struct vop2_win *win; 742 u32 layer_map, sel; 743 int i, j; 744 745 layer_map = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 746 747 for (i = 0; i < vop2->data->nr_layers; i++) { 748 sel = (layer_map >> (4 * i)) & 0xf; 749 layer = &vop2->layer[i]; 750 win = NULL; 751 for (j = 0; j < vop2->data->nr_layers; j++) { 752 if (sel == vop2->data->win_sel_id[j]) { 753 win = &vop2->win[j]; 754 break; 755 } 756 } 757 758 if (!win) { 759 printf("invalid layer map :0x%x\n", layer_map); 760 return; 761 } 762 763 layer->win_phys_id = j; 764 win->layer_id = i; 765 debug("layer%d select %d\n", i, j); 766 } 767 } 768 769 static int vop2_initial(struct vop2 *vop2, struct display_state *state) 770 { 771 struct crtc_state *cstate = &state->crtc_state; 772 struct connector_state *conn_state = &state->conn_state; 773 struct drm_display_mode *mode = &conn_state->mode; 774 char dclk_name[9]; 775 struct clk dclk; 776 uint8_t shift = 0; 777 int i, ret; 778 779 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ 780 ret = clk_set_defaults(cstate->dev); 781 if (ret) 782 debug("%s clk_set_defaults failed %d\n", __func__, ret); 783 snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", cstate->crtc_id); 784 ret = clk_get_by_name(cstate->dev, dclk_name, &dclk); 785 if (!ret) 786 ret = clk_set_rate(&dclk, mode->clock * 1000); 787 788 if (IS_ERR_VALUE(ret)) { 789 printf("%s: Failed to set dclk: ret=%d\n", __func__, ret); 790 return ret; 791 } 792 793 memcpy(vop2->regsbak, vop2->regs, vop2->reg_len); 794 795 rockchip_vop2_init_gamma(vop2, state); 796 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, 797 OVL_PORT_MUX_REG_DONE_IMD_SHIFT, 1, false); 798 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 799 IF_CTRL_REG_DONE_IMD_SHIFT, 1, false); 800 for (i = 0; i < vop2->data->nr_vps - 1; i++) { 801 shift = i * 4; 802 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, PORT_MUX_SHIFT + shift, 8, false); //todo 803 } 804 805 vop2_layer_map_initial(vop2); 806 807 return 0; 808 } 809 810 /* 811 * VOP2 have multi video ports. 812 * video port ------- crtc 813 */ 814 static int rockchip_vop2_preinit(struct display_state *state) 815 { 816 struct crtc_state *cstate = &state->crtc_state; 817 const struct vop2_data *vop2_data = cstate->crtc->data; 818 819 if (!rockchip_vop2) { 820 rockchip_vop2 = malloc(sizeof(struct vop2)); 821 if (!rockchip_vop2) 822 return -ENOMEM; 823 rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); 824 rockchip_vop2->regsbak = malloc(RK3568_MAX_REG); 825 rockchip_vop2->reg_len = RK3568_MAX_REG; 826 rockchip_vop2->grf = 827 syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 828 if (rockchip_vop2->grf <= 0) 829 printf("%s: Get syscon grf failed (ret=%p)\n", __func__, 830 rockchip_vop2->grf); 831 832 rockchip_vop2->version = vop2_data->version; 833 rockchip_vop2->data = vop2_data; 834 } 835 836 cstate->private = rockchip_vop2; 837 cstate->max_output = vop2_data->max_output[cstate->crtc_id]; 838 839 return 0; 840 } 841 842 static int rockchip_vop2_init(struct display_state *state) 843 { 844 struct crtc_state *cstate = &state->crtc_state; 845 struct connector_state *conn_state = &state->conn_state; 846 struct drm_display_mode *mode = &conn_state->mode; 847 //const struct rockchip_crtc *crtc = cstate->crtc; 848 //const struct vop2_data *vop2_data = crtc->data; 849 struct vop2 *vop2 = cstate->private; 850 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 851 u16 hdisplay = mode->crtc_hdisplay; 852 u16 htotal = mode->crtc_htotal; 853 u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; 854 u16 hact_end = hact_st + hdisplay; 855 u16 vdisplay = mode->crtc_vdisplay; 856 u16 vtotal = mode->crtc_vtotal; 857 u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 858 u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; 859 u16 vact_end = vact_st + vdisplay; 860 bool yuv_overlay = false; 861 //bool yuv_overlay = false, post_r2y_en = false, post_y2r_en = false; 862 u32 vp_offset = (cstate->crtc_id * 0x100); 863 //struct clk dclk; 864 //fdt_size_t len; 865 u32 val; 866 //int ret; 867 bool dclk_inv; 868 uint8_t dither_down_en = 0; 869 uint8_t pre_dither_down_en = 0; 870 //uint8_t dither_down_mode = RGB888_TO_RGB666; 871 872 vop2_initial(vop2, state); 873 dclk_inv = (mode->flags & DRM_MODE_FLAG_PPIXDATA) ? 0 : 1; 874 val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); 875 val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); 876 877 if (conn_state->output_if & VOP_OUTPUT_IF_RGB) { 878 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 879 1, false); 880 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 881 RGB_MUX_SHIFT, cstate->crtc_id, false); 882 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 883 IF_CRTL_RGB_LVDS_DCLK_POL_SHIT, !!dclk_inv, 884 false); 885 vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK, 886 GRF_RGB_DCLK_INV_SHIFT, !dclk_inv); 887 } 888 889 if (conn_state->output_if & VOP_OUTPUT_IF_BT1120) { 890 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, RGB_EN_SHIFT, 891 1, false); 892 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, 893 BT1120_EN_SHIFT, 1, false); 894 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 895 RGB_MUX_SHIFT, cstate->crtc_id, false); 896 vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK, 897 GRF_BT1120_CLK_INV_SHIFT, !dclk_inv); 898 } 899 900 if (conn_state->output_if & VOP_OUTPUT_IF_BT656) { 901 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, BT656_EN_SHIFT, 902 1, false); 903 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 904 RGB_MUX_SHIFT, cstate->crtc_id, false); 905 vop2_grf_writel(vop2, RK3568_GRF_VO_CON1, EN_MASK, 906 GRF_BT656_CLK_INV_SHIFT, !dclk_inv); 907 } 908 909 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS0) { 910 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS0_EN_SHIFT, 911 1, false); 912 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 913 LVDS0_MUX_SHIFT, cstate->crtc_id, false); 914 } 915 916 if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { 917 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, LVDS1_EN_SHIFT, 918 1, false); 919 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 920 LVDS1_MUX_SHIFT, cstate->crtc_id, false); 921 } 922 923 if (conn_state->output_flags & 924 (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | 925 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { 926 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 927 LVDS_DUAL_EN_SHIFT, 1, false); 928 if (conn_state->output_flags & 929 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) 930 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 931 LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, 932 false); 933 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 934 vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, 935 LVDS_DUAL_SWAP_EN_SHIFT, 1, false); 936 } 937 938 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { 939 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, 940 1, false); 941 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 942 MIPI0_MUX_SHIFT, cstate->crtc_id, false); 943 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 944 IF_CRTL_MIPI_DCLK_POL_SHIT, ! !dclk_inv, false); 945 } 946 947 if (conn_state->output_if & VOP_OUTPUT_IF_MIPI1) { 948 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI1_EN_SHIFT, 949 1, false); 950 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 951 MIPI1_MUX_SHIFT, cstate->crtc_id, false); 952 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 953 IF_CRTL_MIPI_DCLK_POL_SHIT, ! !dclk_inv, false); 954 } 955 956 if (conn_state->output_flags & 957 ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { 958 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, 959 MIPI_DUAL_EN_SHIFT, 1, false); 960 if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) 961 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, 962 EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, 963 false); 964 } 965 966 if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { 967 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, 968 1, false); 969 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 970 EDP0_MUX_SHIFT, cstate->crtc_id, false); 971 } 972 973 if (conn_state->output_if & VOP_OUTPUT_IF_HDMI0) { 974 vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, HDMI0_EN_SHIFT, 975 1, false); 976 vop2_mask_write(vop2, RK3568_DSP_IF_EN, IF_MUX_MASK, 977 HDMI0_MUX_SHIFT, cstate->crtc_id, false); 978 vop2_mask_write(vop2, RK3568_DSP_IF_POL, EN_MASK, 979 IF_CRTL_HDMI_DCLK_POL_SHIT, 1, false); 980 vop2_mask_write(vop2, RK3568_DSP_IF_POL, 981 IF_CRTL_HDMI_PIN_POL_MASK, 982 IF_CRTL_HDMI_PIN_POL_SHIT, val, false); 983 } 984 985 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && cstate->crtc_id != 0) 986 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 987 988 if (is_uv_swap(conn_state->bus_format, conn_state->output_mode)) 989 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 990 DATA_SWAP_MASK, DATA_SWAP_SHIFT, DSP_RB_SWAP, 991 false); 992 else 993 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, 994 DATA_SWAP_MASK, DATA_SWAP_SHIFT, 0, 995 false); 996 997 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, OUT_MODE_MASK, 998 OUT_MODE_SHIFT, conn_state->output_mode, false); 999 1000 switch (conn_state->bus_format) { 1001 case MEDIA_BUS_FMT_RGB565_1X16: 1002 dither_down_en = 1; 1003 break; 1004 case MEDIA_BUS_FMT_RGB666_1X18: 1005 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 1006 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 1007 case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: 1008 dither_down_en = 1; 1009 break; 1010 case MEDIA_BUS_FMT_YUV8_1X24: 1011 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 1012 dither_down_en = 0; 1013 pre_dither_down_en = 1; 1014 break; 1015 case MEDIA_BUS_FMT_YUV10_1X30: 1016 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 1017 case MEDIA_BUS_FMT_RGB888_1X24: 1018 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 1019 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 1020 default: 1021 dither_down_en = 0; 1022 pre_dither_down_en = 0; 1023 break; 1024 } 1025 1026 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA) 1027 pre_dither_down_en = 0; 1028 else 1029 pre_dither_down_en = 1; 1030 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1031 DITHER_DOWN_EN_SHIFT, dither_down_en, false); 1032 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1033 PRE_DITHER_DOWN_EN_SHIFT, pre_dither_down_en, false); 1034 1035 yuv_overlay = is_yuv_output(conn_state->bus_format) ? 1 : 0; 1036 vop2_mask_write(vop2, RK3568_OVL_CTRL, EN_MASK, cstate->crtc_id, 1037 yuv_overlay, false); 1038 1039 cstate->yuv_overlay = yuv_overlay; 1040 1041 vop2_writel(vop2, RK3568_VP0_DSP_HTOTAL_HS_END + vp_offset, 1042 (htotal << 16) | hsync_len); 1043 val = hact_st << 16; 1044 val |= hact_end; 1045 vop2_writel(vop2, RK3568_VP0_DSP_HACT_ST_END + vp_offset, val); 1046 val = vact_st << 16; 1047 val |= vact_end; 1048 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END + vp_offset, val); 1049 if (mode->flags & DRM_MODE_FLAG_INTERLACE) { 1050 u16 vact_st_f1 = vtotal + vact_st + 1; 1051 u16 vact_end_f1 = vact_st_f1 + vdisplay; 1052 1053 val = vact_st_f1 << 16 | vact_end_f1; 1054 vop2_writel(vop2, RK3568_VP0_DSP_VACT_ST_END_F1 + vp_offset, 1055 val); 1056 1057 val = vtotal << 16 | (vtotal + vsync_len); 1058 vop2_writel(vop2, RK3568_VP0_DSP_VS_ST_END_F1 + vp_offset, val); 1059 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1060 INTERLACE_EN_SHIFT, 1, false); 1061 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1062 P2I_EN_SHIFT, 1, false); 1063 vtotal += vtotal + 1; 1064 } else { 1065 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1066 INTERLACE_EN_SHIFT, 0, false); 1067 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1068 P2I_EN_SHIFT, 0, false); 1069 } 1070 vop2_writel(vop2, RK3568_VP0_DSP_VTOTAL_VS_END + vp_offset, 1071 (vtotal << 16) | vsync_len); 1072 val = ! !(mode->flags & DRM_MODE_FLAG_DBLCLK); 1073 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1074 CORE_DCLK_DIV_EN_SHIFT, val, false); 1075 1076 if (conn_state->output_mode == ROCKCHIP_OUT_MODE_YUV420) 1077 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, DCLK_DIV2_MASK, 1078 DCLK_DIV2_SHIFT, 0x3, false); 1079 else 1080 vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, DCLK_DIV2_MASK, 1081 DCLK_DIV2_SHIFT, 0, false); 1082 1083 if (yuv_overlay) 1084 val = 0x20010200; 1085 else 1086 val = 0; 1087 vop2_writel(vop2, RK3568_VP0_DSP_BG + vp_offset, val); 1088 1089 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1090 POST_DSP_OUT_R2Y_SHIFT, yuv_overlay, false); 1091 1092 vop2_post_config(state, vop2); 1093 vop2_setup_win_for_vp(state); 1094 1095 return 0; 1096 } 1097 1098 static void vop2_setup_win_for_vp(struct display_state *state) 1099 { 1100 struct crtc_state *cstate = &state->crtc_state; 1101 const struct rockchip_crtc *crtc = cstate->crtc; 1102 const struct vop2_data *vop2_data = crtc->data; 1103 struct vop2 *vop2 = cstate->private; 1104 u8 port_id = cstate->crtc_id; 1105 struct vop2_win *win; 1106 struct vop2_layer *layer; 1107 u8 used_layers = 0; 1108 u8 layer_id, win_phys_id, win_sel_id; 1109 u8 shift; 1110 int i; 1111 1112 for (i = 0; i < port_id; i++) 1113 used_layers += vop2->nr_wins[i]; 1114 1115 vop2->nr_wins[port_id]++; 1116 /* 1117 * Win and layer must map one by one, if a win is selected 1118 * by two layers, unexpected error may happen. 1119 * So when we attach a new win to a layer, we also move the 1120 * old win of the layer to the layer where the new win comes from. 1121 * 1122 */ 1123 layer = &vop2->layer[used_layers]; 1124 win = &vop2->win[port_id]; 1125 shift = port_id * 2; 1126 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, LAYER_SEL_PORT_MASK, 1127 LAYER_SEL_PORT_SHIFT + shift, port_id, false); 1128 shift = used_layers * 4; 1129 win_phys_id = vop2->data->win_id[port_id]; 1130 win_sel_id = vop2->data->win_sel_id[win_phys_id]; 1131 vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_PORT_MASK, shift, 1132 win_sel_id, false); 1133 layer_id = win->layer_id; 1134 win_phys_id = layer->win_phys_id; 1135 win->layer_id = layer->id; 1136 layer->win_phys_id = win->phys_id; 1137 layer = &vop2->layer[layer_id]; 1138 win = &vop2->win[win_phys_id]; 1139 shift = layer_id * 4; 1140 win_sel_id = vop2->data->win_sel_id[win_phys_id]; 1141 vop2_mask_write(vop2, RK3568_OVL_LAYER_SEL, LAYER_SEL_PORT_MASK, shift, 1142 win_sel_id, false); 1143 win->layer_id = layer_id; 1144 layer->win_phys_id = win_phys_id; 1145 1146 if (port_id == (vop2_data->nr_vps - 1)) 1147 used_layers = vop2_data->nr_layers; 1148 shift = port_id * 4; 1149 vop2_mask_write(vop2, RK3568_OVL_PORT_SEL, PORT_MUX_MASK, shift, 1150 used_layers, false); 1151 1152 if (port_id == 0) { 1153 vop2_writel(vop2, 0x604, 0x54760123); 1154 vop2_writel(vop2, 0x608, 0x00000755); 1155 vop2_writel(vop2, 0x6e0, 0x2a000000); 1156 } else { 1157 vop2_writel(vop2, 0x604, 0x54760312); 1158 vop2_writel(vop2, 0x608, 0x55050728); 1159 vop2_writel(vop2, 0x6e4, 0x1e000000); 1160 } 1161 } 1162 1163 static int rockchip_vop2_set_plane(struct display_state *state) 1164 { 1165 struct crtc_state *cstate = &state->crtc_state; 1166 struct connector_state *conn_state = &state->conn_state; 1167 struct drm_display_mode *mode = &conn_state->mode; 1168 u32 act_info, dsp_info, dsp_st, dsp_stx, dsp_sty; 1169 struct vop2 *vop2 = cstate->private; 1170 int src_w = cstate->src_w; 1171 int src_h = cstate->src_h; 1172 int crtc_x = cstate->crtc_x; 1173 int crtc_y = cstate->crtc_y; 1174 int crtc_w = cstate->crtc_w; 1175 int crtc_h = cstate->crtc_h; 1176 int xvir = cstate->xvir; 1177 int y_mirror = 0; 1178 int csc_mode; 1179 u32 win_offset; 1180 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id); 1181 1182 if (cstate->crtc_id == 1) 1183 win_offset = 0x400; /* port 1 use smart0*/ 1184 else 1185 win_offset = 0; /* port 0 use esmart0*/ 1186 1187 if (crtc_w > cstate->max_output.width) { 1188 printf("ERROR: output w[%d] exceeded max width[%d]\n", 1189 crtc_w, cstate->max_output.width); 1190 return -EINVAL; 1191 } 1192 1193 act_info = (src_h - 1) << 16; 1194 act_info |= (src_w - 1) & 0xffff; 1195 1196 dsp_info = (crtc_h - 1) << 16; 1197 dsp_info |= (crtc_w - 1) & 0xffff; 1198 1199 dsp_stx = crtc_x; 1200 dsp_sty = crtc_y; 1201 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 1202 1203 if (mode->flags & DRM_MODE_FLAG_YMIRROR) 1204 y_mirror = 1; 1205 else 1206 y_mirror = 0; 1207 1208 if (y_mirror) 1209 cstate->dma_addr += (src_h - 1) * xvir * 4; 1210 vop2_mask_write(vop2, RK3568_ESMART0_CTRL1 + win_offset, EN_MASK, 1211 YMIRROR_EN_SHIFT, y_mirror, false); 1212 1213 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, 1214 WIN_FORMAT_MASK, WIN_FORMAT_SHIFT, cstate->format, 1215 false); 1216 vop2_writel(vop2, RK3568_ESMART0_REGION0_VIR + win_offset, xvir); 1217 vop2_writel(vop2, RK3568_ESMART0_REGION0_YRGB_MST + win_offset, 1218 cstate->dma_addr); 1219 1220 vop2_writel(vop2, RK3568_ESMART0_REGION0_ACT_INFO + win_offset, 1221 act_info); 1222 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_INFO + win_offset, 1223 dsp_info); 1224 vop2_writel(vop2, RK3568_ESMART0_REGION0_DSP_ST + win_offset, dsp_st); 1225 1226 vop2_mask_write(vop2, RK3568_ESMART0_REGION0_CTRL + win_offset, EN_MASK, 1227 WIN_EN_SHIFT, 1, false); 1228 1229 csc_mode = vop2_convert_csc_mode(conn_state->color_space); 1230 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, EN_MASK, 1231 RGB2YUV_EN_SHIFT, 1232 is_yuv_output(conn_state->bus_format), false); 1233 vop2_mask_write(vop2, RK3568_ESMART0_CTRL0 + win_offset, CSC_MODE_MASK, 1234 CSC_MODE_SHIFT, csc_mode, false); 1235 1236 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 1237 return 0; 1238 } 1239 1240 static int rockchip_vop2_prepare(struct display_state *state) 1241 { 1242 return 0; 1243 } 1244 1245 static int rockchip_vop2_enable(struct display_state *state) 1246 { 1247 struct crtc_state *cstate = &state->crtc_state; 1248 struct vop2 *vop2 = cstate->private; 1249 u32 vp_offset = (cstate->crtc_id * 0x100); 1250 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id); 1251 1252 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1253 STANDBY_EN_SHIFT, 0, false); 1254 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 1255 1256 return 0; 1257 } 1258 1259 static int rockchip_vop2_disable(struct display_state *state) 1260 { 1261 struct crtc_state *cstate = &state->crtc_state; 1262 struct vop2 *vop2 = cstate->private; 1263 u32 vp_offset = (cstate->crtc_id * 0x100); 1264 u32 cfg_done = CFG_DONE_EN | BIT(cstate->crtc_id); 1265 1266 vop2_mask_write(vop2, RK3568_VP0_DSP_CTRL + vp_offset, EN_MASK, 1267 STANDBY_EN_SHIFT, 1, false); 1268 vop2_writel(vop2, RK3568_REG_CFG_DONE, cfg_done); 1269 1270 return 0; 1271 } 1272 1273 const struct vop2_data rk3568_vop = { 1274 .nr_vps = 3, 1275 .max_output = { 1276 [VOP2_VP0] = {4096, 2304}, 1277 [VOP2_VP1] = {2048, 1536}, 1278 [VOP2_VP2] = {1920, 1080}, 1279 }, 1280 1281 /* 1282 * Cluster0-Win0: 0 1283 * Cluster1-Win0: 1 1284 * Esmart0-Win0: 2 1285 * Esmart1-Win0: 3 1286 * Smart0-Win0: 4 1287 * Smart1-Win0: 5 1288 */ 1289 .win_id = { 1290 [VOP2_VP0] = 2, 1291 [VOP2_VP1] = 3, 1292 [VOP2_VP2] = 4, 1293 }, 1294 1295 /** 1296 * Win select id: from register LAYER_SEL 1297 * 1298 * Cluster0-Win0: 0 1299 * Cluster1-Win0: 1 1300 * Esmart0-Win0: 2 1301 * Esmart1-Win0: 6 1302 * Smart0-Win0: 3 1303 * Smart1-Win0: 7 1304 */ 1305 .win_sel_id = {0, 1, 2, 6, 3, 7}, 1306 .nr_layers = 6, 1307 }; 1308 1309 const struct rockchip_crtc_funcs rockchip_vop2_funcs = { 1310 .preinit = rockchip_vop2_preinit, 1311 .prepare = rockchip_vop2_prepare, 1312 .init = rockchip_vop2_init, 1313 .set_plane = rockchip_vop2_set_plane, 1314 .enable = rockchip_vop2_enable, 1315 .disable = rockchip_vop2_disable, 1316 }; 1317