From 49ea86f3fae21dd0334668b621e9c88f43a73c86 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 1 Jun 2011 15:54:06 +0300 Subject: [PATCH] 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 --- drivers/video/omap2/dss/dispc.c | 97 ++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 59 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 7c1b7c1..0f3961a 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -114,6 +114,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 @@ -146,6 +147,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) \ @@ -322,14 +340,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); @@ -508,65 +542,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; @@ -3709,8 +3691,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(); @@ -3769,8 +3749,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; } -- 2.7.4