xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_display.c (revision 1ae6d6e5c841cc3093e92b65c74791b2e3380c4f)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <asm/io.h>
8 #include <asm/unaligned.h>
9 #include <config.h>
10 #include <common.h>
11 #include <errno.h>
12 #include <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 <dm/device.h>
23 #include <dm/uclass-internal.h>
24 #include <asm/arch-rockchip/resource_img.h>
25 
26 #include "bmp_helper.h"
27 #include "rockchip_display.h"
28 #include "rockchip_crtc.h"
29 #include "rockchip_connector.h"
30 #include "rockchip_phy.h"
31 #include "rockchip_panel.h"
32 #include "rockchip_vop.h"
33 #include <dm.h>
34 #include <dm/of_access.h>
35 #include <dm/ofnode.h>
36 
37 #define DRIVER_VERSION	"v1.0.0"
38 
39 /***********************************************************************
40  *  Rockchip UBOOT DRM driver version
41  *
42  *  v1.0.0	: add basic version for rockchip drm driver(hjc)
43  *
44  **********************************************************************/
45 
46 #define RK_BLK_SIZE 512
47 
48 DECLARE_GLOBAL_DATA_PTR;
49 static LIST_HEAD(rockchip_display_list);
50 static LIST_HEAD(logo_cache_list);
51 
52 static unsigned long memory_start;
53 static unsigned long memory_end;
54 
55 /*
56  * the phy types are used by different connectors in public.
57  * The current version only has inno hdmi phy for hdmi and tve.
58  */
59 enum public_use_phy {
60 	NONE,
61 	INNO_HDMI_PHY
62 };
63 
64 /* save public phy data */
65 struct public_phy_data {
66 	const struct rockchip_phy *phy_drv;
67 	int phy_node;
68 	int public_phy_type;
69 	bool phy_init;
70 };
71 
72 /* check which kind of public phy does connector use */
73 static int check_public_use_phy(struct display_state *state)
74 {
75 	int ret = NONE;
76 #ifdef CONFIG_ROCKCHIP_INNO_HDMI_PHY
77 	struct connector_state *conn_state = &state->conn_state;
78 
79 	if (!strncmp(dev_read_name(conn_state->dev), "tve", 3) ||
80 	    !strncmp(dev_read_name(conn_state->dev), "hdmi", 4))
81 		ret = INNO_HDMI_PHY;
82 #endif
83 
84 	return ret;
85 }
86 
87 /*
88  * get public phy driver and initialize it.
89  * The current version only has inno hdmi phy for hdmi and tve.
90  */
91 static int get_public_phy(struct display_state *state,
92 			  struct public_phy_data *data)
93 {
94 	struct connector_state *conn_state = &state->conn_state;
95 	struct rockchip_phy *phy;
96 	struct udevice *dev;
97 	int ret = 0;
98 
99 	switch (data->public_phy_type) {
100 	case INNO_HDMI_PHY:
101 #if defined(CONFIG_ROCKCHIP_RK3328)
102 		ret = uclass_get_device_by_name(UCLASS_PHY,
103 						"hdmiphy@ff430000", &dev);
104 #elif defined(CONFIG_ROCKCHIP_RK322X)
105 		ret = uclass_get_device_by_name(UCLASS_PHY,
106 						"hdmi-phy@12030000", &dev);
107 #else
108 		ret = -EINVAL;
109 #endif
110 		if (ret) {
111 			printf("Warn: can't find phy driver\n");
112 			return 0;
113 		}
114 
115 		phy = (struct rockchip_phy *)dev_get_driver_data(dev);
116 		if (!phy) {
117 			printf("failed to get phy driver\n");
118 			return 0;
119 		}
120 
121 		conn_state->phy_dev = dev;
122 		conn_state->phy_node = dev->node;
123 
124 		ret = rockchip_phy_init(phy);
125 		if (ret) {
126 			printf("failed to init phy driver\n");
127 			return ret;
128 		}
129 		conn_state->phy = phy;
130 
131 		printf("inno hdmi phy init success, save it\n");
132 		data->phy_node = ofnode_to_offset(conn_state->phy_node);
133 		data->phy_drv = conn_state->phy;
134 		data->phy_init = true;
135 		return 0;
136 	default:
137 		return -EINVAL;
138 	}
139 }
140 
141 static void init_display_buffer(ulong base)
142 {
143 	memory_start = base + DRM_ROCKCHIP_FB_SIZE;
144 	memory_end = memory_start;
145 }
146 
147 static void *get_display_buffer(int size)
148 {
149 	unsigned long roundup_memory = roundup(memory_end, PAGE_SIZE);
150 	void *buf;
151 
152 	if (roundup_memory + size > memory_start + MEMORY_POOL_SIZE) {
153 		printf("failed to alloc %dbyte memory to display\n", size);
154 		return NULL;
155 	}
156 	buf = (void *)roundup_memory;
157 
158 	memory_end = roundup_memory + size;
159 
160 	return buf;
161 }
162 
163 static unsigned long get_display_size(void)
164 {
165 	return memory_end - memory_start;
166 }
167 
168 /**
169  * vop_support_ymirror - ensure whethere vop support the feature of ymirror.
170  * @logo:	the pointer to the logo information.
171  *
172  */
173 static bool vop_support_ymirror(struct logo_info *logo)
174 {
175 	bool ret;
176 	struct display_state *state;
177 	struct vop_data *vop_data;
178 
179 	ret = false;
180 	state = container_of(logo, struct display_state, logo);
181 	if (state->crtc_state.crtc->data) {
182 		vop_data = (struct vop_data *)state->crtc_state.crtc->data;
183 		printf("VOP hardware version v%d.%d, ",
184 		       VOP_MAJOR(vop_data->version),
185 		       VOP_MINOR(vop_data->version));
186 		/*
187 		 * if the version of VOP is higher than v3.0,
188 		 * which means that the VOP support ymirror,
189 		 * so it isn't need to mirror image by ourself.
190 		 */
191 		if (vop_data->version >= VOP_VERSION(3, 0)) {
192 			printf("Support mirror mode.\n");
193 			ret = true;
194 		} else {
195 			printf("Not support mirror mode.\n");
196 		}
197 	} else {
198 		printf("Error: CRTC drivers is not ready.\n");
199 	}
200 
201 	return ret;
202 }
203 
204 
205 static struct udevice *get_panel_device(struct display_state *state, ofnode conn_node)
206 {
207 	struct panel_state *panel_state = &state->panel_state;
208 	struct udevice *dev;
209 	struct connector_state *conn_state = &state->conn_state;
210 	ofnode node, ports_node, port_node;
211 	struct device_node *port, *panel, *ep;
212 	int ph;
213 	int ret;
214 
215 	node = dev_read_subnode(conn_state->dev, "panel");
216 	if (ofnode_valid(node) &&
217 	    of_device_is_available(ofnode_to_np(node))) {
218 		ret = uclass_get_device_by_ofnode(UCLASS_PANEL, node, &dev);
219 		if (!ret) {
220 			panel_state->node = node;
221 			return dev;
222 		}
223 	}
224 
225 	/* TODO: this path not tested */
226 	ports_node = dev_read_subnode(conn_state->dev, "ports");
227 	if (!ofnode_valid(ports_node))
228 		return NULL;
229 
230 	ofnode_for_each_subnode(port_node, ports_node) {
231 		ofnode_for_each_subnode(node, port_node) {
232 			ph = ofnode_read_u32_default(node, "remote-endpoint", -1);
233 			if (!ph)
234 				continue;
235 			ep = of_find_node_by_phandle(ph);
236 			if (!ofnode_valid(np_to_ofnode(ep))) {
237 				printf("Warn: can't find endpoint from phdl\n");
238 				continue;
239 			}
240 			port = of_get_parent(ep);
241 			if (!ofnode_valid(np_to_ofnode(port))) {
242 				printf("Warn: can't find port node\n");
243 				continue;
244 			}
245 			panel = of_get_parent(port);
246 			if (!ofnode_valid(np_to_ofnode(panel))) {
247 				printf("Warn: can't find panel node\n");
248 				continue;
249 			}
250 			ret = uclass_get_device_by_ofnode(UCLASS_PANEL,
251 							  np_to_ofnode(panel),
252 							  &dev);
253 			if (!ret) {
254 				panel_state->node = np_to_ofnode(panel);
255 				return dev;
256 			}
257 		}
258 	}
259 
260 	return NULL;
261 }
262 
263 static int connector_phy_init(struct display_state *state,
264 			      struct public_phy_data *data)
265 {
266 	struct connector_state *conn_state = &state->conn_state;
267 	struct rockchip_phy *phy;
268 	struct udevice *dev;
269 	int ret, type;
270 
271 	/* does this connector use public phy with others */
272 	type = check_public_use_phy(state);
273 	if (type == INNO_HDMI_PHY) {
274 		/* there is no public phy was initialized */
275 		if (!data->phy_init) {
276 			printf("start get public phy\n");
277 			data->public_phy_type = type;
278 			if (get_public_phy(state, data)) {
279 				printf("can't find correct public phy type\n");
280 				free(data);
281 				return -EINVAL;
282 			}
283 			return 0;
284 		}
285 
286 		/* if this phy has been initialized, get it directly */
287 		conn_state->phy_node = offset_to_ofnode(data->phy_node);
288 		conn_state->phy = (struct rockchip_phy *)data->phy_drv;
289 		return 0;
290 	}
291 
292 	/*
293 	 * if this connector don't use the same phy with others,
294 	 * just get phy as original method.
295 	 */
296 	ret = uclass_get_device_by_phandle(UCLASS_PHY, conn_state->dev, "phys",
297 					   &dev);
298 	if (ret) {
299 		printf("Warn: can't find phy driver\n");
300 		return 0;
301 	}
302 
303 	phy = (struct rockchip_phy *)dev_get_driver_data(dev);
304 	if (!phy) {
305 		printf("failed to find phy driver\n");
306 		return 0;
307 	}
308 
309 	conn_state->phy_dev = dev;
310 	conn_state->phy_node = dev->node;
311 
312 	ret = rockchip_phy_init(phy);
313 	if (ret) {
314 		printf("failed to init phy driver\n");
315 		return ret;
316 	}
317 
318 	conn_state->phy = phy;
319 
320 	return 0;
321 }
322 
323 static int connector_panel_init(struct display_state *state)
324 {
325 	struct connector_state *conn_state = &state->conn_state;
326 	struct panel_state *panel_state = &state->panel_state;
327 	struct udevice *dev;
328 	ofnode conn_node = conn_state->node;
329 	const struct rockchip_panel *panel;
330 	ofnode dsp_lut_node;
331 	int ret, len;
332 
333 	dm_scan_fdt_dev(conn_state->dev);
334 
335 	dev = get_panel_device(state, conn_node);
336 	if (!dev) {
337 		return 0;
338 	}
339 
340 	panel = (const struct rockchip_panel *)dev_get_driver_data(dev);
341 	if (!panel) {
342 		printf("failed to find panel driver\n");
343 		return 0;
344 	}
345 
346 	panel_state->dev = dev;
347 	panel_state->panel = panel;
348 
349 	if (panel->funcs && panel->funcs->init) {
350 		ret = panel->funcs->init(state);
351 		if (ret) {
352 			printf("failed to init panel driver\n");
353 			return ret;
354 		}
355 	}
356 
357 	dsp_lut_node = dev_read_subnode(dev, "dsp-lut");
358 	if (!ofnode_valid(dsp_lut_node)) {
359 		printf("%s can not find dsp-lut node\n", __func__);
360 		return 0;
361 	}
362 
363 	ofnode_get_property(dsp_lut_node, "gamma-lut", &len);
364 	if (len > 0) {
365 		conn_state->gamma.size = len / sizeof(u32);
366 		conn_state->gamma.lut = malloc(len);
367 		if (!conn_state->gamma.lut) {
368 			printf("malloc gamma lut failed\n");
369 			return -ENOMEM;
370 		}
371 		ret = ofnode_read_u32_array(dsp_lut_node, "gamma-lut",
372 					    conn_state->gamma.lut,
373 					    conn_state->gamma.size);
374 		if (ret) {
375 			printf("Cannot decode gamma_lut\n");
376 			conn_state->gamma.lut = NULL;
377 			return -EINVAL;
378 		}
379 		panel_state->dsp_lut_node = dsp_lut_node;
380 	}
381 
382 	return 0;
383 }
384 
385 int drm_mode_vrefresh(const struct drm_display_mode *mode)
386 {
387 	int refresh = 0;
388 	unsigned int calc_val;
389 
390 	if (mode->vrefresh > 0) {
391 		refresh = mode->vrefresh;
392 	} else if (mode->htotal > 0 && mode->vtotal > 0) {
393 		int vtotal;
394 
395 		vtotal = mode->vtotal;
396 		/* work out vrefresh the value will be x1000 */
397 		calc_val = (mode->clock * 1000);
398 		calc_val /= mode->htotal;
399 		refresh = (calc_val + vtotal / 2) / vtotal;
400 
401 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
402 			refresh *= 2;
403 		if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
404 			refresh /= 2;
405 		if (mode->vscan > 1)
406 			refresh /= mode->vscan;
407 	}
408 	return refresh;
409 }
410 
411 static int display_get_timing_from_dts(struct panel_state *panel_state,
412 				       struct drm_display_mode *mode)
413 {
414 	int phandle;
415 	int hactive, vactive, pixelclock;
416 	int hfront_porch, hback_porch, hsync_len;
417 	int vfront_porch, vback_porch, vsync_len;
418 	int val, flags = 0;
419 	ofnode timing, native_mode;
420 
421 	timing = dev_read_subnode(panel_state->dev, "display-timings");
422 	if (!ofnode_valid(timing))
423 		return -ENODEV;
424 
425 	native_mode = ofnode_find_subnode(timing, "timing");
426 	if (!ofnode_valid(native_mode)) {
427 		phandle = ofnode_read_u32_default(timing, "native-mode", -1);
428 		native_mode = np_to_ofnode(of_find_node_by_phandle(phandle));
429 		if (!ofnode_valid(native_mode)) {
430 			printf("failed to get display timings from DT\n");
431 			return -ENXIO;
432 		}
433 	}
434 
435 #define FDT_GET_INT(val, name) \
436 	val = ofnode_read_s32_default(native_mode, name, -1); \
437 	if (val < 0) { \
438 		printf("Can't get %s\n", name); \
439 		return -ENXIO; \
440 	}
441 
442 	FDT_GET_INT(hactive, "hactive");
443 	FDT_GET_INT(vactive, "vactive");
444 	FDT_GET_INT(pixelclock, "clock-frequency");
445 	FDT_GET_INT(hsync_len, "hsync-len");
446 	FDT_GET_INT(hfront_porch, "hfront-porch");
447 	FDT_GET_INT(hback_porch, "hback-porch");
448 	FDT_GET_INT(vsync_len, "vsync-len");
449 	FDT_GET_INT(vfront_porch, "vfront-porch");
450 	FDT_GET_INT(vback_porch, "vback-porch");
451 	FDT_GET_INT(val, "hsync-active");
452 	flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
453 	FDT_GET_INT(val, "vsync-active");
454 	flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
455 	FDT_GET_INT(val, "pixelclk-active");
456 	flags |= val ? DRM_MODE_FLAG_PPIXDATA : 0;
457 
458 	mode->hdisplay = hactive;
459 	mode->hsync_start = mode->hdisplay + hfront_porch;
460 	mode->hsync_end = mode->hsync_start + hsync_len;
461 	mode->htotal = mode->hsync_end + hback_porch;
462 
463 	mode->vdisplay = vactive;
464 	mode->vsync_start = mode->vdisplay + vfront_porch;
465 	mode->vsync_end = mode->vsync_start + vsync_len;
466 	mode->vtotal = mode->vsync_end + vback_porch;
467 
468 	mode->clock = pixelclock / 1000;
469 	mode->flags = flags;
470 
471 	return 0;
472 }
473 
474 /**
475  * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
476  * @p: mode
477  * @adjust_flags: a combination of adjustment flags
478  *
479  * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
480  *
481  * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
482  *   interlaced modes.
483  * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
484  *   buffers containing two eyes (only adjust the timings when needed, eg. for
485  *   "frame packing" or "side by side full").
486  * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
487  *   be performed for doublescan and vscan > 1 modes respectively.
488  */
489 void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
490 {
491 	if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
492 		return;
493 
494 	if (p->flags & DRM_MODE_FLAG_DBLCLK)
495 		p->crtc_clock = 2 * p->clock;
496 	else
497 		p->crtc_clock = p->clock;
498 	p->crtc_hdisplay = p->hdisplay;
499 	p->crtc_hsync_start = p->hsync_start;
500 	p->crtc_hsync_end = p->hsync_end;
501 	p->crtc_htotal = p->htotal;
502 	p->crtc_hskew = p->hskew;
503 	p->crtc_vdisplay = p->vdisplay;
504 	p->crtc_vsync_start = p->vsync_start;
505 	p->crtc_vsync_end = p->vsync_end;
506 	p->crtc_vtotal = p->vtotal;
507 
508 	if (p->flags & DRM_MODE_FLAG_INTERLACE) {
509 		if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
510 			p->crtc_vdisplay /= 2;
511 			p->crtc_vsync_start /= 2;
512 			p->crtc_vsync_end /= 2;
513 			p->crtc_vtotal /= 2;
514 		}
515 	}
516 
517 	if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
518 		if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
519 			p->crtc_vdisplay *= 2;
520 			p->crtc_vsync_start *= 2;
521 			p->crtc_vsync_end *= 2;
522 			p->crtc_vtotal *= 2;
523 		}
524 	}
525 
526 	if (!(adjust_flags & CRTC_NO_VSCAN)) {
527 		if (p->vscan > 1) {
528 			p->crtc_vdisplay *= p->vscan;
529 			p->crtc_vsync_start *= p->vscan;
530 			p->crtc_vsync_end *= p->vscan;
531 			p->crtc_vtotal *= p->vscan;
532 		}
533 	}
534 
535 	if (adjust_flags & CRTC_STEREO_DOUBLE) {
536 		unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
537 
538 		switch (layout) {
539 		case DRM_MODE_FLAG_3D_FRAME_PACKING:
540 			p->crtc_clock *= 2;
541 			p->crtc_vdisplay += p->crtc_vtotal;
542 			p->crtc_vsync_start += p->crtc_vtotal;
543 			p->crtc_vsync_end += p->crtc_vtotal;
544 			p->crtc_vtotal += p->crtc_vtotal;
545 			break;
546 		}
547 	}
548 
549 	p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
550 	p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
551 	p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
552 	p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
553 }
554 
555 /**
556  * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
557  * output format
558  *
559  * @connector: drm connector under action.
560  * @mode: video mode to be tested.
561  *
562  * Returns:
563  * true if the mode can be supported in YCBCR420 format
564  * false if not.
565  */
566 bool drm_mode_is_420_only(const struct drm_display_info *display,
567 			  struct drm_display_mode *mode)
568 {
569 	u8 vic = drm_match_cea_mode(mode);
570 
571 	return test_bit(vic, display->hdmi.y420_vdb_modes);
572 }
573 
574 /**
575  * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
576  * output format also (along with RGB/YCBCR444/422)
577  *
578  * @display: display under action.
579  * @mode: video mode to be tested.
580  *
581  * Returns:
582  * true if the mode can be support YCBCR420 format
583  * false if not.
584  */
585 bool drm_mode_is_420_also(const struct drm_display_info *display,
586 			  struct drm_display_mode *mode)
587 {
588 	u8 vic = drm_match_cea_mode(mode);
589 
590 	return test_bit(vic, display->hdmi.y420_cmdb_modes);
591 }
592 
593 /**
594  * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
595  * output format
596  *
597  * @display: display under action.
598  * @mode: video mode to be tested.
599  *
600  * Returns:
601  * true if the mode can be supported in YCBCR420 format
602  * false if not.
603  */
604 bool drm_mode_is_420(const struct drm_display_info *display,
605 		     struct drm_display_mode *mode)
606 {
607 	return drm_mode_is_420_only(display, mode) ||
608 		drm_mode_is_420_also(display, mode);
609 }
610 
611 static int display_get_timing(struct display_state *state)
612 {
613 	struct connector_state *conn_state = &state->conn_state;
614 	const struct rockchip_connector *conn = conn_state->connector;
615 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
616 	struct drm_display_mode *mode = &conn_state->mode;
617 	const struct drm_display_mode *m;
618 	struct panel_state *panel_state = &state->panel_state;
619 	const struct rockchip_panel *panel = panel_state->panel;
620 	const struct rockchip_panel_funcs *panel_funcs = panel->funcs;
621 	ofnode panel_node = panel_state->node;
622 	int ret;
623 
624 	if (ofnode_valid(panel_node) && !display_get_timing_from_dts(panel_state, mode)) {
625 		printf("Using display timing dts\n");
626 		goto done;
627 	}
628 
629 	if (panel->data) {
630 		m = (const struct drm_display_mode *)panel->data;
631 		memcpy(mode, m, sizeof(*m));
632 		printf("Using display timing from compatible panel driver\n");
633 		goto done;
634 	}
635 
636 	if (conn_funcs->get_edid && !conn_funcs->get_edid(state)) {
637 		int panel_bits_per_colourp;
638 
639 		/* In order to read EDID, the panel needs to be powered on */
640 		if (panel_funcs->prepare) {
641 			ret = panel_funcs->prepare(state);
642 			if (ret) {
643 				printf("failed to prepare panel\n");
644 				return ret;
645 			}
646 		}
647 
648 		if (!edid_get_drm_mode((void *)&conn_state->edid,
649 				     sizeof(conn_state->edid), mode,
650 				     &panel_bits_per_colourp)) {
651 			printf("Using display timing from edid\n");
652 			edid_print_info((void *)&conn_state->edid);
653 			goto done;
654 		} else {
655 			if (panel_funcs->unprepare)
656 				panel_funcs->unprepare(state);
657 		}
658 	}
659 
660 	printf("failed to find display timing\n");
661 	return -ENODEV;
662 done:
663 	printf("Detailed mode clock %u kHz, flags[%x]\n"
664 	       "    H: %04d %04d %04d %04d\n"
665 	       "    V: %04d %04d %04d %04d\n"
666 	       "bus_format: %x\n",
667 	       mode->clock, mode->flags,
668 	       mode->hdisplay, mode->hsync_start,
669 	       mode->hsync_end, mode->htotal,
670 	       mode->vdisplay, mode->vsync_start,
671 	       mode->vsync_end, mode->vtotal,
672 	       conn_state->bus_format);
673 
674 	return 0;
675 }
676 
677 static int display_init(struct display_state *state)
678 {
679 	struct connector_state *conn_state = &state->conn_state;
680 	const struct rockchip_connector *conn = conn_state->connector;
681 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
682 	struct crtc_state *crtc_state = &state->crtc_state;
683 	struct rockchip_crtc *crtc = crtc_state->crtc;
684 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
685 	struct drm_display_mode *mode = &conn_state->mode;
686 	int ret = 0;
687 	static bool __print_once = false;
688 
689 	if (!__print_once) {
690 		__print_once = true;
691 		printf("Rockchip UBOOT DRM driver version: %s\n", DRIVER_VERSION);
692 	}
693 
694 	if (state->is_init)
695 		return 0;
696 
697 	if (!conn_funcs || !crtc_funcs) {
698 		printf("failed to find connector or crtc functions\n");
699 		return -ENXIO;
700 	}
701 
702 	if (conn_funcs->init) {
703 		ret = conn_funcs->init(state);
704 		if (ret)
705 			goto deinit;
706 	}
707 	/*
708 	 * support hotplug, but not connect;
709 	 */
710 #ifdef CONFIG_ROCKCHIP_DRM_TVE
711 	if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_TV) {
712 		printf("hdmi plugin ,skip tve\n");
713 		goto deinit;
714 	}
715 #elif defined(CONFIG_ROCKCHIP_DRM_RK1000)
716 	if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_LVDS) {
717 		printf("hdmi plugin ,skip tve\n");
718 		goto deinit;
719 	}
720 #endif
721 	if (conn_funcs->detect) {
722 		ret = conn_funcs->detect(state);
723 #if defined(CONFIG_ROCKCHIP_DRM_TVE) || defined(CONFIG_ROCKCHIP_DRM_RK1000)
724 		if (conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
725 			crtc->hdmi_hpd = ret;
726 #endif
727 		if (!ret)
728 			goto deinit;
729 	}
730 
731 	if (conn_funcs->get_timing) {
732 		ret = conn_funcs->get_timing(state);
733 		if (ret)
734 			goto deinit;
735 	} else {
736 		ret = display_get_timing(state);
737 		if (ret)
738 			goto deinit;
739 	}
740 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
741 
742 	if (crtc_funcs->init) {
743 		ret = crtc_funcs->init(state);
744 		if (ret)
745 			goto deinit;
746 	}
747 	state->is_init = 1;
748 
749 	return 0;
750 
751 deinit:
752 	if (conn_funcs->deinit)
753 		conn_funcs->deinit(state);
754 	return ret;
755 }
756 
757 int display_send_mcu_cmd(struct display_state *state, u32 type, u32 val)
758 {
759 	struct crtc_state *crtc_state = &state->crtc_state;
760 	const struct rockchip_crtc *crtc = crtc_state->crtc;
761 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
762 	int ret;
763 
764 	if (!state->is_init)
765 		return -EINVAL;
766 
767 	if (crtc_funcs->send_mcu_cmd) {
768 		ret = crtc_funcs->send_mcu_cmd(state, type, val);
769 		if (ret)
770 			return ret;
771 	}
772 
773 	return 0;
774 }
775 
776 static int display_set_plane(struct display_state *state)
777 {
778 	struct crtc_state *crtc_state = &state->crtc_state;
779 	const struct rockchip_crtc *crtc = crtc_state->crtc;
780 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
781 	int ret;
782 
783 	if (!state->is_init)
784 		return -EINVAL;
785 
786 	if (crtc_funcs->set_plane) {
787 		ret = crtc_funcs->set_plane(state);
788 		if (ret)
789 			return ret;
790 	}
791 
792 	return 0;
793 }
794 
795 static int display_panel_prepare(struct display_state *state)
796 {
797 	struct panel_state *panel_state = &state->panel_state;
798 	const struct rockchip_panel *panel = panel_state->panel;
799 
800 	if (!panel || !panel->funcs || !panel->funcs->prepare) {
801 		printf("%s: failed to find panel prepare funcs\n", __func__);
802 		return -ENODEV;
803 	}
804 
805 	return panel->funcs->prepare(state);
806 }
807 
808 static int display_panel_enable(struct display_state *state)
809 {
810 	struct panel_state *panel_state = &state->panel_state;
811 	const struct rockchip_panel *panel = panel_state->panel;
812 
813 	if (!panel || !panel->funcs || !panel->funcs->enable) {
814 		printf("%s: failed to find panel enable funcs\n", __func__);
815 		return -ENODEV;
816 	}
817 
818 	return panel->funcs->enable(state);
819 }
820 
821 static void display_panel_unprepare(struct display_state *state)
822 {
823 	struct panel_state *panel_state = &state->panel_state;
824 	const struct rockchip_panel *panel = panel_state->panel;
825 
826 	if (!panel || !panel->funcs || !panel->funcs->unprepare) {
827 		printf("%s: failed to find panel unprepare funcs\n", __func__);
828 		return;
829 	}
830 
831 	panel->funcs->unprepare(state);
832 }
833 
834 static void display_panel_disable(struct display_state *state)
835 {
836 	struct panel_state *panel_state = &state->panel_state;
837 	const struct rockchip_panel *panel = panel_state->panel;
838 
839 	if (!panel || !panel->funcs || !panel->funcs->disable) {
840 		printf("%s: failed to find panel disable funcs\n", __func__);
841 		return;
842 	}
843 
844 	panel->funcs->disable(state);
845 }
846 
847 static int display_enable(struct display_state *state)
848 {
849 	struct connector_state *conn_state = &state->conn_state;
850 	const struct rockchip_connector *conn = conn_state->connector;
851 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
852 	struct crtc_state *crtc_state = &state->crtc_state;
853 	const struct rockchip_crtc *crtc = crtc_state->crtc;
854 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
855 	int ret = 0;
856 
857 	display_init(state);
858 
859 	if (!state->is_init)
860 		return -EINVAL;
861 
862 	if (state->is_enable)
863 		return 0;
864 
865 	if (crtc_funcs->prepare) {
866 		ret = crtc_funcs->prepare(state);
867 		if (ret)
868 			return ret;
869 	}
870 
871 	if (conn_funcs->prepare) {
872 		ret = conn_funcs->prepare(state);
873 		if (ret)
874 			goto unprepare_crtc;
875 	}
876 
877 	display_panel_prepare(state);
878 
879 	if (crtc_funcs->enable) {
880 		ret = crtc_funcs->enable(state);
881 		if (ret)
882 			goto unprepare_conn;
883 	}
884 
885 	if (conn_funcs->enable) {
886 		ret = conn_funcs->enable(state);
887 		if (ret)
888 			goto disable_crtc;
889 	}
890 
891 	display_panel_enable(state);
892 
893 	state->is_enable = true;
894 	return 0;
895 
896 disable_crtc:
897 	if (crtc_funcs->disable)
898 		crtc_funcs->disable(state);
899 unprepare_conn:
900 	if (conn_funcs->unprepare)
901 		conn_funcs->unprepare(state);
902 unprepare_crtc:
903 	if (crtc_funcs->unprepare)
904 		crtc_funcs->unprepare(state);
905 	return ret;
906 }
907 
908 static int display_disable(struct display_state *state)
909 {
910 	struct connector_state *conn_state = &state->conn_state;
911 	const struct rockchip_connector *conn = conn_state->connector;
912 	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
913 	struct crtc_state *crtc_state = &state->crtc_state;
914 	const struct rockchip_crtc *crtc = crtc_state->crtc;
915 	const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
916 
917 	if (!state->is_init)
918 		return 0;
919 
920 	if (!state->is_enable)
921 		return 0;
922 
923 	display_panel_disable(state);
924 
925 	if (crtc_funcs->disable)
926 		crtc_funcs->disable(state);
927 
928 	if (conn_funcs->disable)
929 		conn_funcs->disable(state);
930 
931 	display_panel_unprepare(state);
932 
933 	if (conn_funcs->unprepare)
934 		conn_funcs->unprepare(state);
935 
936 	state->is_enable = 0;
937 	state->is_init = 0;
938 
939 	return 0;
940 }
941 
942 static int display_logo(struct display_state *state)
943 {
944 	struct crtc_state *crtc_state = &state->crtc_state;
945 	struct connector_state *conn_state = &state->conn_state;
946 	struct logo_info *logo = &state->logo;
947 	int hdisplay, vdisplay;
948 
949 	display_init(state);
950 	if (!state->is_init)
951 		return -ENODEV;
952 
953 	switch (logo->bpp) {
954 	case 16:
955 		crtc_state->format = ROCKCHIP_FMT_RGB565;
956 		break;
957 	case 24:
958 		crtc_state->format = ROCKCHIP_FMT_RGB888;
959 		break;
960 	case 32:
961 		crtc_state->format = ROCKCHIP_FMT_ARGB8888;
962 		break;
963 	default:
964 		printf("can't support bmp bits[%d]\n", logo->bpp);
965 		return -EINVAL;
966 	}
967 	hdisplay = conn_state->mode.hdisplay;
968 	vdisplay = conn_state->mode.vdisplay;
969 	crtc_state->src_w = logo->width;
970 	crtc_state->src_h = logo->height;
971 	crtc_state->src_x = 0;
972 	crtc_state->src_y = 0;
973 	crtc_state->ymirror = logo->ymirror;
974 
975 	crtc_state->dma_addr = (u32)(unsigned long)logo->mem + logo->offset;
976 	crtc_state->xvir = ALIGN(crtc_state->src_w * logo->bpp, 32) >> 5;
977 
978 	if (logo->mode == ROCKCHIP_DISPLAY_FULLSCREEN) {
979 		crtc_state->crtc_x = 0;
980 		crtc_state->crtc_y = 0;
981 		crtc_state->crtc_w = hdisplay;
982 		crtc_state->crtc_h = vdisplay;
983 	} else {
984 		if (crtc_state->src_w >= hdisplay) {
985 			crtc_state->crtc_x = 0;
986 			crtc_state->crtc_w = hdisplay;
987 		} else {
988 			crtc_state->crtc_x = (hdisplay - crtc_state->src_w) / 2;
989 			crtc_state->crtc_w = crtc_state->src_w;
990 		}
991 
992 		if (crtc_state->src_h >= vdisplay) {
993 			crtc_state->crtc_y = 0;
994 			crtc_state->crtc_h = vdisplay;
995 		} else {
996 			crtc_state->crtc_y = (vdisplay - crtc_state->src_h) / 2;
997 			crtc_state->crtc_h = crtc_state->src_h;
998 		}
999 	}
1000 
1001 	display_set_plane(state);
1002 	display_enable(state);
1003 
1004 	return 0;
1005 }
1006 
1007 static int get_crtc_id(ofnode connect)
1008 {
1009 	int phandle;
1010 	struct device_node *remote;
1011 	int val;
1012 
1013 	phandle = ofnode_read_u32_default(connect, "remote-endpoint", -1);
1014 	if (phandle < 0)
1015 		goto err;
1016 	remote = of_find_node_by_phandle(phandle);
1017 	val = ofnode_read_u32_default(np_to_ofnode(remote), "reg", -1);
1018 	if (val < 0)
1019 		goto err;
1020 
1021 	return val;
1022 err:
1023 	printf("Can't get crtc id, default set to id = 0\n");
1024 	return 0;
1025 }
1026 
1027 static int get_crtc_mcu_mode(struct crtc_state *crtc_state)
1028 {
1029 	ofnode mcu_node;
1030 	int total_pixel, cs_pst, cs_pend, rw_pst, rw_pend;
1031 
1032 	mcu_node = dev_read_subnode(crtc_state->dev, "mcu-timing");
1033 
1034 #define FDT_GET_MCU_INT(val, name) \
1035 	do { \
1036 		val = ofnode_read_s32_default(mcu_node, name, -1); \
1037 		if (val < 0) { \
1038 			printf("Can't get %s\n", name); \
1039 			return -ENXIO; \
1040 		} \
1041 	} while (0)
1042 
1043 	FDT_GET_MCU_INT(total_pixel, "mcu-pix-total");
1044 	FDT_GET_MCU_INT(cs_pst, "mcu-cs-pst");
1045 	FDT_GET_MCU_INT(cs_pend, "mcu-cs-pend");
1046 	FDT_GET_MCU_INT(rw_pst, "mcu-rw-pst");
1047 	FDT_GET_MCU_INT(rw_pend, "mcu-rw-pend");
1048 
1049 	crtc_state->mcu_timing.mcu_pix_total = total_pixel;
1050 	crtc_state->mcu_timing.mcu_cs_pst = cs_pst;
1051 	crtc_state->mcu_timing.mcu_cs_pend = cs_pend;
1052 	crtc_state->mcu_timing.mcu_rw_pst = rw_pst;
1053 	crtc_state->mcu_timing.mcu_rw_pend = rw_pend;
1054 
1055 	return 0;
1056 }
1057 
1058 struct rockchip_logo_cache *find_or_alloc_logo_cache(const char *bmp)
1059 {
1060 	struct rockchip_logo_cache *tmp, *logo_cache = NULL;
1061 
1062 	list_for_each_entry(tmp, &logo_cache_list, head) {
1063 		if (!strcmp(tmp->name, bmp)) {
1064 			logo_cache = tmp;
1065 			break;
1066 		}
1067 	}
1068 
1069 	if (!logo_cache) {
1070 		logo_cache = malloc(sizeof(*logo_cache));
1071 		if (!logo_cache) {
1072 			printf("failed to alloc memory for logo cache\n");
1073 			return NULL;
1074 		}
1075 		memset(logo_cache, 0, sizeof(*logo_cache));
1076 		strcpy(logo_cache->name, bmp);
1077 		INIT_LIST_HEAD(&logo_cache->head);
1078 		list_add_tail(&logo_cache->head, &logo_cache_list);
1079 	}
1080 
1081 	return logo_cache;
1082 }
1083 
1084 /* Note: used only for rkfb kernel driver */
1085 static int load_kernel_bmp_logo(struct logo_info *logo, const char *bmp_name)
1086 {
1087 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
1088 	void *dst = NULL;
1089 	int len, size;
1090 	struct bmp_header *header;
1091 
1092 	if (!logo || !bmp_name)
1093 		return -EINVAL;
1094 
1095 	header = malloc(RK_BLK_SIZE);
1096 	if (!header)
1097 		return -ENOMEM;
1098 
1099 	len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
1100 	if (len != RK_BLK_SIZE) {
1101 		free(header);
1102 		return -EINVAL;
1103 	}
1104 	size = get_unaligned_le32(&header->file_size);
1105 	dst = (void *)(memory_start + MEMORY_POOL_SIZE / 2);
1106 	len = rockchip_read_resource_file(dst, bmp_name, 0, size);
1107 	if (len != size) {
1108 		printf("failed to load bmp %s\n", bmp_name);
1109 		free(header);
1110 		return -ENOENT;
1111 	}
1112 
1113 	logo->mem = dst;
1114 
1115 	return 0;
1116 #endif
1117 }
1118 
1119 static int load_bmp_logo(struct logo_info *logo, const char *bmp_name)
1120 {
1121 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
1122 	struct rockchip_logo_cache *logo_cache;
1123 	struct bmp_header *header;
1124 	void *dst = NULL, *pdst;
1125 	int size, len;
1126 	int ret = 0;
1127 
1128 	if (!logo || !bmp_name)
1129 		return -EINVAL;
1130 	logo_cache = find_or_alloc_logo_cache(bmp_name);
1131 	if (!logo_cache)
1132 		return -ENOMEM;
1133 
1134 	if (logo_cache->logo.mem) {
1135 		memcpy(logo, &logo_cache->logo, sizeof(*logo));
1136 		return 0;
1137 	}
1138 
1139 	header = malloc(RK_BLK_SIZE);
1140 	if (!header)
1141 		return -ENOMEM;
1142 
1143 	len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE);
1144 	if (len != RK_BLK_SIZE) {
1145 		ret = -EINVAL;
1146 		goto free_header;
1147 	}
1148 
1149 	logo->bpp = get_unaligned_le16(&header->bit_count);
1150 	logo->width = get_unaligned_le32(&header->width);
1151 	logo->height = get_unaligned_le32(&header->height);
1152 
1153 	size = get_unaligned_le32(&header->file_size);
1154 	if (size > MEMORY_POOL_SIZE) {
1155 		printf("failed to use boot buf as temp bmp buffer\n");
1156 		ret = -ENOMEM;
1157 		goto free_header;
1158 	}
1159 
1160 	pdst = get_display_buffer(size);
1161 	dst = pdst;
1162 
1163 	len = rockchip_read_resource_file(pdst, bmp_name, 0, size);
1164 	if (len != size) {
1165 		printf("failed to load bmp %s\n", bmp_name);
1166 		ret = -ENOENT;
1167 		goto free_header;
1168 	}
1169 
1170 	if (!vop_support_ymirror(logo)) {
1171 		int dst_size;
1172 		/*
1173 		 * TODO: force use 16bpp if bpp less than 16;
1174 		 */
1175 		logo->bpp = (logo->bpp <= 16) ? 16 : logo->bpp;
1176 		dst_size = logo->width * logo->height * logo->bpp >> 3;
1177 
1178 		dst = get_display_buffer(dst_size);
1179 		if (!dst) {
1180 			ret = -ENOMEM;
1181 			goto free_header;
1182 		}
1183 		memset(dst, 0, dst_size);
1184 		if (bmpdecoder(pdst, dst, logo->bpp)) {
1185 			printf("failed to decode bmp %s\n", bmp_name);
1186 			ret = -EINVAL;
1187 			goto free_header;
1188 		}
1189 		flush_dcache_range((ulong)dst,
1190 				   ALIGN((ulong)dst + dst_size,
1191 					 CONFIG_SYS_CACHELINE_SIZE));
1192 
1193 		logo->offset = 0;
1194 		logo->ymirror = 0;
1195 	} else {
1196 		logo->offset = get_unaligned_le32(&header->data_offset);
1197 		logo->ymirror = 1;
1198 	}
1199 	logo->mem = dst;
1200 
1201 	memcpy(&logo_cache->logo, logo, sizeof(*logo));
1202 
1203 free_header:
1204 
1205 	free(header);
1206 
1207 	return ret;
1208 #else
1209 	return -EINVAL;
1210 #endif
1211 }
1212 
1213 void rockchip_show_fbbase(ulong fbbase)
1214 {
1215 	struct display_state *s;
1216 
1217 	list_for_each_entry(s, &rockchip_display_list, head) {
1218 		s->logo.mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1219 		s->logo.mem = (char *)fbbase;
1220 		s->logo.width = DRM_ROCKCHIP_FB_WIDTH;
1221 		s->logo.height = DRM_ROCKCHIP_FB_HEIGHT;
1222 		s->logo.bpp = 32;
1223 		s->logo.ymirror = 0;
1224 
1225 		display_logo(s);
1226 	}
1227 }
1228 
1229 void rockchip_show_bmp(const char *bmp)
1230 {
1231 	struct display_state *s;
1232 
1233 	if (!bmp) {
1234 		list_for_each_entry(s, &rockchip_display_list, head)
1235 			display_disable(s);
1236 		return;
1237 	}
1238 
1239 	list_for_each_entry(s, &rockchip_display_list, head) {
1240 		s->logo.mode = s->charge_logo_mode;
1241 		if (load_bmp_logo(&s->logo, bmp))
1242 			continue;
1243 		display_logo(s);
1244 	}
1245 }
1246 
1247 void rockchip_show_logo(void)
1248 {
1249 	struct display_state *s;
1250 
1251 	list_for_each_entry(s, &rockchip_display_list, head) {
1252 		s->logo.mode = s->logo_mode;
1253 		if (load_bmp_logo(&s->logo, s->ulogo_name))
1254 			printf("failed to display uboot logo\n");
1255 		else
1256 			display_logo(s);
1257 
1258 		/* Load kernel bmp in rockchip_display_fixup() later */
1259 	}
1260 }
1261 
1262 static struct udevice *rockchip_of_find_connector(ofnode endpoint)
1263 {
1264 	ofnode ep, port, ports, conn;
1265 	uint phandle;
1266 	struct udevice *dev;
1267 	int ret;
1268 
1269 	if (ofnode_read_u32(endpoint, "remote-endpoint", &phandle))
1270 		return NULL;
1271 
1272 	ep = ofnode_get_by_phandle(phandle);
1273 	if (!ofnode_valid(ep) || !ofnode_is_available(ep))
1274 		return NULL;
1275 
1276 	port = ofnode_get_parent(ep);
1277 	if (!ofnode_valid(port))
1278 		return NULL;
1279 
1280 	ports = ofnode_get_parent(port);
1281 	if (!ofnode_valid(ports))
1282 		return NULL;
1283 
1284 	conn = ofnode_get_parent(ports);
1285 	if (!ofnode_valid(conn) || !ofnode_is_available(conn))
1286 		return NULL;
1287 
1288 	ret = uclass_get_device_by_ofnode(UCLASS_DISPLAY, conn, &dev);
1289 	if (ret)
1290 		return NULL;
1291 
1292 	return dev;
1293 }
1294 
1295 static int rockchip_display_probe(struct udevice *dev)
1296 {
1297 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
1298 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
1299 	const void *blob = gd->fdt_blob;
1300 	int phandle;
1301 	struct udevice *crtc_dev, *conn_dev;
1302 	struct rockchip_crtc *crtc;
1303 	const struct rockchip_connector *conn;
1304 	struct display_state *s;
1305 	const char *name;
1306 	int ret;
1307 	ofnode node, route_node;
1308 	struct device_node *port_node, *vop_node, *ep_node;
1309 	struct public_phy_data *data;
1310 
1311 	/* Before relocation we don't need to do anything */
1312 	if (!(gd->flags & GD_FLG_RELOC))
1313 		return 0;
1314 
1315 	data = malloc(sizeof(struct public_phy_data));
1316 	if (!data) {
1317 		printf("failed to alloc phy data\n");
1318 		return -ENOMEM;
1319 	}
1320 	data->phy_init = false;
1321 
1322 	init_display_buffer(plat->base);
1323 
1324 	route_node = dev_read_subnode(dev, "route");
1325 	if (!ofnode_valid(route_node))
1326 		return -ENODEV;
1327 
1328 	ofnode_for_each_subnode(node, route_node) {
1329 		if (!ofnode_is_available(node))
1330 			continue;
1331 		phandle = ofnode_read_u32_default(node, "connect", -1);
1332 		if (phandle < 0) {
1333 			printf("Warn: can't find connect node's handle\n");
1334 			continue;
1335 		}
1336 		ep_node = of_find_node_by_phandle(phandle);
1337 		if (!ofnode_valid(np_to_ofnode(ep_node))) {
1338 			printf("Warn: can't find endpoint node from phandle\n");
1339 			continue;
1340 		}
1341 		port_node = of_get_parent(ep_node);
1342 		if (!ofnode_valid(np_to_ofnode(port_node))) {
1343 			printf("Warn: can't find port node from phandle\n");
1344 			continue;
1345 		}
1346 		vop_node = of_get_parent(port_node);
1347 		if (!ofnode_valid(np_to_ofnode(vop_node))) {
1348 			printf("Warn: can't find crtc node from phandle\n");
1349 			continue;
1350 		}
1351 		ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_CRTC,
1352 						  np_to_ofnode(vop_node),
1353 						  &crtc_dev);
1354 		if (ret) {
1355 			printf("Warn: can't find crtc driver %d\n", ret);
1356 			continue;
1357 		}
1358 		crtc = (struct rockchip_crtc *)dev_get_driver_data(crtc_dev);
1359 
1360 		conn_dev = rockchip_of_find_connector(np_to_ofnode(ep_node));
1361 		if (!conn_dev) {
1362 			printf("Warn: can't find connect driver\n");
1363 			continue;
1364 		}
1365 
1366 		conn = (const struct rockchip_connector *)dev_get_driver_data(conn_dev);
1367 
1368 		s = malloc(sizeof(*s));
1369 		if (!s)
1370 			continue;
1371 
1372 		memset(s, 0, sizeof(*s));
1373 
1374 		INIT_LIST_HEAD(&s->head);
1375 		ret = ofnode_read_string_index(node, "logo,uboot", 0, &name);
1376 		if (!ret)
1377 			memcpy(s->ulogo_name, name, strlen(name));
1378 		ret = ofnode_read_string_index(node, "logo,kernel", 0, &name);
1379 		if (!ret)
1380 			memcpy(s->klogo_name, name, strlen(name));
1381 		ret = ofnode_read_string_index(node, "logo,mode", 0, &name);
1382 		if (!strcmp(name, "fullscreen"))
1383 			s->logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1384 		else
1385 			s->logo_mode = ROCKCHIP_DISPLAY_CENTER;
1386 		ret = ofnode_read_string_index(node, "charge_logo,mode", 0, &name);
1387 		if (!strcmp(name, "fullscreen"))
1388 			s->charge_logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;
1389 		else
1390 			s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER;
1391 
1392 		s->blob = blob;
1393 		s->conn_state.node = conn_dev->node;
1394 		s->conn_state.dev = conn_dev;
1395 		s->conn_state.connector = conn;
1396 		s->conn_state.overscan.left_margin = 100;
1397 		s->conn_state.overscan.right_margin = 100;
1398 		s->conn_state.overscan.top_margin = 100;
1399 		s->conn_state.overscan.bottom_margin = 100;
1400 		s->crtc_state.node = np_to_ofnode(vop_node);
1401 		s->crtc_state.dev = crtc_dev;
1402 		s->crtc_state.crtc = crtc;
1403 		s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node));
1404 		s->node = node;
1405 		get_crtc_mcu_mode(&s->crtc_state);
1406 
1407 		if (connector_panel_init(s)) {
1408 			printf("Warn: Failed to init panel drivers\n");
1409 			free(s);
1410 			continue;
1411 		}
1412 
1413 		if (connector_phy_init(s, data)) {
1414 			printf("Warn: Failed to init phy drivers\n");
1415 			free(s);
1416 			continue;
1417 		}
1418 		list_add_tail(&s->head, &rockchip_display_list);
1419 	}
1420 
1421 	if (list_empty(&rockchip_display_list)) {
1422 		printf("Failed to found available display route\n");
1423 		return -ENODEV;
1424 	}
1425 
1426 	uc_priv->xsize = DRM_ROCKCHIP_FB_WIDTH;
1427 	uc_priv->ysize = DRM_ROCKCHIP_FB_HEIGHT;
1428 	uc_priv->bpix = VIDEO_BPP32;
1429 
1430 	#ifdef CONFIG_DRM_ROCKCHIP_VIDEO_FRAMEBUFFER
1431 	rockchip_show_fbbase(plat->base);
1432 	video_set_flush_dcache(dev, true);
1433 	#endif
1434 
1435 	return 0;
1436 }
1437 
1438 void rockchip_display_fixup(void *blob)
1439 {
1440 	const struct rockchip_connector_funcs *conn_funcs;
1441 	const struct rockchip_crtc_funcs *crtc_funcs;
1442 	const struct rockchip_connector *conn;
1443 	const struct rockchip_crtc *crtc;
1444 	struct display_state *s;
1445 	int offset;
1446 	const struct device_node *np;
1447 	const char *path;
1448 
1449 	if (!get_display_size())
1450 		return;
1451 
1452 	if (fdt_node_offset_by_compatible(blob, 0, "rockchip,drm-logo") >= 0) {
1453 		list_for_each_entry(s, &rockchip_display_list, head)
1454 			load_bmp_logo(&s->logo, s->klogo_name);
1455 		offset = fdt_update_reserved_memory(blob, "rockchip,drm-logo",
1456 						    (u64)memory_start,
1457 						    (u64)get_display_size());
1458 		if (offset < 0)
1459 			printf("failed to reserve drm-loader-logo memory\n");
1460 	} else {
1461 		printf("can't found rockchip,drm-logo, use rockchip,fb-logo\n");
1462 		/* Compatible with rkfb display, only need reserve memory */
1463 		offset = fdt_update_reserved_memory(blob, "rockchip,fb-logo",
1464 						    (u64)memory_start,
1465 						    MEMORY_POOL_SIZE);
1466 		if (offset < 0)
1467 			printf("failed to reserve fb-loader-logo memory\n");
1468 		else
1469 			list_for_each_entry(s, &rockchip_display_list, head)
1470 				load_kernel_bmp_logo(&s->logo, s->klogo_name);
1471 		return;
1472 	}
1473 
1474 	list_for_each_entry(s, &rockchip_display_list, head) {
1475 		conn = s->conn_state.connector;
1476 		if (!conn)
1477 			continue;
1478 		conn_funcs = conn->funcs;
1479 		if (!conn_funcs) {
1480 			printf("failed to get exist connector\n");
1481 			continue;
1482 		}
1483 
1484 		crtc = s->crtc_state.crtc;
1485 		if (!crtc)
1486 			continue;
1487 
1488 		crtc_funcs = crtc->funcs;
1489 		if (!crtc_funcs) {
1490 			printf("failed to get exist crtc\n");
1491 			continue;
1492 		}
1493 
1494 		if (crtc_funcs->fixup_dts)
1495 			crtc_funcs->fixup_dts(s, blob);
1496 
1497 		if (conn_funcs->fixup_dts)
1498 			conn_funcs->fixup_dts(s, blob);
1499 
1500 		np = ofnode_to_np(s->node);
1501 		path = np->full_name;
1502 		fdt_increase_size(blob, 0x400);
1503 #define FDT_SET_U32(name, val) \
1504 		do_fixup_by_path_u32(blob, path, name, val, 1);
1505 
1506 		offset = s->logo.offset + (u32)(unsigned long)s->logo.mem
1507 			 - memory_start;
1508 		FDT_SET_U32("logo,offset", offset);
1509 		FDT_SET_U32("logo,width", s->logo.width);
1510 		FDT_SET_U32("logo,height", s->logo.height);
1511 		FDT_SET_U32("logo,bpp", s->logo.bpp);
1512 		FDT_SET_U32("logo,ymirror", s->logo.ymirror);
1513 		FDT_SET_U32("video,hdisplay", s->conn_state.mode.hdisplay);
1514 		FDT_SET_U32("video,vdisplay", s->conn_state.mode.vdisplay);
1515 		FDT_SET_U32("video,crtc_hsync_end", s->conn_state.mode.crtc_hsync_end);
1516 		FDT_SET_U32("video,crtc_vsync_end", s->conn_state.mode.crtc_vsync_end);
1517 		FDT_SET_U32("video,vrefresh",
1518 			    drm_mode_vrefresh(&s->conn_state.mode));
1519 		FDT_SET_U32("video,flags", s->conn_state.mode.flags);
1520 		FDT_SET_U32("overscan,left_margin", s->conn_state.overscan.left_margin);
1521 		FDT_SET_U32("overscan,right_margin", s->conn_state.overscan.right_margin);
1522 		FDT_SET_U32("overscan,top_margin", s->conn_state.overscan.top_margin);
1523 		FDT_SET_U32("overscan,bottom_margin", s->conn_state.overscan.bottom_margin);
1524 #undef FDT_SET_U32
1525 	}
1526 }
1527 
1528 int rockchip_display_bind(struct udevice *dev)
1529 {
1530 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
1531 
1532 	plat->size = DRM_ROCKCHIP_FB_SIZE + MEMORY_POOL_SIZE;
1533 
1534 	return 0;
1535 }
1536 
1537 static const struct udevice_id rockchip_display_ids[] = {
1538 	{ .compatible = "rockchip,display-subsystem" },
1539 	{ }
1540 };
1541 
1542 U_BOOT_DRIVER(rockchip_display) = {
1543 	.name	= "rockchip_display",
1544 	.id	= UCLASS_VIDEO,
1545 	.of_match = rockchip_display_ids,
1546 	.bind	= rockchip_display_bind,
1547 	.probe	= rockchip_display_probe,
1548 };
1549 
1550 static int do_rockchip_logo_show(cmd_tbl_t *cmdtp, int flag, int argc,
1551 			char *const argv[])
1552 {
1553 	if (argc != 1)
1554 		return CMD_RET_USAGE;
1555 
1556 	rockchip_show_logo();
1557 
1558 	return 0;
1559 }
1560 
1561 static int do_rockchip_show_bmp(cmd_tbl_t *cmdtp, int flag, int argc,
1562 				char *const argv[])
1563 {
1564 	if (argc != 2)
1565 		return CMD_RET_USAGE;
1566 
1567 	rockchip_show_bmp(argv[1]);
1568 
1569 	return 0;
1570 }
1571 
1572 U_BOOT_CMD(
1573 	rockchip_show_logo, 1, 1, do_rockchip_logo_show,
1574 	"load and display log from resource partition",
1575 	NULL
1576 );
1577 
1578 U_BOOT_CMD(
1579 	rockchip_show_bmp, 2, 1, do_rockchip_show_bmp,
1580 	"load and display bmp from resource partition",
1581 	"    <bmp_name>"
1582 );
1583