Commit fbf05563 authored by Tomasz Stanislawski's avatar Tomasz Stanislawski Committed by Kukjin Kim
Browse files

ARM: S5P: add support for tv device



This patch adds all the resources for TV drivers and devices for Samsung
Exynos4 and S5PV210 platforms.

Signed-off-by: default avatarTomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
[m.szyprowski: squashed Exynos4 and S5PV210 patches and rewrote commit message]
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
parent c40e7e0d
Loading
Loading
Loading
Loading
+193 −1
Original line number Diff line number Diff line
@@ -88,6 +88,11 @@ static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
	return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
}

static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
{
	return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
}

static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
{
	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
@@ -128,6 +133,16 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
}

static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
{
	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
}

static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
{
	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
}

/* Core list of CMU_CPU side */

static struct clksrc_clk clk_mout_apll = {
@@ -453,6 +468,36 @@ static struct clk init_clocks_off[] = {
		.parent		= &clk_aclk_133.clk,
		.enable		= exynos4_clk_ip_fsys_ctrl,
		.ctrlbit	= (1 << 9),
	}, {
		.name		= "dac",
		.devname	= "s5p-sdo",
		.enable		= exynos4_clk_ip_tv_ctrl,
		.ctrlbit	= (1 << 2),
	}, {
		.name		= "mixer",
		.devname	= "s5p-mixer",
		.enable		= exynos4_clk_ip_tv_ctrl,
		.ctrlbit	= (1 << 1),
	}, {
		.name		= "vp",
		.devname	= "s5p-mixer",
		.enable		= exynos4_clk_ip_tv_ctrl,
		.ctrlbit	= (1 << 0),
	}, {
		.name		= "hdmi",
		.devname	= "exynos4-hdmi",
		.enable		= exynos4_clk_ip_tv_ctrl,
		.ctrlbit	= (1 << 3),
	}, {
		.name		= "hdmiphy",
		.devname	= "exynos4-hdmi",
		.enable		= exynos4_clk_hdmiphy_ctrl,
		.ctrlbit	= (1 << 0),
	}, {
		.name		= "dacphy",
		.devname	= "s5p-sdo",
		.enable		= exynos4_clk_dac_ctrl,
		.ctrlbit	= (1 << 0),
	}, {
		.name		= "sata",
		.parent		= &clk_aclk_133.clk,
@@ -793,6 +838,81 @@ static struct clksrc_sources clkset_mout_mfc = {
	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc_list),
};

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",
		.enable		= exynos4_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",
		.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",
		.enable		= exynos4_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",
		.enable		= exynos4_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,
};

static struct clksrc_clk clk_dout_mmc0 = {
	.clk		= {
		.name		= "dout_mmc0",
@@ -1132,6 +1252,71 @@ static struct clk_ops exynos4_fout_apll_ops = {
	.get_rate = exynos4_fout_apll_get_rate,
};

static u32 vpll_div[][8] = {
	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
};

static unsigned long exynos4_vpll_get_rate(struct clk *clk)
{
	return clk->rate;
}

static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
{
	unsigned int vpll_con0, vpll_con1 = 0;
	unsigned int i;

	/* Return if nothing changed */
	if (clk->rate == rate)
		return 0;

	vpll_con0 = __raw_readl(S5P_VPLL_CON0);
	vpll_con0 &= ~(0x1 << 27 |					\
			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);

	vpll_con1 = __raw_readl(S5P_VPLL_CON1);
	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);

	for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
		if (vpll_div[i][0] == rate) {
			vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
			vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
			vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
			vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
			vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT;
			vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT;
			vpll_con0 |= vpll_div[i][7] << 27;
			break;
		}
	}

	if (i == ARRAY_SIZE(vpll_div)) {
		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
				__func__);
		return -EINVAL;
	}

	__raw_writel(vpll_con0, S5P_VPLL_CON0);
	__raw_writel(vpll_con1, S5P_VPLL_CON1);

	/* Wait for VPLL lock */
	while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
		continue;

	clk->rate = rate;
	return 0;
}

static struct clk_ops exynos4_vpll_ops = {
	.get_rate = exynos4_vpll_get_rate,
	.set_rate = exynos4_vpll_set_rate,
};

void __init_or_cpufreq exynos4_setup_clocks(void)
{
	struct clk *xtal_clk;
@@ -1174,6 +1359,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
	clk_fout_apll.ops = &exynos4_fout_apll_ops;
	clk_fout_mpll.rate = mpll;
	clk_fout_epll.rate = epll;
	clk_fout_vpll.ops = &exynos4_vpll_ops;
	clk_fout_vpll.rate = vpll;

	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1201,7 +1387,10 @@ void __init_or_cpufreq exynos4_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 exynos4_register_clocks(void)
@@ -1213,6 +1402,9 @@ void __init exynos4_register_clocks(void)
	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
		s3c_register_clksrc(sysclks[ptr], 1);

	for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
		s3c_register_clksrc(sclk_tv[ptr], 1);

	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));

+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <plat/fimc-core.h>
#include <plat/iic-core.h>
#include <plat/reset.h>
#include <plat/tv-core.h>

#include <mach/regs-irq.h>
#include <mach/regs-pmu.h>
@@ -162,6 +163,7 @@ void __init exynos4_map_io(void)
	s3c_i2c2_setname("s3c2440-i2c");

	s5p_fb_setname(0, "exynos4-fb");
	s5p_hdmi_setname("exynos4-hdmi");
}

void __init exynos4_init_clocks(int xtal)
+3 −1
Original line number Diff line number Diff line
@@ -93,9 +93,11 @@
#define IRQ_2D			IRQ_SPI(89)
#define IRQ_PCIE		IRQ_SPI(90)

#define IRQ_MIXER		IRQ_SPI(91)
#define IRQ_HDMI		IRQ_SPI(92)
#define IRQ_IIC_HDMIPHY		IRQ_SPI(93)

#define IRQ_MFC			IRQ_SPI(94)
#define IRQ_SDO			IRQ_SPI(95)

#define IRQ_AUDIO_SS		IRQ_SPI(96)
#define IRQ_I2S0		IRQ_SPI(97)
+8 −0
Original line number Diff line number Diff line
@@ -112,6 +112,10 @@

#define EXYNOS4_PA_UART			0x13800000

#define EXYNOS4_PA_VP			0x12C00000
#define EXYNOS4_PA_MIXER		0x12C10000
#define EXYNOS4_PA_SDO			0x12C20000
#define EXYNOS4_PA_HDMI			0x12D00000
#define EXYNOS4_PA_IIC_HDMIPHY		0x138E0000

#define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
@@ -163,6 +167,10 @@
#define S5P_PA_TIMER			EXYNOS4_PA_TIMER
#define S5P_PA_EHCI			EXYNOS4_PA_EHCI

#define S5P_PA_SDO			EXYNOS4_PA_SDO
#define S5P_PA_VP			EXYNOS4_PA_VP
#define S5P_PA_MIXER			EXYNOS4_PA_MIXER
#define S5P_PA_HDMI			EXYNOS4_PA_HDMI
#define S5P_PA_IIC_HDMIPHY		EXYNOS4_PA_IIC_HDMIPHY

#define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
+6 −0
Original line number Diff line number Diff line
@@ -35,9 +35,15 @@
#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)

#define S5P_HDMI_PHY_CONTROL			S5P_PMUREG(0x0700)
#define S5P_HDMI_PHY_ENABLE			(1 << 0)

#define S5P_USBHOST_PHY_CONTROL			S5P_PMUREG(0x0708)
#define S5P_USBHOST_PHY_ENABLE			(1 << 0)

#define S5P_DAC_PHY_CONTROL			S5P_PMUREG(0x070C)
#define S5P_DAC_PHY_ENABLE			(1 << 0)

#define S5P_MIPI_DPHY_CONTROL(n)		S5P_PMUREG(0x0710 + (n) * 4)
#define S5P_MIPI_DPHY_ENABLE			(1 << 0)
#define S5P_MIPI_DPHY_SRESETN			(1 << 1)
Loading