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