From 1a5de0dbf0e30b17fdd122d5f6d4422d56dd90a1 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Thu, 18 Jul 2019 10:21:22 +0800 Subject: [PATCH] drm/rockchip: vop: set frame start to field start for interlace mode In interlace mode(480i60hz) the frame rate is 30hz, this is too low and lead to CTS test failed, so we use field start interrupt instead of frame start, and the vsync will update to 60hz. Change-Id: If73fb2b04dbd6749cc7cf899234a9f1e2283519e Signed-off-by: Sandy Huang --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 35 +++++++++++++++++---- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 ++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 6b7a9766f020..031381f0af6d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1912,8 +1912,13 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc) spin_lock_irqsave(&vop->irq_lock, flags); - VOP_INTR_SET_TYPE(vop, clear, FS_INTR, 1); - VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1); + if (VOP_MAJOR(vop->version) == 3 && VOP_MINOR(vop->version) >= 7) { + VOP_INTR_SET_TYPE(vop, clear, FS_FIELD_INTR, 1); + VOP_INTR_SET_TYPE(vop, enable, FS_FIELD_INTR, 1); + } else { + VOP_INTR_SET_TYPE(vop, clear, FS_INTR, 1); + VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1); + } spin_unlock_irqrestore(&vop->irq_lock, flags); @@ -1930,7 +1935,10 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) spin_lock_irqsave(&vop->irq_lock, flags); - VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0); + if (VOP_MAJOR(vop->version) == 3 && VOP_MINOR(vop->version) >= 7) + VOP_INTR_SET_TYPE(vop, enable, FS_FIELD_INTR, 0); + else + VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0); spin_unlock_irqrestore(&vop->irq_lock, flags); } @@ -3181,7 +3189,10 @@ static void vop_cfg_update(struct drm_crtc *crtc, static bool vop_fs_irq_is_pending(struct vop *vop) { - return VOP_INTR_GET_TYPE(vop, status, FS_INTR); + if (VOP_MAJOR(vop->version) == 3 && VOP_MINOR(vop->version) >= 7) + return VOP_INTR_GET_TYPE(vop, status, FS_FIELD_INTR); + else + return VOP_INTR_GET_TYPE(vop, status, FS_INTR); } static void vop_wait_for_irq_handler(struct vop *vop) @@ -3277,6 +3288,18 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, spin_lock_irqsave(&vop->irq_lock, flags); vop->pre_overlay = s->hdr.pre_overlay; vop_cfg_done(vop); + /* + * rk322x and rk332x odd-even field will mistake when in interlace mode. + * we must switch to frame effect before switch screen and switch to + * field effect after switch screen complete. + */ + if (VOP_MAJOR(vop->version) == 3 && + (VOP_MINOR(vop->version) == 7 || VOP_MINOR(vop->version) == 8)) { + if (!vop->mode_update && VOP_CTRL_GET(vop, reg_done_frm)) + VOP_CTRL_SET(vop, reg_done_frm, 0); + } else { + VOP_CTRL_SET(vop, reg_done_frm, 0); + } vop->mode_update = false; spin_unlock_irqrestore(&vop->irq_lock, flags); @@ -3611,7 +3634,7 @@ static irqreturn_t vop_isr(int irq, void *data) ret = IRQ_HANDLED; } - if (active_irqs & FS_INTR) { + if ((active_irqs & FS_INTR) || (active_irqs & FS_FIELD_INTR)) { /* This is IC design not reasonable, this two register bit need * frame effective, but actually it's effective immediately, so * we config this register at frame start. @@ -3622,7 +3645,7 @@ static irqreturn_t vop_isr(int irq, void *data) spin_unlock_irqrestore(&vop->irq_lock, flags); drm_crtc_handle_vblank(crtc); vop_handle_vblank(vop); - active_irqs &= ~FS_INTR; + active_irqs &= ~(FS_INTR | FS_FIELD_INTR); ret = IRQ_HANDLED; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 37c31f3e98ca..3b079a09c87a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -465,6 +465,8 @@ struct vop_data { #define POST_BUF_EMPTY_INTR BIT(12) #define PWM_GEN_INTR BIT(13) #define DMA_FINISH_INTR BIT(14) +#define FS_FIELD_INTR BIT(15) +#define FE_INTR BIT(16) #define INTR_MASK (DSP_HOLD_VALID_INTR | FS_INTR | \ LINE_FLAG_INTR | BUS_ERROR_INTR | \ @@ -473,8 +475,8 @@ struct vop_data { WIN2_EMPTY_INTR | WIN3_EMPTY_INTR | \ HWC_EMPTY_INTR | \ POST_BUF_EMPTY_INTR | \ - DMA_FINISH_INTR) - + DMA_FINISH_INTR | FS_FIELD_INTR | \ + FE_INTR) #define DSP_HOLD_VALID_INTR_EN(x) ((x) << 4) #define FS_INTR_EN(x) ((x) << 5) #define LINE_FLAG_INTR_EN(x) ((x) << 6)