Merge git://git.infradead.org/iommu-2.6
[pandora-kernel.git] / arch / arm / mach-shmobile / board-ap4evb.c
index 5d24d4e..23d472f 100644 (file)
@@ -44,6 +44,7 @@
 
 #include <sound/sh_fsi.h>
 
+#include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mipi_dsi.h>
 
 /*
  * LCD / IRQ / KEYSC / IrDA
  *
- * IRQ = IRQ26 (TS), IRQ27 (VIO), IRQ28 (TouchScreen)
- * LCD = 2nd LCDC
+ * IRQ = IRQ26 (TS), IRQ27 (VIO), IRQ28 (QHD-TouchScreen)
+ * LCD = 2nd LCDC (WVGA)
  *
  *             |               SW43                    |
  * SW3         |       ON              |       OFF     |
  * -------------+-----------------------+---------------+
  * ON          | KEY / IrDA            | LCD           |
  * OFF         | KEY / IrDA / IRQ      | IRQ           |
+ *
+ *
+ * QHD / WVGA display
+ *
+ * You can choice display type on menuconfig.
+ * Then, check above dip-switch.
  */
 
 /*
@@ -226,43 +233,6 @@ static struct platform_device smc911x_device = {
        },
 };
 
-/* KEYSC (Needs SW43 set to ON) */
-static struct sh_keysc_info keysc_info = {
-       .mode           = SH_KEYSC_MODE_1,
-       .scan_timing    = 3,
-       .delay          = 2500,
-       .keycodes = {
-               KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
-               KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
-               KEY_A, KEY_B, KEY_C, KEY_D, KEY_E,
-               KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
-               KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
-       },
-};
-
-static struct resource keysc_resources[] = {
-       [0] = {
-               .name   = "KEYSC",
-               .start  = 0xe61b0000,
-               .end    = 0xe61b0063,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = evt2irq(0x0be0), /* KEYSC_KEY */
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device keysc_device = {
-       .name           = "sh_keysc",
-       .id             = 0, /* "keysc0" clock */
-       .num_resources  = ARRAY_SIZE(keysc_resources),
-       .resource       = keysc_resources,
-       .dev    = {
-               .platform_data  = &keysc_info,
-       },
-};
-
 /* SH_MMCIF */
 static struct resource sh_mmcif_resources[] = {
        [0] = {
@@ -402,30 +372,10 @@ static struct platform_device usb1_host_device = {
        .resource       = usb1_host_resources,
 };
 
-static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
-       .clock_source = LCDC_CLK_PERIPHERAL, /* One of interface clocks */
+static struct sh_mobile_lcdc_info lcdc_info = {
        .ch[0] = {
                .chan = LCDC_CHAN_MAINLCD,
                .bpp = 16,
-               .interface_type = RGB24,
-               .clock_divider = 1,
-               .flags = LCDC_FLAGS_DWPOL,
-               .lcd_cfg = {
-                       .name = "R63302(QHD)",
-                       .xres = 544,
-                       .yres = 961,
-                       .left_margin = 72,
-                       .right_margin = 600,
-                       .hsync_len = 16,
-                       .upper_margin = 8,
-                       .lower_margin = 8,
-                       .vsync_len = 2,
-                       .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
-               },
-               .lcd_size_cfg = {
-                       .width = 44,
-                       .height = 79,
-               },
        }
 };
 
@@ -447,11 +397,54 @@ static struct platform_device lcdc_device = {
        .num_resources  = ARRAY_SIZE(lcdc_resources),
        .resource       = lcdc_resources,
        .dev    = {
-               .platform_data  = &sh_mobile_lcdc_info,
+               .platform_data  = &lcdc_info,
                .coherent_dma_mask = ~0,
        },
 };
 
+/*
+ * QHD display
+ */
+#ifdef CONFIG_AP4EVB_QHD
+
+/* KEYSC (Needs SW43 set to ON) */
+static struct sh_keysc_info keysc_info = {
+       .mode           = SH_KEYSC_MODE_1,
+       .scan_timing    = 3,
+       .delay          = 2500,
+       .keycodes = {
+               KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
+               KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
+               KEY_A, KEY_B, KEY_C, KEY_D, KEY_E,
+               KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
+               KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
+       },
+};
+
+static struct resource keysc_resources[] = {
+       [0] = {
+               .name   = "KEYSC",
+               .start  = 0xe61b0000,
+               .end    = 0xe61b0063,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = evt2irq(0x0be0), /* KEYSC_KEY */
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device keysc_device = {
+       .name           = "sh_keysc",
+       .id             = 0, /* "keysc0" clock */
+       .num_resources  = ARRAY_SIZE(keysc_resources),
+       .resource       = keysc_resources,
+       .dev    = {
+               .platform_data  = &keysc_info,
+       },
+};
+
+/* MIPI-DSI */
 static struct resource mipidsi0_resources[] = {
        [0] = {
                .start  = 0xffc60000,
@@ -462,7 +455,7 @@ static struct resource mipidsi0_resources[] = {
 
 static struct sh_mipi_dsi_info mipidsi0_info = {
        .data_format    = MIPI_RGB888,
-       .lcd_chan       = &sh_mobile_lcdc_info.ch[0],
+       .lcd_chan       = &lcdc_info.ch[0],
 };
 
 static struct platform_device mipidsi0_device = {
@@ -475,6 +468,50 @@ static struct platform_device mipidsi0_device = {
        },
 };
 
+/* This function will disappear when we switch to (runtime) PM */
+static int __init ap4evb_init_display_clk(void)
+{
+       struct clk *lcdc_clk;
+       struct clk *dsitx_clk;
+       int ret;
+
+       lcdc_clk = clk_get(&lcdc_device.dev, "sh_mobile_lcdc_fb.0");
+       if (IS_ERR(lcdc_clk))
+               return PTR_ERR(lcdc_clk);
+
+       dsitx_clk = clk_get(&mipidsi0_device.dev, "sh-mipi-dsi.0");
+       if (IS_ERR(dsitx_clk)) {
+               ret = PTR_ERR(dsitx_clk);
+               goto eclkdsitxget;
+       }
+
+       ret = clk_enable(lcdc_clk);
+       if (ret < 0)
+               goto eclklcdcon;
+
+       ret = clk_enable(dsitx_clk);
+       if (ret < 0)
+               goto eclkdsitxon;
+
+       return 0;
+
+eclkdsitxon:
+       clk_disable(lcdc_clk);
+eclklcdcon:
+       clk_put(dsitx_clk);
+eclkdsitxget:
+       clk_put(lcdc_clk);
+
+       return ret;
+}
+device_initcall(ap4evb_init_display_clk);
+
+static struct platform_device *qhd_devices[] __initdata = {
+       &mipidsi0_device,
+       &keysc_device,
+};
+#endif /* CONFIG_AP4EVB_QHD */
+
 /* FSI */
 #define IRQ_FSI                evt2irq(0x1840)
 #define FSIACKCR       0xE6150018
@@ -529,24 +566,227 @@ static struct platform_device fsi_device = {
        },
 };
 
+static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
+       .clock_source = LCDC_CLK_EXTERNAL,
+       .ch[0] = {
+               .chan = LCDC_CHAN_MAINLCD,
+               .bpp = 16,
+               .interface_type = RGB24,
+               .clock_divider = 1,
+               .flags = LCDC_FLAGS_DWPOL,
+               .lcd_cfg = {
+                       .name = "HDMI",
+                       /* So far only 720p is supported */
+                       .xres = 1280,
+                       .yres = 720,
+                       /*
+                        * If left and right margins are not multiples of 8,
+                        * LDHAJR will be adjusted accordingly by the LCDC
+                        * driver. Until we start using EDID, these values
+                        * might have to be adjusted for different monitors.
+                        */
+                       .left_margin = 200,
+                       .right_margin = 88,
+                       .hsync_len = 48,
+                       .upper_margin = 20,
+                       .lower_margin = 5,
+                       .vsync_len = 5,
+                       .pixclock = 13468,
+                       .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+               },
+       }
+};
+
+static struct resource lcdc1_resources[] = {
+       [0] = {
+               .name   = "LCDC1",
+               .start  = 0xfe944000,
+               .end    = 0xfe947fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = intcs_evt2irq(0x17a0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device lcdc1_device = {
+       .name           = "sh_mobile_lcdc_fb",
+       .num_resources  = ARRAY_SIZE(lcdc1_resources),
+       .resource       = lcdc1_resources,
+       .id             = 1,
+       .dev    = {
+               .platform_data  = &sh_mobile_lcdc1_info,
+               .coherent_dma_mask = ~0,
+       },
+};
+
+static struct sh_mobile_hdmi_info hdmi_info = {
+       .lcd_chan = &sh_mobile_lcdc1_info.ch[0],
+       .lcd_dev = &lcdc1_device.dev,
+};
+
+static struct resource hdmi_resources[] = {
+       [0] = {
+               .name   = "HDMI",
+               .start  = 0xe6be0000,
+               .end    = 0xe6be00ff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* There's also an HDMI interrupt on INTCS @ 0x18e0 */
+               .start  = evt2irq(0x17e0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device hdmi_device = {
+       .name           = "sh-mobile-hdmi",
+       .num_resources  = ARRAY_SIZE(hdmi_resources),
+       .resource       = hdmi_resources,
+       .id             = -1,
+       .dev    = {
+               .platform_data  = &hdmi_info,
+       },
+};
+
 static struct platform_device *ap4evb_devices[] __initdata = {
        &nor_flash_device,
        &smc911x_device,
-       &keysc_device,
        &sdhi0_device,
        &sdhi1_device,
        &usb1_host_device,
-       &lcdc_device,
-       &mipidsi0_device,
        &fsi_device,
-       &sh_mmcif_device
+       &sh_mmcif_device,
+       &lcdc1_device,
+       &lcdc_device,
+       &hdmi_device,
 };
 
-/* TouchScreen (Needs SW3 set to OFF) */
+static int __init hdmi_init_pm_clock(void)
+{
+       struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
+       int ret;
+       long rate;
+
+       if (IS_ERR(hdmi_ick)) {
+               ret = PTR_ERR(hdmi_ick);
+               pr_err("Cannot get HDMI ICK: %d\n", ret);
+               goto out;
+       }
+
+       ret = clk_set_parent(&pllc2_clk, &dv_clki_div2_clk);
+       if (ret < 0) {
+               pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, pllc2_clk.usecount);
+               goto out;
+       }
+
+       pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&pllc2_clk));
+
+       rate = clk_round_rate(&pllc2_clk, 594000000);
+       if (rate < 0) {
+               pr_err("Cannot get suitable rate: %ld\n", rate);
+               ret = rate;
+               goto out;
+       }
+
+       ret = clk_set_rate(&pllc2_clk, rate);
+       if (ret < 0) {
+               pr_err("Cannot set rate %ld: %d\n", rate, ret);
+               goto out;
+       }
+
+       pr_debug("PLLC2 set frequency %lu\n", rate);
+
+       ret = clk_set_parent(hdmi_ick, &pllc2_clk);
+       if (ret < 0) {
+               pr_err("Cannot set HDMI parent: %d\n", ret);
+               goto out;
+       }
+
+out:
+       if (!IS_ERR(hdmi_ick))
+               clk_put(hdmi_ick);
+       return ret;
+}
+
+device_initcall(hdmi_init_pm_clock);
+
+/*
+ * FIXME !!
+ *
+ * gpio_no_direction
+ * gpio_pull_up
+ * are quick_hack.
+ *
+ * current gpio frame work doesn't have
+ * the method to control only pull up/down/free.
+ * this function should be replaced by correct gpio function
+ */
+static void __init gpio_no_direction(u32 addr)
+{
+       __raw_writeb(0x00, addr);
+}
+
+static void __init gpio_pull_up(u32 addr)
+{
+       u8 data = __raw_readb(addr);
+
+       data &= 0x0F;
+       data |= 0xC0;
+       __raw_writeb(data, addr);
+}
+
+/* TouchScreen */
 #define IRQ28  evt2irq(0x3380) /* IRQ28A */
+#define IRQ7   evt2irq(0x02e0) /* IRQ7A */
+static int ts_get_pendown_state(void)
+{
+       int val1, val2;
+
+       gpio_free(GPIO_FN_IRQ28_123);
+       gpio_free(GPIO_FN_IRQ7_40);
+
+       gpio_request(GPIO_PORT123, NULL);
+       gpio_request(GPIO_PORT40, NULL);
+
+       gpio_direction_input(GPIO_PORT123);
+       gpio_direction_input(GPIO_PORT40);
+
+       val1 = gpio_get_value(GPIO_PORT123);
+       val2 = gpio_get_value(GPIO_PORT40);
+
+       gpio_request(GPIO_FN_IRQ28_123, NULL);  /* for QHD */
+       gpio_request(GPIO_FN_IRQ7_40, NULL);    /* for WVGA */
+
+       return val1 ^ val2;
+}
+
+#define PORT40CR       0xE6051028
+#define PORT123CR      0xE605007B
+static int ts_init(void)
+{
+       gpio_request(GPIO_FN_IRQ28_123, NULL);  /* for QHD */
+       gpio_request(GPIO_FN_IRQ7_40, NULL);    /* for WVGA */
+
+       gpio_pull_up(PORT40CR);
+       gpio_pull_up(PORT123CR);
+
+       return 0;
+}
+
 static struct tsc2007_platform_data tsc2007_info = {
        .model                  = 2007,
        .x_plate_ohms           = 180,
+       .get_pendown_state      = ts_get_pendown_state,
+       .init_platform_hw       = ts_init,
+};
+
+static struct i2c_board_info tsc_device = {
+       I2C_BOARD_INFO("tsc2007", 0x48),
+       .type           = "tsc2007",
+       .platform_data  = &tsc2007_info,
+       /*.irq is selected on ap4evb_init */
 };
 
 /* I2C */
@@ -560,12 +800,6 @@ static struct i2c_board_info i2c1_devices[] = {
        {
                I2C_BOARD_INFO("r2025sd", 0x32),
        },
-       {
-               I2C_BOARD_INFO("tsc2007", 0x48),
-               .type           = "tsc2007",
-               .platform_data  = &tsc2007_info,
-               .irq            = IRQ28,
-       },
 };
 
 static struct map_desc ap4evb_io_desc[] __initdata = {
@@ -589,64 +823,11 @@ static void __init ap4evb_map_io(void)
        shmobile_setup_console();
 }
 
-/* This function will disappear when we switch to (runtime) PM */
-static int __init ap4evb_init_display_clk(void)
-{
-       struct clk *lcdc_clk;
-       struct clk *dsitx_clk;
-       int ret;
-
-       lcdc_clk = clk_get(&lcdc_device.dev, "sh_mobile_lcdc_fb.0");
-       if (IS_ERR(lcdc_clk))
-               return PTR_ERR(lcdc_clk);
-
-       dsitx_clk = clk_get(&mipidsi0_device.dev, "sh-mipi-dsi.0");
-       if (IS_ERR(dsitx_clk)) {
-               ret = PTR_ERR(dsitx_clk);
-               goto eclkdsitxget;
-       }
-
-       ret = clk_enable(lcdc_clk);
-       if (ret < 0)
-               goto eclklcdcon;
-
-       ret = clk_enable(dsitx_clk);
-       if (ret < 0)
-               goto eclkdsitxon;
-
-       return 0;
-
-eclkdsitxon:
-       clk_disable(lcdc_clk);
-eclklcdcon:
-       clk_put(dsitx_clk);
-eclkdsitxget:
-       clk_put(lcdc_clk);
-
-       return ret;
-}
-
-device_initcall(ap4evb_init_display_clk);
-
-/*
- * FIXME !!
- *
- * gpio_no_direction is quick_hack.
- *
- * current gpio frame work doesn't have
- * the method to control only pull up/down/free.
- * this function should be replaced by correct gpio function
- */
-static void __init gpio_no_direction(u32 addr)
-{
-       __raw_writeb(0x00, addr);
-}
-
 #define GPIO_PORT9CR   0xE6051009
 #define GPIO_PORT10CR  0xE605100A
-
 static void __init ap4evb_init(void)
 {
+       u32 srcr4;
        struct clk *clk;
 
        sh7372_pinmux_init();
@@ -687,18 +868,6 @@ static void __init ap4evb_init(void)
        gpio_export(GPIO_PORT34, 0);
        gpio_export(GPIO_PORT35, 0);
 
-       /* enable KEYSC */
-       gpio_request(GPIO_FN_KEYOUT0, NULL);
-       gpio_request(GPIO_FN_KEYOUT1, NULL);
-       gpio_request(GPIO_FN_KEYOUT2, NULL);
-       gpio_request(GPIO_FN_KEYOUT3, NULL);
-       gpio_request(GPIO_FN_KEYOUT4, NULL);
-       gpio_request(GPIO_FN_KEYIN0_136, NULL);
-       gpio_request(GPIO_FN_KEYIN1_135, NULL);
-       gpio_request(GPIO_FN_KEYIN2_134, NULL);
-       gpio_request(GPIO_FN_KEYIN3_133, NULL);
-       gpio_request(GPIO_FN_KEYIN4,     NULL);
-
        /* SDHI0 */
        gpio_request(GPIO_FN_SDHICD0, NULL);
        gpio_request(GPIO_FN_SDHIWP0, NULL);
@@ -709,9 +878,13 @@ static void __init ap4evb_init(void)
        gpio_request(GPIO_FN_SDHID0_1, NULL);
        gpio_request(GPIO_FN_SDHID0_0, NULL);
 
-       /* enable TouchScreen */
-       gpio_request(GPIO_FN_IRQ28_123, NULL);
-       set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
+       /* SDHI1 */
+       gpio_request(GPIO_FN_SDHICMD1, NULL);
+       gpio_request(GPIO_FN_SDHICLK1, NULL);
+       gpio_request(GPIO_FN_SDHID1_3, NULL);
+       gpio_request(GPIO_FN_SDHID1_2, NULL);
+       gpio_request(GPIO_FN_SDHID1_1, NULL);
+       gpio_request(GPIO_FN_SDHID1_0, NULL);
 
        /* MMCIF */
        gpio_request(GPIO_FN_MMCD0_0, NULL);
@@ -777,16 +950,118 @@ static void __init ap4evb_init(void)
        i2c_register_board_info(1, i2c1_devices,
                                ARRAY_SIZE(i2c1_devices));
 
-       /* SDHI1 */
-       gpio_request(GPIO_FN_SDHICMD1, NULL);
-       gpio_request(GPIO_FN_SDHICLK1, NULL);
-       gpio_request(GPIO_FN_SDHID1_3, NULL);
-       gpio_request(GPIO_FN_SDHID1_2, NULL);
-       gpio_request(GPIO_FN_SDHID1_1, NULL);
-       gpio_request(GPIO_FN_SDHID1_0, NULL);
+#ifdef CONFIG_AP4EVB_QHD
+       /*
+        * QHD
+        */
+
+       /* enable KEYSC */
+       gpio_request(GPIO_FN_KEYOUT0, NULL);
+       gpio_request(GPIO_FN_KEYOUT1, NULL);
+       gpio_request(GPIO_FN_KEYOUT2, NULL);
+       gpio_request(GPIO_FN_KEYOUT3, NULL);
+       gpio_request(GPIO_FN_KEYOUT4, NULL);
+       gpio_request(GPIO_FN_KEYIN0_136, NULL);
+       gpio_request(GPIO_FN_KEYIN1_135, NULL);
+       gpio_request(GPIO_FN_KEYIN2_134, NULL);
+       gpio_request(GPIO_FN_KEYIN3_133, NULL);
+       gpio_request(GPIO_FN_KEYIN4,     NULL);
+
+       /* enable TouchScreen */
+       set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
+
+       tsc_device.irq = IRQ28;
+       i2c_register_board_info(1, &tsc_device, 1);
+
+       /* LCDC0 */
+       lcdc_info.clock_source                  = LCDC_CLK_PERIPHERAL;
+       lcdc_info.ch[0].interface_type          = RGB24;
+       lcdc_info.ch[0].clock_divider           = 1;
+       lcdc_info.ch[0].flags                   = LCDC_FLAGS_DWPOL;
+       lcdc_info.ch[0].lcd_cfg.name            = "R63302(QHD)";
+       lcdc_info.ch[0].lcd_cfg.xres            = 544;
+       lcdc_info.ch[0].lcd_cfg.yres            = 961;
+       lcdc_info.ch[0].lcd_cfg.left_margin     = 72;
+       lcdc_info.ch[0].lcd_cfg.right_margin    = 600;
+       lcdc_info.ch[0].lcd_cfg.hsync_len       = 16;
+       lcdc_info.ch[0].lcd_cfg.upper_margin    = 8;
+       lcdc_info.ch[0].lcd_cfg.lower_margin    = 8;
+       lcdc_info.ch[0].lcd_cfg.vsync_len       = 2;
+       lcdc_info.ch[0].lcd_cfg.sync            = FB_SYNC_VERT_HIGH_ACT |
+                                                 FB_SYNC_HOR_HIGH_ACT;
+       lcdc_info.ch[0].lcd_size_cfg.width      = 44;
+       lcdc_info.ch[0].lcd_size_cfg.height     = 79;
+
+       platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices));
+
+#else
+       /*
+        * WVGA
+        */
+       gpio_request(GPIO_FN_LCDD17,   NULL);
+       gpio_request(GPIO_FN_LCDD16,   NULL);
+       gpio_request(GPIO_FN_LCDD15,   NULL);
+       gpio_request(GPIO_FN_LCDD14,   NULL);
+       gpio_request(GPIO_FN_LCDD13,   NULL);
+       gpio_request(GPIO_FN_LCDD12,   NULL);
+       gpio_request(GPIO_FN_LCDD11,   NULL);
+       gpio_request(GPIO_FN_LCDD10,   NULL);
+       gpio_request(GPIO_FN_LCDD9,    NULL);
+       gpio_request(GPIO_FN_LCDD8,    NULL);
+       gpio_request(GPIO_FN_LCDD7,    NULL);
+       gpio_request(GPIO_FN_LCDD6,    NULL);
+       gpio_request(GPIO_FN_LCDD5,    NULL);
+       gpio_request(GPIO_FN_LCDD4,    NULL);
+       gpio_request(GPIO_FN_LCDD3,    NULL);
+       gpio_request(GPIO_FN_LCDD2,    NULL);
+       gpio_request(GPIO_FN_LCDD1,    NULL);
+       gpio_request(GPIO_FN_LCDD0,    NULL);
+       gpio_request(GPIO_FN_LCDDISP,  NULL);
+       gpio_request(GPIO_FN_LCDDCK,   NULL);
+
+       gpio_request(GPIO_PORT189, NULL); /* backlight */
+       gpio_direction_output(GPIO_PORT189, 1);
+
+       gpio_request(GPIO_PORT151, NULL); /* LCDDON */
+       gpio_direction_output(GPIO_PORT151, 1);
+
+       lcdc_info.clock_source                  = LCDC_CLK_BUS;
+       lcdc_info.ch[0].interface_type          = RGB18;
+       lcdc_info.ch[0].clock_divider           = 2;
+       lcdc_info.ch[0].flags                   = 0;
+       lcdc_info.ch[0].lcd_cfg.name            = "WVGA Panel";
+       lcdc_info.ch[0].lcd_cfg.xres            = 800;
+       lcdc_info.ch[0].lcd_cfg.yres            = 480;
+       lcdc_info.ch[0].lcd_cfg.left_margin     = 220;
+       lcdc_info.ch[0].lcd_cfg.right_margin    = 110;
+       lcdc_info.ch[0].lcd_cfg.hsync_len       = 70;
+       lcdc_info.ch[0].lcd_cfg.upper_margin    = 20;
+       lcdc_info.ch[0].lcd_cfg.lower_margin    = 5;
+       lcdc_info.ch[0].lcd_cfg.vsync_len       = 5;
+       lcdc_info.ch[0].lcd_cfg.sync            = 0;
+       lcdc_info.ch[0].lcd_size_cfg.width      = 152;
+       lcdc_info.ch[0].lcd_size_cfg.height     = 91;
+
+       /* enable TouchScreen */
+       set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
+
+       tsc_device.irq = IRQ7;
+       i2c_register_board_info(0, &tsc_device, 1);
+#endif /* CONFIG_AP4EVB_QHD */
 
        sh7372_add_standard_devices();
 
+       /* HDMI */
+       gpio_request(GPIO_FN_HDMI_HPD, NULL);
+       gpio_request(GPIO_FN_HDMI_CEC, NULL);
+
+       /* Reset HDMI, must be held at least one EXTALR (32768Hz) period */
+#define SRCR4 0xe61580bc
+       srcr4 = __raw_readl(SRCR4);
+       __raw_writel(srcr4 | (1 << 13), SRCR4);
+       udelay(50);
+       __raw_writel(srcr4 & ~(1 << 13), SRCR4);
+
        platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
 }
 
@@ -794,6 +1069,9 @@ static void __init ap4evb_timer_init(void)
 {
        sh7372_clock_init();
        shmobile_timer.init();
+
+       /* External clock source */
+       clk_set_rate(&dv_clki_clk, 27000000);
 }
 
 static struct sys_timer ap4evb_timer = {