@@ -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>
@@ -529,6 +530,90 @@ 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 | LCDC_FLAGS_HDMI,
+ .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,
@@ -539,7 +624,9 @@ static struct platform_device *ap4evb_devices[] __initdata = {
&lcdc_device,
&mipidsi0_device,
&fsi_device,
- &sh_mmcif_device
+ &sh_mmcif_device,
+ &lcdc1_device,
+ &hdmi_device,
};
/* TouchScreen (Needs SW3 set to OFF) */
@@ -645,8 +732,36 @@ static void __init gpio_no_direction(u32 addr)
#define GPIO_PORT9CR 0xE6051009
#define GPIO_PORT10CR 0xE605100A
+static int __init hdmi_init_pm_clock(void)
+{
+ struct clk *hdmi_pm = clk_get(NULL, "sh-hdmi.0"),
+ *lcdc1_pm = clk_get(&lcdc1_device.dev, "sh_mobile_lcdc_fb.1");
+ int ret;
+
+ if (!IS_ERR(hdmi_pm)) {
+ ret = clk_enable(hdmi_pm);
+ if (ret < 0)
+ pr_err("Cannot enable clock: %d\n", ret);
+ } else {
+ pr_err("Cannot get HDMI PM: %ld\n", PTR_ERR(hdmi_pm));
+ }
+
+ if (!IS_ERR(lcdc1_pm)) {
+ ret = clk_enable(lcdc1_pm);
+ if (ret < 0)
+ pr_err("Cannot enable clock: %d\n", ret);
+ } else {
+ pr_err("Cannot get LCDC1 PM: %ld\n", PTR_ERR(lcdc1_pm));
+ }
+
+ return 0;
+}
+
+device_initcall(hdmi_init_pm_clock);
+
static void __init ap4evb_init(void)
{
+ u32 srcr4;
struct clk *clk;
sh7372_pinmux_init();
@@ -787,6 +902,17 @@ static void __init ap4evb_init(void)
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));
}