1 /* 2 * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <asm/unaligned.h> 8 #include <config.h> 9 #include <common.h> 10 #include <errno.h> 11 #include <libfdt.h> 12 #include <fdtdec.h> 13 #include <fdt_support.h> 14 #include <linux/list.h> 15 #include <linux/compat.h> 16 #include <linux/media-bus-format.h> 17 #include <malloc.h> 18 #include <video.h> 19 #include <video_rockchip.h> 20 #include <dm/device.h> 21 #include <dm/uclass-internal.h> 22 #include <asm/arch-rockchip/resource_img.h> 23 24 #include "bmp_helper.h" 25 #include "rockchip_display.h" 26 #include "rockchip_crtc.h" 27 #include "rockchip_connector.h" 28 #include "rockchip_phy.h" 29 #include "rockchip_panel.h" 30 #include <dm.h> 31 #include <dm/of_access.h> 32 #include <dm/ofnode.h> 33 34 #define RK_BLK_SIZE 512 35 36 DECLARE_GLOBAL_DATA_PTR; 37 static LIST_HEAD(rockchip_display_list); 38 static LIST_HEAD(logo_cache_list); 39 40 static unsigned long memory_start; 41 static unsigned long memory_end; 42 43 static void init_display_buffer(ulong base) 44 { 45 memory_start = base + DRM_ROCKCHIP_FB_SIZE; 46 memory_end = memory_start; 47 } 48 49 static void *get_display_buffer(int size) 50 { 51 unsigned long roundup_memory = roundup(memory_end, PAGE_SIZE); 52 void *buf; 53 54 if (roundup_memory + size > memory_start + MEMORY_POOL_SIZE) { 55 printf("failed to alloc %dbyte memory to display\n", size); 56 return NULL; 57 } 58 buf = (void *)roundup_memory; 59 60 memory_end = roundup_memory + size; 61 62 return buf; 63 } 64 65 #if 0 66 static unsigned long get_display_size(void) 67 { 68 return memory_end - memory_start; 69 } 70 #endif 71 72 static bool can_direct_logo(int bpp) 73 { 74 return bpp == 24 || bpp == 32; 75 } 76 77 78 static struct udevice *get_panel_device(struct display_state *state, ofnode conn_node) 79 { 80 struct panel_state *panel_state = &state->panel_state; 81 struct udevice *dev; 82 struct connector_state *conn_state = &state->conn_state; 83 ofnode node, ports_node, port_node; 84 struct device_node *port, *panel, *ep; 85 int ph; 86 int ret; 87 88 node = dev_read_subnode(conn_state->dev, "panel"); 89 if (ofnode_valid(node) && 90 of_device_is_available(ofnode_to_np(node))){ 91 ret = uclass_get_device_by_ofnode(UCLASS_PANEL, node, &dev); 92 if(!ret) { 93 printf("%s get panel dev\n", __func__); 94 panel_state->node = node; 95 return dev; 96 } 97 } 98 99 /* TODO: this path not tested */ 100 ports_node = dev_read_subnode(conn_state->dev, "ports"); 101 if (!ofnode_valid(ports_node)) 102 return NULL; 103 104 ofnode_for_each_subnode(port_node, ports_node) { 105 ofnode_for_each_subnode(node, port_node) { 106 ph = ofnode_read_u32_default(node, "remote-endpoint", -1); 107 if (!ph) 108 continue; 109 ep = of_find_node_by_phandle(ph); 110 if (!ofnode_valid(np_to_ofnode(ep))) { 111 printf("Warn: can't find endpoint from phdl\n"); 112 continue; 113 } 114 port = of_get_parent(ep); 115 if (!ofnode_valid(np_to_ofnode(port))) { 116 printf("Warn: can't find port node\n"); 117 continue; 118 } 119 panel = of_get_parent(port); 120 if (!ofnode_valid(np_to_ofnode(panel))) { 121 printf("Warn: can't find panel node\n"); 122 continue; 123 } 124 ret = uclass_get_device_by_ofnode(UCLASS_PANEL, 125 np_to_ofnode(panel), 126 &dev); 127 if (ret) { 128 printf("Warn: can't find panel drv %d\n", ret); 129 continue; 130 } 131 panel_state->node = np_to_ofnode(panel); 132 return dev; 133 } 134 } 135 136 return NULL; 137 } 138 139 static int connector_phy_init(struct display_state *state) 140 { 141 struct connector_state *conn_state = &state->conn_state; 142 const struct rockchip_phy *phy; 143 struct udevice *dev; 144 int ret; 145 146 ret = uclass_get_device_by_phandle(UCLASS_PHY, conn_state->dev, "phys", 147 &dev); 148 if (ret) { 149 printf("Warn: can't find phy driver\n"); 150 return 0; 151 } 152 phy = (const struct rockchip_phy *)dev_get_driver_data(dev); 153 if (!phy) { 154 printf("failed to find phy driver\n"); 155 return 0; 156 } 157 158 conn_state->phy_dev = dev; 159 conn_state->phy_node = dev->node; 160 161 if (!phy->funcs || !phy->funcs->init || 162 phy->funcs->init(state)) { 163 printf("failed to init phy driver\n"); 164 return -EINVAL; 165 } 166 167 conn_state->phy = phy; 168 return 0; 169 } 170 171 static int connector_panel_init(struct display_state *state) 172 { 173 struct connector_state *conn_state = &state->conn_state; 174 struct panel_state *panel_state = &state->panel_state; 175 struct udevice *dev; 176 ofnode conn_node = conn_state->node; 177 const struct rockchip_panel *panel; 178 ofnode dsp_lut_node; 179 int ret, len; 180 181 dm_scan_fdt_dev(conn_state->dev); 182 183 dev = get_panel_device(state, conn_node); 184 if (!dev) { 185 return 0; 186 } 187 188 panel = (const struct rockchip_panel *)dev_get_driver_data(dev); 189 if (!panel) { 190 printf("failed to find panel driver\n"); 191 return 0; 192 } 193 194 panel_state->dev = dev; 195 panel_state->panel = panel; 196 197 ret = rockchip_panel_init(state); 198 if (ret) { 199 printf("failed to init panel driver\n"); 200 return ret; 201 } 202 dsp_lut_node = dev_read_subnode(dev, "dsp-lut"); 203 if (!ofnode_valid(dsp_lut_node)) { 204 printf("%s can not find dsp-lut node\n", __func__); 205 } 206 ofnode_get_property(dsp_lut_node, "gamma-lut", &len); 207 if (len > 0) { 208 conn_state->gamma.size = len / sizeof(u32); 209 conn_state->gamma.lut = malloc(len); 210 if (!conn_state->gamma.lut) { 211 printf("malloc gamma lut failed\n"); 212 return -ENOMEM; 213 } 214 ret = ofnode_read_u32_array(dsp_lut_node, "gamma-lut", 215 conn_state->gamma.lut, 216 conn_state->gamma.size); 217 if (ret) { 218 printf("Cannot decode gamma_lut\n"); 219 conn_state->gamma.lut = NULL; 220 return -EINVAL; 221 } 222 panel_state->dsp_lut_node = dsp_lut_node; 223 } 224 225 return 0; 226 } 227 228 int drm_mode_vrefresh(const struct drm_display_mode *mode) 229 { 230 int refresh = 0; 231 unsigned int calc_val; 232 233 if (mode->vrefresh > 0) { 234 refresh = mode->vrefresh; 235 } else if (mode->htotal > 0 && mode->vtotal > 0) { 236 int vtotal; 237 238 vtotal = mode->vtotal; 239 /* work out vrefresh the value will be x1000 */ 240 calc_val = (mode->clock * 1000); 241 calc_val /= mode->htotal; 242 refresh = (calc_val + vtotal / 2) / vtotal; 243 244 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 245 refresh *= 2; 246 if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 247 refresh /= 2; 248 if (mode->vscan > 1) 249 refresh /= mode->vscan; 250 } 251 return refresh; 252 } 253 254 static int display_get_timing_from_dts(struct panel_state *panel_state, 255 struct drm_display_mode *mode) 256 { 257 int phandle; 258 int hactive, vactive, pixelclock; 259 int hfront_porch, hback_porch, hsync_len; 260 int vfront_porch, vback_porch, vsync_len; 261 int val, flags = 0; 262 ofnode timing, native_mode; 263 264 timing = dev_read_subnode(panel_state->dev, "display-timings"); 265 if (!ofnode_valid(timing)) 266 return -ENODEV; 267 268 native_mode = ofnode_find_subnode(timing, "timing"); 269 if (!ofnode_valid(native_mode)) { 270 phandle = ofnode_read_u32_default(timing, "native-mode", -1); 271 native_mode = np_to_ofnode(of_find_node_by_phandle(phandle)); 272 if (!ofnode_valid(native_mode)) { 273 printf("failed to get display timings from DT\n"); 274 return -ENXIO; 275 } 276 } 277 278 #define FDT_GET_INT(val, name) \ 279 val = ofnode_read_s32_default(native_mode, name, -1); \ 280 if (val < 0) { \ 281 printf("Can't get %s\n", name); \ 282 return -ENXIO; \ 283 } 284 285 FDT_GET_INT(hactive, "hactive"); 286 FDT_GET_INT(vactive, "vactive"); 287 FDT_GET_INT(pixelclock, "clock-frequency"); 288 FDT_GET_INT(hsync_len, "hsync-len"); 289 FDT_GET_INT(hfront_porch, "hfront-porch"); 290 FDT_GET_INT(hback_porch, "hback-porch"); 291 FDT_GET_INT(vsync_len, "vsync-len"); 292 FDT_GET_INT(vfront_porch, "vfront-porch"); 293 FDT_GET_INT(vback_porch, "vback-porch"); 294 FDT_GET_INT(val, "hsync-active"); 295 flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; 296 FDT_GET_INT(val, "vsync-active"); 297 flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; 298 299 mode->hdisplay = hactive; 300 mode->hsync_start = mode->hdisplay + hfront_porch; 301 mode->hsync_end = mode->hsync_start + hsync_len; 302 mode->htotal = mode->hsync_end + hback_porch; 303 304 mode->vdisplay = vactive; 305 mode->vsync_start = mode->vdisplay + vfront_porch; 306 mode->vsync_end = mode->vsync_start + vsync_len; 307 mode->vtotal = mode->vsync_end + vback_porch; 308 309 mode->clock = pixelclock / 1000; 310 mode->flags = flags; 311 312 return 0; 313 } 314 315 static int display_get_timing(struct display_state *state) 316 { 317 struct connector_state *conn_state = &state->conn_state; 318 const struct rockchip_connector *conn = conn_state->connector; 319 const struct rockchip_connector_funcs *conn_funcs = conn->funcs; 320 struct drm_display_mode *mode = &conn_state->mode; 321 const struct drm_display_mode *m; 322 struct panel_state *panel_state = &state->panel_state; 323 ofnode panel = panel_state->node; 324 325 if (ofnode_valid(panel) && !display_get_timing_from_dts(panel_state, mode)) { 326 printf("Using display timing dts\n"); 327 goto done; 328 } 329 330 m = rockchip_get_display_mode_from_panel(state); 331 if (m) { 332 printf("Using display timing from compatible panel driver\n"); 333 memcpy(mode, m, sizeof(*m)); 334 goto done; 335 } 336 337 rockchip_panel_prepare(state); 338 339 if (conn_funcs->get_edid && !conn_funcs->get_edid(state)) { 340 int panel_bits_per_colourp; 341 342 if (!edid_get_drm_mode((void *)&conn_state->edid, 343 sizeof(conn_state->edid), mode, 344 &panel_bits_per_colourp)) { 345 printf("Using display timing from edid\n"); 346 edid_print_info((void *)&conn_state->edid); 347 goto done; 348 } 349 } 350 351 printf("failed to find display timing\n"); 352 return -ENODEV; 353 done: 354 printf("Detailed mode clock %u kHz, flags[%x]\n" 355 " H: %04d %04d %04d %04d\n" 356 " V: %04d %04d %04d %04d\n" 357 "bus_format: %x\n", 358 mode->clock, mode->flags, 359 mode->hdisplay, mode->hsync_start, 360 mode->hsync_end, mode->htotal, 361 mode->vdisplay, mode->vsync_start, 362 mode->vsync_end, mode->vtotal, 363 conn_state->bus_format); 364 365 return 0; 366 } 367 368 static int display_init(struct display_state *state) 369 { 370 struct connector_state *conn_state = &state->conn_state; 371 const struct rockchip_connector *conn = conn_state->connector; 372 const struct rockchip_connector_funcs *conn_funcs = conn->funcs; 373 struct crtc_state *crtc_state = &state->crtc_state; 374 const struct rockchip_crtc *crtc = crtc_state->crtc; 375 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 376 int ret = 0; 377 378 if (state->is_init) 379 return 0; 380 381 if (!conn_funcs || !crtc_funcs) { 382 printf("failed to find connector or crtc functions\n"); 383 return -ENXIO; 384 } 385 386 if (conn_funcs->init) { 387 ret = conn_funcs->init(state); 388 if (ret) 389 goto deinit; 390 } 391 /* 392 * support hotplug, but not connect; 393 */ 394 if (conn_funcs->detect) { 395 ret = conn_funcs->detect(state); 396 if (!ret) 397 goto deinit; 398 } 399 400 if (conn_funcs->get_timing) { 401 ret = conn_funcs->get_timing(state); 402 if (ret) 403 goto deinit; 404 } else { 405 ret = display_get_timing(state); 406 if (ret) 407 goto deinit; 408 } 409 410 if (crtc_funcs->init) { 411 ret = crtc_funcs->init(state); 412 if (ret) 413 goto deinit; 414 } 415 416 state->is_init = 1; 417 418 return 0; 419 420 deinit: 421 if (conn_funcs->deinit) 422 conn_funcs->deinit(state); 423 return ret; 424 } 425 426 static int display_set_plane(struct display_state *state) 427 { 428 struct crtc_state *crtc_state = &state->crtc_state; 429 const struct rockchip_crtc *crtc = crtc_state->crtc; 430 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 431 int ret; 432 433 if (!state->is_init) 434 return -EINVAL; 435 436 if (crtc_funcs->set_plane) { 437 ret = crtc_funcs->set_plane(state); 438 if (ret) 439 return ret; 440 } 441 442 return 0; 443 } 444 445 static int display_enable(struct display_state *state) 446 { 447 struct connector_state *conn_state = &state->conn_state; 448 const struct rockchip_connector *conn = conn_state->connector; 449 const struct rockchip_connector_funcs *conn_funcs = conn->funcs; 450 struct crtc_state *crtc_state = &state->crtc_state; 451 const struct rockchip_crtc *crtc = crtc_state->crtc; 452 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 453 int ret = 0; 454 455 display_init(state); 456 457 if (!state->is_init) 458 return -EINVAL; 459 460 if (state->is_enable) 461 return 0; 462 463 if (crtc_funcs->prepare) { 464 ret = crtc_funcs->prepare(state); 465 if (ret) 466 return ret; 467 } 468 469 if (conn_funcs->prepare) { 470 ret = conn_funcs->prepare(state); 471 if (ret) 472 goto unprepare_crtc; 473 } 474 475 rockchip_panel_prepare(state); 476 477 if (crtc_funcs->enable) { 478 ret = crtc_funcs->enable(state); 479 if (ret) 480 goto unprepare_conn; 481 } 482 483 if (conn_funcs->enable) { 484 ret = conn_funcs->enable(state); 485 if (ret) 486 goto disable_crtc; 487 } 488 489 rockchip_panel_enable(state); 490 491 state->is_enable = true; 492 493 return 0; 494 unprepare_crtc: 495 if (crtc_funcs->unprepare) 496 crtc_funcs->unprepare(state); 497 unprepare_conn: 498 if (conn_funcs->unprepare) 499 conn_funcs->unprepare(state); 500 disable_crtc: 501 if (crtc_funcs->disable) 502 crtc_funcs->disable(state); 503 return ret; 504 } 505 506 static int display_disable(struct display_state *state) 507 { 508 struct connector_state *conn_state = &state->conn_state; 509 const struct rockchip_connector *conn = conn_state->connector; 510 const struct rockchip_connector_funcs *conn_funcs = conn->funcs; 511 struct crtc_state *crtc_state = &state->crtc_state; 512 const struct rockchip_crtc *crtc = crtc_state->crtc; 513 const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs; 514 515 if (!state->is_init) 516 return 0; 517 518 if (!state->is_enable) 519 return 0; 520 521 rockchip_panel_disable(state); 522 523 if (crtc_funcs->disable) 524 crtc_funcs->disable(state); 525 526 if (conn_funcs->disable) 527 conn_funcs->disable(state); 528 529 rockchip_panel_unprepare(state); 530 531 if (conn_funcs->unprepare) 532 conn_funcs->unprepare(state); 533 534 state->is_enable = 0; 535 state->is_init = 0; 536 537 return 0; 538 } 539 540 static int display_logo(struct display_state *state) 541 { 542 struct crtc_state *crtc_state = &state->crtc_state; 543 struct connector_state *conn_state = &state->conn_state; 544 struct logo_info *logo = &state->logo; 545 int hdisplay, vdisplay; 546 547 display_init(state); 548 if (!state->is_init) 549 return -ENODEV; 550 551 switch (logo->bpp) { 552 case 16: 553 crtc_state->format = ROCKCHIP_FMT_RGB565; 554 break; 555 case 24: 556 crtc_state->format = ROCKCHIP_FMT_RGB888; 557 break; 558 case 32: 559 crtc_state->format = ROCKCHIP_FMT_ARGB8888; 560 break; 561 default: 562 printf("can't support bmp bits[%d]\n", logo->bpp); 563 return -EINVAL; 564 } 565 crtc_state->rb_swap = logo->bpp != 32; 566 hdisplay = conn_state->mode.hdisplay; 567 vdisplay = conn_state->mode.vdisplay; 568 crtc_state->src_w = logo->width; 569 crtc_state->src_h = logo->height; 570 crtc_state->src_x = 0; 571 crtc_state->src_y = 0; 572 crtc_state->ymirror = logo->ymirror; 573 574 crtc_state->dma_addr = (u32)(unsigned long)logo->mem + logo->offset; 575 crtc_state->xvir = ALIGN(crtc_state->src_w * logo->bpp, 32) >> 5; 576 577 if (logo->mode == ROCKCHIP_DISPLAY_FULLSCREEN) { 578 crtc_state->crtc_x = 0; 579 crtc_state->crtc_y = 0; 580 crtc_state->crtc_w = hdisplay; 581 crtc_state->crtc_h = vdisplay; 582 } else { 583 if (crtc_state->src_w >= hdisplay) { 584 crtc_state->crtc_x = 0; 585 crtc_state->crtc_w = hdisplay; 586 } else { 587 crtc_state->crtc_x = (hdisplay - crtc_state->src_w) / 2; 588 crtc_state->crtc_w = crtc_state->src_w; 589 } 590 591 if (crtc_state->src_h >= vdisplay) { 592 crtc_state->crtc_y = 0; 593 crtc_state->crtc_h = vdisplay; 594 } else { 595 crtc_state->crtc_y = (vdisplay - crtc_state->src_h) / 2; 596 crtc_state->crtc_h = crtc_state->src_h; 597 } 598 } 599 600 display_set_plane(state); 601 display_enable(state); 602 603 return 0; 604 } 605 606 static int get_crtc_id(ofnode connect) 607 { 608 int phandle; 609 struct device_node *remote; 610 int val; 611 612 phandle = ofnode_read_u32_default(connect, "remote-endpoint", -1); 613 if (phandle < 0) 614 goto err; 615 remote = of_find_node_by_phandle(phandle); 616 val = ofnode_read_u32_default(np_to_ofnode(remote), "reg", -1); 617 if (val < 0) 618 goto err; 619 620 return val; 621 err: 622 printf("Can't get crtc id, default set to id = 0\n"); 623 return 0; 624 } 625 626 struct rockchip_logo_cache *find_or_alloc_logo_cache(const char *bmp) 627 { 628 struct rockchip_logo_cache *tmp, *logo_cache = NULL; 629 630 list_for_each_entry(tmp, &logo_cache_list, head) { 631 if (!strcmp(tmp->name, bmp)) { 632 logo_cache = tmp; 633 break; 634 } 635 } 636 637 if (!logo_cache) { 638 logo_cache = malloc(sizeof(*logo_cache)); 639 if (!logo_cache) { 640 printf("failed to alloc memory for logo cache\n"); 641 return NULL; 642 } 643 memset(logo_cache, 0, sizeof(*logo_cache)); 644 strcpy(logo_cache->name, bmp); 645 INIT_LIST_HEAD(&logo_cache->head); 646 list_add_tail(&logo_cache->head, &logo_cache_list); 647 } 648 649 return logo_cache; 650 } 651 652 static int load_bmp_logo(struct logo_info *logo, const char *bmp_name) 653 { 654 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE 655 struct rockchip_logo_cache *logo_cache; 656 struct bmp_header *header; 657 void *dst = NULL, *pdst; 658 int size, len; 659 int ret = 0; 660 661 if (!logo || !bmp_name) 662 return -EINVAL; 663 logo_cache = find_or_alloc_logo_cache(bmp_name); 664 if (!logo_cache) 665 return -ENOMEM; 666 667 if (logo_cache->logo.mem) { 668 memcpy(logo, &logo_cache->logo, sizeof(*logo)); 669 return 0; 670 } 671 672 header = malloc(RK_BLK_SIZE); 673 if (!header) 674 return -ENOMEM; 675 676 len = rockchip_read_resource_file(header, bmp_name, 0, RK_BLK_SIZE); 677 if (len != RK_BLK_SIZE) { 678 ret = -EINVAL; 679 goto free_header; 680 } 681 682 logo->bpp = get_unaligned_le16(&header->bit_count); 683 logo->width = get_unaligned_le32(&header->width); 684 logo->height = get_unaligned_le32(&header->height); 685 size = get_unaligned_le32(&header->file_size); 686 if (!can_direct_logo(logo->bpp)) { 687 if (size > MEMORY_POOL_SIZE) { 688 printf("failed to use boot buf as temp bmp buffer\n"); 689 ret = -ENOMEM; 690 goto free_header; 691 } 692 pdst = get_display_buffer(size); 693 694 } else { 695 pdst = get_display_buffer(size); 696 dst = pdst; 697 } 698 699 len = rockchip_read_resource_file(pdst, bmp_name, 0, size); 700 if (len != size) { 701 printf("failed to load bmp %s\n", bmp_name); 702 ret = -ENOENT; 703 goto free_header; 704 } 705 706 if (!can_direct_logo(logo->bpp)) { 707 int dst_size; 708 /* 709 * TODO: force use 16bpp if bpp less than 16; 710 */ 711 logo->bpp = (logo->bpp <= 16) ? 16 : logo->bpp; 712 dst_size = logo->width * logo->height * logo->bpp >> 3; 713 714 dst = get_display_buffer(dst_size); 715 if (!dst) { 716 ret = -ENOMEM; 717 goto free_header; 718 } 719 if (bmpdecoder(pdst, dst, logo->bpp)) { 720 printf("failed to decode bmp %s\n", bmp_name); 721 ret = -EINVAL; 722 goto free_header; 723 } 724 flush_dcache_range((ulong)dst, 725 ALIGN((ulong)dst + dst_size, 726 CONFIG_SYS_CACHELINE_SIZE)); 727 728 logo->offset = 0; 729 logo->ymirror = 0; 730 } else { 731 logo->offset = get_unaligned_le32(&header->data_offset); 732 logo->ymirror = 1; 733 } 734 logo->mem = dst; 735 736 memcpy(&logo_cache->logo, logo, sizeof(*logo)); 737 738 free_header: 739 740 free(header); 741 742 return ret; 743 #else 744 return -EINVAL; 745 #endif 746 } 747 748 void rockchip_show_fbbase(ulong fbbase) 749 { 750 struct display_state *s; 751 752 list_for_each_entry(s, &rockchip_display_list, head) { 753 s->logo.mode = ROCKCHIP_DISPLAY_FULLSCREEN; 754 s->logo.mem = (char *)fbbase; 755 s->logo.width = DRM_ROCKCHIP_FB_WIDTH; 756 s->logo.height = DRM_ROCKCHIP_FB_HEIGHT; 757 s->logo.bpp = 32; 758 s->logo.ymirror = 0; 759 760 display_logo(s); 761 } 762 } 763 764 void rockchip_show_bmp(const char *bmp) 765 { 766 struct display_state *s; 767 768 if (!bmp) { 769 list_for_each_entry(s, &rockchip_display_list, head) 770 display_disable(s); 771 return; 772 } 773 774 list_for_each_entry(s, &rockchip_display_list, head) { 775 s->logo.mode = s->charge_logo_mode; 776 if (load_bmp_logo(&s->logo, bmp)) 777 continue; 778 display_logo(s); 779 } 780 } 781 782 void rockchip_show_logo(void) 783 { 784 struct display_state *s; 785 786 list_for_each_entry(s, &rockchip_display_list, head) { 787 s->logo.mode = s->logo_mode; 788 if (load_bmp_logo(&s->logo, s->ulogo_name)) 789 printf("failed to display uboot logo\n"); 790 else 791 display_logo(s); 792 if (load_bmp_logo(&s->logo, s->klogo_name)) 793 printf("failed to display kernel logo\n"); 794 } 795 } 796 797 static int rockchip_display_probe(struct udevice *dev) 798 { 799 struct video_priv *uc_priv = dev_get_uclass_priv(dev); 800 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 801 const void *blob = gd->fdt_blob; 802 int phandle; 803 struct udevice *crtc_dev, *conn_dev; 804 const struct rockchip_crtc *crtc; 805 const struct rockchip_connector *conn; 806 struct display_state *s; 807 const char *name; 808 int ret; 809 ofnode node, route_node; 810 struct device_node *port_node, *vop_node, *ep_node; 811 struct device_node *cnt_node, *p; 812 813 /* Before relocation we don't need to do anything */ 814 if (!(gd->flags & GD_FLG_RELOC)) 815 return 0; 816 init_display_buffer(plat->base); 817 818 route_node = dev_read_subnode(dev, "route"); 819 if (!ofnode_valid(route_node)) 820 return -ENODEV; 821 822 ofnode_for_each_subnode(node, route_node){ 823 phandle = ofnode_read_u32_default(node, "connect", -1); 824 if (phandle < 0) { 825 printf("Warn: can't find connect node's handle\n"); 826 continue; 827 } 828 ep_node = of_find_node_by_phandle(phandle); 829 if (!ofnode_valid(np_to_ofnode(ep_node))) { 830 printf("Warn: can't find endpoint node from phandle\n"); 831 continue; 832 } 833 port_node = of_get_parent(ep_node); 834 if (!ofnode_valid(np_to_ofnode(port_node))) { 835 printf("Warn: can't find port node from phandle\n"); 836 continue; 837 } 838 vop_node = of_get_parent(port_node); 839 if (!ofnode_valid(np_to_ofnode(vop_node))) { 840 printf("Warn: can't find crtc node from phandle\n"); 841 continue; 842 } 843 ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_CRTC, 844 np_to_ofnode(vop_node), 845 &crtc_dev); 846 if (ret) { 847 printf("Warn: can't find crtc driver %d\n", ret); 848 continue; 849 } 850 crtc = (const struct rockchip_crtc *)dev_get_driver_data(crtc_dev); 851 852 phandle = ofnode_read_u32_default(np_to_ofnode(ep_node), 853 "remote-endpoint", -1); 854 cnt_node = of_find_node_by_phandle(phandle); 855 if (phandle < 0) { 856 printf("Warn: can't find remote-endpoint's handle\n"); 857 continue; 858 } 859 while (cnt_node->parent){ 860 p = of_get_parent(cnt_node); 861 if (!strcmp(p->full_name, "/")) 862 break; 863 cnt_node = p; 864 } 865 if (!of_device_is_available(cnt_node)) 866 continue; 867 ret = uclass_get_device_by_ofnode(UCLASS_DISPLAY, 868 np_to_ofnode(cnt_node), 869 &conn_dev); 870 if (ret) { 871 printf("Warn: can't find connect driver\n"); 872 continue; 873 } 874 conn = (const struct rockchip_connector *)dev_get_driver_data(conn_dev); 875 876 s = malloc(sizeof(*s)); 877 if (!s) 878 continue; 879 880 memset(s, 0, sizeof(*s)); 881 882 INIT_LIST_HEAD(&s->head); 883 ret = ofnode_read_string_index(node, "logo,uboot", 0, &s->ulogo_name); 884 ret = ofnode_read_string_index(node, "logo,kernel", 0, &s->klogo_name); 885 ret = ofnode_read_string_index(node, "logo,mode", 0, &name); 886 if (!strcmp(name, "fullscreen")) 887 s->logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN; 888 else 889 s->logo_mode = ROCKCHIP_DISPLAY_CENTER; 890 ret = ofnode_read_string_index(node, "charge_logo,mode", 0, &name); 891 if (!strcmp(name, "fullscreen")) 892 s->charge_logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN; 893 else 894 s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER; 895 896 s->blob = blob; 897 s->conn_state.node = np_to_ofnode(cnt_node); 898 s->conn_state.dev = conn_dev; 899 s->conn_state.connector = conn; 900 s->crtc_state.node = np_to_ofnode(vop_node); 901 s->crtc_state.dev = crtc_dev; 902 s->crtc_state.crtc = crtc; 903 s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node)); 904 s->node = node; 905 906 if (connector_panel_init(s)) { 907 printf("Warn: Failed to init panel drivers\n"); 908 free(s); 909 continue; 910 } 911 912 if (connector_phy_init(s)) { 913 printf("Warn: Failed to init phy drivers\n"); 914 free(s); 915 continue; 916 } 917 list_add_tail(&s->head, &rockchip_display_list); 918 919 } 920 921 if (list_empty(&rockchip_display_list)) { 922 printf("Failed to found available display route\n"); 923 return -ENODEV; 924 } 925 926 uc_priv->xsize = DRM_ROCKCHIP_FB_WIDTH; 927 uc_priv->ysize = DRM_ROCKCHIP_FB_HEIGHT; 928 uc_priv->bpix = VIDEO_BPP32; 929 930 #ifdef CONFIG_DRM_ROCKCHIP_VIDEO_FRAMEBUFFER 931 rockchip_show_fbbase(plat->base); 932 video_set_flush_dcache(dev, true); 933 #endif 934 935 return 0; 936 } 937 938 #if 0 939 void rockchip_display_fixup(void *blob) 940 { 941 const struct rockchip_connector_funcs *conn_funcs; 942 const struct rockchip_crtc_funcs *crtc_funcs; 943 const struct rockchip_connector *conn; 944 const struct rockchip_crtc *crtc; 945 struct display_state *s; 946 u32 offset; 947 int node; 948 char path[100]; 949 int ret; 950 951 if (!get_display_size()) 952 return; 953 954 node = fdt_update_reserved_memory(blob, "rockchip,drm-logo", 955 (u64)memory_start, 956 (u64)get_display_size()); 957 if (node < 0) { 958 printf("failed to add drm-loader-logo memory\n"); 959 return; 960 } 961 962 list_for_each_entry(s, &rockchip_display_list, head) { 963 conn = s->conn_state.connector; 964 if (!conn) 965 continue; 966 conn_funcs = conn->funcs; 967 if (!conn_funcs) { 968 printf("failed to get exist connector\n"); 969 continue; 970 } 971 972 crtc = s->crtc_state.crtc; 973 if (!crtc) 974 continue; 975 976 crtc_funcs = crtc->funcs; 977 if (!crtc_funcs) { 978 printf("failed to get exist crtc\n"); 979 continue; 980 } 981 982 if (crtc_funcs->fixup_dts) 983 crtc_funcs->fixup_dts(s, blob); 984 985 if (conn_funcs->fixup_dts) 986 conn_funcs->fixup_dts(s, blob); 987 988 ret = fdt_get_path(s->blob, s->node, path, sizeof(path)); 989 if (ret < 0) { 990 printf("failed to get route path[%s], ret=%d\n", 991 path, ret); 992 continue; 993 } 994 995 #define FDT_SET_U32(name, val) \ 996 do_fixup_by_path_u32(blob, path, name, val, 1); 997 998 offset = s->logo.offset + s->logo.mem - memory_start; 999 FDT_SET_U32("logo,offset", offset); 1000 FDT_SET_U32("logo,width", s->logo.width); 1001 FDT_SET_U32("logo,height", s->logo.height); 1002 FDT_SET_U32("logo,bpp", s->logo.bpp); 1003 FDT_SET_U32("logo,ymirror", s->logo.ymirror); 1004 FDT_SET_U32("video,hdisplay", s->conn_state.mode.hdisplay); 1005 FDT_SET_U32("video,vdisplay", s->conn_state.mode.vdisplay); 1006 FDT_SET_U32("video,vrefresh", 1007 drm_mode_vrefresh(&s->conn_state.mode)); 1008 #undef FDT_SET_U32 1009 } 1010 } 1011 #endif 1012 1013 int rockchip_display_bind(struct udevice *dev) 1014 { 1015 struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); 1016 1017 plat->size = DRM_ROCKCHIP_FB_SIZE + MEMORY_POOL_SIZE; 1018 1019 return 0; 1020 } 1021 1022 static const struct udevice_id rockchip_display_ids[] = { 1023 { .compatible = "rockchip,display-subsystem" }, 1024 { } 1025 }; 1026 1027 U_BOOT_DRIVER(rockchip_display) = { 1028 .name = "rockchip_display", 1029 .id = UCLASS_VIDEO, 1030 .of_match = rockchip_display_ids, 1031 .bind = rockchip_display_bind, 1032 .probe = rockchip_display_probe, 1033 }; 1034 1035 static int do_rockchip_logo_show(cmd_tbl_t *cmdtp, int flag, int argc, 1036 char *const argv[]) 1037 { 1038 if (argc != 1) 1039 return CMD_RET_USAGE; 1040 1041 rockchip_show_logo(); 1042 1043 return 0; 1044 } 1045 1046 static int do_rockchip_show_bmp(cmd_tbl_t *cmdtp, int flag, int argc, 1047 char *const argv[]) 1048 { 1049 if (argc != 2) 1050 return CMD_RET_USAGE; 1051 1052 rockchip_show_bmp(argv[1]); 1053 1054 return 0; 1055 } 1056 1057 U_BOOT_CMD( 1058 rockchip_show_logo, 1, 1, do_rockchip_logo_show, 1059 "load and display log from resource partition", 1060 NULL 1061 ); 1062 1063 U_BOOT_CMD( 1064 rockchip_show_bmp, 2, 1, do_rockchip_show_bmp, 1065 "load and display bmp from resource partition", 1066 " <bmp_name>" 1067 ); 1068