diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-06-01 15:54:06 +0300 |
---|---|---|
committer | Sebastien Jan <s-jan@ti.com> | 2011-10-10 15:07:05 +0200 |
commit | 30e45082eea27502f70488499b28f3eede4c6e97 (patch) | |
tree | 919fbf8f3f09eab9073b0c5cfbba4b4c6e82f9e3 /drivers | |
parent | eebb6d42a4bcbcdb298b58c043f90648aa879efa (diff) |
OMAP: DSS2: DISPC: Fix context save/restore
The current method of saving and restoring the context could cause a
restore before saving, effectively "restoring" zero values to registers.
Add ctx_valid field to indicate if the saved context is valid and can be
restored.
Also restructure the code to save the ctx_loss_count in save_context(),
which makes more sense than the previous method of storing new
ctx_loss_count in dispc_need_ctx_restore.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 97 |
1 files changed, 38 insertions, 59 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 534899dd98ef..6357eb5d39ae 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -108,6 +108,7 @@ 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 @@ -140,6 +141,23 @@ 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) \ @@ -316,14 +334,30 @@ static void dispc_save_context(void) 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) { - int i; + 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); + /*RR(IRQENABLE);*/ /*RR(CONTROL);*/ RR(CONFIG); @@ -502,65 +536,13 @@ static void dispc_restore_context(void) * the context is fully restored */ RR(IRQENABLE); + + DSSDBG("context restored\n"); } #undef SR #undef RR -static void dispc_init_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 = 0; - - /* - * get_context_loss_count returns negative on error. We'll ignore the - * error and store the error to ctx_loss_cnt, which will cause - * dispc_need_ctx_restore() call to return true. - */ - - if (board_data->get_context_loss_count) - cnt = board_data->get_context_loss_count(dev); - - WARN_ON(cnt < 0); - - dispc.ctx_loss_cnt = cnt; - - DSSDBG("initial ctx_loss_cnt %u\n", cnt); -} - -static bool dispc_need_ctx_restore(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 get_context_loss_count is not available, assume that we need - * context restore always. - */ - if (!board_data->get_context_loss_count) - return true; - - cnt = board_data->get_context_loss_count(dev); - if (cnt < 0) { - dev_err(dev, "getting context loss count failed, will force " - "context restore\n"); - dispc.ctx_loss_cnt = cnt; - return true; - } - - if (cnt == dispc.ctx_loss_cnt) - return false; - - DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt); - dispc.ctx_loss_cnt = cnt; - - return true; -} - int dispc_runtime_get(void) { int r; @@ -3647,8 +3629,6 @@ static int omap_dispchw_probe(struct platform_device *pdev) goto err_irq; } - dispc_init_ctx_loss_count(); - pm_runtime_enable(&pdev->dev); r = dispc_runtime_get(); @@ -3707,8 +3687,7 @@ static int dispc_runtime_resume(struct device *dev) return r; clk_enable(dispc.dss_clk); - if (dispc_need_ctx_restore()) - dispc_restore_context(); + dispc_restore_context(); return 0; } |