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