aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2010-07-21 06:13:25 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-08-04 03:17:49 -0400
commitdfbcdf6420edab4afee73c7958f8fbfaade335b6 (patch)
treec86f0470edb837b7eebb5110120399d13a036531 /arch/arm/mach-shmobile
parent6011bdeaa6089d49c02de69f05980da7bad314ab (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.c154
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
569static 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
600static 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
613static 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
624static struct sh_mobile_hdmi_info hdmi_info = {
625 .lcd_chan = &sh_mobile_lcdc1_info.ch[0],
626 .lcd_dev = &lcdc1_device.dev,
627};
628
629static 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
643static 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
568static struct platform_device *ap4evb_devices[] __initdata = { 653static 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
666static 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
707out:
708 if (!IS_ERR(hdmi_ick))
709 clk_put(hdmi_ick);
710 return ret;
711}
712
713device_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
693static void __init ap4evb_init(void) 828static 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
927static struct sys_timer ap4evb_timer = { 1077static struct sys_timer ap4evb_timer = {