xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_display.c (revision 50a9508e32cf56a7e685d0880ef25c4901ec202e)
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 memory_end;
58 static struct base2_info base_parameter;
59 static uint32_t crc32_table[256];
60 
61 /*
62  * the phy types are used by different connectors in public.
63  * The current version only has inno hdmi phy for hdmi and tve.
64  */
65 enum public_use_phy {
66 	NONE,
67 	INNO_HDMI_PHY
68 };
69 
70 /* save public phy data */
71 struct public_phy_data {
72 	const struct rockchip_phy *phy_drv;
73 	int phy_node;
74 	int public_phy_type;
75 	bool phy_init;
76 };
77 
78 void rockchip_display_make_crc32_table(void)
79 {
80 	uint32_t c;
81 	int n, k;
82 	unsigned long poly;		/* polynomial exclusive-or pattern */
83 	/* terms of polynomial defining this crc (except x^32): */
84 	static const char p[] = {0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26};
85 
86 	/* make exclusive-or pattern from polynomial (0xedb88320L) */
87 	poly = 0L;
88 	for (n = 0; n < sizeof(p) / sizeof(char); n++)
89 		poly |= 1L << (31 - p[n]);
90 
91 	for (n = 0; n < 256; n++) {
92 		c = (unsigned long)n;
93 		for (k = 0; k < 8; k++)
94 		c = c & 1 ? poly ^ (c >> 1) : c >> 1;
95 		crc32_table[n] = cpu_to_le32(c);
96 	}
97 }
98 
99 uint32_t rockchip_display_crc32c_cal(unsigned char *data, int length)
100 {
101 	int i;
102 	uint32_t crc;
103 	crc = 0xFFFFFFFF;
104 
105 	for (i = 0; i < length; i++) {
106 		crc = crc32_table[(crc ^ *data) & 0xff] ^ (crc >> 8);
107 		data++;
108 	}
109 
110 	return crc ^ 0xffffffff;
111 }
112 
113 int rockchip_get_baseparameter(void)
114 {
115 	struct blk_desc *dev_desc;
116 	disk_partition_t part_info;
117 	int block_num = 2048;
118 	char baseparameter_buf[block_num * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
119 	int ret = 0;
120 
121 	dev_desc = rockchip_get_bootdev();
122 	if (!dev_desc) {
123 		printf("%s: Could not find device\n", __func__);
124 		return -ENOENT;
125 	}
126 
127 	if (part_get_info_by_name(dev_desc, "baseparameter", &part_info) < 0) {
128 		printf("Could not find baseparameter partition\n");
129 		return -ENOENT;
130 	}
131 
132 	ret = blk_dread(dev_desc, part_info.start, block_num, (void *)baseparameter_buf);
133 	if (ret < 0) {
134 		printf("read baseparameter failed\n");
135 		return ret;
136 	}
137 
138 	memcpy(&base_parameter, baseparameter_buf, sizeof(base_parameter));
139 	if (strncasecmp(base_parameter.head_flag, "BASP", 4)) {
140 		printf("warning: bad baseparameter\n");
141 		memset(&base_parameter, 0, sizeof(base_parameter));
142 	}
143 	rockchip_display_make_crc32_table();
144 
145 	return ret;
146 }
147 
148 struct base2_disp_info *rockchip_get_disp_info(int type, int id)
149 {
150 	struct base2_disp_info *disp_info;
151 	int i = 0;
152 	u32 crc_val;
153 
154 	for (i = 0; i < 8; i++) {
155 		disp_info = &base_parameter.disp_info[i];
156 		if (disp_info->screen_info[0].type == type &&
157 		    disp_info->screen_info[0].id == id) {
158 			printf("disp info %d, type:%d, id:%d\n", i, type, id);
159 			break;
160 		}
161 	}
162 	if (strncasecmp(disp_info->disp_head_flag, "DISP", 4))
163 		return NULL;
164 
165 	crc_val = rockchip_display_crc32c_cal((unsigned char *)disp_info, sizeof(struct base2_disp_info) - 4);
166 
167 	if (crc_val != disp_info->crc) {
168 		printf("error: connector type[%d], id[%d] disp info crc check error\n", type, id);
169 		return NULL;
170 	}
171 
172 	return disp_info;
173 }
174 
175 /* check which kind of public phy does connector use */
176 static int check_public_use_phy(struct display_state *state)
177 {
178 	int ret = NONE;
179 #ifdef CONFIG_ROCKCHIP_INNO_HDMI_PHY
180 	struct connector_state *conn_state = &state->conn_state;
181 
182 	if (!strncmp(dev_read_name(conn_state->dev), "tve", 3) ||
183 	    !strncmp(dev_read_name(conn_state->dev), "hdmi", 4))
184 		ret = INNO_HDMI_PHY;
185 #endif
186 
187 	return ret;
188 }
189 
190 /*
191  * get public phy driver and initialize it.
192  * The current version only has inno hdmi phy for hdmi and tve.
193  */
194 static int get_public_phy(struct display_state *state,
195 			  struct public_phy_data *data)
196 {
197 	struct connector_state *conn_state = &state->conn_state;
198 	struct rockchip_phy *phy;
199 	struct udevice *dev;
200 	int ret = 0;
201 
202 	switch (data->public_phy_type) {
203 	case INNO_HDMI_PHY:
204 #if defined(CONFIG_ROCKCHIP_RK3328)
205 		ret = uclass_get_device_by_name(UCLASS_PHY,
206 						"hdmiphy@ff430000", &dev);
207 #elif defined(CONFIG_ROCKCHIP_RK322X)
208 		ret = uclass_get_device_by_name(UCLASS_PHY,
209 						"hdmi-phy@12030000", &dev);
210 #else
211 		ret = -EINVAL;
212 #endif
213 		if (ret) {
214 			printf("Warn: can't find phy driver\n");
215 			return 0;
216 		}
217 
218 		phy = (struct rockchip_phy *)dev_get_driver_data(dev);
219 		if (!phy) {
220 			printf("failed to get phy driver\n");
221 			return 0;
222 		}
223 
224 		ret = rockchip_phy_init(phy);
225 		if (ret) {
226 			printf("failed to init phy driver\n");
227 			return ret;
228 		}
229 		conn_state->phy = phy;
230 
231 		debug("inno hdmi phy init success, save it\n");
232 		data->phy_drv = conn_state->phy;
233 		data->phy_init = true;
234 		return 0;
235 	default:
236 		return -EINVAL;
237 	}
238 }
239 
240 static void init_display_buffer(ulong base)
241 {
242 	memory_start = base + DRM_ROCKCHIP_FB_SIZE;
243 	memory_end = memory_start;
244 }
245 
246 void *get_display_buffer(int size)
247 {
248 	unsigned long roundup_memory = roundup(memory_end, PAGE_SIZE);
249 	void *buf;
250 
251 	if (roundup_memory + size > memory_start + MEMORY_POOL_SIZE) {
252 		printf("failed to alloc %dbyte memory to display\n", size);
253 		return NULL;
254 	}
255 	buf = (void *)roundup_memory;
256 
257 	memory_end = roundup_memory + size;
258 
259 	return buf;
260 }
261 
262 static unsigned long get_display_size(void)
263 {
264 	return memory_end - memory_start;
265 }
266 
267 bool can_direct_logo(int bpp)
268 {
269 	return bpp == 24 || bpp == 32;
270 }
271 
272 static int connector_phy_init(struct display_state *state,
273 			      struct public_phy_data *data)
274 {
275 	struct connector_state *conn_state = &state->conn_state;
276 	int type;
277 
278 	/* does this connector use public phy with others */
279 	type = check_public_use_phy(state);
280 	if (type == INNO_HDMI_PHY) {
281 		/* there is no public phy was initialized */
282 		if (!data->phy_init) {
283 			debug("start get public phy\n");
284 			data->public_phy_type = type;
285 			if (get_public_phy(state, data)) {
286 				printf("can't find correct public phy type\n");
287 				free(data);
288 				return -EINVAL;
289 			}
290 			return 0;
291 		}
292 
293 		/* if this phy has been initialized, get it directly */
294 		conn_state->phy = (struct rockchip_phy *)data->phy_drv;
295 		return 0;
296 	}
297 
298 	return 0;
299 }
300 
301 static int connector_panel_init(struct display_state *state)
302 {
303 	struct connector_state *conn_state = &state->conn_state;
304 	struct panel_state *panel_state = &state->panel_state;
305 	const struct rockchip_panel *panel = panel_state->panel;
306 	ofnode dsp_lut_node;
307 	int ret, len;
308 
309 	if (!panel)
310 		return 0;
311 
312 	dsp_lut_node = dev_read_subnode(panel->dev, "dsp-lut");
313 	if (!ofnode_valid(dsp_lut_node)) {
314 		debug("%s can not find dsp-lut node\n", __func__);
315 		return 0;
316 	}
317 
318 	ofnode_get_property(dsp_lut_node, "gamma-lut", &len);
319 	if (len > 0) {
320 		conn_state->gamma.size = len / sizeof(u32);
321 		conn_state->gamma.lut = malloc(len);
322 		if (!conn_state->gamma.lut) {
323 			printf("malloc gamma lut failed\n");
324 			return -ENOMEM;
325 		}
326 		ret = ofnode_read_u32_array(dsp_lut_node, "gamma-lut",
327 					    conn_state->gamma.lut,
328 					    conn_state->gamma.size);
329 		if (ret) {
330 			printf("Cannot decode gamma_lut\n");
331 			conn_state->gamma.lut = NULL;
332 			return -EINVAL;
333 		}
334 		panel_state->dsp_lut_node = dsp_lut_node;
335 	}
336 
337 	return 0;
338 }
339 
340 int drm_mode_vrefresh(const struct drm_display_mode *mode)
341 {
342 	int refresh = 0;
343 	unsigned int calc_val;
344 
345 	if (mode->vrefresh > 0) {
346 		refresh = mode->vrefresh;
347 	} else if (mode->htotal > 0 && mode->vtotal > 0) {
348 		int vtotal;
349 
350 		vtotal = mode->vtotal;
351 		/* work out vrefresh the value will be x1000 */
352 		calc_val = (mode->clock * 1000);
353 		calc_val /= mode->htotal;
354 		refresh = (calc_val + vtotal / 2) / vtotal;
355 
356 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
357 			refresh *= 2;
358 		if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
359 			refresh /= 2;
360 		if (mode->vscan > 1)
361 			refresh /= mode->vscan;
362 	}
363 	return refresh;
364 }
365 
366 static int display_get_timing_from_dts(struct panel_state *panel_state,
367 				       struct drm_display_mode *mode)
368 {
369 	struct rockchip_panel *panel = panel_state->panel;
370 	int phandle;
371 	int hactive, vactive, pixelclock;
372 	int hfront_porch, hback_porch, hsync_len;
373 	int vfront_porch, vback_porch, vsync_len;
374 	int val, flags = 0;
375 	ofnode timing, native_mode;
376 
377 	timing = dev_read_subnode(panel->dev, "display-timings");
378 	if (!ofnode_valid(timing))
379 		return -ENODEV;
380 
381 	native_mode = ofnode_find_subnode(timing, "timing");
382 	if (!ofnode_valid(native_mode)) {
383 		phandle = ofnode_read_u32_default(timing, "native-mode", -1);
384 		native_mode = np_to_ofnode(of_find_node_by_phandle(phandle));
385 		if (!ofnode_valid(native_mode)) {
386 			printf("failed to get display timings from DT\n");
387 			return -ENXIO;
388 		}
389 	}
390 
391 #define FDT_GET_INT(val, name) \
392 	val = ofnode_read_s32_default(native_mode, name, -1); \
393 	if (val < 0) { \
394 		printf("Can't get %s\n", name); \
395 		return -ENXIO; \
396 	}
397 
398 #define FDT_GET_INT_DEFAULT(val, name, default) \
399 	val = ofnode_read_s32_default(native_mode, name, default);
400 
401 	FDT_GET_INT(hactive, "hactive");
402 	FDT_GET_INT(vactive, "vactive");
403 	FDT_GET_INT(pixelclock, "clock-frequency");
404 	FDT_GET_INT(hsync_len, "hsync-len");
405 	FDT_GET_INT(hfront_porch, "hfront-porch");
406 	FDT_GET_INT(hback_porch, "hback-porch");
407 	FDT_GET_INT(vsync_len, "vsync-len");
408 	FDT_GET_INT(vfront_porch, "vfront-porch");
409 	FDT_GET_INT(vback_porch, "vback-porch");
410 	FDT_GET_INT(val, "hsync-active");
411 	flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
412 	FDT_GET_INT(val, "vsync-active");
413 	flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
414 	FDT_GET_INT(val, "pixelclk-active");
415 	flags |= val ? DRM_MODE_FLAG_PPIXDATA : 0;
416 
417 	FDT_GET_INT_DEFAULT(val, "screen-rotate", 0);
418 	if (val == DRM_MODE_FLAG_XMIRROR) {
419 		flags |= DRM_MODE_FLAG_XMIRROR;
420 	} else if (val == DRM_MODE_FLAG_YMIRROR) {
421 		flags |= DRM_MODE_FLAG_YMIRROR;
422 	} else if (val == DRM_MODE_FLAG_XYMIRROR) {
423 		flags |= DRM_MODE_FLAG_XMIRROR;
424 		flags |= DRM_MODE_FLAG_YMIRROR;
425 	}
426 	mode->hdisplay = hactive;
427 	mode->hsync_start = mode->hdisplay + hfront_porch;
428 	mode->hsync_end = mode->hsync_start + hsync_len;
429 	mode->htotal = mode->hsync_end + hback_porch;
430 
431 	mode->vdisplay = vactive;
432 	mode->vsync_start = mode->vdisplay + vfront_porch;
433 	mode->vsync_end = mode->vsync_start + vsync_len;
434 	mode->vtotal = mode->vsync_end + vback_porch;
435 
436 	mode->clock = pixelclock / 1000;
437 	mode->flags = flags;
438 
439 	return 0;
440 }
441 
442 /**
443  * drm_mode_max_resolution_filter - mark modes out of vop max resolution
444  * @edid_data: structure store mode list
445  * @max_output: vop max output resolution
446  */
447 void drm_mode_max_resolution_filter(struct hdmi_edid_data *edid_data,
448 				    struct vop_rect *max_output)
449 {
450 	int i;
451 
452 	for (i = 0; i < edid_data->modes; i++) {
453 		if (edid_data->mode_buf[i].hdisplay > max_output->width ||
454 		    edid_data->mode_buf[i].vdisplay > max_output->height)
455 			edid_data->mode_buf[i].invalid = true;
456 	}
457 }
458 
459 /**
460  * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
461  * @p: mode
462  * @adjust_flags: a combination of adjustment flags
463  *
464  * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
465  *
466  * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
467  *   interlaced modes.
468  * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
469  *   buffers containing two eyes (only adjust the timings when needed, eg. for
470  *   "frame packing" or "side by side full").
471  * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
472  *   be performed for doublescan and vscan > 1 modes respectively.
473  */
474 void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
475 {
476 	if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
477 		return;
478 
479 	if (p->flags & DRM_MODE_FLAG_DBLCLK)
480 		p->crtc_clock = 2 * p->clock;
481 	else
482 		p->crtc_clock = p->clock;
483 	p->crtc_hdisplay = p->hdisplay;
484 	p->crtc_hsync_start = p->hsync_start;
485 	p->crtc_hsync_end = p->hsync_end;
486 	p->crtc_htotal = p->htotal;
487 	p->crtc_hskew = p->hskew;
488 	p->crtc_vdisplay = p->vdisplay;
489 	p->crtc_vsync_start = p->vsync_start;
490 	p->crtc_vsync_end = p->vsync_end;
491 	p->crtc_vtotal = p->vtotal;
492 
493 	if (p->flags & DRM_MODE_FLAG_INTERLACE) {
494 		if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
495 			p->crtc_vdisplay /= 2;
496 			p->crtc_vsync_start /= 2;
497 			p->crtc_vsync_end /= 2;
498 			p->crtc_vtotal /= 2;
499 		}
500 	}
501 
502 	if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
503 		if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
504 			p->crtc_vdisplay *= 2;
505 			p->crtc_vsync_start *= 2;
506 			p->crtc_vsync_end *= 2;
507 			p->crtc_vtotal *= 2;
508 		}
509 	}
510 
511 	if (!(adjust_flags & CRTC_NO_VSCAN)) {
512 		if (p->vscan > 1) {
513 			p->crtc_vdisplay *= p->vscan;
514 			p->crtc_vsync_start *= p->vscan;
515 			p->crtc_vsync_end *= p->vscan;
516 			p->crtc_vtotal *= p->vscan;
517 		}
518 	}
519 
520 	if (adjust_flags & CRTC_STEREO_DOUBLE) {
521 		unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
522 
523 		switch (layout) {
524 		case DRM_MODE_FLAG_3D_FRAME_PACKING:
525 			p->crtc_clock *= 2;
526 			p->crtc_vdisplay += p->crtc_vtotal;
527 			p->crtc_vsync_start += p->crtc_vtotal;
528 			p->crtc_vsync_end += p->crtc_vtotal;
529 			p->crtc_vtotal += p->crtc_vtotal;
530 			break;
531 		}
532 	}
533 
534 	p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
535 	p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
536 	p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
537 	p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
538 }
539 
540 /**
541  * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
542  * output format
543  *
544  * @connector: drm connector under action.
545  * @mode: video mode to be tested.
546  *
547  * Returns:
548  * true if the mode can be supported in YCBCR420 format
549  * false if not.
550  */
551 bool drm_mode_is_420_only(const struct drm_display_info *display,
552 			  struct drm_display_mode *mode)
553 {
554 	u8 vic = drm_match_cea_mode(mode);
555 
556 	return test_bit(vic, display->hdmi.y420_vdb_modes);
557 }
558 
559 /**
560  * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
561  * output format also (along with RGB/YCBCR444/422)
562  *
563  * @display: display under action.
564  * @mode: video mode to be tested.
565  *
566  * Returns:
567  * true if the mode can be support YCBCR420 format
568  * false if not.
569  */
570 bool drm_mode_is_420_also(const struct drm_display_info *display,
571 			  struct drm_display_mode *mode)
572 {
573 	u8 vic = drm_match_cea_mode(mode);
574 
575 	return test_bit(vic, display->hdmi.y420_cmdb_modes);
576 }
577 
578 /**
579  * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
580  * output format
581  *
582  * @display: display under action.
583  * @mode: video mode to be tested.
584  *
585  * Returns:
586  * true if the mode can be supported in YCBCR420 format
587  * false if not.
588  */
589 bool drm_mode_is_420(const struct drm_display_info *display,
590 		     struct drm_display_mode *mode)
591 {
592 	return drm_mode_is_420_only(display, mode) ||
593 		drm_mode_is_420_also(display, mode);
594 }
595 
596 static int display_get_timing(struct display_state *state)
597 {
598 	struct connector_state *conn_state = &state->conn_state;
599 	struct drm_display_mode *mode = &conn_state->mode;
600 	const struct drm_display_mode *m;
601 	struct panel_state *panel_state = &state->panel_state;
602 	const struct rockchip_panel *panel = panel_state->panel;
603 
604 	if (dev_of_valid(panel->dev) &&
605 	    !display_get_timing_from_dts(panel_state, mode)) {
606 		printf("Using display timing dts\n");
607 		return 0;
608 	}
609 
610 	if (panel->data) {
611 		m = (const struct drm_display_mode *)panel->data;
612 		memcpy(mode, m, sizeof(*m));
613 		printf("Using display timing from compatible panel driver\n");
614 		return 0;
615 	}
616 
617 	return -ENODEV;
618 }
619 
620 static int display_pre_init(void)
621 {
622 	struct display_state *state;
623 	int ret = 0;
624 
625 	list_for_each_entry(state, &rockchip_display_list, head) {
626 		struct connector_state *conn_state = &state->conn_state;
627 		const struct rockchip_connector *conn = conn_state->connector;
628 		const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
629 		struct crtc_state *crtc_state = &state->crtc_state;
630 		struct rockchip_crtc *crtc = crtc_state->crtc;
631 
632 		if (conn_funcs->pre_init) {
633 			ret = conn_funcs->pre_init(state);
634 			if (ret)
635 				printf("pre init conn error\n");
636 		}
637 		crtc->vps[crtc_state->crtc_id].output_type = conn_state->type;
638 	}
639 	return ret;
640 }
641 
642 static int display_init(struct display_state *state)
643 {
644 	struct connector_state *conn_state = &state->conn_state;
645 	struct panel_state *panel_state = &state->panel_state;
646 	const struct rockchip_connector *conn = conn_state->connector;
647 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
648 	struct crtc_state *crtc_state = &state->crtc_state;
649 	struct rockchip_crtc *crtc = crtc_state->crtc;
650 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
651 	struct drm_display_mode *mode = &conn_state->mode;
652 	const char *compatible;
653 	int ret = 0;
654 	static bool __print_once = false;
655 #if defined(CONFIG_I2C_EDID)
656 	int bpc;
657 #endif
658 	if (!__print_once) {
659 		__print_once = true;
660 		printf("Rockchip UBOOT DRM driver version: %s\n", DRIVER_VERSION);
661 	}
662 
663 	if (state->is_init)
664 		return 0;
665 
666 	if (!conn_funcs || !crtc_funcs) {
667 		printf("failed to find connector or crtc functions\n");
668 		return -ENXIO;
669 	}
670 
671 	if (crtc_state->crtc->active && !crtc_state->ports_node &&
672 	    memcmp(&crtc_state->crtc->active_mode, &conn_state->mode,
673 		   sizeof(struct drm_display_mode))) {
674 		printf("%s has been used for output type: %d, mode: %dx%dp%d\n",
675 			crtc_state->dev->name,
676 			crtc_state->crtc->active_mode.type,
677 			crtc_state->crtc->active_mode.hdisplay,
678 			crtc_state->crtc->active_mode.vdisplay,
679 			crtc_state->crtc->active_mode.vrefresh);
680 		return -ENODEV;
681 	}
682 
683 	if (crtc_funcs->preinit) {
684 		ret = crtc_funcs->preinit(state);
685 		if (ret)
686 			return ret;
687 	}
688 
689 	if (panel_state->panel)
690 		rockchip_panel_init(panel_state->panel);
691 
692 	if (conn_funcs->init) {
693 		ret = conn_funcs->init(state);
694 		if (ret)
695 			goto deinit;
696 	}
697 
698 	if (conn_state->phy)
699 		rockchip_phy_init(conn_state->phy);
700 
701 	/*
702 	 * support hotplug, but not connect;
703 	 */
704 #ifdef CONFIG_ROCKCHIP_DRM_TVE
705 	if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_TV) {
706 		printf("hdmi plugin ,skip tve\n");
707 		goto deinit;
708 	}
709 #elif defined(CONFIG_DRM_ROCKCHIP_RK1000)
710 	if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_LVDS) {
711 		printf("hdmi plugin ,skip tve\n");
712 		goto deinit;
713 	}
714 #endif
715 	if (conn_funcs->detect) {
716 		ret = conn_funcs->detect(state);
717 #if defined(CONFIG_ROCKCHIP_DRM_TVE) || defined(CONFIG_DRM_ROCKCHIP_RK1000)
718 		if (conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
719 			crtc->hdmi_hpd = ret;
720 #endif
721 		if (!ret)
722 			goto deinit;
723 	}
724 
725 	if (panel_state->panel) {
726 		ret = display_get_timing(state);
727 		if (!ret)
728 			conn_state->bpc = panel_state->panel->bpc;
729 #if defined(CONFIG_I2C_EDID)
730 		if (ret < 0 && conn_funcs->get_edid) {
731 			rockchip_panel_prepare(panel_state->panel);
732 
733 			ret = conn_funcs->get_edid(state);
734 			if (!ret) {
735 				ret = edid_get_drm_mode((void *)&conn_state->edid,
736 							sizeof(conn_state->edid),
737 							mode, &bpc);
738 				if (!ret) {
739 					conn_state->bpc = bpc;
740 					edid_print_info((void *)&conn_state->edid);
741 				}
742 			}
743 		}
744 #endif
745 	} else if (conn_state->bridge) {
746 		ret = video_bridge_read_edid(conn_state->bridge->dev,
747 					     conn_state->edid, EDID_SIZE);
748 		if (ret > 0) {
749 #if defined(CONFIG_I2C_EDID)
750 			ret = edid_get_drm_mode(conn_state->edid, ret, mode,
751 						&bpc);
752 			if (!ret) {
753 				conn_state->bpc = bpc;
754 				edid_print_info((void *)&conn_state->edid);
755 			}
756 #endif
757 		} else {
758 			ret = video_bridge_get_timing(conn_state->bridge->dev);
759 		}
760 	} else if (conn_funcs->get_timing) {
761 		ret = conn_funcs->get_timing(state);
762 	} else if (conn_funcs->get_edid) {
763 		ret = conn_funcs->get_edid(state);
764 #if defined(CONFIG_I2C_EDID)
765 		if (!ret) {
766 			ret = edid_get_drm_mode((void *)&conn_state->edid,
767 						sizeof(conn_state->edid), mode,
768 						&bpc);
769 			if (!ret) {
770 				conn_state->bpc = bpc;
771 				edid_print_info((void *)&conn_state->edid);
772 			}
773 		}
774 #endif
775 	}
776 
777 	if (ret)
778 		goto deinit;
779 
780 	/* rk356x series drive mipi pixdata on posedge */
781 	compatible = dev_read_string(conn_state->dev, "compatible");
782 	if (!strcmp(compatible, "rockchip,rk3568-mipi-dsi"))
783 		conn_state->mode.flags |= DRM_MODE_FLAG_PPIXDATA;
784 
785 	printf("Detailed mode clock %u kHz, flags[%x]\n"
786 	       "    H: %04d %04d %04d %04d\n"
787 	       "    V: %04d %04d %04d %04d\n"
788 	       "bus_format: %x\n",
789 	       mode->clock, mode->flags,
790 	       mode->hdisplay, mode->hsync_start,
791 	       mode->hsync_end, mode->htotal,
792 	       mode->vdisplay, mode->vsync_start,
793 	       mode->vsync_end, mode->vtotal,
794 	       conn_state->bus_format);
795 
796 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
797 
798 	if (conn_state->bridge)
799 		rockchip_bridge_mode_set(conn_state->bridge, &conn_state->mode);
800 
801 	if (crtc_funcs->init) {
802 		ret = crtc_funcs->init(state);
803 		if (ret)
804 			goto deinit;
805 	}
806 	state->is_init = 1;
807 
808 	crtc_state->crtc->active = true;
809 	memcpy(&crtc_state->crtc->active_mode,
810 	       &conn_state->mode, sizeof(struct drm_display_mode));
811 
812 	return 0;
813 
814 deinit:
815 	if (conn_funcs->deinit)
816 		conn_funcs->deinit(state);
817 	return ret;
818 }
819 
820 int display_send_mcu_cmd(struct display_state *state, u32 type, u32 val)
821 {
822 	struct crtc_state *crtc_state = &state->crtc_state;
823 	const struct rockchip_crtc *crtc = crtc_state->crtc;
824 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
825 	int ret;
826 
827 	if (!state->is_init)
828 		return -EINVAL;
829 
830 	if (crtc_funcs->send_mcu_cmd) {
831 		ret = crtc_funcs->send_mcu_cmd(state, type, val);
832 		if (ret)
833 			return ret;
834 	}
835 
836 	return 0;
837 }
838 
839 static int display_set_plane(struct display_state *state)
840 {
841 	struct crtc_state *crtc_state = &state->crtc_state;
842 	const struct rockchip_crtc *crtc = crtc_state->crtc;
843 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
844 	int ret;
845 
846 	if (!state->is_init)
847 		return -EINVAL;
848 
849 	if (crtc_funcs->set_plane) {
850 		ret = crtc_funcs->set_plane(state);
851 		if (ret)
852 			return ret;
853 	}
854 
855 	return 0;
856 }
857 
858 static int display_enable(struct display_state *state)
859 {
860 	struct connector_state *conn_state = &state->conn_state;
861 	const struct rockchip_connector *conn = conn_state->connector;
862 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
863 	struct crtc_state *crtc_state = &state->crtc_state;
864 	const struct rockchip_crtc *crtc = crtc_state->crtc;
865 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
866 	struct panel_state *panel_state = &state->panel_state;
867 
868 	if (!state->is_init)
869 		return -EINVAL;
870 
871 	if (state->is_enable)
872 		return 0;
873 
874 	if (crtc_funcs->prepare)
875 		crtc_funcs->prepare(state);
876 
877 	if (conn_funcs->prepare)
878 		conn_funcs->prepare(state);
879 
880 	if (conn_state->bridge)
881 		rockchip_bridge_pre_enable(conn_state->bridge);
882 
883 	if (panel_state->panel)
884 		rockchip_panel_prepare(panel_state->panel);
885 
886 	if (crtc_funcs->enable)
887 		crtc_funcs->enable(state);
888 
889 	if (conn_funcs->enable)
890 		conn_funcs->enable(state);
891 
892 	if (conn_state->bridge)
893 		rockchip_bridge_enable(conn_state->bridge);
894 
895 	if (panel_state->panel)
896 		rockchip_panel_enable(panel_state->panel);
897 
898 	state->is_enable = true;
899 
900 	return 0;
901 }
902 
903 static int display_disable(struct display_state *state)
904 {
905 	struct connector_state *conn_state = &state->conn_state;
906 	const struct rockchip_connector *conn = conn_state->connector;
907 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
908 	struct crtc_state *crtc_state = &state->crtc_state;
909 	const struct rockchip_crtc *crtc = crtc_state->crtc;
910 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
911 	struct panel_state *panel_state = &state->panel_state;
912 
913 	if (!state->is_init)
914 		return 0;
915 
916 	if (!state->is_enable)
917 		return 0;
918 
919 	if (panel_state->panel)
920 		rockchip_panel_disable(panel_state->panel);
921 
922 	if (conn_state->bridge)
923 		rockchip_bridge_disable(conn_state->bridge);
924 
925 	if (conn_funcs->disable)
926 		conn_funcs->disable(state);
927 
928 	if (crtc_funcs->disable)
929 		crtc_funcs->disable(state);
930 
931 	if (panel_state->panel)
932 		rockchip_panel_unprepare(panel_state->panel);
933 
934 	if (conn_state->bridge)
935 		rockchip_bridge_post_disable(conn_state->bridge);
936 
937 	if (conn_funcs->unprepare)
938 		conn_funcs->unprepare(state);
939 
940 	state->is_enable = 0;
941 	state->is_init = 0;
942 
943 	return 0;
944 }
945 
946 static int display_logo(struct display_state *state)
947 {
948 	struct crtc_state *crtc_state = &state->crtc_state;
949 	struct connector_state *conn_state = &state->conn_state;
950 	struct logo_info *logo = &state->logo;
951 	int hdisplay, vdisplay, ret;
952 
953 	ret = display_init(state);
954 	if (!state->is_init || ret)
955 		return -ENODEV;
956 
957 	switch (logo->bpp) {
958 	case 16:
959 		crtc_state->format = ROCKCHIP_FMT_RGB565;
960 		break;
961 	case 24:
962 		crtc_state->format = ROCKCHIP_FMT_RGB888;
963 		break;
964 	case 32:
965 		crtc_state->format = ROCKCHIP_FMT_ARGB8888;
966 		break;
967 	default:
968 		printf("can't support bmp bits[%d]\n", logo->bpp);
969 		return -EINVAL;
970 	}
971 	hdisplay = conn_state->mode.hdisplay;
972 	vdisplay = conn_state->mode.vdisplay;
973 	crtc_state->src_w = logo->width;
974 	crtc_state->src_h = logo->height;
975 	crtc_state->src_x = 0;
976 	crtc_state->src_y = 0;
977 	crtc_state->ymirror = logo->ymirror;
978 
979 	crtc_state->dma_addr = (u32)(unsigned long)logo->mem + logo->offset;
980 	crtc_state->xvir = ALIGN(crtc_state->src_w * logo->bpp, 32) >> 5;
981 
982 	if (logo->mode == ROCKCHIP_DISPLAY_FULLSCREEN) {
983 		crtc_state->crtc_x = 0;
984 		crtc_state->crtc_y = 0;
985 		crtc_state->crtc_w = hdisplay;
986 		crtc_state->crtc_h = vdisplay;
987 	} else {
988 		if (crtc_state->src_w >= hdisplay) {
989 			crtc_state->crtc_x = 0;
990 			crtc_state->crtc_w = hdisplay;
991 		} else {
992 			crtc_state->crtc_x = (hdisplay - crtc_state->src_w) / 2;
993 			crtc_state->crtc_w = crtc_state->src_w;
994 		}
995 
996 		if (crtc_state->src_h >= vdisplay) {
997 			crtc_state->crtc_y = 0;
998 			crtc_state->crtc_h = vdisplay;
999 		} else {
1000 			crtc_state->crtc_y = (vdisplay - crtc_state->src_h) / 2;
1001 			crtc_state->crtc_h = crtc_state->src_h;
1002 		}
1003 	}
1004 
1005 	display_set_plane(state);
1006 	display_enable(state);
1007 
1008 	return 0;
1009 }
1010 
1011 static int get_crtc_id(ofnode connect)
1012 {
1013 	int phandle;
1014 	struct device_node *remote;
1015 	int val;
1016 
1017 	phandle = ofnode_read_u32_default(connect, "remote-endpoint", -1);
1018 	if (phandle < 0)
1019 		goto err;
1020 	remote = of_find_node_by_phandle(phandle);
1021 	val = ofnode_read_u32_default(np_to_ofnode(remote), "reg", -1);
1022 	if (val < 0)
1023 		goto err;
1024 
1025 	return val;
1026 err:
1027 	printf("Can't get crtc id, default set to id = 0\n");
1028 	return 0;
1029 }
1030 
1031 static int get_crtc_mcu_mode(struct crtc_state *crtc_state)
1032 {
1033 	ofnode mcu_node;
1034 	int total_pixel, cs_pst, cs_pend, rw_pst, rw_pend;
1035 
1036 	mcu_node = dev_read_subnode(crtc_state->dev, "mcu-timing");
1037 	if (!ofnode_valid(mcu_node))
1038 		return -ENODEV;
1039 
1040 #define FDT_GET_MCU_INT(val, name) \
1041 	do { \
1042 		val = ofnode_read_s32_default(mcu_node, name, -1); \
1043 		if (val < 0) { \
1044 			printf("Can't get %s\n", name); \
1045 			return -ENXIO; \
1046 		} \
1047 	} while (0)
1048 
1049 	FDT_GET_MCU_INT(total_pixel, "mcu-pix-total");
1050 	FDT_GET_MCU_INT(cs_pst, "mcu-cs-pst");
1051 	FDT_GET_MCU_INT(cs_pend, "mcu-cs-pend");
1052 	FDT_GET_MCU_INT(rw_pst, "mcu-rw-pst");
1053 	FDT_GET_MCU_INT(rw_pend, "mcu-rw-pend");
1054 
1055 	crtc_state->mcu_timing.mcu_pix_total = total_pixel;
1056 	crtc_state->mcu_timing.mcu_cs_pst = cs_pst;
1057 	crtc_state->mcu_timing.mcu_cs_pend = cs_pend;
1058 	crtc_state->mcu_timing.mcu_rw_pst = rw_pst;
1059 	crtc_state->mcu_timing.mcu_rw_pend = rw_pend;
1060 
1061 	return 0;
1062 }
1063 
1064 struct rockchip_logo_cache *find_or_alloc_logo_cache(const char *bmp)
1065 {
1066 	struct rockchip_logo_cache *tmp, *logo_cache = NULL;
1067 
1068 	list_for_each_entry(tmp, &logo_cache_list, head) {
1069 		if (!strcmp(tmp->name, bmp)) {
1070 			logo_cache = tmp;
1071 			break;
1072 		}
1073 	}
1074 
1075 	if (!logo_cache) {
1076 		logo_cache = malloc(sizeof(*logo_cache));
1077 		if (!logo_cache) {
1078 			printf("failed to alloc memory for logo cache\n");
1079 			return NULL;
1080 		}
1081 		memset(logo_cache, 0, sizeof(*logo_cache));
1082 		strcpy(logo_cache->name, bmp);
1083 		INIT_LIST_HEAD(&logo_cache->head);
1084 		list_add_tail(&logo_cache->head, &logo_cache_list);
1085 	}
1086 
1087 	return logo_cache;
1088 }
1089 
1090 /* Note: used only for rkfb kernel driver */
1091 static int load_kernel_bmp_logo(struct logo_info *logo, const char *bmp_name)
1092 {
1093 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
1094 	void *dst = NULL;
1095 	int len, size;
1096 	struct bmp_header *header;
1097 
1098 	if (!logo || !bmp_name)
1099 		return -EINVAL;
1100 
1101 	header = malloc(RK_BLK_SIZE);
1102 	if (!header)
1103 		return -ENOMEM;
1104 
1105 	len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
1106 	if (len != RK_BLK_SIZE) {
1107 		free(header);
1108 		return -EINVAL;
1109 	}
1110 	size = get_unaligned_le32(&header->file_size);
1111 	dst = (void *)(memory_start + MEMORY_POOL_SIZE / 2);
1112 	len = rockchip_read_resource_file(dst, bmp_name, 0, size);
1113 	if (len != size) {
1114 		printf("failed to load bmp %s\n", bmp_name);
1115 		free(header);
1116 		return -ENOENT;
1117 	}
1118 
1119 	logo->mem = dst;
1120 #endif
1121 
1122 	return 0;
1123 }
1124 
1125 static int load_bmp_logo(struct logo_info *logo, const char *bmp_name)
1126 {
1127 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
1128 	struct rockchip_logo_cache *logo_cache;
1129 	struct bmp_header *header;
1130 	void *dst = NULL, *pdst;
1131 	int size, len;
1132 	int ret = 0;
1133 	int reserved = 0;
1134 
1135 	if (!logo || !bmp_name)
1136 		return -EINVAL;
1137 	logo_cache = find_or_alloc_logo_cache(bmp_name);
1138 	if (!logo_cache)
1139 		return -ENOMEM;
1140 
1141 	if (logo_cache->logo.mem) {
1142 		memcpy(logo, &logo_cache->logo, sizeof(*logo));
1143 		return 0;
1144 	}
1145 
1146 	header = malloc(RK_BLK_SIZE);
1147 	if (!header)
1148 		return -ENOMEM;
1149 
1150 	len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
1151 	if (len != RK_BLK_SIZE) {
1152 		ret = -EINVAL;
1153 		goto free_header;
1154 	}
1155 
1156 	logo->bpp = get_unaligned_le16(&header->bit_count);
1157 	logo->width = get_unaligned_le32(&header->width);
1158 	logo->height = get_unaligned_le32(&header->height);
1159 	reserved = get_unaligned_le32(&header->reserved);
1160 	if (logo->height < 0)
1161 	    logo->height = -logo->height;
1162 	size = get_unaligned_le32(&header->file_size);
1163 	if (!can_direct_logo(logo->bpp)) {
1164 		if (size > MEMORY_POOL_SIZE) {
1165 			printf("failed to use boot buf as temp bmp buffer\n");
1166 			ret = -ENOMEM;
1167 			goto free_header;
1168 		}
1169 		pdst = get_display_buffer(size);
1170 
1171 	} else {
1172 		pdst = get_display_buffer(size);
1173 		dst = pdst;
1174 	}
1175 
1176 	len = rockchip_read_resource_file(pdst, bmp_name, 0, size);
1177 	if (len != size) {
1178 		printf("failed to load bmp %s\n", bmp_name);
1179 		ret = -ENOENT;
1180 		goto free_header;
1181 	}
1182 
1183 	if (!can_direct_logo(logo->bpp)) {
1184 		int dst_size;
1185 		/*
1186 		 * TODO: force use 16bpp if bpp less than 16;
1187 		 */
1188 		logo->bpp = (logo->bpp <= 16) ? 16 : logo->bpp;
1189 		dst_size = logo->width * logo->height * logo->bpp >> 3;
1190 
1191 		dst = get_display_buffer(dst_size);
1192 		if (!dst) {
1193 			ret = -ENOMEM;
1194 			goto free_header;
1195 		}
1196 		if (bmpdecoder(pdst, dst, logo->bpp)) {
1197 			printf("failed to decode bmp %s\n", bmp_name);
1198 			ret = -EINVAL;
1199 			goto free_header;
1200 		}
1201 		flush_dcache_range((ulong)dst,
1202 				   ALIGN((ulong)dst + dst_size,
1203 					 CONFIG_SYS_CACHELINE_SIZE));
1204 
1205 		logo->offset = 0;
1206 		logo->ymirror = 0;
1207 	} else {
1208 		logo->offset = get_unaligned_le32(&header->data_offset);
1209 		if (reserved == BMP_PROCESSED_FLAG)
1210 			logo->ymirror = 0;
1211 		else
1212 			logo->ymirror = 1;
1213 	}
1214 	logo->mem = dst;
1215 
1216 	memcpy(&logo_cache->logo, logo, sizeof(*logo));
1217 
1218 free_header:
1219 
1220 	free(header);
1221 
1222 	return ret;
1223 #else
1224 	return -EINVAL;
1225 #endif
1226 }
1227 
1228 void rockchip_show_fbbase(ulong fbbase)
1229 {
1230 	struct display_state *s;
1231 
1232 	list_for_each_entry(s, &rockchip_display_list, head) {
1233 		s->logo.mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1234 		s->logo.mem = (char *)fbbase;
1235 		s->logo.width = DRM_ROCKCHIP_FB_WIDTH;
1236 		s->logo.height = DRM_ROCKCHIP_FB_HEIGHT;
1237 		s->logo.bpp = 32;
1238 		s->logo.ymirror = 0;
1239 
1240 		display_logo(s);
1241 	}
1242 }
1243 
1244 int rockchip_show_bmp(const char *bmp)
1245 {
1246 	struct display_state *s;
1247 	int ret = 0;
1248 
1249 	if (!bmp) {
1250 		list_for_each_entry(s, &rockchip_display_list, head)
1251 			display_disable(s);
1252 		return -ENOENT;
1253 	}
1254 
1255 	list_for_each_entry(s, &rockchip_display_list, head) {
1256 		s->logo.mode = s->charge_logo_mode;
1257 		if (load_bmp_logo(&s->logo, bmp))
1258 			continue;
1259 		ret = display_logo(s);
1260 	}
1261 
1262 	return ret;
1263 }
1264 
1265 int rockchip_show_logo(void)
1266 {
1267 	struct display_state *s;
1268 	int ret = 0;
1269 
1270 	list_for_each_entry(s, &rockchip_display_list, head) {
1271 		s->logo.mode = s->logo_mode;
1272 		if (load_bmp_logo(&s->logo, s->ulogo_name))
1273 			printf("failed to display uboot logo\n");
1274 		else
1275 			ret = display_logo(s);
1276 
1277 		/* Load kernel bmp in rockchip_display_fixup() later */
1278 	}
1279 
1280 	return ret;
1281 }
1282 
1283 enum {
1284 	PORT_DIR_IN,
1285 	PORT_DIR_OUT,
1286 };
1287 
1288 static struct rockchip_panel *rockchip_of_find_panel(struct udevice *dev)
1289 {
1290 	ofnode panel_node, ports, port, ep, port_parent_node;
1291 	struct udevice *panel_dev;
1292 	int ret;
1293 
1294 	panel_node = dev_read_subnode(dev, "panel");
1295 	if (ofnode_valid(panel_node) && ofnode_is_available(panel_node)) {
1296 		ret = uclass_get_device_by_ofnode(UCLASS_PANEL, panel_node,
1297 						  &panel_dev);
1298 		if (!ret)
1299 			goto found;
1300 	}
1301 
1302 	ports = dev_read_subnode(dev, "ports");
1303 	if (!ofnode_valid(ports))
1304 		return NULL;
1305 
1306 	ofnode_for_each_subnode(port, ports) {
1307 		u32 reg;
1308 
1309 		if (ofnode_read_u32(port, "reg", &reg))
1310 			continue;
1311 
1312 		if (reg != PORT_DIR_OUT)
1313 			continue;
1314 
1315 		ofnode_for_each_subnode(ep, port) {
1316 			ofnode _ep, _port;
1317 			uint phandle;
1318 			bool is_ports_node = false;
1319 
1320 			if (ofnode_read_u32(ep, "remote-endpoint", &phandle))
1321 				continue;
1322 
1323 			_ep = ofnode_get_by_phandle(phandle);
1324 			if (!ofnode_valid(_ep))
1325 				continue;
1326 
1327 			_port = ofnode_get_parent(_ep);
1328 			if (!ofnode_valid(_port))
1329 				continue;
1330 
1331 			port_parent_node = ofnode_get_parent(_port);
1332 			is_ports_node = strstr(port_parent_node.np->full_name, "ports") ? 1 : 0;
1333 			if (is_ports_node)
1334 				panel_node = ofnode_get_parent(port_parent_node);
1335 			else
1336 				panel_node = ofnode_get_parent(_port);
1337 			if (!ofnode_valid(panel_node))
1338 				continue;
1339 
1340 			ret = uclass_get_device_by_ofnode(UCLASS_PANEL,
1341 							  panel_node,
1342 							  &panel_dev);
1343 			if (!ret)
1344 				goto found;
1345 		}
1346 	}
1347 
1348 	return NULL;
1349 
1350 found:
1351 	return (struct rockchip_panel *)dev_get_driver_data(panel_dev);
1352 }
1353 
1354 static struct rockchip_bridge *rockchip_of_find_bridge(struct udevice *conn_dev)
1355 {
1356 	ofnode node, ports, port, ep;
1357 	struct udevice *dev;
1358 	int ret;
1359 
1360 	ports = dev_read_subnode(conn_dev, "ports");
1361 	if (!ofnode_valid(ports))
1362 		return NULL;
1363 
1364 	ofnode_for_each_subnode(port, ports) {
1365 		u32 reg;
1366 
1367 		if (ofnode_read_u32(port, "reg", &reg))
1368 			continue;
1369 
1370 		if (reg != PORT_DIR_OUT)
1371 			continue;
1372 
1373 		ofnode_for_each_subnode(ep, port) {
1374 			ofnode _ep, _port, _ports;
1375 			uint phandle;
1376 
1377 			if (ofnode_read_u32(ep, "remote-endpoint", &phandle))
1378 				continue;
1379 
1380 			_ep = ofnode_get_by_phandle(phandle);
1381 			if (!ofnode_valid(_ep))
1382 				continue;
1383 
1384 			_port = ofnode_get_parent(_ep);
1385 			if (!ofnode_valid(_port))
1386 				continue;
1387 
1388 			_ports = ofnode_get_parent(_port);
1389 			if (!ofnode_valid(_ports))
1390 				continue;
1391 
1392 			node = ofnode_get_parent(_ports);
1393 			if (!ofnode_valid(node))
1394 				continue;
1395 
1396 			ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE,
1397 							  node, &dev);
1398 			if (!ret)
1399 				goto found;
1400 		}
1401 	}
1402 
1403 	return NULL;
1404 
1405 found:
1406 	return (struct rockchip_bridge *)dev_get_driver_data(dev);
1407 }
1408 
1409 static struct udevice *rockchip_of_find_connector(ofnode endpoint)
1410 {
1411 	ofnode ep, port, ports, conn;
1412 	uint phandle;
1413 	struct udevice *dev;
1414 	int ret;
1415 
1416 	if (ofnode_read_u32(endpoint, "remote-endpoint", &phandle))
1417 		return NULL;
1418 
1419 	ep = ofnode_get_by_phandle(phandle);
1420 	if (!ofnode_valid(ep) || !ofnode_is_available(ep))
1421 		return NULL;
1422 
1423 	port = ofnode_get_parent(ep);
1424 	if (!ofnode_valid(port))
1425 		return NULL;
1426 
1427 	ports = ofnode_get_parent(port);
1428 	if (!ofnode_valid(ports))
1429 		return NULL;
1430 
1431 	conn = ofnode_get_parent(ports);
1432 	if (!ofnode_valid(conn) || !ofnode_is_available(conn))
1433 		return NULL;
1434 
1435 	ret = uclass_get_device_by_ofnode(UCLASS_DISPLAY, conn, &dev);
1436 	if (ret)
1437 		return NULL;
1438 
1439 	return dev;
1440 }
1441 
1442 static bool rockchip_get_display_path_status(ofnode endpoint)
1443 {
1444 	ofnode ep;
1445 	uint phandle;
1446 
1447 	if (ofnode_read_u32(endpoint, "remote-endpoint", &phandle))
1448 		return false;
1449 
1450 	ep = ofnode_get_by_phandle(phandle);
1451 	if (!ofnode_valid(ep) || !ofnode_is_available(ep))
1452 		return false;
1453 
1454 	return true;
1455 }
1456 
1457 static struct rockchip_phy *rockchip_of_find_phy(struct udevice *dev)
1458 {
1459 	struct udevice *phy_dev;
1460 	int ret;
1461 
1462 	ret = uclass_get_device_by_phandle(UCLASS_PHY, dev, "phys", &phy_dev);
1463 	if (ret)
1464 		return NULL;
1465 
1466 	return (struct rockchip_phy *)dev_get_driver_data(phy_dev);
1467 }
1468 
1469 #if defined(CONFIG_ROCKCHIP_RK3568)
1470 static int rockchip_display_fixup_dts(void *blob)
1471 {
1472 	ofnode route_node, route_subnode, conn_ep, conn_port;
1473 	const struct device_node *route_sub_devnode;
1474 	const struct device_node *ep_node, *conn_ep_dev_node;
1475 	u32 phandle;
1476 	int conn_ep_offset;
1477 	const char *route_sub_path, *path;
1478 
1479 	/* Don't go further if new variant after
1480 	 * reading PMUGRF_SOC_CON15
1481 	 */
1482 	if ((readl(0xfdc20100) & GENMASK(15, 14)))
1483 		return 0;
1484 
1485 	route_node = ofnode_path("/display-subsystem/route");
1486 	if (!ofnode_valid(route_node))
1487 		return -EINVAL;
1488 
1489 	ofnode_for_each_subnode(route_subnode, route_node) {
1490 		if (!ofnode_is_available(route_subnode))
1491 			continue;
1492 
1493 		route_sub_devnode = ofnode_to_np(route_subnode);
1494 		route_sub_path = route_sub_devnode->full_name;
1495 		if (!strstr(ofnode_get_name(route_subnode), "dsi") &&
1496 		    !strstr(ofnode_get_name(route_subnode), "edp"))
1497 			return 0;
1498 
1499 		phandle = ofnode_read_u32_default(route_subnode, "connect", -1);
1500 		if (phandle < 0) {
1501 			printf("Warn: can't find connect node's handle\n");
1502 			continue;
1503 		}
1504 
1505 		ep_node = of_find_node_by_phandle(phandle);
1506 		if (!ofnode_valid(np_to_ofnode(ep_node))) {
1507 			printf("Warn: can't find endpoint node from phandle\n");
1508 			continue;
1509 		}
1510 
1511 		ofnode_read_u32(np_to_ofnode(ep_node), "remote-endpoint", &phandle);
1512 		conn_ep = ofnode_get_by_phandle(phandle);
1513 		if (!ofnode_valid(conn_ep) || !ofnode_is_available(conn_ep))
1514 			return -ENODEV;
1515 
1516 		conn_port = ofnode_get_parent(conn_ep);
1517 		if (!ofnode_valid(conn_port))
1518 			return -ENODEV;
1519 
1520 		ofnode_for_each_subnode(conn_ep, conn_port) {
1521 			conn_ep_dev_node = ofnode_to_np(conn_ep);
1522 			path = conn_ep_dev_node->full_name;
1523 			ofnode_read_u32(conn_ep, "remote-endpoint", &phandle);
1524 			conn_ep_offset = fdt_path_offset(blob, path);
1525 
1526 			if (!ofnode_is_available(conn_ep) &&
1527 			    strstr(ofnode_get_name(conn_ep), "endpoint@0")) {
1528 				do_fixup_by_path_u32(blob, route_sub_path,
1529 						     "connect", phandle, 1);
1530 				fdt_status_okay(blob, conn_ep_offset);
1531 
1532 			} else if (ofnode_is_available(conn_ep) &&
1533 				   strstr(ofnode_get_name(conn_ep), "endpoint@1")) {
1534 				fdt_status_disabled(blob, conn_ep_offset);
1535 			}
1536 		}
1537 	}
1538 
1539 	return 0;
1540 }
1541 #endif
1542 
1543 static int rockchip_display_probe(struct udevice *dev)
1544 {
1545 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
1546 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
1547 	const void *blob = gd->fdt_blob;
1548 	int phandle;
1549 	struct udevice *crtc_dev, *conn_dev;
1550 	struct rockchip_crtc *crtc;
1551 	const struct rockchip_connector *conn;
1552 	struct rockchip_panel *panel = NULL;
1553 	struct rockchip_bridge *bridge = NULL;
1554 	struct rockchip_phy *phy = NULL;
1555 	struct display_state *s;
1556 	const char *name;
1557 	int ret;
1558 	ofnode node, route_node;
1559 	struct device_node *port_node, *vop_node, *ep_node, *port_parent_node;
1560 	struct public_phy_data *data;
1561 	bool is_ports_node = false;
1562 
1563 #if defined(CONFIG_ROCKCHIP_RK3568)
1564 	rockchip_display_fixup_dts((void *)blob);
1565 #endif
1566 
1567 	/* Before relocation we don't need to do anything */
1568 	if (!(gd->flags & GD_FLG_RELOC))
1569 		return 0;
1570 
1571 	data = malloc(sizeof(struct public_phy_data));
1572 	if (!data) {
1573 		printf("failed to alloc phy data\n");
1574 		return -ENOMEM;
1575 	}
1576 	data->phy_init = false;
1577 
1578 	init_display_buffer(plat->base);
1579 
1580 	route_node = dev_read_subnode(dev, "route");
1581 	if (!ofnode_valid(route_node))
1582 		return -ENODEV;
1583 
1584 	ofnode_for_each_subnode(node, route_node) {
1585 		if (!ofnode_is_available(node))
1586 			continue;
1587 		phandle = ofnode_read_u32_default(node, "connect", -1);
1588 		if (phandle < 0) {
1589 			printf("Warn: can't find connect node's handle\n");
1590 			continue;
1591 		}
1592 		ep_node = of_find_node_by_phandle(phandle);
1593 		if (!ofnode_valid(np_to_ofnode(ep_node))) {
1594 			printf("Warn: can't find endpoint node from phandle\n");
1595 			continue;
1596 		}
1597 		port_node = of_get_parent(ep_node);
1598 		if (!ofnode_valid(np_to_ofnode(port_node))) {
1599 			printf("Warn: can't find port node from phandle\n");
1600 			continue;
1601 		}
1602 
1603 		port_parent_node = of_get_parent(port_node);
1604 		if (!ofnode_valid(np_to_ofnode(port_parent_node))) {
1605 			printf("Warn: can't find port parent node from phandle\n");
1606 			continue;
1607 		}
1608 
1609 		is_ports_node = strstr(port_parent_node->full_name, "ports") ? 1 : 0;
1610 		if (is_ports_node) {
1611 			vop_node = of_get_parent(port_parent_node);
1612 			if (!ofnode_valid(np_to_ofnode(vop_node))) {
1613 				printf("Warn: can't find crtc node from phandle\n");
1614 				continue;
1615 			}
1616 		} else {
1617 			vop_node = port_parent_node;
1618 		}
1619 
1620 		ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_CRTC,
1621 						  np_to_ofnode(vop_node),
1622 						  &crtc_dev);
1623 		if (ret) {
1624 			printf("Warn: can't find crtc driver %d\n", ret);
1625 			continue;
1626 		}
1627 		crtc = (struct rockchip_crtc *)dev_get_driver_data(crtc_dev);
1628 
1629 		conn_dev = rockchip_of_find_connector(np_to_ofnode(ep_node));
1630 		if (!conn_dev) {
1631 			printf("Warn: can't find connect driver\n");
1632 			continue;
1633 		}
1634 
1635 		conn = (const struct rockchip_connector *)dev_get_driver_data(conn_dev);
1636 
1637 		phy = rockchip_of_find_phy(conn_dev);
1638 
1639 		bridge = rockchip_of_find_bridge(conn_dev);
1640 		if (bridge)
1641 			panel = rockchip_of_find_panel(bridge->dev);
1642 		else
1643 			panel = rockchip_of_find_panel(conn_dev);
1644 
1645 		s = malloc(sizeof(*s));
1646 		if (!s)
1647 			continue;
1648 
1649 		memset(s, 0, sizeof(*s));
1650 
1651 		INIT_LIST_HEAD(&s->head);
1652 		ret = ofnode_read_string_index(node, "logo,uboot", 0, &name);
1653 		if (!ret)
1654 			memcpy(s->ulogo_name, name, strlen(name));
1655 		ret = ofnode_read_string_index(node, "logo,kernel", 0, &name);
1656 		if (!ret)
1657 			memcpy(s->klogo_name, name, strlen(name));
1658 		ret = ofnode_read_string_index(node, "logo,mode", 0, &name);
1659 		if (!strcmp(name, "fullscreen"))
1660 			s->logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1661 		else
1662 			s->logo_mode = ROCKCHIP_DISPLAY_CENTER;
1663 		ret = ofnode_read_string_index(node, "charge_logo,mode", 0, &name);
1664 		if (!strcmp(name, "fullscreen"))
1665 			s->charge_logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1666 		else
1667 			s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER;
1668 
1669 		s->blob = blob;
1670 		s->panel_state.panel = panel;
1671 		s->conn_state.node = conn_dev->node;
1672 		s->conn_state.dev = conn_dev;
1673 		s->conn_state.connector = conn;
1674 		s->conn_state.phy = phy;
1675 		s->conn_state.bridge = bridge;
1676 		s->conn_state.overscan.left_margin = 100;
1677 		s->conn_state.overscan.right_margin = 100;
1678 		s->conn_state.overscan.top_margin = 100;
1679 		s->conn_state.overscan.bottom_margin = 100;
1680 		s->crtc_state.node = np_to_ofnode(vop_node);
1681 		s->crtc_state.dev = crtc_dev;
1682 		s->crtc_state.crtc = crtc;
1683 		s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node));
1684 		s->node = node;
1685 
1686 		if (is_ports_node) { /* only vop2 will get into here */
1687 			ofnode vp_node = np_to_ofnode(port_node);
1688 			static bool get_plane_mask_from_dts;
1689 
1690 			s->crtc_state.ports_node = port_parent_node;
1691 			if (!get_plane_mask_from_dts) {
1692 				ofnode vp_sub_node;
1693 				int vp_id = 0;
1694 				bool vp_enable = false;
1695 
1696 				ofnode_for_each_subnode(vp_node, np_to_ofnode(port_parent_node)) {
1697 					vp_id = ofnode_read_u32_default(vp_node, "reg", 0);
1698 					ret = ofnode_read_u32_default(vp_node, "rockchip,plane-mask", 0);
1699 					if (ret) {
1700 						s->crtc_state.crtc->vps[vp_id].plane_mask = ret;
1701 						s->crtc_state.crtc->assign_plane |= true;
1702 						printf("get vp%d plane mask:0x%x from dts\n", vp_id, ret);
1703 					}
1704 
1705 					/* To check current vp status */
1706 					vp_enable = false;
1707 					ofnode_for_each_subnode(vp_sub_node, vp_node)
1708 						vp_enable |= rockchip_get_display_path_status(vp_sub_node);
1709 					s->crtc_state.crtc->vps[vp_id].enable = vp_enable;
1710 				}
1711 				get_plane_mask_from_dts = true;
1712 			}
1713 		}
1714 
1715 		if (bridge)
1716 			bridge->state = s;
1717 
1718 		if (panel)
1719 			panel->state = s;
1720 
1721 		get_crtc_mcu_mode(&s->crtc_state);
1722 
1723 		ret = ofnode_read_u32_default(s->crtc_state.node,
1724 					      "rockchip,dual-channel-swap", 0);
1725 		s->crtc_state.dual_channel_swap = ret;
1726 		if (connector_panel_init(s)) {
1727 			printf("Warn: Failed to init panel drivers\n");
1728 			free(s);
1729 			continue;
1730 		}
1731 
1732 		if (connector_phy_init(s, data)) {
1733 			printf("Warn: Failed to init phy drivers\n");
1734 			free(s);
1735 			continue;
1736 		}
1737 		list_add_tail(&s->head, &rockchip_display_list);
1738 	}
1739 
1740 	if (list_empty(&rockchip_display_list)) {
1741 		debug("Failed to found available display route\n");
1742 		return -ENODEV;
1743 	}
1744 	rockchip_get_baseparameter();
1745 	display_pre_init();
1746 
1747 	uc_priv->xsize = DRM_ROCKCHIP_FB_WIDTH;
1748 	uc_priv->ysize = DRM_ROCKCHIP_FB_HEIGHT;
1749 	uc_priv->bpix = VIDEO_BPP32;
1750 
1751 	#ifdef CONFIG_DRM_ROCKCHIP_VIDEO_FRAMEBUFFER
1752 	rockchip_show_fbbase(plat->base);
1753 	video_set_flush_dcache(dev, true);
1754 	#endif
1755 
1756 	return 0;
1757 }
1758 
1759 void rockchip_display_fixup(void *blob)
1760 {
1761 	const struct rockchip_connector_funcs *conn_funcs;
1762 	const struct rockchip_crtc_funcs *crtc_funcs;
1763 	const struct rockchip_connector *conn;
1764 	const struct rockchip_crtc *crtc;
1765 	struct display_state *s;
1766 	int offset;
1767 	const struct device_node *np;
1768 	const char *path;
1769 
1770 	if (fdt_node_offset_by_compatible(blob, 0, "rockchip,drm-logo") >= 0) {
1771 		list_for_each_entry(s, &rockchip_display_list, head)
1772 			load_bmp_logo(&s->logo, s->klogo_name);
1773 
1774 		if (!get_display_size())
1775 			return;
1776 
1777 		offset = fdt_update_reserved_memory(blob, "rockchip,drm-logo",
1778 						    (u64)memory_start,
1779 						    (u64)get_display_size());
1780 		if (offset < 0)
1781 			printf("failed to reserve drm-loader-logo memory\n");
1782 	} else {
1783 		printf("can't found rockchip,drm-logo, use rockchip,fb-logo\n");
1784 		/* Compatible with rkfb display, only need reserve memory */
1785 		offset = fdt_update_reserved_memory(blob, "rockchip,fb-logo",
1786 						    (u64)memory_start,
1787 						    MEMORY_POOL_SIZE);
1788 		if (offset < 0)
1789 			printf("failed to reserve fb-loader-logo memory\n");
1790 		else
1791 			list_for_each_entry(s, &rockchip_display_list, head)
1792 				load_kernel_bmp_logo(&s->logo, s->klogo_name);
1793 		return;
1794 	}
1795 
1796 	list_for_each_entry(s, &rockchip_display_list, head) {
1797 		conn = s->conn_state.connector;
1798 		if (!conn)
1799 			continue;
1800 		conn_funcs = conn->funcs;
1801 		if (!conn_funcs) {
1802 			printf("failed to get exist connector\n");
1803 			continue;
1804 		}
1805 
1806 		crtc = s->crtc_state.crtc;
1807 		if (!crtc)
1808 			continue;
1809 
1810 		crtc_funcs = crtc->funcs;
1811 		if (!crtc_funcs) {
1812 			printf("failed to get exist crtc\n");
1813 			continue;
1814 		}
1815 
1816 		if (crtc_funcs->fixup_dts)
1817 			crtc_funcs->fixup_dts(s, blob);
1818 
1819 		if (conn_funcs->fixup_dts)
1820 			conn_funcs->fixup_dts(s, blob);
1821 
1822 		np = ofnode_to_np(s->node);
1823 		path = np->full_name;
1824 		fdt_increase_size(blob, 0x400);
1825 #define FDT_SET_U32(name, val) \
1826 		do_fixup_by_path_u32(blob, path, name, val, 1);
1827 
1828 		offset = s->logo.offset + (u32)(unsigned long)s->logo.mem
1829 			 - memory_start;
1830 		FDT_SET_U32("logo,offset", offset);
1831 		FDT_SET_U32("logo,width", s->logo.width);
1832 		FDT_SET_U32("logo,height", s->logo.height);
1833 		FDT_SET_U32("logo,bpp", s->logo.bpp);
1834 		FDT_SET_U32("logo,ymirror", s->logo.ymirror);
1835 		FDT_SET_U32("video,clock", s->conn_state.mode.clock);
1836 		FDT_SET_U32("video,hdisplay", s->conn_state.mode.hdisplay);
1837 		FDT_SET_U32("video,vdisplay", s->conn_state.mode.vdisplay);
1838 		FDT_SET_U32("video,crtc_hsync_end", s->conn_state.mode.crtc_hsync_end);
1839 		FDT_SET_U32("video,crtc_vsync_end", s->conn_state.mode.crtc_vsync_end);
1840 		FDT_SET_U32("video,vrefresh",
1841 			    drm_mode_vrefresh(&s->conn_state.mode));
1842 		FDT_SET_U32("video,flags", s->conn_state.mode.flags);
1843 		FDT_SET_U32("video,aspect_ratio", s->conn_state.mode.picture_aspect_ratio);
1844 		FDT_SET_U32("overscan,left_margin", s->conn_state.overscan.left_margin);
1845 		FDT_SET_U32("overscan,right_margin", s->conn_state.overscan.right_margin);
1846 		FDT_SET_U32("overscan,top_margin", s->conn_state.overscan.top_margin);
1847 		FDT_SET_U32("overscan,bottom_margin", s->conn_state.overscan.bottom_margin);
1848 #undef FDT_SET_U32
1849 	}
1850 }
1851 
1852 int rockchip_display_bind(struct udevice *dev)
1853 {
1854 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
1855 
1856 	plat->size = DRM_ROCKCHIP_FB_SIZE + MEMORY_POOL_SIZE;
1857 
1858 	return 0;
1859 }
1860 
1861 static const struct udevice_id rockchip_display_ids[] = {
1862 	{ .compatible = "rockchip,display-subsystem" },
1863 	{ }
1864 };
1865 
1866 U_BOOT_DRIVER(rockchip_display) = {
1867 	.name	= "rockchip_display",
1868 	.id	= UCLASS_VIDEO,
1869 	.of_match = rockchip_display_ids,
1870 	.bind	= rockchip_display_bind,
1871 	.probe	= rockchip_display_probe,
1872 };
1873 
1874 static int do_rockchip_logo_show(cmd_tbl_t *cmdtp, int flag, int argc,
1875 			char *const argv[])
1876 {
1877 	if (argc != 1)
1878 		return CMD_RET_USAGE;
1879 
1880 	rockchip_show_logo();
1881 
1882 	return 0;
1883 }
1884 
1885 static int do_rockchip_show_bmp(cmd_tbl_t *cmdtp, int flag, int argc,
1886 				char *const argv[])
1887 {
1888 	if (argc != 2)
1889 		return CMD_RET_USAGE;
1890 
1891 	rockchip_show_bmp(argv[1]);
1892 
1893 	return 0;
1894 }
1895 
1896 U_BOOT_CMD(
1897 	rockchip_show_logo, 1, 1, do_rockchip_logo_show,
1898 	"load and display log from resource partition",
1899 	NULL
1900 );
1901 
1902 U_BOOT_CMD(
1903 	rockchip_show_bmp, 2, 1, do_rockchip_show_bmp,
1904 	"load and display bmp from resource partition",
1905 	"    <bmp_name>"
1906 );
1907