Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dfbcdf64 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Paul Mundt
Browse files

ARM: mach-shmobile: add HDMI support to the ap4evb board



Support HDMI in 720p mode.

Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: default avatarMagnus Damm <damm@opensource.se>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 6011bdea
Loading
Loading
Loading
Loading
+152 −2
Original line number Diff line number Diff line
@@ -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 = {