1 From 074d7a2c41bbfa252b7c1f1d85b355dce89dcbe7 Mon Sep 17 00:00:00 2001
2 From: Mario Kleiner <mario.kleiner.de@gmail.com>
3 Date: Tue, 19 Jul 2016 20:58:58 +0200
4 Subject: [PATCH] drm/vc4: Fix handling of interlaced video modes.
6 We must not apply CRTC_INTERLACE_HALVE_V to interlaced modes during
7 mode enumeration, as drm_helper_probe_single_connector_modes
8 does, so wrap it and reset the effect of CRTC_INTERLACE_HALVE_V
9 on affected interlaced modes.
11 Also mode_fixup interlaced modes passed in from user space.
13 This fixes the vblank timestamping constants and entries in
14 the mode->crtc_xxx fields needed for precise vblank timestamping.
16 Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
17 Signed-off-by: Eric Anholt <eric@anholt.net>
19 drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++++++++++
20 drivers/gpu/drm/vc4/vc4_hdmi.c | 29 +++++++++++++++++++++++++++--
21 2 files changed, 45 insertions(+), 2 deletions(-)
23 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
24 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
25 @@ -538,6 +538,23 @@ static void vc4_crtc_enable(struct drm_c
26 CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
29 +static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc,
30 + const struct drm_display_mode *mode,
31 + struct drm_display_mode *adjusted_mode)
34 + * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when
35 + * coming from user space. We don't want this, as it screws up
36 + * vblank timestamping, so fix it up.
38 + drm_mode_set_crtcinfo(adjusted_mode, 0);
40 + DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id);
41 + drm_mode_debug_printmodeline(adjusted_mode);
46 static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
47 struct drm_crtc_state *state)
49 @@ -848,6 +865,7 @@ static const struct drm_crtc_helper_func
50 .mode_set_nofb = vc4_crtc_mode_set_nofb,
51 .disable = vc4_crtc_disable,
52 .enable = vc4_crtc_enable,
53 + .mode_fixup = vc4_crtc_mode_fixup,
54 .atomic_check = vc4_crtc_atomic_check,
55 .atomic_flush = vc4_crtc_atomic_flush,
57 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
58 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
59 @@ -219,10 +219,35 @@ vc4_hdmi_connector_best_encoder(struct d
60 return hdmi_connector->encoder;
64 + * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to
65 + * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it
66 + * screws up vblank timestamping for interlaced modes, so fix it up.
68 +static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector,
69 + uint32_t maxX, uint32_t maxY)
71 + struct drm_display_mode *mode;
74 + count = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
78 + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n",
79 + connector->base.id, connector->name);
80 + list_for_each_entry(mode, &connector->modes, head) {
81 + drm_mode_set_crtcinfo(mode, 0);
82 + drm_mode_debug_printmodeline(mode);
88 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
89 .dpms = drm_atomic_helper_connector_dpms,
90 .detect = vc4_hdmi_connector_detect,
91 - .fill_modes = drm_helper_probe_single_connector_modes,
92 + .fill_modes = vc4_hdmi_connector_probe_modes,
93 .destroy = vc4_hdmi_connector_destroy,
94 .reset = drm_atomic_helper_connector_reset,
95 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
96 @@ -258,7 +283,7 @@ static struct drm_connector *vc4_hdmi_co
97 connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
98 DRM_CONNECTOR_POLL_DISCONNECT);
100 - connector->interlace_allowed = 0;
101 + connector->interlace_allowed = 1;
102 connector->doublescan_allowed = 0;
104 drm_mode_connector_attach_encoder(connector, encoder);