diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2010-07-21 06:13:25 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-08-04 03:17:49 -0400 |
commit | dfbcdf6420edab4afee73c7958f8fbfaade335b6 (patch) | |
tree | c86f0470edb837b7eebb5110120399d13a036531 /arch/arm/mach-shmobile | |
parent | 6011bdeaa6089d49c02de69f05980da7bad314ab (diff) |
ARM: mach-shmobile: add HDMI support to the ap4evb board
Support HDMI in 720p mode.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 154 |
1 files changed, 152 insertions, 2 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 968601201fb5..024f8f4c2a33 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -44,6 +44,7 @@ | |||
44 | 44 | ||
45 | #include <sound/sh_fsi.h> | 45 | #include <sound/sh_fsi.h> |
46 | 46 | ||
47 | #include <video/sh_mobile_hdmi.h> | ||
47 | #include <video/sh_mobile_lcdc.h> | 48 | #include <video/sh_mobile_lcdc.h> |
48 | #include <video/sh_mipi_dsi.h> | 49 | #include <video/sh_mipi_dsi.h> |
49 | 50 | ||
@@ -565,17 +566,152 @@ static struct platform_device fsi_device = { | |||
565 | }, | 566 | }, |
566 | }; | 567 | }; |
567 | 568 | ||
569 | static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = { | ||
570 | .clock_source = LCDC_CLK_EXTERNAL, | ||
571 | .ch[0] = { | ||
572 | .chan = LCDC_CHAN_MAINLCD, | ||
573 | .bpp = 16, | ||
574 | .interface_type = RGB24, | ||
575 | .clock_divider = 1, | ||
576 | .flags = LCDC_FLAGS_DWPOL, | ||
577 | .lcd_cfg = { | ||
578 | .name = "HDMI", | ||
579 | /* So far only 720p is supported */ | ||
580 | .xres = 1280, | ||
581 | .yres = 720, | ||
582 | /* | ||
583 | * If left and right margins are not multiples of 8, | ||
584 | * LDHAJR will be adjusted accordingly by the LCDC | ||
585 | * driver. Until we start using EDID, these values | ||
586 | * might have to be adjusted for different monitors. | ||
587 | */ | ||
588 | .left_margin = 200, | ||
589 | .right_margin = 88, | ||
590 | .hsync_len = 48, | ||
591 | .upper_margin = 20, | ||
592 | .lower_margin = 5, | ||
593 | .vsync_len = 5, | ||
594 | .pixclock = 13468, | ||
595 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, | ||
596 | }, | ||
597 | } | ||
598 | }; | ||
599 | |||
600 | static struct resource lcdc1_resources[] = { | ||
601 | [0] = { | ||
602 | .name = "LCDC1", | ||
603 | .start = 0xfe944000, | ||
604 | .end = 0xfe947fff, | ||
605 | .flags = IORESOURCE_MEM, | ||
606 | }, | ||
607 | [1] = { | ||
608 | .start = intcs_evt2irq(0x17a0), | ||
609 | .flags = IORESOURCE_IRQ, | ||
610 | }, | ||
611 | }; | ||
612 | |||
613 | static struct platform_device lcdc1_device = { | ||
614 | .name = "sh_mobile_lcdc_fb", | ||
615 | .num_resources = ARRAY_SIZE(lcdc1_resources), | ||
616 | .resource = lcdc1_resources, | ||
617 | .id = 1, | ||
618 | .dev = { | ||
619 | .platform_data = &sh_mobile_lcdc1_info, | ||
620 | .coherent_dma_mask = ~0, | ||
621 | }, | ||
622 | }; | ||
623 | |||
624 | static struct sh_mobile_hdmi_info hdmi_info = { | ||
625 | .lcd_chan = &sh_mobile_lcdc1_info.ch[0], | ||
626 | .lcd_dev = &lcdc1_device.dev, | ||
627 | }; | ||
628 | |||
629 | static struct resource hdmi_resources[] = { | ||
630 | [0] = { | ||
631 | .name = "HDMI", | ||
632 | .start = 0xe6be0000, | ||
633 | .end = 0xe6be00ff, | ||
634 | .flags = IORESOURCE_MEM, | ||
635 | }, | ||
636 | [1] = { | ||
637 | /* There's also an HDMI interrupt on INTCS @ 0x18e0 */ | ||
638 | .start = evt2irq(0x17e0), | ||
639 | .flags = IORESOURCE_IRQ, | ||
640 | }, | ||
641 | }; | ||
642 | |||
643 | static struct platform_device hdmi_device = { | ||
644 | .name = "sh-mobile-hdmi", | ||
645 | .num_resources = ARRAY_SIZE(hdmi_resources), | ||
646 | .resource = hdmi_resources, | ||
647 | .id = -1, | ||
648 | .dev = { | ||
649 | .platform_data = &hdmi_info, | ||
650 | }, | ||
651 | }; | ||
652 | |||
568 | static struct platform_device *ap4evb_devices[] __initdata = { | 653 | static struct platform_device *ap4evb_devices[] __initdata = { |
569 | &nor_flash_device, | 654 | &nor_flash_device, |
570 | &smc911x_device, | 655 | &smc911x_device, |
571 | &sdhi0_device, | 656 | &sdhi0_device, |
572 | &sdhi1_device, | 657 | &sdhi1_device, |
573 | &usb1_host_device, | 658 | &usb1_host_device, |
574 | &lcdc_device, | ||
575 | &fsi_device, | 659 | &fsi_device, |
576 | &sh_mmcif_device | 660 | &sh_mmcif_device |
661 | &lcdc1_device, | ||
662 | &lcdc_device, | ||
663 | &hdmi_device, | ||
577 | }; | 664 | }; |
578 | 665 | ||
666 | static int __init hdmi_init_pm_clock(void) | ||
667 | { | ||
668 | struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick"); | ||
669 | int ret; | ||
670 | long rate; | ||
671 | |||
672 | if (IS_ERR(hdmi_ick)) { | ||
673 | ret = PTR_ERR(hdmi_ick); | ||
674 | pr_err("Cannot get HDMI ICK: %d\n", ret); | ||
675 | goto out; | ||
676 | } | ||
677 | |||
678 | ret = clk_set_parent(&pllc2_clk, &dv_clki_div2_clk); | ||
679 | if (ret < 0) { | ||
680 | pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, pllc2_clk.usecount); | ||
681 | goto out; | ||
682 | } | ||
683 | |||
684 | pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&pllc2_clk)); | ||
685 | |||
686 | rate = clk_round_rate(&pllc2_clk, 594000000); | ||
687 | if (rate < 0) { | ||
688 | pr_err("Cannot get suitable rate: %ld\n", rate); | ||
689 | ret = rate; | ||
690 | goto out; | ||
691 | } | ||
692 | |||
693 | ret = clk_set_rate(&pllc2_clk, rate); | ||
694 | if (ret < 0) { | ||
695 | pr_err("Cannot set rate %ld: %d\n", rate, ret); | ||
696 | goto out; | ||
697 | } | ||
698 | |||
699 | pr_debug("PLLC2 set frequency %lu\n", rate); | ||
700 | |||
701 | ret = clk_set_parent(hdmi_ick, &pllc2_clk); | ||
702 | if (ret < 0) { | ||
703 | pr_err("Cannot set HDMI parent: %d\n", ret); | ||
704 | goto out; | ||
705 | } | ||
706 | |||
707 | out: | ||
708 | if (!IS_ERR(hdmi_ick)) | ||
709 | clk_put(hdmi_ick); | ||
710 | return ret; | ||
711 | } | ||
712 | |||
713 | device_initcall(hdmi_init_pm_clock); | ||
714 | |||
579 | /* | 715 | /* |
580 | * FIXME !! | 716 | * FIXME !! |
581 | * | 717 | * |
@@ -689,9 +825,9 @@ static void __init ap4evb_map_io(void) | |||
689 | 825 | ||
690 | #define GPIO_PORT9CR 0xE6051009 | 826 | #define GPIO_PORT9CR 0xE6051009 |
691 | #define GPIO_PORT10CR 0xE605100A | 827 | #define GPIO_PORT10CR 0xE605100A |
692 | |||
693 | static void __init ap4evb_init(void) | 828 | static void __init ap4evb_init(void) |
694 | { | 829 | { |
830 | u32 srcr4; | ||
695 | struct clk *clk; | 831 | struct clk *clk; |
696 | 832 | ||
697 | sh7372_pinmux_init(); | 833 | sh7372_pinmux_init(); |
@@ -915,6 +1051,17 @@ static void __init ap4evb_init(void) | |||
915 | 1051 | ||
916 | sh7372_add_standard_devices(); | 1052 | sh7372_add_standard_devices(); |
917 | 1053 | ||
1054 | /* HDMI */ | ||
1055 | gpio_request(GPIO_FN_HDMI_HPD, NULL); | ||
1056 | gpio_request(GPIO_FN_HDMI_CEC, NULL); | ||
1057 | |||
1058 | /* Reset HDMI, must be held at least one EXTALR (32768Hz) period */ | ||
1059 | #define SRCR4 0xe61580bc | ||
1060 | srcr4 = __raw_readl(SRCR4); | ||
1061 | __raw_writel(srcr4 | (1 << 13), SRCR4); | ||
1062 | udelay(50); | ||
1063 | __raw_writel(srcr4 & ~(1 << 13), SRCR4); | ||
1064 | |||
918 | platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); | 1065 | platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); |
919 | } | 1066 | } |
920 | 1067 | ||
@@ -922,6 +1069,9 @@ static void __init ap4evb_timer_init(void) | |||
922 | { | 1069 | { |
923 | sh7372_clock_init(); | 1070 | sh7372_clock_init(); |
924 | shmobile_timer.init(); | 1071 | shmobile_timer.init(); |
1072 | |||
1073 | /* External clock source */ | ||
1074 | clk_set_rate(&dv_clki_clk, 27000000); | ||
925 | } | 1075 | } |
926 | 1076 | ||
927 | static struct sys_timer ap4evb_timer = { | 1077 | static struct sys_timer ap4evb_timer = { |