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 <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang
2019-07-18 10:21:22 +08:00
committed by Tao Huang
parent 6b2cb2ade2
commit 1a5de0dbf0
2 changed files with 33 additions and 8 deletions

View File

@@ -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;
}

View File

@@ -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)