All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomasz Stanislawski <t.stanislaws@samsung.com>
To: linux-media@vger.kernel.org, linux-samsung-soc@vger.kernel.org
Cc: m.szyprowski@samsung.com, t.stanislaws@samsung.com,
	kyungmin.park@samsung.com
Subject: [PATCH 5/5] s5pc210: add s5p-tv to platform devices
Date: Tue, 08 Feb 2011 10:30:27 +0100	[thread overview]
Message-ID: <1297157427-14560-6-git-send-email-t.stanislaws@samsung.com> (raw)
In-Reply-To: <1297157427-14560-1-git-send-email-t.stanislaws@samsung.com>

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-s5pv310/Kconfig                   |    7 +
 arch/arm/mach-s5pv310/Makefile                  |    1 +
 arch/arm/mach-s5pv310/clock.c                   |  126 +++++++-
 arch/arm/mach-s5pv310/dev-tv.c                  |  450 +++++++++++++++++++++++
 arch/arm/mach-s5pv310/include/mach/irqs.h       |    4 +
 arch/arm/mach-s5pv310/include/mach/map.h        |   26 ++
 arch/arm/mach-s5pv310/include/mach/regs-clock.h |   15 +
 arch/arm/plat-samsung/include/plat/devs.h       |    2 +
 8 files changed, 630 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/dev-tv.c

diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
index 09c4c21..e62103b 100644
--- a/arch/arm/mach-s5pv310/Kconfig
+++ b/arch/arm/mach-s5pv310/Kconfig
@@ -20,6 +20,11 @@ config S5PV310_DEV_PD
 	help
 	  Compile in platform device definitions for Power Domain
 
+config S5PV310_DEV_TV
+	bool
+	help
+	  Compile in platform device definition for TV interface
+
 config S5PV310_SETUP_I2C1
 	bool
 	help
@@ -102,6 +107,8 @@ config MACH_UNIVERSAL_C210
 	select S3C_DEV_HSMMC3
 	select S5PV310_SETUP_SDHCI
 	select S3C_DEV_I2C1
+	select S3C_DEV_I2C8
+	select S5PV310_DEV_TV
 	select S5PV310_SETUP_I2C1
 	help
 	  Machine support for Samsung Mobile Universal S5PC210 Reference
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
index 036fb38..a234b80 100644
--- a/arch/arm/mach-s5pv310/Makefile
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -32,6 +32,7 @@ obj-y					+= dev-audio.o
 obj-$(CONFIG_S5PV310_DEV_PD)		+= dev-pd.o
 obj-$(CONFIG_S5PV310_DEV_SYSMMU)	+= dev-sysmmu.o
 
+obj-$(CONFIG_S5PV310_DEV_TV)		+= dev-tv.o
 obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o
 obj-$(CONFIG_S5PV310_SETUP_I2C2)	+= setup-i2c2.o
 obj-$(CONFIG_S5PV310_SETUP_I2C3)	+= setup-i2c3.o
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index 6161b54..5bca261 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -81,6 +81,11 @@ static int s5pv310_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
 }
 
+static int s5pv310_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
+}
+
 static int s5pv310_clk_ip_cam_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
@@ -116,6 +121,11 @@ static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
 }
 
+static int s5pv310_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
 /* Core list of CMU_CPU side */
 
 static struct clksrc_clk clk_mout_apll = {
@@ -432,6 +442,26 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pv310_clk_ip_lcd1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
+		.name           = "dac",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 2),
+	}, {
+		.name           = "mixer",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 1),
+	}, {
+		.name           = "vp",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 0),
+	}, {
+		.name           = "hdmi",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 3),
+	}, {
 		.name		= "hsmmc",
 		.id		= 0,
 		.parent		= &clk_aclk_133.clk,
@@ -697,6 +727,93 @@ static struct clksrc_sources clkset_mout_g2d = {
 	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
 };
 
+/* --------------------------------------
+ *         TV subsystem CLOCKS
+ * --------------------------------------
+ */
+
+static struct clk *clkset_sclk_dac_list[] = {
+	[0] = &clk_sclk_vpll.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+	.sources	= clkset_sclk_dac_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+	.clk		= {
+		.name		= "sclk_dac",
+		.id		= -1,
+		.enable		= s5pv310_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 8),
+	},
+	.sources = &clkset_sclk_dac,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel  = {
+	.clk		= {
+		.name		= "sclk_pixel",
+		.id		= -1,
+		.parent = &clk_sclk_vpll.clk,
+	},
+	.reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+	[0] = &clk_sclk_pixel.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+	.sources	= clkset_sclk_hdmi_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+	.clk		= {
+		.name		= "sclk_hdmi",
+		.id		= -1,
+		.enable		= s5pv310_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources = &clkset_sclk_hdmi,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+	[0] = &clk_sclk_dac.clk,
+	[1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+	.sources	= clkset_sclk_mixer_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clksrc_clk clk_sclk_mixer = {
+	.clk		= {
+		.name		= "sclk_mixer",
+		.id		= -1,
+		.enable		= s5pv310_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	},
+	.sources = &clkset_sclk_mixer,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+	&clk_sclk_dac,
+	&clk_sclk_pixel,
+	&clk_sclk_hdmi,
+	&clk_sclk_mixer,
+	NULL,
+};
+
+/* -------------------------------------------- */
+
 static struct clksrc_clk clk_dout_mmc0 = {
 	.clk		= {
 		.name		= "dout_mmc0",
@@ -1106,7 +1223,10 @@ void __init_or_cpufreq s5pv310_setup_clocks(void)
 }
 
 static struct clk *clks[] __initdata = {
-	/* Nothing here yet */
+	&clk_sclk_hdmi27m,
+	&clk_sclk_hdmiphy,
+	&clk_sclk_usbphy0,
+	&clk_sclk_usbphy1,
 };
 
 void __init s5pv310_register_clocks(void)
@@ -1118,6 +1238,10 @@ void __init s5pv310_register_clocks(void)
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
 
+	/* register TV clocks */
+	for (ptr = 0; sclk_tv[ptr]; ++ptr)
+		s3c_register_clksrc(sclk_tv[ptr], 1);
+
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
diff --git a/arch/arm/mach-s5pv310/dev-tv.c b/arch/arm/mach-s5pv310/dev-tv.c
new file mode 100644
index 0000000..b652c4c
--- /dev/null
+++ b/arch/arm/mach-s5pv310/dev-tv.c
@@ -0,0 +1,450 @@
+/* linux/arch/arm/mach-s5pv310/dev-tv.c
+ *
+ * Copyright 20i10 Samsung Electronics
+ *      Tomasz Stanislawski <t.stanislaws@samsung.com>
+ *
+ * S5P series device definition for TV device
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include "plat/tv.h"
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+/* macro for setting registeres */
+#define SETREG(name, value, mask) \
+do { \
+	u32 reg = readl(name); \
+	reg &= ~mask; \
+	reg |= value; \
+	writel(reg, name); \
+	reg = readl(name); \
+	printk(KERN_DEBUG #name " <- %08x\n", reg); \
+} while (0)
+
+/* macro for debugging registeres */
+#define DBGREG(name) \
+do { \
+	u32 reg = readl(name); \
+	printk(KERN_DEBUG #name " <- %08x\n", reg); \
+} while (0)
+
+static void dbg_plat_regs(void);
+
+/* very simpler tv-power-domain support */
+static int tv_power_cnt;
+
+static void tv_power_get(void)
+{
+	if (++tv_power_cnt == 1) {
+		int tries;
+		printk(KERN_ERR "TV power domain on - start\n");
+		dbg_plat_regs();
+		SETREG(S5P_CLKGATE_BLOCK, 0x02, 0x02); /* keep here */
+		SETREG(S5P_CMU_CLKSTOP_TV_SYS_PWR, 1, 1);
+		SETREG(S5P_CMU_RESET_TV_SYS_PWR, 1, 1);
+		SETREG(S5P_TV_SYS_PWR, 7, 7);
+		/* power domain on sequence */
+		SETREG(S5P_TV_CONFIGURATION, 7, 7);
+		for (tries = 1000; tries; mdelay(1), tries--)
+			if ((readl(S5P_TV_STATUS) & 7) == 7)
+				break;
+		WARN(tries == 0, "failed to turn TV power domain on\n");
+		printk(KERN_ERR "TV power domain on - finish\n");
+		dbg_plat_regs();
+	}
+}
+
+static void tv_power_put(void)
+{
+	if (--tv_power_cnt == 0) {
+		int tries;
+		printk(KERN_ERR "TV power domain off - start\n");
+		dbg_plat_regs();
+		SETREG(S5P_TV_CONFIGURATION, 0, 7);
+		for (tries = 1000; tries; mdelay(1), tries--)
+			if ((readl(S5P_TV_STATUS) & 7) == 0)
+				break;
+		WARN(tries == 0, "failed to turn TV power domain off\n");
+		SETREG(S5P_TV_SYS_PWR, 0, 7);
+		SETREG(S5P_CMU_RESET_TV_SYS_PWR, 0, 1);
+		SETREG(S5P_CMU_CLKSTOP_TV_SYS_PWR, 0, 1);
+		SETREG(S5P_CLKGATE_BLOCK, 0x00, 0x02); /* keep here */
+		printk(KERN_ERR "TV power domain off - finish\n");
+		dbg_plat_regs();
+	}
+}
+
+/* HDMI interface */
+static struct resource s5p_hdmi_resources[] = {
+	[0] = {
+		.start  = S5P_PA_HDMI,
+		.end    = S5P_PA_HDMI + S5P_SZ_HDMI - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_HDMI,
+		.end    = IRQ_HDMI,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct hdmi_platform_data hdmi_pdata;
+
+struct platform_device s5p_device_hdmi = {
+	.name           = "s5p-hdmi",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(s5p_hdmi_resources),
+	.resource       = s5p_hdmi_resources,
+	.dev.platform_data = &hdmi_pdata,
+};
+EXPORT_SYMBOL(s5p_device_hdmi);
+
+static struct hdmi_plat_resource {
+	struct clk *hdmi;
+	struct clk *sclk_hdmi;
+	struct clk *sclk_pixel;
+	struct clk *sclk_hdmiphy;
+	struct regulator *ldo4;
+} hdmi_plat_resource;
+
+static void hdmi_deinit(struct device *dev);
+
+static int hdmi_init(struct device *dev)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	dev_info(dev, "platform HDMI Init\n");
+	memset(res, 0, sizeof *res);
+	/* get clocks, power, and GPIOs */
+	gpio_request(S5PV310_GPX3(7), "hpd-plug");
+	gpio_request(S5PV310_GPE0(1), "hdmi-en");
+
+	/* direct HPD to HDMI chip */
+	gpio_direction_input(S5PV310_GPX3(7));
+	s3c_gpio_cfgpin(S5PV310_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(S5PV310_GPX3(7), S3C_GPIO_PULL_NONE);
+
+	/* move this names somewhere */
+	res->hdmi = clk_get(dev, "hdmi");
+	if (IS_ERR_OR_NULL(res->hdmi)) {
+		dev_err(dev, "failed to get clock 'hdmi'\n");
+		goto fail;
+	}
+	res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
+	if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
+		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
+		goto fail;
+	}
+	res->sclk_pixel = clk_get(dev, "sclk_pixel");
+	if (IS_ERR_OR_NULL(res->sclk_pixel)) {
+		dev_err(dev, "failed to get clock 'sclk_pixel'\n");
+		goto fail;
+	}
+	res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
+	if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
+		dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n");
+		goto fail;
+	}
+	res->ldo4 = regulator_get(dev, "vadc_3.3v_c210");
+	if (IS_ERR_OR_NULL(res->ldo4)) {
+		dev_err(dev, "failed to get regulator 'ldo4'\n");
+		goto fail;
+	}
+
+	/* use VPP as parent clock; HDMIPHY is not working yet */
+	clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+	/* regulator_enable(res->ldo4); */
+	tv_power_get();
+
+	dbg_plat_regs();
+
+	return 0;
+fail:
+	dev_err(dev, "platform HDMI Init - failed\n");
+	hdmi_deinit(dev);
+	return -ENODEV;
+}
+
+static void hdmi_deinit(struct device *dev)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	dev_info(dev, "platform HDMI Deinit\n");
+	/* put clocks, power, and GPIOs */
+	if (!IS_ERR_OR_NULL(res->ldo4)) {
+		tv_power_put();
+		/* regulator_disable(res->ldo4); */
+		regulator_put(res->ldo4);
+	}
+	if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
+		clk_put(res->sclk_hdmiphy);
+	if (!IS_ERR_OR_NULL(res->sclk_pixel))
+		clk_put(res->sclk_pixel);
+	if (!IS_ERR_OR_NULL(res->sclk_hdmi))
+		clk_put(res->sclk_hdmi);
+	if (!IS_ERR_OR_NULL(res->hdmi))
+		clk_put(res->hdmi);
+	memset(res, 0, sizeof *res);
+	gpio_free(S5PV310_GPE0(1));
+	gpio_free(S5PV310_GPX3(7));
+}
+
+static int hdmi_power_setup(struct device *dev, int en)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	if (en) {
+		dev_info(dev, "HDMI power-on\n");
+		/* turn HDMI power on */
+		gpio_direction_output(S5PV310_GPE0(1), 1);
+		/* tv_power_get(); */
+		regulator_enable(res->ldo4);
+		/* turn clocks on */
+		clk_enable(res->hdmi);
+		clk_enable(res->sclk_hdmi);
+		/* power-on hdmi physical interface */
+		SETREG(S5P_HDMI_PHY_CONTROL, 1, 1);
+	} else {
+		dev_info(dev, "HDMI power-off\n");
+		/* power-off hdmiphy */
+		SETREG(S5P_HDMI_PHY_CONTROL, 0, 1);
+		/* turn clocks off */
+		clk_disable(res->sclk_hdmi);
+		clk_disable(res->hdmi);
+		/* turn HDMI power off */
+		regulator_disable(res->ldo4);
+		/* tv_power_put(); */
+		gpio_direction_output(S5PV310_GPE0(1), 0);
+	}
+	dbg_plat_regs();
+	return 0;
+}
+
+static int hdmi_stream_setup(struct device *dev, int en)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	/* NOTE: assumed HDMI power is on */
+	if (en) {
+		dev_info(dev, "HDMI: stream on\n");
+		/* hdmiphy clock is used for HDMI in streaming mode */
+		clk_disable(res->sclk_hdmi);
+		clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy);
+		clk_enable(res->sclk_hdmi);
+		/* SETREG(S5P_CLKSRC_TV, 0x00000001, 0x00000001); */
+	} else {
+		dev_info(dev, "HDMI: stream off\n");
+		/* pixel(vpll) clock is used for HDMI in config mode */
+		clk_disable(res->sclk_hdmi);
+		clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+		clk_enable(res->sclk_hdmi);
+		/* SETREG(S5P_CLKSRC_TV, 0x00000000, 0x00000001); */
+	}
+	dbg_plat_regs();
+	return 0;
+}
+
+static struct hdmi_platform_data hdmi_pdata = {
+	.init = hdmi_init,
+	.deinit = hdmi_deinit,
+	.power_setup = hdmi_power_setup,
+	.stream_setup = hdmi_stream_setup,
+};
+
+/* MIXER */
+static struct resource s5p_mixer_resources[] = {
+	[0] = {
+		.start  = S5P_PA_MIXER,
+		.end    = S5P_PA_MIXER + S5P_SZ_MIXER - 1,
+		.flags  = IORESOURCE_MEM,
+		.name	= "mxr"
+	},
+	[1] = {
+		.start  = S5P_PA_VP,
+		.end    = S5P_PA_VP + S5P_SZ_VP - 1,
+		.flags  = IORESOURCE_MEM,
+		.name	= "vp"
+	},
+	[2] = {
+		.start  = IRQ_MIXER,
+		.end    = IRQ_MIXER,
+		.flags  = IORESOURCE_IRQ,
+		.name	= "irq"
+	},
+};
+
+static struct mxr_platform_data mxr_pdata;
+
+struct platform_device s5p_device_mixer = {
+	.name           = "s5p-mixer",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(s5p_mixer_resources),
+	.resource       = s5p_mixer_resources,
+	.dev		= {
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &s5p_device_mixer.dev.coherent_dma_mask,
+		.platform_data = &mxr_pdata,
+	}
+};
+EXPORT_SYMBOL(s5p_device_mixer);
+
+static struct mxr_plat_resource {
+	struct clk *mixer;
+	struct clk *vp;
+	struct clk *sclk_mixer;
+	struct clk *sclk_hdmi;
+	struct clk *sclk_dac;
+	struct regulator *ldo4;
+} mxr_plat_resource;
+
+static void mxr_deinit(struct device *dev);
+
+static int mxr_init(struct device *dev)
+{
+	struct mxr_plat_resource *res = &mxr_plat_resource;
+	dev_info(dev, "platform Mixer Init\n");
+	res->mixer = clk_get(dev, "mixer");
+	if (IS_ERR_OR_NULL(res->mixer)) {
+		dev_err(dev, "failed to get clock 'mixer'\n");
+		goto fail;
+	}
+	res->vp = clk_get(dev, "vp");
+	if (IS_ERR_OR_NULL(res->vp)) {
+		dev_err(dev, "failed to get clock 'vp'\n");
+		goto fail;
+	}
+	res->sclk_mixer = clk_get(dev, "sclk_mixer");
+	if (IS_ERR_OR_NULL(res->sclk_mixer)) {
+		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
+		goto fail;
+	}
+	res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
+	if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
+		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
+		goto fail;
+	}
+	res->sclk_dac = clk_get(dev, "sclk_dac");
+	if (IS_ERR_OR_NULL(res->sclk_dac)) {
+		dev_err(dev, "failed to get clock 'sclk_dac'\n");
+		goto fail;
+	}
+	res->ldo4 = regulator_get(dev, "vadc_3.3v_c210");
+	if (IS_ERR_OR_NULL(res->ldo4)) {
+		dev_err(dev, "failed to get regulator 'ldo4'\n");
+		goto fail;
+	}
+	/* regulator_enable(res->ldo4); */
+	tv_power_get();
+
+	/* XXX: fixed connetction between MIXER and HDMI */
+	clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
+	dbg_plat_regs();
+	return 0;
+fail:
+	dev_err(dev, "platform Mixer Init - failed\n");
+	mxr_deinit(dev);
+	return -ENODEV;
+}
+
+static void mxr_deinit(struct device *dev)
+{
+	struct mxr_plat_resource *res = &mxr_plat_resource;
+	dev_info(dev, "platform Mixer denit\n");
+	if (!IS_ERR_OR_NULL(res->ldo4)) {
+		tv_power_put();
+		/* regulator_disable(res->ldo4); */
+		regulator_put(res->ldo4);
+	}
+	if (!IS_ERR_OR_NULL(res->sclk_dac))
+		clk_put(res->sclk_dac);
+	if (!IS_ERR_OR_NULL(res->sclk_hdmi))
+		clk_put(res->sclk_hdmi);
+	if (!IS_ERR_OR_NULL(res->sclk_mixer))
+		clk_put(res->sclk_mixer);
+	if (!IS_ERR_OR_NULL(res->vp))
+		clk_put(res->vp);
+	if (!IS_ERR_OR_NULL(res->mixer))
+		clk_put(res->mixer);
+	memset(res, 0, sizeof *res);
+}
+
+static int mxr_power_setup(struct device *dev, int en)
+{
+	struct mxr_plat_resource *res = &mxr_plat_resource;
+	/* enable/disable clocks, power, and GPIOs */
+	if (en) {
+		dev_info(dev, "MIXER power-on\n");
+		/* turn MIXER power on */
+		/* tv_power_get(); */
+		regulator_enable(res->ldo4);
+		/* turn clocks on */
+		clk_enable(res->mixer);
+		clk_enable(res->vp);
+		clk_enable(res->sclk_mixer);
+		/* HDMI CEC (no support) */
+		/* SETREG(S5P_CLKGATE_IP_PERIR, ~0, 1 << 11); */
+		/* keep here */
+	} else {
+		dev_info(dev, "MIXER power-off\n");
+		/* turn clocks off */
+		clk_disable(res->sclk_mixer);
+		clk_disable(res->vp);
+		clk_disable(res->mixer);
+		/* turn MIXER power off */
+		regulator_disable(res->ldo4);
+		/* tv_power_put(); */
+	}
+	dbg_plat_regs();
+	return 0;
+}
+
+static struct mxr_platform_output output[] = {
+	{ .output_name = "S5P HDMI connector", .module_name = "s5p-hdmi" },
+};
+
+static struct mxr_platform_data mxr_pdata = {
+	.output = output,
+	.output_cnt = ARRAY_SIZE(output),
+	.init = mxr_init,
+	.deinit = mxr_deinit,
+	.power_setup = mxr_power_setup,
+};
+
+static void dbg_plat_regs(void)
+{
+	DBGREG(S5P_CLKSRC_TV);
+	DBGREG(S5P_CLKSRC_MASK_TV);
+	DBGREG(S5P_CLKGATE_IP_TV);
+	DBGREG(S5P_CLKGATE_IP_PERIL); /* remove (unknown?) */
+	DBGREG(S5P_CLKGATE_IP_PERIL); /* I2C HDMI (I2C8) remove */
+	DBGREG(S5P_CLKGATE_IP_PERIR); /* HDMI CEC remove (no support) */
+	DBGREG(S5P_CLKGATE_BLOCK); /* keep here */
+	DBGREG(S5P_CLKSRC_TOP0);
+	DBGREG(S5P_CLKSRC_TOP1);
+	DBGREG(S5P_HDMI_PHY_CONTROL);
+	DBGREG(S5P_CMU_CLKSTOP_TV_SYS_PWR);
+	DBGREG(S5P_CMU_RESET_TV_SYS_PWR);
+	DBGREG(S5P_TV_SYS_PWR);
+	DBGREG(S5P_TV_CONFIGURATION);
+	DBGREG(S5P_TV_STATUS);
+	DBGREG(S5P_CLKDIV_TV);
+}
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 0ba778b..76cfe4d 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -116,6 +116,10 @@
 
 #define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
 
+/* Set the default NR_IRQS */
+#define IRQ_MIXER		COMBINER_IRQ(36, 0)
+#define IRQ_TVENC		COMBINER_IRQ(36, 1)
+
 #define IRQ_EINT4		COMBINER_IRQ(37, 0)
 #define IRQ_EINT5		COMBINER_IRQ(37, 1)
 #define IRQ_EINT6		COMBINER_IRQ(37, 2)
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index 845b739..acc2a71 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -147,4 +147,30 @@
 #define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
 #define S5P_PA_MIPI_CSIS1		S5PV310_PA_MIPI_CSIS1
 
+/* CEC */
+#define S5PV210_PA_CEC		(0x100B0000)
+#define S5P_PA_CEC		S5PV210_PA_CEC
+#define S5P_SZ_CEC		SZ_4K
+
+/* TVOUT */
+#define S5PV210_PA_TVENC	(0x12C20000)
+#define S5P_PA_TVENC		S5PV210_PA_TVENC
+#define S5P_SZ_TVENC		SZ_64K
+
+#define S5PV210_PA_VP		(0x12C00000)
+#define S5P_PA_VP		S5PV210_PA_VP
+#define S5P_SZ_VP		SZ_64K
+
+#define S5PV210_PA_MIXER	(0x12C10000)
+#define S5P_PA_MIXER		S5PV210_PA_MIXER
+#define S5P_SZ_MIXER		SZ_64K
+
+#define S5PV210_PA_HDMI		(0x12D00000)
+#define S5P_PA_HDMI		S5PV210_PA_HDMI
+#define S5P_SZ_HDMI		SZ_1M
+
+#define S5PV210_I2C_HDMI_PHY	(0x138E0000)
+#define S5P_I2C_HDMI_PHY	S5PV210_I2C_HDMI_PHY
+#define S5P_I2C_HDMI_SZ_PHY	SZ_1K
+
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index b5c4ada..b1af66c 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -33,6 +33,7 @@
 #define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
 #define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
 #define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_TV			S5P_CLKREG(0x0C224)
 #define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
 #define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
 #define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
@@ -42,6 +43,7 @@
 
 #define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
 #define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
+#define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
 #define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
 #define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
 #define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
@@ -58,6 +60,7 @@
 
 #define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
 #define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
+#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
 #define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
 #define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
 #define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
@@ -67,6 +70,7 @@
 #define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
 
 #define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
+#define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
 #define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
 #define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
 #define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
@@ -164,4 +168,15 @@
 
 #define S5P_EPLL_CON			S5P_EPLL_CON0
 
+/* TVOUT related */
+#define S5P_TV_CONFIGURATION		S5P_PMUREG(0x03C20)
+#define S5P_TV_STATUS			S5P_PMUREG(0x03C24)
+#define S5P_TV_SYS_PWR			S5P_PMUREG(0x1384)
+#define S5P_CMU_CLKSTOP_TV_SYS_PWR	S5P_PMUREG(0x1144)
+#define S5P_CMU_RESET_TV_SYS_PWR	S5P_PMUREG(0x1164)
+
+#define S5P_HDMI_PHY_CONTROL		S5P_PMUREG(0x0700)
+#define S5P_CLKOUT_CMU_TOP		S5P_CLKREG(0x0CA00)
+#define S5P_PMU_DEBUG			S5P_PMUREG(0x0A00)
+
 #endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 6effbb4..a6b78d4 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -134,6 +134,8 @@ extern struct platform_device samsung_device_keypad;
 extern struct platform_device s5p_device_fimc0;
 extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
+extern struct platform_device s5p_device_hdmi;
+extern struct platform_device s5p_device_mixer;
 
 extern struct platform_device s5p_device_mipi_csis0;
 extern struct platform_device s5p_device_mipi_csis1;
-- 
1.7.3.5


  parent reply	other threads:[~2011-02-08  9:30 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
2011-02-08  9:30 ` [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy Tomasz Stanislawski
2011-02-09  7:14   ` Kukjin Kim
2011-02-08  9:30 ` [PATCH 2/5] universal: i2c: add I2C controller 8 (HDMIPHY) Tomasz Stanislawski
2011-02-09  6:54   ` Kukjin Kim
2011-02-08  9:30 ` [PATCH 3/5] v4l: add macro for 1080p59_54 preset Tomasz Stanislawski
2011-02-08  9:30 ` [PATCH 4/5] s5p-tv: add driver for HDMI output on S5PC210 platform Tomasz Stanislawski
2011-02-08  9:30 ` Tomasz Stanislawski [this message]
2011-02-09  6:40   ` [PATCH 5/5] s5pc210: add s5p-tv to platform devices Kukjin Kim
2011-02-08  9:47 ` [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Hans Verkuil
2011-02-08 10:08   ` Marek Szyprowski
2011-02-08 10:21   ` Tomasz Stanislawski
2011-02-08 15:28   ` Alex Deucher
2011-02-08 22:47     ` Andy Walls
2011-02-09  7:12       ` Alex Deucher
2011-02-09 19:00         ` Matt Turner
2011-02-09 19:43           ` Hans Verkuil
2011-02-09 23:59             ` Alex Deucher
2011-02-10  0:51         ` Andy Walls
2011-02-12 18:38           ` Alex Deucher
2011-02-09  8:59     ` Hans Verkuil
2011-02-09 17:55       ` Alex Deucher
2011-02-09 18:45         ` Corbin Simpson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1297157427-14560-6-git-send-email-t.stanislaws@samsung.com \
    --to=t.stanislaws@samsung.com \
    --cc=kyungmin.park@samsung.com \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.