summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2011-03-01 14:55:47 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2011-03-01 14:55:47 +1100
commit45c7e0f733d063ed81002100a005a16f3fc58abf (patch)
treedb15d7dc57f8589485f82df76aaa1157c898a886 /drivers
parent2625773d0492c4253c0f66f04a2d5ae6aaa50741 (diff)
parent799a6268ead76a3572ede4e5bf0d296f4fa3ce96 (diff)
Merge remote-tracking branch 'omap_dss2/for-next'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c25
-rw-r--r--drivers/video/omap2/dss/Kconfig6
-rw-r--r--drivers/video/omap2/dss/core.c450
-rw-r--r--drivers/video/omap2/dss/dispc.c160
-rw-r--r--drivers/video/omap2/dss/dpi.c37
-rw-r--r--drivers/video/omap2/dss/dsi.c116
-rw-r--r--drivers/video/omap2/dss/dss.c459
-rw-r--r--drivers/video/omap2/dss/dss.h56
-rw-r--r--drivers/video/omap2/dss/manager.c4
-rw-r--r--drivers/video/omap2/dss/overlay.c4
-rw-r--r--drivers/video/omap2/dss/rfbi.c128
-rw-r--r--drivers/video/omap2/dss/sdi.c26
-rw-r--r--drivers/video/omap2/dss/venc.c122
-rw-r--r--drivers/video/omap2/omapfb/Kconfig6
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c23
15 files changed, 913 insertions, 709 deletions
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 07eb30ee59c8..4a9b9ff59467 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -156,6 +156,31 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "toppoly_tdo35s",
},
+
+ /* Samsung LTE430WQ-F0C */
+ {
+ {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 9200,
+
+ .hfp = 8,
+ .hsw = 41,
+ .hbp = 45 - 41,
+
+ .vfp = 4,
+ .vsw = 10,
+ .vbp = 12 - 10,
+ },
+ .acbi = 0x0,
+ .acb = 0x0,
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .power_on_delay = 0,
+ .power_off_delay = 0,
+ .name = "samsung_lte430wq_f0c",
+ },
};
struct panel_drv_data {
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 43b64403eaa4..db01473c3307 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,8 +1,8 @@
menuconfig OMAP2_DSS
- tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
- depends on ARCH_OMAP2 || ARCH_OMAP3
+ tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)"
+ depends on ARCH_OMAP2PLUS
help
- OMAP2/3 Display Subsystem support.
+ OMAP2+ Display Subsystem support.
if OMAP2_DSS
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 8e89f6049280..266cd3cbf4df 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -34,332 +34,26 @@
#include <linux/regulator/consumer.h>
#include <plat/display.h>
-#include <plat/clock.h>
#include "dss.h"
#include "dss_features.h"
static struct {
struct platform_device *pdev;
- int ctx_id;
-
- struct clk *dss_ick;
- struct clk *dss1_fck;
- struct clk *dss2_fck;
- struct clk *dss_54m_fck;
- struct clk *dss_96m_fck;
- unsigned num_clks_enabled;
struct regulator *vdds_dsi_reg;
struct regulator *vdds_sdi_reg;
- struct regulator *vdda_dac_reg;
} core;
-static void dss_clk_enable_all_no_ctx(void);
-static void dss_clk_disable_all_no_ctx(void);
-static void dss_clk_enable_no_ctx(enum dss_clock clks);
-static void dss_clk_disable_no_ctx(enum dss_clock clks);
-
static char *def_disp_name;
module_param_named(def_disp, def_disp_name, charp, 0);
-MODULE_PARM_DESC(def_disp_name, "default display name");
+MODULE_PARM_DESC(def_disp, "default display name");
#ifdef DEBUG
unsigned int dss_debug;
module_param_named(debug, dss_debug, bool, 0644);
#endif
-/* CONTEXT */
-static int dss_get_ctx_id(void)
-{
- struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
- int r;
-
- if (!pdata->get_last_off_on_transaction_id)
- return 0;
- r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
- if (r < 0) {
- dev_err(&core.pdev->dev, "getting transaction ID failed, "
- "will force context restore\n");
- r = -1;
- }
- return r;
-}
-
-int dss_need_ctx_restore(void)
-{
- int id = dss_get_ctx_id();
-
- if (id < 0 || id != core.ctx_id) {
- DSSDBG("ctx id %d -> id %d\n",
- core.ctx_id, id);
- core.ctx_id = id;
- return 1;
- } else {
- return 0;
- }
-}
-
-static void save_all_ctx(void)
-{
- DSSDBG("save context\n");
-
- dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
-
- dss_save_context();
- dispc_save_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
- dsi_save_context();
-#endif
-
- dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
-}
-
-static void restore_all_ctx(void)
-{
- DSSDBG("restore context\n");
-
- dss_clk_enable_all_no_ctx();
-
- dss_restore_context();
- dispc_restore_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
- dsi_restore_context();
-#endif
-
- dss_clk_disable_all_no_ctx();
-}
-
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-/* CLOCKS */
-static void core_dump_clocks(struct seq_file *s)
-{
- int i;
- struct clk *clocks[5] = {
- core.dss_ick,
- core.dss1_fck,
- core.dss2_fck,
- core.dss_54m_fck,
- core.dss_96m_fck
- };
-
- seq_printf(s, "- CORE -\n");
-
- seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled);
-
- for (i = 0; i < 5; i++) {
- if (!clocks[i])
- continue;
- seq_printf(s, "%-15s\t%lu\t%d\n",
- clocks[i]->name,
- clk_get_rate(clocks[i]),
- clocks[i]->usecount);
- }
-}
-#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
-
-static int dss_get_clock(struct clk **clock, const char *clk_name)
-{
- struct clk *clk;
-
- clk = clk_get(&core.pdev->dev, clk_name);
-
- if (IS_ERR(clk)) {
- DSSERR("can't get clock %s", clk_name);
- return PTR_ERR(clk);
- }
-
- *clock = clk;
-
- DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
-
- return 0;
-}
-
-static int dss_get_clocks(void)
-{
- int r;
-
- core.dss_ick = NULL;
- core.dss1_fck = NULL;
- core.dss2_fck = NULL;
- core.dss_54m_fck = NULL;
- core.dss_96m_fck = NULL;
-
- r = dss_get_clock(&core.dss_ick, "ick");
- if (r)
- goto err;
-
- r = dss_get_clock(&core.dss1_fck, "dss1_fck");
- if (r)
- goto err;
-
- r = dss_get_clock(&core.dss2_fck, "dss2_fck");
- if (r)
- goto err;
-
- r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
- if (r)
- goto err;
-
- r = dss_get_clock(&core.dss_96m_fck, "video_fck");
- if (r)
- goto err;
-
- return 0;
-
-err:
- if (core.dss_ick)
- clk_put(core.dss_ick);
- if (core.dss1_fck)
- clk_put(core.dss1_fck);
- if (core.dss2_fck)
- clk_put(core.dss2_fck);
- if (core.dss_54m_fck)
- clk_put(core.dss_54m_fck);
- if (core.dss_96m_fck)
- clk_put(core.dss_96m_fck);
-
- return r;
-}
-
-static void dss_put_clocks(void)
-{
- if (core.dss_96m_fck)
- clk_put(core.dss_96m_fck);
- clk_put(core.dss_54m_fck);
- clk_put(core.dss1_fck);
- clk_put(core.dss2_fck);
- clk_put(core.dss_ick);
-}
-
-unsigned long dss_clk_get_rate(enum dss_clock clk)
-{
- switch (clk) {
- case DSS_CLK_ICK:
- return clk_get_rate(core.dss_ick);
- case DSS_CLK_FCK1:
- return clk_get_rate(core.dss1_fck);
- case DSS_CLK_FCK2:
- return clk_get_rate(core.dss2_fck);
- case DSS_CLK_54M:
- return clk_get_rate(core.dss_54m_fck);
- case DSS_CLK_96M:
- return clk_get_rate(core.dss_96m_fck);
- }
-
- BUG();
- return 0;
-}
-
-static unsigned count_clk_bits(enum dss_clock clks)
-{
- unsigned num_clks = 0;
-
- if (clks & DSS_CLK_ICK)
- ++num_clks;
- if (clks & DSS_CLK_FCK1)
- ++num_clks;
- if (clks & DSS_CLK_FCK2)
- ++num_clks;
- if (clks & DSS_CLK_54M)
- ++num_clks;
- if (clks & DSS_CLK_96M)
- ++num_clks;
-
- return num_clks;
-}
-
-static void dss_clk_enable_no_ctx(enum dss_clock clks)
-{
- unsigned num_clks = count_clk_bits(clks);
-
- if (clks & DSS_CLK_ICK)
- clk_enable(core.dss_ick);
- if (clks & DSS_CLK_FCK1)
- clk_enable(core.dss1_fck);
- if (clks & DSS_CLK_FCK2)
- clk_enable(core.dss2_fck);
- if (clks & DSS_CLK_54M)
- clk_enable(core.dss_54m_fck);
- if (clks & DSS_CLK_96M)
- clk_enable(core.dss_96m_fck);
-
- core.num_clks_enabled += num_clks;
-}
-
-void dss_clk_enable(enum dss_clock clks)
-{
- bool check_ctx = core.num_clks_enabled == 0;
-
- dss_clk_enable_no_ctx(clks);
-
- if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
- restore_all_ctx();
-}
-
-static void dss_clk_disable_no_ctx(enum dss_clock clks)
-{
- unsigned num_clks = count_clk_bits(clks);
-
- if (clks & DSS_CLK_ICK)
- clk_disable(core.dss_ick);
- if (clks & DSS_CLK_FCK1)
- clk_disable(core.dss1_fck);
- if (clks & DSS_CLK_FCK2)
- clk_disable(core.dss2_fck);
- if (clks & DSS_CLK_54M)
- clk_disable(core.dss_54m_fck);
- if (clks & DSS_CLK_96M)
- clk_disable(core.dss_96m_fck);
-
- core.num_clks_enabled -= num_clks;
-}
-
-void dss_clk_disable(enum dss_clock clks)
-{
- if (cpu_is_omap34xx()) {
- unsigned num_clks = count_clk_bits(clks);
-
- BUG_ON(core.num_clks_enabled < num_clks);
-
- if (core.num_clks_enabled == num_clks)
- save_all_ctx();
- }
-
- dss_clk_disable_no_ctx(clks);
-}
-
-static void dss_clk_enable_all_no_ctx(void)
-{
- enum dss_clock clks;
-
- clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
- if (cpu_is_omap34xx())
- clks |= DSS_CLK_96M;
- dss_clk_enable_no_ctx(clks);
-}
-
-static void dss_clk_disable_all_no_ctx(void)
-{
- enum dss_clock clks;
-
- clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
- if (cpu_is_omap34xx())
- clks |= DSS_CLK_96M;
- dss_clk_disable_no_ctx(clks);
-}
-
-static void dss_clk_disable_all(void)
-{
- enum dss_clock clks;
-
- clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
- if (cpu_is_omap34xx())
- clks |= DSS_CLK_96M;
- dss_clk_disable(clks);
-}
-
/* REGULATORS */
struct regulator *dss_get_vdds_dsi(void)
@@ -390,32 +84,7 @@ struct regulator *dss_get_vdds_sdi(void)
return reg;
}
-struct regulator *dss_get_vdda_dac(void)
-{
- struct regulator *reg;
-
- if (core.vdda_dac_reg != NULL)
- return core.vdda_dac_reg;
-
- reg = regulator_get(&core.pdev->dev, "vdda_dac");
- if (!IS_ERR(reg))
- core.vdda_dac_reg = reg;
-
- return reg;
-}
-
-/* DEBUGFS */
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-static void dss_debug_dump_clocks(struct seq_file *s)
-{
- core_dump_clocks(s);
- dss_dump_clocks(s);
- dispc_dump_clocks(s);
-#ifdef CONFIG_OMAP2_DSS_DSI
- dsi_dump_clocks(s);
-#endif
-}
-
static int dss_debug_show(struct seq_file *s, void *unused)
{
void (*func)(struct seq_file *) = s->private;
@@ -508,30 +177,18 @@ static int omap_dss_probe(struct platform_device *pdev)
dss_init_overlay_managers(pdev);
dss_init_overlays(pdev);
- r = dss_get_clocks();
- if (r)
- goto err_clocks;
-
- dss_clk_enable_all_no_ctx();
-
- core.ctx_id = dss_get_ctx_id();
- DSSDBG("initial ctx id %u\n", core.ctx_id);
-
-#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
- /* DISPC_CONTROL */
- if (omap_readl(0x48050440) & 1) /* LCD enabled? */
- skip_init = 1;
-#endif
-
- r = dss_init(skip_init);
+ r = dss_init_platform_driver();
if (r) {
- DSSERR("Failed to initialize DSS\n");
+ DSSERR("Failed to initialize DSS platform driver\n");
goto err_dss;
}
- r = rfbi_init();
+ /* keep clocks enabled to prevent context saves/restores during init */
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+
+ r = rfbi_init_platform_driver();
if (r) {
- DSSERR("Failed to initialize rfbi\n");
+ DSSERR("Failed to initialize rfbi platform driver\n");
goto err_rfbi;
}
@@ -541,18 +198,23 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_dpi;
}
- r = dispc_init();
+ r = dispc_init_platform_driver();
if (r) {
- DSSERR("Failed to initialize dispc\n");
+ DSSERR("Failed to initialize dispc platform driver\n");
goto err_dispc;
}
- r = venc_init(pdev);
+ r = venc_init_platform_driver();
if (r) {
- DSSERR("Failed to initialize venc\n");
+ DSSERR("Failed to initialize venc platform driver\n");
goto err_venc;
}
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ /* DISPC_CONTROL */
+ if (omap_readl(0x48050440) & 1) /* LCD enabled? */
+ skip_init = 1;
+#endif
if (cpu_is_omap34xx()) {
r = sdi_init(skip_init);
if (r) {
@@ -560,9 +222,9 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_sdi;
}
- r = dsi_init(pdev);
+ r = dsi_init_platform_driver();
if (r) {
- DSSERR("Failed to initialize DSI\n");
+ DSSERR("Failed to initialize DSI platform driver\n");
goto err_dsi;
}
}
@@ -589,7 +251,7 @@ static int omap_dss_probe(struct platform_device *pdev)
pdata->default_device = dssdev;
}
- dss_clk_disable_all();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return 0;
@@ -597,24 +259,21 @@ err_register:
dss_uninitialize_debugfs();
err_debugfs:
if (cpu_is_omap34xx())
- dsi_exit();
+ dsi_uninit_platform_driver();
err_dsi:
if (cpu_is_omap34xx())
sdi_exit();
err_sdi:
- venc_exit();
+ venc_uninit_platform_driver();
err_venc:
- dispc_exit();
+ dispc_uninit_platform_driver();
err_dispc:
dpi_exit();
err_dpi:
- rfbi_exit();
+ rfbi_uninit_platform_driver();
err_rfbi:
- dss_exit();
+ dss_uninit_platform_driver();
err_dss:
- dss_clk_disable_all_no_ctx();
- dss_put_clocks();
-err_clocks:
return r;
}
@@ -623,61 +282,19 @@ static int omap_dss_remove(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
int i;
- int c;
dss_uninitialize_debugfs();
- venc_exit();
- dispc_exit();
+ venc_uninit_platform_driver();
+ dispc_uninit_platform_driver();
dpi_exit();
- rfbi_exit();
+ rfbi_uninit_platform_driver();
if (cpu_is_omap34xx()) {
- dsi_exit();
+ dsi_uninit_platform_driver();
sdi_exit();
}
- dss_exit();
-
- /* these should be removed at some point */
- c = core.dss_ick->usecount;
- if (c > 0) {
- DSSERR("warning: dss_ick usecount %d, disabling\n", c);
- while (c-- > 0)
- clk_disable(core.dss_ick);
- }
-
- c = core.dss1_fck->usecount;
- if (c > 0) {
- DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
- while (c-- > 0)
- clk_disable(core.dss1_fck);
- }
-
- c = core.dss2_fck->usecount;
- if (c > 0) {
- DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
- while (c-- > 0)
- clk_disable(core.dss2_fck);
- }
-
- c = core.dss_54m_fck->usecount;
- if (c > 0) {
- DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
- while (c-- > 0)
- clk_disable(core.dss_54m_fck);
- }
-
- if (core.dss_96m_fck) {
- c = core.dss_96m_fck->usecount;
- if (c > 0) {
- DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
- c);
- while (c-- > 0)
- clk_disable(core.dss_96m_fck);
- }
- }
-
- dss_put_clocks();
+ dss_uninit_platform_driver();
dss_uninit_overlays(pdev);
dss_uninit_overlay_managers(pdev);
@@ -715,7 +332,7 @@ static struct platform_driver omap_dss_driver = {
.suspend = omap_dss_suspend,
.resume = omap_dss_resume,
.driver = {
- .name = "omapdss",
+ .name = "omap_display",
.owner = THIS_MODULE,
},
};
@@ -965,11 +582,6 @@ static void __exit omap_dss_exit(void)
core.vdds_sdi_reg = NULL;
}
- if (core.vdda_dac_reg != NULL) {
- regulator_put(core.vdda_dac_reg);
- core.vdda_dac_reg = NULL;
- }
-
platform_driver_unregister(&omap_dss_driver);
omap_dss_bus_unregister();
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 9f8c69f16e61..762ce6beeba7 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/hardirq.h>
+#include <linux/interrupt.h>
#include <plat/sram.h>
#include <plat/clock.h>
@@ -42,8 +43,6 @@
#include "dss_features.h"
/* DISPC */
-#define DISPC_BASE 0x48050400
-
#define DISPC_SZ_REGS SZ_4K
struct dispc_reg { u16 idx; };
@@ -178,7 +177,9 @@ struct dispc_irq_stats {
};
static struct {
+ struct platform_device *pdev;
void __iomem *base;
+ int irq;
u32 fifo_size[3];
@@ -552,9 +553,9 @@ void dispc_restore_context(void)
static inline void enable_clocks(bool enable)
{
if (enable)
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
else
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
bool dispc_go_busy(enum omap_channel channel)
@@ -2312,7 +2313,7 @@ unsigned long dispc_fclk_rate(void)
unsigned long r = 0;
if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
- r = dss_clk_get_rate(DSS_CLK_FCK1);
+ r = dss_clk_get_rate(DSS_CLK_FCK);
else
#ifdef CONFIG_OMAP2_DSS_DSI
r = dsi_get_dsi1_pll_rate();
@@ -2440,7 +2441,7 @@ void dispc_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(DISPC_REVISION);
DUMPREG(DISPC_SYSCONFIG);
@@ -2597,7 +2598,7 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_VID_PRELOAD(0));
DUMPREG(DISPC_VID_PRELOAD(1));
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -2866,10 +2867,10 @@ static void print_irq_status(u32 status)
* but we presume they are on because we got an IRQ. However,
* an irq handler may turn the clocks off, so we may not have
* clock later in the function. */
-void dispc_irq_handler(void)
+static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
{
int i;
- u32 irqstatus;
+ u32 irqstatus, irqenable;
u32 handledirqs = 0;
u32 unhandled_errors;
struct omap_dispc_isr_data *isr_data;
@@ -2878,6 +2879,13 @@ void dispc_irq_handler(void)
spin_lock(&dispc.irq_lock);
irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
+ irqenable = dispc_read_reg(DISPC_IRQENABLE);
+
+ /* IRQ is not for us */
+ if (!(irqstatus & irqenable)) {
+ spin_unlock(&dispc.irq_lock);
+ return IRQ_NONE;
+ }
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
spin_lock(&dispc.irq_stats_lock);
@@ -2929,6 +2937,8 @@ void dispc_irq_handler(void)
}
spin_unlock(&dispc.irq_lock);
+
+ return IRQ_HANDLED;
}
static void dispc_error_worker(struct work_struct *work)
@@ -3269,47 +3279,6 @@ static void _omap_dispc_initial_config(void)
dispc_read_plane_fifo_sizes();
}
-int dispc_init(void)
-{
- u32 rev;
-
- spin_lock_init(&dispc.irq_lock);
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
- spin_lock_init(&dispc.irq_stats_lock);
- dispc.irq_stats.last_reset = jiffies;
-#endif
-
- INIT_WORK(&dispc.error_work, dispc_error_worker);
-
- dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
- if (!dispc.base) {
- DSSERR("can't ioremap DISPC\n");
- return -ENOMEM;
- }
-
- enable_clocks(1);
-
- _omap_dispc_initial_config();
-
- _omap_dispc_initialize_irq();
-
- dispc_save_context();
-
- rev = dispc_read_reg(DISPC_REVISION);
- printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
- FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
- enable_clocks(0);
-
- return 0;
-}
-
-void dispc_exit(void)
-{
- iounmap(dispc.base);
-}
-
int dispc_enable_plane(enum omap_plane plane, bool enable)
{
DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -3359,3 +3328,94 @@ int dispc_setup_plane(enum omap_plane plane,
return r;
}
+
+/* DISPC HW IP initialisation */
+static int omap_dispchw_probe(struct platform_device *pdev)
+{
+ u32 rev;
+ int r = 0;
+ struct resource *dispc_mem;
+
+ dispc.pdev = pdev;
+
+ spin_lock_init(&dispc.irq_lock);
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+ spin_lock_init(&dispc.irq_stats_lock);
+ dispc.irq_stats.last_reset = jiffies;
+#endif
+
+ INIT_WORK(&dispc.error_work, dispc_error_worker);
+
+ dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
+ if (!dispc_mem) {
+ DSSERR("can't get IORESOURCE_MEM DISPC\n");
+ r = -EINVAL;
+ goto fail0;
+ }
+ dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
+ if (!dispc.base) {
+ DSSERR("can't ioremap DISPC\n");
+ r = -ENOMEM;
+ goto fail0;
+ }
+ dispc.irq = platform_get_irq(dispc.pdev, 0);
+ if (dispc.irq < 0) {
+ DSSERR("platform_get_irq failed\n");
+ r = -ENODEV;
+ goto fail1;
+ }
+
+ r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
+ "OMAP DISPC", dispc.pdev);
+ if (r < 0) {
+ DSSERR("request_irq failed\n");
+ goto fail1;
+ }
+
+ enable_clocks(1);
+
+ _omap_dispc_initial_config();
+
+ _omap_dispc_initialize_irq();
+
+ dispc_save_context();
+
+ rev = dispc_read_reg(DISPC_REVISION);
+ dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ enable_clocks(0);
+
+ return 0;
+fail1:
+ iounmap(dispc.base);
+fail0:
+ return r;
+}
+
+static int omap_dispchw_remove(struct platform_device *pdev)
+{
+ free_irq(dispc.irq, dispc.pdev);
+ iounmap(dispc.base);
+ return 0;
+}
+
+static struct platform_driver omap_dispchw_driver = {
+ .probe = omap_dispchw_probe,
+ .remove = omap_dispchw_remove,
+ .driver = {
+ .name = "omap_dispc",
+ .owner = THIS_MODULE,
+ },
+};
+
+int dispc_init_platform_driver(void)
+{
+ return platform_driver_register(&omap_dispchw_driver);
+}
+
+void dispc_uninit_platform_driver(void)
+{
+ return platform_driver_unregister(&omap_dispchw_driver);
+}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 75fb0a515430..026702b921e5 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -107,7 +107,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
bool is_tft;
int r = 0;
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dssdev->panel.acbi, dssdev->panel.acb);
@@ -137,7 +137,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
dispc_set_lcd_timings(dssdev->manager->id, t);
err0:
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return r;
}
@@ -173,14 +173,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
goto err1;
}
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
r = dpi_basic_init(dssdev);
if (r)
goto err2;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
- dss_clk_enable(DSS_CLK_FCK2);
+ dss_clk_enable(DSS_CLK_SYSCK);
r = dsi_pll_init(dssdev, 0, 1);
if (r)
goto err3;
@@ -199,10 +199,10 @@ err4:
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dsi_pll_uninit();
err3:
- dss_clk_disable(DSS_CLK_FCK2);
+ dss_clk_disable(DSS_CLK_SYSCK);
#endif
err2:
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
err1:
@@ -219,10 +219,10 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
dsi_pll_uninit();
- dss_clk_disable(DSS_CLK_FCK2);
+ dss_clk_disable(DSS_CLK_SYSCK);
#endif
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
@@ -303,22 +303,27 @@ int dpi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("init_display\n");
- return 0;
-}
+ if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
+ struct regulator *vdds_dsi;
-int dpi_init(struct platform_device *pdev)
-{
- if (cpu_is_omap34xx()) {
- dpi.vdds_dsi_reg = dss_get_vdds_dsi();
- if (IS_ERR(dpi.vdds_dsi_reg)) {
+ vdds_dsi = dss_get_vdds_dsi();
+
+ if (IS_ERR(vdds_dsi)) {
DSSERR("can't get VDDS_DSI regulator\n");
- return PTR_ERR(dpi.vdds_dsi_reg);
+ return PTR_ERR(vdds_dsi);
}
+
+ dpi.vdds_dsi_reg = vdds_dsi;
}
return 0;
}
+int dpi_init(struct platform_device *pdev)
+{
+ return 0;
+}
+
void dpi_exit(void)
{
}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index ddf3a0560822..2444404c6179 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -42,8 +42,6 @@
/*#define VERBOSE_IRQ*/
#define DSI_CATCH_MISSING_TE
-#define DSI_BASE 0x4804FC00
-
struct dsi_reg { u16 idx; };
#define DSI_REG(idx) ((const struct dsi_reg) { idx })
@@ -222,7 +220,9 @@ struct dsi_irq_stats {
static struct
{
+ struct platform_device *pdev;
void __iomem *base;
+ int irq;
struct dsi_clock_info current_cinfo;
@@ -481,13 +481,17 @@ static void print_irq_status_cio(u32 status)
static int debug_irq;
/* called from dss */
-void dsi_irq_handler(void)
+static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
{
u32 irqstatus, vcstatus, ciostatus;
int i;
irqstatus = dsi_read_reg(DSI_IRQSTATUS);
+ /* IRQ is not for us */
+ if (!irqstatus)
+ return IRQ_NONE;
+
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
spin_lock(&dsi.irq_stats_lock);
dsi.irq_stats.irq_count++;
@@ -565,9 +569,9 @@ void dsi_irq_handler(void)
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
spin_unlock(&dsi.irq_stats_lock);
#endif
+ return IRQ_HANDLED;
}
-
static void _dsi_initialize_irq(void)
{
u32 l;
@@ -641,18 +645,18 @@ static void dsi_vc_disable_bta_irq(int channel)
static inline void enable_clocks(bool enable)
{
if (enable)
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
else
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
/* source clock for DSI PLL. this could also be PCLKFREE */
static inline void dsi_enable_pll_clock(bool enable)
{
if (enable)
- dss_clk_enable(DSS_CLK_FCK2);
+ dss_clk_enable(DSS_CLK_SYSCK);
else
- dss_clk_disable(DSS_CLK_FCK2);
+ dss_clk_disable(DSS_CLK_SYSCK);
if (enable && dsi.pll_locked) {
if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
@@ -728,7 +732,7 @@ static unsigned long dsi_fclk_rate(void)
if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) {
/* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
- r = dss_clk_get_rate(DSS_CLK_FCK1);
+ r = dss_clk_get_rate(DSS_CLK_FCK);
} else {
/* DSI FCLK source is DSI2_PLL_FCLK */
r = dsi_get_dsi2_pll_rate();
@@ -808,7 +812,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
return -EINVAL;
if (cinfo->use_dss2_fck) {
- cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2);
+ cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
/* XXX it is unclear if highfreq should be used
* with DSS2_FCK source also */
cinfo->highfreq = 0;
@@ -854,7 +858,7 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
int match = 0;
unsigned long dss_clk_fck2;
- dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
+ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_SYSCK);
if (req_pck == dsi.cache_req_pck &&
dsi.cache_cinfo.clkin == dss_clk_fck2) {
@@ -1306,7 +1310,7 @@ void dsi_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(DSI_REVISION);
DUMPREG(DSI_SYSCONFIG);
@@ -1378,7 +1382,7 @@ void dsi_dump_regs(struct seq_file *s)
DUMPREG(DSI_PLL_CONFIGURATION1);
DUMPREG(DSI_PLL_CONFIGURATION2);
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -3223,6 +3227,19 @@ int dsi_init_display(struct omap_dss_device *dssdev)
dsi.vc[0].dssdev = dssdev;
dsi.vc[1].dssdev = dssdev;
+ if (dsi.vdds_dsi_reg == NULL) {
+ struct regulator *vdds_dsi;
+
+ vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi");
+
+ if (IS_ERR(vdds_dsi)) {
+ DSSERR("can't get VDDS_DSI regulator\n");
+ return PTR_ERR(vdds_dsi);
+ }
+
+ dsi.vdds_dsi_reg = vdds_dsi;
+ }
+
return 0;
}
@@ -3238,10 +3255,11 @@ void dsi_wait_dsi2_pll_active(void)
DSSERR("DSI2 PLL clock not active\n");
}
-int dsi_init(struct platform_device *pdev)
+static int dsi_init(struct platform_device *pdev)
{
u32 rev;
int r;
+ struct resource *dsi_mem;
spin_lock_init(&dsi.errors_lock);
dsi.errors = 0;
@@ -3268,24 +3286,36 @@ int dsi_init(struct platform_device *pdev)
dsi.te_timer.function = dsi_te_timeout;
dsi.te_timer.data = 0;
#endif
- dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
+ dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0);
+ if (!dsi_mem) {
+ DSSERR("can't get IORESOURCE_MEM DSI\n");
+ r = -EINVAL;
+ goto err1;
+ }
+ dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem));
if (!dsi.base) {
DSSERR("can't ioremap DSI\n");
r = -ENOMEM;
goto err1;
}
+ dsi.irq = platform_get_irq(dsi.pdev, 0);
+ if (dsi.irq < 0) {
+ DSSERR("platform_get_irq failed\n");
+ r = -ENODEV;
+ goto err2;
+ }
- dsi.vdds_dsi_reg = dss_get_vdds_dsi();
- if (IS_ERR(dsi.vdds_dsi_reg)) {
- DSSERR("can't get VDDS_DSI regulator\n");
- r = PTR_ERR(dsi.vdds_dsi_reg);
+ r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED,
+ "OMAP DSI1", dsi.pdev);
+ if (r < 0) {
+ DSSERR("request_irq failed\n");
goto err2;
}
enable_clocks(1);
rev = dsi_read_reg(DSI_REVISION);
- printk(KERN_INFO "OMAP DSI rev %d.%d\n",
+ dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n",
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
enable_clocks(0);
@@ -3298,8 +3328,14 @@ err1:
return r;
}
-void dsi_exit(void)
+static void dsi_exit(void)
{
+ if (dsi.vdds_dsi_reg != NULL) {
+ regulator_put(dsi.vdds_dsi_reg);
+ dsi.vdds_dsi_reg = NULL;
+ }
+
+ free_irq(dsi.irq, dsi.pdev);
iounmap(dsi.base);
destroy_workqueue(dsi.workqueue);
@@ -3307,3 +3343,41 @@ void dsi_exit(void)
DSSDBG("omap_dsi_exit\n");
}
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *pdev)
+{
+ int r;
+ dsi.pdev = pdev;
+ r = dsi_init(pdev);
+ if (r) {
+ DSSERR("Failed to initialize DSI\n");
+ goto err_dsi;
+ }
+err_dsi:
+ return r;
+}
+
+static int omap_dsi1hw_remove(struct platform_device *pdev)
+{
+ dsi_exit();
+ return 0;
+}
+
+static struct platform_driver omap_dsi1hw_driver = {
+ .probe = omap_dsi1hw_probe,
+ .remove = omap_dsi1hw_remove,
+ .driver = {
+ .name = "omap_dsi1",
+ .owner = THIS_MODULE,
+ },
+};
+
+int dsi_init_platform_driver(void)
+{
+ return platform_driver_register(&omap_dsi1hw_driver);
+}
+
+void dsi_uninit_platform_driver(void)
+{
+ return platform_driver_unregister(&omap_dsi1hw_driver);
+}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 77c3621c9171..5a93e6678213 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -26,15 +26,13 @@
#include <linux/io.h>
#include <linux/err.h>
#include <linux/delay.h>
-#include <linux/interrupt.h>
#include <linux/seq_file.h>
#include <linux/clk.h>
#include <plat/display.h>
+#include <plat/clock.h>
#include "dss.h"
-#define DSS_BASE 0x48050000
-
#define DSS_SZ_REGS SZ_512
struct dss_reg {
@@ -59,9 +57,17 @@ struct dss_reg {
dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
static struct {
+ struct platform_device *pdev;
void __iomem *base;
+ int ctx_id;
struct clk *dpll4_m4_ck;
+ struct clk *dss_ick;
+ struct clk *dss_fck;
+ struct clk *dss_sys_clk;
+ struct clk *dss_tv_fck;
+ struct clk *dss_video_fck;
+ unsigned num_clks_enabled;
unsigned long cache_req_pck;
unsigned long cache_prate;
@@ -74,6 +80,11 @@ static struct {
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
} dss;
+static void dss_clk_enable_all_no_ctx(void);
+static void dss_clk_disable_all_no_ctx(void);
+static void dss_clk_enable_no_ctx(enum dss_clock clks);
+static void dss_clk_disable_no_ctx(enum dss_clock clks);
+
static int _omap_dss_wait_reset(void);
static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -214,7 +225,7 @@ void dss_dump_clocks(struct seq_file *s)
unsigned long dpll4_ck_rate;
unsigned long dpll4_m4_ck_rate;
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
@@ -227,21 +238,21 @@ void dss_dump_clocks(struct seq_file *s)
seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n",
dpll4_ck_rate,
dpll4_ck_rate / dpll4_m4_ck_rate,
- dss_clk_get_rate(DSS_CLK_FCK1));
+ dss_clk_get_rate(DSS_CLK_FCK));
else
seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
dpll4_ck_rate,
dpll4_ck_rate / dpll4_m4_ck_rate,
- dss_clk_get_rate(DSS_CLK_FCK1));
+ dss_clk_get_rate(DSS_CLK_FCK));
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
void dss_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(DSS_REVISION);
DUMPREG(DSS_SYSCONFIG);
@@ -252,7 +263,7 @@ void dss_dump_regs(struct seq_file *s)
DUMPREG(DSS_PLL_CONTROL);
DUMPREG(DSS_SDI_STATUS);
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -337,7 +348,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
int dss_get_clock_div(struct dss_clock_info *cinfo)
{
- cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
if (cpu_is_omap34xx()) {
unsigned long prate;
@@ -378,7 +389,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
prate = dss_get_dpll4_rate();
- fck = dss_clk_get_rate(DSS_CLK_FCK1);
+ fck = dss_clk_get_rate(DSS_CLK_FCK);
if (req_pck == dss.cache_req_pck &&
((cpu_is_omap34xx() && prate == dss.cache_prate) ||
dss.cache_dss_cinfo.fck == fck)) {
@@ -405,7 +416,7 @@ retry:
if (cpu_is_omap24xx()) {
struct dispc_clock_info cur_dispc;
/* XXX can we change the clock on omap2? */
- fck = dss_clk_get_rate(DSS_CLK_FCK1);
+ fck = dss_clk_get_rate(DSS_CLK_FCK);
fck_div = 1;
dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -482,31 +493,6 @@ found:
return 0;
}
-
-
-static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
-{
- dispc_irq_handler();
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
-{
- u32 irqstatus;
-
- irqstatus = dss_read_reg(DSS_IRQSTATUS);
-
- if (irqstatus & (1<<0)) /* DISPC_IRQ */
- dispc_irq_handler();
-#ifdef CONFIG_OMAP2_DSS_DSI
- if (irqstatus & (1<<1)) /* DSI_IRQ */
- dsi_irq_handler();
-#endif
-
- return IRQ_HANDLED;
-}
-
static int _omap_dss_wait_reset(void)
{
int t = 0;
@@ -549,12 +535,19 @@ void dss_set_dac_pwrdn_bgz(bool enable)
REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
}
-int dss_init(bool skip_init)
+static int dss_init(bool skip_init)
{
int r;
u32 rev;
+ struct resource *dss_mem;
- dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
+ dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+ if (!dss_mem) {
+ DSSERR("can't get IORESOURCE_MEM DSS\n");
+ r = -EINVAL;
+ goto fail0;
+ }
+ dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
if (!dss.base) {
DSSERR("can't ioremap DSS\n");
r = -ENOMEM;
@@ -590,23 +583,12 @@ int dss_init(bool skip_init)
REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
#endif
- r = request_irq(INT_24XX_DSS_IRQ,
- cpu_is_omap24xx()
- ? dss_irq_handler_omap2
- : dss_irq_handler_omap3,
- 0, "OMAP DSS", NULL);
-
- if (r < 0) {
- DSSERR("omap2 dss: request_irq failed\n");
- goto fail1;
- }
-
if (cpu_is_omap34xx()) {
dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
if (IS_ERR(dss.dpll4_m4_ck)) {
DSSERR("Failed to get dpll4_m4_ck\n");
r = PTR_ERR(dss.dpll4_m4_ck);
- goto fail2;
+ goto fail1;
}
}
@@ -621,21 +603,386 @@ int dss_init(bool skip_init)
return 0;
-fail2:
- free_irq(INT_24XX_DSS_IRQ, NULL);
fail1:
iounmap(dss.base);
fail0:
return r;
}
-void dss_exit(void)
+static void dss_exit(void)
{
if (cpu_is_omap34xx())
clk_put(dss.dpll4_m4_ck);
- free_irq(INT_24XX_DSS_IRQ, NULL);
-
iounmap(dss.base);
}
+/* CONTEXT */
+static int dss_get_ctx_id(void)
+{
+ struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
+ int r;
+
+ if (!pdata->board_data->get_last_off_on_transaction_id)
+ return 0;
+ r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
+ if (r < 0) {
+ dev_err(&dss.pdev->dev, "getting transaction ID failed, "
+ "will force context restore\n");
+ r = -1;
+ }
+ return r;
+}
+
+int dss_need_ctx_restore(void)
+{
+ int id = dss_get_ctx_id();
+
+ if (id < 0 || id != dss.ctx_id) {
+ DSSDBG("ctx id %d -> id %d\n",
+ dss.ctx_id, id);
+ dss.ctx_id = id;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void save_all_ctx(void)
+{
+ DSSDBG("save context\n");
+
+ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
+
+ dss_save_context();
+ dispc_save_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_save_context();
+#endif
+
+ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
+}
+
+static void restore_all_ctx(void)
+{
+ DSSDBG("restore context\n");
+
+ dss_clk_enable_all_no_ctx();
+
+ dss_restore_context();
+ dispc_restore_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_restore_context();
+#endif
+
+ dss_clk_disable_all_no_ctx();
+}
+
+static int dss_get_clock(struct clk **clock, const char *clk_name)
+{
+ struct clk *clk;
+
+ clk = clk_get(&dss.pdev->dev, clk_name);
+
+ if (IS_ERR(clk)) {
+ DSSERR("can't get clock %s", clk_name);
+ return PTR_ERR(clk);
+ }
+
+ *clock = clk;
+
+ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
+
+ return 0;
+}
+
+static int dss_get_clocks(void)
+{
+ int r;
+
+ dss.dss_ick = NULL;
+ dss.dss_fck = NULL;
+ dss.dss_sys_clk = NULL;
+ dss.dss_tv_fck = NULL;
+ dss.dss_video_fck = NULL;
+
+ r = dss_get_clock(&dss.dss_ick, "ick");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&dss.dss_fck, "fck");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&dss.dss_video_fck, "video_clk");
+ if (r)
+ goto err;
+
+ return 0;
+
+err:
+ if (dss.dss_ick)
+ clk_put(dss.dss_ick);
+ if (dss.dss_fck)
+ clk_put(dss.dss_fck);
+ if (dss.dss_sys_clk)
+ clk_put(dss.dss_sys_clk);
+ if (dss.dss_tv_fck)
+ clk_put(dss.dss_tv_fck);
+ if (dss.dss_video_fck)
+ clk_put(dss.dss_video_fck);
+
+ return r;
+}
+
+static void dss_put_clocks(void)
+{
+ if (dss.dss_video_fck)
+ clk_put(dss.dss_video_fck);
+ clk_put(dss.dss_tv_fck);
+ clk_put(dss.dss_fck);
+ clk_put(dss.dss_sys_clk);
+ clk_put(dss.dss_ick);
+}
+
+unsigned long dss_clk_get_rate(enum dss_clock clk)
+{
+ switch (clk) {
+ case DSS_CLK_ICK:
+ return clk_get_rate(dss.dss_ick);
+ case DSS_CLK_FCK:
+ return clk_get_rate(dss.dss_fck);
+ case DSS_CLK_SYSCK:
+ return clk_get_rate(dss.dss_sys_clk);
+ case DSS_CLK_TVFCK:
+ return clk_get_rate(dss.dss_tv_fck);
+ case DSS_CLK_VIDFCK:
+ return clk_get_rate(dss.dss_video_fck);
+ }
+
+ BUG();
+ return 0;
+}
+
+static unsigned count_clk_bits(enum dss_clock clks)
+{
+ unsigned num_clks = 0;
+
+ if (clks & DSS_CLK_ICK)
+ ++num_clks;
+ if (clks & DSS_CLK_FCK)
+ ++num_clks;
+ if (clks & DSS_CLK_SYSCK)
+ ++num_clks;
+ if (clks & DSS_CLK_TVFCK)
+ ++num_clks;
+ if (clks & DSS_CLK_VIDFCK)
+ ++num_clks;
+
+ return num_clks;
+}
+
+static void dss_clk_enable_no_ctx(enum dss_clock clks)
+{
+ unsigned num_clks = count_clk_bits(clks);
+
+ if (clks & DSS_CLK_ICK)
+ clk_enable(dss.dss_ick);
+ if (clks & DSS_CLK_FCK)
+ clk_enable(dss.dss_fck);
+ if (clks & DSS_CLK_SYSCK)
+ clk_enable(dss.dss_sys_clk);
+ if (clks & DSS_CLK_TVFCK)
+ clk_enable(dss.dss_tv_fck);
+ if (clks & DSS_CLK_VIDFCK)
+ clk_enable(dss.dss_video_fck);
+
+ dss.num_clks_enabled += num_clks;
+}
+
+void dss_clk_enable(enum dss_clock clks)
+{
+ bool check_ctx = dss.num_clks_enabled == 0;
+
+ dss_clk_enable_no_ctx(clks);
+
+ if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
+ restore_all_ctx();
+}
+
+static void dss_clk_disable_no_ctx(enum dss_clock clks)
+{
+ unsigned num_clks = count_clk_bits(clks);
+
+ if (clks & DSS_CLK_ICK)
+ clk_disable(dss.dss_ick);
+ if (clks & DSS_CLK_FCK)
+ clk_disable(dss.dss_fck);
+ if (clks & DSS_CLK_SYSCK)
+ clk_disable(dss.dss_sys_clk);
+ if (clks & DSS_CLK_TVFCK)
+ clk_disable(dss.dss_tv_fck);
+ if (clks & DSS_CLK_VIDFCK)
+ clk_disable(dss.dss_video_fck);
+
+ dss.num_clks_enabled -= num_clks;
+}
+
+void dss_clk_disable(enum dss_clock clks)
+{
+ if (cpu_is_omap34xx()) {
+ unsigned num_clks = count_clk_bits(clks);
+
+ BUG_ON(dss.num_clks_enabled < num_clks);
+
+ if (dss.num_clks_enabled == num_clks)
+ save_all_ctx();
+ }
+
+ dss_clk_disable_no_ctx(clks);
+}
+
+static void dss_clk_enable_all_no_ctx(void)
+{
+ enum dss_clock clks;
+
+ clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
+ if (cpu_is_omap34xx())
+ clks |= DSS_CLK_VIDFCK;
+ dss_clk_enable_no_ctx(clks);
+}
+
+static void dss_clk_disable_all_no_ctx(void)
+{
+ enum dss_clock clks;
+
+ clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
+ if (cpu_is_omap34xx())
+ clks |= DSS_CLK_VIDFCK;
+ dss_clk_disable_no_ctx(clks);
+}
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+/* CLOCKS */
+static void core_dump_clocks(struct seq_file *s)
+{
+ int i;
+ struct clk *clocks[5] = {
+ dss.dss_ick,
+ dss.dss_fck,
+ dss.dss_sys_clk,
+ dss.dss_tv_fck,
+ dss.dss_video_fck
+ };
+
+ seq_printf(s, "- CORE -\n");
+
+ seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
+
+ for (i = 0; i < 5; i++) {
+ if (!clocks[i])
+ continue;
+ seq_printf(s, "%-15s\t%lu\t%d\n",
+ clocks[i]->name,
+ clk_get_rate(clocks[i]),
+ clocks[i]->usecount);
+ }
+}
+#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
+
+/* DEBUGFS */
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+void dss_debug_dump_clocks(struct seq_file *s)
+{
+ core_dump_clocks(s);
+ dss_dump_clocks(s);
+ dispc_dump_clocks(s);
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_dump_clocks(s);
+#endif
+}
+#endif
+
+
+/* DSS HW IP initialisation */
+static int omap_dsshw_probe(struct platform_device *pdev)
+{
+ int r;
+ int skip_init = 0;
+
+ dss.pdev = pdev;
+
+ r = dss_get_clocks();
+ if (r)
+ goto err_clocks;
+
+ dss_clk_enable_all_no_ctx();
+
+ dss.ctx_id = dss_get_ctx_id();
+ DSSDBG("initial ctx id %u\n", dss.ctx_id);
+
+#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
+ /* DISPC_CONTROL */
+ if (omap_readl(0x48050440) & 1) /* LCD enabled? */
+ skip_init = 1;
+#endif
+
+ r = dss_init(skip_init);
+ if (r) {
+ DSSERR("Failed to initialize DSS\n");
+ goto err_dss;
+ }
+
+ dss_clk_disable_all_no_ctx();
+ return 0;
+
+err_dss:
+ dss_clk_disable_all_no_ctx();
+ dss_put_clocks();
+err_clocks:
+ return r;
+}
+
+static int omap_dsshw_remove(struct platform_device *pdev)
+{
+
+ dss_exit();
+
+ /*
+ * As part of hwmod changes, DSS is not the only controller of dss
+ * clocks; hwmod framework itself will also enable clocks during hwmod
+ * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
+ * need to disable clocks if their usecounts > 1.
+ */
+ WARN_ON(dss.num_clks_enabled > 0);
+
+ dss_put_clocks();
+ return 0;
+}
+
+static struct platform_driver omap_dsshw_driver = {
+ .probe = omap_dsshw_probe,
+ .remove = omap_dsshw_remove,
+ .driver = {
+ .name = "omap_dss",
+ .owner = THIS_MODULE,
+ },
+};
+
+int dss_init_platform_driver(void)
+{
+ return platform_driver_register(&omap_dsshw_driver);
+}
+
+void dss_uninit_platform_driver(void)
+{
+ return platform_driver_unregister(&omap_dsshw_driver);
+}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index b394951120ac..4b02e079f20e 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -112,11 +112,11 @@ enum omap_parallel_interface_mode {
};
enum dss_clock {
- DSS_CLK_ICK = 1 << 0,
- DSS_CLK_FCK1 = 1 << 1,
- DSS_CLK_FCK2 = 1 << 2,
- DSS_CLK_54M = 1 << 3,
- DSS_CLK_96M = 1 << 4,
+ DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */
+ DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */
+ DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */
+ DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */
+ DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/
};
enum dss_clk_source {
@@ -169,15 +169,9 @@ struct seq_file;
struct platform_device;
/* core */
-void dss_clk_enable(enum dss_clock clks);
-void dss_clk_disable(enum dss_clock clks);
-unsigned long dss_clk_get_rate(enum dss_clock clk);
-int dss_need_ctx_restore(void);
-void dss_dump_clocks(struct seq_file *s);
struct bus_type *dss_get_bus(void);
struct regulator *dss_get_vdds_dsi(void);
struct regulator *dss_get_vdds_sdi(void);
-struct regulator *dss_get_vdda_dac(void);
/* display */
int dss_suspend_all_devices(void);
@@ -214,13 +208,21 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
/* DSS */
-int dss_init(bool skip_init);
-void dss_exit(void);
+int dss_init_platform_driver(void);
+void dss_uninit_platform_driver(void);
void dss_save_context(void);
void dss_restore_context(void);
+void dss_clk_enable(enum dss_clock clks);
+void dss_clk_disable(enum dss_clock clks);
+unsigned long dss_clk_get_rate(enum dss_clock clk);
+int dss_need_ctx_restore(void);
+void dss_dump_clocks(struct seq_file *s);
void dss_dump_regs(struct seq_file *s);
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+void dss_debug_dump_clocks(struct seq_file *s);
+#endif
void dss_sdi_init(u8 datapairs);
int dss_sdi_enable(void);
@@ -259,8 +261,8 @@ static inline void sdi_exit(void)
/* DSI */
#ifdef CONFIG_OMAP2_DSS_DSI
-int dsi_init(struct platform_device *pdev);
-void dsi_exit(void);
+int dsi_init_platform_driver(void);
+void dsi_uninit_platform_driver(void);
void dsi_dump_clocks(struct seq_file *s);
void dsi_dump_irqs(struct seq_file *s);
@@ -285,11 +287,11 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
void dsi_wait_dsi1_pll_active(void);
void dsi_wait_dsi2_pll_active(void);
#else
-static inline int dsi_init(struct platform_device *pdev)
+static inline int dsi_init_platform_driver(void)
{
return 0;
}
-static inline void dsi_exit(void)
+static inline void dsi_uninit_platform_driver(void)
{
}
static inline void dsi_wait_dsi1_pll_active(void)
@@ -316,8 +318,8 @@ static inline void dpi_exit(void)
#endif
/* DISPC */
-int dispc_init(void);
-void dispc_exit(void);
+int dispc_init_platform_driver(void);
+void dispc_uninit_platform_driver(void);
void dispc_dump_clocks(struct seq_file *s);
void dispc_dump_irqs(struct seq_file *s);
void dispc_dump_regs(struct seq_file *s);
@@ -409,24 +411,24 @@ int dispc_get_clock_div(enum omap_channel channel,
/* VENC */
#ifdef CONFIG_OMAP2_DSS_VENC
-int venc_init(struct platform_device *pdev);
-void venc_exit(void);
+int venc_init_platform_driver(void);
+void venc_uninit_platform_driver(void);
void venc_dump_regs(struct seq_file *s);
int venc_init_display(struct omap_dss_device *display);
#else
-static inline int venc_init(struct platform_device *pdev)
+static inline int venc_init_platform_driver(void)
{
return 0;
}
-static inline void venc_exit(void)
+static inline void venc_uninit_platform_driver(void)
{
}
#endif
/* RFBI */
#ifdef CONFIG_OMAP2_DSS_RFBI
-int rfbi_init(void);
-void rfbi_exit(void);
+int rfbi_init_platform_driver(void);
+void rfbi_uninit_platform_driver(void);
void rfbi_dump_regs(struct seq_file *s);
int rfbi_configure(int rfbi_module, int bpp, int lines);
@@ -437,11 +439,11 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
unsigned long rfbi_get_max_tx_rate(void);
int rfbi_init_display(struct omap_dss_device *display);
#else
-static inline int rfbi_init(void)
+static inline int rfbi_init_platform_driver(void)
{
return 0;
}
-static inline void rfbi_exit(void)
+static inline void rfbi_uninit_platform_driver(void)
{
}
#endif
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 172d4e697309..1f53bf20b6cb 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -1394,7 +1394,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
}
r = 0;
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
if (!dss_cache.irq_enabled) {
u32 mask;
@@ -1407,7 +1407,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
dss_cache.irq_enabled = true;
}
configure_dispc();
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
spin_unlock_irqrestore(&dss_cache.lock, flags);
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 456efef03c20..996e9a4f6771 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -490,7 +490,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
ovl->manager = mgr;
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
/* XXX: on manual update display, in auto update mode, a bug happens
* here. When an overlay is first enabled on LCD, then it's disabled,
* and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
@@ -499,7 +499,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
* but I don't understand how or why. */
msleep(40);
dispc_set_channel_out(ovl->id, mgr->id);
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return 0;
}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 10a2ffe02882..9e0f196a9839 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -36,8 +36,6 @@
#include <plat/display.h>
#include "dss.h"
-#define RFBI_BASE 0x48050800
-
struct rfbi_reg { u16 idx; };
#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
@@ -100,6 +98,7 @@ static int rfbi_convert_timings(struct rfbi_timings *t);
static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
static struct {
+ struct platform_device *pdev;
void __iomem *base;
unsigned long l4_khz;
@@ -142,9 +141,9 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
static void rfbi_enable_clocks(bool enable)
{
if (enable)
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
else
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
void omap_rfbi_write_command(const void *buf, u32 len)
@@ -497,7 +496,7 @@ unsigned long rfbi_get_max_tx_rate(void)
};
l4_rate = rfbi.l4_khz / 1000;
- dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
+ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000;
for (i = 0; i < ARRAY_SIZE(ftab); i++) {
/* Use a window instead of an exact match, to account
@@ -922,7 +921,7 @@ void rfbi_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(RFBI_REVISION);
DUMPREG(RFBI_SYSCONFIG);
@@ -953,54 +952,10 @@ void rfbi_dump_regs(struct seq_file *s)
DUMPREG(RFBI_VSYNC_WIDTH);
DUMPREG(RFBI_HSYNC_WIDTH);
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
-int rfbi_init(void)
-{
- u32 rev;
- u32 l;
-
- spin_lock_init(&rfbi.cmd_lock);
-
- init_completion(&rfbi.cmd_done);
- atomic_set(&rfbi.cmd_fifo_full, 0);
- atomic_set(&rfbi.cmd_pending, 0);
-
- rfbi.base = ioremap(RFBI_BASE, SZ_256);
- if (!rfbi.base) {
- DSSERR("can't ioremap RFBI\n");
- return -ENOMEM;
- }
-
- rfbi_enable_clocks(1);
-
- msleep(10);
-
- rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
-
- /* Enable autoidle and smart-idle */
- l = rfbi_read_reg(RFBI_SYSCONFIG);
- l |= (1 << 0) | (2 << 3);
- rfbi_write_reg(RFBI_SYSCONFIG, l);
-
- rev = rfbi_read_reg(RFBI_REVISION);
- printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
- FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
- rfbi_enable_clocks(0);
-
- return 0;
-}
-
-void rfbi_exit(void)
-{
- DSSDBG("rfbi_exit\n");
-
- iounmap(rfbi.base);
-}
-
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
int r;
@@ -1056,3 +1011,74 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
return 0;
}
+
+/* RFBI HW IP initialisation */
+static int omap_rfbihw_probe(struct platform_device *pdev)
+{
+ u32 rev;
+ u32 l;
+ struct resource *rfbi_mem;
+
+ rfbi.pdev = pdev;
+
+ spin_lock_init(&rfbi.cmd_lock);
+
+ init_completion(&rfbi.cmd_done);
+ atomic_set(&rfbi.cmd_fifo_full, 0);
+ atomic_set(&rfbi.cmd_pending, 0);
+
+ rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
+ if (!rfbi_mem) {
+ DSSERR("can't get IORESOURCE_MEM RFBI\n");
+ return -EINVAL;
+ }
+ rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
+ if (!rfbi.base) {
+ DSSERR("can't ioremap RFBI\n");
+ return -ENOMEM;
+ }
+
+ rfbi_enable_clocks(1);
+
+ msleep(10);
+
+ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+
+ /* Enable autoidle and smart-idle */
+ l = rfbi_read_reg(RFBI_SYSCONFIG);
+ l |= (1 << 0) | (2 << 3);
+ rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+ rev = rfbi_read_reg(RFBI_REVISION);
+ dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ rfbi_enable_clocks(0);
+
+ return 0;
+}
+
+static int omap_rfbihw_remove(struct platform_device *pdev)
+{
+ iounmap(rfbi.base);
+ return 0;
+}
+
+static struct platform_driver omap_rfbihw_driver = {
+ .probe = omap_rfbihw_probe,
+ .remove = omap_rfbihw_remove,
+ .driver = {
+ .name = "omap_rfbi",
+ .owner = THIS_MODULE,
+ },
+};
+
+int rfbi_init_platform_driver(void)
+{
+ return platform_driver_register(&omap_rfbihw_driver);
+}
+
+void rfbi_uninit_platform_driver(void)
+{
+ return platform_driver_unregister(&omap_rfbihw_driver);
+}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index b64adf7dfc88..9f10a0d9e760 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -70,7 +70,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
/* In case of skip_init sdi_init has already enabled the clocks */
if (!sdi.skip_init)
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
sdi_basic_init(dssdev);
@@ -130,7 +130,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
return 0;
err2:
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
regulator_disable(sdi.vdds_sdi_reg);
err1:
omap_dss_stop_device(dssdev);
@@ -145,7 +145,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
dss_sdi_disable();
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
regulator_disable(sdi.vdds_sdi_reg);
@@ -157,6 +157,19 @@ int sdi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("SDI init\n");
+ if (sdi.vdds_sdi_reg == NULL) {
+ struct regulator *vdds_sdi;
+
+ vdds_sdi = dss_get_vdds_sdi();
+
+ if (IS_ERR(vdds_sdi)) {
+ DSSERR("can't get VDDS_SDI regulator\n");
+ return PTR_ERR(vdds_sdi);
+ }
+
+ sdi.vdds_sdi_reg = vdds_sdi;
+ }
+
return 0;
}
@@ -165,17 +178,12 @@ int sdi_init(bool skip_init)
/* we store this for first display enable, then clear it */
sdi.skip_init = skip_init;
- sdi.vdds_sdi_reg = dss_get_vdds_sdi();
- if (IS_ERR(sdi.vdds_sdi_reg)) {
- DSSERR("can't get VDDS_SDI regulator\n");
- return PTR_ERR(sdi.vdds_sdi_reg);
- }
/*
* Enable clocks already here, otherwise there would be a toggle
* of them until sdi_display_enable is called.
*/
if (skip_init)
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
return 0;
}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index eff35050e28a..9cfcc364882f 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -39,8 +39,6 @@
#include "dss.h"
-#define VENC_BASE 0x48050C00
-
/* Venc registers */
#define VENC_REV_ID 0x00
#define VENC_STATUS 0x04
@@ -289,6 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = {
EXPORT_SYMBOL(omap_dss_ntsc_timings);
static struct {
+ struct platform_device *pdev;
void __iomem *base;
struct mutex venc_lock;
u32 wss_data;
@@ -381,11 +380,11 @@ static void venc_reset(void)
static void venc_enable_clocks(int enable)
{
if (enable)
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
- DSS_CLK_96M);
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+ DSS_CLK_VIDFCK);
else
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
- DSS_CLK_96M);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+ DSS_CLK_VIDFCK);
}
static const struct venc_config *venc_timings_to_config(
@@ -641,50 +640,23 @@ static struct omap_dss_driver venc_driver = {
};
/* driver end */
-
-
-int venc_init(struct platform_device *pdev)
+int venc_init_display(struct omap_dss_device *dssdev)
{
- u8 rev_id;
+ DSSDBG("init_display\n");
- mutex_init(&venc.venc_lock);
+ if (venc.vdda_dac_reg == NULL) {
+ struct regulator *vdda_dac;
- venc.wss_data = 0;
+ vdda_dac = regulator_get(&venc.pdev->dev, "vdda_dac");
- venc.base = ioremap(VENC_BASE, SZ_1K);
- if (!venc.base) {
- DSSERR("can't ioremap VENC\n");
- return -ENOMEM;
- }
+ if (IS_ERR(vdda_dac)) {
+ DSSERR("can't get VDDA_DAC regulator\n");
+ return PTR_ERR(vdda_dac);
+ }
- venc.vdda_dac_reg = dss_get_vdda_dac();
- if (IS_ERR(venc.vdda_dac_reg)) {
- iounmap(venc.base);
- DSSERR("can't get VDDA_DAC regulator\n");
- return PTR_ERR(venc.vdda_dac_reg);
+ venc.vdda_dac_reg = vdda_dac;
}
- venc_enable_clocks(1);
-
- rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
- printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
-
- venc_enable_clocks(0);
-
- return omap_dss_register_driver(&venc_driver);
-}
-
-void venc_exit(void)
-{
- omap_dss_unregister_driver(&venc_driver);
-
- iounmap(venc.base);
-}
-
-int venc_init_display(struct omap_dss_device *dssdev)
-{
- DSSDBG("init_display\n");
-
return 0;
}
@@ -740,3 +712,67 @@ void venc_dump_regs(struct seq_file *s)
#undef DUMPREG
}
+
+/* VENC HW IP initialisation */
+static int omap_venchw_probe(struct platform_device *pdev)
+{
+ u8 rev_id;
+ struct resource *venc_mem;
+
+ venc.pdev = pdev;
+
+ mutex_init(&venc.venc_lock);
+
+ venc.wss_data = 0;
+
+ venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
+ if (!venc_mem) {
+ DSSERR("can't get IORESOURCE_MEM VENC\n");
+ return -EINVAL;
+ }
+ venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
+ if (!venc.base) {
+ DSSERR("can't ioremap VENC\n");
+ return -ENOMEM;
+ }
+
+ venc_enable_clocks(1);
+
+ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
+ dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
+
+ venc_enable_clocks(0);
+
+ return omap_dss_register_driver(&venc_driver);
+}
+
+static int omap_venchw_remove(struct platform_device *pdev)
+{
+ if (venc.vdda_dac_reg != NULL) {
+ regulator_put(venc.vdda_dac_reg);
+ venc.vdda_dac_reg = NULL;
+ }
+ omap_dss_unregister_driver(&venc_driver);
+
+ iounmap(venc.base);
+ return 0;
+}
+
+static struct platform_driver omap_venchw_driver = {
+ .probe = omap_venchw_probe,
+ .remove = omap_venchw_remove,
+ .driver = {
+ .name = "omap_venc",
+ .owner = THIS_MODULE,
+ },
+};
+
+int venc_init_platform_driver(void)
+{
+ return platform_driver_register(&omap_venchw_driver);
+}
+
+void venc_uninit_platform_driver(void)
+{
+ return platform_driver_unregister(&omap_venchw_driver);
+}
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 65149b22cf37..aa33386c81ff 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -1,5 +1,5 @@
menuconfig FB_OMAP2
- tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
+ tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
depends on FB && OMAP2_DSS
select OMAP2_VRAM
@@ -8,10 +8,10 @@ menuconfig FB_OMAP2
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
- Frame buffer driver for OMAP2/3 based boards.
+ Frame buffer driver for OMAP2+ based boards.
config FB_OMAP2_DEBUG_SUPPORT
- bool "Debug support for OMAP2/3 FB"
+ bool "Debug support for OMAP2+ FB"
default y
depends on FB_OMAP2
help
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 4fdab8e9c496..505ec6672049 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2090,7 +2090,7 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
{
int r;
u8 bpp;
- struct omap_video_timings timings;
+ struct omap_video_timings timings, temp_timings;
r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
if (r)
@@ -2100,14 +2100,23 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
++fbdev->num_bpp_overrides;
- if (!display->driver->check_timings || !display->driver->set_timings)
- return -EINVAL;
+ if (display->driver->check_timings) {
+ r = display->driver->check_timings(display, &timings);
+ if (r)
+ return r;
+ } else {
+ /* If check_timings is not present compare xres and yres */
+ if (display->driver->get_timings) {
+ display->driver->get_timings(display, &temp_timings);
- r = display->driver->check_timings(display, &timings);
- if (r)
- return r;
+ if (temp_timings.x_res != timings.x_res ||
+ temp_timings.y_res != timings.y_res)
+ return -EINVAL;
+ }
+ }
- display->driver->set_timings(display, &timings);
+ if (display->driver->set_timings)
+ display->driver->set_timings(display, &timings);
return 0;
}