| .. | .. |
|---|
| 7 | 7 | #include <common.h> |
|---|
| 8 | 8 | #include <boot_rkimg.h> |
|---|
| 9 | 9 | #include <asm/io.h> |
|---|
| 10 | +#include <asm/gpio.h> |
|---|
| 10 | 11 | #include <dm/of_access.h> |
|---|
| 11 | 12 | #include <dm/device.h> |
|---|
| 12 | 13 | #include <linux/dw_hdmi.h> |
|---|
| .. | .. |
|---|
| 35 | 36 | #define RK3328_GRF_SOC_CON2 0x0408 |
|---|
| 36 | 37 | #define RK3328_GRF_SOC_CON3 0x040c |
|---|
| 37 | 38 | #define RK3328_GRF_SOC_CON4 0x0410 |
|---|
| 39 | + |
|---|
| 40 | +#define RK3528_GPIO0A_IOMUX_SEL_H 0x4 |
|---|
| 41 | +#define RK3528_GPIO0A_PULL 0x200 |
|---|
| 42 | +#define RK3528_DDC_PULL (0xf00 << 16) |
|---|
| 43 | +#define RK3528_VO_GRF_HDMI_MASK 0x60014 |
|---|
| 44 | +#define RK3528_HDMI_SNKDET_SEL ((BIT(6) << 16) | BIT(6)) |
|---|
| 45 | +#define RK3528_HDMI_SNKDET BIT(21) |
|---|
| 46 | +#define RK3528_HDMI_CECIN_MSK ((BIT(2) << 16) | BIT(2)) |
|---|
| 47 | +#define RK3528_HDMI_SDAIN_MSK ((BIT(1) << 16) | BIT(1)) |
|---|
| 48 | +#define RK3528_HDMI_SCLIN_MSK ((BIT(0) << 16) | BIT(0)) |
|---|
| 49 | + |
|---|
| 50 | +#define RK3528_GPIO_SWPORT_DR_L 0x0000 |
|---|
| 51 | +#define RK3528_GPIO0_A2_DR ((BIT(2) << 16) | BIT(2)) |
|---|
| 38 | 52 | |
|---|
| 39 | 53 | #define RK3568_GRF_VO_CON1 0x0364 |
|---|
| 40 | 54 | #define RK3568_HDMI_SDAIN_MSK ((1 << 15) | (1 << (15 + 16))) |
|---|
| .. | .. |
|---|
| 177 | 191 | } |
|---|
| 178 | 192 | }; |
|---|
| 179 | 193 | |
|---|
| 180 | | -static const struct dw_hdmi_phy_config rockchip_phy_config[] = { |
|---|
| 194 | +static struct dw_hdmi_phy_config rockchip_phy_config[] = { |
|---|
| 181 | 195 | /*pixelclk symbol term vlev*/ |
|---|
| 182 | 196 | { 74250000, 0x8009, 0x0004, 0x0272}, |
|---|
| 183 | 197 | { 165000000, 0x802b, 0x0004, 0x0209}, |
|---|
| .. | .. |
|---|
| 334 | 348 | enum dw_hdmi_devtype dev_type, |
|---|
| 335 | 349 | bool output_bus_format_rgb) |
|---|
| 336 | 350 | { |
|---|
| 337 | | - int ret, i, screen_size; |
|---|
| 338 | | - struct base_disp_info base_parameter; |
|---|
| 339 | 351 | struct base2_disp_info *base2_parameter = conn_state->disp_info; |
|---|
| 340 | 352 | const struct base_overscan *scan; |
|---|
| 341 | 353 | struct base_screen_info *screen_info = NULL; |
|---|
| 342 | 354 | struct base2_screen_info *screen_info2 = NULL; |
|---|
| 343 | 355 | int max_scan = 100; |
|---|
| 344 | 356 | int min_scan = 51; |
|---|
| 357 | +#ifdef CONFIG_SPL_BUILD |
|---|
| 358 | + int i, screen_size; |
|---|
| 359 | +#else |
|---|
| 360 | + int ret, i, screen_size; |
|---|
| 345 | 361 | int offset = 0; |
|---|
| 346 | 362 | bool found = false; |
|---|
| 347 | 363 | struct blk_desc *dev_desc; |
|---|
| 348 | 364 | disk_partition_t part_info; |
|---|
| 349 | 365 | char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN); |
|---|
| 366 | + struct base_disp_info base_parameter; |
|---|
| 367 | +#endif |
|---|
| 350 | 368 | |
|---|
| 351 | 369 | overscan->left_margin = max_scan; |
|---|
| 352 | 370 | overscan->right_margin = max_scan; |
|---|
| .. | .. |
|---|
| 358 | 376 | else |
|---|
| 359 | 377 | *bus_format = MEDIA_BUS_FMT_YUV8_1X24; |
|---|
| 360 | 378 | |
|---|
| 379 | +#ifdef CONFIG_SPL_BUILD |
|---|
| 380 | + scan = &base2_parameter->overscan_info; |
|---|
| 381 | + screen_size = sizeof(base2_parameter->screen_info) / |
|---|
| 382 | + sizeof(base2_parameter->screen_info[0]); |
|---|
| 383 | + |
|---|
| 384 | + for (i = 0; i < screen_size; i++) { |
|---|
| 385 | + if (base2_parameter->screen_info[i].type == |
|---|
| 386 | + DRM_MODE_CONNECTOR_HDMIA) { |
|---|
| 387 | + screen_info2 = |
|---|
| 388 | + &base2_parameter->screen_info[i]; |
|---|
| 389 | + break; |
|---|
| 390 | + } |
|---|
| 391 | + } |
|---|
| 392 | + screen_info = malloc(sizeof(*screen_info)); |
|---|
| 393 | + |
|---|
| 394 | + screen_info->type = screen_info2->type; |
|---|
| 395 | + screen_info->mode = screen_info2->resolution; |
|---|
| 396 | + screen_info->format = screen_info2->format; |
|---|
| 397 | + screen_info->depth = screen_info2->depthc; |
|---|
| 398 | + screen_info->feature = screen_info2->feature; |
|---|
| 399 | +#else |
|---|
| 361 | 400 | if (!base2_parameter) { |
|---|
| 362 | 401 | dev_desc = rockchip_get_bootdev(); |
|---|
| 363 | 402 | if (!dev_desc) { |
|---|
| .. | .. |
|---|
| 422 | 461 | screen_info->depth = screen_info2->depthc; |
|---|
| 423 | 462 | screen_info->feature = screen_info2->feature; |
|---|
| 424 | 463 | } |
|---|
| 464 | +#endif |
|---|
| 425 | 465 | |
|---|
| 426 | 466 | if (scan->leftscale < min_scan && scan->leftscale > 0) |
|---|
| 427 | 467 | overscan->left_margin = min_scan; |
|---|
| .. | .. |
|---|
| 443 | 483 | else if (scan->bottomscale < max_scan && scan->bottomscale > 0) |
|---|
| 444 | 484 | overscan->bottom_margin = scan->bottomscale; |
|---|
| 445 | 485 | |
|---|
| 486 | +#ifndef CONFIG_SPL_BUILD |
|---|
| 446 | 487 | null_basep: |
|---|
| 488 | +#endif |
|---|
| 447 | 489 | |
|---|
| 448 | 490 | if (screen_info) |
|---|
| 449 | 491 | printf("base_parameter.mode:%dx%d\n", |
|---|
| .. | .. |
|---|
| 463 | 505 | writel(RK3328_IO_3V_DOMAIN, grf + RK3328_GRF_SOC_CON4); |
|---|
| 464 | 506 | } |
|---|
| 465 | 507 | |
|---|
| 466 | | -void dw_hdmi_set_iomux(void *grf, int dev_type) |
|---|
| 508 | +void dw_hdmi_set_iomux(void *grf, void *gpio_base, struct gpio_desc *hpd_gpiod, |
|---|
| 509 | + int dev_type) |
|---|
| 467 | 510 | { |
|---|
| 511 | + u32 val = 0; |
|---|
| 512 | + int i = 400; |
|---|
| 513 | +#ifdef CONFIG_SPL_BUILD |
|---|
| 514 | + void *gpio0_ioc = (void *)RK3528_GPIO0_IOC_BASE; |
|---|
| 515 | +#endif |
|---|
| 516 | + |
|---|
| 468 | 517 | switch (dev_type) { |
|---|
| 469 | 518 | case RK3328_HDMI: |
|---|
| 470 | 519 | writel(RK3328_IO_DDC_IN_MSK, grf + RK3328_GRF_SOC_CON2); |
|---|
| .. | .. |
|---|
| 473 | 522 | case RK3228_HDMI: |
|---|
| 474 | 523 | writel(RK3228_IO_3V_DOMAIN, grf + RK3228_GRF_SOC_CON6); |
|---|
| 475 | 524 | writel(RK3228_IO_DDC_IN_MSK, grf + RK3228_GRF_SOC_CON2); |
|---|
| 525 | + break; |
|---|
| 526 | + case RK3528_HDMI: |
|---|
| 527 | + writel(RK3528_HDMI_SDAIN_MSK | RK3528_HDMI_SCLIN_MSK | |
|---|
| 528 | + RK3528_HDMI_SNKDET_SEL, |
|---|
| 529 | + grf + RK3528_VO_GRF_HDMI_MASK); |
|---|
| 530 | + |
|---|
| 531 | +#ifdef CONFIG_SPL_BUILD |
|---|
| 532 | + val = (0x11 << 16) | 0x11; |
|---|
| 533 | + writel(val, gpio0_ioc + RK3528_GPIO0A_IOMUX_SEL_H); |
|---|
| 534 | + |
|---|
| 535 | + writel(RK3528_DDC_PULL, gpio0_ioc + RK3528_GPIO0A_PULL); |
|---|
| 536 | + |
|---|
| 537 | + /* gpio0_a2's input enable is controlled by gpio output data bit */ |
|---|
| 538 | + writel(RK3528_GPIO0_A2_DR, gpio_base + RK3528_GPIO_SWPORT_DR_L); |
|---|
| 539 | + |
|---|
| 540 | + while (i--) { |
|---|
| 541 | + val = readl(gpio_base + 0x70) & BIT(2); |
|---|
| 542 | + if (val) |
|---|
| 543 | + break; |
|---|
| 544 | + mdelay(5); |
|---|
| 545 | + } |
|---|
| 546 | +#else |
|---|
| 547 | + writel(val, grf + RK3528_VO_GRF_HDMI_MASK); |
|---|
| 548 | + |
|---|
| 549 | + /* gpio0_a2's input enable is controlled by gpio output data bit */ |
|---|
| 550 | + writel(RK3528_GPIO0_A2_DR, gpio_base + RK3528_GPIO_SWPORT_DR_L); |
|---|
| 551 | + |
|---|
| 552 | + if (dm_gpio_is_valid(hpd_gpiod)) { |
|---|
| 553 | + while (i--) { |
|---|
| 554 | + val = dm_gpio_get_value(hpd_gpiod); |
|---|
| 555 | + if (val) |
|---|
| 556 | + break; |
|---|
| 557 | + mdelay(5); |
|---|
| 558 | + } |
|---|
| 559 | + } |
|---|
| 560 | +#endif |
|---|
| 561 | + |
|---|
| 562 | + if (val) |
|---|
| 563 | + val = RK3528_HDMI_SNKDET | BIT(5); |
|---|
| 564 | + else |
|---|
| 565 | + val = RK3528_HDMI_SNKDET; |
|---|
| 566 | + writel(val, grf + RK3528_VO_GRF_HDMI_MASK); |
|---|
| 567 | + |
|---|
| 476 | 568 | break; |
|---|
| 477 | 569 | case RK3568_HDMI: |
|---|
| 478 | 570 | writel(RK3568_HDMI_SDAIN_MSK | RK3568_HDMI_SCLIN_MSK, |
|---|
| .. | .. |
|---|
| 544 | 636 | .dev_type = RK3399_HDMI, |
|---|
| 545 | 637 | }; |
|---|
| 546 | 638 | |
|---|
| 639 | +const struct dw_hdmi_plat_data rk3528_hdmi_drv_data = { |
|---|
| 640 | + .vop_sel_bit = 0, |
|---|
| 641 | + .grf_vop_sel_reg = 0, |
|---|
| 642 | + .phy_ops = &inno_dw_hdmi_phy_ops, |
|---|
| 643 | + .phy_name = "inno_dw_hdmi_phy2", |
|---|
| 644 | + .dev_type = RK3528_HDMI, |
|---|
| 645 | +}; |
|---|
| 646 | + |
|---|
| 547 | 647 | const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { |
|---|
| 548 | 648 | .vop_sel_bit = 0, |
|---|
| 549 | 649 | .grf_vop_sel_reg = 0, |
|---|
| .. | .. |
|---|
| 554 | 654 | .dev_type = RK3568_HDMI, |
|---|
| 555 | 655 | }; |
|---|
| 556 | 656 | |
|---|
| 657 | +#ifdef CONFIG_SPL_BUILD |
|---|
| 658 | +int rockchip_spl_dw_hdmi_probe(struct connector_state *conn_state) |
|---|
| 659 | +{ |
|---|
| 660 | + conn_state->connector = malloc(sizeof(struct rockchip_connector)); |
|---|
| 661 | + |
|---|
| 662 | + memset(conn_state->connector, 0, sizeof(*conn_state->connector)); |
|---|
| 663 | + rockchip_connector_bind(conn_state->connector, NULL, 0, &rockchip_dw_hdmi_funcs, |
|---|
| 664 | + (void *)&rk3528_hdmi_drv_data, |
|---|
| 665 | + DRM_MODE_CONNECTOR_HDMIA); |
|---|
| 666 | + |
|---|
| 667 | + return 0; |
|---|
| 668 | +} |
|---|
| 669 | +#else |
|---|
| 557 | 670 | static int rockchip_dw_hdmi_probe(struct udevice *dev) |
|---|
| 558 | 671 | { |
|---|
| 559 | 672 | int id; |
|---|
| .. | .. |
|---|
| 568 | 681 | |
|---|
| 569 | 682 | return 0; |
|---|
| 570 | 683 | } |
|---|
| 684 | +#endif |
|---|
| 571 | 685 | |
|---|
| 572 | 686 | static const struct udevice_id rockchip_dw_hdmi_ids[] = { |
|---|
| 573 | 687 | { |
|---|
| 688 | + .compatible = "rockchip,rk3528-dw-hdmi", |
|---|
| 689 | + .data = (ulong)&rk3528_hdmi_drv_data, |
|---|
| 690 | + }, { |
|---|
| 574 | 691 | .compatible = "rockchip,rk3568-dw-hdmi", |
|---|
| 575 | 692 | .data = (ulong)&rk3568_hdmi_drv_data, |
|---|
| 576 | 693 | }, { |
|---|
| .. | .. |
|---|
| 598 | 715 | .name = "rockchip_dw_hdmi", |
|---|
| 599 | 716 | .id = UCLASS_DISPLAY, |
|---|
| 600 | 717 | .of_match = rockchip_dw_hdmi_ids, |
|---|
| 718 | +#ifndef CONFIG_SPL_BUILD |
|---|
| 601 | 719 | .probe = rockchip_dw_hdmi_probe, |
|---|
| 720 | +#endif |
|---|
| 602 | 721 | .priv_auto_alloc_size = sizeof(struct rockchip_connector), |
|---|
| 603 | 722 | }; |
|---|