diff options
| -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 7c1b7c1e4b63..0f3961a1ce26 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 | ||
| 150 | static 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 | ||
| 327 | static void dispc_restore_context(void) | 350 | static 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 | ||
| 516 | static 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 | |||
| 539 | static 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 | |||
| 570 | int dispc_runtime_get(void) | 552 | int 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 | } |
