drm/rockchip: vop: fix display flash when switch to iommu mapping
authorMark Yao <mark.yao@rock-chips.com>
Mon, 28 Nov 2016 00:46:29 +0000 (08:46 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 28 Nov 2016 03:52:35 +0000 (11:52 +0800)
Do iommu mapping with looping vop vblank register have a problem, when
iommu attach take too long time or vblank time is too short, the display
would flash.

This patch use another method to fix this problem:
  Use standby and dsp_hold interrupt to enter vblank time, when iommu
  mapping is finish, exit vop standby, then vop would start scanout
  immediately,
      vop enter standby    -> |
      dsp_hold irq         -> |--------- vblank start
      do iommu mapping     -> | vblank time
      exit standby         -> |--------- vblank end

We try add 20ms delay to iommu attach, display also looks good, that
means this method have higher compatibility.

Change-Id: I59d57c9085631d0c42174ea18890c80e26b42d22
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_vop.c

index e45a8b7f33fc33d6c7b3ec712500985de53e3a5b..6ac5afff4653e1f9d29e41eaf882a5528fc4f33d 100644 (file)
@@ -1536,13 +1536,25 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
        if (!vop->is_iommu_enabled && vop->is_iommu_needed) {
                int ret;
                if (!vop_is_allwin_disabled(vop)) {
+                       reinit_completion(&vop->dsp_hold_completion);
+                       vop_dsp_hold_valid_irq_enable(vop);
+
                        vop_cfg_update(crtc, old_crtc_state);
-                       while(!vop_is_cfg_done_complete(vop));
+                       spin_lock(&vop->reg_lock);
+
+                       VOP_CTRL_SET(vop, standby, 1);
+
+                       spin_unlock(&vop->reg_lock);
+
+                       wait_for_completion(&vop->dsp_hold_completion);
+
+                       vop_dsp_hold_valid_irq_disable(vop);
                }
                ret = rockchip_drm_dma_attach_device(vop->drm_dev, vop->dev);
                if (ret) {
                        dev_err(vop->dev, "failed to attach dma mapping, %d\n", ret);
                }
+               VOP_CTRL_SET(vop, standby, 0);
                vop->is_iommu_enabled = true;
        }