aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-06-01 08:54:06 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-07-25 03:22:07 -0400
commit49ea86f3fae21dd0334668b621e9c88f43a73c86 (patch)
treec1940d9d5f9de067c0474448848f54318cbfcefd /drivers/video
parent39020710e707a01d80ea6c9e55dad4de93bb4730 (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/video')
-rw-r--r--drivers/video/omap2/dss/dispc.c97
1 files changed, 38 insertions, 59 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 7c1b7c1e4b6..0f3961a1ce2 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -114,6 +114,7 @@ static struct {
114 u32 error_irqs; 114 u32 error_irqs;
115 struct work_struct error_work; 115 struct work_struct error_work;
116 116
117 bool ctx_valid;
117 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 118 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
118 119
119#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 120#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -146,6 +147,23 @@ static inline u32 dispc_read_reg(const u16 idx)
146 return __raw_readl(dispc.base + idx); 147 return __raw_readl(dispc.base + idx);
147} 148}
148 149
150static int dispc_get_ctx_loss_count(void)
151{
152 struct device *dev = &dispc.pdev->dev;
153 struct omap_display_platform_data *pdata = dev->platform_data;
154 struct omap_dss_board_info *board_data = pdata->board_data;
155 int cnt;
156
157 if (!board_data->get_context_loss_count)
158 return -ENOENT;
159
160 cnt = board_data->get_context_loss_count(dev);
161
162 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
163
164 return cnt;
165}
166
149#define SR(reg) \ 167#define SR(reg) \
150 dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) 168 dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
151#define RR(reg) \ 169#define RR(reg) \
@@ -322,14 +340,30 @@ static void dispc_save_context(void)
322 340
323 if (dss_has_feature(FEAT_CORE_CLK_DIV)) 341 if (dss_has_feature(FEAT_CORE_CLK_DIV))
324 SR(DIVISOR); 342 SR(DIVISOR);
343
344 dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
345 dispc.ctx_valid = true;
346
347 DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
325} 348}
326 349
327static void dispc_restore_context(void) 350static void dispc_restore_context(void)
328{ 351{
329 int i; 352 int i, ctx;
330 353
331 DSSDBG("dispc_restore_context\n"); 354 DSSDBG("dispc_restore_context\n");
332 355
356 if (!dispc.ctx_valid)
357 return;
358
359 ctx = dispc_get_ctx_loss_count();
360
361 if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
362 return;
363
364 DSSDBG("ctx_loss_count: saved %d, current %d\n",
365 dispc.ctx_loss_cnt, ctx);
366
333 /*RR(IRQENABLE);*/ 367 /*RR(IRQENABLE);*/
334 /*RR(CONTROL);*/ 368 /*RR(CONTROL);*/
335 RR(CONFIG); 369 RR(CONFIG);
@@ -508,65 +542,13 @@ static void dispc_restore_context(void)
508 * the context is fully restored 542 * the context is fully restored
509 */ 543 */
510 RR(IRQENABLE); 544 RR(IRQENABLE);
545
546 DSSDBG("context restored\n");
511} 547}
512 548
513#undef SR 549#undef SR
514#undef RR 550#undef RR
515 551
516static void dispc_init_ctx_loss_count(void)
517{
518 struct device *dev = &dispc.pdev->dev;
519 struct omap_display_platform_data *pdata = dev->platform_data;
520 struct omap_dss_board_info *board_data = pdata->board_data;
521 int cnt = 0;
522
523 /*
524 * get_context_loss_count returns negative on error. We'll ignore the
525 * error and store the error to ctx_loss_cnt, which will cause
526 * dispc_need_ctx_restore() call to return true.
527 */
528
529 if (board_data->get_context_loss_count)
530 cnt = board_data->get_context_loss_count(dev);
531
532 WARN_ON(cnt < 0);
533
534 dispc.ctx_loss_cnt = cnt;
535
536 DSSDBG("initial ctx_loss_cnt %u\n", cnt);
537}
538
539static bool dispc_need_ctx_restore(void)
540{
541 struct device *dev = &dispc.pdev->dev;
542 struct omap_display_platform_data *pdata = dev->platform_data;
543 struct omap_dss_board_info *board_data = pdata->board_data;
544 int cnt;
545
546 /*
547 * If get_context_loss_count is not available, assume that we need
548 * context restore always.
549 */
550 if (!board_data->get_context_loss_count)
551 return true;
552
553 cnt = board_data->get_context_loss_count(dev);
554 if (cnt < 0) {
555 dev_err(dev, "getting context loss count failed, will force "
556 "context restore\n");
557 dispc.ctx_loss_cnt = cnt;
558 return true;
559 }
560
561 if (cnt == dispc.ctx_loss_cnt)
562 return false;
563
564 DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt);
565 dispc.ctx_loss_cnt = cnt;
566
567 return true;
568}
569
570int dispc_runtime_get(void) 552int dispc_runtime_get(void)
571{ 553{
572 int r; 554 int r;
@@ -3709,8 +3691,6 @@ static int omap_dispchw_probe(struct platform_device *pdev)
3709 goto err_irq; 3691 goto err_irq;
3710 } 3692 }
3711 3693
3712 dispc_init_ctx_loss_count();
3713
3714 pm_runtime_enable(&pdev->dev); 3694 pm_runtime_enable(&pdev->dev);
3715 3695
3716 r = dispc_runtime_get(); 3696 r = dispc_runtime_get();
@@ -3769,8 +3749,7 @@ static int dispc_runtime_resume(struct device *dev)
3769 return r; 3749 return r;
3770 3750
3771 clk_enable(dispc.dss_clk); 3751 clk_enable(dispc.dss_clk);
3772 if (dispc_need_ctx_restore()) 3752 dispc_restore_context();
3773 dispc_restore_context();
3774 3753
3775 return 0; 3754 return 0;
3776} 3755}