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