aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorInki Dae <inki.dae@samsung.com>2011-11-11 07:28:00 -0500
committerInki Dae <inki.dae@samsung.com>2011-11-15 00:58:46 -0500
commit483b88f86e1682241bfa0848e348aa175257c6e7 (patch)
tree505793b55f418b475d791876b82f97886160de6b /drivers/gpu
parent2c871127e994a678b82104a4110eb7fcc87f05ad (diff)
drm/exynos: fix vblank bug.
In case that vblank_disable_allowed is 1, the problem that manager->pipe could be -1 at vsync interrupt handler could be induced so this patch fixes that. Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index f5c8b072e497..272c3b53c062 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -447,7 +447,9 @@ static void fimd_win_commit(struct device *dev)
447static void fimd_win_disable(struct device *dev) 447static void fimd_win_disable(struct device *dev)
448{ 448{
449 struct fimd_context *ctx = get_fimd_context(dev); 449 struct fimd_context *ctx = get_fimd_context(dev);
450 struct fimd_win_data *win_data; 450 struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
451 struct drm_device *drm_dev = subdrv->drm_dev;
452 struct exynos_drm_manager *manager = &subdrv->manager;
451 int win = ctx->default_win; 453 int win = ctx->default_win;
452 u32 val; 454 u32 val;
453 455
@@ -456,8 +458,6 @@ static void fimd_win_disable(struct device *dev)
456 if (win < 0 || win > WINDOWS_NR) 458 if (win < 0 || win > WINDOWS_NR)
457 return; 459 return;
458 460
459 win_data = &ctx->win_data[win];
460
461 /* protect windows */ 461 /* protect windows */
462 val = readl(ctx->regs + SHADOWCON); 462 val = readl(ctx->regs + SHADOWCON);
463 val |= SHADOWCON_WINx_PROTECT(win); 463 val |= SHADOWCON_WINx_PROTECT(win);
@@ -473,6 +473,29 @@ static void fimd_win_disable(struct device *dev)
473 val &= ~SHADOWCON_CHx_ENABLE(win); 473 val &= ~SHADOWCON_CHx_ENABLE(win);
474 val &= ~SHADOWCON_WINx_PROTECT(win); 474 val &= ~SHADOWCON_WINx_PROTECT(win);
475 writel(val, ctx->regs + SHADOWCON); 475 writel(val, ctx->regs + SHADOWCON);
476
477 /* fimd dma off. */
478 val = readl(ctx->regs + VIDCON0);
479 val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
480 writel(val, ctx->regs + VIDCON0);
481
482 /*
483 * if vblank is enabled status with dma off then
484 * it disables vsync interrupt.
485 */
486 if (drm_dev->vblank_enabled[manager->pipe] &&
487 atomic_read(&drm_dev->vblank_refcount[manager->pipe])) {
488 drm_vblank_put(drm_dev, manager->pipe);
489
490 /*
491 * if vblank_disable_allowed is 0 then disable vsync interrupt
492 * right now else the vsync interrupt would be disabled by drm
493 * timer once a current process gives up ownershop of
494 * vblank event.
495 */
496 if (!drm_dev->vblank_disable_allowed)
497 drm_vblank_off(drm_dev, manager->pipe);
498 }
476} 499}
477 500
478static struct exynos_drm_overlay_ops fimd_overlay_ops = { 501static struct exynos_drm_overlay_ops fimd_overlay_ops = {
@@ -528,6 +551,16 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
528 /* VSYNC interrupt */ 551 /* VSYNC interrupt */
529 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); 552 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
530 553
554 /*
555 * in case that vblank_disable_allowed is 1, it could induce
556 * the problem that manager->pipe could be -1 because with
557 * disable callback, vsync interrupt isn't disabled and at this moment,
558 * vsync interrupt could occur. the vsync interrupt would be disabled
559 * by timer handler later.
560 */
561 if (manager->pipe == -1)
562 return IRQ_HANDLED;
563
531 drm_handle_vblank(drm_dev, manager->pipe); 564 drm_handle_vblank(drm_dev, manager->pipe);
532 fimd_finish_pageflip(drm_dev, manager->pipe); 565 fimd_finish_pageflip(drm_dev, manager->pipe);
533 566
@@ -548,13 +581,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
548 */ 581 */
549 drm_dev->irq_enabled = 1; 582 drm_dev->irq_enabled = 1;
550 583
551 /*
552 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
553 * by drm timer once a current process gives up ownership of
554 * vblank event.(drm_vblank_put function was called)
555 */
556 drm_dev->vblank_disable_allowed = 1;
557
558 return 0; 584 return 0;
559} 585}
560 586