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