summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vc4/vc4_crtc.c
diff options
context:
space:
mode:
authorEric Anholt2016-09-29 02:30:25 +0200
committerEric Anholt2016-10-06 20:58:27 +0200
commit682e62c45406ccf81216481be59c2f7ca5a883d4 (patch)
treef8a37357784f3008869cfbff0ac84ea980fd696d /drivers/gpu/drm/vc4/vc4_crtc.c
parentdrm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL changes. (diff)
downloadkernel-qcow2-linux-682e62c45406ccf81216481be59c2f7ca5a883d4.tar.gz
kernel-qcow2-linux-682e62c45406ccf81216481be59c2f7ca5a883d4.tar.xz
kernel-qcow2-linux-682e62c45406ccf81216481be59c2f7ca5a883d4.zip
drm/vc4: Fix support for interlaced modes on HDMI.
We really do need to be using the halved V fields. I had been confused by the code I was using as a reference because it stored halved vsync fields but not halved vdisplay, so it looked like I only needed to divide vdisplay by 2. This reverts part of Mario's timestamping fixes that prevented CRTC_HALVE_V from applying, and instead adjusts the timestamping code to not use the crtc field in that case. Fixes locking of 1920x1080x60i on my Dell 2408WFP. There are black bars on the top and bottom, but I suspect that might be an under/overscan flags problem as opposed to video timings. Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_crtc.c')
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c49
1 files changed, 26 insertions, 23 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2682f07d8f1e..83cafea03eff 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -229,7 +229,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
* and need to make things up in a approximative but consistent way.
*/
ret |= DRM_SCANOUTPOS_IN_VBLANK;
- vblank_lines = mode->crtc_vtotal - mode->crtc_vdisplay;
+ vblank_lines = mode->vtotal - mode->vdisplay;
if (flags & DRM_CALLED_FROM_VBLIRQ) {
/*
@@ -378,7 +378,6 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct drm_crtc_state *state = crtc->state;
struct drm_display_mode *mode = &state->adjusted_mode;
bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
- u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0));
u32 format = PV_CONTROL_FORMAT_24;
bool debug_dump_regs = false;
int clock_select = vc4_get_clock_select(crtc);
@@ -404,32 +403,46 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
CRTC_WRITE(PV_VERTA,
- VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
PV_VERTA_VBP) |
- VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+ VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
PV_VERTA_VSYNC));
CRTC_WRITE(PV_VERTB,
- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+ VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
PV_VERTB_VFP) |
- VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
if (interlace) {
CRTC_WRITE(PV_VERTA_EVEN,
- VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1,
+ VC4_SET_FIELD(mode->crtc_vtotal -
+ mode->crtc_vsync_end - 1,
PV_VERTA_VBP) |
- VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
+ VC4_SET_FIELD(mode->crtc_vsync_end -
+ mode->crtc_vsync_start,
PV_VERTA_VSYNC));
CRTC_WRITE(PV_VERTB_EVEN,
- VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
+ VC4_SET_FIELD(mode->crtc_vsync_start -
+ mode->crtc_vdisplay,
PV_VERTB_VFP) |
- VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
+
+ /* We set up first field even mode for HDMI. VEC's
+ * NTSC mode would want first field odd instead, once
+ * we support it (to do so, set ODD_FIRST and put the
+ * delay in VSYNCD_EVEN instead).
+ */
+ CRTC_WRITE(PV_V_CONTROL,
+ PV_VCONTROL_CONTINUOUS |
+ PV_VCONTROL_INTERLACE |
+ VC4_SET_FIELD(mode->htotal / 2,
+ PV_VCONTROL_ODD_DELAY));
+ CRTC_WRITE(PV_VSYNCD_EVEN, 0);
+ } else {
+ CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS);
}
CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
- CRTC_WRITE(PV_V_CONTROL,
- PV_VCONTROL_CONTINUOUS |
- (interlace ? PV_VCONTROL_INTERLACE : 0));
CRTC_WRITE(PV_CONTROL,
VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
@@ -544,16 +557,6 @@ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc,
return false;
}
- /*
- * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when
- * coming from user space. We don't want this, as it screws up
- * vblank timestamping, so fix it up.
- */
- drm_mode_set_crtcinfo(adjusted_mode, 0);
-
- DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id);
- drm_mode_debug_printmodeline(adjusted_mode);
-
return true;
}