* [PATCH V6 4/5] video: s3c-fb: Add support EXYNOS4 FIMD
From: Jingoo Han @ 2011-06-22 12:18 UTC (permalink / raw)
To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev,
Jonghun Han
Cc: Anand Kumar N, Thomas Abraham, Sylwester Nawrocki,
Marek Szyprowski, Kyungmin Park, Inki Dae, ARM Linux, Ben Dooks,
Jingoo Han
This patch adds struct s3c_fb_driverdata s3c_fb_data_exynos4 for EXYNOS4
and adds lcd clock gating support.
FIMD driver needs two clocks for FIMD IP and LCD pixel clock. Previously,
both clocks are provided by using bus clock such as HCLK. However, EXYNOS4
can not select HCLK for LCD pixel clock because the EXYNOS4 FIMD IP does not
have the CLKSEL bit of VIDCON0. So, FIMD driver should provide the lcd clock
using SCLK_FIMD as LCD pixel clock for EXYNOS4.
The driver selects enabling lcd clock according to has_clksel which means
the CLKSEL bit of VIDCON0. If there is has_clksel, the driver will not
enable the lcd clock using SCLK_FIMD because bus clock using HCLK is used
a LCD pixel clock.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/video/Kconfig | 2 +-
drivers/video/s3c-fb.c | 88 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 549b960..963b8b7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2027,7 +2027,7 @@ config FB_TMIO_ACCELL
config FB_S3C
tristate "Samsung S3C framebuffer support"
- depends on FB && S3C_DEV_FB
+ depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 4aecf21..cb0d3ea 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -81,6 +81,7 @@ struct s3c_fb;
* @palette: Address of palette memory, or 0 if none.
* @has_prtcon: Set if has PRTCON register.
* @has_shadowcon: Set if has SHADOWCON register.
+ * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
*/
struct s3c_fb_variant {
unsigned int is_2443:1;
@@ -98,6 +99,7 @@ struct s3c_fb_variant {
unsigned int has_prtcon:1;
unsigned int has_shadowcon:1;
+ unsigned int has_clksel:1;
};
/**
@@ -186,6 +188,7 @@ struct s3c_fb_vsync {
* @dev: The device that we bound to, for printing, etc.
* @regs_res: The resource we claimed for the IO registers.
* @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
+ * @lcd_clk: The clk (sclk) feeding pixclk.
* @regs: The mapped hardware registers.
* @variant: Variant information for this hardware.
* @enabled: A bitmask of enabled hardware windows.
@@ -200,6 +203,7 @@ struct s3c_fb {
struct device *dev;
struct resource *regs_res;
struct clk *bus_clk;
+ struct clk *lcd_clk;
void __iomem *regs;
struct s3c_fb_variant variant;
@@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
*/
static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
{
- unsigned long clk = clk_get_rate(sfb->bus_clk);
+ unsigned long clk;
unsigned long long tmp;
unsigned int result;
+ if (sfb->variant.has_clksel)
+ clk = clk_get_rate(sfb->bus_clk);
+ else
+ clk = clk_get_rate(sfb->lcd_clk);
+
tmp = (unsigned long long)clk;
tmp *= pixclk;
@@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
clk_enable(sfb->bus_clk);
+ if (!sfb->variant.has_clksel) {
+ sfb->lcd_clk = clk_get(dev, "sclk_fimd");
+ if (IS_ERR(sfb->lcd_clk)) {
+ dev_err(dev, "failed to get lcd clock\n");
+ ret = PTR_ERR(sfb->lcd_clk);
+ goto err_bus_clk;
+ }
+
+ clk_enable(sfb->lcd_clk);
+ }
+
pm_runtime_enable(sfb->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "failed to find registers\n");
ret = -ENOENT;
- goto err_clk;
+ goto err_lcd_clk;
}
sfb->regs_res = request_mem_region(res->start, resource_size(res),
@@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
if (!sfb->regs_res) {
dev_err(dev, "failed to claim register region\n");
ret = -ENOENT;
- goto err_clk;
+ goto err_lcd_clk;
}
sfb->regs = ioremap(res->start, resource_size(res));
@@ -1450,7 +1470,13 @@ err_ioremap:
err_req_region:
release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
-err_clk:
+err_lcd_clk:
+ if (!sfb->variant.has_clksel) {
+ clk_disable(sfb->lcd_clk);
+ clk_put(sfb->lcd_clk);
+ }
+
+err_bus_clk:
clk_disable(sfb->bus_clk);
clk_put(sfb->bus_clk);
@@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
iounmap(sfb->regs);
+ if (!sfb->variant.has_clksel) {
+ clk_disable(sfb->lcd_clk);
+ clk_put(sfb->lcd_clk);
+ }
+
clk_disable(sfb->bus_clk);
clk_put(sfb->bus_clk);
@@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev)
s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
}
+ if (!sfb->variant.has_clksel)
+ clk_disable(sfb->lcd_clk);
+
clk_disable(sfb->bus_clk);
return 0;
}
@@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev)
clk_enable(sfb->bus_clk);
+ if (!sfb->variant.has_clksel)
+ clk_enable(sfb->lcd_clk);
+
/* setup gpio and output polarity controls */
pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
@@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
}
+ if (!sfb->variant.has_clksel)
+ clk_disable(sfb->lcd_clk);
+
clk_disable(sfb->bus_clk);
return 0;
}
@@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev)
clk_enable(sfb->bus_clk);
+ if (!sfb->variant.has_clksel)
+ clk_enable(sfb->lcd_clk);
+
/* setup gpio and output polarity controls */
pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
@@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = {
},
.has_prtcon = 1,
+ .has_clksel = 1,
},
.win[0] = &s3c_fb_data_64xx_wins[0],
.win[1] = &s3c_fb_data_64xx_wins[1],
@@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
},
.has_prtcon = 1,
+ .has_clksel = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1815,6 +1860,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
},
.has_shadowcon = 1,
+ .has_clksel = 1,
+ },
+ .win[0] = &s3c_fb_data_s5p_wins[0],
+ .win[1] = &s3c_fb_data_s5p_wins[1],
+ .win[2] = &s3c_fb_data_s5p_wins[2],
+ .win[3] = &s3c_fb_data_s5p_wins[3],
+ .win[4] = &s3c_fb_data_s5p_wins[4],
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
+ .variant = {
+ .nr_windows = 5,
+ .vidtcon = VIDTCON0,
+ .wincon = WINCON(0),
+ .winmap = WINxMAP(0),
+ .keycon = WKEYCON,
+ .osd = VIDOSD_BASE,
+ .osd_stride = 16,
+ .buf_start = VIDW_BUF_START(0),
+ .buf_size = VIDW_BUF_SIZE(0),
+ .buf_end = VIDW_BUF_END(0),
+
+ .palette = {
+ [0] = 0x2400,
+ [1] = 0x2800,
+ [2] = 0x2c00,
+ [3] = 0x3000,
+ [4] = 0x3400,
+ },
+
+ .has_shadowcon = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
[0] = 0x400,
[1] = 0x800,
},
+ .has_clksel = 1,
},
.win[0] = &(struct s3c_fb_win_variant) {
.palette_sz = 256,
@@ -1870,6 +1947,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
.name = "s5pv210-fb",
.driver_data = (unsigned long)&s3c_fb_data_s5pv210,
}, {
+ .name = "exynos4-fb",
+ .driver_data = (unsigned long)&s3c_fb_data_exynos4,
+ }, {
.name = "s3c2443-fb",
.driver_data = (unsigned long)&s3c_fb_data_s3c2443,
},
--
1.7.1
^ permalink raw reply related
* [PATCH V6 3/5] ARM: EXYNOS4: Add platform device and helper functions for FIMD
From: Jingoo Han @ 2011-06-22 12:17 UTC (permalink / raw)
To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
Cc: Anand Kumar N, Thomas Abraham, Sylwester Nawrocki,
Marek Szyprowski, Kyungmin Park, Inki Dae, ARM Linux, Ben Dooks,
Signed-off-by: Jonghun Han, Jingoo Han
From: Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
This patch adds platform device s5p_device_fimd0 for EXYNOS4 FIMD0.
EXYNOS4 has two FIMDs(FIMD0, FIMD1). FIMD1 will be added later.
Some definitions used to enable EXYNOS4 FIMD0 are added.
Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
arch/arm/mach-exynos4/Kconfig | 9 +++
arch/arm/mach-exynos4/Makefile | 1 +
arch/arm/mach-exynos4/cpu.c | 4 +-
arch/arm/mach-exynos4/include/mach/regs-fb.h | 21 +++++++
arch/arm/mach-exynos4/setup-fimd0.c | 75 ++++++++++++++++++++++++++
arch/arm/plat-s5p/Kconfig | 5 ++
arch/arm/plat-s5p/Makefile | 1 +
arch/arm/plat-s5p/dev-fimd0.c | 67 +++++++++++++++++++++++
arch/arm/plat-samsung/include/plat/devs.h | 1 +
arch/arm/plat-samsung/include/plat/fb-core.h | 15 +++++
arch/arm/plat-samsung/include/plat/fb.h | 24 ++++++++
11 files changed, 222 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-exynos4/include/mach/regs-fb.h
create mode 100644 arch/arm/mach-exynos4/setup-fimd0.c
create mode 100644 arch/arm/plat-s5p/dev-fimd0.c
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..2024f50 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -25,6 +25,11 @@ config EXYNOS4_DEV_AHCI
help
Compile in platform device definitions for AHCI
+config EXYNOS4_SETUP_FIMD0
+ bool
+ help
+ Common setup code for FIMD0.
+
config EXYNOS4_DEV_PD
bool
help
@@ -103,6 +108,7 @@ menu "EXYNOS4 Machines"
config MACH_SMDKC210
bool "SMDKC210"
select CPU_EXYNOS4210
+ select S5P_DEV_FIMD0
select S3C_DEV_RTC
select S3C_DEV_WDT
select S3C_DEV_I2C1
@@ -112,6 +118,7 @@ config MACH_SMDKC210
select S3C_DEV_HSMMC3
select EXYNOS4_DEV_PD
select EXYNOS4_DEV_SYSMMU
+ select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_SDHCI
help
@@ -120,6 +127,7 @@ config MACH_SMDKC210
config MACH_SMDKV310
bool "SMDKV310"
select CPU_EXYNOS4210
+ select S5P_DEV_FIMD0
select S3C_DEV_RTC
select S3C_DEV_WDT
select S3C_DEV_I2C1
@@ -130,6 +138,7 @@ config MACH_SMDKV310
select SAMSUNG_DEV_KEYPAD
select EXYNOS4_DEV_PD
select EXYNOS4_DEV_SYSMMU
+ select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_KEYPAD
select EXYNOS4_SETUP_SDHCI
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index 60fe5ec..96472f1 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C2) += setup-i2c2.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C3) += setup-i2c3.o
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 9babe44..778a5b0 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -19,9 +19,10 @@
#include <plat/cpu.h>
#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/fb-core.h>
#include <plat/exynos4.h>
#include <plat/sdhci.h>
-#include <plat/devs.h>
#include <plat/fimc-core.h>
#include <mach/regs-irq.h>
@@ -132,6 +133,7 @@ void __init exynos4_map_io(void)
s3c_fimc_setname(1, "exynos4-fimc");
s3c_fimc_setname(2, "exynos4-fimc");
s3c_fimc_setname(3, "exynos4-fimc");
+ s5p_fb_setname(0, "exynos4-fb"); /* FIMD0 */
}
void __init exynos4_init_clocks(int xtal)
diff --git a/arch/arm/mach-exynos4/include/mach/regs-fb.h b/arch/arm/mach-exynos4/include/mach/regs-fb.h
new file mode 100644
index 0000000..f320105
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-fb.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Dummy framebuffer to allow build for the moment.
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_MACH_REGS_FB_H
+#define __ASM_ARCH_MACH_REGS_FB_H __FILE__
+
+#include <plat/regs-fb-v4.h>
+
+static inline unsigned int s3c_fb_pal_reg(unsigned int window, int reg)
+{
+ return 0x2400 + (window * 256 * 4) + reg;
+}
+
+#endif /* __ASM_ARCH_MACH_REGS_FB_H */
diff --git a/arch/arm/mach-exynos4/setup-fimd0.c b/arch/arm/mach-exynos4/setup-fimd0.c
new file mode 100644
index 0000000..3295615
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-fimd0.c
@@ -0,0 +1,75 @@
+/* linux/arch/arm/mach-exynos4/setup-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Base Exynos4 FIMD 0 configuration
+ *
+ * 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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+
+#include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-clock.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+void exynos4_fimd0_gpio_setup_24bpp(void)
+{
+ unsigned int reg = 0;
+
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
+
+ /*
+ * Set DISPLAY_CONTROL register for Display path selection.
+ *
+ * DISPLAY_CONTROL[1:0]
+ * ---------------------
+ * 00 | MIE
+ * 01 | MDINE
+ * 10 | FIMD : selected
+ * 11 | FIMD
+ */
+ reg = __raw_readl(S3C_VA_SYS + 0x0210);
+ reg |= (1 << 1);
+ __raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
+
+int __init exynos4_fimd0_setup_clock(struct device *dev, const char *parent,
+ unsigned long clk_rate)
+{
+ struct clk *clk_parent;
+ struct clk *sclk;
+
+ sclk = clk_get(dev, "sclk_fimd");
+ if (IS_ERR(sclk))
+ return PTR_ERR(sclk);
+
+ clk_parent = clk_get(NULL, parent);
+ if (IS_ERR(clk_parent)) {
+ clk_put(sclk);
+ return PTR_ERR(clk_parent);
+ }
+
+ clk_set_parent(sclk, clk_parent);
+ if (!clk_rate)
+ clk_rate = 134000000UL;
+ clk_set_rate(sclk, clk_rate);
+
+ clk_put(sclk);
+ clk_put(clk_parent);
+
+ return 0;
+}
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index e98f5c5..46de16e 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -70,6 +70,11 @@ config S5P_DEV_FIMC3
help
Compile in platform device definitions for FIMC controller 3
+config S5P_DEV_FIMD0
+ bool
+ help
+ Compile in platform device definitions for FIMD controller 0
+
config S5P_DEV_ONENAND
bool
help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index e234cc4..eec7e24 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o
+obj-$(CONFIG_S5P_DEV_FIMD0) += dev-fimd0.o
obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
diff --git a/arch/arm/plat-s5p/dev-fimd0.c b/arch/arm/plat-s5p/dev-fimd0.c
new file mode 100644
index 0000000..9e7176c
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimd0.c
@@ -0,0 +1,67 @@
+/* linux/arch/arm/plat-s5p/dev-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Core file for Samsung Display Controller (FIMD) driver
+ *
+ * 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 <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 <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/fb.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+static struct resource s5p_fimd0_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMD0,
+ .end = S5P_PA_FIMD0 + SZ_32K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMD0_VSYNC,
+ .end = IRQ_FIMD0_VSYNC,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_FIMD0_FIFO,
+ .end = IRQ_FIMD0_FIFO,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = IRQ_FIMD0_SYSTEM,
+ .end = IRQ_FIMD0_SYSTEM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 fimd0_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimd0 = {
+ .name = "s5p-fb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_fimd0_resource),
+ .resource = s5p_fimd0_resource,
+ .dev = {
+ .dma_mask = &fimd0_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+ s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+ &s5p_device_fimd0);
+}
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 4af108f..370bd2b 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -45,6 +45,7 @@ extern struct platform_device s3c64xx_device_ac97;
extern struct platform_device s3c_device_ts;
extern struct platform_device s3c_device_fb;
+extern struct platform_device s5p_device_fimd0;
extern struct platform_device s3c_device_ohci;
extern struct platform_device s3c_device_lcd;
extern struct platform_device s3c_device_wdt;
diff --git a/arch/arm/plat-samsung/include/plat/fb-core.h b/arch/arm/plat-samsung/include/plat/fb-core.h
index bca383e..6abcbf1 100644
--- a/arch/arm/plat-samsung/include/plat/fb-core.h
+++ b/arch/arm/plat-samsung/include/plat/fb-core.h
@@ -26,4 +26,19 @@ static inline void s3c_fb_setname(char *name)
#endif
}
+/* Re-define device name depending on support. */
+static inline void s5p_fb_setname(int id, char *name)
+{
+ switch (id) {
+#ifdef CONFIG_S5P_DEV_FIMD0
+ case 0:
+ s5p_device_fimd0.name = name;
+ break;
+#endif
+ default:
+ printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
+ break;
+ }
+}
+
#endif /* __ASM_PLAT_FB_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index cb3ca3a..a7b1c18 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -74,6 +74,14 @@ struct s3c_fb_platdata {
extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
/**
+ * s5p_fimd0_set_platdata() - Setup the FB device with platform data.
+ * @pd: The platform data to set. The data is copied from the passed structure
+ * so the machine data can mark the data __initdata so that any unused
+ * machines will end up dumping their data at runtime.
+ */
+extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
+
+/**
* s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface.
@@ -94,4 +102,20 @@ extern void s5pc100_fb_gpio_setup_24bpp(void);
*/
extern void s5pv210_fb_gpio_setup_24bpp(void);
+/**
+ * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
+ */
+extern void exynos4_fimd0_gpio_setup_24bpp(void);
+
+/**
+ * exynos4_fimd0_setup_clock() = Exynos4 setup function for parent clock.
+ * @dev: device pointer
+ * @parent: parent clock used for LCD pixel clock
+ * @clk_rate: clock rate for parent clock
+ */
+int __init exynos4_fimd0_setup_clock(struct device *dev, const char *parent,
+ unsigned long clk_rate);
+
#endif /* __PLAT_S3C_FB_H */
--
1.7.1
^ permalink raw reply related
* [PATCH V6 2/5] ARM: EXYNOS4: Add FIMD resource definition
From: Jingoo Han @ 2011-06-22 12:16 UTC (permalink / raw)
To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev
Cc: Anand Kumar N, Thomas Abraham, Sylwester Nawrocki,
Marek Szyprowski, Kyungmin Park, Inki Dae, ARM Linux, Ben Dooks,
Jonghun Han, Jingoo Han
From: Jonghun Han <jonghun.han@samsung.com>
This patch adds resource definitions for EXYNOS4 FIMD.
IRQ and SFR definitions are added.
Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
arch/arm/mach-exynos4/include/mach/irqs.h | 8 ++++++++
arch/arm/mach-exynos4/include/mach/map.h | 5 +++++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 5d03730..2cd2090 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -73,6 +73,14 @@
#define IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6)
#define IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7)
+#define IRQ_FIMD0_FIFO COMBINER_IRQ(11, 0)
+#define IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1)
+#define IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2)
+
+#define IRQ_FIMD1_FIFO COMBINER_IRQ(12, 0)
+#define IRQ_FIMD1_VSYNC COMBINER_IRQ(12, 1)
+#define IRQ_FIMD1_SYSTEM COMBINER_IRQ(12, 2)
+
#define IRQ_PDMA0 COMBINER_IRQ(21, 0)
#define IRQ_PDMA1 COMBINER_IRQ(21, 1)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 0009e77..94006f7 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -93,6 +93,9 @@
#define EXYNOS4_PA_MIPI_CSIS0 0x11880000
#define EXYNOS4_PA_MIPI_CSIS1 0x11890000
+#define EXYNOS4_PA_FIMD0 0x11C00000
+#define EXYNOS4_PA_FIMD1 0x12000000
+
#define EXYNOS4_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000))
#define EXYNOS4_PA_SATA 0x12560000
@@ -140,6 +143,8 @@
#define S5P_PA_FIMC3 EXYNOS4_PA_FIMC3
#define S5P_PA_MIPI_CSIS0 EXYNOS4_PA_MIPI_CSIS0
#define S5P_PA_MIPI_CSIS1 EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_FIMD0 EXYNOS4_PA_FIMD0
+#define S5P_PA_FIMD1 EXYNOS4_PA_FIMD1
#define S5P_PA_ONENAND EXYNOS4_PA_ONENAND
#define S5P_PA_ONENAND_DMA EXYNOS4_PA_ONENAND_DMA
#define S5P_PA_SDRAM EXYNOS4_PA_SDRAM
--
1.7.1
^ permalink raw reply related
* [PATCH V6 1/5] ARM: EXYNOS4: Change clock name for FIMD
From: Jingoo Han @ 2011-06-22 12:16 UTC (permalink / raw)
To: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev,
Jonghun Han
Cc: Anand Kumar N, Thomas Abraham, Sylwester Nawrocki,
Marek Szyprowski, Kyungmin Park, Inki Dae, ARM Linux, Ben Dooks,
Jingoo Han
This patch changes clock name for FIMD from "fimd" to "lcd".
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
arch/arm/mach-exynos4/clock.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 871f9d5..12e6853 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -433,12 +433,12 @@ static struct clk init_clocks_off[] = {
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 3),
}, {
- .name = "fimd",
+ .name = "lcd",
.id = 0,
.enable = exynos4_clk_ip_lcd0_ctrl,
.ctrlbit = (1 << 0),
}, {
- .name = "fimd",
+ .name = "lcd",
.id = 1,
.enable = exynos4_clk_ip_lcd1_ctrl,
.ctrlbit = (1 << 0),
--
1.7.1
^ permalink raw reply related
* [PATCH 8/8] OMAP4: DSS: Rename hdmi_omap4_panel.c to hdmi_panel.c
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
As the panel driver will remain generic across OMAP's renaming it to
hdmi_panel.c
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/omap2/dss/Makefile | 2 +-
.../omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
rename drivers/video/omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} (99%)
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 10d9d3b..37d537c 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
- hdmi_omap4_panel.o
+ hdmi_panel.o
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
similarity index 99%
rename from drivers/video/omap2/dss/hdmi_omap4_panel.c
rename to drivers/video/omap2/dss/hdmi_panel.c
index 7d4f2bd..e30182f 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -1,5 +1,5 @@
/*
- * hdmi_omap4_panel.c
+ * hdmi_panel.c
*
* HDMI library support functions for TI OMAP4 processors.
*
--
1.7.5.4
^ permalink raw reply related
* [PATCH 7/8] HDMI: Move HDMI IP Library from OMAP DSS to common
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
Moving support of HDMI IP library from OMAP4 DSS directory to Video directory as
HDMI IP present in both TI OMAP4, TI81xx, TI38xx Processor,Thus the library in
DSS can be reused in TI81xx, TI38xx processors.
Although both these processors have different Display subsytem HDMI IP remains
the same , thus to promote the reuse of code across SoC's, IP library named
hdmi_4xxx_ip.c is moved from DSS to video directory.Also functions are renamed
as the module has to export and the function name would be global symbol table,
hence renaming to function name specific to the library module.
With this approach Independent of their(OMAP/TI81xx/TI38xx) respective DSS, generic IP
configurations will be done using this library.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/Kconfig | 7 ++++++
drivers/video/Makefile | 1 +
drivers/video/{omap2/dss => }/hdmi_ti_4xxx_ip.c | 24 ++++++++++++++++++++++-
drivers/video/{omap2/dss => }/hdmi_ti_4xxx_ip.h | 5 ++++
drivers/video/omap2/dss/Kconfig | 1 +
drivers/video/omap2/dss/Makefile | 1 -
6 files changed, 37 insertions(+), 2 deletions(-)
rename drivers/video/{omap2/dss => }/hdmi_ti_4xxx_ip.c (97%)
rename drivers/video/{omap2/dss => }/hdmi_ti_4xxx_ip.h (98%)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e6a8d8c..2204fef 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2341,6 +2341,13 @@ config FB_PUV3_UNIGFX
Choose this option if you want to use the Unigfx device as a
framebuffer device. Without the support of PCI & AGP.
+config HDMI_TI_4XXX_IP
+ tristate
+ default n
+ help
+ HDMI Library Interface , for TI OMAP4/Netra IP.
+ See http://www.hdmi.org/ for HDMI specification.
+
source "drivers/video/omap/Kconfig"
source "drivers/video/omap2/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 2ea44b6..3118055 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
obj-$(CONFIG_FB_OMAP) += omap/
obj-y += omap2/
+obj-$(CONFIG_HDMI_TI_4XXX_IP) += hdmi_ti_4xxx_ip.o
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
diff --git a/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c b/drivers/video/hdmi_ti_4xxx_ip.c
similarity index 97%
rename from drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
rename to drivers/video/hdmi_ti_4xxx_ip.c
index 51dc2a8..c8ea145 100644
--- a/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
+++ b/drivers/video/hdmi_ti_4xxx_ip.c
@@ -29,7 +29,6 @@
#include <linux/string.h>
#include "hdmi_ti_4xxx_ip.h"
-#include "dss.h"
static inline void hdmi_write_reg(void __iomem *base_addr,
const struct hdmi_reg idx, u32 val)
@@ -179,6 +178,7 @@ if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
return 0;
}
+EXPORT_SYMBOL(hdmi_ti_4xxx_set_pll_pwr);
static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
{
@@ -264,6 +264,8 @@ void hdmi_ti_4xxx_phy_off(struct hdmi_ip_data *ip_data)
{
hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
}
+EXPORT_SYMBOL(hdmi_ti_4xxx_phy_init);
+EXPORT_SYMBOL(hdmi_ti_4xxx_phy_off);
static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
u8 *pedid, int ext)
@@ -404,6 +406,7 @@ int read_ti_4xxx_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length)
}
return 0;
}
+EXPORT_SYMBOL(read_ti_4xxx_edid);
static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
struct hdmi_core_infoframe_avi *avi_cfg,
@@ -631,6 +634,7 @@ void hdmi_ti_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
{
REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
}
+EXPORT_SYMBOL(hdmi_ti_4xxx_wp_video_start);
static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
struct omap_video_timings *timings, struct hdmi_config *param)
@@ -779,3 +783,21 @@ void hdmi_ti_4xxx_basic_configure(struct hdmi_ip_data *ip_data,
repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
hdmi_core_av_packet_config(ip_data, repeat_cfg);
}
+EXPORT_SYMBOL(hdmi_ti_4xxx_basic_configure);
+
+static int __init hdmi_ti_4xxx_init(void)
+{
+ return 0;
+}
+
+static void __exit hdmi_ti_4xxx_exit(void)
+{
+
+}
+
+module_init(hdmi_ti_4xxx_init);
+module_exit(hdmi_ti_4xxx_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("hdmi_ti_4xxx_ip module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.h b/drivers/video/hdmi_ti_4xxx_ip.h
similarity index 98%
rename from drivers/video/omap2/dss/hdmi_ti_4xxx_ip.h
rename to drivers/video/hdmi_ti_4xxx_ip.h
index 97e573c..b0b8c92 100644
--- a/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.h
+++ b/drivers/video/hdmi_ti_4xxx_ip.h
@@ -183,6 +183,11 @@ struct hdmi_reg { u16 idx; };
#define HDMI_TXPHY_POWER_CTRL HDMI_REG(0x8)
#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_REG(0xC)
+#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
+#define FLD_MOD(orig, val, start, end) \
+ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
#define REG_FLD_MOD(base, idx, val, start, end) \
hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
val, start, end))
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 0d12524..8f9420e 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -63,6 +63,7 @@ config OMAP2_DSS_VENC
config OMAP4_DSS_HDMI
bool "HDMI support"
depends on ARCH_OMAP4
+ select HDMI_TI_4XXX_IP
default y
help
HDMI Interface. This adds the High Definition Multimedia Interface.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index cf967e0..10d9d3b 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -6,5 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
- hdmi_ti_4xxx_ip.o \
hdmi_omap4_panel.o
--
1.7.5.4
^ permalink raw reply related
* [PATCH 6/8] OMAP4: DSS: HDMI: Rename the functions in HDMI IP
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
Functions that are included in the generic video include of HDMI TI OMAP4, TI8xx
etc IP library is renamed to have IP specific names so that it will not conflict
with similar function from other IP.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/omap2/dss/hdmi.c | 18 +++++++++---------
drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c | 18 +++++++++---------
include/video/hdmi_ti_4xxx_ip.h | 14 +++++++-------
3 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 1bd98d9..d42bb5d 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -395,7 +395,7 @@ static void hdmi_read_edid(struct omap_video_timings *dp)
memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
if (!hdmi.edid_set)
- ret = read_edid(&hdmi.hdmi_data, hdmi.edid,
+ ret = read_ti_4xxx_edid(&hdmi.hdmi_data, hdmi.edid,
HDMI_EDID_MAX_LENGTH);
if (!ret) {
if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
@@ -508,16 +508,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi_compute_pll(dssdev, phy, &pll_data);
- hdmi_wp_video_start(&hdmi.hdmi_data, 0);
+ hdmi_ti_4xxx_wp_video_start(&hdmi.hdmi_data, 0);
/* config the PLL and PHY hdmi_set_pll_pwrfirst */
- r = hdmi_pll_program(&hdmi.hdmi_data, &pll_data);
+ r = hdmi_ti_4xxx_pll_program(&hdmi.hdmi_data, &pll_data);
if (r) {
DSSDBG("Failed to lock PLL\n");
goto err;
}
- r = hdmi_phy_init(&hdmi.hdmi_data);
+ r = hdmi_ti_4xxx_phy_init(&hdmi.hdmi_data);
if (r) {
DSSDBG("Failed to start PHY\n");
goto err;
@@ -525,7 +525,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi.cfg.cm.mode = hdmi.mode;
hdmi.cfg.cm.code = hdmi.code;
- hdmi_basic_configure(&hdmi.hdmi_data, &hdmi.cfg);
+ hdmi_ti_4xxx_basic_configure(&hdmi.hdmi_data, &hdmi.cfg);
/* Make selection of HDMI in DSS */
dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
@@ -547,7 +547,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1);
- hdmi_wp_video_start(&hdmi.hdmi_data, 1);
+ hdmi_ti_4xxx_wp_video_start(&hdmi.hdmi_data, 1);
return 0;
err:
@@ -559,9 +559,9 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
{
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
- hdmi_wp_video_start(&hdmi.hdmi_data, 0);
- hdmi_phy_off(&hdmi.hdmi_data);
- hdmi_set_pll_pwr(&hdmi.hdmi_data, HDMI_PLLPWRCMD_ALLOFF);
+ hdmi_ti_4xxx_wp_video_start(&hdmi.hdmi_data, 0);
+ hdmi_ti_4xxx_phy_off(&hdmi.hdmi_data);
+ hdmi_ti_4xxx_set_pll_pwr(&hdmi.hdmi_data, HDMI_PLLPWRCMD_ALLOFF);
hdmi_runtime_put();
hdmi.edid_set = 0;
diff --git a/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c b/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
index b4e8875..51dc2a8 100644
--- a/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
+++ b/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
@@ -165,7 +165,7 @@ static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
}
/* PLL_PWR_CMD */
-int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
+int hdmi_ti_4xxx_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
{
/* Command for power control of HDMI PLL */
REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
@@ -195,17 +195,17 @@ static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
return 0;
}
-int hdmi_pll_program(struct hdmi_ip_data *ip_data,
+int hdmi_ti_4xxx_pll_program(struct hdmi_ip_data *ip_data,
struct hdmi_pll_info *fmt)
{
u16 r = 0;
enum hdmi_clk_refsel refsel;
- r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
+ r = hdmi_ti_4xxx_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
if (r)
return r;
- r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
+ r = hdmi_ti_4xxx_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
if (r)
return r;
@@ -222,7 +222,7 @@ int hdmi_pll_program(struct hdmi_ip_data *ip_data,
return 0;
}
-int hdmi_phy_init(struct hdmi_ip_data *ip_data)
+int hdmi_ti_4xxx_phy_init(struct hdmi_ip_data *ip_data)
{
u16 r = 0;
@@ -260,7 +260,7 @@ int hdmi_phy_init(struct hdmi_ip_data *ip_data)
return 0;
}
-void hdmi_phy_off(struct hdmi_ip_data *ip_data)
+void hdmi_ti_4xxx_phy_off(struct hdmi_ip_data *ip_data)
{
hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
}
@@ -376,7 +376,7 @@ static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
return 0;
}
-int read_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length)
+int read_ti_4xxx_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length)
{
int r = 0, n = 0, i = 0;
int max_ext_blocks = (max_length / 128) - 1;
@@ -627,7 +627,7 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
}
-void hdmi_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
+void hdmi_ti_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
{
REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
}
@@ -694,7 +694,7 @@ static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
}
-void hdmi_basic_configure(struct hdmi_ip_data *ip_data,
+void hdmi_ti_4xxx_basic_configure(struct hdmi_ip_data *ip_data,
struct hdmi_config *cfg)
{
/* HDMI */
diff --git a/include/video/hdmi_ti_4xxx_ip.h b/include/video/hdmi_ti_4xxx_ip.h
index 3355f40..d354280 100644
--- a/include/video/hdmi_ti_4xxx_ip.h
+++ b/include/video/hdmi_ti_4xxx_ip.h
@@ -82,13 +82,13 @@ struct hdmi_pll_info {
u16 dcofreq;
};
-int hdmi_phy_init(struct hdmi_ip_data *ip_data);
-void hdmi_phy_off(struct hdmi_ip_data *ip_data);
-int read_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length);
-void hdmi_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
-int hdmi_pll_program(struct hdmi_ip_data *ip_data,
+int hdmi_ti_4xxx_phy_init(struct hdmi_ip_data *ip_data);
+void hdmi_ti_4xxx_phy_off(struct hdmi_ip_data *ip_data);
+int read_ti_4xxx_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length);
+void hdmi_ti_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
+int hdmi_ti_4xxx_pll_program(struct hdmi_ip_data *ip_data,
struct hdmi_pll_info *fmt);
-int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val);
-void hdmi_basic_configure(struct hdmi_ip_data *ip_data,
+int hdmi_ti_4xxx_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val);
+void hdmi_ti_4xxx_basic_configure(struct hdmi_ip_data *ip_data,
struct hdmi_config *cfg);
#endif
--
1.7.5.4
^ permalink raw reply related
* [PATCH 5/8] OMAP4: DSS2: HDMI: Split the HDMI driver to DSS and IP
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
Splitting HDMI IP dependent IP configuring code from HDMI DSS dependent code and
moving to a new IP file.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/omap2/dss/Makefile | 1 +
drivers/video/omap2/dss/hdmi.c | 751 -------------------
drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c | 781 ++++++++++++++++++++
.../video/omap2/dss/{hdmi.h => hdmi_ti_4xxx_ip.h} | 9 +-
include/video/hdmi_ti_4xxx_ip.h | 10 +
5 files changed, 797 insertions(+), 755 deletions(-)
create mode 100644 drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
rename drivers/video/omap2/dss/{hdmi.h => hdmi_ti_4xxx_ip.h} (99%)
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 10d9d3b..cf967e0 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -6,4 +6,5 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
+ hdmi_ti_4xxx_ip.o \
hdmi_omap4_panel.o
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 1f34f63..1bd98d9 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -41,7 +41,6 @@
#endif
#include "dss.h"
-#include "hdmi.h"
#include "dss_features.h"
#define HDMI_WP 0x0
@@ -163,58 +162,6 @@ static const int code_vesa[85] = {
static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
-static inline void hdmi_write_reg(void __iomem *base_addr,
- const struct hdmi_reg idx, u32 val)
-{
- __raw_writel(val, base_addr + idx.idx);
-}
-
-static inline u32 hdmi_read_reg(void __iomem *base_addr,
- const struct hdmi_reg idx)
-{
- return __raw_readl(base_addr + idx.idx);
-}
-
-static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data)
-{
- return (void __iomem *) (ip_data->base_wp);
-}
-
-static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
-{
- return (void __iomem *) (ip_data->base_wp + ip_data->hdmi_phy_offset);
-}
-
-static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
-{
- return (void __iomem *) (ip_data->base_wp + ip_data->hdmi_pll_offset);
-}
-
-static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
-{
- return (void __iomem *)
- (ip_data->base_wp + ip_data->hdmi_core_av_offset);
-}
-
-static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
-{
- return (void __iomem *)
- (ip_data->base_wp + ip_data->hdmi_core_sys_offset);
-}
-
-static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
- const struct hdmi_reg idx,
- int b2, int b1, u32 val)
-{
- u32 t = 0;
- while (val != REG_GET(base_addr, idx, b2, b1)) {
- udelay(1);
- if (t++ > 10000)
- return !val;
- }
- return val;
-}
-
static int hdmi_runtime_get(void)
{
int r;
@@ -272,328 +219,6 @@ int hdmi_init_display(struct omap_dss_device *dssdev)
return 0;
}
-static int hdmi_pll_init(struct hdmi_ip_data *ip_data,
- enum hdmi_clk_refsel refsel, int dcofreq,
- struct hdmi_pll_info *fmt, u16 sd)
-{
- u32 r;
-
- /* PLL start always use manual mode */
- REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
-
- r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1);
- r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
- r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */
-
- hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1, r);
-
- r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2);
-
- r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
- r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
- r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
-
- if (dcofreq) {
- /* divider programming for frequency beyond 1000Mhz */
- REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_CFG3, sd, 17, 10);
- r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
- } else {
- r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
- }
-
- hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2, r);
-
- r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4);
- r = FLD_MOD(r, fmt->regm2, 24, 18);
- r = FLD_MOD(r, fmt->regmf, 17, 0);
-
- hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4, r);
-
- /* go now */
- REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_GO, 0x1, 0, 0);
-
- /* wait for bit change */
- if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), PLLCTRL_PLL_GO,
- 0, 0, 1) != 1) {
- DSSERR("PLL GO bit not set\n");
- return -ETIMEDOUT;
- }
-
- /* Wait till the lock bit is set in PLL status */
- if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
- PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
- DSSWARN("cannot lock PLL\n");
- DSSWARN("CFG1 0x%x\n",
- hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1));
- DSSWARN("CFG2 0x%x\n",
- hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2));
- DSSWARN("CFG4 0x%x\n",
- hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4));
- return -ETIMEDOUT;
- }
-
- DSSDBG("PLL locked!\n");
-
- return 0;
-}
-
-/* PHY_PWR_CMD */
-static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
-{
- /* Command for power control of HDMI PHY */
- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6);
-
- /* Status of the power control of HDMI PHY */
- if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
- HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
- DSSERR("Failed to set PHY power mode to %d\n", val);
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-/* PLL_PWR_CMD */
-int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
-{
- /* Command for power control of HDMI PLL */
- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
-
- /* wait till PHY_PWR_STATUS is set */
- if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
- 1, 0, val) != val) {
- DSSERR("Failed to set PHY_PWR_STATUS\n");
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
-{
- /* SYSRESET controlled by power FSM */
- REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
-
- /* READ 0x0 reset is in progress */
- if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
- PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
- DSSERR("Failed to sysreset PLL\n");
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static int hdmi_phy_init(struct hdmi_ip_data *ip_data)
-{
- u16 r = 0;
-
- r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
- if (r)
- return r;
-
- r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
- if (r)
- return r;
-
- /*
- * Read address 0 in order to get the SCP reset done completed
- * Dummy access performed to make sure reset is done
- */
- hdmi_read_reg(hdmi_phy_base(ip_data), HDMI_TXPHY_TX_CTRL);
-
- /*
- * Write to phy address 0 to configure the clock
- * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
- */
- REG_FLD_MOD(hdmi_phy_base(ip_data), HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
-
- /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
- hdmi_write_reg(hdmi_phy_base(ip_data),
- HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
-
- /* Setup max LDO voltage */
- REG_FLD_MOD(hdmi_phy_base(ip_data), HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
-
- /* Write to phy address 3 to change the polarity control */
- REG_FLD_MOD(hdmi_phy_base(ip_data),
- HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
-
- return 0;
-}
-
-static int hdmi_pll_program(struct hdmi_ip_data *ip_data,
- struct hdmi_pll_info *fmt)
-{
- u16 r = 0;
- enum hdmi_clk_refsel refsel;
-
- r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
- if (r)
- return r;
-
- r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
- if (r)
- return r;
-
- r = hdmi_pll_reset(ip_data);
- if (r)
- return r;
-
- refsel = HDMI_REFSEL_SYSCLK;
-
- r = hdmi_pll_init(ip_data, refsel, fmt->dcofreq, fmt, fmt->regsd);
- if (r)
- return r;
-
- return 0;
-}
-
-static void hdmi_phy_off(struct hdmi_ip_data *ip_data)
-{
- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
-}
-
-static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
- u8 *pedid, int ext)
-{
- u32 i, j;
- char checksum = 0;
- u32 offset = 0;
-
- /* Turn on CLK for DDC */
- REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_DPD, 0x7, 2, 0);
-
- /*
- * SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
- * right shifted values( The behavior is not consistent and seen only
- * with some TV's)
- */
- usleep_range(800, 1000);
-
- if (!ext) {
- /* Clk SCL Devices */
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_CMD, 0xA, 3, 0);
-
- /* HDMI_CORE_DDC_STATUS_IN_PROG */
- if (hdmi_wait_for_bit_change(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
- DSSERR("Failed to program DDC\n");
- return -ETIMEDOUT;
- }
-
- /* Clear FIFO */
- REG_FLD_MOD(hdmi_core_sys_base(ip_data)
- , HDMI_CORE_DDC_CMD, 0x9, 3, 0);
-
- /* HDMI_CORE_DDC_STATUS_IN_PROG */
- if (hdmi_wait_for_bit_change(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
- DSSERR("Failed to program DDC\n");
- return -ETIMEDOUT;
- }
-
- } else {
- if (ext % 2 != 0)
- offset = 0x80;
- }
-
- /* Load Segment Address Register */
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
-
- /* Load Slave Address Register */
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
-
- /* Load Offset Address Register */
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_OFFSET, offset, 7, 0);
-
- /* Load Byte Count */
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
-
- /* Set DDC_CMD */
- if (ext)
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_CMD, 0x4, 3, 0);
- else
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_CMD, 0x2, 3, 0);
-
- /* HDMI_CORE_DDC_STATUS_BUS_LOW */
- if (REG_GET(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_STATUS, 6, 6) = 1) {
- DSSWARN("I2C Bus Low?\n");
- return -EIO;
- }
- /* HDMI_CORE_DDC_STATUS_NO_ACK */
- if (REG_GET(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_STATUS, 5, 5) = 1) {
- DSSWARN("I2C No Ack\n");
- return -EIO;
- }
-
- i = ext * 128;
- j = 0;
- while (((REG_GET(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_STATUS, 4, 4) = 1) ||
- (REG_GET(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_STATUS, 2, 2) = 0)) && j < 128) {
-
- if (REG_GET(hdmi_core_sys_base(ip_data)
- , HDMI_CORE_DDC_STATUS, 2, 2) = 0) {
- /* FIFO not empty */
- pedid[i++] = REG_GET(hdmi_core_sys_base(ip_data),
- HDMI_CORE_DDC_DATA, 7, 0);
- j++;
- }
- }
-
- for (j = 0; j < 128; j++)
- checksum += pedid[j];
-
- if (checksum != 0) {
- DSSERR("E-EDID checksum failed!!\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static int read_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length)
-{
- int r = 0, n = 0, i = 0;
- int max_ext_blocks = (max_length / 128) - 1;
-
- r = hdmi_core_ddc_edid(ip_data, pedid, 0);
- if (r) {
- return r;
- } else {
- n = pedid[0x7e];
-
- /*
- * README: need to comply with max_length set by the caller.
- * Better implementation should be to allocate necessary
- * memory to store EDID according to nb_block field found
- * in first block
- */
- if (n > max_ext_blocks)
- n = max_ext_blocks;
-
- for (i = 1; i <= n; i++) {
- r = hdmi_core_ddc_edid(ip_data, pedid, i);
- if (r)
- return r;
- }
- }
- return 0;
-}
-
static void copy_hdmi_to_dss_timings(struct hdmi_video_timings hdmi_timings,
struct omap_video_timings *timings)
{
@@ -794,382 +419,6 @@ static void hdmi_read_edid(struct omap_video_timings *dp)
}
-static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
- struct hdmi_core_infoframe_avi *avi_cfg,
- struct hdmi_core_packet_enable_repeat *repeat_cfg)
-{
- DSSDBG("Enter hdmi_core_init\n");
-
- /* video core */
- video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
- video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
- video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
- video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
- video_cfg->hdmi_dvi = HDMI_DVI;
- video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
-
- /* info frame */
- avi_cfg->db1_format = 0;
- avi_cfg->db1_active_info = 0;
- avi_cfg->db1_bar_info_dv = 0;
- avi_cfg->db1_scan_info = 0;
- avi_cfg->db2_colorimetry = 0;
- avi_cfg->db2_aspect_ratio = 0;
- avi_cfg->db2_active_fmt_ar = 0;
- avi_cfg->db3_itc = 0;
- avi_cfg->db3_ec = 0;
- avi_cfg->db3_q_range = 0;
- avi_cfg->db3_nup_scaling = 0;
- avi_cfg->db4_videocode = 0;
- avi_cfg->db5_pixel_repeat = 0;
- avi_cfg->db6_7_line_eoftop = 0 ;
- avi_cfg->db8_9_line_sofbottom = 0;
- avi_cfg->db10_11_pixel_eofleft = 0;
- avi_cfg->db12_13_pixel_sofright = 0;
-
- /* packet enable and repeat */
- repeat_cfg->audio_pkt = 0;
- repeat_cfg->audio_pkt_repeat = 0;
- repeat_cfg->avi_infoframe = 0;
- repeat_cfg->avi_infoframe_repeat = 0;
- repeat_cfg->gen_cntrl_pkt = 0;
- repeat_cfg->gen_cntrl_pkt_repeat = 0;
- repeat_cfg->generic_pkt = 0;
- repeat_cfg->generic_pkt_repeat = 0;
-}
-
-static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data)
-{
- DSSDBG("Enter hdmi_core_powerdown_disable\n");
- REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
-}
-
-static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
-{
- DSSDBG("Enter hdmi_core_swreset_release\n");
- REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0);
-}
-
-static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data)
-{
- DSSDBG("Enter hdmi_core_swreset_assert\n");
- REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0);
-}
-
-/* HDMI_CORE_VIDEO_CONFIG */
-static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
- struct hdmi_core_video_config *cfg)
-{
- u32 r = 0;
-
- /* sys_ctrl1 default configuration not tunable */
- r = hdmi_read_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
- hdmi_write_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, r);
-
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
-
- /* Vid_Mode */
- r = hdmi_read_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_VID_MODE);
-
- /* dither truncation configuration */
- if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
- r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
- r = FLD_MOD(r, 1, 5, 5);
- } else {
- r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
- r = FLD_MOD(r, 0, 5, 5);
- }
- hdmi_write_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_VID_MODE, r);
-
- /* HDMI_Ctrl */
- r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL);
- r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
- r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
- r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r);
-
- /* TMDS_CTRL */
- REG_FLD_MOD(hdmi_core_sys_base(ip_data),
- HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
-}
-
-static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data,
- struct hdmi_core_infoframe_avi info_avi)
-{
- u32 val;
- char sum = 0, checksum = 0;
-
- sum += 0x82 + 0x002 + 0x00D;
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_TYPE, 0x082);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_VERS, 0x002);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_LEN, 0x00D);
-
- val = (info_avi.db1_format << 5) |
- (info_avi.db1_active_info << 4) |
- (info_avi.db1_bar_info_dv << 2) |
- (info_avi.db1_scan_info);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(0), val);
- sum += val;
-
- val = (info_avi.db2_colorimetry << 6) |
- (info_avi.db2_aspect_ratio << 4) |
- (info_avi.db2_active_fmt_ar);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(1), val);
- sum += val;
-
- val = (info_avi.db3_itc << 7) |
- (info_avi.db3_ec << 4) |
- (info_avi.db3_q_range << 2) |
- (info_avi.db3_nup_scaling);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(2), val);
- sum += val;
-
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(3),
- info_avi.db4_videocode);
- sum += info_avi.db4_videocode;
-
- val = info_avi.db5_pixel_repeat;
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(4), val);
- sum += val;
-
- val = info_avi.db6_7_line_eoftop & 0x00FF;
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(5), val);
- sum += val;
-
- val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(6), val);
- sum += val;
-
- val = info_avi.db8_9_line_sofbottom & 0x00FF;
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(7), val);
- sum += val;
-
- val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(8), val);
- sum += val;
-
- val = info_avi.db10_11_pixel_eofleft & 0x00FF;
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(9), val);
- sum += val;
-
- val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(10), val);
- sum += val;
-
- val = info_avi.db12_13_pixel_sofright & 0x00FF;
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(11), val);
- sum += val;
-
- val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(12), val);
- sum += val;
-
- checksum = 0x100 - sum;
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_CHSUM, checksum);
-}
-
-static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
- struct hdmi_core_packet_enable_repeat repeat_cfg)
-{
- /* enable/repeat the infoframe */
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1,
- (repeat_cfg.audio_pkt << 5) |
- (repeat_cfg.audio_pkt_repeat << 4) |
- (repeat_cfg.avi_infoframe << 1) |
- (repeat_cfg.avi_infoframe_repeat));
-
- /* enable/repeat the packet */
- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2,
- (repeat_cfg.gen_cntrl_pkt << 3) |
- (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
- (repeat_cfg.generic_pkt << 1) |
- (repeat_cfg.generic_pkt_repeat));
-}
-
-static void hdmi_wp_init(struct omap_video_timings *timings,
- struct hdmi_video_format *video_fmt,
- struct hdmi_video_interface *video_int)
-{
- DSSDBG("Enter hdmi_wp_init\n");
-
- timings->hbp = 0;
- timings->hfp = 0;
- timings->hsw = 0;
- timings->vbp = 0;
- timings->vfp = 0;
- timings->vsw = 0;
-
- video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
- video_fmt->y_res = 0;
- video_fmt->x_res = 0;
-
- video_int->vsp = 0;
- video_int->hsp = 0;
-
- video_int->interlacing = 0;
- video_int->tm = 0; /* HDMI_TIMING_SLAVE */
-
-}
-
-static void hdmi_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
-{
- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
-}
-
-static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
- struct omap_video_timings *timings, struct hdmi_config *param)
-{
- DSSDBG("Enter hdmi_wp_video_init_format\n");
-
- video_fmt->y_res = param->timings.timings.y_res;
- video_fmt->x_res = param->timings.timings.x_res;
-
- timings->hbp = param->timings.timings.hbp;
- timings->hfp = param->timings.timings.hfp;
- timings->hsw = param->timings.timings.hsw;
- timings->vbp = param->timings.timings.vbp;
- timings->vfp = param->timings.timings.vfp;
- timings->vsw = param->timings.timings.vsw;
-}
-
-static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
- struct hdmi_video_format *video_fmt)
-{
- u32 l = 0;
-
- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG,
- video_fmt->packing_mode, 10, 8);
-
- l |= FLD_VAL(video_fmt->y_res, 31, 16);
- l |= FLD_VAL(video_fmt->x_res, 15, 0);
- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
-}
-
-static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data,
- struct hdmi_video_interface *video_int)
-{
- u32 r;
- DSSDBG("Enter hdmi_wp_video_config_interface\n");
-
- r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
- r = FLD_MOD(r, video_int->vsp, 7, 7);
- r = FLD_MOD(r, video_int->hsp, 6, 6);
- r = FLD_MOD(r, video_int->interlacing, 3, 3);
- r = FLD_MOD(r, video_int->tm, 1, 0);
- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
-}
-
-static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
- struct omap_video_timings *timings)
-{
- u32 timing_h = 0;
- u32 timing_v = 0;
-
- DSSDBG("Enter hdmi_wp_video_config_timing\n");
-
- timing_h |= FLD_VAL(timings->hbp, 31, 20);
- timing_h |= FLD_VAL(timings->hfp, 19, 8);
- timing_h |= FLD_VAL(timings->hsw, 7, 0);
- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h);
-
- timing_v |= FLD_VAL(timings->vbp, 31, 20);
- timing_v |= FLD_VAL(timings->vfp, 19, 8);
- timing_v |= FLD_VAL(timings->vsw, 7, 0);
- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
-}
-
-static void hdmi_basic_configure(struct hdmi_ip_data *ip_data,
- struct hdmi_config *cfg)
-{
- /* HDMI */
- struct omap_video_timings video_timing;
- struct hdmi_video_format video_format;
- struct hdmi_video_interface video_interface;
- /* HDMI core */
- struct hdmi_core_infoframe_avi avi_cfg;
- struct hdmi_core_video_config v_core_cfg;
- struct hdmi_core_packet_enable_repeat repeat_cfg;
-
- hdmi_wp_init(&video_timing, &video_format,
- &video_interface);
-
- hdmi_core_init(&v_core_cfg,
- &avi_cfg,
- &repeat_cfg);
-
- hdmi_wp_video_init_format(&video_format,
- &video_timing, cfg);
-
- hdmi_wp_video_config_timing(ip_data, &video_timing);
-
- /* video config */
- video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
-
- hdmi_wp_video_config_format(ip_data, &video_format);
-
- video_interface.vsp = cfg->timings.vsync_pol;
- video_interface.hsp = cfg->timings.hsync_pol;
- video_interface.interlacing = cfg->interlace;
- video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
-
- hdmi_wp_video_config_interface(ip_data, &video_interface);
-
- /*
- * configure core video part
- * set software reset in the core
- */
- hdmi_core_swreset_assert(ip_data);
-
- /* power down off */
- hdmi_core_powerdown_disable(ip_data);
-
- v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
- v_core_cfg.hdmi_dvi = cfg->cm.mode;
-
- hdmi_core_video_config(ip_data, &v_core_cfg);
-
- /* release software reset in the core */
- hdmi_core_swreset_release(ip_data);
-
- /*
- * configure packet
- * info frame video see doc CEA861-D page 65
- */
- avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
- avi_cfg.db1_active_info - HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
- avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
- avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
- avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
- avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
- avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
- avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
- avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
- avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
- avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
- avi_cfg.db4_videocode = cfg->cm.code;
- avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
- avi_cfg.db6_7_line_eoftop = 0;
- avi_cfg.db8_9_line_sofbottom = 0;
- avi_cfg.db10_11_pixel_eofleft = 0;
- avi_cfg.db12_13_pixel_sofright = 0;
-
- hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg);
-
- /* enable/repeat the infoframe */
- repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
- repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
- /* wakeup */
- repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
- repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
- hdmi_core_av_packet_config(ip_data, repeat_cfg);
-}
-
static void update_hdmi_timings(struct hdmi_config *cfg,
struct omap_video_timings *timings, int code)
{
diff --git a/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c b/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
new file mode 100644
index 0000000..b4e8875
--- /dev/null
+++ b/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.c
@@ -0,0 +1,781 @@
+/*
+ * hdmi_ti_4xxx_ip.c
+ *
+ * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Yong Zhi
+ * Mythri pk <mythripk@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+
+#include "hdmi_ti_4xxx_ip.h"
+#include "dss.h"
+
+static inline void hdmi_write_reg(void __iomem *base_addr,
+ const struct hdmi_reg idx, u32 val)
+{
+ __raw_writel(val, base_addr + idx.idx);
+}
+
+static inline u32 hdmi_read_reg(void __iomem *base_addr,
+ const struct hdmi_reg idx)
+{
+ return __raw_readl(base_addr + idx.idx);
+}
+
+static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *) (ip_data->base_wp);
+}
+
+static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *) (ip_data->base_wp + ip_data->hdmi_phy_offset);
+}
+
+static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *) (ip_data->base_wp + ip_data->hdmi_pll_offset);
+}
+
+static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *)
+ (ip_data->base_wp + ip_data->hdmi_core_av_offset);
+}
+
+static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *)
+ (ip_data->base_wp + ip_data->hdmi_core_sys_offset);
+}
+
+static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
+ const struct hdmi_reg idx,
+ int b2, int b1, u32 val)
+{
+ u32 t = 0;
+ while (val != REG_GET(base_addr, idx, b2, b1)) {
+ udelay(1);
+ if (t++ > 10000)
+ return !val;
+ }
+ return val;
+}
+
+static int hdmi_pll_init(struct hdmi_ip_data *ip_data,
+ enum hdmi_clk_refsel refsel, int dcofreq,
+ struct hdmi_pll_info *fmt, u16 sd)
+{
+ u32 r;
+
+ /* PLL start always use manual mode */
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
+
+ r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1);
+ r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
+ r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */
+
+ hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1, r);
+
+ r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2);
+
+ r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
+ r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
+ r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
+
+ if (dcofreq) {
+ /* divider programming for frequency beyond 1000Mhz */
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_CFG3, sd, 17, 10);
+ r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
+ } else {
+ r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
+ }
+
+ hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2, r);
+
+ r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4);
+ r = FLD_MOD(r, fmt->regm2, 24, 18);
+ r = FLD_MOD(r, fmt->regmf, 17, 0);
+
+ hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4, r);
+
+ /* go now */
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_GO, 0x1, 0, 0);
+
+ /* wait for bit change */
+ if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), PLLCTRL_PLL_GO,
+ 0, 0, 1) != 1) {
+ pr_err("PLL GO bit not set\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Wait till the lock bit is set in PLL status */
+ if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
+ PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
+ pr_err("cannot lock PLL\n");
+ pr_err("CFG1 0x%x\n",
+ hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1));
+ pr_err("CFG2 0x%x\n",
+ hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2));
+ pr_err("CFG4 0x%x\n",
+ hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4));
+ return -ETIMEDOUT;
+ }
+
+ pr_debug("PLL locked!\n");
+
+ return 0;
+}
+
+/* PHY_PWR_CMD */
+static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
+{
+ /* Command for power control of HDMI PHY */
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6);
+
+ /* Status of the power control of HDMI PHY */
+ if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
+ HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
+ pr_err("Failed to set PHY power mode to %d\n", val);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+/* PLL_PWR_CMD */
+int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
+{
+ /* Command for power control of HDMI PLL */
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
+
+ /* wait till PHY_PWR_STATUS is set */
+if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
+ 1, 0, val) != val) {
+ pr_err("Failed to set PLL_PWR_STATUS\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
+{
+ /* SYSRESET controlled by power FSM */
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
+
+ /* READ 0x0 reset is in progress */
+ if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
+ PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
+ pr_err("Failed to sysreset PLL\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+int hdmi_pll_program(struct hdmi_ip_data *ip_data,
+ struct hdmi_pll_info *fmt)
+{
+ u16 r = 0;
+ enum hdmi_clk_refsel refsel;
+
+ r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
+ if (r)
+ return r;
+
+ r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
+ if (r)
+ return r;
+
+ r = hdmi_pll_reset(ip_data);
+ if (r)
+ return r;
+
+ refsel = HDMI_REFSEL_SYSCLK;
+
+ r = hdmi_pll_init(ip_data, refsel, fmt->dcofreq, fmt, fmt->regsd);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+int hdmi_phy_init(struct hdmi_ip_data *ip_data)
+{
+ u16 r = 0;
+
+ r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+ if (r)
+ return r;
+
+ r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
+ if (r)
+ return r;
+
+ /*
+ * Read address 0 in order to get the SCP reset done completed
+ * Dummy access performed to make sure reset is done
+ */
+ hdmi_read_reg(hdmi_phy_base(ip_data), HDMI_TXPHY_TX_CTRL);
+
+ /*
+ * Write to phy address 0 to configure the clock
+ * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
+ */
+ REG_FLD_MOD(hdmi_phy_base(ip_data), HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
+
+ /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
+ hdmi_write_reg(hdmi_phy_base(ip_data),
+ HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
+
+ /* Setup max LDO voltage */
+ REG_FLD_MOD(hdmi_phy_base(ip_data), HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
+
+ /* Write to phy address 3 to change the polarity control */
+ REG_FLD_MOD(hdmi_phy_base(ip_data),
+ HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+
+ return 0;
+}
+
+void hdmi_phy_off(struct hdmi_ip_data *ip_data)
+{
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+}
+
+static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
+ u8 *pedid, int ext)
+{
+ u32 i, j;
+ char checksum = 0;
+ u32 offset = 0;
+
+ /* Turn on CLK for DDC */
+ REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_DPD, 0x7, 2, 0);
+
+ /*
+ * SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
+ * right shifted values( The behavior is not consistent and seen only
+ * with some TV's)
+ */
+ usleep_range(800, 1000);
+
+ if (!ext) {
+ /* Clk SCL Devices */
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+
+ /* HDMI_CORE_DDC_STATUS_IN_PROG */
+ if (hdmi_wait_for_bit_change(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+ pr_err("Failed to program DDC\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Clear FIFO */
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data)
+ , HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+
+ /* HDMI_CORE_DDC_STATUS_IN_PROG */
+ if (hdmi_wait_for_bit_change(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+ pr_err("Failed to program DDC\n");
+ return -ETIMEDOUT;
+ }
+
+ } else {
+ if (ext % 2 != 0)
+ offset = 0x80;
+ }
+
+ /* Load Segment Address Register */
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
+
+ /* Load Slave Address Register */
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
+
+ /* Load Offset Address Register */
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_OFFSET, offset, 7, 0);
+
+ /* Load Byte Count */
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
+
+ /* Set DDC_CMD */
+ if (ext)
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_CMD, 0x4, 3, 0);
+ else
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_CMD, 0x2, 3, 0);
+
+ /* HDMI_CORE_DDC_STATUS_BUS_LOW */
+ if (REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 6, 6) = 1) {
+ pr_err("I2C Bus Low?\n");
+ return -EIO;
+ }
+ /* HDMI_CORE_DDC_STATUS_NO_ACK */
+ if (REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 5, 5) = 1) {
+ pr_err("I2C No Ack\n");
+ return -EIO;
+ }
+
+ i = ext * 128;
+ j = 0;
+ while (((REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 4, 4) = 1) ||
+ (REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 2, 2) = 0)) && j < 128) {
+
+ if (REG_GET(hdmi_core_sys_base(ip_data)
+ , HDMI_CORE_DDC_STATUS, 2, 2) = 0) {
+ /* FIFO not empty */
+ pedid[i++] = REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_DATA, 7, 0);
+ j++;
+ }
+ }
+
+ for (j = 0; j < 128; j++)
+ checksum += pedid[j];
+
+ if (checksum != 0) {
+ pr_err("E-EDID checksum failed!!\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int read_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length)
+{
+ int r = 0, n = 0, i = 0;
+ int max_ext_blocks = (max_length / 128) - 1;
+
+ r = hdmi_core_ddc_edid(ip_data, pedid, 0);
+ if (r) {
+ return r;
+ } else {
+ n = pedid[0x7e];
+
+ /*
+ * README: need to comply with max_length set by the caller.
+ * Better implementation should be to allocate necessary
+ * memory to store EDID according to nb_block field found
+ * in first block
+ */
+ if (n > max_ext_blocks)
+ n = max_ext_blocks;
+
+ for (i = 1; i <= n; i++) {
+ r = hdmi_core_ddc_edid(ip_data, pedid, i);
+ if (r)
+ return r;
+ }
+ }
+ return 0;
+}
+
+static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
+ struct hdmi_core_infoframe_avi *avi_cfg,
+ struct hdmi_core_packet_enable_repeat *repeat_cfg)
+{
+ pr_debug("Enter hdmi_core_init\n");
+
+ /* video core */
+ video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
+ video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
+ video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
+ video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
+ video_cfg->hdmi_dvi = HDMI_DVI;
+ video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
+
+ /* info frame */
+ avi_cfg->db1_format = 0;
+ avi_cfg->db1_active_info = 0;
+ avi_cfg->db1_bar_info_dv = 0;
+ avi_cfg->db1_scan_info = 0;
+ avi_cfg->db2_colorimetry = 0;
+ avi_cfg->db2_aspect_ratio = 0;
+ avi_cfg->db2_active_fmt_ar = 0;
+ avi_cfg->db3_itc = 0;
+ avi_cfg->db3_ec = 0;
+ avi_cfg->db3_q_range = 0;
+ avi_cfg->db3_nup_scaling = 0;
+ avi_cfg->db4_videocode = 0;
+ avi_cfg->db5_pixel_repeat = 0;
+ avi_cfg->db6_7_line_eoftop = 0 ;
+ avi_cfg->db8_9_line_sofbottom = 0;
+ avi_cfg->db10_11_pixel_eofleft = 0;
+ avi_cfg->db12_13_pixel_sofright = 0;
+
+ /* packet enable and repeat */
+ repeat_cfg->audio_pkt = 0;
+ repeat_cfg->audio_pkt_repeat = 0;
+ repeat_cfg->avi_infoframe = 0;
+ repeat_cfg->avi_infoframe_repeat = 0;
+ repeat_cfg->gen_cntrl_pkt = 0;
+ repeat_cfg->gen_cntrl_pkt_repeat = 0;
+ repeat_cfg->generic_pkt = 0;
+ repeat_cfg->generic_pkt_repeat = 0;
+}
+
+static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data)
+{
+ pr_debug("Enter hdmi_core_powerdown_disable\n");
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
+{
+ pr_debug("Enter hdmi_core_swreset_release\n");
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data)
+{
+ pr_debug("Enter hdmi_core_swreset_assert\n");
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0);
+}
+
+/* HDMI_CORE_VIDEO_CONFIG */
+static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_video_config *cfg)
+{
+ u32 r = 0;
+
+ /* sys_ctrl1 default configuration not tunable */
+ r = hdmi_read_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1);
+ r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
+ r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
+ r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
+ r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
+ hdmi_write_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, r);
+
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
+
+ /* Vid_Mode */
+ r = hdmi_read_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_VID_MODE);
+
+ /* dither truncation configuration */
+ if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
+ r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
+ r = FLD_MOD(r, 1, 5, 5);
+ } else {
+ r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
+ r = FLD_MOD(r, 0, 5, 5);
+ }
+ hdmi_write_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_VID_MODE, r);
+
+ /* HDMI_Ctrl */
+ r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL);
+ r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
+ r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
+ r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r);
+
+ /* TMDS_CTRL */
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
+}
+
+static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_infoframe_avi info_avi)
+{
+ u32 val;
+ char sum = 0, checksum = 0;
+
+ sum += 0x82 + 0x002 + 0x00D;
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_TYPE, 0x082);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_VERS, 0x002);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_LEN, 0x00D);
+
+ val = (info_avi.db1_format << 5) |
+ (info_avi.db1_active_info << 4) |
+ (info_avi.db1_bar_info_dv << 2) |
+ (info_avi.db1_scan_info);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(0), val);
+ sum += val;
+
+ val = (info_avi.db2_colorimetry << 6) |
+ (info_avi.db2_aspect_ratio << 4) |
+ (info_avi.db2_active_fmt_ar);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(1), val);
+ sum += val;
+
+ val = (info_avi.db3_itc << 7) |
+ (info_avi.db3_ec << 4) |
+ (info_avi.db3_q_range << 2) |
+ (info_avi.db3_nup_scaling);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(2), val);
+ sum += val;
+
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(3),
+ info_avi.db4_videocode);
+ sum += info_avi.db4_videocode;
+
+ val = info_avi.db5_pixel_repeat;
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(4), val);
+ sum += val;
+
+ val = info_avi.db6_7_line_eoftop & 0x00FF;
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(5), val);
+ sum += val;
+
+ val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(6), val);
+ sum += val;
+
+ val = info_avi.db8_9_line_sofbottom & 0x00FF;
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(7), val);
+ sum += val;
+
+ val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(8), val);
+ sum += val;
+
+ val = info_avi.db10_11_pixel_eofleft & 0x00FF;
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(9), val);
+ sum += val;
+
+ val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(10), val);
+ sum += val;
+
+ val = info_avi.db12_13_pixel_sofright & 0x00FF;
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(11), val);
+ sum += val;
+
+ val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(12), val);
+ sum += val;
+
+ checksum = 0x100 - sum;
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_CHSUM, checksum);
+}
+
+static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_packet_enable_repeat repeat_cfg)
+{
+ /* enable/repeat the infoframe */
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1,
+ (repeat_cfg.audio_pkt << 5) |
+ (repeat_cfg.audio_pkt_repeat << 4) |
+ (repeat_cfg.avi_infoframe << 1) |
+ (repeat_cfg.avi_infoframe_repeat));
+
+ /* enable/repeat the packet */
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2,
+ (repeat_cfg.gen_cntrl_pkt << 3) |
+ (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
+ (repeat_cfg.generic_pkt << 1) |
+ (repeat_cfg.generic_pkt_repeat));
+}
+
+static void hdmi_wp_init(struct omap_video_timings *timings,
+ struct hdmi_video_format *video_fmt,
+ struct hdmi_video_interface *video_int)
+{
+ pr_debug("Enter hdmi_wp_init\n");
+
+ timings->hbp = 0;
+ timings->hfp = 0;
+ timings->hsw = 0;
+ timings->vbp = 0;
+ timings->vfp = 0;
+ timings->vsw = 0;
+
+ video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
+ video_fmt->y_res = 0;
+ video_fmt->x_res = 0;
+
+ video_int->vsp = 0;
+ video_int->hsp = 0;
+
+ video_int->interlacing = 0;
+ video_int->tm = 0; /* HDMI_TIMING_SLAVE */
+
+}
+
+void hdmi_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
+{
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
+}
+
+static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
+ struct omap_video_timings *timings, struct hdmi_config *param)
+{
+ pr_debug("Enter hdmi_wp_video_init_format\n");
+
+ video_fmt->y_res = param->timings.timings.y_res;
+ video_fmt->x_res = param->timings.timings.x_res;
+
+ timings->hbp = param->timings.timings.hbp;
+ timings->hfp = param->timings.timings.hfp;
+ timings->hsw = param->timings.timings.hsw;
+ timings->vbp = param->timings.timings.vbp;
+ timings->vfp = param->timings.timings.vfp;
+ timings->vsw = param->timings.timings.vsw;
+}
+
+static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
+ struct hdmi_video_format *video_fmt)
+{
+ u32 l = 0;
+
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG,
+ video_fmt->packing_mode, 10, 8);
+
+ l |= FLD_VAL(video_fmt->y_res, 31, 16);
+ l |= FLD_VAL(video_fmt->x_res, 15, 0);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
+}
+
+static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data,
+ struct hdmi_video_interface *video_int)
+{
+ u32 r;
+ pr_debug("Enter hdmi_wp_video_config_interface\n");
+
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
+ r = FLD_MOD(r, video_int->vsp, 7, 7);
+ r = FLD_MOD(r, video_int->hsp, 6, 6);
+ r = FLD_MOD(r, video_int->interlacing, 3, 3);
+ r = FLD_MOD(r, video_int->tm, 1, 0);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
+}
+
+static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
+ struct omap_video_timings *timings)
+{
+ u32 timing_h = 0;
+ u32 timing_v = 0;
+
+ pr_debug("Enter hdmi_wp_video_config_timing\n");
+
+ timing_h |= FLD_VAL(timings->hbp, 31, 20);
+ timing_h |= FLD_VAL(timings->hfp, 19, 8);
+ timing_h |= FLD_VAL(timings->hsw, 7, 0);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h);
+
+ timing_v |= FLD_VAL(timings->vbp, 31, 20);
+ timing_v |= FLD_VAL(timings->vfp, 19, 8);
+ timing_v |= FLD_VAL(timings->vsw, 7, 0);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
+}
+
+void hdmi_basic_configure(struct hdmi_ip_data *ip_data,
+ struct hdmi_config *cfg)
+{
+ /* HDMI */
+ struct omap_video_timings video_timing;
+ struct hdmi_video_format video_format;
+ struct hdmi_video_interface video_interface;
+ /* HDMI core */
+ struct hdmi_core_infoframe_avi avi_cfg;
+ struct hdmi_core_video_config v_core_cfg;
+ struct hdmi_core_packet_enable_repeat repeat_cfg;
+
+ hdmi_wp_init(&video_timing, &video_format,
+ &video_interface);
+
+ hdmi_core_init(&v_core_cfg,
+ &avi_cfg,
+ &repeat_cfg);
+
+ hdmi_wp_video_init_format(&video_format, &video_timing, cfg);
+
+ hdmi_wp_video_config_timing(ip_data, &video_timing);
+
+ /* video config */
+ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
+
+ hdmi_wp_video_config_format(ip_data, &video_format);
+
+ video_interface.vsp = cfg->timings.vsync_pol;
+ video_interface.hsp = cfg->timings.hsync_pol;
+ video_interface.interlacing = cfg->interlace;
+ video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
+
+ hdmi_wp_video_config_interface(ip_data, &video_interface);
+
+ /*
+ * configure core video part
+ * set software reset in the core
+ */
+ hdmi_core_swreset_assert(ip_data);
+
+ /* power down off */
+ hdmi_core_powerdown_disable(ip_data);
+
+ v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
+ v_core_cfg.hdmi_dvi = cfg->cm.mode;
+
+ hdmi_core_video_config(ip_data, &v_core_cfg);
+
+ /* release software reset in the core */
+ hdmi_core_swreset_release(ip_data);
+
+ /*
+ * configure packet
+ * info frame video see doc CEA861-D page 65
+ */
+ avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
+ avi_cfg.db1_active_info + HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
+ avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
+ avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
+ avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
+ avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
+ avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
+ avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
+ avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
+ avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
+ avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
+ avi_cfg.db4_videocode = cfg->cm.code;
+ avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
+ avi_cfg.db6_7_line_eoftop = 0;
+ avi_cfg.db8_9_line_sofbottom = 0;
+ avi_cfg.db10_11_pixel_eofleft = 0;
+ avi_cfg.db12_13_pixel_sofright = 0;
+
+ hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg);
+
+ /* enable/repeat the infoframe */
+ repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
+ repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
+ /* wakeup */
+ repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
+ repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
+ hdmi_core_av_packet_config(ip_data, repeat_cfg);
+}
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.h
similarity index 99%
rename from drivers/video/omap2/dss/hdmi.h
rename to drivers/video/omap2/dss/hdmi_ti_4xxx_ip.h
index 4b0fab3..97e573c 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/hdmi_ti_4xxx_ip.h
@@ -1,7 +1,7 @@
/*
- * hdmi.h
+ * hdmi_ti_4xxx_ip.h
*
- * HDMI driver definition for TI OMAP4 processors.
+ * HDMI header definition for TI81xx, TI38xx, TI OMAP4 etc processors.
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
*
@@ -18,11 +18,12 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _OMAP4_DSS_HDMI_H_
-#define _OMAP4_DSS_HDMI_H_
+#ifndef _HDMI_TI_4xxx_H_
+#define _HDMI_TI_4xxx_H_
#include <linux/string.h>
#include <video/omapdss.h>
+#include <video/hdmi_ti_4xxx_ip.h>
struct hdmi_reg { u16 idx; };
diff --git a/include/video/hdmi_ti_4xxx_ip.h b/include/video/hdmi_ti_4xxx_ip.h
index 49640cd..3355f40 100644
--- a/include/video/hdmi_ti_4xxx_ip.h
+++ b/include/video/hdmi_ti_4xxx_ip.h
@@ -81,4 +81,14 @@ struct hdmi_pll_info {
u16 regsd;
u16 dcofreq;
};
+
+int hdmi_phy_init(struct hdmi_ip_data *ip_data);
+void hdmi_phy_off(struct hdmi_ip_data *ip_data);
+int read_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length);
+void hdmi_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
+int hdmi_pll_program(struct hdmi_ip_data *ip_data,
+ struct hdmi_pll_info *fmt);
+int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val);
+void hdmi_basic_configure(struct hdmi_ip_data *ip_data,
+ struct hdmi_config *cfg);
#endif
--
1.7.5.4
^ permalink raw reply related
* [PATCH 4/8] OMAP4: DSS: HDMI: Move the common header file definition
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
Some of the header file definitions of HDMI IP are needed by audio driver thus
moving the common defintion to more generic Include/video.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/omap2/dss/dss.h | 10 -----
drivers/video/omap2/dss/hdmi.c | 1 +
drivers/video/omap2/dss/hdmi.h | 51 -----------------------
include/video/hdmi_ti_4xxx_ip.h | 84 +++++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+), 61 deletions(-)
create mode 100644 include/video/hdmi_ti_4xxx_ip.h
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index ce17a61..324e982 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -156,16 +156,6 @@ struct dsi_clock_info {
bool use_sys_clk;
};
-/* HDMI PLL structure */
-struct hdmi_pll_info {
- u16 regn;
- u16 regm;
- u32 regmf;
- u16 regm2;
- u16 regsd;
- u16 dcofreq;
-};
-
struct seq_file;
struct platform_device;
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index c24d573..1f34f63 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -33,6 +33,7 @@
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <video/omapdss.h>
+#include <video/hdmi_ti_4xxx_ip.h>
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
#include <sound/soc.h>
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
index dcc30b7..4b0fab3 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/hdmi.h
@@ -188,39 +188,12 @@ struct hdmi_reg { u16 idx; };
#define REG_GET(base, idx, start, end) \
FLD_GET(hdmi_read_reg(base, idx), start, end)
-struct hdmi_video_timings {
- u16 x_res;
- u16 y_res;
- /* Unit: KHz */
- u32 pixel_clock;
- u16 hsw;
- u16 hfp;
- u16 hbp;
- u16 vsw;
- u16 vfp;
- u16 vbp;
-};
-
-/* HDMI timing structure */
-struct hdmi_timings {
- struct hdmi_video_timings timings;
- int vsync_pol;
- int hsync_pol;
-};
-
enum hdmi_phy_pwr {
HDMI_PHYPWRCMD_OFF = 0,
HDMI_PHYPWRCMD_LDOON = 1,
HDMI_PHYPWRCMD_TXON = 2
};
-enum hdmi_pll_pwr {
- HDMI_PLLPWRCMD_ALLOFF = 0,
- HDMI_PLLPWRCMD_PLLONLY = 1,
- HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
- HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
-};
-
enum hdmi_clk_refsel {
HDMI_REFSEL_PCLK = 0,
HDMI_REFSEL_REF1 = 1,
@@ -256,11 +229,6 @@ enum hdmi_core_packet_mode {
HDMI_PACKETMODE48BITPERPIXEL = 7
};
-enum hdmi_core_hdmi_dvi {
- HDMI_DVI = 0,
- HDMI_HDMI = 1
-};
-
enum hdmi_core_tclkselclkmult {
HDMI_FPLL05IDCK = 0,
HDMI_FPLL10IDCK = 1,
@@ -561,25 +529,6 @@ struct hdmi_video_interface {
int tm; /* Timing mode */
};
-struct hdmi_ip_data {
- void __iomem *base_wp; /* HDMI wrapper */
- unsigned long hdmi_core_sys_offset;
- unsigned long hdmi_core_av_offset;
- unsigned long hdmi_pll_offset;
- unsigned long hdmi_phy_offset;
-};
-
-struct hdmi_cm {
- int code;
- int mode;
-};
-
-struct hdmi_config {
- struct hdmi_timings timings;
- u16 interlace;
- struct hdmi_cm cm;
-};
-
struct hdmi_audio_format {
enum hdmi_stereo_channels stereo_channels;
u8 active_chnnls_msk;
diff --git a/include/video/hdmi_ti_4xxx_ip.h b/include/video/hdmi_ti_4xxx_ip.h
new file mode 100644
index 0000000..49640cd
--- /dev/null
+++ b/include/video/hdmi_ti_4xxx_ip.h
@@ -0,0 +1,84 @@
+/*
+ * hdmi_ti_4xxx_ip.h
+ *
+ * HDMI driver definition for TI OMAP4, TI81xx, TI38xx Processor.
+ *
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _HDMI_TI_4xxx_
+#define _HDMI_TI_4xxx_
+
+enum hdmi_pll_pwr {
+ HDMI_PLLPWRCMD_ALLOFF = 0,
+ HDMI_PLLPWRCMD_PLLONLY = 1,
+ HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
+ HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
+};
+
+enum hdmi_core_hdmi_dvi {
+ HDMI_DVI = 0,
+ HDMI_HDMI = 1
+};
+
+struct hdmi_ip_data {
+ void __iomem *base_wp; /* HDMI wrapper */
+ unsigned long hdmi_core_sys_offset;
+ unsigned long hdmi_core_av_offset;
+ unsigned long hdmi_pll_offset;
+ unsigned long hdmi_phy_offset;
+};
+
+struct hdmi_video_timings {
+ u16 x_res;
+ u16 y_res;
+ /* Unit: KHz */
+ u32 pixel_clock;
+ u16 hsw;
+ u16 hfp;
+ u16 hbp;
+ u16 vsw;
+ u16 vfp;
+ u16 vbp;
+};
+
+/* HDMI timing structure */
+struct hdmi_timings {
+ struct hdmi_video_timings timings;
+ int vsync_pol;
+ int hsync_pol;
+};
+
+struct hdmi_cm {
+ int code;
+ int mode;
+};
+
+struct hdmi_config {
+ struct hdmi_timings timings;
+ u16 interlace;
+ struct hdmi_cm cm;
+};
+
+/* HDMI PLL structure */
+struct hdmi_pll_info {
+ u16 regn;
+ u16 regm;
+ u32 regmf;
+ u16 regm2;
+ u16 regsd;
+ u16 dcofreq;
+};
+#endif
--
1.7.5.4
^ permalink raw reply related
* [PATCH 3/8] OMAP4: DSS: HDMI: Use specific HDMI timings structure
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
Define new HDMI timings structure to replace the OMAP DSS timing strucutre in hdmi.c
to have the HDMI include defintion out of DSS.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/omap2/dss/hdmi.c | 23 ++++++++++++++++++++---
drivers/video/omap2/dss/hdmi.h | 15 ++++++++++++++-
2 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 4ee879a..c24d573 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -593,6 +593,20 @@ static int read_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length)
return 0;
}
+static void copy_hdmi_to_dss_timings(struct hdmi_video_timings hdmi_timings,
+ struct omap_video_timings *timings)
+{
+ timings->x_res = hdmi_timings.x_res;
+ timings->y_res = hdmi_timings.y_res;
+ timings->pixel_clock = hdmi_timings.pixel_clock;
+ timings->hbp = hdmi_timings.hbp;
+ timings->hfp = hdmi_timings.hfp;
+ timings->hsw = hdmi_timings.hsw;
+ timings->vbp = hdmi_timings.vbp;
+ timings->vfp = hdmi_timings.vfp;
+ timings->vsw = hdmi_timings.vsw;
+}
+
static int get_timings_index(void)
{
int code;
@@ -617,7 +631,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
{
int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;
int timing_vsync = 0, timing_hsync = 0;
- struct omap_video_timings temp;
+ struct hdmi_video_timings temp;
struct hdmi_cm cm = {-1};
DSSDBG("hdmi_get_code\n");
@@ -775,7 +789,8 @@ static void hdmi_read_edid(struct omap_video_timings *dp)
code = get_timings_index();
- *dp = cea_vesa_timings[code].timings;
+ copy_hdmi_to_dss_timings(cea_vesa_timings[code].timings, dp);
+
}
static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
@@ -1234,7 +1249,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi_read_edid(p);
}
code = get_timings_index();
- dssdev->panel.timings = cea_vesa_timings[code].timings;
+ copy_hdmi_to_dss_timings(cea_vesa_timings[code].timings,
+ &dssdev->panel.timings);
+
update_hdmi_timings(&hdmi.cfg, p, code);
phy = p->pixel_clock;
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
index f57ef4a..dcc30b7 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/hdmi.h
@@ -188,9 +188,22 @@ struct hdmi_reg { u16 idx; };
#define REG_GET(base, idx, start, end) \
FLD_GET(hdmi_read_reg(base, idx), start, end)
+struct hdmi_video_timings {
+ u16 x_res;
+ u16 y_res;
+ /* Unit: KHz */
+ u32 pixel_clock;
+ u16 hsw;
+ u16 hfp;
+ u16 hbp;
+ u16 vsw;
+ u16 vfp;
+ u16 vbp;
+};
+
/* HDMI timing structure */
struct hdmi_timings {
- struct omap_video_timings timings;
+ struct hdmi_video_timings timings;
int vsync_pol;
int hsync_pol;
};
--
1.7.5.4
^ permalink raw reply related
* [PATCH 2/8] OMAP4 : DSS : HDMI : Move the EDID portion from HDMI IP
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
Clean up to move the EDID definition to hdmi.c from the header file which is IP
dependent.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/omap2/dss/hdmi.c | 10 ++++++++++
drivers/video/omap2/dss/hdmi.h | 10 ----------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 1d16ee2..4ee879a 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -49,6 +49,16 @@
#define HDMI_PLLCTRL 0x200
#define HDMI_PHY 0x300
+/* HDMI EDID Length move this */
+#define HDMI_EDID_MAX_LENGTH 256
+#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
+#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
+#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
+#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
+#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
+
+#define OMAP_HDMI_TIMINGS_NB 34
+
static struct {
struct mutex lock;
struct omap_display_platform_data *pdata;
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
index 2281823..f57ef4a 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/hdmi.h
@@ -182,16 +182,6 @@ struct hdmi_reg { u16 idx; };
#define HDMI_TXPHY_POWER_CTRL HDMI_REG(0x8)
#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_REG(0xC)
-/* HDMI EDID Length */
-#define HDMI_EDID_MAX_LENGTH 256
-#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
-#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
-#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
-#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
-#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
-
-#define OMAP_HDMI_TIMINGS_NB 34
-
#define REG_FLD_MOD(base, idx, val, start, end) \
hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
val, start, end))
--
1.7.5.4
^ permalink raw reply related
* [PATCH 1/8] OMAP4: DSS: HDMI: HDMI clean up to pass base_address
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
As the base_address of the HDMI might differ across SoC's, offset of the HDMI
logical blocks and base address got from the platform data are passed
dynamically to the functions that modify HDMI IP registers.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
drivers/video/omap2/dss/hdmi.c | 518 ++++++++++++++++++++++++----------------
drivers/video/omap2/dss/hdmi.h | 292 +++++++++++------------
2 files changed, 452 insertions(+), 358 deletions(-)
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 5e5b98b..1d16ee2 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -43,11 +43,17 @@
#include "hdmi.h"
#include "dss_features.h"
+#define HDMI_WP 0x0
+#define HDMI_CORE_SYS 0x400
+#define HDMI_CORE_AV 0x900
+#define HDMI_PLLCTRL 0x200
+#define HDMI_PHY 0x300
+
static struct {
struct mutex lock;
struct omap_display_platform_data *pdata;
struct platform_device *pdev;
- void __iomem *base_wp; /* HDMI wrapper */
+ struct hdmi_ip_data hdmi_data;
int code;
int mode;
u8 edid[HDMI_EDID_MAX_LENGTH];
@@ -146,21 +152,51 @@ static const int code_vesa[85] = {
static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
-static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val)
+static inline void hdmi_write_reg(void __iomem *base_addr,
+ const struct hdmi_reg idx, u32 val)
+{
+ __raw_writel(val, base_addr + idx.idx);
+}
+
+static inline u32 hdmi_read_reg(void __iomem *base_addr,
+ const struct hdmi_reg idx)
+{
+ return __raw_readl(base_addr + idx.idx);
+}
+
+static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *) (ip_data->base_wp);
+}
+
+static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
{
- __raw_writel(val, hdmi.base_wp + idx.idx);
+ return (void __iomem *) (ip_data->base_wp + ip_data->hdmi_phy_offset);
}
-static inline u32 hdmi_read_reg(const struct hdmi_reg idx)
+static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
{
- return __raw_readl(hdmi.base_wp + idx.idx);
+ return (void __iomem *) (ip_data->base_wp + ip_data->hdmi_pll_offset);
}
-static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
+static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *)
+ (ip_data->base_wp + ip_data->hdmi_core_av_offset);
+}
+
+static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
+{
+ return (void __iomem *)
+ (ip_data->base_wp + ip_data->hdmi_core_sys_offset);
+}
+
+static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
+ const struct hdmi_reg idx,
int b2, int b1, u32 val)
{
u32 t = 0;
- while (val != REG_GET(idx, b2, b1)) {
+ while (val != REG_GET(base_addr, idx, b2, b1)) {
udelay(1);
if (t++ > 10000)
return !val;
@@ -225,21 +261,22 @@ int hdmi_init_display(struct omap_dss_device *dssdev)
return 0;
}
-static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
+static int hdmi_pll_init(struct hdmi_ip_data *ip_data,
+ enum hdmi_clk_refsel refsel, int dcofreq,
struct hdmi_pll_info *fmt, u16 sd)
{
u32 r;
/* PLL start always use manual mode */
- REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
- r = hdmi_read_reg(PLLCTRL_CFG1);
+ r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1);
r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */
- hdmi_write_reg(PLLCTRL_CFG1, r);
+ hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1, r);
- r = hdmi_read_reg(PLLCTRL_CFG2);
+ r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2);
r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
@@ -247,38 +284,40 @@ static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
if (dcofreq) {
/* divider programming for frequency beyond 1000Mhz */
- REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10);
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_CFG3, sd, 17, 10);
r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
} else {
r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
}
- hdmi_write_reg(PLLCTRL_CFG2, r);
+ hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2, r);
- r = hdmi_read_reg(PLLCTRL_CFG4);
+ r = hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4);
r = FLD_MOD(r, fmt->regm2, 24, 18);
r = FLD_MOD(r, fmt->regmf, 17, 0);
- hdmi_write_reg(PLLCTRL_CFG4, r);
+ hdmi_write_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4, r);
/* go now */
- REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0);
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_GO, 0x1, 0, 0);
/* wait for bit change */
- if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) {
+ if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), PLLCTRL_PLL_GO,
+ 0, 0, 1) != 1) {
DSSERR("PLL GO bit not set\n");
return -ETIMEDOUT;
}
/* Wait till the lock bit is set in PLL status */
- if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
+ if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
+ PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
DSSWARN("cannot lock PLL\n");
DSSWARN("CFG1 0x%x\n",
- hdmi_read_reg(PLLCTRL_CFG1));
+ hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG1));
DSSWARN("CFG2 0x%x\n",
- hdmi_read_reg(PLLCTRL_CFG2));
+ hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG2));
DSSWARN("CFG4 0x%x\n",
- hdmi_read_reg(PLLCTRL_CFG4));
+ hdmi_read_reg(hdmi_pll_base(ip_data), PLLCTRL_CFG4));
return -ETIMEDOUT;
}
@@ -288,13 +327,14 @@ static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
}
/* PHY_PWR_CMD */
-static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val)
+static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
{
/* Command for power control of HDMI PHY */
- REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6);
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6);
/* Status of the power control of HDMI PHY */
- if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
+ if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
+ HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
DSSERR("Failed to set PHY power mode to %d\n", val);
return -ETIMEDOUT;
}
@@ -303,13 +343,14 @@ static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val)
}
/* PLL_PWR_CMD */
-static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val)
+int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
{
/* Command for power control of HDMI PLL */
- REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2);
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
/* wait till PHY_PWR_STATUS is set */
- if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) {
+ if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
+ 1, 0, val) != val) {
DSSERR("Failed to set PHY_PWR_STATUS\n");
return -ETIMEDOUT;
}
@@ -317,13 +358,14 @@ static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val)
return 0;
}
-static int hdmi_pll_reset(void)
+static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
{
/* SYSRESET controlled by power FSM */
- REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
+ REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
/* READ 0x0 reset is in progress */
- if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
+ if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
+ PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
DSSERR("Failed to sysreset PLL\n");
return -ETIMEDOUT;
}
@@ -331,15 +373,15 @@ static int hdmi_pll_reset(void)
return 0;
}
-static int hdmi_phy_init(void)
+static int hdmi_phy_init(struct hdmi_ip_data *ip_data)
{
u16 r = 0;
- r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON);
+ r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
if (r)
return r;
- r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
+ r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
if (r)
return r;
@@ -347,65 +389,69 @@ static int hdmi_phy_init(void)
* Read address 0 in order to get the SCP reset done completed
* Dummy access performed to make sure reset is done
*/
- hdmi_read_reg(HDMI_TXPHY_TX_CTRL);
+ hdmi_read_reg(hdmi_phy_base(ip_data), HDMI_TXPHY_TX_CTRL);
/*
* Write to phy address 0 to configure the clock
* use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
*/
- REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
+ REG_FLD_MOD(hdmi_phy_base(ip_data), HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
/* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
- hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
+ hdmi_write_reg(hdmi_phy_base(ip_data),
+ HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
/* Setup max LDO voltage */
- REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
+ REG_FLD_MOD(hdmi_phy_base(ip_data), HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
/* Write to phy address 3 to change the polarity control */
- REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+ REG_FLD_MOD(hdmi_phy_base(ip_data),
+ HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
return 0;
}
-static int hdmi_pll_program(struct hdmi_pll_info *fmt)
+static int hdmi_pll_program(struct hdmi_ip_data *ip_data,
+ struct hdmi_pll_info *fmt)
{
u16 r = 0;
enum hdmi_clk_refsel refsel;
- r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
+ r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
if (r)
return r;
- r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
+ r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
if (r)
return r;
- r = hdmi_pll_reset();
+ r = hdmi_pll_reset(ip_data);
if (r)
return r;
refsel = HDMI_REFSEL_SYSCLK;
- r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd);
+ r = hdmi_pll_init(ip_data, refsel, fmt->dcofreq, fmt, fmt->regsd);
if (r)
return r;
return 0;
}
-static void hdmi_phy_off(void)
+static void hdmi_phy_off(struct hdmi_ip_data *ip_data)
{
- hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
}
-static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
+ u8 *pedid, int ext)
{
u32 i, j;
char checksum = 0;
u32 offset = 0;
/* Turn on CLK for DDC */
- REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_DPD, 0x7, 2, 0);
/*
* SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
@@ -416,21 +462,23 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
if (!ext) {
/* Clk SCL Devices */
- REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_CMD, 0xA, 3, 0);
/* HDMI_CORE_DDC_STATUS_IN_PROG */
- if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
- 4, 4, 0) != 0) {
+ if (hdmi_wait_for_bit_change(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
DSSERR("Failed to program DDC\n");
return -ETIMEDOUT;
}
/* Clear FIFO */
- REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data)
+ , HDMI_CORE_DDC_CMD, 0x9, 3, 0);
/* HDMI_CORE_DDC_STATUS_IN_PROG */
- if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
- 4, 4, 0) != 0) {
+ if (hdmi_wait_for_bit_change(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
DSSERR("Failed to program DDC\n");
return -ETIMEDOUT;
}
@@ -441,44 +489,56 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
}
/* Load Segment Address Register */
- REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
/* Load Slave Address Register */
- REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
/* Load Offset Address Register */
- REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_OFFSET, offset, 7, 0);
/* Load Byte Count */
- REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
- REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
/* Set DDC_CMD */
if (ext)
- REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_CMD, 0x4, 3, 0);
else
- REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_CMD, 0x2, 3, 0);
/* HDMI_CORE_DDC_STATUS_BUS_LOW */
- if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) = 1) {
+ if (REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 6, 6) = 1) {
DSSWARN("I2C Bus Low?\n");
return -EIO;
}
/* HDMI_CORE_DDC_STATUS_NO_ACK */
- if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) = 1) {
+ if (REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 5, 5) = 1) {
DSSWARN("I2C No Ack\n");
return -EIO;
}
i = ext * 128;
j = 0;
- while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) = 1) ||
- (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) = 0)) &&
- j < 128) {
+ while (((REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 4, 4) = 1) ||
+ (REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_STATUS, 2, 2) = 0)) && j < 128) {
- if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) = 0) {
+ if (REG_GET(hdmi_core_sys_base(ip_data)
+ , HDMI_CORE_DDC_STATUS, 2, 2) = 0) {
/* FIFO not empty */
- pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
+ pedid[i++] = REG_GET(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_DDC_DATA, 7, 0);
j++;
}
}
@@ -494,12 +554,12 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
return 0;
}
-static int read_edid(u8 *pedid, u16 max_length)
+static int read_edid(struct hdmi_ip_data *ip_data, u8 *pedid, u16 max_length)
{
int r = 0, n = 0, i = 0;
int max_ext_blocks = (max_length / 128) - 1;
- r = hdmi_core_ddc_edid(pedid, 0);
+ r = hdmi_core_ddc_edid(ip_data, pedid, 0);
if (r) {
return r;
} else {
@@ -515,7 +575,7 @@ static int read_edid(u8 *pedid, u16 max_length)
n = max_ext_blocks;
for (i = 1; i <= n; i++) {
- r = hdmi_core_ddc_edid(pedid, i);
+ r = hdmi_core_ddc_edid(ip_data, pedid, i);
if (r)
return r;
}
@@ -685,8 +745,8 @@ static void hdmi_read_edid(struct omap_video_timings *dp)
memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
if (!hdmi.edid_set)
- ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
-
+ ret = read_edid(&hdmi.hdmi_data, hdmi.edid,
+ HDMI_EDID_MAX_LENGTH);
if (!ret) {
if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
/* search for timings of default resolution */
@@ -752,41 +812,43 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
repeat_cfg->generic_pkt_repeat = 0;
}
-static void hdmi_core_powerdown_disable(void)
+static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data)
{
DSSDBG("Enter hdmi_core_powerdown_disable\n");
- REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
}
-static void hdmi_core_swreset_release(void)
+static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
{
DSSDBG("Enter hdmi_core_swreset_release\n");
- REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0);
}
-static void hdmi_core_swreset_assert(void)
+static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data)
{
DSSDBG("Enter hdmi_core_swreset_assert\n");
- REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0);
}
-/* DSS_HDMI_CORE_VIDEO_CONFIG */
-static void hdmi_core_video_config(struct hdmi_core_video_config *cfg)
+/* HDMI_CORE_VIDEO_CONFIG */
+static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_video_config *cfg)
{
u32 r = 0;
/* sys_ctrl1 default configuration not tunable */
- r = hdmi_read_reg(HDMI_CORE_CTRL1);
+ r = hdmi_read_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1);
r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
- hdmi_write_reg(HDMI_CORE_CTRL1, r);
+ hdmi_write_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, r);
- REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
/* Vid_Mode */
- r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE);
+ r = hdmi_read_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_VID_MODE);
/* dither truncation configuration */
if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
@@ -796,106 +858,107 @@ static void hdmi_core_video_config(struct hdmi_core_video_config *cfg)
r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
r = FLD_MOD(r, 0, 5, 5);
}
- hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r);
+ hdmi_write_reg(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_VID_MODE, r);
/* HDMI_Ctrl */
- r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL);
+ r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL);
r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
- hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r);
/* TMDS_CTRL */
- REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL,
- cfg->tclk_sel_clkmult, 6, 5);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
}
-static void hdmi_core_aux_infoframe_avi_config(
+static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_infoframe_avi info_avi)
{
u32 val;
char sum = 0, checksum = 0;
sum += 0x82 + 0x002 + 0x00D;
- hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082);
- hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002);
- hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_TYPE, 0x082);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_VERS, 0x002);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_LEN, 0x00D);
val = (info_avi.db1_format << 5) |
(info_avi.db1_active_info << 4) |
(info_avi.db1_bar_info_dv << 2) |
(info_avi.db1_scan_info);
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(0), val);
sum += val;
val = (info_avi.db2_colorimetry << 6) |
(info_avi.db2_aspect_ratio << 4) |
(info_avi.db2_active_fmt_ar);
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(1), val);
sum += val;
val = (info_avi.db3_itc << 7) |
(info_avi.db3_ec << 4) |
(info_avi.db3_q_range << 2) |
(info_avi.db3_nup_scaling);
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(2), val);
sum += val;
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(3),
+ info_avi.db4_videocode);
sum += info_avi.db4_videocode;
val = info_avi.db5_pixel_repeat;
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(4), val);
sum += val;
val = info_avi.db6_7_line_eoftop & 0x00FF;
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(5), val);
sum += val;
val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(6), val);
sum += val;
val = info_avi.db8_9_line_sofbottom & 0x00FF;
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(7), val);
sum += val;
val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(8), val);
sum += val;
val = info_avi.db10_11_pixel_eofleft & 0x00FF;
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(9), val);
sum += val;
val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(10), val);
sum += val;
val = info_avi.db12_13_pixel_sofright & 0x00FF;
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(11), val);
sum += val;
val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
- hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_DBYTE(12), val);
sum += val;
checksum = 0x100 - sum;
- hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AVI_CHSUM, checksum);
}
-static void hdmi_core_av_packet_config(
+static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_packet_enable_repeat repeat_cfg)
{
/* enable/repeat the infoframe */
- hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1,
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1,
(repeat_cfg.audio_pkt << 5) |
(repeat_cfg.audio_pkt_repeat << 4) |
(repeat_cfg.avi_infoframe << 1) |
(repeat_cfg.avi_infoframe_repeat));
/* enable/repeat the packet */
- hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2,
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2,
(repeat_cfg.gen_cntrl_pkt << 3) |
(repeat_cfg.gen_cntrl_pkt_repeat << 2) |
(repeat_cfg.generic_pkt << 1) |
@@ -927,9 +990,9 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
}
-static void hdmi_wp_video_start(bool start)
+static void hdmi_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
{
- REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31);
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
}
static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
@@ -948,33 +1011,34 @@ static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
timings->vsw = param->timings.timings.vsw;
}
-static void hdmi_wp_video_config_format(
+static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
struct hdmi_video_format *video_fmt)
{
u32 l = 0;
- REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8);
+ REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG,
+ video_fmt->packing_mode, 10, 8);
l |= FLD_VAL(video_fmt->y_res, 31, 16);
l |= FLD_VAL(video_fmt->x_res, 15, 0);
- hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
}
-static void hdmi_wp_video_config_interface(
+static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data,
struct hdmi_video_interface *video_int)
{
u32 r;
DSSDBG("Enter hdmi_wp_video_config_interface\n");
- r = hdmi_read_reg(HDMI_WP_VIDEO_CFG);
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
r = FLD_MOD(r, video_int->vsp, 7, 7);
r = FLD_MOD(r, video_int->hsp, 6, 6);
r = FLD_MOD(r, video_int->interlacing, 3, 3);
r = FLD_MOD(r, video_int->tm, 1, 0);
- hdmi_write_reg(HDMI_WP_VIDEO_CFG, r);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
}
-static void hdmi_wp_video_config_timing(
+static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
struct omap_video_timings *timings)
{
u32 timing_h = 0;
@@ -985,15 +1049,16 @@ static void hdmi_wp_video_config_timing(
timing_h |= FLD_VAL(timings->hbp, 31, 20);
timing_h |= FLD_VAL(timings->hfp, 19, 8);
timing_h |= FLD_VAL(timings->hsw, 7, 0);
- hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h);
timing_v |= FLD_VAL(timings->vbp, 31, 20);
timing_v |= FLD_VAL(timings->vfp, 19, 8);
timing_v |= FLD_VAL(timings->vsw, 7, 0);
- hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
}
-static void hdmi_basic_configure(struct hdmi_config *cfg)
+static void hdmi_basic_configure(struct hdmi_ip_data *ip_data,
+ struct hdmi_config *cfg)
{
/* HDMI */
struct omap_video_timings video_timing;
@@ -1014,36 +1079,36 @@ static void hdmi_basic_configure(struct hdmi_config *cfg)
hdmi_wp_video_init_format(&video_format,
&video_timing, cfg);
- hdmi_wp_video_config_timing(&video_timing);
+ hdmi_wp_video_config_timing(ip_data, &video_timing);
/* video config */
video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
- hdmi_wp_video_config_format(&video_format);
+ hdmi_wp_video_config_format(ip_data, &video_format);
video_interface.vsp = cfg->timings.vsync_pol;
video_interface.hsp = cfg->timings.hsync_pol;
video_interface.interlacing = cfg->interlace;
video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
- hdmi_wp_video_config_interface(&video_interface);
+ hdmi_wp_video_config_interface(ip_data, &video_interface);
/*
* configure core video part
* set software reset in the core
*/
- hdmi_core_swreset_assert();
+ hdmi_core_swreset_assert(ip_data);
/* power down off */
- hdmi_core_powerdown_disable();
+ hdmi_core_powerdown_disable(ip_data);
v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
v_core_cfg.hdmi_dvi = cfg->cm.mode;
- hdmi_core_video_config(&v_core_cfg);
+ hdmi_core_video_config(ip_data, &v_core_cfg);
/* release software reset in the core */
- hdmi_core_swreset_release();
+ hdmi_core_swreset_release(ip_data);
/*
* configure packet
@@ -1068,7 +1133,7 @@ static void hdmi_basic_configure(struct hdmi_config *cfg)
avi_cfg.db10_11_pixel_eofleft = 0;
avi_cfg.db12_13_pixel_sofright = 0;
- hdmi_core_aux_infoframe_avi_config(avi_cfg);
+ hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg);
/* enable/repeat the infoframe */
repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
@@ -1076,7 +1141,7 @@ static void hdmi_basic_configure(struct hdmi_config *cfg)
/* wakeup */
repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
- hdmi_core_av_packet_config(repeat_cfg);
+ hdmi_core_av_packet_config(ip_data, repeat_cfg);
}
static void update_hdmi_timings(struct hdmi_config *cfg,
@@ -1166,16 +1231,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi_compute_pll(dssdev, phy, &pll_data);
- hdmi_wp_video_start(0);
+ hdmi_wp_video_start(&hdmi.hdmi_data, 0);
- /* config the PLL and PHY first */
- r = hdmi_pll_program(&pll_data);
+ /* config the PLL and PHY hdmi_set_pll_pwrfirst */
+ r = hdmi_pll_program(&hdmi.hdmi_data, &pll_data);
if (r) {
DSSDBG("Failed to lock PLL\n");
goto err;
}
- r = hdmi_phy_init();
+ r = hdmi_phy_init(&hdmi.hdmi_data);
if (r) {
DSSDBG("Failed to start PHY\n");
goto err;
@@ -1183,7 +1248,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi.cfg.cm.mode = hdmi.mode;
hdmi.cfg.cm.code = hdmi.code;
- hdmi_basic_configure(&hdmi.cfg);
+ hdmi_basic_configure(&hdmi.hdmi_data, &hdmi.cfg);
/* Make selection of HDMI in DSS */
dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
@@ -1205,7 +1270,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1);
- hdmi_wp_video_start(1);
+ hdmi_wp_video_start(&hdmi.hdmi_data, 1);
return 0;
err:
@@ -1217,9 +1282,9 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
{
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
- hdmi_wp_video_start(0);
- hdmi_phy_off();
- hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
+ hdmi_wp_video_start(&hdmi.hdmi_data, 0);
+ hdmi_phy_off(&hdmi.hdmi_data);
+ hdmi_set_pll_pwr(&hdmi.hdmi_data, HDMI_PLLPWRCMD_ALLOFF);
hdmi_runtime_put();
hdmi.edid_set = 0;
@@ -1311,14 +1376,14 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-static void hdmi_wp_audio_config_format(
- struct hdmi_audio_format *aud_fmt)
+static void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
+ struct hdmi_audio_format *aud_fmt)
{
u32 r;
DSSDBG("Enter hdmi_wp_audio_config_format\n");
- r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG);
r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
@@ -1327,68 +1392,81 @@ static void hdmi_wp_audio_config_format(
r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
- hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
}
-static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
+static void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
+ struct hdmi_audio_dma *aud_dma)
{
u32 r;
DSSDBG("Enter hdmi_wp_audio_config_dma\n");
- r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2);
r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
r = FLD_MOD(r, aud_dma->block_size, 7, 0);
- hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r);
- r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
+ r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL);
r = FLD_MOD(r, aud_dma->mode, 9, 9);
r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
- hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
}
-static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
+static void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
+ struct hdmi_core_audio_config *cfg)
{
u32 r;
/* audio clock recovery parameters */
- r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
+ r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_ACR_CTRL);
r = FLD_MOD(r, cfg->use_mclk, 2, 2);
r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
r = FLD_MOD(r, cfg->cts_mode, 0, 0);
- hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_ACR_CTRL, r);
- REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
if (cfg->cts_mode = HDMI_AUDIO_CTS_MODE_SW) {
- REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
} else {
/*
* HDMI IP uses this configuration to divide the MCLK to
* update CTS value.
*/
- REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
/* Configure clock for audio packets */
- REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
- cfg->aud_par_busclk, 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
- (cfg->aud_par_busclk >> 8), 7, 0);
- REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
- (cfg->aud_par_busclk >> 16), 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
+ cfg->aud_par_busclk, 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
+ (cfg->aud_par_busclk >> 8), 7, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
+ (cfg->aud_par_busclk >> 16), 7, 0);
}
/* Override of SPDIF sample frequency with value in I2S_CHST4 */
- REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
+ REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_SPDIF_CTRL,
+ cfg->fs_override, 1, 1);
/* I2S parameters */
- REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_I2S_CHST4,
+ cfg->freq_sample, 3, 0);
- r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
+ r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_I2S_IN_CTRL);
r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
@@ -1397,27 +1475,29 @@ static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
- hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_I2S_IN_CTRL, r);
- r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
+ r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_I2S_CHST5);
r = FLD_MOD(r, cfg->freq_sample, 7, 4);
r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
- hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_I2S_CHST5, r);
- REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
+ REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_I2S_IN_LEN,
+ cfg->i2s_cfg.in_length_bits, 3, 0);
/* Audio channels and mode parameters */
- REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
- r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
+ REG_FLD_MOD(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL,
+ cfg->layout, 2, 1);
+ r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_MODE);
r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
r = FLD_MOD(r, cfg->en_spdif, 1, 1);
- hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_MODE, r);
}
-static void hdmi_core_audio_infoframe_config(
+static void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_infoframe_audio *info_aud)
{
u8 val;
@@ -1428,38 +1508,39 @@ static void hdmi_core_audio_infoframe_config(
* described in HDMI 1.4a Section 8.2.2 specification.
* Checksum calculation is defined in Section 5.3.5.
*/
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUDIO_TYPE, 0x84);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUDIO_VERS, 0x01);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUDIO_LEN, 0x0a);
sum += 0x84 + 0x001 + 0x00a;
val = (info_aud->db1_coding_type << 4)
| (info_aud->db1_channel_count - 1);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(0), val);
sum += val;
val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(1), val);
sum += val;
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
val = info_aud->db4_channel_alloc;
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(3), val);
sum += val;
val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(4), val);
sum += val;
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
- hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
+ hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
checksum = 0x100 - sum;
- hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
+ hdmi_write_reg(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUDIO_CHSUM, checksum);
/*
* TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
@@ -1467,7 +1548,8 @@ static void hdmi_core_audio_infoframe_config(
*/
}
-static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
+static int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
+ u32 sample_freq, u32 *n, u32 *cts)
{
u32 r;
u32 deep_color = 0;
@@ -1479,7 +1561,7 @@ static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
* Obtain current deep color configuration. This needed
* to calculate the TMDS clock based on the pixel clock.
*/
- r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
+ r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0);
switch (r) {
case 1: /* No deep color selected */
deep_color = 100;
@@ -1523,7 +1605,8 @@ static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
return 0;
}
-static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data,
+ struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
@@ -1577,7 +1660,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- err = hdmi_config_audio_acr(params_rate(params), &n, &cts);
+ err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts);
if (err < 0)
return err;
@@ -1593,8 +1676,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
audio_dma.fifo_threshold = 0x20; /* in number of samples */
- hdmi_wp_audio_config_dma(&audio_dma);
- hdmi_wp_audio_config_format(&audio_format);
+ hdmi_wp_audio_config_dma(ip_data, &audio_dma);
+ hdmi_wp_audio_config_format(ip_data, &audio_format);
/*
* I2S config
@@ -1638,7 +1721,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
/* Use parallel audio interface */
core_cfg.en_parallel_aud_input = true;
- hdmi_core_audio_config(&core_cfg);
+ hdmi_core_audio_config(ip_data, &core_cfg);
/*
* Configure packet
@@ -1652,29 +1735,36 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
aud_if_cfg.db5_downmix_inh = false;
aud_if_cfg.db5_lsv = 0;
- hdmi_core_audio_infoframe_config(&aud_if_cfg);
+ hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg);
return 0;
}
-static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
+ struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
{
int err = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 1, 31, 31);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 1, 30, 30);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
- REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 0, 30, 30);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, 0, 31, 31);
break;
default:
err = -EINVAL;
@@ -1765,20 +1855,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
}
/* Base address taken from platform */
- hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem));
- if (!hdmi.base_wp) {
+ hdmi.hdmi_data.base_wp = ioremap(hdmi_mem->start,
+ resource_size(hdmi_mem));
+ if (!hdmi.hdmi_data.base_wp) {
DSSERR("can't ioremap WP\n");
return -ENOMEM;
}
r = hdmi_get_clocks(pdev);
if (r) {
- iounmap(hdmi.base_wp);
+ iounmap(hdmi.hdmi_data.base_wp);
return r;
}
pm_runtime_enable(&pdev->dev);
+ hdmi.hdmi_data.hdmi_core_sys_offset = HDMI_CORE_SYS;
+ hdmi.hdmi_data.hdmi_core_av_offset = HDMI_CORE_AV;
+ hdmi.hdmi_data.hdmi_pll_offset = HDMI_PLLCTRL;
+ hdmi.hdmi_data.hdmi_phy_offset = HDMI_PHY;
+
hdmi_panel_init();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
@@ -1808,7 +1904,7 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
hdmi_put_clocks();
- iounmap(hdmi.base_wp);
+ iounmap(hdmi.hdmi_data.base_wp);
return 0;
}
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
index c885f9c..2281823 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/hdmi.h
@@ -24,174 +24,163 @@
#include <linux/string.h>
#include <video/omapdss.h>
-#define HDMI_WP 0x0
-#define HDMI_CORE_SYS 0x400
-#define HDMI_CORE_AV 0x900
-#define HDMI_PLLCTRL 0x200
-#define HDMI_PHY 0x300
-
struct hdmi_reg { u16 idx; };
#define HDMI_REG(idx) ((const struct hdmi_reg) { idx })
/* HDMI Wrapper */
-#define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx)
-
-#define HDMI_WP_REVISION HDMI_WP_REG(0x0)
-#define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10)
-#define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24)
-#define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28)
-#define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40)
-#define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C)
-#define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50)
-#define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60)
-#define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68)
-#define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C)
-#define HDMI_WP_WP_CLK HDMI_WP_REG(0x70)
-#define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80)
-#define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84)
-#define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88)
-#define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C)
+
+#define HDMI_WP_REVISION HDMI_REG(0x0)
+#define HDMI_WP_SYSCONFIG HDMI_REG(0x10)
+#define HDMI_WP_IRQSTATUS_RAW HDMI_REG(0x24)
+#define HDMI_WP_IRQSTATUS HDMI_REG(0x28)
+#define HDMI_WP_PWR_CTRL HDMI_REG(0x40)
+#define HDMI_WP_IRQENABLE_SET HDMI_REG(0x2C)
+#define HDMI_WP_VIDEO_CFG HDMI_REG(0x50)
+#define HDMI_WP_VIDEO_SIZE HDMI_REG(0x60)
+#define HDMI_WP_VIDEO_TIMING_H HDMI_REG(0x68)
+#define HDMI_WP_VIDEO_TIMING_V HDMI_REG(0x6C)
+#define HDMI_WP_WP_CLK HDMI_REG(0x70)
+#define HDMI_WP_AUDIO_CFG HDMI_REG(0x80)
+#define HDMI_WP_AUDIO_CFG2 HDMI_REG(0x84)
+#define HDMI_WP_AUDIO_CTRL HDMI_REG(0x88)
+#define HDMI_WP_AUDIO_DATA HDMI_REG(0x8C)
/* HDMI IP Core System */
-#define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx)
-
-#define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0)
-#define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8)
-#define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC)
-#define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10)
-#define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14)
-#define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20)
-#define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24)
-#define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124)
-#define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128)
-#define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0)
-#define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4)
-#define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8)
-#define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC)
-#define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0)
-#define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4)
-#define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208)
-#define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8)
-#define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC)
-#define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0)
-#define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8)
-#define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC)
-#define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0)
-#define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4)
+
+#define HDMI_CORE_SYS_VND_IDL HDMI_REG(0x0)
+#define HDMI_CORE_SYS_DEV_IDL HDMI_REG(0x8)
+#define HDMI_CORE_SYS_DEV_IDH HDMI_REG(0xC)
+#define HDMI_CORE_SYS_DEV_REV HDMI_REG(0x10)
+#define HDMI_CORE_SYS_SRST HDMI_REG(0x14)
+#define HDMI_CORE_CTRL1 HDMI_REG(0x20)
+#define HDMI_CORE_SYS_SYS_STAT HDMI_REG(0x24)
+#define HDMI_CORE_SYS_VID_ACEN HDMI_REG(0x124)
+#define HDMI_CORE_SYS_VID_MODE HDMI_REG(0x128)
+#define HDMI_CORE_SYS_INTR_STATE HDMI_REG(0x1C0)
+#define HDMI_CORE_SYS_INTR1 HDMI_REG(0x1C4)
+#define HDMI_CORE_SYS_INTR2 HDMI_REG(0x1C8)
+#define HDMI_CORE_SYS_INTR3 HDMI_REG(0x1CC)
+#define HDMI_CORE_SYS_INTR4 HDMI_REG(0x1D0)
+#define HDMI_CORE_SYS_UMASK1 HDMI_REG(0x1D4)
+#define HDMI_CORE_SYS_TMDS_CTRL HDMI_REG(0x208)
+#define HDMI_CORE_SYS_DE_DLY HDMI_REG(0xC8)
+#define HDMI_CORE_SYS_DE_CTRL HDMI_REG(0xCC)
+#define HDMI_CORE_SYS_DE_TOP HDMI_REG(0xD0)
+#define HDMI_CORE_SYS_DE_CNTL HDMI_REG(0xD8)
+#define HDMI_CORE_SYS_DE_CNTH HDMI_REG(0xDC)
+#define HDMI_CORE_SYS_DE_LINL HDMI_REG(0xE0)
+#define HDMI_CORE_SYS_DE_LINH_1 HDMI_REG(0xE4)
#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
/* HDMI DDC E-DID */
-#define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC)
-#define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8)
-#define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4)
-#define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC)
-#define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0)
-#define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4)
-#define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0)
-#define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8)
+#define HDMI_CORE_DDC_CMD HDMI_REG(0x3CC)
+#define HDMI_CORE_DDC_STATUS HDMI_REG(0x3C8)
+#define HDMI_CORE_DDC_ADDR HDMI_REG(0x3B4)
+#define HDMI_CORE_DDC_OFFSET HDMI_REG(0x3BC)
+#define HDMI_CORE_DDC_COUNT1 HDMI_REG(0x3C0)
+#define HDMI_CORE_DDC_COUNT2 HDMI_REG(0x3C4)
+#define HDMI_CORE_DDC_DATA HDMI_REG(0x3D0)
+#define HDMI_CORE_DDC_SEGM HDMI_REG(0x3B8)
/* HDMI IP Core Audio Video */
-#define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx)
-
-#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC)
-#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4)
-#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8)
-#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC)
-#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100)
-#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104)
-#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108)
-#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C)
-#define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110)
-#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15)
-#define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190)
-#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
-#define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210)
-#define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10)
-#define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290)
-#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
-#define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300)
-#define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31)
-#define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380)
-#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31)
-#define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4)
-#define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8)
-#define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC)
-#define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10)
-#define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14)
-#define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18)
-#define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C)
-#define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20)
-#define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24)
-#define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28)
-#define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C)
-#define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50)
-#define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54)
-#define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60)
-#define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64)
-#define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C)
-#define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70)
-#define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74)
-#define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78)
-#define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C)
-#define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80)
-#define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84)
-#define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88)
-#define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C)
-#define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90)
-#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC)
-#define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0)
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC)
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0)
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4)
-#define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0)
-#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4)
-#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8)
-#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC)
-#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100)
-#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104)
-#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108)
-#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C)
-#define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180)
-#define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184)
-#define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188)
-#define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C)
-#define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200)
-#define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204)
-#define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208)
-#define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C)
-#define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280)
-#define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284)
-#define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288)
-#define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C)
-#define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C)
-#define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC)
+
+#define HDMI_CORE_AV_HDMI_CTRL HDMI_REG(0xBC)
+#define HDMI_CORE_AV_DPD HDMI_REG(0xF4)
+#define HDMI_CORE_AV_PB_CTRL1 HDMI_REG(0xF8)
+#define HDMI_CORE_AV_PB_CTRL2 HDMI_REG(0xFC)
+#define HDMI_CORE_AV_AVI_TYPE HDMI_REG(0x100)
+#define HDMI_CORE_AV_AVI_VERS HDMI_REG(0x104)
+#define HDMI_CORE_AV_AVI_LEN HDMI_REG(0x108)
+#define HDMI_CORE_AV_AVI_CHSUM HDMI_REG(0x10C)
+#define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_REG(n * 4 + 0x110)
+#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_REG(15)
+#define HDMI_CORE_AV_SPD_DBYTE HDMI_REG(0x190)
+#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_REG(27)
+#define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_REG(n * 4 + 0x210)
+#define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_REG(10)
+#define HDMI_CORE_AV_MPEG_DBYTE HDMI_REG(0x290)
+#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_REG(27)
+#define HDMI_CORE_AV_GEN_DBYTE HDMI_REG(0x300)
+#define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_REG(31)
+#define HDMI_CORE_AV_GEN2_DBYTE HDMI_REG(0x380)
+#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_REG(31)
+#define HDMI_CORE_AV_ACR_CTRL HDMI_REG(0x4)
+#define HDMI_CORE_AV_FREQ_SVAL HDMI_REG(0x8)
+#define HDMI_CORE_AV_N_SVAL1 HDMI_REG(0xC)
+#define HDMI_CORE_AV_N_SVAL2 HDMI_REG(0x10)
+#define HDMI_CORE_AV_N_SVAL3 HDMI_REG(0x14)
+#define HDMI_CORE_AV_CTS_SVAL1 HDMI_REG(0x18)
+#define HDMI_CORE_AV_CTS_SVAL2 HDMI_REG(0x1C)
+#define HDMI_CORE_AV_CTS_SVAL3 HDMI_REG(0x20)
+#define HDMI_CORE_AV_CTS_HVAL1 HDMI_REG(0x24)
+#define HDMI_CORE_AV_CTS_HVAL2 HDMI_REG(0x28)
+#define HDMI_CORE_AV_CTS_HVAL3 HDMI_REG(0x2C)
+#define HDMI_CORE_AV_AUD_MODE HDMI_REG(0x50)
+#define HDMI_CORE_AV_SPDIF_CTRL HDMI_REG(0x54)
+#define HDMI_CORE_AV_HW_SPDIF_FS HDMI_REG(0x60)
+#define HDMI_CORE_AV_SWAP_I2S HDMI_REG(0x64)
+#define HDMI_CORE_AV_SPDIF_ERTH HDMI_REG(0x6C)
+#define HDMI_CORE_AV_I2S_IN_MAP HDMI_REG(0x70)
+#define HDMI_CORE_AV_I2S_IN_CTRL HDMI_REG(0x74)
+#define HDMI_CORE_AV_I2S_CHST0 HDMI_REG(0x78)
+#define HDMI_CORE_AV_I2S_CHST1 HDMI_REG(0x7C)
+#define HDMI_CORE_AV_I2S_CHST2 HDMI_REG(0x80)
+#define HDMI_CORE_AV_I2S_CHST4 HDMI_REG(0x84)
+#define HDMI_CORE_AV_I2S_CHST5 HDMI_REG(0x88)
+#define HDMI_CORE_AV_ASRC HDMI_REG(0x8C)
+#define HDMI_CORE_AV_I2S_IN_LEN HDMI_REG(0x90)
+#define HDMI_CORE_AV_HDMI_CTRL HDMI_REG(0xBC)
+#define HDMI_CORE_AV_AUDO_TXSTAT HDMI_REG(0xC0)
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_REG(0xCC)
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_REG(0xD0)
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_REG(0xD4)
+#define HDMI_CORE_AV_TEST_TXCTRL HDMI_REG(0xF0)
+#define HDMI_CORE_AV_DPD HDMI_REG(0xF4)
+#define HDMI_CORE_AV_PB_CTRL1 HDMI_REG(0xF8)
+#define HDMI_CORE_AV_PB_CTRL2 HDMI_REG(0xFC)
+#define HDMI_CORE_AV_AVI_TYPE HDMI_REG(0x100)
+#define HDMI_CORE_AV_AVI_VERS HDMI_REG(0x104)
+#define HDMI_CORE_AV_AVI_LEN HDMI_REG(0x108)
+#define HDMI_CORE_AV_AVI_CHSUM HDMI_REG(0x10C)
+#define HDMI_CORE_AV_SPD_TYPE HDMI_REG(0x180)
+#define HDMI_CORE_AV_SPD_VERS HDMI_REG(0x184)
+#define HDMI_CORE_AV_SPD_LEN HDMI_REG(0x188)
+#define HDMI_CORE_AV_SPD_CHSUM HDMI_REG(0x18C)
+#define HDMI_CORE_AV_AUDIO_TYPE HDMI_REG(0x200)
+#define HDMI_CORE_AV_AUDIO_VERS HDMI_REG(0x204)
+#define HDMI_CORE_AV_AUDIO_LEN HDMI_REG(0x208)
+#define HDMI_CORE_AV_AUDIO_CHSUM HDMI_REG(0x20C)
+#define HDMI_CORE_AV_MPEG_TYPE HDMI_REG(0x280)
+#define HDMI_CORE_AV_MPEG_VERS HDMI_REG(0x284)
+#define HDMI_CORE_AV_MPEG_LEN HDMI_REG(0x288)
+#define HDMI_CORE_AV_MPEG_CHSUM HDMI_REG(0x28C)
+#define HDMI_CORE_AV_CP_BYTE1 HDMI_REG(0x37C)
+#define HDMI_CORE_AV_CEC_ADDR_ID HDMI_REG(0x3FC)
#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
/* PLL */
-#define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx)
-#define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0)
-#define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4)
-#define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8)
-#define PLLCTRL_CFG1 HDMI_PLL_REG(0xC)
-#define PLLCTRL_CFG2 HDMI_PLL_REG(0x10)
-#define PLLCTRL_CFG3 HDMI_PLL_REG(0x14)
-#define PLLCTRL_CFG4 HDMI_PLL_REG(0x20)
+#define PLLCTRL_PLL_CONTROL HDMI_REG(0x0)
+#define PLLCTRL_PLL_STATUS HDMI_REG(0x4)
+#define PLLCTRL_PLL_GO HDMI_REG(0x8)
+#define PLLCTRL_CFG1 HDMI_REG(0xC)
+#define PLLCTRL_CFG2 HDMI_REG(0x10)
+#define PLLCTRL_CFG3 HDMI_REG(0x14)
+#define PLLCTRL_CFG4 HDMI_REG(0x20)
/* HDMI PHY */
-#define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx)
-#define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0)
-#define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4)
-#define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8)
-#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC)
+#define HDMI_TXPHY_TX_CTRL HDMI_REG(0x0)
+#define HDMI_TXPHY_DIGITAL_CTRL HDMI_REG(0x4)
+#define HDMI_TXPHY_POWER_CTRL HDMI_REG(0x8)
+#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_REG(0xC)
/* HDMI EDID Length */
#define HDMI_EDID_MAX_LENGTH 256
@@ -203,10 +192,11 @@ struct hdmi_reg { u16 idx; };
#define OMAP_HDMI_TIMINGS_NB 34
-#define REG_FLD_MOD(idx, val, start, end) \
- hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end))
-#define REG_GET(idx, start, end) \
- FLD_GET(hdmi_read_reg(idx), start, end)
+#define REG_FLD_MOD(base, idx, val, start, end) \
+ hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
+ val, start, end))
+#define REG_GET(base, idx, start, end) \
+ FLD_GET(hdmi_read_reg(base, idx), start, end)
/* HDMI timing structure */
struct hdmi_timings {
@@ -568,6 +558,14 @@ struct hdmi_video_interface {
int tm; /* Timing mode */
};
+struct hdmi_ip_data {
+ void __iomem *base_wp; /* HDMI wrapper */
+ unsigned long hdmi_core_sys_offset;
+ unsigned long hdmi_core_av_offset;
+ unsigned long hdmi_pll_offset;
+ unsigned long hdmi_phy_offset;
+};
+
struct hdmi_cm {
int code;
int mode;
--
1.7.5.4
^ permalink raw reply related
* [PATCH 0/8] HDMI: Split hdmi.c to seperate HDMI IP dependant code from DSS.
From: Mythri P K @ 2011-06-22 11:55 UTC (permalink / raw)
To: linux-fbdev
HDMI IP block is common between TI OMAP4 Procerssor and Netra processor although
the Display subsytem is different. Thus to reuse the code between these two
processors , HDMI IP dependant code is seperated out from hdmi.c and moved to
new library file hdmi_ti_4xxx_ip.c which now resides in /drivers/video a more
generic location out of omap2/dss folder.
This patch series does the split and also renames hdmi_omap4_panel.c to
hdmi_panel.c as that file has nothing specific to OMAP4 and can be reused for
other OMAP family of processors as well.
This is based on Tomi's DSS pmruntime-v2 branch:
git://gitorious.org/linux-omap-dss2/linux.git
Tree with the patches for verification is available in
http://gitorious.org/~mythripk/linux-omap-dss2/mythripk-linux-lo-dss2/commits/hdmi_pmrumtime
Mythri P K (8):
OMAP4: DSS: HDMI: HDMI clean up to pass base_address dynamically
to IP dependant functions of HDMI
OMAP4 : DSS : HDMI : Move the EDID portion from HDMI IP header
OMAP4: DSS: HDMI: Use specific HDMI timings structure instead of
OMAP DSS timings
OMAP4: DSS: HDMI: Move the common header file definition to
Include/video
OMAP4: DSS2: HDMI: Split the HDMI driver to DSS and IP specific
portion.
OMAP4: DSS: HDMI: Rename the functions in HDMI IP library to IP
specific name
HDMI: Move HDMI IP Library from OMAP DSS to common Video
directory for IP present in TI OMAP4, TI81xx, TI38xx
Processor
OMAP4: DSS: Rename hdmi_omap4_panel.c to hdmi_panel.c
drivers/video/Kconfig | 7 +
drivers/video/Makefile | 1 +
drivers/video/hdmi_ti_4xxx_ip.c | 803 +++++++++++++++++
drivers/video/hdmi_ti_4xxx_ip.h | 587 +++++++++++++
drivers/video/omap2/dss/Kconfig | 1 +
drivers/video/omap2/dss/Makefile | 2 +-
drivers/video/omap2/dss/dss.h | 10 -
drivers/video/omap2/dss/hdmi.c | 919 ++++----------------
drivers/video/omap2/dss/hdmi.h | 631 --------------
.../omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} | 2 +-
include/video/hdmi_ti_4xxx_ip.h | 94 ++
11 files changed, 1641 insertions(+), 1416 deletions(-)
create mode 100644 drivers/video/hdmi_ti_4xxx_ip.c
create mode 100644 drivers/video/hdmi_ti_4xxx_ip.h
delete mode 100644 drivers/video/omap2/dss/hdmi.h
rename drivers/video/omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} (99%)
create mode 100644 include/video/hdmi_ti_4xxx_ip.h
--
1.7.5.4
^ permalink raw reply
* RE: [PATCH] fsl-diu-fb: remove the ioctl interface
From: Jenkins, Clive @ 2011-06-22 10:39 UTC (permalink / raw)
To: Anatolij Gustschin, Timur Tabi; +Cc: linuxppc-dev, linux-fbdev, lethal, yorksun
In-Reply-To: <20110622003853.1041385c@wker>
> > The ioctl interface in the Freescale DIU framebuffer driver is just
a
> > collection of miscellaneous functions which were only used in a
one-time
> > demo application that was never distributed. Plus, the ioctls were
spread
> > across two types (both conflicting), and the demo app didn't even
use all
> > of them.
> >
> > Removing the ioctl interface also allows us to clean up the header
file and
> > remove other unusued stuff.
>
> No! We are using ioctl interface of this driver in many video
> rendering applications on overlay planes on huge number of boards.
> So, please don't remove it.
>
> Anatolij
Can you make available your application code by posting a link to it?
Thanks,
Clive
^ permalink raw reply
* RE: [PATCH V5 5/5] ARM: EXYNOS4: Add platform data for EXYNOS4 FIMD
From: Marek Szyprowski @ 2011-06-22 9:47 UTC (permalink / raw)
To: 'Jingoo Han', 'Kukjin Kim', 'Paul Mundt',
linux-samsung-soc, linux-fbdev
Cc: 'Anand Kumar N', 'Thomas Abraham',
Sylwester Nawrocki, 'Kyungmin Park', 'Inki Dae',
'ARM Linux', 'Ben Dooks', 'Jonghun Han'
In-Reply-To: <1308724904-31521-1-git-send-email-jg1.han@samsung.com>
Hello,
On Wednesday, June 22, 2011 8:42 AM Jingoo Han wrote:
> From: Jonghun Han <jonghun.han@samsung.com>
>
> This patch adds support EXYNOS4 FIMD0 and LTE480WV LCD pannel.
>
> Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
> ---
> arch/arm/mach-exynos4/mach-smdkc210.c | 114
> +++++++++++++++++++++++++++++++++
> arch/arm/mach-exynos4/mach-smdkv310.c | 114
> +++++++++++++++++++++++++++++++++
> 2 files changed, 228 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-exynos4/mach-smdkc210.c b/arch/arm/mach-
> exynos4/mach-smdkc210.c
> index e645f7a..360a50a 100644
> --- a/arch/arm/mach-exynos4/mach-smdkc210.c
> +++ b/arch/arm/mach-exynos4/mach-smdkc210.c
> @@ -9,26 +9,33 @@
> */
>
> #include <linux/serial_core.h>
> +#include <linux/delay.h>
> #include <linux/gpio.h>
> +#include <linux/lcd.h>
> #include <linux/mmc/host.h>
> #include <linux/platform_device.h>
> #include <linux/smsc911x.h>
> #include <linux/io.h>
> #include <linux/i2c.h>
> +#include <linux/clk.h>
>
> #include <asm/mach/arch.h>
> #include <asm/mach-types.h>
>
> +#include <video/platform_lcd.h>
> +
> #include <plat/regs-serial.h>
> #include <plat/regs-srom.h>
> #include <plat/exynos4.h>
> #include <plat/cpu.h>
> #include <plat/devs.h>
> +#include <plat/fb.h>
> #include <plat/sdhci.h>
> #include <plat/iic.h>
> #include <plat/pd.h>
>
> #include <mach/map.h>
> +#include <mach/regs-fb.h>
>
> /* Following are default values for UCON, ULCON and UFCON UART registers
> */
> #define SMDKC210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
> @@ -111,6 +118,69 @@ static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata
> __initdata = {
> .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
> };
>
> +static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
> + unsigned int power)
> +{
> + if (power) {
> +#if !defined(CONFIG_BACKLIGHT_PWM)
> + gpio_request(EXYNOS4_GPD0(1), "GPD0");
> + gpio_direction_output(EXYNOS4_GPD0(1), 1);
> + gpio_free(EXYNOS4_GPD0(1));
> +#endif
> + /* fire nRESET on power up */
> + gpio_request(EXYNOS4_GPX0(6), "GPX0");
> +
> + gpio_direction_output(EXYNOS4_GPX0(6), 1);
> + mdelay(100);
> +
> + gpio_set_value(EXYNOS4_GPX0(6), 0);
> + mdelay(10);
> +
> + gpio_set_value(EXYNOS4_GPX0(6), 1);
> + mdelay(10);
> +
> + gpio_free(EXYNOS4_GPX0(6));
> + } else {
> +#if !defined(CONFIG_BACKLIGHT_PWM)
> + gpio_request(EXYNOS4_GPD0(1), "GPD0");
> + gpio_direction_output(EXYNOS4_GPD0(1), 0);
> + gpio_free(EXYNOS4_GPD0(1));
> +#endif
> + }
> +}
> +
> +static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
> + .set_power = lcd_lte480wv_set_power,
> +};
> +
> +static struct platform_device smdkc210_lcd_lte480wv = {
> + .name = "platform-lcd",
> + .dev.parent = &s5p_device_fimd0.dev,
> + .dev.platform_data = &smdkc210_lcd_lte480wv_data,
> +};
> +
> +static struct s3c_fb_pd_win smdkc210_fb_win0 = {
> + .win_mode = {
> + .left_margin = 13,
> + .right_margin = 8,
> + .upper_margin = 7,
> + .lower_margin = 5,
> + .hsync_len = 3,
> + .vsync_len = 1,
> + .xres = 800,
> + .yres = 480,
> + },
> + .max_bpp = 32,
> + .default_bpp = 24,
> +};
> +
> +static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
> + .win[0] = &smdkc210_fb_win0,
> + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
> + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
> + .setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
> +};
> +
> static struct resource smdkc210_smsc911x_resources[] = {
> [0] = {
> .start = EXYNOS4_PA_SROM_BANK(1),
> @@ -165,6 +235,8 @@ static struct platform_device *smdkc210_devices[]
> __initdata = {
> &exynos4_device_pd[PD_GPS],
> &exynos4_device_sysmmu,
> &samsung_asoc_dma,
> + &s5p_device_fimd0,
> + &smdkc210_lcd_lte480wv,
> &smdkc210_smsc911x,
> };
>
> @@ -191,6 +263,44 @@ static void __init smdkc210_smsc911x_init(void)
> (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
> }
>
> +static int __init smdkc210_fimd0_setup_clock(void)
> +{
> + struct clk *sclk = NULL;
> + struct clk *mout_mpll = NULL;
> +
> + u32 rate = 0;
> +
> + sclk = clk_get(&s5p_device_fimd0.dev, "sclk_fimd");
> + if (IS_ERR(sclk)) {
> + printk(KERN_ERR "failed to get sclk for fimd\n");
> + goto err_clk2;
> + }
> +
> + mout_mpll = clk_get(NULL, "mout_mpll");
> + if (IS_ERR(mout_mpll)) {
> + printk(KERN_ERR "failed to get mout_mpll\n");
> + goto err_clk1;
> + }
> +
> + clk_set_parent(sclk, mout_mpll);
> + if (!rate)
> + rate = 134000000;
> +
> + clk_set_rate(sclk, rate);
> +
> + clk_put(sclk);
> + clk_put(mout_mpll);
> +
> + return 0;
> +
> +err_clk1:
> + clk_put(mout_mpll);
> +err_clk2:
> + clk_put(sclk);
> +
> + return -EINVAL;
> +}
> +
I'm not sure if mach-smdk*.c is the right place for the above code.
IMHO all the code that configures very low level, board specific parameters
(like clocks and their relations) should be performed in boot loarder.
(snipped)
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply
* Re: [PATCH V5 5/5] ARM: EXYNOS4: Add platform data for EXYNOS4 FIMD
From: Sylwester Nawrocki @ 2011-06-22 8:56 UTC (permalink / raw)
To: Jingoo Han
Cc: Kukjin Kim, Paul Mundt, linux-samsung-soc, linux-fbdev,
Jonghun Han, Anand Kumar N, Thomas Abraham, Marek Szyprowski,
Kyungmin Park, Inki Dae, ARM Linux, Ben Dooks
In-Reply-To: <1308724904-31521-1-git-send-email-jg1.han@samsung.com>
Hello,
On 06/22/2011 08:41 AM, Jingoo Han wrote:
> From: Jonghun Han <jonghun.han@samsung.com>
>
> This patch adds support EXYNOS4 FIMD0 and LTE480WV LCD pannel.
>
> Signed-off-by: Jonghun Han <jonghun.han@samsung.com>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
> ---
> arch/arm/mach-exynos4/mach-smdkc210.c | 114 +++++++++++++++++++++++++++++++++
> arch/arm/mach-exynos4/mach-smdkv310.c | 114 +++++++++++++++++++++++++++++++++
> 2 files changed, 228 insertions(+), 0 deletions(-)
...
> +static int __init smdkc210_fimd0_setup_clock(void)
> +{
> + struct clk *sclk = NULL;
> + struct clk *mout_mpll = NULL;
You don't need initialize to NULL here.
> +
> + u32 rate = 0;
Other than this variable is not really needed I would make it unsigned long.
> +
> + sclk = clk_get(&s5p_device_fimd0.dev, "sclk_fimd");
> + if (IS_ERR(sclk)) {
> + printk(KERN_ERR "failed to get sclk for fimd\n");
> + goto err_clk2;
You could just do:
return PTR_ERR(sclk);
> + }
> +
> + mout_mpll = clk_get(NULL, "mout_mpll");
> + if (IS_ERR(mout_mpll)) {
> + printk(KERN_ERR "failed to get mout_mpll\n");
> + goto err_clk1;
> + }
> +
> + clk_set_parent(sclk, mout_mpll);
> + if (!rate)
> + rate = 134000000;
134000000UL
> +
> + clk_set_rate(sclk, rate);
> +
> + clk_put(sclk);
> + clk_put(mout_mpll);
> +
> + return 0;
> +
> +err_clk1:
> + clk_put(mout_mpll);
clk_put is supposed to be used only for clocks that were successfully acquired.
> +err_clk2:
> + clk_put(sclk);
Ditto.
> +
> + return -EINVAL;
> +}
...
> +static int __init smdkv310_fimd0_setup_clock(void)
> +{
> + struct clk *sclk = NULL;
> + struct clk *mout_mpll = NULL;
> +
> + u32 rate = 0;
> +
> + sclk = clk_get(&s5p_device_fimd0.dev, "sclk_fimd");
> + if (IS_ERR(sclk)) {
> + printk(KERN_ERR "failed to get sclk for fimd\n");
> + goto err_clk2;
> + }
> +
> + mout_mpll = clk_get(NULL, "mout_mpll");
> + if (IS_ERR(mout_mpll)) {
> + printk(KERN_ERR "failed to get mout_mpll\n");
> + goto err_clk1;
> + }
> +
> + clk_set_parent(sclk, mout_mpll);
> + if (!rate)
> + rate = 134000000;
> +
> + clk_set_rate(sclk, rate);
> +
> + clk_put(sclk);
> + clk_put(mout_mpll);
> +
> + return 0;
> +
> +err_clk1:
> + clk_put(mout_mpll);
> +err_clk2:
> + clk_put(sclk);
> +
> + return -EINVAL;
> +}
We have multiple copies of same function and I suspect other boards will try
to repeat this pattern which is not that good.
It would be worth to create common function for all boards if we really
must have that, e.g.
int __init exynos4_fimd_setup_clock(struct device *dev, const char *parent,
unsigned long clk_rate);
{
struct clk *clk_parent;
struct clk *sclk;
sclk = clk_get(dev, "sclk_fimd");
if (IS_ERR(sclk))
return PTR_ERR(sclk);
clk_parent = clk_get(NULL, parent);
if (IS_ERR(parent_clk)) {
clk_put(sclk);
return PTR_ERR(clk_parent);
}
clk_set_parent(sclk, clk_parent);
if (!rate)
rate = 134000000UL;
clk_set_rate(sclk, rate);
clk_put(sclk);
clk_put(clk_parent);
return 0;
}
But I have no idea where to put that...
Perhaps we should create common mach-exynos4/setup-fimd.c file for FIMD0, FIMD1.
But then it would contain ugly #ifdef for unused FIMD1 setup functions
("#ifdef CONFIG_DEV_FIMD0 ..") if only FIMD0 is used. Maybe someone else has
better idea.
Regards,
--
Sylwester Nawrocki
Samsung Poland R&D Center
^ permalink raw reply
* Re: [PATCH/RFC] fbdev: Add FOURCC-based format configuration API
From: Laurent Pinchart @ 2011-06-22 8:50 UTC (permalink / raw)
To: Florian Tobias Schandinat
Cc: Geert Uytterhoeven, linux-fbdev, linux-media, dri-devel
In-Reply-To: <4E018189.3020305@gmx.de>
Hi Florian,
On Wednesday 22 June 2011 07:45:45 Florian Tobias Schandinat wrote:
> On 06/21/2011 10:31 PM, Laurent Pinchart wrote:
> > On Tuesday 21 June 2011 22:49:14 Geert Uytterhoeven wrote:
> >> On Tue, Jun 21, 2011 at 17:36, Laurent Pinchart wrote:
> >>> +The FOURCC-based API replaces format descriptions by four character
> >>> codes +(FOURCC). FOURCCs are abstract identifiers that uniquely define
> >>> a format +without explicitly describing it. This is the only API that
> >>> supports YUV +formats. Drivers are also encouraged to implement the
> >>> FOURCC-based API for RGB +and grayscale formats.
> >>> +
> >>> +Drivers that support the FOURCC-based API report this capability by
> >>> setting +the FB_CAP_FOURCC bit in the fb_fix_screeninfo capabilities
> >>> field. +
> >>> +FOURCC definitions are located in the linux/videodev2.h header.
> >>> However, and +despite starting with the V4L2_PIX_FMT_prefix, they are
> >>> not restricted to V4L2 +and don't require usage of the V4L2 subsystem.
> >>> FOURCC documentation is +available in
> >>> Documentation/DocBook/v4l/pixfmt.xml.
> >>> +
> >>> +To select a format, applications set the FB_VMODE_FOURCC bit in the
> >>> +fb_var_screeninfo vmode field, and set the fourcc field to the desired
> >>> FOURCC. +The bits_per_pixel, red, green, blue, transp and nonstd fields
> >>> must be set to +0 by applications and ignored by drivers. Note that the
> >>> grayscale and fourcc +fields share the same memory location.
> >>> Application must thus not set the +grayscale field to 0.
> >>
> >> These are the only parts I don't like: (ab)using the vmode field (this
> >> isn't really a vmode flag), and the union of grayscale and fourcc (avoid
> >> unions where possible).
> >
> > I've proposed adding a FB_NONSTD_FORMAT bit to the nonstd field as a
> > FOURCC mode indicator in my initial RFC. Florian Tobias Schandinat
> > wasn't very happy with that, and proposed using the vmode field instead.
> >
> > Given that there's virtually no fbdev documentation, whether the vmode
> > field and/or nonstd field are good fit for a FOURCC mode indicator is
> > subject to interpretation.
>
> The reason for my suggestion is that the vmode field is accepted to contain
> only flags and at least to me there is no hard line what is part of the
> video mode and what is not.
Lacks of documentation indeed makes that line fuzzy. I really hope that
api.txt will be extended to cover the full fbdev API :-)
> In contrast the nonstd field is already used in a lot of different
> (incompatible) ways. I think if we only use the nonstd field for handling
> FOURCC it is likely that some problems will appear.
>
> >> What about storing the FOURCC value in nonstd instead?
> >
> > Wouldn't that be a union of nonstd and fourcc ? :-) FOURCC-based format
> > setting will be a standard fbdev API, I'm not very keen on storing it in
> > the nonstd field without a union.
> >
> >> As FOURCC values are always 4 ASCII characters (hence all 4 bytes must
> >> be non-zero), I don't think there are any conflicts with existing values
> >> of nonstd. To make it even safer and easier to parse, you could set bit
> >> 31 of nonstd as a FOURCC indicator.
> >
> > I would then create a union between nonstd and fourcc, and document
> > nonstd as being used for the legacy API only. Most existing drivers use
> > a couple of nonstd bits only. The driver that (ab)uses nonstd the most
> > is pxafb and uses bits 22:0. Bits 31:24 are never used as far as I can
> > tell, so nonstd& 0xff000000 != 0 could be used as a FOURCC mode test.
> >
> > This assumes that FOURCCs will never have their last character set to
> > '\0'. Is that a safe assumption for the future ?
>
> Yes, I think. The information I found indicates that space should be used
> for padding, so a \0 shouldn't exist.
> I think using only the nonstd field and requiring applications to check the
> capabilities would be possible, although not fool proof ;)
>
> Great work, Laurent, do you have plans to modify fbset to allow using this
> format API from the command line?
Once we agree on an API, I will implement it in a driver and update fbset.
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH 4/4] OMAP: DSS2: Fix FIFO threshold and burst size for OMAP4
From: Tomi Valkeinen @ 2011-06-22 8:45 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1308732326-17278-1-git-send-email-tomi.valkeinen@ti.com>
The DMA FIFO threshold registers and burst size registers have changed
for OMAP4. The current code only handles OMAP2/3 case, and so the
values are a bit off for OMAP4. A summary of the differences between
OMAP2/3 and OMAP4:
Burst size:
OMAP2/3: 4 x 32 bits / 8 x 32 bits / 16 x 32 bits
OMAP4: 2 x 128 bits / 4 x 128 bits / 8 x 128 bits
Threshold size:
OMAP2/3: in bytes (8 bit units)
OMAP4: in 128bit units
This patch fixes the issue by creating two new helper functions in
dss_features: dss_feat_get_buffer_size_unit() and
dss_feat_get_burst_size_unit(). These return (in bytes) the unit size
for threshold registers and unit size for burst size register,
respectively, and are used to calculate correct values.
For the threshold size the usage is straightforward. However, the burst
size register has different multipliers for OMAP2/3 and OMAP4. This
patch solves the problem by defining the multipliers for the burst size
as 2x, 4x and 8x, which fit fine for the OMAP4 burst size definition
(i.e. burst size unit for OMAP4 is 128bits), but requires a slight twist
on OMAP2/3 by defining the burst size unit as 64bit.
As the driver in practice always uses the maximum burst size, and no use
case currently exists where we would want to use a smaller burst size,
this patch changes the driver to hardcode the burst size when
initializing DISPC. This makes the threshold configuration code somewhat
simpler.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 50 ++++++++++++++++++++++++++-----
drivers/video/omap2/dss/display.c | 12 +++----
drivers/video/omap2/dss/dsi.c | 11 ++-----
drivers/video/omap2/dss/dss.h | 15 ++-------
drivers/video/omap2/dss/dss_features.c | 23 ++++++++++++++
drivers/video/omap2/dss/dss_features.h | 3 ++
drivers/video/omap2/dss/manager.c | 12 ++++----
7 files changed, 86 insertions(+), 40 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 0151f16..2fcb73b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -79,6 +79,12 @@ struct dispc_v_coef {
s8 vc00;
};
+enum omap_burst_size {
+ BURST_SIZE_X2 = 0,
+ BURST_SIZE_X4 = 1,
+ BURST_SIZE_X8 = 2,
+};
+
#define REG_GET(idx, start, end) \
FLD_GET(dispc_read_reg(idx), start, end)
@@ -1044,11 +1050,10 @@ void dispc_set_channel_out(enum omap_plane plane,
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
}
-void dispc_set_burst_size(enum omap_plane plane,
+static void dispc_set_burst_size(enum omap_plane plane,
enum omap_burst_size burst_size)
{
int shift;
- u32 val;
switch (plane) {
case OMAP_DSS_GFX:
@@ -1063,9 +1068,24 @@ void dispc_set_burst_size(enum omap_plane plane,
return;
}
- val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
- val = FLD_MOD(val, burst_size, shift+1, shift);
- dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
+}
+
+static void dispc_configure_burst_sizes(void)
+{
+ int i;
+ const int burst_size = BURST_SIZE_X8;
+
+ /* Configure burst size always to maximum size */
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+ dispc_set_burst_size(i, burst_size);
+}
+
+u32 dispc_get_burst_size(enum omap_plane plane)
+{
+ unsigned unit = dss_feat_get_burst_size_unit();
+ /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
+ return unit * 8;
}
void dispc_enable_gamma_table(bool enable)
@@ -1160,12 +1180,15 @@ static void dispc_read_plane_fifo_sizes(void)
u32 size;
int plane;
u8 start, end;
+ u32 unit;
+
+ unit = dss_feat_get_buffer_size_unit();
dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
- size = FLD_GET(dispc_read_reg(DISPC_OVL_FIFO_SIZE_STATUS(plane)),
- start, end);
+ size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
+ size *= unit;
dispc.fifo_size[plane] = size;
}
}
@@ -1175,9 +1198,18 @@ u32 dispc_get_plane_fifo_size(enum omap_plane plane)
return dispc.fifo_size[plane];
}
-void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
{
u8 hi_start, hi_end, lo_start, lo_end;
+ u32 unit;
+
+ unit = dss_feat_get_buffer_size_unit();
+
+ WARN_ON(low % unit != 0);
+ WARN_ON(high % unit != 0);
+
+ low /= unit;
+ high /= unit;
dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
@@ -3601,6 +3633,8 @@ static void _omap_dispc_initial_config(void)
dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
dispc_read_plane_fifo_sizes();
+
+ dispc_configure_burst_sizes();
}
/* DISPC HW IP initialisation */
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index a0bbdf6..94495e4 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -29,6 +29,7 @@
#include <video/omapdss.h>
#include "dss.h"
+#include "dss_features.h"
static ssize_t display_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -282,16 +283,13 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
EXPORT_SYMBOL(omapdss_default_get_resolution);
void default_get_overlay_fifo_thresholds(enum omap_plane plane,
- u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 fifo_size, u32 burst_size,
u32 *fifo_low, u32 *fifo_high)
{
- unsigned burst_size_bytes;
+ unsigned buf_unit = dss_feat_get_buffer_size_unit();
- *burst_size = OMAP_DSS_BURST_16x32;
- burst_size_bytes = 16 * 32 / 8;
-
- *fifo_high = fifo_size - 1;
- *fifo_low = fifo_size - burst_size_bytes;
+ *fifo_high = fifo_size - buf_unit;
+ *fifo_low = fifo_size - burst_size;
}
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 62b11c5..12bc2e7 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4292,16 +4292,11 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
EXPORT_SYMBOL(omapdss_dsi_enable_te);
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
- u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 fifo_size, u32 burst_size,
u32 *fifo_low, u32 *fifo_high)
{
- unsigned burst_size_bytes;
-
- *burst_size = OMAP_DSS_BURST_16x32;
- burst_size_bytes = 16 * 32 / 8;
-
- *fifo_high = fifo_size - burst_size_bytes;
- *fifo_low = fifo_size - burst_size_bytes * 2;
+ *fifo_high = fifo_size - burst_size;
+ *fifo_low = fifo_size - burst_size * 2;
}
int dsi_init_display(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 9dc5c00..adeff04 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -97,12 +97,6 @@ extern unsigned int dss_debug;
#define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
-enum omap_burst_size {
- OMAP_DSS_BURST_4x32 = 0,
- OMAP_DSS_BURST_8x32 = 1,
- OMAP_DSS_BURST_16x32 = 2,
-};
-
enum omap_parallel_interface_mode {
OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
@@ -186,7 +180,7 @@ void dss_uninit_device(struct platform_device *pdev,
bool dss_use_replication(struct omap_dss_device *dssdev,
enum omap_color_mode mode);
void default_get_overlay_fifo_thresholds(enum omap_plane plane,
- u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 fifo_size, u32 burst_size,
u32 *fifo_low, u32 *fifo_high);
/* manager */
@@ -293,7 +287,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
bool enable_hsdiv);
void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
- u32 fifo_size, enum omap_burst_size *burst_size,
+ u32 fifo_size, u32 burst_size,
u32 *fifo_low, u32 *fifo_high);
void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
@@ -394,10 +388,9 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
void dispc_set_digit_size(u16 width, u16 height);
u32 dispc_get_plane_fifo_size(enum omap_plane plane);
-void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
+void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
void dispc_enable_fifomerge(bool enable);
-void dispc_set_burst_size(enum omap_plane plane,
- enum omap_burst_size burst_size);
+u32 dispc_get_burst_size(enum omap_plane plane);
void dispc_enable_cpr(enum omap_channel channel, bool enable);
void dispc_set_cpr_coef(enum omap_channel channel,
struct omap_dss_cpr_coefs *coefs);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index bd420f9..b415c4e 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -49,6 +49,9 @@ struct omap_dss_features {
const enum omap_color_mode *supported_color_modes;
const char * const *clksrc_names;
const struct dss_param_range *dss_params;
+
+ const u32 buffer_size_unit;
+ const u32 burst_size_unit;
};
/* This struct is assigned to one of the below during initialization */
@@ -274,6 +277,8 @@ static const struct omap_dss_features omap2_dss_features = {
.supported_color_modes = omap2_dss_supported_color_modes,
.clksrc_names = omap2_dss_clk_source_names,
.dss_params = omap2_dss_param_range,
+ .buffer_size_unit = 1,
+ .burst_size_unit = 8,
};
/* OMAP3 DSS Features */
@@ -296,6 +301,8 @@ static const struct omap_dss_features omap3430_dss_features = {
.supported_color_modes = omap3_dss_supported_color_modes,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
+ .buffer_size_unit = 1,
+ .burst_size_unit = 8,
};
static const struct omap_dss_features omap3630_dss_features = {
@@ -317,6 +324,8 @@ static const struct omap_dss_features omap3630_dss_features = {
.supported_color_modes = omap3_dss_supported_color_modes,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
+ .buffer_size_unit = 1,
+ .burst_size_unit = 8,
};
/* OMAP4 DSS Features */
@@ -339,6 +348,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
.supported_color_modes = omap4_dss_supported_color_modes,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
+ .buffer_size_unit = 16,
+ .burst_size_unit = 16,
};
/* For all the other OMAP4 versions */
@@ -361,6 +372,8 @@ static const struct omap_dss_features omap4_dss_features = {
.supported_color_modes = omap4_dss_supported_color_modes,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
+ .buffer_size_unit = 16,
+ .burst_size_unit = 16,
};
/* Functions returning values related to a DSS feature */
@@ -406,6 +419,16 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
return omap_current_dss_features->clksrc_names[id];
}
+u32 dss_feat_get_buffer_size_unit(void)
+{
+ return omap_current_dss_features->buffer_size_unit;
+}
+
+u32 dss_feat_get_burst_size_unit(void)
+{
+ return omap_current_dss_features->burst_size_unit;
+}
+
/* DSS has_feature check */
bool dss_has_feature(enum dss_feat_id id)
{
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 5be8103..b7398cb 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -94,6 +94,9 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode);
const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
+u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
+u32 dss_feat_get_burst_size_unit(void); /* in bytes */
+
bool dss_has_feature(enum dss_feat_id id);
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
void dss_features_init(void);
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index ad76c5b..13d72d5 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -507,7 +507,6 @@ struct overlay_cache_data {
bool replication;
bool ilace;
- enum omap_burst_size burst_size;
u32 fifo_low;
u32 fifo_high;
};
@@ -947,8 +946,7 @@ static int configure_overlay(enum omap_plane plane)
dispc_enable_replication(plane, c->replication);
- dispc_set_burst_size(plane, c->burst_size);
- dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
+ dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
dispc_enable_plane(plane, 1);
@@ -1421,7 +1419,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
/* Configure overlay fifos */
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
struct omap_dss_device *dssdev;
- u32 size;
+ u32 size, burst_size;
ovl = omap_dss_get_overlay(i);
@@ -1439,6 +1437,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
if (use_fifomerge)
size *= 3;
+ burst_size = dispc_get_burst_size(ovl->id);
+
switch (dssdev->type) {
case OMAP_DISPLAY_TYPE_DPI:
case OMAP_DISPLAY_TYPE_DBI:
@@ -1446,13 +1446,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
case OMAP_DISPLAY_TYPE_VENC:
case OMAP_DISPLAY_TYPE_HDMI:
default_get_overlay_fifo_thresholds(ovl->id, size,
- &oc->burst_size, &oc->fifo_low,
+ burst_size, &oc->fifo_low,
&oc->fifo_high);
break;
#ifdef CONFIG_OMAP2_DSS_DSI
case OMAP_DISPLAY_TYPE_DSI:
dsi_get_overlay_fifo_thresholds(ovl->id, size,
- &oc->burst_size, &oc->fifo_low,
+ burst_size, &oc->fifo_low,
&oc->fifo_high);
break;
#endif
--
1.7.4.1
^ permalink raw reply related
* [PATCH 3/4] OMAP: DSS2: DSI: sync when disabling a display
From: Tomi Valkeinen @ 2011-06-22 8:45 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1308732326-17278-1-git-send-email-tomi.valkeinen@ti.com>
When the panel driver calls omapdss_dsi_display_disable() it is possible
that there are still some unsent packets in the TX fifo.
Add dsi_sync_vc() calls in the beginning of
omapdss_dsi_display_disable() to make sure the TX fifos are empty.
This allows us to remove the msleep(10) hack from panel-taal.c
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/displays/panel-taal.c | 5 +----
drivers/video/omap2/dss/dsi.c | 5 +++++
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 4cb0449..4e888ac 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1247,11 +1247,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
int r;
r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
- if (!r) {
+ if (!r)
r = taal_sleep_in(td);
- /* HACK: wait a bit so that the message goes through */
- msleep(10);
- }
if (r) {
dev_err(&dssdev->dev,
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b6a57bb..62b11c5 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4263,6 +4263,11 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
mutex_lock(&dsi->lock);
+ dsi_sync_vc(dsidev, 0);
+ dsi_sync_vc(dsidev, 1);
+ dsi_sync_vc(dsidev, 2);
+ dsi_sync_vc(dsidev, 3);
+
dsi_display_uninit_dispc(dssdev);
dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/4] OMAP: DSS2: Add Color Phase Rotation support
From: Tomi Valkeinen @ 2011-06-22 8:45 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1308732326-17278-1-git-send-email-tomi.valkeinen@ti.com>
Add Color Phase Rotation (CPR) support and sysfs files to enable CPR and
to set the CPR coefficient matrix.
CPR is enabled via manager?/cpr_enable file, and the coefficient matrix
is set via manager?/cpr_coef file. The values in cpr_coef are in the
following order:
RR RG RB GR GG GB BR BG BB
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 34 +++++++++++
drivers/video/omap2/dss/dss.h | 3 +
drivers/video/omap2/dss/manager.c | 114 +++++++++++++++++++++++++++++++++++++
include/video/omapdss.h | 9 +++
4 files changed, 160 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index eac768f..0151f16 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1082,6 +1082,40 @@ void dispc_enable_gamma_table(bool enable)
REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
}
+void dispc_enable_cpr(enum omap_channel channel, bool enable)
+{
+ u16 reg;
+
+ if (channel = OMAP_DSS_CHANNEL_LCD)
+ reg = DISPC_CONFIG;
+ else if (channel = OMAP_DSS_CHANNEL_LCD2)
+ reg = DISPC_CONFIG2;
+ else
+ return;
+
+ REG_FLD_MOD(reg, enable, 15, 15);
+}
+
+void dispc_set_cpr_coef(enum omap_channel channel,
+ struct omap_dss_cpr_coefs *coefs)
+{
+ u32 coef_r, coef_g, coef_b;
+
+ if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2)
+ return;
+
+ coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
+ FLD_VAL(coefs->rb, 9, 0);
+ coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) |
+ FLD_VAL(coefs->gb, 9, 0);
+ coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) |
+ FLD_VAL(coefs->bb, 9, 0);
+
+ dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r);
+ dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g);
+ dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
+}
+
static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
{
u32 val;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index ce17a61..9dc5c00 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -398,6 +398,9 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
void dispc_enable_fifomerge(bool enable);
void dispc_set_burst_size(enum omap_plane plane,
enum omap_burst_size burst_size);
+void dispc_enable_cpr(enum omap_channel channel, bool enable);
+void dispc_set_cpr_coef(enum omap_channel channel,
+ struct omap_dss_cpr_coefs *coefs);
void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 4691b81..ad76c5b 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -275,6 +275,108 @@ static ssize_t manager_alpha_blending_enabled_store(
return size;
}
+static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable);
+}
+
+static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay_manager_info info;
+ int v;
+ int r;
+ bool enable;
+
+ if (!dss_has_feature(FEAT_CPR))
+ return -ENODEV;
+
+ r = kstrtoint(buf, 0, &v);
+ if (r)
+ return r;
+
+ enable = !!v;
+
+ mgr->get_manager_info(mgr, &info);
+
+ if (info.cpr_enable = enable)
+ return size;
+
+ info.cpr_enable = enable;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
+ char *buf)
+{
+ struct omap_overlay_manager_info info;
+
+ mgr->get_manager_info(mgr, &info);
+
+ return snprintf(buf, PAGE_SIZE,
+ "%d %d %d %d %d %d %d %d %d\n",
+ info.cpr_coefs.rr,
+ info.cpr_coefs.rg,
+ info.cpr_coefs.rb,
+ info.cpr_coefs.gr,
+ info.cpr_coefs.gg,
+ info.cpr_coefs.gb,
+ info.cpr_coefs.br,
+ info.cpr_coefs.bg,
+ info.cpr_coefs.bb);
+}
+
+static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
+ const char *buf, size_t size)
+{
+ struct omap_overlay_manager_info info;
+ struct omap_dss_cpr_coefs coefs;
+ int r, i;
+ s16 *arr;
+
+ if (!dss_has_feature(FEAT_CPR))
+ return -ENODEV;
+
+ if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
+ &coefs.rr, &coefs.rg, &coefs.rb,
+ &coefs.gr, &coefs.gg, &coefs.gb,
+ &coefs.br, &coefs.bg, &coefs.bb) != 9)
+ return -EINVAL;
+
+ arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
+ coefs.gr, coefs.gg, coefs.gb,
+ coefs.br, coefs.bg, coefs.bb };
+
+ for (i = 0; i < 9; ++i) {
+ if (arr[i] < -512 || arr[i] > 511)
+ return -EINVAL;
+ }
+
+ mgr->get_manager_info(mgr, &info);
+
+ info.cpr_coefs = coefs;
+
+ r = mgr->set_manager_info(mgr, &info);
+ if (r)
+ return r;
+
+ r = mgr->apply(mgr);
+ if (r)
+ return r;
+
+ return size;
+}
+
struct manager_attribute {
struct attribute attr;
ssize_t (*show)(struct omap_overlay_manager *, char *);
@@ -300,6 +402,12 @@ static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
manager_alpha_blending_enabled_show,
manager_alpha_blending_enabled_store);
+static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
+ manager_cpr_enable_show,
+ manager_cpr_enable_store);
+static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
+ manager_cpr_coef_show,
+ manager_cpr_coef_store);
static struct attribute *manager_sysfs_attrs[] = {
@@ -310,6 +418,8 @@ static struct attribute *manager_sysfs_attrs[] = {
&manager_attr_trans_key_value.attr,
&manager_attr_trans_key_enabled.attr,
&manager_attr_alpha_blending_enabled.attr,
+ &manager_attr_cpr_enable.attr,
+ &manager_attr_cpr_coef.attr,
NULL
};
@@ -858,6 +968,10 @@ static void configure_manager(enum omap_channel channel)
dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
dispc_enable_trans_key(channel, mi->trans_enabled);
dispc_enable_alpha_blending(channel, mi->alpha_enabled);
+ if (dss_has_feature(FEAT_CPR)) {
+ dispc_enable_cpr(channel, mi->cpr_enable);
+ dispc_set_cpr_coef(channel, &mi->cpr_coefs);
+ }
}
/* configure_dispc() tries to write values from cache to shadow registers.
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index e02823e..3b55ef2 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -290,6 +290,12 @@ extern const struct omap_video_timings omap_dss_pal_timings;
extern const struct omap_video_timings omap_dss_ntsc_timings;
#endif
+struct omap_dss_cpr_coefs {
+ s16 rr, rg, rb;
+ s16 gr, gg, gb;
+ s16 br, bg, bb;
+};
+
struct omap_overlay_info {
bool enabled;
@@ -349,6 +355,9 @@ struct omap_overlay_manager_info {
bool trans_enabled;
bool alpha_enabled;
+
+ bool cpr_enable;
+ struct omap_dss_cpr_coefs cpr_coefs;
};
struct omap_overlay_manager {
--
1.7.4.1
^ permalink raw reply related
* [PATCH 1/4] OMAP: DSS: Minor cleanup in ovl and mgr cache structs
From: Tomi Valkeinen @ 2011-06-22 8:45 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Nishant Kamat, Tomi Valkeinen
In-Reply-To: <1308732326-17278-1-git-send-email-tomi.valkeinen@ti.com>
From: Nishant Kamat <nskamat@ti.com>
The overlay_cache_data and manager_cache_data structs include
the elements of omap_overlay_info and omap_overlay_manager_info
structs respectively. Include the structs instead of the individual
elements to reduce code.
Signed-off-by: Nishant Kamat <nskamat@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/manager.c | 158 ++++++++++++++----------------------
1 files changed, 62 insertions(+), 96 deletions(-)
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index c6d26c6..4691b81 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -391,23 +391,7 @@ struct overlay_cache_data {
bool enabled;
- u32 paddr;
- void __iomem *vaddr;
- u32 p_uv_addr; /* relevant for NV12 format only */
- u16 screen_width;
- u16 width;
- u16 height;
- enum omap_color_mode color_mode;
- u8 rotation;
- enum omap_dss_rotation_type rotation_type;
- bool mirror;
-
- u16 pos_x;
- u16 pos_y;
- u16 out_width; /* if 0, out_width = width */
- u16 out_height; /* if 0, out_height = height */
- u8 global_alpha;
- u8 pre_mult_alpha;
+ struct omap_overlay_info info;
enum omap_channel channel;
bool replication;
@@ -427,13 +411,7 @@ struct manager_cache_data {
* VSYNC/EVSYNC */
bool shadow_dirty;
- u32 default_color;
-
- enum omap_dss_trans_key_type trans_key_type;
- u32 trans_key;
- bool trans_enabled;
-
- bool alpha_enabled;
+ struct omap_overlay_manager_info info;
bool manual_update;
bool do_manual_update;
@@ -699,10 +677,12 @@ static bool rectangle_intersects(int x1, int y1, int w1, int h1,
static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
{
- if (oc->out_width != 0 && oc->width != oc->out_width)
+ struct omap_overlay_info *oi = &oc->info;
+
+ if (oi->out_width != 0 && oi->width != oi->out_width)
return true;
- if (oc->out_height != 0 && oc->height != oc->out_height)
+ if (oi->out_height != 0 && oi->height != oi->out_height)
return true;
return false;
@@ -712,6 +692,8 @@ static int configure_overlay(enum omap_plane plane)
{
struct overlay_cache_data *c;
struct manager_cache_data *mc;
+ struct omap_overlay_info *oi;
+ struct omap_overlay_manager_info *mi;
u16 outw, outh;
u16 x, y, w, h;
u32 paddr;
@@ -721,6 +703,7 @@ static int configure_overlay(enum omap_plane plane)
DSSDBGF("%d", plane);
c = &dss_cache.overlay_cache[plane];
+ oi = &c->info;
if (!c->enabled) {
dispc_enable_plane(plane, 0);
@@ -728,14 +711,15 @@ static int configure_overlay(enum omap_plane plane)
}
mc = &dss_cache.manager_cache[c->channel];
+ mi = &mc->info;
- x = c->pos_x;
- y = c->pos_y;
- w = c->width;
- h = c->height;
- outw = c->out_width = 0 ? c->width : c->out_width;
- outh = c->out_height = 0 ? c->height : c->out_height;
- paddr = c->paddr;
+ x = oi->pos_x;
+ y = oi->pos_y;
+ w = oi->width;
+ h = oi->height;
+ outw = oi->out_width = 0 ? oi->width : oi->out_width;
+ outh = oi->out_height = 0 ? oi->height : oi->out_height;
+ paddr = oi->paddr;
orig_w = w;
orig_h = h;
@@ -754,7 +738,7 @@ static int configure_overlay(enum omap_plane plane)
return 0;
}
- switch (c->color_mode) {
+ switch (oi->color_mode) {
case OMAP_DSS_COLOR_NV12:
bpp = 8;
break;
@@ -784,23 +768,23 @@ static int configure_overlay(enum omap_plane plane)
BUG();
}
- if (mc->x > c->pos_x) {
+ if (mc->x > oi->pos_x) {
x = 0;
- outw -= (mc->x - c->pos_x);
- paddr += (mc->x - c->pos_x) *
+ outw -= (mc->x - oi->pos_x);
+ paddr += (mc->x - oi->pos_x) *
scale_x_m / scale_x_d * bpp / 8;
} else {
- x = c->pos_x - mc->x;
+ x = oi->pos_x - mc->x;
}
- if (mc->y > c->pos_y) {
+ if (mc->y > oi->pos_y) {
y = 0;
- outh -= (mc->y - c->pos_y);
- paddr += (mc->y - c->pos_y) *
+ outh -= (mc->y - oi->pos_y);
+ paddr += (mc->y - oi->pos_y) *
scale_y_m / scale_y_d *
- c->screen_width * bpp / 8;
+ oi->screen_width * bpp / 8;
} else {
- y = c->pos_y - mc->y;
+ y = oi->pos_y - mc->y;
}
if (mc->w < (x + outw))
@@ -819,8 +803,8 @@ static int configure_overlay(enum omap_plane plane)
* the width if the original width was bigger.
*/
if ((w & 1) &&
- (c->color_mode = OMAP_DSS_COLOR_YUV2 ||
- c->color_mode = OMAP_DSS_COLOR_UYVY)) {
+ (oi->color_mode = OMAP_DSS_COLOR_YUV2 ||
+ oi->color_mode = OMAP_DSS_COLOR_UYVY)) {
if (orig_w > w)
w += 1;
else
@@ -830,19 +814,19 @@ static int configure_overlay(enum omap_plane plane)
r = dispc_setup_plane(plane,
paddr,
- c->screen_width,
+ oi->screen_width,
x, y,
w, h,
outw, outh,
- c->color_mode,
+ oi->color_mode,
c->ilace,
- c->rotation_type,
- c->rotation,
- c->mirror,
- c->global_alpha,
- c->pre_mult_alpha,
+ oi->rotation_type,
+ oi->rotation,
+ oi->mirror,
+ oi->global_alpha,
+ oi->pre_mult_alpha,
c->channel,
- c->p_uv_addr);
+ oi->p_uv_addr);
if (r) {
/* this shouldn't happen */
@@ -863,16 +847,17 @@ static int configure_overlay(enum omap_plane plane)
static void configure_manager(enum omap_channel channel)
{
- struct manager_cache_data *c;
+ struct omap_overlay_manager_info *mi;
DSSDBGF("%d", channel);
- c = &dss_cache.manager_cache[channel];
+ /* picking info from the cache */
+ mi = &dss_cache.manager_cache[channel].info;
- dispc_set_default_color(channel, c->default_color);
- dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
- dispc_enable_trans_key(channel, c->trans_enabled);
- dispc_enable_alpha_blending(channel, c->alpha_enabled);
+ dispc_set_default_color(channel, mi->default_color);
+ dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
+ dispc_enable_trans_key(channel, mi->trans_enabled);
+ dispc_enable_alpha_blending(channel, mi->alpha_enabled);
}
/* configure_dispc() tries to write values from cache to shadow registers.
@@ -990,6 +975,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
{
struct overlay_cache_data *oc;
struct manager_cache_data *mc;
+ struct omap_overlay_info *oi;
const int num_ovls = dss_feat_get_num_ovls();
struct omap_overlay_manager *mgr;
int i;
@@ -1032,6 +1018,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
unsigned outw, outh;
oc = &dss_cache.overlay_cache[i];
+ oi = &oc->info;
if (oc->channel != mgr->id)
continue;
@@ -1047,39 +1034,39 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
if (!dispc_is_overlay_scaled(oc))
continue;
- outw = oc->out_width = 0 ?
- oc->width : oc->out_width;
- outh = oc->out_height = 0 ?
- oc->height : oc->out_height;
+ outw = oi->out_width = 0 ?
+ oi->width : oi->out_width;
+ outh = oi->out_height = 0 ?
+ oi->height : oi->out_height;
/* is the overlay outside the update region? */
if (!rectangle_intersects(x, y, w, h,
- oc->pos_x, oc->pos_y,
+ oi->pos_x, oi->pos_y,
outw, outh))
continue;
/* if the overlay totally inside the update region? */
- if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
+ if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
x, y, w, h))
continue;
- if (x > oc->pos_x)
- x1 = oc->pos_x;
+ if (x > oi->pos_x)
+ x1 = oi->pos_x;
else
x1 = x;
- if (y > oc->pos_y)
- y1 = oc->pos_y;
+ if (y > oi->pos_y)
+ y1 = oi->pos_y;
else
y1 = y;
- if ((x + w) < (oc->pos_x + outw))
- x2 = oc->pos_x + outw;
+ if ((x + w) < (oi->pos_x + outw))
+ x2 = oi->pos_x + outw;
else
x2 = x + w;
- if ((y + h) < (oc->pos_y + outh))
- y2 = oc->pos_y + outh;
+ if ((y + h) < (oi->pos_y + outh))
+ y2 = oi->pos_y + outh;
else
y2 = y + h;
@@ -1258,23 +1245,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
ovl->info_dirty = false;
oc->dirty = true;
-
- oc->paddr = ovl->info.paddr;
- oc->vaddr = ovl->info.vaddr;
- oc->p_uv_addr = ovl->info.p_uv_addr;
- oc->screen_width = ovl->info.screen_width;
- oc->width = ovl->info.width;
- oc->height = ovl->info.height;
- oc->color_mode = ovl->info.color_mode;
- oc->rotation = ovl->info.rotation;
- oc->rotation_type = ovl->info.rotation_type;
- oc->mirror = ovl->info.mirror;
- oc->pos_x = ovl->info.pos_x;
- oc->pos_y = ovl->info.pos_y;
- oc->out_width = ovl->info.out_width;
- oc->out_height = ovl->info.out_height;
- oc->global_alpha = ovl->info.global_alpha;
- oc->pre_mult_alpha = ovl->info.pre_mult_alpha;
+ oc->info = ovl->info;
oc->replication dss_use_replication(dssdev, ovl->info.color_mode);
@@ -1312,12 +1283,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
mgr->info_dirty = false;
mc->dirty = true;
-
- mc->default_color = mgr->info.default_color;
- mc->trans_key_type = mgr->info.trans_key_type;
- mc->trans_key = mgr->info.trans_key;
- mc->trans_enabled = mgr->info.trans_enabled;
- mc->alpha_enabled = mgr->info.alpha_enabled;
+ mc->info = mgr->info;
mc->manual_update dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
--
1.7.4.1
^ permalink raw reply related
* [PATCH 0/4] OMAP: DSS2: misc patches
From: Tomi Valkeinen @ 2011-06-22 8:45 UTC (permalink / raw)
To: linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
Here are few miscellaneous patches for DSS. A pure cleanup patch from Nishant,
patch adding Color Phase Rotation support, and two minor fixes.
Tomi
Nishant Kamat (1):
OMAP: DSS: Minor cleanup in ovl and mgr cache structs
Tomi Valkeinen (3):
OMAP: DSS2: Add Color Phase Rotation support
OMAP: DSS2: DSI: sync when disabling a display
OMAP: DSS2: Fix FIFO threshold and burst size for OMAP4
drivers/video/omap2/displays/panel-taal.c | 5 +-
drivers/video/omap2/dss/dispc.c | 84 ++++++++-
drivers/video/omap2/dss/display.c | 12 +-
drivers/video/omap2/dss/dsi.c | 16 +-
drivers/video/omap2/dss/dss.h | 18 +-
drivers/video/omap2/dss/dss_features.c | 23 +++
drivers/video/omap2/dss/dss_features.h | 3 +
drivers/video/omap2/dss/manager.c | 284 ++++++++++++++++++----------
include/video/omapdss.h | 9 +
9 files changed, 314 insertions(+), 140 deletions(-)
--
1.7.4.1
^ permalink raw reply
* Re: Some questions about DRM(Direct Rendering Manager)
From: InKi Dae @ 2011-06-22 7:50 UTC (permalink / raw)
To: daeinki, dri-devel
Cc: linux-fbdev, Kukjin Kim, Kyungmin Park, airlied, Paul Mundt,
jesse.barnes, linux-arm-kernel
In-Reply-To: <4E0185E7.8020708@samsung.com>
It adds dri-devel@lists.freedesktop.org to this mail thread.
Thank you.
2011년 6월 22일 오후 3:04, daeinki <inki.dae@samsung.com>님의 말:
> below is additional comments.
>
> daeinki 쓴 글:
>> Hi all,
>>
>> I'm writing Samsung SoC based DRM framework and this one includes FIMD
>> and HDMI driver as hardware dependent modules. and for now, encoder,
>> connector, crtc and fb module has been materialized almost. but I'm
>> contending with framebuffer setting issue(created fb_info should be
>> registered to linux framebuffer through register_framebuffer() or not)as
>> default framebuffer at booting time.
>>
>> at drm_fb_helper_single_fb_probe() of drm_fb_helper.c file, fb_helper's
>> fb_probe callback is called and this one creates new framebuffer and
>> returns a value more then 0 if true. internally, this process creates an
>> fb_info object and drm_framebuffer and then drm_framebuffer would be
>> added to mode_config.fb_list of the drm_device.
>>
> it's my mistake. return value is 0 if true, nonzero otherwise.
>
>> a value returned, new_fb is used to decide that it calls
>> register_framebuffer() or drm_fb_helper_set_par(). at this point, I am
>> confused it's a good way to call register_framebuffer() otherwise
>> drm_fb_helper_set_par(). if register_framebuffer() is called then I
>> guess drm_fb_helper_set_par() or drm_crtc_helper_set_config() should be
>> called somewhere subsequently to apply this one to real hardware because
>> previous process is just for maintaining data logically.(not set up data
>> to h/w)
>>
>> it's a right way to call register_framebuffer() and then
>> drm_fb_helper_set_par() or drm_crtc_helper_set_config()? otherwise just
>> only drm_fb_helper_set_par() or drm_crtc_helper_set_config() ignoring
>> register_framebuffer()? and what is the purpose of using
>> register_framebuffer()?
>>
> I understood that if fb_probe() callback is fail then fb_info object is
> registered to linux framebuffer through register_framebuffer()
> otherwise(if true) hardware configuration would be completed by
> drm_fb_helper_set_par() so the reason of using register_framebuffer() is
> that the case of failing fb_probe() callback, it is for drawing on only
> linux framebuffer. is it right?
>
>> In my case, first, register_framebuffer() is called and then if desired
>> default crtc id is matched with drm_fb_helper->crtc_info[0 ~ n].crtc_id,
>> it gets mode_set of drm_fb_helper->crtc_info[n] and then it calls
>> drm_crtc_helper_set_config(mode_set). at this time, all the hardware
>> configurations would be completed.
>>
>> thank you in advance.
>>
>> Best Regards
>> Inki Dae.
>>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 5/5] fbdev: sh_mobile_meram: Assign meram to the SH7372_A4LC power domain
From: Damian Hobson-Garcia @ 2011-06-22 7:49 UTC (permalink / raw)
To: linux-fbdev
Register the MERAM device as a part of the A4LC power domain for
power management.
Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
arch/arm/mach-shmobile/board-mackerel.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index f556b2a..53f2b93 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1585,6 +1585,7 @@ static void __init mackerel_init(void)
sh7372_init_pm_domain(&sh7372_a4lc_domain);
sh7372_add_device_to_domain(SH7372_A4LC, &lcdc_device);
sh7372_add_device_to_domain(SH7372_A4LC, &hdmi_lcdc_device);
+ sh7372_add_device_to_domain(SH7372_A4LC, &meram_device);
hdmi_init_pm_clock();
sh7372_pm_init();
--
1.7.1
^ permalink raw reply related
* [PATCH 4/5 v3] fbdev: sh_mobile_meram: Backup/restore device registers on shutdown/resume
From: Damian Hobson-Garcia @ 2011-06-22 7:49 UTC (permalink / raw)
To: linux-fbdev
Save and reconfigure the MERAM registers when the MERAM is powered down
and restored
Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
Changes from V2
=======
* The private data structure definition was moved from sh_mobile_meram.h to
sh_mobile_meram.c. This has been moved into a separate patch
drivers/video/sh_mobile_meram.c | 71 +++++++++++++++++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index cc71cbf..7afd77a 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -37,12 +37,31 @@
#define MEQSEL1 0x40
#define MEQSEL2 0x44
+static unsigned long common_regs[] = {
+ MEVCR1,
+ MEQSEL1,
+ MEQSEL2,
+};
+#define CMN_REGS_SIZE ARRAY_SIZE(common_regs)
+
+static unsigned long icb_regs[] = {
+ MExxCTL,
+ MExxBSIZE,
+ MExxMNCF,
+ MExxSARA,
+ MExxSARB,
+ MExxSBSIZE,
+};
+#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
+
struct sh_mobile_meram_priv {
void __iomem *base;
struct mutex lock;
unsigned long used_icb;
int used_meram_cache_regions;
unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
+ unsigned long cmn_saved_regs[CMN_REGS_SIZE];
+ unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM];
};
/* settings */
@@ -489,6 +508,57 @@ int sh_mobile_meram_pm_put_sync(struct sh_mobile_meram_info *pdata)
return 0;
}
+static int sh_mobile_meram_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+ int k, j;
+
+ for (k = 0; k < CMN_REGS_SIZE; k++)
+ priv->cmn_saved_regs[k] = meram_read_reg(priv->base,
+ common_regs[k]);
+
+ for (j = 0; j < 32; j++) {
+ if (!test_bit(j, &priv->used_icb))
+ continue;
+ for (k = 0; k < ICB_REGS_SIZE; k++) {
+ priv->icb_saved_regs[j * ICB_REGS_SIZE + k] + meram_read_icb(priv->base, j, icb_regs[k]);
+ /* Reset ICB on resume */
+ if (icb_regs[k] = MExxCTL)
+ priv->icb_saved_regs[j * ICB_REGS_SIZE + k] + 0x70;
+ }
+ }
+ return 0;
+}
+
+static int sh_mobile_meram_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+ int k, j;
+
+ for (j = 0; j < 32; j++) {
+ if (!test_bit(j, &priv->used_icb))
+ continue;
+ for (k = 0; k < ICB_REGS_SIZE; k++) {
+ meram_write_icb(priv->base, j, icb_regs[k],
+ priv->icb_saved_regs[j * ICB_REGS_SIZE + k]);
+ }
+ }
+
+ for (k = 0; k < CMN_REGS_SIZE; k++)
+ meram_write_reg(priv->base, common_regs[k],
+ priv->cmn_saved_regs[k]);
+ return 0;
+}
+
+static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = {
+ .runtime_suspend = sh_mobile_meram_runtime_suspend,
+ .runtime_resume = sh_mobile_meram_runtime_resume,
+};
+
static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
.module = THIS_MODULE,
.meram_register = sh_mobile_meram_register,
@@ -579,6 +649,7 @@ static struct platform_driver sh_mobile_meram_driver = {
.driver = {
.name = "sh_mobile_meram",
.owner = THIS_MODULE,
+ .pm = &sh_mobile_meram_dev_pm_ops,
},
.probe = sh_mobile_meram_probe,
.remove = sh_mobile_meram_remove,
--
1.7.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox