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