|
@@ -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>
|
|
|
|
|
@@ -565,17 +566,152 @@ 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,
|
|
|
&sdhi0_device,
|
|
|
&sdhi1_device,
|
|
|
&usb1_host_device,
|
|
|
- &lcdc_device,
|
|
|
&fsi_device,
|
|
|
&sh_mmcif_device
|
|
|
+ &lcdc1_device,
|
|
|
+ &lcdc_device,
|
|
|
+ &hdmi_device,
|
|
|
};
|
|
|
|
|
|
+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 !!
|
|
|
*
|
|
@@ -689,9 +825,9 @@ static void __init ap4evb_map_io(void)
|
|
|
|
|
|
#define GPIO_PORT9CR 0xE6051009
|
|
|
#define GPIO_PORT10CR 0xE605100A
|
|
|
-
|
|
|
static void __init ap4evb_init(void)
|
|
|
{
|
|
|
+ u32 srcr4;
|
|
|
struct clk *clk;
|
|
|
|
|
|
sh7372_pinmux_init();
|
|
@@ -915,6 +1051,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));
|
|
|
}
|
|
|
|
|
@@ -922,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 = {
|