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