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