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