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