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