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 struct drm_display_mode *mode = &conn_state->mode; 469 const struct drm_display_mode *m; 470 struct panel_state *panel_state = &state->panel_state; 471 const struct rockchip_panel *panel = panel_state->panel; 472 473 if (dev_of_valid(panel->dev) && 474 !display_get_timing_from_dts(panel_state, mode)) { 475 printf("Using display timing dts\n"); 476 goto done; 477 } 478 479 if (panel->data) { 480 m = (const struct drm_display_mode *)panel->data; 481 memcpy(mode, m, sizeof(*m)); 482 printf("Using display timing from compatible panel driver\n"); 483 goto done; 484 } 485 486 printf("failed to find display timing\n"); 487 return -ENODEV; 488 done: 489 printf("Detailed mode clock %u kHz, flags[%x]\n" 490 " H: %04d %04d %04d %04d\n" 491 " V: %04d %04d %04d %04d\n" 492 "bus_format: %x\n", 493 mode->clock, mode->flags, 494 mode->hdisplay, mode->hsync_start, 495 mode->hsync_end, mode->htotal, 496 mode->vdisplay, mode->vsync_start, 497 mode->vsync_end, mode->vtotal, 498 conn_state->bus_format); 499 500 return 0; 501 } 502 503 static int display_init(struct display_state *state) 504 { 505 struct connector_state *conn_state = &state->conn_state; 506 struct panel_state *panel_state = &state->panel_state; 507 const struct rockchip_connector *conn = conn_state->connector; 508 const struct rockchip_connector_funcs *conn_funcs = conn->funcs; 509 struct crtc_state *crtc_state = &state->crtc_state; 510 struct rockchip_crtc *crtc = crtc_state->crtc; 511 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 512 struct drm_display_mode *mode = &conn_state->mode; 513 int bpc; 514 int ret = 0; 515 static bool __print_once = false; 516 517 if (!__print_once) { 518 __print_once = true; 519 printf("Rockchip UBOOT DRM driver version: %s\n", DRIVER_VERSION); 520 } 521 522 if (state->is_init) 523 return 0; 524 525 if (!conn_funcs || !crtc_funcs) { 526 printf("failed to find connector or crtc functions\n"); 527 return -ENXIO; 528 } 529 530 if (panel_state->panel) 531 rockchip_panel_init(panel_state->panel); 532 533 if (conn_funcs->init) { 534 ret = conn_funcs->init(state); 535 if (ret) 536 goto deinit; 537 } 538 539 if (conn_state->phy) 540 rockchip_phy_init(conn_state->phy); 541 542 /* 543 * support hotplug, but not connect; 544 */ 545 #ifdef CONFIG_ROCKCHIP_DRM_TVE 546 if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_TV) { 547 printf("hdmi plugin ,skip tve\n"); 548 goto deinit; 549 } 550 #elif defined(CONFIG_ROCKCHIP_DRM_RK1000) 551 if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_LVDS) { 552 printf("hdmi plugin ,skip tve\n"); 553 goto deinit; 554 } 555 #endif 556 if (conn_funcs->detect) { 557 ret = conn_funcs->detect(state); 558 #if defined(CONFIG_ROCKCHIP_DRM_TVE) || defined(CONFIG_ROCKCHIP_DRM_RK1000) 559 if (conn_state->type == DRM_MODE_CONNECTOR_HDMIA) 560 crtc->hdmi_hpd = ret; 561 #endif 562 if (!ret) 563 goto deinit; 564 } 565 566 if (panel_state->panel) { 567 ret = display_get_timing(state); 568 } else if (conn_state->bridge) { 569 ret = video_bridge_read_edid(conn_state->bridge->dev, 570 conn_state->edid, EDID_SIZE); 571 if (ret > 0) { 572 ret = edid_get_drm_mode(conn_state->edid, ret, mode, 573 &bpc); 574 if (!ret) 575 edid_print_info((void *)&conn_state->edid); 576 } 577 } else if (conn_funcs->get_timing) { 578 ret = conn_funcs->get_timing(state); 579 } else if (conn_funcs->get_edid) { 580 ret = conn_funcs->get_edid(state); 581 if (!ret) { 582 ret = edid_get_drm_mode((void *)&conn_state->edid, 583 sizeof(conn_state->edid), mode, 584 &bpc); 585 if (!ret) 586 edid_print_info((void *)&conn_state->edid); 587 } 588 } 589 590 if (ret) 591 goto deinit; 592 593 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 594 595 if (crtc_funcs->init) { 596 ret = crtc_funcs->init(state); 597 if (ret) 598 goto deinit; 599 } 600 state->is_init = 1; 601 602 return 0; 603 604 deinit: 605 if (conn_funcs->deinit) 606 conn_funcs->deinit(state); 607 return ret; 608 } 609 610 int display_send_mcu_cmd(struct display_state *state, u32 type, u32 val) 611 { 612 struct crtc_state *crtc_state = &state->crtc_state; 613 const struct rockchip_crtc *crtc = crtc_state->crtc; 614 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 615 int ret; 616 617 if (!state->is_init) 618 return -EINVAL; 619 620 if (crtc_funcs->send_mcu_cmd) { 621 ret = crtc_funcs->send_mcu_cmd(state, type, val); 622 if (ret) 623 return ret; 624 } 625 626 return 0; 627 } 628 629 static int display_set_plane(struct display_state *state) 630 { 631 struct crtc_state *crtc_state = &state->crtc_state; 632 const struct rockchip_crtc *crtc = crtc_state->crtc; 633 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 634 int ret; 635 636 if (!state->is_init) 637 return -EINVAL; 638 639 if (crtc_funcs->set_plane) { 640 ret = crtc_funcs->set_plane(state); 641 if (ret) 642 return ret; 643 } 644 645 return 0; 646 } 647 648 static int display_enable(struct display_state *state) 649 { 650 struct connector_state *conn_state = &state->conn_state; 651 const struct rockchip_connector *conn = conn_state->connector; 652 const struct rockchip_connector_funcs *conn_funcs = conn->funcs; 653 struct crtc_state *crtc_state = &state->crtc_state; 654 const struct rockchip_crtc *crtc = crtc_state->crtc; 655 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 656 struct panel_state *panel_state = &state->panel_state; 657 658 display_init(state); 659 660 if (!state->is_init) 661 return -EINVAL; 662 663 if (state->is_enable) 664 return 0; 665 666 if (crtc_funcs->prepare) 667 crtc_funcs->prepare(state); 668 669 if (conn_funcs->prepare) 670 conn_funcs->prepare(state); 671 672 if (conn_state->bridge) 673 rockchip_bridge_pre_enable(conn_state->bridge); 674 675 if (panel_state->panel) 676 rockchip_panel_prepare(panel_state->panel); 677 678 if (crtc_funcs->enable) 679 crtc_funcs->enable(state); 680 681 if (conn_funcs->enable) 682 conn_funcs->enable(state); 683 684 if (conn_state->bridge) 685 rockchip_bridge_enable(conn_state->bridge); 686 687 if (panel_state->panel) 688 rockchip_panel_enable(panel_state->panel); 689 690 state->is_enable = true; 691 692 return 0; 693 } 694 695 static int display_disable(struct display_state *state) 696 { 697 struct connector_state *conn_state = &state->conn_state; 698 const struct rockchip_connector *conn = conn_state->connector; 699 const struct rockchip_connector_funcs *conn_funcs = conn->funcs; 700 struct crtc_state *crtc_state = &state->crtc_state; 701 const struct rockchip_crtc *crtc = crtc_state->crtc; 702 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 703 struct panel_state *panel_state = &state->panel_state; 704 705 if (!state->is_init) 706 return 0; 707 708 if (!state->is_enable) 709 return 0; 710 711 if (panel_state->panel) 712 rockchip_panel_disable(panel_state->panel); 713 714 if (conn_state->bridge) 715 rockchip_bridge_disable(conn_state->bridge); 716 717 if (conn_funcs->disable) 718 conn_funcs->disable(state); 719 720 if (crtc_funcs->disable) 721 crtc_funcs->disable(state); 722 723 if (panel_state->panel) 724 rockchip_panel_unprepare(panel_state->panel); 725 726 if (conn_state->bridge) 727 rockchip_bridge_post_disable(conn_state->bridge); 728 729 if (conn_funcs->unprepare) 730 conn_funcs->unprepare(state); 731 732 state->is_enable = 0; 733 state->is_init = 0; 734 735 return 0; 736 } 737 738 static int display_logo(struct display_state *state) 739 { 740 struct crtc_state *crtc_state = &state->crtc_state; 741 struct connector_state *conn_state = &state->conn_state; 742 struct logo_info *logo = &state->logo; 743 int hdisplay, vdisplay; 744 745 display_init(state); 746 if (!state->is_init) 747 return -ENODEV; 748 749 switch (logo->bpp) { 750 case 16: 751 crtc_state->format = ROCKCHIP_FMT_RGB565; 752 break; 753 case 24: 754 crtc_state->format = ROCKCHIP_FMT_RGB888; 755 break; 756 case 32: 757 crtc_state->format = ROCKCHIP_FMT_ARGB8888; 758 break; 759 default: 760 printf("can't support bmp bits[%d]\n", logo->bpp); 761 return -EINVAL; 762 } 763 crtc_state->rb_swap = logo->bpp != 32; 764 hdisplay = conn_state->mode.hdisplay; 765 vdisplay = conn_state->mode.vdisplay; 766 crtc_state->src_w = logo->width; 767 crtc_state->src_h = logo->height; 768 crtc_state->src_x = 0; 769 crtc_state->src_y = 0; 770 crtc_state->ymirror = logo->ymirror; 771 772 crtc_state->dma_addr = (u32)(unsigned long)logo->mem + logo->offset; 773 crtc_state->xvir = ALIGN(crtc_state->src_w * logo->bpp, 32) >> 5; 774 775 if (logo->mode == ROCKCHIP_DISPLAY_FULLSCREEN) { 776 crtc_state->crtc_x = 0; 777 crtc_state->crtc_y = 0; 778 crtc_state->crtc_w = hdisplay; 779 crtc_state->crtc_h = vdisplay; 780 } else { 781 if (crtc_state->src_w >= hdisplay) { 782 crtc_state->crtc_x = 0; 783 crtc_state->crtc_w = hdisplay; 784 } else { 785 crtc_state->crtc_x = (hdisplay - crtc_state->src_w) / 2; 786 crtc_state->crtc_w = crtc_state->src_w; 787 } 788 789 if (crtc_state->src_h >= vdisplay) { 790 crtc_state->crtc_y = 0; 791 crtc_state->crtc_h = vdisplay; 792 } else { 793 crtc_state->crtc_y = (vdisplay - crtc_state->src_h) / 2; 794 crtc_state->crtc_h = crtc_state->src_h; 795 } 796 } 797 798 display_set_plane(state); 799 display_enable(state); 800 801 return 0; 802 } 803 804 static int get_crtc_id(ofnode connect) 805 { 806 int phandle; 807 struct device_node *remote; 808 int val; 809 810 phandle = ofnode_read_u32_default(connect, "remote-endpoint", -1); 811 if (phandle < 0) 812 goto err; 813 remote = of_find_node_by_phandle(phandle); 814 val = ofnode_read_u32_default(np_to_ofnode(remote), "reg", -1); 815 if (val < 0) 816 goto err; 817 818 return val; 819 err: 820 printf("Can't get crtc id, default set to id = 0\n"); 821 return 0; 822 } 823 824 static int get_crtc_mcu_mode(struct crtc_state *crtc_state) 825 { 826 ofnode mcu_node; 827 int total_pixel, cs_pst, cs_pend, rw_pst, rw_pend; 828 829 mcu_node = dev_read_subnode(crtc_state->dev, "mcu-timing"); 830 if (!ofnode_valid(mcu_node)) 831 return -ENODEV; 832 833 #define FDT_GET_MCU_INT(val, name) \ 834 do { \ 835 val = ofnode_read_s32_default(mcu_node, name, -1); \ 836 if (val < 0) { \ 837 printf("Can't get %s\n", name); \ 838 return -ENXIO; \ 839 } \ 840 } while (0) 841 842 FDT_GET_MCU_INT(total_pixel, "mcu-pix-total"); 843 FDT_GET_MCU_INT(cs_pst, "mcu-cs-pst"); 844 FDT_GET_MCU_INT(cs_pend, "mcu-cs-pend"); 845 FDT_GET_MCU_INT(rw_pst, "mcu-rw-pst"); 846 FDT_GET_MCU_INT(rw_pend, "mcu-rw-pend"); 847 848 crtc_state->mcu_timing.mcu_pix_total = total_pixel; 849 crtc_state->mcu_timing.mcu_cs_pst = cs_pst; 850 crtc_state->mcu_timing.mcu_cs_pend = cs_pend; 851 crtc_state->mcu_timing.mcu_rw_pst = rw_pst; 852 crtc_state->mcu_timing.mcu_rw_pend = rw_pend; 853 854 return 0; 855 } 856 857 struct rockchip_logo_cache *find_or_alloc_logo_cache(const char *bmp) 858 { 859 struct rockchip_logo_cache *tmp, *logo_cache = NULL; 860 861 list_for_each_entry(tmp, &logo_cache_list, head) { 862 if (!strcmp(tmp->name, bmp)) { 863 logo_cache = tmp; 864 break; 865 } 866 } 867 868 if (!logo_cache) { 869 logo_cache = malloc(sizeof(*logo_cache)); 870 if (!logo_cache) { 871 printf("failed to alloc memory for logo cache\n"); 872 return NULL; 873 } 874 memset(logo_cache, 0, sizeof(*logo_cache)); 875 strcpy(logo_cache->name, bmp); 876 INIT_LIST_HEAD(&logo_cache->head); 877 list_add_tail(&logo_cache->head, &logo_cache_list); 878 } 879 880 return logo_cache; 881 } 882 883 /* Note: used only for rkfb kernel driver */ 884 static int load_kernel_bmp_logo(struct logo_info *logo, const char *bmp_name) 885 { 886 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 887 void *dst = NULL; 888 int len, size; 889 struct bmp_header *header; 890 891 if (!logo || !bmp_name) 892 return -EINVAL; 893 894 header = malloc(RK_BLK_SIZE); 895 if (!header) 896 return -ENOMEM; 897 898 len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE); 899 if (len != RK_BLK_SIZE) { 900 free(header); 901 return -EINVAL; 902 } 903 size = get_unaligned_le32(&header->file_size); 904 dst = (void *)(memory_start + MEMORY_POOL_SIZE / 2); 905 len = rockchip_read_resource_file(dst, bmp_name, 0, size); 906 if (len != size) { 907 printf("failed to load bmp %s\n", bmp_name); 908 free(header); 909 return -ENOENT; 910 } 911 912 logo->mem = dst; 913 914 return 0; 915 #endif 916 } 917 918 static int load_bmp_logo(struct logo_info *logo, const char *bmp_name) 919 { 920 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 921 struct rockchip_logo_cache *logo_cache; 922 struct bmp_header *header; 923 void *dst = NULL, *pdst; 924 int size, len; 925 int ret = 0; 926 927 if (!logo || !bmp_name) 928 return -EINVAL; 929 logo_cache = find_or_alloc_logo_cache(bmp_name); 930 if (!logo_cache) 931 return -ENOMEM; 932 933 if (logo_cache->logo.mem) { 934 memcpy(logo, &logo_cache->logo, sizeof(*logo)); 935 return 0; 936 } 937 938 header = malloc(RK_BLK_SIZE); 939 if (!header) 940 return -ENOMEM; 941 942 len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE); 943 if (len != RK_BLK_SIZE) { 944 ret = -EINVAL; 945 goto free_header; 946 } 947 948 logo->bpp = get_unaligned_le16(&header->bit_count); 949 logo->width = get_unaligned_le32(&header->width); 950 logo->height = get_unaligned_le32(&header->height); 951 size = get_unaligned_le32(&header->file_size); 952 if (!can_direct_logo(logo->bpp)) { 953 if (size > MEMORY_POOL_SIZE) { 954 printf("failed to use boot buf as temp bmp buffer\n"); 955 ret = -ENOMEM; 956 goto free_header; 957 } 958 pdst = get_display_buffer(size); 959 960 } else { 961 pdst = get_display_buffer(size); 962 dst = pdst; 963 } 964 965 len = rockchip_read_resource_file(pdst, bmp_name, 0, size); 966 if (len != size) { 967 printf("failed to load bmp %s\n", bmp_name); 968 ret = -ENOENT; 969 goto free_header; 970 } 971 972 if (!can_direct_logo(logo->bpp)) { 973 int dst_size; 974 /* 975 * TODO: force use 16bpp if bpp less than 16; 976 */ 977 logo->bpp = (logo->bpp <= 16) ? 16 : logo->bpp; 978 dst_size = logo->width * logo->height * logo->bpp >> 3; 979 980 dst = get_display_buffer(dst_size); 981 if (!dst) { 982 ret = -ENOMEM; 983 goto free_header; 984 } 985 if (bmpdecoder(pdst, dst, logo->bpp)) { 986 printf("failed to decode bmp %s\n", bmp_name); 987 ret = -EINVAL; 988 goto free_header; 989 } 990 flush_dcache_range((ulong)dst, 991 ALIGN((ulong)dst + dst_size, 992 CONFIG_SYS_CACHELINE_SIZE)); 993 994 logo->offset = 0; 995 logo->ymirror = 0; 996 } else { 997 logo->offset = get_unaligned_le32(&header->data_offset); 998 logo->ymirror = 1; 999 } 1000 logo->mem = dst; 1001 1002 memcpy(&logo_cache->logo, logo, sizeof(*logo)); 1003 1004 free_header: 1005 1006 free(header); 1007 1008 return ret; 1009 #else 1010 return -EINVAL; 1011 #endif 1012 } 1013 1014 void rockchip_show_fbbase(ulong fbbase) 1015 { 1016 struct display_state *s; 1017 1018 list_for_each_entry(s, &rockchip_display_list, head) { 1019 s->logo.mode = ROCKCHIP_DISPLAY_FULLSCREEN; 1020 s->logo.mem = (char *)fbbase; 1021 s->logo.width = DRM_ROCKCHIP_FB_WIDTH; 1022 s->logo.height = DRM_ROCKCHIP_FB_HEIGHT; 1023 s->logo.bpp = 32; 1024 s->logo.ymirror = 0; 1025 1026 display_logo(s); 1027 } 1028 } 1029 1030 void rockchip_show_bmp(const char *bmp) 1031 { 1032 struct display_state *s; 1033 1034 if (!bmp) { 1035 list_for_each_entry(s, &rockchip_display_list, head) 1036 display_disable(s); 1037 return; 1038 } 1039 1040 list_for_each_entry(s, &rockchip_display_list, head) { 1041 s->logo.mode = s->charge_logo_mode; 1042 if (load_bmp_logo(&s->logo, bmp)) 1043 continue; 1044 display_logo(s); 1045 } 1046 } 1047 1048 void rockchip_show_logo(void) 1049 { 1050 struct display_state *s; 1051 1052 list_for_each_entry(s, &rockchip_display_list, head) { 1053 s->logo.mode = s->logo_mode; 1054 if (load_bmp_logo(&s->logo, s->ulogo_name)) 1055 printf("failed to display uboot logo\n"); 1056 else 1057 display_logo(s); 1058 1059 /* Load kernel bmp in rockchip_display_fixup() later */ 1060 } 1061 } 1062 1063 enum { 1064 PORT_DIR_IN, 1065 PORT_DIR_OUT, 1066 }; 1067 1068 static struct rockchip_panel *rockchip_of_find_panel(struct udevice *dev) 1069 { 1070 ofnode panel_node, ports, port, ep; 1071 struct udevice *panel_dev; 1072 int ret; 1073 1074 panel_node = dev_read_subnode(dev, "panel"); 1075 if (ofnode_valid(panel_node) && ofnode_is_available(panel_node)) { 1076 ret = uclass_get_device_by_ofnode(UCLASS_PANEL, panel_node, 1077 &panel_dev); 1078 if (!ret) 1079 goto found; 1080 } 1081 1082 ports = dev_read_subnode(dev, "ports"); 1083 if (!ofnode_valid(ports)) 1084 return NULL; 1085 1086 ofnode_for_each_subnode(port, ports) { 1087 u32 reg; 1088 1089 if (ofnode_read_u32(port, "reg", ®)) 1090 continue; 1091 1092 if (reg != PORT_DIR_OUT) 1093 continue; 1094 1095 ofnode_for_each_subnode(ep, port) { 1096 ofnode _ep, _port; 1097 uint phandle; 1098 1099 if (ofnode_read_u32(ep, "remote-endpoint", &phandle)) 1100 continue; 1101 1102 _ep = ofnode_get_by_phandle(phandle); 1103 if (!ofnode_valid(_ep)) 1104 continue; 1105 1106 _port = ofnode_get_parent(_ep); 1107 if (!ofnode_valid(_port)) 1108 continue; 1109 1110 panel_node = ofnode_get_parent(_port); 1111 if (!ofnode_valid(panel_node)) 1112 continue; 1113 1114 ret = uclass_get_device_by_ofnode(UCLASS_PANEL, 1115 panel_node, 1116 &panel_dev); 1117 if (!ret) 1118 goto found; 1119 } 1120 } 1121 1122 return NULL; 1123 1124 found: 1125 return (struct rockchip_panel *)dev_get_driver_data(panel_dev); 1126 } 1127 1128 static struct rockchip_bridge *rockchip_of_find_bridge(struct udevice *conn_dev) 1129 { 1130 ofnode node, ports, port, ep; 1131 struct udevice *dev; 1132 int ret; 1133 1134 ports = dev_read_subnode(conn_dev, "ports"); 1135 if (!ofnode_valid(ports)) 1136 return NULL; 1137 1138 ofnode_for_each_subnode(port, ports) { 1139 u32 reg; 1140 1141 if (ofnode_read_u32(port, "reg", ®)) 1142 continue; 1143 1144 if (reg != PORT_DIR_OUT) 1145 continue; 1146 1147 ofnode_for_each_subnode(ep, port) { 1148 ofnode _ep, _port, _ports; 1149 uint phandle; 1150 1151 if (ofnode_read_u32(ep, "remote-endpoint", &phandle)) 1152 continue; 1153 1154 _ep = ofnode_get_by_phandle(phandle); 1155 if (!ofnode_valid(_ep)) 1156 continue; 1157 1158 _port = ofnode_get_parent(_ep); 1159 if (!ofnode_valid(_port)) 1160 continue; 1161 1162 _ports = ofnode_get_parent(_port); 1163 if (!ofnode_valid(_ports)) 1164 continue; 1165 1166 node = ofnode_get_parent(_ports); 1167 if (!ofnode_valid(node)) 1168 continue; 1169 1170 ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_BRIDGE, 1171 node, &dev); 1172 if (!ret) 1173 goto found; 1174 } 1175 } 1176 1177 return NULL; 1178 1179 found: 1180 return (struct rockchip_bridge *)dev_get_driver_data(dev); 1181 } 1182 1183 static struct udevice *rockchip_of_find_connector(ofnode endpoint) 1184 { 1185 ofnode ep, port, ports, conn; 1186 uint phandle; 1187 struct udevice *dev; 1188 int ret; 1189 1190 if (ofnode_read_u32(endpoint, "remote-endpoint", &phandle)) 1191 return NULL; 1192 1193 ep = ofnode_get_by_phandle(phandle); 1194 if (!ofnode_valid(ep) || !ofnode_is_available(ep)) 1195 return NULL; 1196 1197 port = ofnode_get_parent(ep); 1198 if (!ofnode_valid(port)) 1199 return NULL; 1200 1201 ports = ofnode_get_parent(port); 1202 if (!ofnode_valid(ports)) 1203 return NULL; 1204 1205 conn = ofnode_get_parent(ports); 1206 if (!ofnode_valid(conn) || !ofnode_is_available(conn)) 1207 return NULL; 1208 1209 ret = uclass_get_device_by_ofnode(UCLASS_DISPLAY, conn, &dev); 1210 if (ret) 1211 return NULL; 1212 1213 return dev; 1214 } 1215 1216 static struct rockchip_phy *rockchip_of_find_phy(struct udevice *dev) 1217 { 1218 struct udevice *phy_dev; 1219 int ret; 1220 1221 ret = uclass_get_device_by_phandle(UCLASS_PHY, dev, "phys", &phy_dev); 1222 if (ret) 1223 return NULL; 1224 1225 return (struct rockchip_phy *)dev_get_driver_data(phy_dev); 1226 } 1227 1228 static int rockchip_display_probe(struct udevice *dev) 1229 { 1230 struct video_priv *uc_priv = dev_get_uclass_priv(dev); 1231 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 1232 const void *blob = gd->fdt_blob; 1233 int phandle; 1234 struct udevice *crtc_dev, *conn_dev; 1235 struct rockchip_crtc *crtc; 1236 const struct rockchip_connector *conn; 1237 struct rockchip_panel *panel = NULL; 1238 struct rockchip_bridge *bridge = NULL; 1239 struct rockchip_phy *phy = NULL; 1240 struct display_state *s; 1241 const char *name; 1242 int ret; 1243 ofnode node, route_node; 1244 struct device_node *port_node, *vop_node, *ep_node; 1245 struct public_phy_data *data; 1246 1247 /* Before relocation we don't need to do anything */ 1248 if (!(gd->flags & GD_FLG_RELOC)) 1249 return 0; 1250 1251 data = malloc(sizeof(struct public_phy_data)); 1252 if (!data) { 1253 printf("failed to alloc phy data\n"); 1254 return -ENOMEM; 1255 } 1256 data->phy_init = false; 1257 1258 init_display_buffer(plat->base); 1259 1260 route_node = dev_read_subnode(dev, "route"); 1261 if (!ofnode_valid(route_node)) 1262 return -ENODEV; 1263 1264 ofnode_for_each_subnode(node, route_node) { 1265 if (!ofnode_is_available(node)) 1266 continue; 1267 phandle = ofnode_read_u32_default(node, "connect", -1); 1268 if (phandle < 0) { 1269 printf("Warn: can't find connect node's handle\n"); 1270 continue; 1271 } 1272 ep_node = of_find_node_by_phandle(phandle); 1273 if (!ofnode_valid(np_to_ofnode(ep_node))) { 1274 printf("Warn: can't find endpoint node from phandle\n"); 1275 continue; 1276 } 1277 port_node = of_get_parent(ep_node); 1278 if (!ofnode_valid(np_to_ofnode(port_node))) { 1279 printf("Warn: can't find port node from phandle\n"); 1280 continue; 1281 } 1282 vop_node = of_get_parent(port_node); 1283 if (!ofnode_valid(np_to_ofnode(vop_node))) { 1284 printf("Warn: can't find crtc node from phandle\n"); 1285 continue; 1286 } 1287 ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_CRTC, 1288 np_to_ofnode(vop_node), 1289 &crtc_dev); 1290 if (ret) { 1291 printf("Warn: can't find crtc driver %d\n", ret); 1292 continue; 1293 } 1294 crtc = (struct rockchip_crtc *)dev_get_driver_data(crtc_dev); 1295 1296 conn_dev = rockchip_of_find_connector(np_to_ofnode(ep_node)); 1297 if (!conn_dev) { 1298 printf("Warn: can't find connect driver\n"); 1299 continue; 1300 } 1301 1302 conn = (const struct rockchip_connector *)dev_get_driver_data(conn_dev); 1303 1304 phy = rockchip_of_find_phy(conn_dev); 1305 1306 bridge = rockchip_of_find_bridge(conn_dev); 1307 if (bridge) 1308 panel = rockchip_of_find_panel(bridge->dev); 1309 else 1310 panel = rockchip_of_find_panel(conn_dev); 1311 1312 s = malloc(sizeof(*s)); 1313 if (!s) 1314 continue; 1315 1316 memset(s, 0, sizeof(*s)); 1317 1318 INIT_LIST_HEAD(&s->head); 1319 ret = ofnode_read_string_index(node, "logo,uboot", 0, &name); 1320 if (!ret) 1321 memcpy(s->ulogo_name, name, strlen(name)); 1322 ret = ofnode_read_string_index(node, "logo,kernel", 0, &name); 1323 if (!ret) 1324 memcpy(s->klogo_name, name, strlen(name)); 1325 ret = ofnode_read_string_index(node, "logo,mode", 0, &name); 1326 if (!strcmp(name, "fullscreen")) 1327 s->logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN; 1328 else 1329 s->logo_mode = ROCKCHIP_DISPLAY_CENTER; 1330 ret = ofnode_read_string_index(node, "charge_logo,mode", 0, &name); 1331 if (!strcmp(name, "fullscreen")) 1332 s->charge_logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN; 1333 else 1334 s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER; 1335 1336 s->blob = blob; 1337 s->panel_state.panel = panel; 1338 s->conn_state.node = conn_dev->node; 1339 s->conn_state.dev = conn_dev; 1340 s->conn_state.connector = conn; 1341 s->conn_state.phy = phy; 1342 s->conn_state.bridge = bridge; 1343 s->conn_state.overscan.left_margin = 100; 1344 s->conn_state.overscan.right_margin = 100; 1345 s->conn_state.overscan.top_margin = 100; 1346 s->conn_state.overscan.bottom_margin = 100; 1347 s->crtc_state.node = np_to_ofnode(vop_node); 1348 s->crtc_state.dev = crtc_dev; 1349 s->crtc_state.crtc = crtc; 1350 s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node)); 1351 s->node = node; 1352 1353 if (bridge) 1354 bridge->state = s; 1355 1356 if (panel) 1357 panel->state = s; 1358 1359 get_crtc_mcu_mode(&s->crtc_state); 1360 1361 if (connector_panel_init(s)) { 1362 printf("Warn: Failed to init panel drivers\n"); 1363 free(s); 1364 continue; 1365 } 1366 1367 if (connector_phy_init(s, data)) { 1368 printf("Warn: Failed to init phy drivers\n"); 1369 free(s); 1370 continue; 1371 } 1372 list_add_tail(&s->head, &rockchip_display_list); 1373 } 1374 1375 if (list_empty(&rockchip_display_list)) { 1376 printf("Failed to found available display route\n"); 1377 return -ENODEV; 1378 } 1379 1380 uc_priv->xsize = DRM_ROCKCHIP_FB_WIDTH; 1381 uc_priv->ysize = DRM_ROCKCHIP_FB_HEIGHT; 1382 uc_priv->bpix = VIDEO_BPP32; 1383 1384 #ifdef CONFIG_DRM_ROCKCHIP_VIDEO_FRAMEBUFFER 1385 rockchip_show_fbbase(plat->base); 1386 video_set_flush_dcache(dev, true); 1387 #endif 1388 1389 return 0; 1390 } 1391 1392 void rockchip_display_fixup(void *blob) 1393 { 1394 const struct rockchip_connector_funcs *conn_funcs; 1395 const struct rockchip_crtc_funcs *crtc_funcs; 1396 const struct rockchip_connector *conn; 1397 const struct rockchip_crtc *crtc; 1398 struct display_state *s; 1399 int offset; 1400 const struct device_node *np; 1401 const char *path; 1402 1403 if (!get_display_size()) 1404 return; 1405 1406 if (fdt_node_offset_by_compatible(blob, 0, "rockchip,drm-logo") >= 0) { 1407 list_for_each_entry(s, &rockchip_display_list, head) 1408 load_bmp_logo(&s->logo, s->klogo_name); 1409 offset = fdt_update_reserved_memory(blob, "rockchip,drm-logo", 1410 (u64)memory_start, 1411 (u64)get_display_size()); 1412 if (offset < 0) 1413 printf("failed to reserve drm-loader-logo memory\n"); 1414 } else { 1415 printf("can't found rockchip,drm-logo, use rockchip,fb-logo\n"); 1416 /* Compatible with rkfb display, only need reserve memory */ 1417 offset = fdt_update_reserved_memory(blob, "rockchip,fb-logo", 1418 (u64)memory_start, 1419 MEMORY_POOL_SIZE); 1420 if (offset < 0) 1421 printf("failed to reserve fb-loader-logo memory\n"); 1422 else 1423 list_for_each_entry(s, &rockchip_display_list, head) 1424 load_kernel_bmp_logo(&s->logo, s->klogo_name); 1425 return; 1426 } 1427 1428 list_for_each_entry(s, &rockchip_display_list, head) { 1429 conn = s->conn_state.connector; 1430 if (!conn) 1431 continue; 1432 conn_funcs = conn->funcs; 1433 if (!conn_funcs) { 1434 printf("failed to get exist connector\n"); 1435 continue; 1436 } 1437 1438 crtc = s->crtc_state.crtc; 1439 if (!crtc) 1440 continue; 1441 1442 crtc_funcs = crtc->funcs; 1443 if (!crtc_funcs) { 1444 printf("failed to get exist crtc\n"); 1445 continue; 1446 } 1447 1448 if (crtc_funcs->fixup_dts) 1449 crtc_funcs->fixup_dts(s, blob); 1450 1451 if (conn_funcs->fixup_dts) 1452 conn_funcs->fixup_dts(s, blob); 1453 1454 np = ofnode_to_np(s->node); 1455 path = np->full_name; 1456 fdt_increase_size(blob, 0x400); 1457 #define FDT_SET_U32(name, val) \ 1458 do_fixup_by_path_u32(blob, path, name, val, 1); 1459 1460 offset = s->logo.offset + (u32)(unsigned long)s->logo.mem 1461 - memory_start; 1462 FDT_SET_U32("logo,offset", offset); 1463 FDT_SET_U32("logo,width", s->logo.width); 1464 FDT_SET_U32("logo,height", s->logo.height); 1465 FDT_SET_U32("logo,bpp", s->logo.bpp); 1466 FDT_SET_U32("logo,ymirror", s->logo.ymirror); 1467 FDT_SET_U32("video,hdisplay", s->conn_state.mode.hdisplay); 1468 FDT_SET_U32("video,vdisplay", s->conn_state.mode.vdisplay); 1469 FDT_SET_U32("video,crtc_hsync_end", s->conn_state.mode.crtc_hsync_end); 1470 FDT_SET_U32("video,crtc_vsync_end", s->conn_state.mode.crtc_vsync_end); 1471 FDT_SET_U32("video,vrefresh", 1472 drm_mode_vrefresh(&s->conn_state.mode)); 1473 FDT_SET_U32("video,flags", s->conn_state.mode.flags); 1474 FDT_SET_U32("overscan,left_margin", s->conn_state.overscan.left_margin); 1475 FDT_SET_U32("overscan,right_margin", s->conn_state.overscan.right_margin); 1476 FDT_SET_U32("overscan,top_margin", s->conn_state.overscan.top_margin); 1477 FDT_SET_U32("overscan,bottom_margin", s->conn_state.overscan.bottom_margin); 1478 #undef FDT_SET_U32 1479 } 1480 } 1481 1482 int rockchip_display_bind(struct udevice *dev) 1483 { 1484 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 1485 1486 plat->size = DRM_ROCKCHIP_FB_SIZE + MEMORY_POOL_SIZE; 1487 1488 return 0; 1489 } 1490 1491 static const struct udevice_id rockchip_display_ids[] = { 1492 { .compatible = "rockchip,display-subsystem" }, 1493 { } 1494 }; 1495 1496 U_BOOT_DRIVER(rockchip_display) = { 1497 .name = "rockchip_display", 1498 .id = UCLASS_VIDEO, 1499 .of_match = rockchip_display_ids, 1500 .bind = rockchip_display_bind, 1501 .probe = rockchip_display_probe, 1502 }; 1503 1504 static int do_rockchip_logo_show(cmd_tbl_t *cmdtp, int flag, int argc, 1505 char *const argv[]) 1506 { 1507 if (argc != 1) 1508 return CMD_RET_USAGE; 1509 1510 rockchip_show_logo(); 1511 1512 return 0; 1513 } 1514 1515 static int do_rockchip_show_bmp(cmd_tbl_t *cmdtp, int flag, int argc, 1516 char *const argv[]) 1517 { 1518 if (argc != 2) 1519 return CMD_RET_USAGE; 1520 1521 rockchip_show_bmp(argv[1]); 1522 1523 return 0; 1524 } 1525 1526 U_BOOT_CMD( 1527 rockchip_show_logo, 1, 1, do_rockchip_logo_show, 1528 "load and display log from resource partition", 1529 NULL 1530 ); 1531 1532 U_BOOT_CMD( 1533 rockchip_show_bmp, 2, 1, do_rockchip_show_bmp, 1534 "load and display bmp from resource partition", 1535 " <bmp_name>" 1536 ); 1537