summaryrefslogtreecommitdiff
path: root/drivers/video/omap2/dss
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2011-07-21 21:48:13 -0400
committerNicolas Pitre <nicolas.pitre@linaro.org>2011-07-21 21:48:13 -0400
commitf25718e8cff17b5c64ad11c2a6e9d2ee1b676eef (patch)
treee0368d1f4a4b21cfbc1a04f216580ae6b913d1ea /drivers/video/omap2/dss
parentc7e0c8535d73f8c5bf760926a2bd71c9840cf2ef (diff)
Revert "Merge remote-tracking branch 'arm-soc/for-next' into linaro-3.0"
This reverts commit c7e0c8535d73f8c5bf760926a2bd71c9840cf2ef, reversing changes made to dfee09c8acf18e84fe197bb5d821d1e4e02d020f. John Stultz reports that Panda doesn't boot anymore and 'git bisect' indicated the merge commit itself as the culprit. The resulting kernel log is: [ 1.734802] OMAP DSS rev 4.0 [ 1.740417] omap_hwmod: dss_core: _wait_target_disable failed [ 1.746429] omap_device: omapdss_dss.-1: new worst case deactivate latency 01 [ 1.755035] omapdss DISPC error: can't get dss_clk [ 1.760101] omapdss_dispc: probe of omapdss_dispc failed with error -2 [ 1.767333] omapdss HDMI error: can't get hdmi_clk [ 1.772399] omapdss_hdmi: probe of omapdss_hdmi failed with error -2 [ 1.780273] ------------[ cut here ]------------ [ 1.785125] WARNING: at drivers/video/omap2/dss/dispc.c:553dispc_runtime_ge) [ 1.793640] Modules linked in: [ 1.796905] ---[ end trace 6fcb132ac310d004 ]--- [ 1.801757] Unable to handle kernel NULL pointer dereference at virtualaddr0 [...] Revert it so a later version of the arm-soc merge result can be used instead.
Diffstat (limited to 'drivers/video/omap2/dss')
-rw-r--r--drivers/video/omap2/dss/Kconfig12
-rw-r--r--drivers/video/omap2/dss/core.c15
-rw-r--r--drivers/video/omap2/dss/dispc.c484
-rw-r--r--drivers/video/omap2/dss/display.c45
-rw-r--r--drivers/video/omap2/dss/dpi.c73
-rw-r--r--drivers/video/omap2/dss/dsi.c277
-rw-r--r--drivers/video/omap2/dss/dss.c584
-rw-r--r--drivers/video/omap2/dss/dss.h34
-rw-r--r--drivers/video/omap2/dss/dss_features.c13
-rw-r--r--drivers/video/omap2/dss/dss_features.h4
-rw-r--r--drivers/video/omap2/dss/hdmi.c162
-rw-r--r--drivers/video/omap2/dss/manager.c67
-rw-r--r--drivers/video/omap2/dss/overlay.c27
-rw-r--r--drivers/video/omap2/dss/rfbi.c111
-rw-r--r--drivers/video/omap2/dss/sdi.c40
-rw-r--r--drivers/video/omap2/dss/venc.c180
16 files changed, 1075 insertions, 1053 deletions
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 0d12524db14..6b3e2da1141 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -117,6 +117,18 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
Max FCK is 173MHz, so this doesn't work if your PCK
is very high.
+config OMAP2_DSS_SLEEP_BEFORE_RESET
+ bool "Sleep 50ms before DSS reset"
+ default y
+ help
+ For some unknown reason we may get SYNC_LOST errors from the display
+ subsystem at initialization time if we don't sleep before resetting
+ the DSS. See the source (dss.c) for more comments.
+
+ However, 50ms is quite long time to sleep, and with some
+ configurations the SYNC_LOST may never happen, so the sleep can
+ be disabled here.
+
config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
bool "Sleep 20ms after VENC reset"
default y
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index f0bae6d5340..3da426719dd 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -183,11 +183,8 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_dss;
}
- r = dispc_init_platform_driver();
- if (r) {
- DSSERR("Failed to initialize dispc platform driver\n");
- goto err_dispc;
- }
+ /* 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) {
@@ -195,6 +192,12 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_rfbi;
}
+ r = dispc_init_platform_driver();
+ if (r) {
+ DSSERR("Failed to initialize dispc platform driver\n");
+ goto err_dispc;
+ }
+
r = venc_init_platform_driver();
if (r) {
DSSERR("Failed to initialize venc platform driver\n");
@@ -235,6 +238,8 @@ static int omap_dss_probe(struct platform_device *pdev)
pdata->default_device = dssdev;
}
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+
return 0;
err_register:
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index eac768ff2d3..7a9a2e7d968 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -33,8 +33,6 @@
#include <linux/workqueue.h>
#include <linux/hardirq.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
#include <plat/sram.h>
#include <plat/clock.h>
@@ -94,11 +92,7 @@ struct dispc_irq_stats {
static struct {
struct platform_device *pdev;
void __iomem *base;
-
- int ctx_loss_cnt;
-
int irq;
- struct clk *dss_clk;
u32 fifo_size[3];
@@ -108,7 +102,6 @@ static struct {
u32 error_irqs;
struct work_struct error_work;
- bool ctx_valid;
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -141,34 +134,18 @@ static inline u32 dispc_read_reg(const u16 idx)
return __raw_readl(dispc.base + idx);
}
-static int dispc_get_ctx_loss_count(void)
-{
- struct device *dev = &dispc.pdev->dev;
- struct omap_display_platform_data *pdata = dev->platform_data;
- struct omap_dss_board_info *board_data = pdata->board_data;
- int cnt;
-
- if (!board_data->get_context_loss_count)
- return -ENOENT;
-
- cnt = board_data->get_context_loss_count(dev);
-
- WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
-
- return cnt;
-}
-
#define SR(reg) \
dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
#define RR(reg) \
dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
-static void dispc_save_context(void)
+void dispc_save_context(void)
{
int i;
+ if (cpu_is_omap24xx())
+ return;
- DSSDBG("dispc_save_context\n");
-
+ SR(SYSCONFIG);
SR(IRQENABLE);
SR(CONTROL);
SR(CONFIG);
@@ -181,8 +158,7 @@ static void dispc_save_context(void)
SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
- SR(GLOBAL_ALPHA);
+ SR(GLOBAL_ALPHA);
SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -212,25 +188,20 @@ static void dispc_save_context(void)
SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
+ SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+ SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+ SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
- if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
- }
+ SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+ SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+ SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
}
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_GFX));
+ SR(OVL_PRELOAD(OMAP_DSS_GFX));
/* VID1 */
SR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -255,10 +226,8 @@ static void dispc_save_context(void)
for (i = 0; i < 5; i++)
SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
- }
+ for (i = 0; i < 8; i++)
+ SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -279,8 +248,7 @@ static void dispc_save_context(void)
if (dss_has_feature(FEAT_ATTR2))
SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+ SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
/* VID2 */
SR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -305,10 +273,8 @@ static void dispc_save_context(void)
for (i = 0; i < 5; i++)
SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
- }
+ for (i = 0; i < 8; i++)
+ SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -329,35 +295,16 @@ static void dispc_save_context(void)
if (dss_has_feature(FEAT_ATTR2))
SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+ SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
if (dss_has_feature(FEAT_CORE_CLK_DIV))
SR(DIVISOR);
-
- dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
- dispc.ctx_valid = true;
-
- DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
}
-static void dispc_restore_context(void)
+void dispc_restore_context(void)
{
- int i, ctx;
-
- DSSDBG("dispc_restore_context\n");
-
- if (!dispc.ctx_valid)
- return;
-
- ctx = dispc_get_ctx_loss_count();
-
- if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
- return;
-
- DSSDBG("ctx_loss_count: saved %d, current %d\n",
- dispc.ctx_loss_cnt, ctx);
-
+ int i;
+ RR(SYSCONFIG);
/*RR(IRQENABLE);*/
/*RR(CONTROL);*/
RR(CONFIG);
@@ -370,8 +317,7 @@ static void dispc_restore_context(void)
RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
- RR(GLOBAL_ALPHA);
+ RR(GLOBAL_ALPHA);
RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -401,25 +347,20 @@ static void dispc_restore_context(void)
RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
+ RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+ RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+ RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
- if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
- }
+ RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+ RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+ RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
}
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_GFX));
+ RR(OVL_PRELOAD(OMAP_DSS_GFX));
/* VID1 */
RR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -444,10 +385,8 @@ static void dispc_restore_context(void)
for (i = 0; i < 5; i++)
RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
- }
+ for (i = 0; i < 8; i++)
+ RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -468,8 +407,7 @@ static void dispc_restore_context(void)
if (dss_has_feature(FEAT_ATTR2))
RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+ RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
/* VID2 */
RR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -494,10 +432,8 @@ static void dispc_restore_context(void)
for (i = 0; i < 5; i++)
RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
- }
+ for (i = 0; i < 8; i++)
+ RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -518,8 +454,7 @@ static void dispc_restore_context(void)
if (dss_has_feature(FEAT_ATTR2))
RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+ RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
if (dss_has_feature(FEAT_CORE_CLK_DIV))
RR(DIVISOR);
@@ -536,35 +471,19 @@ static void dispc_restore_context(void)
* the context is fully restored
*/
RR(IRQENABLE);
-
- DSSDBG("context restored\n");
}
#undef SR
#undef RR
-int dispc_runtime_get(void)
-{
- int r;
-
- DSSDBG("dispc_runtime_get\n");
-
- r = pm_runtime_get_sync(&dispc.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-void dispc_runtime_put(void)
+static inline void enable_clocks(bool enable)
{
- int r;
-
- DSSDBG("dispc_runtime_put\n");
-
- r = pm_runtime_put(&dispc.pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
-
bool dispc_go_busy(enum omap_channel channel)
{
int bit;
@@ -586,6 +505,8 @@ void dispc_go(enum omap_channel channel)
int bit;
bool enable_bit, go_bit;
+ enable_clocks(1);
+
if (channel == OMAP_DSS_CHANNEL_LCD ||
channel == OMAP_DSS_CHANNEL_LCD2)
bit = 0; /* LCDENABLE */
@@ -599,7 +520,7 @@ void dispc_go(enum omap_channel channel)
enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
if (!enable_bit)
- return;
+ goto end;
if (channel == OMAP_DSS_CHANNEL_LCD ||
channel == OMAP_DSS_CHANNEL_LCD2)
@@ -614,7 +535,7 @@ void dispc_go(enum omap_channel channel)
if (go_bit) {
DSSERR("GO bit not down for channel %d\n", channel);
- return;
+ goto end;
}
DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
@@ -624,6 +545,8 @@ void dispc_go(enum omap_channel channel)
REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
else
REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
+end:
+ enable_clocks(0);
}
static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -997,7 +920,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
}
-void dispc_set_channel_out(enum omap_plane plane,
+static void _dispc_set_channel_out(enum omap_plane plane,
enum omap_channel channel)
{
int shift;
@@ -1050,6 +973,8 @@ void dispc_set_burst_size(enum omap_plane plane,
int shift;
u32 val;
+ enable_clocks(1);
+
switch (plane) {
case OMAP_DSS_GFX:
shift = 6;
@@ -1066,6 +991,8 @@ void dispc_set_burst_size(enum omap_plane plane,
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);
+
+ enable_clocks(0);
}
void dispc_enable_gamma_table(bool enable)
@@ -1102,7 +1029,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
else
bit = 10;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
+ enable_clocks(0);
}
void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1110,7 +1039,9 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
u32 val;
BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ enable_clocks(1);
dispc_write_reg(DISPC_SIZE_MGR(channel), val);
+ enable_clocks(0);
}
void dispc_set_digit_size(u16 width, u16 height)
@@ -1118,7 +1049,9 @@ void dispc_set_digit_size(u16 width, u16 height)
u32 val;
BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ enable_clocks(1);
dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
+ enable_clocks(0);
}
static void dispc_read_plane_fifo_sizes(void)
@@ -1127,6 +1060,8 @@ static void dispc_read_plane_fifo_sizes(void)
int plane;
u8 start, end;
+ enable_clocks(1);
+
dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
@@ -1134,6 +1069,8 @@ static void dispc_read_plane_fifo_sizes(void)
start, end);
dispc.fifo_size[plane] = size;
}
+
+ enable_clocks(0);
}
u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1148,6 +1085,8 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
+ enable_clocks(1);
+
DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
plane,
REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
@@ -1159,12 +1098,18 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
FLD_VAL(high, hi_start, hi_end) |
FLD_VAL(low, lo_start, lo_end));
+
+ enable_clocks(0);
}
void dispc_enable_fifomerge(bool enable)
{
+ enable_clocks(1);
+
DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
+
+ enable_clocks(0);
}
static void _dispc_set_fir(enum omap_plane plane,
@@ -1784,7 +1729,14 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
return dispc_pclk_rate(channel) * vf * hf;
}
-int dispc_setup_plane(enum omap_plane plane,
+void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
+{
+ enable_clocks(1);
+ _dispc_set_channel_out(plane, channel_out);
+ enable_clocks(0);
+}
+
+static int _dispc_setup_plane(enum omap_plane plane,
u32 paddr, u16 screen_width,
u16 pos_x, u16 pos_y,
u16 width, u16 height,
@@ -1792,7 +1744,7 @@ int dispc_setup_plane(enum omap_plane plane,
enum omap_color_mode color_mode,
bool ilace,
enum omap_dss_rotation_type rotation_type,
- u8 rotation, bool mirror,
+ u8 rotation, int mirror,
u8 global_alpha, u8 pre_mult_alpha,
enum omap_channel channel, u32 puv_addr)
{
@@ -1806,14 +1758,6 @@ int dispc_setup_plane(enum omap_plane plane,
u16 frame_height = height;
unsigned int field_offset = 0;
- DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
- "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
- plane, paddr, screen_width, pos_x, pos_y,
- width, height,
- out_width, out_height,
- ilace, color_mode,
- rotation, mirror, channel);
-
if (paddr == 0)
return -EINVAL;
@@ -1959,13 +1903,9 @@ int dispc_setup_plane(enum omap_plane plane,
return 0;
}
-int dispc_enable_plane(enum omap_plane plane, bool enable)
+static void _dispc_enable_plane(enum omap_plane plane, bool enable)
{
- DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
-
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
-
- return 0;
}
static void dispc_disable_isr(void *data, u32 mask)
@@ -1989,6 +1929,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
int r;
u32 irq;
+ enable_clocks(1);
+
/* When we disable LCD output, we need to wait until frame is done.
* Otherwise the DSS is still working, and turning off the clocks
* prevents DSS from going to OFF mode */
@@ -2022,6 +1964,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
if (r)
DSSERR("failed to unregister FRAMEDONE isr\n");
}
+
+ enable_clocks(0);
}
static void _enable_digit_out(bool enable)
@@ -2034,8 +1978,12 @@ static void dispc_enable_digit_out(bool enable)
struct completion frame_done_completion;
int r;
- if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
+ enable_clocks(1);
+
+ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
+ enable_clocks(0);
return;
+ }
if (enable) {
unsigned long flags;
@@ -2087,6 +2035,8 @@ static void dispc_enable_digit_out(bool enable)
_omap_dispc_set_irqs();
spin_unlock_irqrestore(&dispc.irq_lock, flags);
}
+
+ enable_clocks(0);
}
bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2117,7 +2067,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
if (!dss_has_feature(FEAT_LCDENABLEPOL))
return;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
+ enable_clocks(0);
}
void dispc_lcd_enable_signal(bool enable)
@@ -2125,7 +2077,9 @@ void dispc_lcd_enable_signal(bool enable)
if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
return;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
+ enable_clocks(0);
}
void dispc_pck_free_enable(bool enable)
@@ -2133,15 +2087,19 @@ void dispc_pck_free_enable(bool enable)
if (!dss_has_feature(FEAT_PCKFREEENABLE))
return;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
+ enable_clocks(0);
}
void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
{
+ enable_clocks(1);
if (channel == OMAP_DSS_CHANNEL_LCD2)
REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
else
REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
+ enable_clocks(0);
}
@@ -2164,21 +2122,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
return;
}
+ enable_clocks(1);
if (channel == OMAP_DSS_CHANNEL_LCD2)
REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
else
REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
+ enable_clocks(0);
}
void dispc_set_loadmode(enum omap_dss_load_mode mode)
{
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
+ enable_clocks(0);
}
void dispc_set_default_color(enum omap_channel channel, u32 color)
{
+ enable_clocks(1);
dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
+ enable_clocks(0);
}
u32 dispc_get_default_color(enum omap_channel channel)
@@ -2189,7 +2153,9 @@ u32 dispc_get_default_color(enum omap_channel channel)
channel != OMAP_DSS_CHANNEL_LCD &&
channel != OMAP_DSS_CHANNEL_LCD2);
+ enable_clocks(1);
l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
+ enable_clocks(0);
return l;
}
@@ -2198,6 +2164,7 @@ void dispc_set_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type type,
u32 trans_key)
{
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2206,12 +2173,14 @@ void dispc_set_trans_key(enum omap_channel ch,
REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
+ enable_clocks(0);
}
void dispc_get_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type *type,
u32 *trans_key)
{
+ enable_clocks(1);
if (type) {
if (ch == OMAP_DSS_CHANNEL_LCD)
*type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2225,28 +2194,33 @@ void dispc_get_trans_key(enum omap_channel ch,
if (trans_key)
*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
+ enable_clocks(0);
}
void dispc_enable_trans_key(enum omap_channel ch, bool enable)
{
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
else /* OMAP_DSS_CHANNEL_LCD2 */
REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
+ enable_clocks(0);
}
void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
{
if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
return;
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
else /* OMAP_DSS_CHANNEL_LCD2 */
REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
+ enable_clocks(0);
}
bool dispc_alpha_blending_enabled(enum omap_channel ch)
{
@@ -2255,6 +2229,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
return false;
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
enabled = REG_GET(DISPC_CONFIG, 18, 18);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2263,6 +2238,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
enabled = REG_GET(DISPC_CONFIG2, 18, 18);
else
BUG();
+ enable_clocks(0);
return enabled;
}
@@ -2272,6 +2248,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
{
bool enabled;
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
enabled = REG_GET(DISPC_CONFIG, 10, 10);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2280,6 +2257,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
enabled = REG_GET(DISPC_CONFIG2, 10, 10);
else
BUG();
+ enable_clocks(0);
return enabled;
}
@@ -2307,10 +2285,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
return;
}
+ enable_clocks(1);
if (channel == OMAP_DSS_CHANNEL_LCD2)
REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
else
REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
+ enable_clocks(0);
}
void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2342,6 +2322,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
return;
}
+ enable_clocks(1);
+
if (channel == OMAP_DSS_CHANNEL_LCD2) {
l = dispc_read_reg(DISPC_CONTROL2);
l = FLD_MOD(l, stallmode, 11, 11);
@@ -2353,6 +2335,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
l = FLD_MOD(l, gpout1, 16, 16);
dispc_write_reg(DISPC_CONTROL, l);
}
+
+ enable_clocks(0);
}
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2405,8 +2389,10 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
FLD_VAL(vbp, 31, 20);
}
+ enable_clocks(1);
dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
+ enable_clocks(0);
}
/* change name to mode? */
@@ -2449,8 +2435,10 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
BUG_ON(lck_div < 1);
BUG_ON(pck_div < 2);
+ enable_clocks(1);
dispc_write_reg(DISPC_DIVISORo(channel),
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+ enable_clocks(0);
}
static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -2469,7 +2457,7 @@ unsigned long dispc_fclk_rate(void)
switch (dss_get_dispc_clk_source()) {
case OMAP_DSS_CLK_SRC_FCK:
- r = clk_get_rate(dispc.dss_clk);
+ r = dss_clk_get_rate(DSS_CLK_FCK);
break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
dsidev = dsi_get_dsidev_from_id(0);
@@ -2499,7 +2487,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
switch (dss_get_lcd_clk_source(channel)) {
case OMAP_DSS_CLK_SRC_FCK:
- r = clk_get_rate(dispc.dss_clk);
+ r = dss_clk_get_rate(DSS_CLK_FCK);
break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
dsidev = dsi_get_dsidev_from_id(0);
@@ -2538,8 +2526,7 @@ void dispc_dump_clocks(struct seq_file *s)
enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
enum omap_dss_clk_source lcd_clk_src;
- if (dispc_runtime_get())
- return;
+ enable_clocks(1);
seq_printf(s, "- DISPC -\n");
@@ -2587,8 +2574,7 @@ void dispc_dump_clocks(struct seq_file *s)
seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
}
-
- dispc_runtime_put();
+ enable_clocks(0);
}
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -2643,8 +2629,7 @@ void dispc_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
- if (dispc_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(DISPC_REVISION);
DUMPREG(DISPC_SYSCONFIG);
@@ -2664,8 +2649,7 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
- DUMPREG(DISPC_GLOBAL_ALPHA);
+ DUMPREG(DISPC_GLOBAL_ALPHA);
DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -2696,25 +2680,20 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_CPR)) {
- DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
+ DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+ DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+ DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
- if (dss_has_feature(FEAT_CPR)) {
- DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- }
+ DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+ DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+ DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
}
- if (dss_has_feature(FEAT_PRELOAD))
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
+ DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
@@ -2765,16 +2744,14 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
- }
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -2835,17 +2812,14 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
- }
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -2884,12 +2858,10 @@ void dispc_dump_regs(struct seq_file *s)
if (dss_has_feature(FEAT_ATTR2))
DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
- if (dss_has_feature(FEAT_PRELOAD)) {
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
- }
+ DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
+ DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
- dispc_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -2910,7 +2882,9 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
l |= FLD_VAL(acbi, 11, 8);
l |= FLD_VAL(acb, 7, 0);
+ enable_clocks(1);
dispc_write_reg(DISPC_POL_FREQ(channel), l);
+ enable_clocks(0);
}
void dispc_set_pol_freq(enum omap_channel channel,
@@ -3031,11 +3005,15 @@ static void _omap_dispc_set_irqs(void)
mask |= isr_data->mask;
}
+ enable_clocks(1);
+
old_mask = dispc_read_reg(DISPC_IRQENABLE);
/* clear the irqstatus for newly enabled irqs */
dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
dispc_write_reg(DISPC_IRQENABLE, mask);
+
+ enable_clocks(0);
}
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3544,6 +3522,13 @@ static void _omap_dispc_initial_config(void)
{
u32 l;
+ l = dispc_read_reg(DISPC_SYSCONFIG);
+ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
+ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
+ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
+ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
+ dispc_write_reg(DISPC_SYSCONFIG, l);
+
/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
l = dispc_read_reg(DISPC_DIVISOR);
@@ -3569,25 +3554,67 @@ static void _omap_dispc_initial_config(void)
dispc_read_plane_fifo_sizes();
}
+int dispc_enable_plane(enum omap_plane plane, bool enable)
+{
+ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
+ enable_clocks(1);
+ _dispc_enable_plane(plane, enable);
+ enable_clocks(0);
+
+ return 0;
+}
+
+int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror, u8 global_alpha,
+ u8 pre_mult_alpha, enum omap_channel channel,
+ u32 puv_addr)
+{
+ int r = 0;
+
+ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
+ "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
+ plane, paddr, screen_width, pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ ilace, color_mode,
+ rotation, mirror, channel);
+
+ enable_clocks(1);
+
+ r = _dispc_setup_plane(plane,
+ paddr, screen_width,
+ pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ color_mode, ilace,
+ rotation_type,
+ rotation, mirror,
+ global_alpha,
+ pre_mult_alpha,
+ channel, puv_addr);
+
+ enable_clocks(0);
+
+ return r;
+}
+
/* DISPC HW IP initialisation */
static int omap_dispchw_probe(struct platform_device *pdev)
{
u32 rev;
int r = 0;
struct resource *dispc_mem;
- struct clk *clk;
dispc.pdev = pdev;
- clk = clk_get(&pdev->dev, "dss_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get dss_clk\n");
- r = PTR_ERR(clk);
- goto err_get_clk;
- }
-
- dispc.dss_clk = clk;
-
spin_lock_init(&dispc.irq_lock);
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3601,103 +3628,62 @@ static int omap_dispchw_probe(struct platform_device *pdev)
if (!dispc_mem) {
DSSERR("can't get IORESOURCE_MEM DISPC\n");
r = -EINVAL;
- goto err_ioremap;
+ goto fail0;
}
dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
if (!dispc.base) {
DSSERR("can't ioremap DISPC\n");
r = -ENOMEM;
- goto err_ioremap;
+ goto fail0;
}
dispc.irq = platform_get_irq(dispc.pdev, 0);
if (dispc.irq < 0) {
DSSERR("platform_get_irq failed\n");
r = -ENODEV;
- goto err_irq;
+ 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 err_irq;
+ goto fail1;
}
- pm_runtime_enable(&pdev->dev);
-
- r = dispc_runtime_get();
- if (r)
- goto err_runtime_get;
+ 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));
- dispc_runtime_put();
+ enable_clocks(0);
return 0;
-
-err_runtime_get:
- pm_runtime_disable(&pdev->dev);
- free_irq(dispc.irq, dispc.pdev);
-err_irq:
+fail1:
iounmap(dispc.base);
-err_ioremap:
- clk_put(dispc.dss_clk);
-err_get_clk:
+fail0:
return r;
}
static int omap_dispchw_remove(struct platform_device *pdev)
{
- pm_runtime_disable(&pdev->dev);
-
- clk_put(dispc.dss_clk);
-
free_irq(dispc.irq, dispc.pdev);
iounmap(dispc.base);
return 0;
}
-static int dispc_runtime_suspend(struct device *dev)
-{
- dispc_save_context();
- clk_disable(dispc.dss_clk);
- dss_runtime_put();
-
- return 0;
-}
-
-static int dispc_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- return r;
-
- clk_enable(dispc.dss_clk);
- dispc_restore_context();
-
- return 0;
-}
-
-static const struct dev_pm_ops dispc_pm_ops = {
- .runtime_suspend = dispc_runtime_suspend,
- .runtime_resume = dispc_runtime_resume,
-};
-
static struct platform_driver omap_dispchw_driver = {
.probe = omap_dispchw_probe,
.remove = omap_dispchw_remove,
.driver = {
.name = "omapdss_dispc",
.owner = THIS_MODULE,
- .pm = &dispc_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index a0bbdf6684b..c2dfc8c5005 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -65,6 +65,48 @@ static ssize_t display_enabled_store(struct device *dev,
return size;
}
+static ssize_t display_upd_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
+ if (dssdev->driver->get_update_mode)
+ mode = dssdev->driver->get_update_mode(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
+}
+
+static ssize_t display_upd_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int val, r;
+ enum omap_dss_update_mode mode;
+
+ if (!dssdev->driver->set_update_mode)
+ return -EINVAL;
+
+ r = kstrtoint(buf, 0, &val);
+ if (r)
+ return r;
+
+ switch (val) {
+ case OMAP_DSS_UPDATE_DISABLED:
+ case OMAP_DSS_UPDATE_AUTO:
+ case OMAP_DSS_UPDATE_MANUAL:
+ mode = (enum omap_dss_update_mode)val;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ r = dssdev->driver->set_update_mode(dssdev, mode);
+ if (r)
+ return r;
+
+ return size;
+}
+
static ssize_t display_tear_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -252,6 +294,8 @@ static ssize_t display_wss_store(struct device *dev,
static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
+ display_upd_mode_show, display_upd_mode_store);
static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
display_tear_show, display_tear_store);
static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
@@ -265,6 +309,7 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
static struct device_attribute *display_sysfs_attrs[] = {
&dev_attr_enabled,
+ &dev_attr_update_mode,
&dev_attr_tear_elim,
&dev_attr_timings,
&dev_attr_rotate,
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index f053b180ecd..ff6bd30132d 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -23,6 +23,7 @@
#define DSS_SUBSYS_NAME "DPI"
#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
@@ -129,6 +130,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
bool is_tft;
int r = 0;
+ 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);
@@ -141,7 +144,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
&fck, &lck_div, &pck_div);
if (r)
- return r;
+ goto err0;
pck = fck / lck_div / pck_div / 1000;
@@ -155,10 +158,12 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
dispc_set_lcd_timings(dssdev->manager->id, t);
- return 0;
+err0:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+ return r;
}
-static void dpi_basic_init(struct omap_dss_device *dssdev)
+static int dpi_basic_init(struct omap_dss_device *dssdev)
{
bool is_tft;
@@ -170,6 +175,8 @@ static void dpi_basic_init(struct omap_dss_device *dssdev)
OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
dispc_set_tft_data_lines(dssdev->manager->id,
dssdev->phy.dpi.data_lines);
+
+ return 0;
}
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -179,38 +186,31 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
- goto err_start_dev;
+ goto err0;
}
if (cpu_is_omap34xx()) {
r = regulator_enable(dpi.vdds_dsi_reg);
if (r)
- goto err_reg_enable;
+ goto err1;
}
- r = dss_runtime_get();
- if (r)
- goto err_get_dss;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
- r = dispc_runtime_get();
+ r = dpi_basic_init(dssdev);
if (r)
- goto err_get_dispc;
-
- dpi_basic_init(dssdev);
+ goto err2;
if (dpi_use_dsi_pll(dssdev)) {
- r = dsi_runtime_get(dpi.dsidev);
- if (r)
- goto err_get_dsi;
-
+ dss_clk_enable(DSS_CLK_SYSCK);
r = dsi_pll_init(dpi.dsidev, 0, 1);
if (r)
- goto err_dsi_pll_init;
+ goto err3;
}
r = dpi_set_mode(dssdev);
if (r)
- goto err_set_mode;
+ goto err4;
mdelay(2);
@@ -218,22 +218,19 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
return 0;
-err_set_mode:
+err4:
if (dpi_use_dsi_pll(dssdev))
dsi_pll_uninit(dpi.dsidev, true);
-err_dsi_pll_init:
+err3:
if (dpi_use_dsi_pll(dssdev))
- dsi_runtime_put(dpi.dsidev);
-err_get_dsi:
- dispc_runtime_put();
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
+ dss_clk_disable(DSS_CLK_SYSCK);
+err2:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
-err_reg_enable:
+err1:
omap_dss_stop_device(dssdev);
-err_start_dev:
+err0:
return r;
}
EXPORT_SYMBOL(omapdss_dpi_display_enable);
@@ -245,11 +242,10 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
if (dpi_use_dsi_pll(dssdev)) {
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dsi_pll_uninit(dpi.dsidev, true);
- dsi_runtime_put(dpi.dsidev);
+ dss_clk_disable(DSS_CLK_SYSCK);
}
- dispc_runtime_put();
- dss_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
@@ -261,26 +257,11 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
void dpi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
- int r;
-
DSSDBG("dpi_set_timings\n");
dssdev->panel.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
- r = dss_runtime_get();
- if (r)
- return;
-
- r = dispc_runtime_get();
- if (r) {
- dss_runtime_put();
- return;
- }
-
dpi_set_mode(dssdev);
dispc_go(dssdev->manager->id);
-
- dispc_runtime_put();
- dss_runtime_put();
}
}
EXPORT_SYMBOL(dpi_set_timings);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b6a57bb7a61..345757cfcbe 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -36,7 +36,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include <plat/clock.h>
@@ -268,12 +267,8 @@ struct dsi_isr_tables {
struct dsi_data {
struct platform_device *pdev;
void __iomem *base;
-
int irq;
- struct clk *dss_clk;
- struct clk *sys_clk;
-
void (*dsi_mux_pads)(bool enable);
struct dsi_clock_info current_cinfo;
@@ -394,6 +389,15 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
return __raw_readl(dsi->base + idx.idx);
}
+
+void dsi_save_context(void)
+{
+}
+
+void dsi_restore_context(void)
+{
+}
+
void dsi_bus_lock(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -489,18 +493,9 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
total_bytes * 1000 / total_us);
}
#else
-static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
-{
-}
-
-static inline void dsi_perf_mark_start(struct platform_device *dsidev)
-{
-}
-
-static inline void dsi_perf_show(struct platform_device *dsidev,
- const char *name)
-{
-}
+#define dsi_perf_mark_setup(x)
+#define dsi_perf_mark_start(x)
+#define dsi_perf_show(x, y)
#endif
static void print_irq_status(u32 status)
@@ -1044,27 +1039,13 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
return e;
}
-int dsi_runtime_get(struct platform_device *dsidev)
+/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
+static inline void enable_clocks(bool enable)
{
- int r;
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
- DSSDBG("dsi_runtime_get\n");
-
- r = pm_runtime_get_sync(&dsi->pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-void dsi_runtime_put(struct platform_device *dsidev)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- int r;
-
- DSSDBG("dsi_runtime_put\n");
-
- r = pm_runtime_put(&dsi->pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
/* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1074,9 +1055,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
if (enable)
- clk_enable(dsi->sys_clk);
+ dss_clk_enable(DSS_CLK_SYSCK);
else
- clk_disable(dsi->sys_clk);
+ dss_clk_disable(DSS_CLK_SYSCK);
if (enable && dsi->pll_locked) {
if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1169,11 +1150,10 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
{
unsigned long r;
int dsi_module = dsi_get_dsidev_id(dsidev);
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
/* DSI FCLK source is DSS_CLK_FCK */
- r = clk_get_rate(dsi->dss_clk);
+ r = dss_clk_get_rate(DSS_CLK_FCK);
} else {
/* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
@@ -1282,7 +1262,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
return -EINVAL;
if (cinfo->use_sys_clk) {
- cinfo->clkin = clk_get_rate(dsi->sys_clk);
+ cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
/* XXX it is unclear if highfreq should be used
* with DSS_SYS_CLK source also */
cinfo->highfreq = 0;
@@ -1331,7 +1311,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
int match = 0;
unsigned long dss_sys_clk, max_dss_fck;
- dss_sys_clk = clk_get_rate(dsi->sys_clk);
+ dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
@@ -1621,6 +1601,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
dsi->vdds_dsi_reg = vdds_dsi;
}
+ enable_clocks(1);
dsi_enable_pll_clock(dsidev, 1);
/*
* Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
@@ -1672,6 +1653,7 @@ err1:
}
err0:
dsi_disable_scp_clk(dsidev);
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
return r;
}
@@ -1689,6 +1671,7 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
}
dsi_disable_scp_clk(dsidev);
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
DSSDBG("PLL uninit done\n");
@@ -1705,8 +1688,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
dispc_clk_src = dss_get_dispc_clk_source();
dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
- if (dsi_runtime_get(dsidev))
- return;
+ enable_clocks(1);
seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
@@ -1749,7 +1731,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk);
- dsi_runtime_put(dsidev);
+ enable_clocks(0);
}
void dsi_dump_clocks(struct seq_file *s)
@@ -1891,8 +1873,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
- if (dsi_runtime_get(dsidev))
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
dsi_enable_scp_clk(dsidev);
DUMPREG(DSI_REVISION);
@@ -1966,7 +1947,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
DUMPREG(DSI_PLL_CONFIGURATION2);
dsi_disable_scp_clk(dsidev);
- dsi_runtime_put(dsidev);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -2482,6 +2463,28 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
dsi->dsi_mux_pads(false);
}
+static int _dsi_wait_reset(struct platform_device *dsidev)
+{
+ int t = 0;
+
+ while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) {
+ if (++t > 5) {
+ DSSERR("soft reset failed\n");
+ return -ENODEV;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int _dsi_reset(struct platform_device *dsidev)
+{
+ /* Soft reset */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
+ return _dsi_wait_reset(dsidev);
+}
+
static void dsi_config_tx_fifo(struct platform_device *dsidev,
enum fifo_size size1, enum fifo_size size2,
enum fifo_size size3, enum fifo_size size4)
@@ -3383,10 +3386,6 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
- /* Reset LANEx_ULPS_SIG2 */
- REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
- 7, 5);
-
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
dsi_if_enable(dsidev, false);
@@ -4199,6 +4198,22 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
dsi_pll_uninit(dsidev, disconnect_lanes);
}
+static int dsi_core_init(struct platform_device *dsidev)
+{
+ /* Autoidle */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
+
+ /* ENWAKEUP */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
+
+ /* SIDLEMODE smart-idle */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
+
+ _dsi_initialize_irq(dsidev);
+
+ return 0;
+}
+
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4214,37 +4229,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
- goto err_start_dev;
+ goto err0;
}
- r = dsi_runtime_get(dsidev);
- if (r)
- goto err_get_dsi;
-
+ enable_clocks(1);
dsi_enable_pll_clock(dsidev, 1);
- _dsi_initialize_irq(dsidev);
+ r = _dsi_reset(dsidev);
+ if (r)
+ goto err1;
+
+ dsi_core_init(dsidev);
r = dsi_display_init_dispc(dssdev);
if (r)
- goto err_init_dispc;
+ goto err1;
r = dsi_display_init_dsi(dssdev);
if (r)
- goto err_init_dsi;
+ goto err2;
mutex_unlock(&dsi->lock);
return 0;
-err_init_dsi:
+err2:
dsi_display_uninit_dispc(dssdev);
-err_init_dispc:
+err1:
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
- dsi_runtime_put(dsidev);
-err_get_dsi:
omap_dss_stop_device(dssdev);
-err_start_dev:
+err0:
mutex_unlock(&dsi->lock);
DSSDBG("dsi_display_enable FAILED\n");
return r;
@@ -4267,7 +4282,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
- dsi_runtime_put(dsidev);
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
omap_dss_stop_device(dssdev);
@@ -4422,44 +4437,7 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
}
-static int dsi_get_clocks(struct platform_device *dsidev)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct clk *clk;
-
- clk = clk_get(&dsidev->dev, "dss_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get dss_clk\n");
- return PTR_ERR(clk);
- }
-
- dsi->dss_clk = clk;
-
- clk = clk_get(&dsidev->dev, "sys_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get sys_clk\n");
- clk_put(dsi->dss_clk);
- dsi->dss_clk = NULL;
- return PTR_ERR(clk);
- }
-
- dsi->sys_clk = clk;
-
- return 0;
-}
-
-static void dsi_put_clocks(struct platform_device *dsidev)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
- if (dsi->dss_clk)
- clk_put(dsi->dss_clk);
- if (dsi->sys_clk)
- clk_put(dsi->sys_clk);
-}
-
-/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
+static int dsi_init(struct platform_device *dsidev)
{
struct omap_display_platform_data *dss_plat_data;
struct omap_dss_board_info *board_info;
@@ -4471,7 +4449,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
if (!dsi) {
r = -ENOMEM;
- goto err_alloc;
+ goto err0;
}
dsi->pdev = dsidev;
@@ -4494,12 +4472,6 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
mutex_init(&dsi->lock);
sema_init(&dsi->bus_lock, 1);
- r = dsi_get_clocks(dsidev);
- if (r)
- goto err_get_clk;
-
- pm_runtime_enable(&dsidev->dev);
-
INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
dsi_framedone_timeout_work_callback);
@@ -4512,26 +4484,26 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
if (!dsi_mem) {
DSSERR("can't get IORESOURCE_MEM DSI\n");
r = -EINVAL;
- goto err_ioremap;
+ goto err1;
}
dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
if (!dsi->base) {
DSSERR("can't ioremap DSI\n");
r = -ENOMEM;
- goto err_ioremap;
+ goto err1;
}
dsi->irq = platform_get_irq(dsi->pdev, 0);
if (dsi->irq < 0) {
DSSERR("platform_get_irq failed\n");
r = -ENODEV;
- goto err_get_irq;
+ goto err2;
}
r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
dev_name(&dsidev->dev), dsi->pdev);
if (r < 0) {
DSSERR("request_irq failed\n");
- goto err_get_irq;
+ goto err2;
}
/* DSI VCs initialization */
@@ -4543,9 +4515,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
dsi_calc_clock_param_ranges(dsidev);
- r = dsi_runtime_get(dsidev);
- if (r)
- goto err_get_dsi;
+ enable_clocks(1);
rev = dsi_read_reg(dsidev, DSI_REVISION);
dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4553,32 +4523,21 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
- dsi_runtime_put(dsidev);
+ enable_clocks(0);
return 0;
-
-err_get_dsi:
- free_irq(dsi->irq, dsi->pdev);
-err_get_irq:
+err2:
iounmap(dsi->base);
-err_ioremap:
- pm_runtime_disable(&dsidev->dev);
-err_get_clk:
+err1:
kfree(dsi);
-err_alloc:
+err0:
return r;
}
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
+static void dsi_exit(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- WARN_ON(dsi->scp_clk_refcount > 0);
-
- pm_runtime_disable(&dsidev->dev);
-
- dsi_put_clocks(dsidev);
-
if (dsi->vdds_dsi_reg != NULL) {
if (dsi->vdds_dsi_enabled) {
regulator_disable(dsi->vdds_dsi_reg);
@@ -4594,56 +4553,38 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
kfree(dsi);
- return 0;
+ DSSDBG("omap_dsi_exit\n");
}
-static int dsi_runtime_suspend(struct device *dev)
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *dsidev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
-
- clk_disable(dsi->dss_clk);
-
- dispc_runtime_put();
- dss_runtime_put();
+ int r;
- return 0;
+ r = dsi_init(dsidev);
+ if (r) {
+ DSSERR("Failed to initialize DSI\n");
+ goto err_dsi;
+ }
+err_dsi:
+ return r;
}
-static int dsi_runtime_resume(struct device *dev)
+static int omap_dsi1hw_remove(struct platform_device *dsidev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
- int r;
-
- r = dss_runtime_get();
- if (r)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r)
- goto err_get_dispc;
-
- clk_enable(dsi->dss_clk);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ dsi_exit(dsidev);
+ WARN_ON(dsi->scp_clk_refcount > 0);
return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
}
-static const struct dev_pm_ops dsi_pm_ops = {
- .runtime_suspend = dsi_runtime_suspend,
- .runtime_resume = dsi_runtime_resume,
-};
-
static struct platform_driver omap_dsi1hw_driver = {
.probe = omap_dsi1hw_probe,
.remove = omap_dsi1hw_remove,
.driver = {
.name = "omapdss_dsi1",
.owner = THIS_MODULE,
- .pm = &dsi_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 5c6499a4d6a..d9489d5c4f0 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -28,8 +28,6 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include <plat/clock.h>
@@ -61,9 +59,15 @@ struct dss_reg {
static struct {
struct platform_device *pdev;
void __iomem *base;
+ int ctx_id;
struct clk *dpll4_m4_ck;
- struct clk *dss_clk;
+ 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,7 +78,6 @@ static struct {
enum omap_dss_clk_source dispc_clk_source;
enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
- bool ctx_valid;
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
} dss;
@@ -84,6 +87,13 @@ static const char * const dss_generic_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
};
+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)
{
__raw_writel(val, dss.base + idx.idx);
@@ -99,10 +109,12 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
#define RR(reg) \
dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
-static void dss_save_context(void)
+void dss_save_context(void)
{
- DSSDBG("dss_save_context\n");
+ if (cpu_is_omap24xx())
+ return;
+ SR(SYSCONFIG);
SR(CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -110,19 +122,14 @@ static void dss_save_context(void)
SR(SDI_CONTROL);
SR(PLL_CONTROL);
}
-
- dss.ctx_valid = true;
-
- DSSDBG("context saved\n");
}
-static void dss_restore_context(void)
+void dss_restore_context(void)
{
- DSSDBG("dss_restore_context\n");
-
- if (!dss.ctx_valid)
- return;
+ if (_omap_dss_wait_reset())
+ DSSERR("DSS not coming out of reset after sleep\n");
+ RR(SYSCONFIG);
RR(CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -130,8 +137,6 @@ static void dss_restore_context(void)
RR(SDI_CONTROL);
RR(PLL_CONTROL);
}
-
- DSSDBG("context restored\n");
}
#undef SR
@@ -229,7 +234,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
return dss_generic_clk_source_names[clk_src];
}
-
void dss_dump_clocks(struct seq_file *s)
{
unsigned long dpll4_ck_rate;
@@ -237,14 +241,13 @@ void dss_dump_clocks(struct seq_file *s)
const char *fclk_name, *fclk_real_name;
unsigned long fclk_rate;
- if (dss_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
seq_printf(s, "- DSS -\n");
fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
- fclk_rate = clk_get_rate(dss.dss_clk);
+ fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
if (dss.dpll4_m4_ck) {
dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -270,15 +273,14 @@ void dss_dump_clocks(struct seq_file *s)
fclk_rate);
}
- dss_runtime_put();
+ 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))
- if (dss_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(DSS_REVISION);
DUMPREG(DSS_SYSCONFIG);
@@ -292,7 +294,7 @@ void dss_dump_regs(struct seq_file *s)
DUMPREG(DSS_SDI_STATUS);
}
- dss_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -435,7 +437,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
} else {
if (cinfo->fck_div != 0)
return -EINVAL;
- cinfo->fck = clk_get_rate(dss.dss_clk);
+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
}
return 0;
@@ -465,7 +467,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
int dss_get_clock_div(struct dss_clock_info *cinfo)
{
- cinfo->fck = clk_get_rate(dss.dss_clk);
+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
if (dss.dpll4_m4_ck) {
unsigned long prate;
@@ -510,7 +512,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
- fck = clk_get_rate(dss.dss_clk);
+ 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)) {
@@ -537,7 +539,7 @@ retry:
if (dss.dpll4_m4_ck == NULL) {
struct dispc_clock_info cur_dispc;
/* XXX can we change the clock on omap2? */
- fck = clk_get_rate(dss.dss_clk);
+ fck = dss_clk_get_rate(DSS_CLK_FCK);
fck_div = 1;
dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -614,6 +616,28 @@ found:
return 0;
}
+static int _omap_dss_wait_reset(void)
+{
+ int t = 0;
+
+ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
+ if (++t > 1000) {
+ DSSERR("soft reset failed\n");
+ return -ENODEV;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int _omap_dss_reset(void)
+{
+ /* Soft reset */
+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
+ return _omap_dss_wait_reset();
+}
+
void dss_set_venc_output(enum omap_dss_venc_type type)
{
int l = 0;
@@ -639,83 +663,424 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
}
-static int dss_get_clocks(void)
+static int dss_init(void)
{
- struct clk *clk;
int r;
+ u32 rev;
+ struct resource *dss_mem;
+ struct clk *dpll4_m4_ck;
- clk = clk_get(&dss.pdev->dev, "dss_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get clock dss_clk\n");
- r = PTR_ERR(clk);
- goto err;
+ 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;
+ goto fail0;
}
- dss.dss_clk = clk;
+ /* disable LCD and DIGIT output. This seems to fix the synclost
+ * problem that we get, if the bootloader starts the DSS and
+ * the kernel resets it */
+ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+
+#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
+ /* We need to wait here a bit, otherwise we sometimes start to
+ * get synclost errors, and after that only power cycle will
+ * restore DSS functionality. I have no idea why this happens.
+ * And we have to wait _before_ resetting the DSS, but after
+ * enabling clocks.
+ *
+ * This bug was at least present on OMAP3430. It's unknown
+ * if it happens on OMAP2 or OMAP3630.
+ */
+ msleep(50);
+#endif
+ _omap_dss_reset();
+
+ /* autoidle */
+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+
+ /* Select DPLL */
+ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
+ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
+ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
+#endif
if (cpu_is_omap34xx()) {
- clk = clk_get(NULL, "dpll4_m4_ck");
- if (IS_ERR(clk)) {
+ dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+ if (IS_ERR(dpll4_m4_ck)) {
DSSERR("Failed to get dpll4_m4_ck\n");
- r = PTR_ERR(clk);
- goto err;
+ r = PTR_ERR(dpll4_m4_ck);
+ goto fail1;
}
} else if (cpu_is_omap44xx()) {
- clk = clk_get(NULL, "dpll_per_m5x2_ck");
- if (IS_ERR(clk)) {
- DSSERR("Failed to get dpll_per_m5x2_ck\n");
- r = PTR_ERR(clk);
- goto err;
+ dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
+ if (IS_ERR(dpll4_m4_ck)) {
+ DSSERR("Failed to get dpll4_m4_ck\n");
+ r = PTR_ERR(dpll4_m4_ck);
+ goto fail1;
}
} else { /* omap24xx */
- clk = NULL;
+ dpll4_m4_ck = NULL;
}
- dss.dpll4_m4_ck = clk;
+ dss.dpll4_m4_ck = dpll4_m4_ck;
- return 0;
+ dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+ dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+ dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-err:
- if (dss.dss_clk)
- clk_put(dss.dss_clk);
- if (dss.dpll4_m4_ck)
- clk_put(dss.dpll4_m4_ck);
+ dss_save_context();
+
+ rev = dss_read_reg(DSS_REVISION);
+ printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ return 0;
+fail1:
+ iounmap(dss.base);
+fail0:
return r;
}
-static void dss_put_clocks(void)
+static void dss_exit(void)
{
if (dss.dpll4_m4_ck)
clk_put(dss.dpll4_m4_ck);
- clk_put(dss.dss_clk);
+
+ iounmap(dss.base);
}
-int dss_runtime_get(void)
+/* CONTEXT */
+static int dss_get_ctx_id(void)
{
+ struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
int r;
- DSSDBG("dss_runtime_get\n");
+ 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();
- r = pm_runtime_get_sync(&dss.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
+ dss_restore_context();
+ dispc_restore_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_restore_context();
+#endif
+
+ dss_clk_disable_all_no_ctx();
}
-void dss_runtime_put(void)
+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;
+ struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
+
+ 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;
+
+ if (!pdata->opt_clock_available) {
+ r = -ENODEV;
+ goto err;
+ }
+
+ if (pdata->opt_clock_available("sys_clk")) {
+ r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
+ if (r)
+ goto err;
+ }
+
+ if (pdata->opt_clock_available("tv_clk")) {
+ r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
+ if (r)
+ goto err;
+ }
+
+ if (pdata->opt_clock_available("video_clk")) {
+ 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);
- DSSDBG("dss_runtime_put\n");
+ return r;
+}
- r = pm_runtime_put(&dss.pdev->dev);
- WARN_ON(r < 0);
+static void dss_put_clocks(void)
+{
+ if (dss.dss_video_fck)
+ clk_put(dss.dss_video_fck);
+ if (dss.dss_tv_fck)
+ clk_put(dss.dss_tv_fck);
+ if (dss.dss_sys_clk)
+ clk_put(dss.dss_sys_clk);
+ clk_put(dss.dss_fck);
+ 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) && dss.dss_sys_clk)
+ clk_enable(dss.dss_sys_clk);
+ if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
+ clk_enable(dss.dss_tv_fck);
+ if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
+ 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);
+
+ /*
+ * HACK: On omap4 the registers may not be accessible right after
+ * enabling the clocks. At some point this will be handled by
+ * pm_runtime, but for the time begin this should make things work.
+ */
+ if (cpu_is_omap44xx() && check_ctx)
+ udelay(10);
+
+ 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) && dss.dss_sys_clk)
+ clk_disable(dss.dss_sys_clk);
+ if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
+ clk_disable(dss.dss_tv_fck);
+ if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
+ 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
+ };
+
+ const char *names[5] = {
+ "ick",
+ "fck",
+ "sys_clk",
+ "tv_fck",
+ "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, "%s (%s)%*s\t%lu\t%d\n",
+ names[i],
+ clocks[i]->name,
+ 24 - strlen(names[i]) - strlen(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
@@ -724,51 +1089,28 @@ void dss_debug_dump_clocks(struct seq_file *s)
}
#endif
+
/* DSS HW IP initialisation */
static int omap_dsshw_probe(struct platform_device *pdev)
{
- struct resource *dss_mem;
- u32 rev;
int r;
dss.pdev = pdev;
- dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
- if (!dss_mem) {
- DSSERR("can't get IORESOURCE_MEM DSS\n");
- r = -EINVAL;
- goto err_ioremap;
- }
- dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
- if (!dss.base) {
- DSSERR("can't ioremap DSS\n");
- r = -ENOMEM;
- goto err_ioremap;
- }
-
r = dss_get_clocks();
if (r)
goto err_clocks;
- pm_runtime_enable(&pdev->dev);
-
- r = dss_runtime_get();
- if (r)
- goto err_runtime_get;
+ dss_clk_enable_all_no_ctx();
- /* Select DPLL */
- REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+ dss.ctx_id = dss_get_ctx_id();
+ DSSDBG("initial ctx id %u\n", dss.ctx_id);
-#ifdef CONFIG_OMAP2_DSS_VENC
- REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
- REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
- REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
-#endif
- dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
- dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
- dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
- dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
- dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+ r = dss_init();
+ if (r) {
+ DSSERR("Failed to initialize DSS\n");
+ goto err_dss;
+ }
r = dpi_init();
if (r) {
@@ -782,66 +1124,42 @@ static int omap_dsshw_probe(struct platform_device *pdev)
goto err_sdi;
}
- rev = dss_read_reg(DSS_REVISION);
- printk(KERN_INFO "OMAP DSS rev %d.%d\n",
- FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
- dss_runtime_put();
-
+ dss_clk_disable_all_no_ctx();
return 0;
err_sdi:
dpi_exit();
err_dpi:
- dss_runtime_put();
-err_runtime_get:
- pm_runtime_disable(&pdev->dev);
+ dss_exit();
+err_dss:
+ dss_clk_disable_all_no_ctx();
dss_put_clocks();
err_clocks:
- iounmap(dss.base);
-err_ioremap:
return r;
}
static int omap_dsshw_remove(struct platform_device *pdev)
{
- dpi_exit();
- sdi_exit();
- iounmap(dss.base);
+ dss_exit();
- pm_runtime_disable(&pdev->dev);
+ /*
+ * 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 int dss_runtime_suspend(struct device *dev)
-{
- dss_save_context();
- clk_disable(dss.dss_clk);
return 0;
}
-static int dss_runtime_resume(struct device *dev)
-{
- clk_enable(dss.dss_clk);
- dss_restore_context();
- return 0;
-}
-
-static const struct dev_pm_ops dss_pm_ops = {
- .runtime_suspend = dss_runtime_suspend,
- .runtime_resume = dss_runtime_resume,
-};
-
static struct platform_driver omap_dsshw_driver = {
.probe = omap_dsshw_probe,
.remove = omap_dsshw_remove,
.driver = {
.name = "omapdss_dss",
.owner = THIS_MODULE,
- .pm = &dss_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index ce17a613a30..8ab6d43329b 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -109,6 +109,14 @@ enum omap_parallel_interface_mode {
OMAP_DSS_PARALLELMODE_DSI,
};
+enum dss_clock {
+ 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_hdmi_venc_clk_source_select {
DSS_VENC_TV_CLK = 0,
DSS_HDMI_M_PCLK = 1,
@@ -212,10 +220,13 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
int dss_init_platform_driver(void);
void dss_uninit_platform_driver(void);
-int dss_runtime_get(void);
-void dss_runtime_put(void);
-
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
+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);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
@@ -272,15 +283,15 @@ struct file_operations;
int dsi_init_platform_driver(void);
void dsi_uninit_platform_driver(void);
-int dsi_runtime_get(struct platform_device *dsidev);
-void dsi_runtime_put(struct platform_device *dsidev);
-
void dsi_dump_clocks(struct seq_file *s);
void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
+void dsi_save_context(void);
+void dsi_restore_context(void);
+
int dsi_init_display(struct omap_dss_device *display);
void dsi_irq_handler(void);
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
@@ -306,13 +317,6 @@ static inline int dsi_init_platform_driver(void)
static inline void dsi_uninit_platform_driver(void)
{
}
-static inline int dsi_runtime_get(struct platform_device *dsidev)
-{
- return 0;
-}
-static inline void dsi_runtime_put(struct platform_device *dsidev)
-{
-}
static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
{
WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -380,8 +384,8 @@ void dispc_dump_regs(struct seq_file *s);
void dispc_irq_handler(void);
void dispc_fake_vsync_irq(void);
-int dispc_runtime_get(void);
-void dispc_runtime_put(void);
+void dispc_save_context(void);
+void dispc_restore_context(void);
void dispc_enable_sidle(void);
void dispc_disable_sidle(void);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index bd420f9650c..1c18888e5df 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -286,9 +286,7 @@ static const struct omap_dss_features omap3430_dss_features = {
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
- FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
- FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
- FEAT_FIR_COEF_V,
+ FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
.num_mgrs = 2,
.num_ovls = 3,
@@ -308,8 +306,7 @@ static const struct omap_dss_features omap3630_dss_features = {
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
- FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
- FEAT_FIR_COEF_V,
+ FEAT_DSI_PLL_FREQSEL,
.num_mgrs = 2,
.num_ovls = 3,
@@ -330,8 +327,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
- FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
- FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
+ FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
.num_mgrs = 3,
.num_ovls = 3,
@@ -352,8 +348,7 @@ static const struct omap_dss_features omap4_dss_features = {
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
- FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
- FEAT_PRELOAD | FEAT_FIR_COEF_V,
+ FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
.num_mgrs = 3,
.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 5be8103a159..07b346f7d91 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -51,10 +51,6 @@ enum dss_feat_id {
FEAT_HDMI_CTS_SWMODE = 1 << 19,
FEAT_HANDLE_UV_SEPARATE = 1 << 20,
FEAT_ATTR2 = 1 << 21,
- FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22,
- FEAT_CPR = 1 << 23,
- FEAT_PRELOAD = 1 << 24,
- FEAT_FIR_COEF_V = 1 << 25,
};
/* DSS register field id */
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 1bbf31329c7..b0555f4f0a7 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -29,9 +29,6 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
#include <video/omapdss.h>
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -54,9 +51,6 @@ static struct {
u8 edid_set;
bool custom_set;
struct hdmi_config cfg;
-
- struct clk *sys_clk;
- struct clk *hdmi_clk;
} hdmi;
/*
@@ -168,27 +162,6 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
return val;
}
-static int hdmi_runtime_get(void)
-{
- int r;
-
- DSSDBG("hdmi_runtime_get\n");
-
- r = pm_runtime_get_sync(&hdmi.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-static void hdmi_runtime_put(void)
-{
- int r;
-
- DSSDBG("hdmi_runtime_put\n");
-
- r = pm_runtime_put(&hdmi.pdev->dev);
- WARN_ON(r < 0);
-}
-
int hdmi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("init_display\n");
@@ -338,11 +311,30 @@ static int hdmi_phy_init(void)
return 0;
}
+static int hdmi_wait_softreset(void)
+{
+ /* reset W1 */
+ REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
+
+ /* wait till SOFTRESET == 0 */
+ if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
+ DSSERR("sysconfig reset failed\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static int hdmi_pll_program(struct hdmi_pll_info *fmt)
{
u16 r = 0;
enum hdmi_clk_refsel refsel;
+ /* wait for wrapper reset */
+ r = hdmi_wait_softreset();
+ if (r)
+ return r;
+
r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
if (r)
return r;
@@ -1072,7 +1064,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
unsigned long clkin, refclk;
u32 mf;
- clkin = clk_get_rate(hdmi.sys_clk) / 10000;
+ clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
/*
* Input clock is predivided by N + 1
* out put of which is reference clk
@@ -1106,6 +1098,16 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
}
+static void hdmi_enable_clocks(int enable)
+{
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
+ DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
+ DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
+}
+
static int hdmi_power_on(struct omap_dss_device *dssdev)
{
int r, code = 0;
@@ -1113,9 +1115,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
struct omap_video_timings *p;
unsigned long phy;
- r = hdmi_runtime_get();
- if (r)
- return r;
+ hdmi_enable_clocks(1);
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
@@ -1180,7 +1180,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
return 0;
err:
- hdmi_runtime_put();
+ hdmi_enable_clocks(0);
return -EIO;
}
@@ -1191,7 +1191,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
hdmi_wp_video_start(0);
hdmi_phy_off();
hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
- hdmi_runtime_put();
+ hdmi_enable_clocks(0);
hdmi.edid_set = 0;
}
@@ -1686,43 +1686,14 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
};
#endif
-static int hdmi_get_clocks(struct platform_device *pdev)
-{
- struct clk *clk;
-
- clk = clk_get(&pdev->dev, "sys_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get sys_clk\n");
- return PTR_ERR(clk);
- }
-
- hdmi.sys_clk = clk;
-
- clk = clk_get(&pdev->dev, "hdmi_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get hdmi_clk\n");
- clk_put(hdmi.sys_clk);
- return PTR_ERR(clk);
- }
-
- hdmi.hdmi_clk = clk;
-
- return 0;
-}
-
-static void hdmi_put_clocks(void)
-{
- if (hdmi.sys_clk)
- clk_put(hdmi.sys_clk);
- if (hdmi.hdmi_clk)
- clk_put(hdmi.hdmi_clk);
-}
-
/* HDMI HW IP initialisation */
static int omapdss_hdmihw_probe(struct platform_device *pdev)
{
struct resource *hdmi_mem;
- int r;
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+ int ret;
+#endif
hdmi.pdata = pdev->dev.platform_data;
hdmi.pdev = pdev;
@@ -1742,25 +1713,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
return -ENOMEM;
}
- r = hdmi_get_clocks(pdev);
- if (r) {
- iounmap(hdmi.base_wp);
- return r;
- }
-
- pm_runtime_enable(&pdev->dev);
-
hdmi_panel_init();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
/* Register ASoC codec DAI */
- r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+ ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
&hdmi_codec_dai_drv, 1);
- if (r) {
+ if (ret) {
DSSERR("can't register ASoC HDMI audio codec\n");
- return r;
+ return ret;
}
#endif
return 0;
@@ -1775,62 +1738,17 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
snd_soc_unregister_codec(&pdev->dev);
#endif
- pm_runtime_disable(&pdev->dev);
-
- hdmi_put_clocks();
-
iounmap(hdmi.base_wp);
return 0;
}
-static int hdmi_runtime_suspend(struct device *dev)
-{
- clk_disable(hdmi.hdmi_clk);
- clk_disable(hdmi.sys_clk);
-
- dispc_runtime_put();
- dss_runtime_put();
-
- return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r < 0)
- goto err_get_dispc;
-
-
- clk_enable(hdmi.sys_clk);
- clk_enable(hdmi.hdmi_clk);
-
- return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
-}
-
-static const struct dev_pm_ops hdmi_pm_ops = {
- .runtime_suspend = hdmi_runtime_suspend,
- .runtime_resume = hdmi_runtime_resume,
-};
-
static struct platform_driver omapdss_hdmihw_driver = {
.probe = omapdss_hdmihw_probe,
.remove = omapdss_hdmihw_remove,
.driver = {
.name = "omapdss_hdmi",
.owner = THIS_MODULE,
- .pm = &hdmi_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index c6d26c6e697..9aeea50e33f 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -416,6 +416,8 @@ struct overlay_cache_data {
enum omap_burst_size burst_size;
u32 fifo_low;
u32 fifo_high;
+
+ bool manual_update;
};
struct manager_cache_data {
@@ -435,6 +437,7 @@ struct manager_cache_data {
bool alpha_enabled;
+ bool manual_upd_display;
bool manual_update;
bool do_manual_update;
@@ -536,15 +539,24 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return 0;
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
- return 0;
-
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
|| dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
} else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ enum omap_dss_update_mode mode;
+ mode = dssdev->driver->get_update_mode(dssdev);
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return 0;
+
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_FRAMEDONE
+ : DISPC_IRQ_FRAMEDONE2;
+ } else {
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_VSYNC
+ : DISPC_IRQ_VSYNC2;
+ }
}
mc = &dss_cache.manager_cache[mgr->id];
@@ -605,15 +617,24 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return 0;
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
- return 0;
-
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
|| dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
} else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ enum omap_dss_update_mode mode;
+ mode = dssdev->driver->get_update_mode(dssdev);
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return 0;
+
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_FRAMEDONE
+ : DISPC_IRQ_FRAMEDONE2;
+ } else {
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_VSYNC
+ : DISPC_IRQ_VSYNC2;
+ }
}
oc = &dss_cache.overlay_cache[ovl->id];
@@ -742,7 +763,7 @@ static int configure_overlay(enum omap_plane plane)
orig_outw = outw;
orig_outh = outh;
- if (mc->manual_update && mc->do_manual_update) {
+ if (c->manual_update && mc->do_manual_update) {
unsigned bpp;
unsigned scale_x_m = w, scale_x_d = outw;
unsigned scale_y_m = h, scale_y_d = outh;
@@ -907,7 +928,7 @@ static int configure_dispc(void)
if (!oc->dirty)
continue;
- if (mc->manual_update && !mc->do_manual_update)
+ if (oc->manual_update && !mc->do_manual_update)
continue;
if (mgr_busy[oc->channel]) {
@@ -955,7 +976,7 @@ static int configure_dispc(void)
/* We don't need GO with manual update display. LCD iface will
* always be turned off after frame, and new settings will be
* taken in to use at next update */
- if (!mc->manual_update)
+ if (!mc->manual_upd_display)
dispc_go(i);
}
@@ -1215,10 +1236,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
- r = dispc_runtime_get();
- if (r)
- return r;
-
spin_lock_irqsave(&dss_cache.lock, flags);
/* Configure overlays */
@@ -1285,6 +1302,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
oc->enabled = true;
+ oc->manual_update =
+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+ dssdev->driver->get_update_mode(dssdev) !=
+ OMAP_DSS_UPDATE_AUTO;
+
++num_planes_enabled;
}
@@ -1319,8 +1341,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
mc->trans_enabled = mgr->info.trans_enabled;
mc->alpha_enabled = mgr->info.alpha_enabled;
- mc->manual_update =
+ mc->manual_upd_display =
dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+
+ mc->manual_update =
+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+ dssdev->driver->get_update_mode(dssdev) !=
+ OMAP_DSS_UPDATE_AUTO;
}
/* XXX TODO: Try to get fifomerge working. The problem is that it
@@ -1382,6 +1409,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
}
r = 0;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
if (!dss_cache.irq_enabled) {
u32 mask;
@@ -1394,11 +1422,10 @@ 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_FCK);
spin_unlock_irqrestore(&dss_cache.lock, flags);
- dispc_runtime_put();
-
return r;
}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index c84380c53c3..0f08025b1f0 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -84,42 +84,32 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
old_mgr = ovl->manager;
- r = dispc_runtime_get();
- if (r)
- return r;
-
/* detach old manager */
if (old_mgr) {
r = ovl->unset_manager(ovl);
if (r) {
DSSERR("detach failed\n");
- goto err;
+ return r;
}
r = old_mgr->apply(old_mgr);
if (r)
- goto err;
+ return r;
}
if (mgr) {
r = ovl->set_manager(ovl, mgr);
if (r) {
DSSERR("Failed to attach overlay\n");
- goto err;
+ return r;
}
r = mgr->apply(mgr);
if (r)
- goto err;
+ return r;
}
- dispc_runtime_put();
-
return size;
-
-err:
- dispc_runtime_put();
- return r;
}
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
@@ -248,9 +238,6 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
u8 alpha;
struct omap_overlay_info info;
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
- return -ENODEV;
-
r = kstrtou8(buf, 0, &alpha);
if (r)
return r;
@@ -517,6 +504,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
ovl->manager = mgr;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
* seem to get SYNC_LOST_DIGIT error.
@@ -530,6 +518,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
* the overlay, but before moving the overlay to TV.
*/
dispc_set_channel_out(ovl->id, mgr->id);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return 0;
}
@@ -730,8 +719,6 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
}
if (mgr) {
- dispc_runtime_get();
-
for (i = 0; i < dss_feat_get_num_ovls(); i++) {
struct omap_overlay *ovl;
ovl = omap_dss_get_overlay(i);
@@ -741,8 +728,6 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
omap_dss_set_manager(ovl, mgr);
}
}
-
- dispc_runtime_put();
}
}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index c57e3fbf239..c06fbe0bc67 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -33,8 +33,6 @@
#include <linux/hrtimer.h>
#include <linux/seq_file.h>
#include <linux/semaphore.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include "dss.h"
@@ -122,25 +120,12 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
return __raw_readl(rfbi.base + idx.idx);
}
-static int rfbi_runtime_get(void)
+static void rfbi_enable_clocks(bool enable)
{
- int r;
-
- DSSDBG("rfbi_runtime_get\n");
-
- r = pm_runtime_get_sync(&rfbi.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-static void rfbi_runtime_put(void)
-{
- int r;
-
- DSSDBG("rfbi_runtime_put\n");
-
- r = pm_runtime_put(&rfbi.pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
void rfbi_bus_lock(void)
@@ -820,8 +805,7 @@ void rfbi_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
- if (rfbi_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(RFBI_REVISION);
DUMPREG(RFBI_SYSCONFIG);
@@ -852,7 +836,7 @@ void rfbi_dump_regs(struct seq_file *s)
DUMPREG(RFBI_VSYNC_WIDTH);
DUMPREG(RFBI_HSYNC_WIDTH);
- rfbi_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -860,9 +844,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
int r;
- r = rfbi_runtime_get();
- if (r)
- return r;
+ rfbi_enable_clocks(1);
r = omap_dss_start_device(dssdev);
if (r) {
@@ -897,7 +879,6 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
err1:
omap_dss_stop_device(dssdev);
err0:
- rfbi_runtime_put();
return r;
}
EXPORT_SYMBOL(omapdss_rfbi_display_enable);
@@ -908,7 +889,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
DISPC_IRQ_FRAMEDONE);
omap_dss_stop_device(dssdev);
- rfbi_runtime_put();
+ rfbi_enable_clocks(0);
}
EXPORT_SYMBOL(omapdss_rfbi_display_disable);
@@ -923,9 +904,8 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
static int omap_rfbihw_probe(struct platform_device *pdev)
{
u32 rev;
+ u32 l;
struct resource *rfbi_mem;
- struct clk *clk;
- int r;
rfbi.pdev = pdev;
@@ -934,99 +914,46 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
if (!rfbi_mem) {
DSSERR("can't get IORESOURCE_MEM RFBI\n");
- r = -EINVAL;
- goto err_ioremap;
+ return -EINVAL;
}
rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
if (!rfbi.base) {
DSSERR("can't ioremap RFBI\n");
- r = -ENOMEM;
- goto err_ioremap;
+ return -ENOMEM;
}
- pm_runtime_enable(&pdev->dev);
-
- r = rfbi_runtime_get();
- if (r)
- goto err_get_rfbi;
+ rfbi_enable_clocks(1);
msleep(10);
- clk = clk_get(&pdev->dev, "rfbi_iclk");
- if (IS_ERR(clk)) {
- DSSERR("can't get rfbi_iclk\n");
- r = PTR_ERR(clk);
- goto err_get_ick;
- }
-
- rfbi.l4_khz = clk_get_rate(clk) / 1000;
+ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
- clk_put(clk);
+ /* 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_runtime_put();
+ rfbi_enable_clocks(0);
return 0;
-
-err_get_ick:
- rfbi_runtime_put();
-err_get_rfbi:
- pm_runtime_disable(&pdev->dev);
- iounmap(rfbi.base);
-err_ioremap:
- return r;
}
static int omap_rfbihw_remove(struct platform_device *pdev)
{
- pm_runtime_disable(&pdev->dev);
iounmap(rfbi.base);
return 0;
}
-static int rfbi_runtime_suspend(struct device *dev)
-{
- dispc_runtime_put();
- dss_runtime_put();
-
- return 0;
-}
-
-static int rfbi_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r < 0)
- goto err_get_dispc;
-
- return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
-}
-
-static const struct dev_pm_ops rfbi_pm_ops = {
- .runtime_suspend = rfbi_runtime_suspend,
- .runtime_resume = rfbi_runtime_resume,
-};
-
static struct platform_driver omap_rfbihw_driver = {
.probe = omap_rfbihw_probe,
.remove = omap_rfbihw_remove,
.driver = {
.name = "omapdss_rfbi",
.owner = THIS_MODULE,
- .pm = &rfbi_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 3a688c871a4..0bd4b0350f8 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -20,11 +20,13 @@
#define DSS_SUBSYS_NAME "SDI"
#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/regulator/consumer.h>
#include <video/omapdss.h>
+#include <plat/cpu.h>
#include "dss.h"
static struct {
@@ -58,20 +60,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
- goto err_start_dev;
+ goto err0;
}
r = regulator_enable(sdi.vdds_sdi_reg);
if (r)
- goto err_reg_enable;
+ goto err1;
- r = dss_runtime_get();
- if (r)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r)
- goto err_get_dispc;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
sdi_basic_init(dssdev);
@@ -84,7 +80,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = dss_calc_clock_div(1, t->pixel_clock * 1000,
&dss_cinfo, &dispc_cinfo);
if (r)
- goto err_calc_clock_div;
+ goto err2;
fck = dss_cinfo.fck;
lck_div = dispc_cinfo.lck_div;
@@ -105,34 +101,27 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = dss_set_clock_div(&dss_cinfo);
if (r)
- goto err_set_dss_clock_div;
+ goto err2;
r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
- goto err_set_dispc_clock_div;
+ goto err2;
dss_sdi_init(dssdev->phy.sdi.datapairs);
r = dss_sdi_enable();
if (r)
- goto err_sdi_enable;
+ goto err1;
mdelay(2);
dssdev->manager->enable(dssdev->manager);
return 0;
-
-err_sdi_enable:
-err_set_dispc_clock_div:
-err_set_dss_clock_div:
-err_calc_clock_div:
- dispc_runtime_put();
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
+err2:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
regulator_disable(sdi.vdds_sdi_reg);
-err_reg_enable:
+err1:
omap_dss_stop_device(dssdev);
-err_start_dev:
+err0:
return r;
}
EXPORT_SYMBOL(omapdss_sdi_display_enable);
@@ -143,8 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
dss_sdi_disable();
- dispc_runtime_put();
- dss_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
regulator_disable(sdi.vdds_sdi_reg);
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index f75159dc7f7..980f919ed98 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -33,13 +33,11 @@
#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
-#include "dss_features.h"
/* Venc registers */
#define VENC_REV_ID 0x00
@@ -294,9 +292,6 @@ static struct {
struct mutex venc_lock;
u32 wss_data;
struct regulator *vdda_dac_reg;
-
- struct clk *tv_clk;
- struct clk *tv_dac_clk;
} venc;
static inline void venc_write_reg(int idx, u32 val)
@@ -385,25 +380,14 @@ static void venc_reset(void)
#endif
}
-static int venc_runtime_get(void)
-{
- int r;
-
- DSSDBG("venc_runtime_get\n");
-
- r = pm_runtime_get_sync(&venc.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-static void venc_runtime_put(void)
+static void venc_enable_clocks(int enable)
{
- int r;
-
- DSSDBG("venc_runtime_put\n");
-
- r = pm_runtime_put(&venc.pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+ DSS_CLK_VIDFCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+ DSS_CLK_VIDFCK);
}
static const struct venc_config *venc_timings_to_config(
@@ -422,6 +406,8 @@ static void venc_power_on(struct omap_dss_device *dssdev)
{
u32 l;
+ venc_enable_clocks(1);
+
venc_reset();
venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
@@ -462,6 +448,8 @@ static void venc_power_off(struct omap_dss_device *dssdev)
dssdev->platform_disable(dssdev);
regulator_disable(venc.vdda_dac_reg);
+
+ venc_enable_clocks(0);
}
@@ -499,10 +487,6 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
goto err1;
}
- r = venc_runtime_get();
- if (r)
- goto err1;
-
venc_power_on(dssdev);
venc.wss_data = 0;
@@ -536,8 +520,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
venc_power_off(dssdev);
- venc_runtime_put();
-
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
omap_dss_stop_device(dssdev);
@@ -556,6 +538,20 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
return venc_panel_enable(dssdev);
}
+static enum omap_dss_update_mode venc_get_update_mode(
+ struct omap_dss_device *dssdev)
+{
+ return OMAP_DSS_UPDATE_AUTO;
+}
+
+static int venc_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+{
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return -EINVAL;
+ return 0;
+}
+
static void venc_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
@@ -602,7 +598,6 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
const struct venc_config *config;
- int r;
DSSDBG("venc_set_wss\n");
@@ -613,19 +608,16 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
/* Invert due to VENC_L21_WC_CTL:INV=1 */
venc.wss_data = (wss ^ 0xfffff) << 8;
- r = venc_runtime_get();
- if (r)
- goto err;
+ venc_enable_clocks(1);
venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
venc.wss_data);
- venc_runtime_put();
+ venc_enable_clocks(0);
-err:
mutex_unlock(&venc.venc_lock);
- return r;
+ return 0;
}
static struct omap_dss_driver venc_driver = {
@@ -640,6 +632,9 @@ static struct omap_dss_driver venc_driver = {
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
+ .set_update_mode = venc_set_update_mode,
+ .get_update_mode = venc_get_update_mode,
+
.get_timings = venc_get_timings,
.set_timings = venc_set_timings,
.check_timings = venc_check_timings,
@@ -678,8 +673,7 @@ void venc_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
- if (venc_runtime_get())
- return;
+ venc_enable_clocks(1);
DUMPREG(VENC_F_CONTROL);
DUMPREG(VENC_VIDOUT_CTRL);
@@ -723,53 +717,16 @@ void venc_dump_regs(struct seq_file *s)
DUMPREG(VENC_OUTPUT_CONTROL);
DUMPREG(VENC_OUTPUT_TEST);
- venc_runtime_put();
+ venc_enable_clocks(0);
#undef DUMPREG
}
-static int venc_get_clocks(struct platform_device *pdev)
-{
- struct clk *clk;
-
- clk = clk_get(&pdev->dev, "tv_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get tv_clk\n");
- return PTR_ERR(clk);
- }
-
- venc.tv_clk = clk;
-
- if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
- clk = clk_get(&pdev->dev, "tv_dac_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get tv_dac_clk\n");
- clk_put(venc.tv_clk);
- return PTR_ERR(clk);
- }
- } else {
- clk = NULL;
- }
-
- venc.tv_dac_clk = clk;
-
- return 0;
-}
-
-static void venc_put_clocks(void)
-{
- if (venc.tv_clk)
- clk_put(venc.tv_clk);
- if (venc.tv_dac_clk)
- clk_put(venc.tv_dac_clk);
-}
-
/* VENC HW IP initialisation */
static int omap_venchw_probe(struct platform_device *pdev)
{
u8 rev_id;
struct resource *venc_mem;
- int r;
venc.pdev = pdev;
@@ -780,40 +737,22 @@ static int omap_venchw_probe(struct platform_device *pdev)
venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
if (!venc_mem) {
DSSERR("can't get IORESOURCE_MEM VENC\n");
- r = -EINVAL;
- goto err_ioremap;
+ return -EINVAL;
}
venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
if (!venc.base) {
DSSERR("can't ioremap VENC\n");
- r = -ENOMEM;
- goto err_ioremap;
+ return -ENOMEM;
}
- r = venc_get_clocks(pdev);
- if (r)
- goto err_get_clk;
-
- pm_runtime_enable(&pdev->dev);
-
- r = venc_runtime_get();
- if (r)
- goto err_get_venc;
+ 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_runtime_put();
+ venc_enable_clocks(0);
return omap_dss_register_driver(&venc_driver);
-
-err_get_venc:
- pm_runtime_disable(&pdev->dev);
- venc_put_clocks();
-err_get_clk:
- iounmap(venc.base);
-err_ioremap:
- return r;
}
static int omap_venchw_remove(struct platform_device *pdev)
@@ -824,61 +763,16 @@ static int omap_venchw_remove(struct platform_device *pdev)
}
omap_dss_unregister_driver(&venc_driver);
- pm_runtime_disable(&pdev->dev);
- venc_put_clocks();
-
iounmap(venc.base);
return 0;
}
-static int venc_runtime_suspend(struct device *dev)
-{
- if (venc.tv_dac_clk)
- clk_disable(venc.tv_dac_clk);
- clk_disable(venc.tv_clk);
-
- dispc_runtime_put();
- dss_runtime_put();
-
- return 0;
-}
-
-static int venc_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r < 0)
- goto err_get_dispc;
-
- clk_enable(venc.tv_clk);
- if (venc.tv_dac_clk)
- clk_enable(venc.tv_dac_clk);
-
- return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
-}
-
-static const struct dev_pm_ops venc_pm_ops = {
- .runtime_suspend = venc_runtime_suspend,
- .runtime_resume = venc_runtime_resume,
-};
-
static struct platform_driver omap_venchw_driver = {
.probe = omap_venchw_probe,
.remove = omap_venchw_remove,
.driver = {
.name = "omapdss_venc",
.owner = THIS_MODULE,
- .pm = &venc_pm_ops,
},
};