xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_display.c (revision c6d8e6aac063eabd956f25ad0e4c1531dd59f385)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <asm/unaligned.h>
8 #include <boot_rkimg.h>
9 #include <config.h>
10 #include <common.h>
11 #include <errno.h>
12 #include <linux/libfdt.h>
13 #include <fdtdec.h>
14 #include <fdt_support.h>
15 #include <linux/hdmi.h>
16 #include <linux/list.h>
17 #include <linux/compat.h>
18 #include <linux/media-bus-format.h>
19 #include <malloc.h>
20 #include <video.h>
21 #include <video_rockchip.h>
22 #include <video_bridge.h>
23 #include <dm/device.h>
24 #include <dm/uclass-internal.h>
25 #include <asm/arch-rockchip/resource_img.h>
26 
27 #include "bmp_helper.h"
28 #include "rockchip_display.h"
29 #include "rockchip_crtc.h"
30 #include "rockchip_connector.h"
31 #include "rockchip_bridge.h"
32 #include "rockchip_phy.h"
33 #include "rockchip_panel.h"
34 #include <dm.h>
35 #include <dm/of_access.h>
36 #include <dm/ofnode.h>
37 #include <asm/io.h>
38 
39 #define DRIVER_VERSION	"v1.0.1"
40 
41 /***********************************************************************
42  *  Rockchip UBOOT DRM driver version
43  *
44  *  v1.0.0	: add basic version for rockchip drm driver(hjc)
45  *  v1.0.1	: add much dsi update(hjc)
46  *
47  **********************************************************************/
48 
49 #define RK_BLK_SIZE 512
50 #define BMP_PROCESSED_FLAG 8399
51 
52 DECLARE_GLOBAL_DATA_PTR;
53 static LIST_HEAD(rockchip_display_list);
54 static LIST_HEAD(logo_cache_list);
55 
56 static unsigned long memory_start;
57 static unsigned long cubic_lut_memory_start;
58 static unsigned long memory_end;
59 static struct base2_info base_parameter;
60 static u32 align_size = PAGE_SIZE;
61 
62 /*
63  * the phy types are used by different connectors in public.
64  * The current version only has inno hdmi phy for hdmi and tve.
65  */
66 enum public_use_phy {
67 	NONE,
68 	INNO_HDMI_PHY
69 };
70 
71 /* save public phy data */
72 struct public_phy_data {
73 	const struct rockchip_phy *phy_drv;
74 	int phy_node;
75 	int public_phy_type;
76 	bool phy_init;
77 };
78 
79 char* rockchip_get_output_if_name(u32 output_if, char *name)
80 {
81 	if (output_if & VOP_OUTPUT_IF_RGB)
82 		strcat(name, " RGB");
83 	if (output_if & VOP_OUTPUT_IF_BT1120)
84 		strcat(name, " BT1120");
85 	if (output_if & VOP_OUTPUT_IF_BT656)
86 		strcat(name, " BT656");
87 	if (output_if & VOP_OUTPUT_IF_LVDS0)
88 		strcat(name, " LVDS0");
89 	if (output_if & VOP_OUTPUT_IF_LVDS1)
90 		strcat(name, " LVDS1");
91 	if (output_if & VOP_OUTPUT_IF_MIPI0)
92 		strcat(name, " MIPI0");
93 	if (output_if & VOP_OUTPUT_IF_MIPI1)
94 		strcat(name, " MIPI1");
95 	if (output_if & VOP_OUTPUT_IF_eDP0)
96 		strcat(name, " eDP0");
97 	if (output_if & VOP_OUTPUT_IF_eDP1)
98 		strcat(name, " eDP1");
99 	if (output_if & VOP_OUTPUT_IF_DP0)
100 		strcat(name, " DP0");
101 	if (output_if & VOP_OUTPUT_IF_DP1)
102 		strcat(name, " DP1");
103 	if (output_if & VOP_OUTPUT_IF_HDMI0)
104 		strcat(name, " HDMI0");
105 	if (output_if & VOP_OUTPUT_IF_HDMI1)
106 		strcat(name, " HDMI1");
107 
108 	return name;
109 }
110 
111 u32 rockchip_drm_get_cycles_per_pixel(u32 bus_format)
112 {
113 	switch (bus_format) {
114 	case MEDIA_BUS_FMT_RGB565_1X16:
115 	case MEDIA_BUS_FMT_RGB666_1X18:
116 	case MEDIA_BUS_FMT_RGB888_1X24:
117 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
118 		return 1;
119 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
120 	case MEDIA_BUS_FMT_BGR565_2X8_LE:
121 		return 2;
122 	case MEDIA_BUS_FMT_RGB666_3X6:
123 	case MEDIA_BUS_FMT_RGB888_3X8:
124 	case MEDIA_BUS_FMT_BGR888_3X8:
125 		return 3;
126 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
127 	case MEDIA_BUS_FMT_BGR888_DUMMY_4X8:
128 		return 4;
129 	default:
130 		return 1;
131 	}
132 }
133 
134 int rockchip_get_baseparameter(void)
135 {
136 	struct blk_desc *dev_desc;
137 	disk_partition_t part_info;
138 	int block_num = 2048;
139 	char baseparameter_buf[block_num * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
140 	int ret = 0;
141 
142 	dev_desc = rockchip_get_bootdev();
143 	if (!dev_desc) {
144 		printf("%s: Could not find device\n", __func__);
145 		return -ENOENT;
146 	}
147 
148 	if (part_get_info_by_name(dev_desc, "baseparameter", &part_info) < 0) {
149 		printf("Could not find baseparameter partition\n");
150 		return -ENOENT;
151 	}
152 
153 	ret = blk_dread(dev_desc, part_info.start, block_num, (void *)baseparameter_buf);
154 	if (ret < 0) {
155 		printf("read baseparameter failed\n");
156 		return ret;
157 	}
158 
159 	memcpy(&base_parameter, baseparameter_buf, sizeof(base_parameter));
160 	if (strncasecmp(base_parameter.head_flag, "BASP", 4)) {
161 		printf("warning: bad baseparameter\n");
162 		memset(&base_parameter, 0, sizeof(base_parameter));
163 	}
164 	rockchip_display_make_crc32_table();
165 
166 	return ret;
167 }
168 
169 struct base2_disp_info *rockchip_get_disp_info(int type, int id)
170 {
171 	struct base2_disp_info *disp_info;
172 	struct base2_disp_header *disp_header;
173 	int i = 0, offset = -1;
174 	u32 crc_val;
175 	u32 base2_length;
176 	void *base_parameter_addr = (void *)&base_parameter;
177 
178 	for (i = 0; i < 8; i++) {
179 		disp_header = &base_parameter.disp_header[i];
180 		if (disp_header->connector_type == type &&
181 		    disp_header->connector_id == id) {
182 			printf("disp info %d, type:%d, id:%d\n", i, type, id);
183 			offset = disp_header->offset;
184 			break;
185 		}
186 	}
187 
188 	if (offset < 0)
189 		return NULL;
190 	disp_info = base_parameter_addr + offset;
191 	if (disp_info->screen_info[0].type != type ||
192 	    disp_info->screen_info[0].id != id) {
193 		printf("base2_disp_info couldn't be found, screen_info type[%d] or id[%d] mismatched\n",
194 		       disp_info->screen_info[0].type,
195 		       disp_info->screen_info[0].id);
196 		return NULL;
197 	}
198 
199 	if (strncasecmp(disp_info->disp_head_flag, "DISP", 4))
200 		return NULL;
201 
202 	if (base_parameter.major_version == 3 && base_parameter.minor_version == 0) {
203 		crc_val = rockchip_display_crc32c_cal((unsigned char *)disp_info,
204 						      sizeof(struct base2_disp_info) - 4);
205 		if (crc_val != disp_info->crc2) {
206 			printf("error: connector type[%d], id[%d] disp info crc2 check error\n",
207 			       type, id);
208 			return NULL;
209 		}
210 	} else {
211 		base2_length = sizeof(struct base2_disp_info) - sizeof(struct csc_info) -
212 			       sizeof(struct acm_data) - 10 * 1024 - 4;
213 		crc_val = rockchip_display_crc32c_cal((unsigned char *)disp_info, base2_length - 4);
214 		if (crc_val != disp_info->crc) {
215 			printf("error: connector type[%d], id[%d] disp info crc check error\n",
216 			       type, id);
217 			return NULL;
218 		}
219 	}
220 
221 	return disp_info;
222 }
223 
224 /* check which kind of public phy does connector use */
225 static int check_public_use_phy(struct rockchip_connector *conn)
226 {
227 	int ret = NONE;
228 #ifdef CONFIG_ROCKCHIP_INNO_HDMI_PHY
229 
230 	if (!strncmp(dev_read_name(conn->dev), "tve", 3) ||
231 	    !strncmp(dev_read_name(conn->dev), "hdmi", 4))
232 		ret = INNO_HDMI_PHY;
233 #endif
234 
235 	return ret;
236 }
237 
238 /*
239  * get public phy driver and initialize it.
240  * The current version only has inno hdmi phy for hdmi and tve.
241  */
242 static int get_public_phy(struct rockchip_connector *conn,
243 			  struct public_phy_data *data)
244 {
245 	struct rockchip_phy *phy;
246 	struct udevice *dev;
247 	int ret = 0;
248 
249 	switch (data->public_phy_type) {
250 	case INNO_HDMI_PHY:
251 #if defined(CONFIG_ROCKCHIP_RK3328)
252 		ret = uclass_get_device_by_name(UCLASS_PHY,
253 						"hdmiphy@ff430000", &dev);
254 #elif defined(CONFIG_ROCKCHIP_RK322X)
255 		ret = uclass_get_device_by_name(UCLASS_PHY,
256 						"hdmi-phy@12030000", &dev);
257 #else
258 		ret = -EINVAL;
259 #endif
260 		if (ret) {
261 			printf("Warn: can't find phy driver\n");
262 			return 0;
263 		}
264 
265 		phy = (struct rockchip_phy *)dev_get_driver_data(dev);
266 		if (!phy) {
267 			printf("failed to get phy driver\n");
268 			return 0;
269 		}
270 
271 		ret = rockchip_phy_init(phy);
272 		if (ret) {
273 			printf("failed to init phy driver\n");
274 			return ret;
275 		}
276 		conn->phy = phy;
277 
278 		debug("inno hdmi phy init success, save it\n");
279 		data->phy_drv = conn->phy;
280 		data->phy_init = true;
281 		return 0;
282 	default:
283 		return -EINVAL;
284 	}
285 }
286 
287 static void init_display_buffer(ulong base)
288 {
289 	memory_start = ALIGN(base + DRM_ROCKCHIP_FB_SIZE, align_size);
290 	memory_end = memory_start;
291 	cubic_lut_memory_start = ALIGN(memory_start + MEMORY_POOL_SIZE, align_size);
292 }
293 
294 void *get_display_buffer(int size)
295 {
296 	unsigned long roundup_memory = roundup(memory_end, PAGE_SIZE);
297 	void *buf;
298 
299 	if (roundup_memory + size > memory_start + MEMORY_POOL_SIZE) {
300 		printf("failed to alloc %dbyte memory to display\n", size);
301 		return NULL;
302 	}
303 	buf = (void *)roundup_memory;
304 
305 	memory_end = roundup_memory + size;
306 
307 	return buf;
308 }
309 
310 static unsigned long get_display_size(void)
311 {
312 	return memory_end - memory_start;
313 }
314 
315 static unsigned long get_single_cubic_lut_size(void)
316 {
317 	ulong cubic_lut_size;
318 	int cubic_lut_step = CONFIG_ROCKCHIP_CUBIC_LUT_SIZE;
319 
320 	/* This is depend on IC designed */
321 	cubic_lut_size = (cubic_lut_step * cubic_lut_step * cubic_lut_step + 1) / 2 * 16;
322 	cubic_lut_size = roundup(cubic_lut_size, PAGE_SIZE);
323 
324 	return cubic_lut_size;
325 }
326 
327 static unsigned long get_cubic_lut_offset(int crtc_id)
328 {
329 	return crtc_id * get_single_cubic_lut_size();
330 }
331 
332 unsigned long get_cubic_lut_buffer(int crtc_id)
333 {
334 	return cubic_lut_memory_start + crtc_id * get_single_cubic_lut_size();
335 }
336 
337 static unsigned long get_cubic_memory_size(void)
338 {
339 	/* Max support 4 cubic lut */
340 	return get_single_cubic_lut_size() * 4;
341 }
342 
343 bool can_direct_logo(int bpp)
344 {
345 	return bpp == 16 || bpp == 32;
346 }
347 
348 static int connector_phy_init(struct rockchip_connector *conn,
349 			      struct public_phy_data *data)
350 {
351 	int type;
352 
353 	/* does this connector use public phy with others */
354 	type = check_public_use_phy(conn);
355 	if (type == INNO_HDMI_PHY) {
356 		/* there is no public phy was initialized */
357 		if (!data->phy_init) {
358 			debug("start get public phy\n");
359 			data->public_phy_type = type;
360 			if (get_public_phy(conn, data)) {
361 				printf("can't find correct public phy type\n");
362 				free(data);
363 				return -EINVAL;
364 			}
365 			return 0;
366 		}
367 
368 		/* if this phy has been initialized, get it directly */
369 		conn->phy = (struct rockchip_phy *)data->phy_drv;
370 		return 0;
371 	}
372 
373 	return 0;
374 }
375 
376 int rockchip_ofnode_get_display_mode(ofnode node, struct drm_display_mode *mode, u32 *bus_flags)
377 {
378 	int hactive, vactive, pixelclock;
379 	int hfront_porch, hback_porch, hsync_len;
380 	int vfront_porch, vback_porch, vsync_len;
381 	int val, flags = 0;
382 
383 #define FDT_GET_BOOL(val, name) \
384 	val = ofnode_read_bool(node, name);
385 
386 #define FDT_GET_INT(val, name) \
387 	val = ofnode_read_s32_default(node, name, -1); \
388 	if (val < 0) { \
389 		printf("Can't get %s\n", name); \
390 		return -ENXIO; \
391 	}
392 
393 #define FDT_GET_INT_DEFAULT(val, name, default) \
394 	val = ofnode_read_s32_default(node, name, default);
395 
396 	FDT_GET_INT(hactive, "hactive");
397 	FDT_GET_INT(vactive, "vactive");
398 	FDT_GET_INT(pixelclock, "clock-frequency");
399 	FDT_GET_INT(hsync_len, "hsync-len");
400 	FDT_GET_INT(hfront_porch, "hfront-porch");
401 	FDT_GET_INT(hback_porch, "hback-porch");
402 	FDT_GET_INT(vsync_len, "vsync-len");
403 	FDT_GET_INT(vfront_porch, "vfront-porch");
404 	FDT_GET_INT(vback_porch, "vback-porch");
405 	FDT_GET_INT(val, "hsync-active");
406 	flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
407 	FDT_GET_INT(val, "vsync-active");
408 	flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
409 
410 	FDT_GET_BOOL(val, "interlaced");
411 	flags |= val ? DRM_MODE_FLAG_INTERLACE : 0;
412 	FDT_GET_BOOL(val, "doublescan");
413 	flags |= val ? DRM_MODE_FLAG_DBLSCAN : 0;
414 	FDT_GET_BOOL(val, "doubleclk");
415 	flags |= val ? DISPLAY_FLAGS_DOUBLECLK : 0;
416 
417 	FDT_GET_INT(val, "de-active");
418 	*bus_flags |= val ? DRM_BUS_FLAG_DE_HIGH : DRM_BUS_FLAG_DE_LOW;
419 	FDT_GET_INT(val, "pixelclk-active");
420 	*bus_flags |= val ? DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE : DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
421 
422 	FDT_GET_INT_DEFAULT(val, "screen-rotate", 0);
423 	if (val == DRM_MODE_FLAG_XMIRROR) {
424 		flags |= DRM_MODE_FLAG_XMIRROR;
425 	} else if (val == DRM_MODE_FLAG_YMIRROR) {
426 		flags |= DRM_MODE_FLAG_YMIRROR;
427 	} else if (val == DRM_MODE_FLAG_XYMIRROR) {
428 		flags |= DRM_MODE_FLAG_XMIRROR;
429 		flags |= DRM_MODE_FLAG_YMIRROR;
430 	}
431 	mode->hdisplay = hactive;
432 	mode->hsync_start = mode->hdisplay + hfront_porch;
433 	mode->hsync_end = mode->hsync_start + hsync_len;
434 	mode->htotal = mode->hsync_end + hback_porch;
435 
436 	mode->vdisplay = vactive;
437 	mode->vsync_start = mode->vdisplay + vfront_porch;
438 	mode->vsync_end = mode->vsync_start + vsync_len;
439 	mode->vtotal = mode->vsync_end + vback_porch;
440 
441 	mode->clock = pixelclock / 1000;
442 	mode->flags = flags;
443 	mode->vrefresh = drm_mode_vrefresh(mode);
444 
445 	return 0;
446 }
447 
448 static int display_get_force_timing_from_dts(ofnode node,
449 					     struct drm_display_mode *mode,
450 					     u32 *bus_flags)
451 {
452 	int ret = 0;
453 
454 	ret = rockchip_ofnode_get_display_mode(node, mode, bus_flags);
455 
456 	if (ret) {
457 		mode->clock = 74250;
458 		mode->flags = 0x5;
459 		mode->hdisplay = 1280;
460 		mode->hsync_start = 1390;
461 		mode->hsync_end = 1430;
462 		mode->htotal = 1650;
463 		mode->hskew = 0;
464 		mode->vdisplay = 720;
465 		mode->vsync_start = 725;
466 		mode->vsync_end = 730;
467 		mode->vtotal = 750;
468 		mode->vrefresh = 60;
469 		mode->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
470 		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
471 	}
472 
473 	printf("route node %s force_timing, use %dx%dp%d as default mode\n",
474 	       ret ? "undefine" : "define", mode->hdisplay, mode->vdisplay,
475 	       mode->vscan);
476 
477 	return 0;
478 }
479 
480 static int display_get_timing_from_dts(struct rockchip_panel *panel,
481 				       struct drm_display_mode *mode,
482 				       u32 *bus_flags)
483 {
484 	struct ofnode_phandle_args args;
485 	ofnode dt, timing, mcu_panel;
486 	int ret;
487 
488 	mcu_panel = dev_read_subnode(panel->dev, "mcu-panel");
489 	dt = dev_read_subnode(panel->dev, "display-timings");
490 	if (ofnode_valid(dt)) {
491 		ret = ofnode_parse_phandle_with_args(dt, "native-mode", NULL,
492 						     0, 0, &args);
493 		if (ret)
494 			return ret;
495 
496 		timing = args.node;
497 	} else if (ofnode_valid(mcu_panel)) {
498 		dt = ofnode_find_subnode(mcu_panel, "display-timings");
499 		ret = ofnode_parse_phandle_with_args(dt, "native-mode", NULL,
500 						     0, 0, &args);
501 		if (ret)
502 			return ret;
503 
504 		timing = args.node;
505 	} else {
506 		timing = dev_read_subnode(panel->dev, "panel-timing");
507 	}
508 
509 	if (!ofnode_valid(timing)) {
510 		printf("failed to get display timings from DT\n");
511 		return -ENXIO;
512 	}
513 
514 	rockchip_ofnode_get_display_mode(timing, mode, bus_flags);
515 
516 	if (IS_ENABLED(CONFIG_ROCKCHIP_RK3568) || IS_ENABLED(CONFIG_ROCKCHIP_RK3588)) {
517 		if (mode->hdisplay % 4) {
518 			int old_hdisplay = mode->hdisplay;
519 			int align = 4 - (mode->hdisplay % 4);
520 
521 			mode->hdisplay += align;
522 			mode->hsync_start += align;
523 			mode->hsync_end += align;
524 			mode->htotal += align;
525 
526 			ofnode_write_u32_array(timing, "hactive", (u32 *)&mode->hdisplay, 1);
527 
528 			printf("WARN: hactive need to be aligned with 4-pixel, %d -> %d\n",
529 				old_hdisplay, mode->hdisplay);
530 		}
531 	}
532 
533 	return 0;
534 }
535 
536 static int display_get_timing(struct display_state *state)
537 {
538 	struct connector_state *conn_state = &state->conn_state;
539 	struct drm_display_mode *mode = &conn_state->mode;
540 	const struct drm_display_mode *m;
541 	struct rockchip_panel *panel = conn_state->connector->panel;
542 
543 	if (panel->funcs->get_mode)
544 		return panel->funcs->get_mode(panel, mode);
545 
546 	if (dev_of_valid(panel->dev) &&
547 	    !display_get_timing_from_dts(panel, mode, &conn_state->bus_flags)) {
548 		printf("Using display timing dts\n");
549 		return 0;
550 	}
551 
552 	if (panel->data) {
553 		m = (const struct drm_display_mode *)panel->data;
554 		memcpy(mode, m, sizeof(*m));
555 		printf("Using display timing from compatible panel driver\n");
556 		return 0;
557 	}
558 
559 	return -ENODEV;
560 }
561 
562 static int display_pre_init(void)
563 {
564 	struct display_state *state;
565 	int ret = 0;
566 
567 	list_for_each_entry(state, &rockchip_display_list, head) {
568 		struct connector_state *conn_state = &state->conn_state;
569 		struct crtc_state *crtc_state = &state->crtc_state;
570 		struct rockchip_crtc *crtc = crtc_state->crtc;
571 
572 		ret = rockchip_connector_pre_init(state);
573 		if (ret)
574 			printf("pre init conn error\n");
575 
576 		crtc->vps[crtc_state->crtc_id].output_type = conn_state->type;
577 	}
578 	return ret;
579 }
580 
581 static int display_use_force_mode(struct display_state *state)
582 {
583 	struct connector_state *conn_state = &state->conn_state;
584 	struct drm_display_mode *mode = &conn_state->mode;
585 
586 	conn_state->bpc = 8;
587 	memcpy(mode, &state->force_mode, sizeof(struct drm_display_mode));
588 	conn_state->bus_format = state->force_bus_format;
589 
590 	return 0;
591 }
592 
593 static int display_get_edid_mode(struct display_state *state)
594 {
595 	int ret = 0;
596 	struct connector_state *conn_state = &state->conn_state;
597 	struct drm_display_mode *mode = &conn_state->mode;
598 	int bpc;
599 
600 	ret = edid_get_drm_mode(conn_state->edid, sizeof(conn_state->edid), mode, &bpc);
601 	if (!ret) {
602 		conn_state->bpc = bpc;
603 		edid_print_info((void *)&conn_state->edid);
604 	} else {
605 		conn_state->bpc = 8;
606 		mode->clock = 74250;
607 		mode->flags = 0x5;
608 		mode->hdisplay = 1280;
609 		mode->hsync_start = 1390;
610 		mode->hsync_end = 1430;
611 		mode->htotal = 1650;
612 		mode->hskew = 0;
613 		mode->vdisplay = 720;
614 		mode->vsync_start = 725;
615 		mode->vsync_end = 730;
616 		mode->vtotal = 750;
617 		mode->vrefresh = 60;
618 		mode->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
619 		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
620 
621 		printf("error: %s get mode from edid failed, use 720p60 as default mode\n",
622 		       state->conn_state.connector->dev->name);
623 	}
624 
625 	return ret;
626 }
627 
628 static int display_mode_valid(struct display_state *state)
629 {
630 	struct connector_state *conn_state = &state->conn_state;
631 	struct rockchip_connector *conn = conn_state->connector;
632 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
633 	struct crtc_state *crtc_state = &state->crtc_state;
634 	const struct rockchip_crtc *crtc = crtc_state->crtc;
635 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
636 	int ret;
637 
638 	if (conn_funcs->mode_valid && state->enabled_at_spl == false) {
639 		ret = conn_funcs->mode_valid(conn, state);
640 		if (ret)
641 			return ret;
642 	}
643 
644 	if (crtc_funcs->mode_valid) {
645 		ret = crtc_funcs->mode_valid(state);
646 		if (ret)
647 			return ret;
648 	}
649 
650 	return 0;
651 }
652 
653 static int display_mode_fixup(struct display_state *state)
654 {
655 	struct crtc_state *crtc_state = &state->crtc_state;
656 	const struct rockchip_crtc *crtc = crtc_state->crtc;
657 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
658 	int ret;
659 
660 	if (crtc_funcs->mode_fixup) {
661 		ret = crtc_funcs->mode_fixup(state);
662 		if (ret)
663 			return ret;
664 	}
665 
666 	return 0;
667 }
668 
669 static int display_init(struct display_state *state)
670 {
671 	struct connector_state *conn_state = &state->conn_state;
672 	struct rockchip_connector *conn = conn_state->connector;
673 	struct crtc_state *crtc_state = &state->crtc_state;
674 	struct rockchip_crtc *crtc = crtc_state->crtc;
675 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
676 	struct drm_display_mode *mode = &conn_state->mode;
677 	const char *compatible;
678 	int ret = 0;
679 	static bool __print_once = false;
680 #ifdef CONFIG_SPL_BUILD
681 	struct spl_display_info *spl_disp_info = (struct spl_display_info *)CONFIG_SPL_VIDEO_BUF;
682 #endif
683 	if (!__print_once) {
684 		__print_once = true;
685 		printf("Rockchip UBOOT DRM driver version: %s\n", DRIVER_VERSION);
686 	}
687 
688 	if (state->is_init)
689 		return 0;
690 
691 	if (!crtc_funcs) {
692 		printf("failed to find crtc functions\n");
693 		return -ENXIO;
694 	}
695 
696 #ifdef CONFIG_SPL_BUILD
697 	if (state->conn_state.type == DRM_MODE_CONNECTOR_HDMIA)
698 		state->enabled_at_spl = spl_disp_info->enabled == 1 ? true : false;
699 	if (state->enabled_at_spl)
700 		printf("HDMI enabled at SPL\n");
701 #endif
702 	if (crtc_state->crtc->active && !crtc_state->ports_node &&
703 	    memcmp(&crtc_state->crtc->active_mode, &conn_state->mode,
704 		   sizeof(struct drm_display_mode))) {
705 		printf("%s has been used for output type: %d, mode: %dx%dp%d\n",
706 			crtc_state->dev->name,
707 			crtc_state->crtc->active_mode.type,
708 			crtc_state->crtc->active_mode.hdisplay,
709 			crtc_state->crtc->active_mode.vdisplay,
710 			crtc_state->crtc->active_mode.vrefresh);
711 		return -ENODEV;
712 	}
713 
714 	if (crtc_funcs->preinit) {
715 		ret = crtc_funcs->preinit(state);
716 		if (ret)
717 			return ret;
718 	}
719 
720 	if (state->enabled_at_spl == false) {
721 		ret = rockchip_connector_init(state);
722 		if (ret)
723 			goto deinit;
724 	}
725 
726 	/*
727 	 * support hotplug, but not connect;
728 	 */
729 #ifdef CONFIG_DRM_ROCKCHIP_TVE
730 	if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_TV) {
731 		printf("hdmi plugin ,skip tve\n");
732 		goto deinit;
733 	}
734 #elif defined(CONFIG_DRM_ROCKCHIP_RK1000)
735 	if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_LVDS) {
736 		printf("hdmi plugin ,skip tve\n");
737 		goto deinit;
738 	}
739 #endif
740 
741 	ret = rockchip_connector_detect(state);
742 #if defined(CONFIG_DRM_ROCKCHIP_TVE) || defined(CONFIG_DRM_ROCKCHIP_RK1000)
743 	if (conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
744 		crtc->hdmi_hpd = ret;
745 	if (state->enabled_at_spl)
746 		crtc->hdmi_hpd = true;
747 #endif
748 	if (!ret && !state->force_output)
749 		goto deinit;
750 
751 	ret = 0;
752 	if (state->enabled_at_spl == true) {
753 #ifdef CONFIG_SPL_BUILD
754 		struct drm_display_mode *mode = &conn_state->mode;
755 
756 		memcpy(mode, &spl_disp_info->mode,  sizeof(*mode));
757 		conn_state->bus_format = spl_disp_info->bus_format;
758 
759 		printf("%s get display mode from spl:%dx%d, bus format:0x%x\n",
760 			conn->dev->name, mode->hdisplay, mode->vdisplay, conn_state->bus_format);
761 #endif
762 	} else if (conn->panel) {
763 		ret = display_get_timing(state);
764 		if (!ret)
765 			conn_state->bpc = conn->panel->bpc;
766 #if defined(CONFIG_I2C_EDID)
767 		if (ret < 0 && conn->funcs->get_edid) {
768 			rockchip_panel_prepare(conn->panel);
769 			ret = conn->funcs->get_edid(conn, state);
770 			if (!ret)
771 				display_get_edid_mode(state);
772 		}
773 #endif
774 	} else if (conn->bridge) {
775 		ret = video_bridge_read_edid(conn->bridge->dev,
776 					     conn_state->edid, EDID_SIZE);
777 		if (ret > 0) {
778 #if defined(CONFIG_I2C_EDID)
779 			display_get_edid_mode(state);
780 #endif
781 		} else {
782 			ret = video_bridge_get_timing(conn->bridge->dev);
783 		}
784 	} else if (conn->funcs->get_timing) {
785 		ret = conn->funcs->get_timing(conn, state);
786 	} else if (conn->funcs->get_edid) {
787 		ret = conn->funcs->get_edid(conn, state);
788 #if defined(CONFIG_I2C_EDID)
789 		if (!ret)
790 			display_get_edid_mode(state);
791 #endif
792 	}
793 
794 	if (!ret && conn_state->secondary) {
795 		struct rockchip_connector *connector = conn_state->secondary;
796 
797 		if (connector->panel) {
798 			if (connector->panel->funcs->get_mode) {
799 				struct drm_display_mode *_mode = drm_mode_create();
800 
801 				ret = connector->panel->funcs->get_mode(connector->panel, _mode);
802 				if (!ret && !drm_mode_equal(_mode, mode))
803 					ret = -EINVAL;
804 
805 				drm_mode_destroy(_mode);
806 			}
807 		}
808 	}
809 
810 	if (ret && !state->force_output)
811 		goto deinit;
812 	if (state->force_output)
813 		display_use_force_mode(state);
814 
815 	if (display_mode_valid(state))
816 		goto deinit;
817 
818 	/* rk356x series drive mipi pixdata on posedge */
819 	compatible = dev_read_string(conn->dev, "compatible");
820 	if (!strcmp(compatible, "rockchip,rk3568-mipi-dsi")) {
821 		conn_state->bus_flags &= ~DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
822 		conn_state->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
823 	}
824 
825 	printf("%s: %s detailed mode clock %u kHz, flags[%x]\n"
826 	       "    H: %04d %04d %04d %04d\n"
827 	       "    V: %04d %04d %04d %04d\n"
828 	       "bus_format: %x\n",
829 	       conn->dev->name,
830 	       state->force_output ? "use force output" : "",
831 	       mode->clock, mode->flags,
832 	       mode->hdisplay, mode->hsync_start,
833 	       mode->hsync_end, mode->htotal,
834 	       mode->vdisplay, mode->vsync_start,
835 	       mode->vsync_end, mode->vtotal,
836 	       conn_state->bus_format);
837 
838 	if (display_mode_fixup(state))
839 		goto deinit;
840 
841 	if (conn->bridge)
842 		rockchip_bridge_mode_set(conn->bridge, &conn_state->mode);
843 
844 	if (crtc_funcs->init && state->enabled_at_spl == false) {
845 		ret = crtc_funcs->init(state);
846 		if (ret)
847 			goto deinit;
848 	}
849 	state->is_init = 1;
850 
851 	crtc_state->crtc->active = true;
852 	memcpy(&crtc_state->crtc->active_mode,
853 	       &conn_state->mode, sizeof(struct drm_display_mode));
854 
855 	return 0;
856 
857 deinit:
858 	rockchip_connector_deinit(state);
859 	return ret;
860 }
861 
862 int display_send_mcu_cmd(struct display_state *state, u32 type, u32 val)
863 {
864 	struct crtc_state *crtc_state = &state->crtc_state;
865 	const struct rockchip_crtc *crtc = crtc_state->crtc;
866 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
867 	int ret;
868 
869 	if (!state->is_init)
870 		return -EINVAL;
871 
872 	if (crtc_funcs->send_mcu_cmd) {
873 		ret = crtc_funcs->send_mcu_cmd(state, type, val);
874 		if (ret)
875 			return ret;
876 	}
877 
878 	return 0;
879 }
880 
881 static int display_set_plane(struct display_state *state)
882 {
883 	struct crtc_state *crtc_state = &state->crtc_state;
884 	const struct rockchip_crtc *crtc = crtc_state->crtc;
885 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
886 	int ret;
887 
888 	if (!state->is_init)
889 		return -EINVAL;
890 
891 	if (crtc_funcs->set_plane) {
892 		ret = crtc_funcs->set_plane(state);
893 		if (ret)
894 			return ret;
895 	}
896 
897 	return 0;
898 }
899 
900 static int display_enable(struct display_state *state)
901 {
902 	struct crtc_state *crtc_state = &state->crtc_state;
903 	const struct rockchip_crtc *crtc = crtc_state->crtc;
904 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
905 
906 	if (!state->is_init)
907 		return -EINVAL;
908 
909 	if (state->is_enable)
910 		return 0;
911 
912 	if (crtc_funcs->prepare)
913 		crtc_funcs->prepare(state);
914 
915 	if (state->enabled_at_spl == false)
916 		rockchip_connector_pre_enable(state);
917 
918 	if (crtc_funcs->enable)
919 		crtc_funcs->enable(state);
920 
921 	if (state->enabled_at_spl == false)
922 		rockchip_connector_enable(state);
923 
924 	if (crtc_state->soft_te)
925 		crtc_funcs->apply_soft_te(state);
926 
927 	state->is_enable = true;
928 
929 	return 0;
930 }
931 
932 static int display_disable(struct display_state *state)
933 {
934 	struct crtc_state *crtc_state = &state->crtc_state;
935 	const struct rockchip_crtc *crtc = crtc_state->crtc;
936 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
937 
938 	if (!state->is_init)
939 		return 0;
940 
941 	if (!state->is_enable)
942 		return 0;
943 
944 	rockchip_connector_disable(state);
945 
946 	if (crtc_funcs->disable)
947 		crtc_funcs->disable(state);
948 
949 	rockchip_connector_post_disable(state);
950 
951 	state->is_enable = 0;
952 	state->is_init = 0;
953 
954 	return 0;
955 }
956 
957 static int display_check(struct display_state *state)
958 {
959 	struct connector_state *conn_state = &state->conn_state;
960 	struct rockchip_connector *conn = conn_state->connector;
961 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
962 	struct crtc_state *crtc_state = &state->crtc_state;
963 	const struct rockchip_crtc *crtc = crtc_state->crtc;
964 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
965 	int ret;
966 
967 	if (!state->is_init)
968 		return 0;
969 
970 	if (conn_funcs->check) {
971 		ret = conn_funcs->check(conn, state);
972 		if (ret)
973 			goto check_fail;
974 	}
975 
976 	if (crtc_funcs->check) {
977 		ret = crtc_funcs->check(state);
978 		if (ret)
979 			goto check_fail;
980 	}
981 
982 	if (crtc_funcs->plane_check) {
983 		ret = crtc_funcs->plane_check(state);
984 		if (ret)
985 			goto check_fail;
986 	}
987 
988 	return 0;
989 
990 check_fail:
991 	state->is_init = false;
992 	return ret;
993 }
994 
995 static int display_logo(struct display_state *state)
996 {
997 	struct crtc_state *crtc_state = &state->crtc_state;
998 	struct connector_state *conn_state = &state->conn_state;
999 	struct logo_info *logo = &state->logo;
1000 	int hdisplay, vdisplay, ret;
1001 
1002 	ret = display_init(state);
1003 	if (!state->is_init || ret)
1004 		return -ENODEV;
1005 
1006 	switch (logo->bpp) {
1007 	case 16:
1008 		crtc_state->format = ROCKCHIP_FMT_RGB565;
1009 		break;
1010 	case 24:
1011 		crtc_state->format = ROCKCHIP_FMT_RGB888;
1012 		break;
1013 	case 32:
1014 		crtc_state->format = ROCKCHIP_FMT_ARGB8888;
1015 		break;
1016 	default:
1017 		printf("can't support bmp bits[%d]\n", logo->bpp);
1018 		return -EINVAL;
1019 	}
1020 	hdisplay = conn_state->mode.crtc_hdisplay;
1021 	vdisplay = conn_state->mode.vdisplay;
1022 	crtc_state->src_rect.w = logo->width;
1023 	crtc_state->src_rect.h = logo->height;
1024 	crtc_state->src_rect.x = 0;
1025 	crtc_state->src_rect.y = 0;
1026 	crtc_state->ymirror = logo->ymirror;
1027 	crtc_state->rb_swap = 0;
1028 
1029 	crtc_state->dma_addr = (u32)(unsigned long)logo->mem + logo->offset;
1030 	crtc_state->xvir = ALIGN(crtc_state->src_rect.w * logo->bpp, 32) >> 5;
1031 
1032 	if (state->logo_mode == ROCKCHIP_DISPLAY_FULLSCREEN) {
1033 		crtc_state->crtc_rect.x = 0;
1034 		crtc_state->crtc_rect.y = 0;
1035 		crtc_state->crtc_rect.w = hdisplay;
1036 		crtc_state->crtc_rect.h = vdisplay;
1037 	} else {
1038 		if (crtc_state->src_rect.w >= hdisplay) {
1039 			crtc_state->crtc_rect.x = 0;
1040 			crtc_state->crtc_rect.w = hdisplay;
1041 		} else {
1042 			crtc_state->crtc_rect.x = (hdisplay - crtc_state->src_rect.w) / 2;
1043 			crtc_state->crtc_rect.w = crtc_state->src_rect.w;
1044 		}
1045 
1046 		if (crtc_state->src_rect.h >= vdisplay) {
1047 			crtc_state->crtc_rect.y = 0;
1048 			crtc_state->crtc_rect.h = vdisplay;
1049 		} else {
1050 			crtc_state->crtc_rect.y = (vdisplay - crtc_state->src_rect.h) / 2;
1051 			crtc_state->crtc_rect.h = crtc_state->src_rect.h;
1052 		}
1053 	}
1054 
1055 	display_check(state);
1056 	ret = display_set_plane(state);
1057 	if (ret)
1058 		return ret;
1059 	display_enable(state);
1060 
1061 	return 0;
1062 }
1063 
1064 static int get_crtc_id(ofnode connect, bool is_ports_node)
1065 {
1066 	struct device_node *port_node;
1067 	struct device_node *remote;
1068 	int phandle;
1069 	int val;
1070 
1071 	if (is_ports_node) {
1072 		port_node = of_get_parent(connect.np);
1073 		if (!port_node)
1074 			goto err;
1075 
1076 		val = ofnode_read_u32_default(np_to_ofnode(port_node), "reg", -1);
1077 		if (val < 0)
1078 			goto err;
1079 	} else {
1080 		phandle = ofnode_read_u32_default(connect, "remote-endpoint", -1);
1081 		if (phandle < 0)
1082 			goto err;
1083 
1084 		remote = of_find_node_by_phandle(phandle);
1085 		if (!remote)
1086 			goto err;
1087 
1088 		val = ofnode_read_u32_default(np_to_ofnode(remote), "reg", -1);
1089 		if (val < 0)
1090 			goto err;
1091 	}
1092 
1093 	return val;
1094 err:
1095 	printf("Can't get crtc id, default set to id = 0\n");
1096 	return 0;
1097 }
1098 
1099 static int get_crtc_mcu_mode(struct crtc_state *crtc_state, struct device_node *port_node,
1100 			     bool is_ports_node)
1101 {
1102 	ofnode mcu_node, vp_node;
1103 	int total_pixel, cs_pst, cs_pend, rw_pst, rw_pend;
1104 
1105 	if (is_ports_node) {
1106 		vp_node = np_to_ofnode(port_node);
1107 		mcu_node = ofnode_find_subnode(vp_node, "mcu-timing");
1108 		if (!ofnode_valid(mcu_node))
1109 			return -ENODEV;
1110 	} else {
1111 		mcu_node = dev_read_subnode(crtc_state->dev, "mcu-timing");
1112 		if (!ofnode_valid(mcu_node))
1113 			return -ENODEV;
1114 	}
1115 
1116 #define FDT_GET_MCU_INT(val, name) \
1117 	do { \
1118 		val = ofnode_read_s32_default(mcu_node, name, -1); \
1119 		if (val < 0) { \
1120 			printf("Can't get %s\n", name); \
1121 			return -ENXIO; \
1122 		} \
1123 	} while (0)
1124 
1125 	FDT_GET_MCU_INT(total_pixel, "mcu-pix-total");
1126 	FDT_GET_MCU_INT(cs_pst, "mcu-cs-pst");
1127 	FDT_GET_MCU_INT(cs_pend, "mcu-cs-pend");
1128 	FDT_GET_MCU_INT(rw_pst, "mcu-rw-pst");
1129 	FDT_GET_MCU_INT(rw_pend, "mcu-rw-pend");
1130 
1131 	crtc_state->mcu_timing.mcu_pix_total = total_pixel;
1132 	crtc_state->mcu_timing.mcu_cs_pst = cs_pst;
1133 	crtc_state->mcu_timing.mcu_cs_pend = cs_pend;
1134 	crtc_state->mcu_timing.mcu_rw_pst = rw_pst;
1135 	crtc_state->mcu_timing.mcu_rw_pend = rw_pend;
1136 
1137 	return 0;
1138 }
1139 
1140 struct rockchip_logo_cache *find_or_alloc_logo_cache(const char *bmp)
1141 {
1142 	struct rockchip_logo_cache *tmp, *logo_cache = NULL;
1143 
1144 	list_for_each_entry(tmp, &logo_cache_list, head) {
1145 		if (!strcmp(tmp->name, bmp)) {
1146 			logo_cache = tmp;
1147 			break;
1148 		}
1149 	}
1150 
1151 	if (!logo_cache) {
1152 		logo_cache = malloc(sizeof(*logo_cache));
1153 		if (!logo_cache) {
1154 			printf("failed to alloc memory for logo cache\n");
1155 			return NULL;
1156 		}
1157 		memset(logo_cache, 0, sizeof(*logo_cache));
1158 		strcpy(logo_cache->name, bmp);
1159 		INIT_LIST_HEAD(&logo_cache->head);
1160 		list_add_tail(&logo_cache->head, &logo_cache_list);
1161 	}
1162 
1163 	return logo_cache;
1164 }
1165 
1166 /* Note: used only for rkfb kernel driver */
1167 static int load_kernel_bmp_logo(struct logo_info *logo, const char *bmp_name)
1168 {
1169 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
1170 	void *dst = NULL;
1171 	int len, size;
1172 	struct bmp_header *header;
1173 
1174 	if (!logo || !bmp_name)
1175 		return -EINVAL;
1176 
1177 	header = malloc(RK_BLK_SIZE);
1178 	if (!header)
1179 		return -ENOMEM;
1180 
1181 	len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
1182 	if (len != RK_BLK_SIZE) {
1183 		free(header);
1184 		return -EINVAL;
1185 	}
1186 	size = get_unaligned_le32(&header->file_size);
1187 	dst = (void *)(memory_start + MEMORY_POOL_SIZE / 2);
1188 	len = rockchip_read_resource_file(dst, bmp_name, 0, size);
1189 	if (len != size) {
1190 		printf("failed to load bmp %s\n", bmp_name);
1191 		free(header);
1192 		return -ENOENT;
1193 	}
1194 
1195 	logo->mem = dst;
1196 #endif
1197 
1198 	return 0;
1199 }
1200 
1201 static int load_bmp_logo(struct logo_info *logo, const char *bmp_name)
1202 {
1203 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
1204 	struct rockchip_logo_cache *logo_cache;
1205 	struct bmp_header *header;
1206 	void *dst = NULL, *pdst;
1207 	int size, len;
1208 	int ret = 0;
1209 	int reserved = 0;
1210 	int dst_size;
1211 
1212 	if (!logo || !bmp_name)
1213 		return -EINVAL;
1214 	logo_cache = find_or_alloc_logo_cache(bmp_name);
1215 	if (!logo_cache)
1216 		return -ENOMEM;
1217 
1218 	if (logo_cache->logo.mem) {
1219 		memcpy(logo, &logo_cache->logo, sizeof(*logo));
1220 		return 0;
1221 	}
1222 
1223 	header = malloc(RK_BLK_SIZE);
1224 	if (!header)
1225 		return -ENOMEM;
1226 
1227 	len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
1228 	if (len != RK_BLK_SIZE) {
1229 		ret = -EINVAL;
1230 		goto free_header;
1231 	}
1232 
1233 	logo->bpp = get_unaligned_le16(&header->bit_count);
1234 	logo->width = get_unaligned_le32(&header->width);
1235 	logo->height = get_unaligned_le32(&header->height);
1236 	dst_size = logo->width * logo->height * logo->bpp >> 3;
1237 	reserved = get_unaligned_le32(&header->reserved);
1238 	if (logo->height < 0)
1239 	    logo->height = -logo->height;
1240 	size = get_unaligned_le32(&header->file_size);
1241 	if (!can_direct_logo(logo->bpp)) {
1242 		if (size > MEMORY_POOL_SIZE) {
1243 			printf("failed to use boot buf as temp bmp buffer\n");
1244 			ret = -ENOMEM;
1245 			goto free_header;
1246 		}
1247 		pdst = get_display_buffer(size);
1248 
1249 	} else {
1250 		pdst = get_display_buffer(size);
1251 		dst = pdst;
1252 	}
1253 
1254 	len = rockchip_read_resource_file(pdst, bmp_name, 0, size);
1255 	if (len != size) {
1256 		printf("failed to load bmp %s\n", bmp_name);
1257 		ret = -ENOENT;
1258 		goto free_header;
1259 	}
1260 
1261 	if (!can_direct_logo(logo->bpp)) {
1262 		/*
1263 		 * TODO: force use 16bpp if bpp less than 16;
1264 		 */
1265 		logo->bpp = (logo->bpp <= 16) ? 16 : logo->bpp;
1266 		dst_size = logo->width * logo->height * logo->bpp >> 3;
1267 		dst = get_display_buffer(dst_size);
1268 		if (!dst) {
1269 			ret = -ENOMEM;
1270 			goto free_header;
1271 		}
1272 		if (bmpdecoder(pdst, dst, logo->bpp)) {
1273 			printf("failed to decode bmp %s\n", bmp_name);
1274 			ret = -EINVAL;
1275 			goto free_header;
1276 		}
1277 
1278 		logo->offset = 0;
1279 		logo->ymirror = 0;
1280 	} else {
1281 		logo->offset = get_unaligned_le32(&header->data_offset);
1282 		if (reserved == BMP_PROCESSED_FLAG)
1283 			logo->ymirror = 0;
1284 		else
1285 			logo->ymirror = 1;
1286 	}
1287 	logo->mem = dst;
1288 
1289 	memcpy(&logo_cache->logo, logo, sizeof(*logo));
1290 
1291 	flush_dcache_range((ulong)dst, ALIGN((ulong)dst + dst_size, CONFIG_SYS_CACHELINE_SIZE));
1292 
1293 free_header:
1294 
1295 	free(header);
1296 
1297 	return ret;
1298 #else
1299 	return -EINVAL;
1300 #endif
1301 }
1302 
1303 void rockchip_show_fbbase(ulong fbbase)
1304 {
1305 	struct display_state *s;
1306 
1307 	list_for_each_entry(s, &rockchip_display_list, head) {
1308 		s->logo.mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1309 		s->logo.mem = (char *)fbbase;
1310 		s->logo.width = DRM_ROCKCHIP_FB_WIDTH;
1311 		s->logo.height = DRM_ROCKCHIP_FB_HEIGHT;
1312 		s->logo.bpp = 32;
1313 		s->logo.ymirror = 0;
1314 
1315 		display_logo(s);
1316 	}
1317 }
1318 
1319 int rockchip_show_bmp(const char *bmp)
1320 {
1321 	struct display_state *s;
1322 	int ret = 0;
1323 
1324 	if (!bmp) {
1325 		list_for_each_entry(s, &rockchip_display_list, head)
1326 			display_disable(s);
1327 		return -ENOENT;
1328 	}
1329 
1330 	list_for_each_entry(s, &rockchip_display_list, head) {
1331 		s->logo.mode = s->charge_logo_mode;
1332 		if (load_bmp_logo(&s->logo, bmp))
1333 			continue;
1334 		ret = display_logo(s);
1335 	}
1336 
1337 	return ret;
1338 }
1339 
1340 int rockchip_show_logo(void)
1341 {
1342 	struct display_state *s;
1343 	struct display_state *ms = NULL;
1344 	int ret = 0;
1345 	int count = 0;
1346 
1347 	list_for_each_entry(s, &rockchip_display_list, head) {
1348 		s->logo.mode = s->logo_mode;
1349 		if (load_bmp_logo(&s->logo, s->ulogo_name)) {
1350 			printf("failed to display uboot logo\n");
1351 		} else {
1352 			ret = display_logo(s);
1353 			if (ret == -EAGAIN)
1354 				ms = s;
1355 		}
1356 		/* Load kernel bmp in rockchip_display_fixup() later */
1357 	}
1358 
1359 	/*
1360 	 * For rk3566, the mirror win must be enabled after the related
1361 	 * source win. If error code is EAGAIN, the mirror win may be
1362 	 * first enabled unexpectedly, and we will move the enabling process
1363 	 * as follows.
1364 	 */
1365 	if (ms) {
1366 		while (count < 5) {
1367 			ret = display_logo(ms);
1368 			if (ret != -EAGAIN)
1369 				break;
1370 			mdelay(10);
1371 			count++;
1372 		}
1373 	}
1374 
1375 	return ret;
1376 }
1377 
1378 int rockchip_vop_dump(const char *cmd)
1379 {
1380 	struct display_state *state;
1381 	struct crtc_state *crtc_state;
1382 	struct rockchip_crtc *crtc;
1383 	const struct rockchip_crtc_funcs *crtc_funcs;
1384 	int ret = -EINVAL;
1385 
1386 	list_for_each_entry(state, &rockchip_display_list, head) {
1387 		if (!state->is_init)
1388 			continue;
1389 		crtc_state = &state->crtc_state;
1390 		crtc = crtc_state->crtc;
1391 		crtc_funcs = crtc->funcs;
1392 
1393 		if (!cmd)
1394 			ret = crtc_funcs->active_regs_dump(state);
1395 		else if (!strcmp(cmd, "a") || !strcmp(cmd, "all"))
1396 			ret = crtc_funcs->regs_dump(state);
1397 		if (!ret)
1398 			break;
1399 	}
1400 
1401 	if (ret)
1402 		ret = CMD_RET_USAGE;
1403 
1404 	return ret;
1405 }
1406 
1407 enum {
1408 	PORT_DIR_IN,
1409 	PORT_DIR_OUT,
1410 };
1411 
1412 const struct device_node *rockchip_of_graph_get_port_by_id(ofnode node, int id)
1413 {
1414 	ofnode ports, port;
1415 	u32 reg;
1416 
1417 	ports = ofnode_find_subnode(node, "ports");
1418 	if (!ofnode_valid(ports))
1419 		return NULL;
1420 
1421 	ofnode_for_each_subnode(port, ports) {
1422 		if (ofnode_read_u32(port, "reg", &reg))
1423 			continue;
1424 
1425 		if (reg == id)
1426 			break;
1427 	}
1428 
1429 	if (reg == id)
1430 		return ofnode_to_np(port);
1431 
1432 	return NULL;
1433 }
1434 
1435 static const struct device_node *rockchip_of_graph_get_port_parent(ofnode port)
1436 {
1437 	ofnode parent;
1438 	int is_ports_node;
1439 
1440 	parent = ofnode_get_parent(port);
1441 	is_ports_node = strstr(ofnode_to_np(parent)->full_name, "ports") ? 1 : 0;
1442 	if (is_ports_node)
1443 		parent = ofnode_get_parent(parent);
1444 
1445 	return ofnode_to_np(parent);
1446 }
1447 
1448 const struct device_node *
1449 rockchip_of_graph_get_endpoint_by_regs(ofnode node, int port, int endpoint)
1450 {
1451 	const struct device_node *port_node;
1452 	ofnode ep;
1453 	u32 reg;
1454 
1455 	port_node = rockchip_of_graph_get_port_by_id(node, port);
1456 	if (!port_node)
1457 		return NULL;
1458 
1459 	ofnode_for_each_subnode(ep, np_to_ofnode(port_node)) {
1460 		if (ofnode_read_u32(ep, "reg", &reg))
1461 			break;
1462 		if (reg == endpoint)
1463 			break;
1464 	}
1465 
1466 	if (!ofnode_valid(ep))
1467 		return NULL;
1468 
1469 	return ofnode_to_np(ep);
1470 }
1471 
1472 static const struct device_node *
1473 rockchip_of_graph_get_remote_node(ofnode node, int port, int endpoint)
1474 {
1475 	const struct device_node *ep_node;
1476 	ofnode ep;
1477 	uint phandle;
1478 
1479 	ep_node = rockchip_of_graph_get_endpoint_by_regs(node, port, endpoint);
1480 	if (!ep_node)
1481 		return NULL;
1482 
1483 	if (ofnode_read_u32(np_to_ofnode(ep_node), "remote-endpoint", &phandle))
1484 		return NULL;
1485 
1486 	ep = ofnode_get_by_phandle(phandle);
1487 	if (!ofnode_valid(ep))
1488 		return NULL;
1489 
1490 	return ofnode_to_np(ep);
1491 }
1492 
1493 static int rockchip_of_find_panel(struct udevice *dev, struct rockchip_panel **panel)
1494 {
1495 	const struct device_node *ep_node, *panel_node;
1496 	ofnode panel_ofnode, port;
1497 	struct udevice *panel_dev;
1498 	int ret = 0;
1499 
1500 	*panel = NULL;
1501 	panel_ofnode = dev_read_subnode(dev, "panel");
1502 	if (ofnode_valid(panel_ofnode) && ofnode_is_available(panel_ofnode)) {
1503 		ret = uclass_get_device_by_ofnode(UCLASS_PANEL, panel_ofnode,
1504 						  &panel_dev);
1505 		if (!ret)
1506 			goto found;
1507 	}
1508 
1509 	ep_node = rockchip_of_graph_get_remote_node(dev->node, PORT_DIR_OUT, 0);
1510 	if (!ep_node)
1511 		return -ENODEV;
1512 
1513 	port = ofnode_get_parent(np_to_ofnode(ep_node));
1514 	if (!ofnode_valid(port))
1515 		return -ENODEV;
1516 
1517 	panel_node = rockchip_of_graph_get_port_parent(port);
1518 	if (!panel_node)
1519 		return -ENODEV;
1520 
1521 	ret = uclass_get_device_by_ofnode(UCLASS_PANEL, np_to_ofnode(panel_node), &panel_dev);
1522 	if (!ret)
1523 		goto found;
1524 
1525 	return -ENODEV;
1526 
1527 found:
1528 	*panel = (struct rockchip_panel *)dev_get_driver_data(panel_dev);
1529 	return 0;
1530 }
1531 
1532 static int rockchip_of_find_bridge(struct udevice *dev, struct rockchip_bridge **bridge)
1533 {
1534 	const struct device_node *ep_node, *bridge_node;
1535 	ofnode port;
1536 	struct udevice *bridge_dev;
1537 	int ret = 0;
1538 
1539 	ep_node = rockchip_of_graph_get_remote_node(dev->node, PORT_DIR_OUT, 0);
1540 	if (!ep_node)
1541 		return -ENODEV;
1542 
1543 	port = ofnode_get_parent(np_to_ofnode(ep_node));
1544 	if (!ofnode_valid(port))
1545 		return -ENODEV;
1546 
1547 	bridge_node = rockchip_of_graph_get_port_parent(port);
1548 	if (!bridge_node)
1549 		return -ENODEV;
1550 
1551 	ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, np_to_ofnode(bridge_node),
1552 					  &bridge_dev);
1553 	if (!ret)
1554 		goto found;
1555 
1556 	return -ENODEV;
1557 
1558 found:
1559 	*bridge = (struct rockchip_bridge *)dev_get_driver_data(bridge_dev);
1560 	return 0;
1561 }
1562 
1563 static int rockchip_of_find_panel_or_bridge(struct udevice *dev, struct rockchip_panel **panel,
1564 					    struct rockchip_bridge **bridge)
1565 {
1566 	int ret = 0;
1567 
1568 	if (*panel)
1569 		return 0;
1570 
1571 	*panel = NULL;
1572 	*bridge = NULL;
1573 
1574 	if (panel) {
1575 		ret  = rockchip_of_find_panel(dev, panel);
1576 		if (!ret)
1577 			return 0;
1578 	}
1579 
1580 	if (ret) {
1581 		ret = rockchip_of_find_bridge(dev, bridge);
1582 		if (!ret)
1583 			ret = rockchip_of_find_panel_or_bridge((*bridge)->dev, panel,
1584 							       &(*bridge)->next_bridge);
1585 	}
1586 
1587 	return ret;
1588 }
1589 
1590 static struct rockchip_phy *rockchip_of_find_phy(struct udevice *dev)
1591 {
1592 	struct udevice *phy_dev;
1593 	int ret;
1594 
1595 	ret = uclass_get_device_by_phandle(UCLASS_PHY, dev, "phys", &phy_dev);
1596 	if (ret)
1597 		return NULL;
1598 
1599 	return (struct rockchip_phy *)dev_get_driver_data(phy_dev);
1600 }
1601 
1602 static struct udevice *rockchip_of_find_connector_device(ofnode endpoint)
1603 {
1604 	ofnode ep, port, ports, conn;
1605 	uint phandle;
1606 	struct udevice *dev;
1607 	int ret;
1608 
1609 	if (ofnode_read_u32(endpoint, "remote-endpoint", &phandle))
1610 		return NULL;
1611 
1612 	ep = ofnode_get_by_phandle(phandle);
1613 	if (!ofnode_valid(ep) || !ofnode_is_available(ep))
1614 		return NULL;
1615 
1616 	port = ofnode_get_parent(ep);
1617 	if (!ofnode_valid(port))
1618 		return NULL;
1619 
1620 	ports = ofnode_get_parent(port);
1621 	if (!ofnode_valid(ports))
1622 		return NULL;
1623 
1624 	conn = ofnode_get_parent(ports);
1625 	if (!ofnode_valid(conn) || !ofnode_is_available(conn))
1626 		return NULL;
1627 
1628 	ret = uclass_get_device_by_ofnode(UCLASS_DISPLAY, conn, &dev);
1629 	if (ret)
1630 		return NULL;
1631 
1632 	return dev;
1633 }
1634 
1635 static struct rockchip_connector *rockchip_of_get_connector(ofnode endpoint)
1636 {
1637 	struct rockchip_connector *conn;
1638 	struct udevice *dev;
1639 	int ret;
1640 
1641 	dev = rockchip_of_find_connector_device(endpoint);
1642 	if (!dev) {
1643 		printf("Warn: can't find connect driver\n");
1644 		return NULL;
1645 	}
1646 
1647 	conn = get_rockchip_connector_by_device(dev);
1648 	if (!conn)
1649 		return NULL;
1650 	ret = rockchip_of_find_panel_or_bridge(dev, &conn->panel, &conn->bridge);
1651 	if (ret)
1652 		debug("Warn: no find panel or bridge\n");
1653 
1654 	conn->phy = rockchip_of_find_phy(dev);
1655 
1656 	return conn;
1657 }
1658 
1659 static struct rockchip_connector *rockchip_get_split_connector(struct rockchip_connector *conn)
1660 {
1661 	char *conn_name;
1662 	struct device_node *split_node;
1663 	struct udevice *split_dev;
1664 	struct rockchip_connector *split_conn;
1665 	bool split_mode;
1666 	int ret;
1667 
1668 	split_mode = ofnode_read_bool(conn->dev->node, "split-mode");
1669 	split_mode |= ofnode_read_bool(conn->dev->node, "dual-channel");
1670 	if (!split_mode)
1671 		return NULL;
1672 
1673 	switch (conn->type) {
1674 	case DRM_MODE_CONNECTOR_DisplayPort:
1675 		conn_name = "dp";
1676 		break;
1677 	case DRM_MODE_CONNECTOR_eDP:
1678 		conn_name = "edp";
1679 		break;
1680 	case DRM_MODE_CONNECTOR_HDMIA:
1681 		conn_name = "hdmi";
1682 		break;
1683 	case DRM_MODE_CONNECTOR_LVDS:
1684 		conn_name = "lvds";
1685 		break;
1686 	default:
1687 		return NULL;
1688 	}
1689 
1690 	split_node = of_alias_get_dev(conn_name, !conn->id);
1691 	if (!split_node || !of_device_is_available(split_node))
1692 		return NULL;
1693 
1694 	ret = uclass_get_device_by_ofnode(UCLASS_DISPLAY, np_to_ofnode(split_node), &split_dev);
1695 	if (ret)
1696 		return NULL;
1697 
1698 	split_conn = get_rockchip_connector_by_device(split_dev);
1699 	if (!split_conn)
1700 		return NULL;
1701 	ret = rockchip_of_find_panel_or_bridge(split_dev, &split_conn->panel, &split_conn->bridge);
1702 	if (ret)
1703 		debug("Warn: no find panel or bridge\n");
1704 
1705 	split_conn->phy = rockchip_of_find_phy(split_dev);
1706 
1707 	return split_conn;
1708 }
1709 
1710 static bool rockchip_get_display_path_status(ofnode endpoint)
1711 {
1712 	ofnode ep;
1713 	uint phandle;
1714 
1715 	if (ofnode_read_u32(endpoint, "remote-endpoint", &phandle))
1716 		return false;
1717 
1718 	ep = ofnode_get_by_phandle(phandle);
1719 	if (!ofnode_valid(ep) || !ofnode_is_available(ep))
1720 		return false;
1721 
1722 	return true;
1723 }
1724 
1725 #if defined(CONFIG_ROCKCHIP_RK3568)
1726 static int rockchip_display_fixup_dts(void *blob)
1727 {
1728 	ofnode route_node, route_subnode, conn_ep, conn_port;
1729 	const struct device_node *route_sub_devnode;
1730 	const struct device_node *ep_node, *conn_ep_dev_node;
1731 	u32 phandle;
1732 	int conn_ep_offset;
1733 	const char *route_sub_path, *path;
1734 
1735 	/* Don't go further if new variant after
1736 	 * reading PMUGRF_SOC_CON15
1737 	 */
1738 	if ((readl(0xfdc20100) & GENMASK(15, 14)))
1739 		return 0;
1740 
1741 	route_node = ofnode_path("/display-subsystem/route");
1742 	if (!ofnode_valid(route_node))
1743 		return -EINVAL;
1744 
1745 	ofnode_for_each_subnode(route_subnode, route_node) {
1746 		if (!ofnode_is_available(route_subnode))
1747 			continue;
1748 
1749 		route_sub_devnode = ofnode_to_np(route_subnode);
1750 		route_sub_path = route_sub_devnode->full_name;
1751 		if (!strstr(ofnode_get_name(route_subnode), "dsi") &&
1752 		    !strstr(ofnode_get_name(route_subnode), "edp"))
1753 			return 0;
1754 
1755 		phandle = ofnode_read_u32_default(route_subnode, "connect", -1);
1756 		if (phandle < 0) {
1757 			printf("Warn: can't find connect node's handle\n");
1758 			continue;
1759 		}
1760 
1761 		ep_node = of_find_node_by_phandle(phandle);
1762 		if (!ofnode_valid(np_to_ofnode(ep_node))) {
1763 			printf("Warn: can't find endpoint node from phandle\n");
1764 			continue;
1765 		}
1766 
1767 		ofnode_read_u32(np_to_ofnode(ep_node), "remote-endpoint", &phandle);
1768 		conn_ep = ofnode_get_by_phandle(phandle);
1769 		if (!ofnode_valid(conn_ep) || !ofnode_is_available(conn_ep))
1770 			return -ENODEV;
1771 
1772 		conn_port = ofnode_get_parent(conn_ep);
1773 		if (!ofnode_valid(conn_port))
1774 			return -ENODEV;
1775 
1776 		ofnode_for_each_subnode(conn_ep, conn_port) {
1777 			conn_ep_dev_node = ofnode_to_np(conn_ep);
1778 			path = conn_ep_dev_node->full_name;
1779 			ofnode_read_u32(conn_ep, "remote-endpoint", &phandle);
1780 			conn_ep_offset = fdt_path_offset(blob, path);
1781 
1782 			if (!ofnode_is_available(conn_ep) &&
1783 			    strstr(ofnode_get_name(conn_ep), "endpoint@0")) {
1784 				do_fixup_by_path_u32(blob, route_sub_path,
1785 						     "connect", phandle, 1);
1786 				fdt_status_okay(blob, conn_ep_offset);
1787 
1788 			} else if (ofnode_is_available(conn_ep) &&
1789 				   strstr(ofnode_get_name(conn_ep), "endpoint@1")) {
1790 				fdt_status_disabled(blob, conn_ep_offset);
1791 			}
1792 		}
1793 	}
1794 
1795 	return 0;
1796 }
1797 #endif
1798 
1799 static int rockchip_display_probe(struct udevice *dev)
1800 {
1801 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
1802 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
1803 	const void *blob = gd->fdt_blob;
1804 	int phandle;
1805 	struct udevice *crtc_dev;
1806 	struct rockchip_crtc *crtc;
1807 	struct rockchip_connector *conn, *split_conn;
1808 	struct display_state *s;
1809 	const char *name;
1810 	int ret;
1811 	ofnode node, route_node, timing_node;
1812 	struct device_node *port_node, *vop_node, *ep_node, *port_parent_node;
1813 	struct public_phy_data *data;
1814 	bool is_ports_node = false;
1815 
1816 #if defined(CONFIG_ROCKCHIP_RK3568)
1817 	rockchip_display_fixup_dts((void *)blob);
1818 #endif
1819 	/* Before relocation we don't need to do anything */
1820 	if (!(gd->flags & GD_FLG_RELOC))
1821 		return 0;
1822 
1823 	data = malloc(sizeof(struct public_phy_data));
1824 	if (!data) {
1825 		printf("failed to alloc phy data\n");
1826 		return -ENOMEM;
1827 	}
1828 	data->phy_init = false;
1829 
1830 	init_display_buffer(plat->base);
1831 
1832 	route_node = dev_read_subnode(dev, "route");
1833 	if (!ofnode_valid(route_node))
1834 		return -ENODEV;
1835 
1836 	ofnode_for_each_subnode(node, route_node) {
1837 		if (!ofnode_is_available(node))
1838 			continue;
1839 		phandle = ofnode_read_u32_default(node, "connect", -1);
1840 		if (phandle < 0) {
1841 			printf("Warn: can't find connect node's handle\n");
1842 			continue;
1843 		}
1844 		ep_node = of_find_node_by_phandle(phandle);
1845 		if (!ofnode_valid(np_to_ofnode(ep_node))) {
1846 			printf("Warn: can't find endpoint node from phandle\n");
1847 			continue;
1848 		}
1849 		port_node = of_get_parent(ep_node);
1850 		if (!ofnode_valid(np_to_ofnode(port_node))) {
1851 			printf("Warn: can't find port node from phandle\n");
1852 			continue;
1853 		}
1854 
1855 		port_parent_node = of_get_parent(port_node);
1856 		if (!ofnode_valid(np_to_ofnode(port_parent_node))) {
1857 			printf("Warn: can't find port parent node from phandle\n");
1858 			continue;
1859 		}
1860 
1861 		is_ports_node = strstr(port_parent_node->full_name, "ports") ? 1 : 0;
1862 		if (is_ports_node) {
1863 			vop_node = of_get_parent(port_parent_node);
1864 			if (!ofnode_valid(np_to_ofnode(vop_node))) {
1865 				printf("Warn: can't find crtc node from phandle\n");
1866 				continue;
1867 			}
1868 		} else {
1869 			vop_node = port_parent_node;
1870 		}
1871 
1872 		ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_CRTC,
1873 						  np_to_ofnode(vop_node),
1874 						  &crtc_dev);
1875 		if (ret) {
1876 			printf("Warn: can't find crtc driver %d\n", ret);
1877 			continue;
1878 		}
1879 		crtc = (struct rockchip_crtc *)dev_get_driver_data(crtc_dev);
1880 
1881 		conn = rockchip_of_get_connector(np_to_ofnode(ep_node));
1882 		if (!conn) {
1883 			printf("Warn: can't get connect driver\n");
1884 			continue;
1885 		}
1886 		split_conn = rockchip_get_split_connector(conn);
1887 
1888 		s = malloc(sizeof(*s));
1889 		if (!s)
1890 			continue;
1891 
1892 		memset(s, 0, sizeof(*s));
1893 
1894 		INIT_LIST_HEAD(&s->head);
1895 		ret = ofnode_read_string_index(node, "logo,uboot", 0, &name);
1896 		if (!ret)
1897 			memcpy(s->ulogo_name, name, strlen(name));
1898 		ret = ofnode_read_string_index(node, "logo,kernel", 0, &name);
1899 		if (!ret)
1900 			memcpy(s->klogo_name, name, strlen(name));
1901 		ret = ofnode_read_string_index(node, "logo,mode", 0, &name);
1902 		if (!strcmp(name, "fullscreen"))
1903 			s->logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1904 		else
1905 			s->logo_mode = ROCKCHIP_DISPLAY_CENTER;
1906 		ret = ofnode_read_string_index(node, "charge_logo,mode", 0, &name);
1907 		if (!strcmp(name, "fullscreen"))
1908 			s->charge_logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1909 		else
1910 			s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER;
1911 
1912 		s->force_output = ofnode_read_bool(node, "force-output");
1913 
1914 		if (s->force_output) {
1915 			timing_node = ofnode_find_subnode(node, "force_timing");
1916 			ret = display_get_force_timing_from_dts(timing_node,
1917 								&s->force_mode,
1918 								&s->conn_state.bus_flags);
1919 			if (ofnode_read_u32(node, "force-bus-format", &s->force_bus_format))
1920 				s->force_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
1921 		}
1922 
1923 		s->blob = blob;
1924 		s->conn_state.connector = conn;
1925 		s->conn_state.secondary = NULL;
1926 		s->conn_state.type = conn->type;
1927 		if (split_conn) {
1928 			s->conn_state.secondary = split_conn;
1929 			s->conn_state.output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE;
1930 			s->conn_state.output_flags |= conn->id ? ROCKCHIP_OUTPUT_DATA_SWAP : 0;
1931 		}
1932 		s->conn_state.overscan.left_margin = 100;
1933 		s->conn_state.overscan.right_margin = 100;
1934 		s->conn_state.overscan.top_margin = 100;
1935 		s->conn_state.overscan.bottom_margin = 100;
1936 		s->crtc_state.node = np_to_ofnode(vop_node);
1937 		s->crtc_state.dev = crtc_dev;
1938 		s->crtc_state.crtc = crtc;
1939 		s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node), is_ports_node);
1940 		s->node = node;
1941 
1942 		if (is_ports_node) { /* only vop2 will get into here */
1943 			ofnode vp_node = np_to_ofnode(port_node);
1944 			static bool get_plane_mask_from_dts;
1945 
1946 			s->crtc_state.ports_node = port_parent_node;
1947 			if (!get_plane_mask_from_dts) {
1948 				ofnode vp_sub_node;
1949 				int vp_id = 0;
1950 				bool vp_enable = false;
1951 
1952 				ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
1953 					int cursor_plane = -1;
1954 
1955 					vp_id = ofnode_read_u32_default(vp_node, "reg", 0);
1956 
1957 					s->crtc_state.crtc->vps[vp_id].xmirror_en =
1958 						ofnode_read_bool(vp_node, "xmirror-enable");
1959 
1960 					ret = ofnode_read_u32_default(vp_node, "rockchip,plane-mask", 0);
1961 
1962 					cursor_plane = ofnode_read_u32_default(vp_node, "cursor-win-id", -1);
1963 					s->crtc_state.crtc->vps[vp_id].cursor_plane = cursor_plane;
1964 					if (ret) {
1965 						s->crtc_state.crtc->vps[vp_id].plane_mask = ret;
1966 						s->crtc_state.crtc->assign_plane |= true;
1967 						s->crtc_state.crtc->vps[vp_id].primary_plane_id =
1968 							ofnode_read_u32_default(vp_node, "rockchip,primary-plane", U8_MAX);
1969 						printf("get vp%d plane mask:0x%x, primary id:%d, cursor_plane:%d, from dts\n",
1970 						       vp_id,
1971 						       s->crtc_state.crtc->vps[vp_id].plane_mask,
1972 						       s->crtc_state.crtc->vps[vp_id].primary_plane_id == U8_MAX ? -1 :
1973 						       s->crtc_state.crtc->vps[vp_id].primary_plane_id,
1974 						       cursor_plane);
1975 					}
1976 
1977 					/* To check current vp status */
1978 					vp_enable = false;
1979 					ofnode_for_each_subnode(vp_sub_node, vp_node)
1980 						vp_enable |= rockchip_get_display_path_status(vp_sub_node);
1981 					s->crtc_state.crtc->vps[vp_id].enable = vp_enable;
1982 				}
1983 				get_plane_mask_from_dts = true;
1984 			}
1985 		}
1986 
1987 		get_crtc_mcu_mode(&s->crtc_state, port_node, is_ports_node);
1988 
1989 		ret = ofnode_read_u32_default(s->crtc_state.node,
1990 					      "rockchip,dual-channel-swap", 0);
1991 		s->crtc_state.dual_channel_swap = ret;
1992 
1993 		if (connector_phy_init(conn, data)) {
1994 			printf("Warn: Failed to init phy drivers\n");
1995 			free(s);
1996 			continue;
1997 		}
1998 		list_add_tail(&s->head, &rockchip_display_list);
1999 	}
2000 
2001 	if (list_empty(&rockchip_display_list)) {
2002 		debug("Failed to found available display route\n");
2003 		return -ENODEV;
2004 	}
2005 	rockchip_get_baseparameter();
2006 	display_pre_init();
2007 
2008 	uc_priv->xsize = DRM_ROCKCHIP_FB_WIDTH;
2009 	uc_priv->ysize = DRM_ROCKCHIP_FB_HEIGHT;
2010 	uc_priv->bpix = VIDEO_BPP32;
2011 
2012 	#ifdef CONFIG_DRM_ROCKCHIP_VIDEO_FRAMEBUFFER
2013 	rockchip_show_fbbase(plat->base);
2014 	video_set_flush_dcache(dev, true);
2015 	#endif
2016 
2017 	return 0;
2018 }
2019 
2020 void rockchip_display_fixup(void *blob)
2021 {
2022 	const struct rockchip_connector_funcs *conn_funcs;
2023 	const struct rockchip_crtc_funcs *crtc_funcs;
2024 	struct rockchip_connector *conn;
2025 	const struct rockchip_crtc *crtc;
2026 	struct display_state *s;
2027 	int offset;
2028 	int ret;
2029 	const struct device_node *np;
2030 	const char *path;
2031 	const char *cacm_header;
2032 	u64 aligned_memory_size;
2033 
2034 	if (fdt_node_offset_by_compatible(blob, 0, "rockchip,drm-logo") >= 0) {
2035 		list_for_each_entry(s, &rockchip_display_list, head) {
2036 			ret = load_bmp_logo(&s->logo, s->klogo_name);
2037 			if (ret < 0) {
2038 				s->is_klogo_valid = false;
2039 				printf("VP%d fail to load kernel logo\n", s->crtc_state.crtc_id);
2040 			} else {
2041 				s->is_klogo_valid = true;
2042 			}
2043 		}
2044 
2045 		if (!get_display_size())
2046 			return;
2047 
2048 		aligned_memory_size = (u64)ALIGN(get_display_size(), align_size);
2049 		offset = fdt_update_reserved_memory(blob, "rockchip,drm-logo",
2050 						    (u64)memory_start,
2051 						    aligned_memory_size);
2052 		if (offset < 0)
2053 			printf("failed to reserve drm-loader-logo memory\n");
2054 
2055 		if (get_cubic_memory_size()) {
2056 			aligned_memory_size = (u64)ALIGN(get_cubic_memory_size(), align_size);
2057 			offset = fdt_update_reserved_memory(blob, "rockchip,drm-cubic-lut",
2058 							    (u64)cubic_lut_memory_start,
2059 							    aligned_memory_size);
2060 			if (offset < 0)
2061 				printf("failed to reserve drm-cubic-lut memory\n");
2062 		}
2063 	} else {
2064 		printf("can't found rockchip,drm-logo, use rockchip,fb-logo\n");
2065 		/* Compatible with rkfb display, only need reserve memory */
2066 		offset = fdt_update_reserved_memory(blob, "rockchip,fb-logo",
2067 						    (u64)memory_start,
2068 						    MEMORY_POOL_SIZE);
2069 		if (offset < 0)
2070 			printf("failed to reserve fb-loader-logo memory\n");
2071 		else
2072 			list_for_each_entry(s, &rockchip_display_list, head)
2073 				load_kernel_bmp_logo(&s->logo, s->klogo_name);
2074 		return;
2075 	}
2076 
2077 	list_for_each_entry(s, &rockchip_display_list, head) {
2078 		/*
2079 		 * If plane mask is not set in dts, fixup dts to assign it
2080 		 * whether crtc is initialized or not.
2081 		 */
2082 		if (s->crtc_state.crtc->funcs->fixup_dts && !s->crtc_state.crtc->assign_plane)
2083 			s->crtc_state.crtc->funcs->fixup_dts(s, blob);
2084 
2085 		if (!s->is_init || !s->is_klogo_valid)
2086 			continue;
2087 
2088 		conn = s->conn_state.connector;
2089 		if (!conn)
2090 			continue;
2091 		conn_funcs = conn->funcs;
2092 		if (!conn_funcs) {
2093 			printf("failed to get exist connector\n");
2094 			continue;
2095 		}
2096 
2097 		if (s->conn_state.secondary &&
2098 		    s->conn_state.secondary->type != DRM_MODE_CONNECTOR_LVDS) {
2099 			s->conn_state.mode.clock *= 2;
2100 			s->conn_state.mode.hdisplay *= 2;
2101 		}
2102 
2103 		crtc = s->crtc_state.crtc;
2104 		if (!crtc)
2105 			continue;
2106 
2107 		crtc_funcs = crtc->funcs;
2108 		if (!crtc_funcs) {
2109 			printf("failed to get exist crtc\n");
2110 			continue;
2111 		}
2112 
2113 		np = ofnode_to_np(s->node);
2114 		path = np->full_name;
2115 		fdt_increase_size(blob, 0x400);
2116 #define FDT_SET_U32(name, val) \
2117 		do_fixup_by_path_u32(blob, path, name, val, 1);
2118 
2119 		offset = s->logo.offset + (u32)(unsigned long)s->logo.mem
2120 			 - memory_start;
2121 		FDT_SET_U32("logo,offset", offset);
2122 		FDT_SET_U32("logo,width", s->logo.width);
2123 		FDT_SET_U32("logo,height", s->logo.height);
2124 		FDT_SET_U32("logo,bpp", s->logo.bpp);
2125 		FDT_SET_U32("logo,ymirror", s->logo.ymirror);
2126 		FDT_SET_U32("video,clock", s->conn_state.mode.clock);
2127 		FDT_SET_U32("video,hdisplay", s->conn_state.mode.hdisplay);
2128 		FDT_SET_U32("video,vdisplay", s->conn_state.mode.vdisplay);
2129 		FDT_SET_U32("video,crtc_hsync_end", s->conn_state.mode.crtc_hsync_end);
2130 		FDT_SET_U32("video,crtc_vsync_end", s->conn_state.mode.crtc_vsync_end);
2131 		FDT_SET_U32("video,vrefresh",
2132 			    drm_mode_vrefresh(&s->conn_state.mode));
2133 		FDT_SET_U32("video,flags", s->conn_state.mode.flags);
2134 		FDT_SET_U32("video,aspect_ratio", s->conn_state.mode.picture_aspect_ratio);
2135 		FDT_SET_U32("overscan,left_margin", s->conn_state.overscan.left_margin);
2136 		FDT_SET_U32("overscan,right_margin", s->conn_state.overscan.right_margin);
2137 		FDT_SET_U32("overscan,top_margin", s->conn_state.overscan.top_margin);
2138 		FDT_SET_U32("overscan,bottom_margin", s->conn_state.overscan.bottom_margin);
2139 
2140 		if (s->conn_state.disp_info) {
2141 			cacm_header = (const char*)&s->conn_state.disp_info->cacm_header;
2142 
2143 			FDT_SET_U32("bcsh,brightness", s->conn_state.disp_info->bcsh_info.brightness);
2144 			FDT_SET_U32("bcsh,contrast", s->conn_state.disp_info->bcsh_info.contrast);
2145 			FDT_SET_U32("bcsh,saturation", s->conn_state.disp_info->bcsh_info.saturation);
2146 			FDT_SET_U32("bcsh,hue", s->conn_state.disp_info->bcsh_info.hue);
2147 
2148 			if (!strncasecmp(cacm_header, "CACM", 4)) {
2149 				FDT_SET_U32("post-csc,hue",
2150 					    s->conn_state.disp_info->csc_info.hue);
2151 				FDT_SET_U32("post-csc,saturation",
2152 					    s->conn_state.disp_info->csc_info.saturation);
2153 				FDT_SET_U32("post-csc,contrast",
2154 					    s->conn_state.disp_info->csc_info.contrast);
2155 				FDT_SET_U32("post-csc,brightness",
2156 					    s->conn_state.disp_info->csc_info.brightness);
2157 				FDT_SET_U32("post-csc,r-gain",
2158 					    s->conn_state.disp_info->csc_info.r_gain);
2159 				FDT_SET_U32("post-csc,g-gain",
2160 					    s->conn_state.disp_info->csc_info.g_gain);
2161 				FDT_SET_U32("post-csc,b-gain",
2162 					    s->conn_state.disp_info->csc_info.b_gain);
2163 				FDT_SET_U32("post-csc,r-offset",
2164 					    s->conn_state.disp_info->csc_info.r_offset);
2165 				FDT_SET_U32("post-csc,g-offset",
2166 					    s->conn_state.disp_info->csc_info.g_offset);
2167 				FDT_SET_U32("post-csc,b-offset",
2168 					    s->conn_state.disp_info->csc_info.b_offset);
2169 				FDT_SET_U32("post-csc,enable",
2170 					    s->conn_state.disp_info->csc_info.csc_enable);
2171 			}
2172 		}
2173 
2174 		if (s->conn_state.disp_info->cubic_lut_data.size &&
2175 		    CONFIG_ROCKCHIP_CUBIC_LUT_SIZE)
2176 			FDT_SET_U32("cubic_lut,offset", get_cubic_lut_offset(s->crtc_state.crtc_id));
2177 
2178 #undef FDT_SET_U32
2179 	}
2180 }
2181 
2182 int rockchip_display_bind(struct udevice *dev)
2183 {
2184 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
2185 
2186 	plat->size = DRM_ROCKCHIP_FB_SIZE + MEMORY_POOL_SIZE;
2187 
2188 	return 0;
2189 }
2190 
2191 static const struct udevice_id rockchip_display_ids[] = {
2192 	{ .compatible = "rockchip,display-subsystem" },
2193 	{ }
2194 };
2195 
2196 U_BOOT_DRIVER(rockchip_display) = {
2197 	.name	= "rockchip_display",
2198 	.id	= UCLASS_VIDEO,
2199 	.of_match = rockchip_display_ids,
2200 	.bind	= rockchip_display_bind,
2201 	.probe	= rockchip_display_probe,
2202 };
2203 
2204 static int do_rockchip_logo_show(cmd_tbl_t *cmdtp, int flag, int argc,
2205 			char *const argv[])
2206 {
2207 	if (argc != 1)
2208 		return CMD_RET_USAGE;
2209 
2210 	rockchip_show_logo();
2211 
2212 	return 0;
2213 }
2214 
2215 static int do_rockchip_show_bmp(cmd_tbl_t *cmdtp, int flag, int argc,
2216 				char *const argv[])
2217 {
2218 	if (argc != 2)
2219 		return CMD_RET_USAGE;
2220 
2221 	rockchip_show_bmp(argv[1]);
2222 
2223 	return 0;
2224 }
2225 
2226 static int do_rockchip_vop_dump(cmd_tbl_t *cmdtp, int flag, int argc,
2227 				char *const argv[])
2228 {
2229 	int ret;
2230 
2231 	if (argc < 1 || argc > 2)
2232 		return CMD_RET_USAGE;
2233 
2234 	ret = rockchip_vop_dump(argv[1]);
2235 
2236 	return ret;
2237 }
2238 
2239 U_BOOT_CMD(
2240 	rockchip_show_logo, 1, 1, do_rockchip_logo_show,
2241 	"load and display log from resource partition",
2242 	NULL
2243 );
2244 
2245 U_BOOT_CMD(
2246 	rockchip_show_bmp, 2, 1, do_rockchip_show_bmp,
2247 	"load and display bmp from resource partition",
2248 	"    <bmp_name>"
2249 );
2250 
2251 U_BOOT_CMD(
2252 	vop_dump, 2, 1, do_rockchip_vop_dump,
2253 	"dump vop regs",
2254 	" [a/all]"
2255 );
2256