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