.. | .. |
---|
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 | }; |
---|