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