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