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