From ca9bfa7eed20ea34e862804e62aae10eb159edbb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 28 Jan 2012 14:49:20 +0100 Subject: [PATCH] drm/i915: fixup interlaced vertical timings confusion, part 1 We have a pretty decent confusion about vertical timings of interlaced modes. Peter Ross has written a patch that makes interlace modes work on a lot more platforms/output combinations by doubling the vertical timings. The issue with that patch is that core drm _does_ support specifying whether we want these vertical timings in fields or frames, we just haven't managed to consistently use this facility. The relavant function is drm_mode_set_crtcinfo, which fills in the crtc timing information. The first thing to note is that the drm core keeps interlaced modes in frames, but displays modelines in fields. So when the crtc modeset helper copies over the mode into adjusted_mode it will already contain vertical timings in half-frames. The result is that the fixup code in intel_crtc_mode_fixup doesn't actually do anything (in most cases at least). Now gen3+ natively supports interlaced modes and wants the vertical timings in frames. Which is what sdvo already fixes up, at least under some conditions. There are a few other place that demand vertical timings in fields but never actually deal with interlaced modes, so use frame timings for consistency, too. These are: - lvds panel, - dvo encoders - dvo is the only way gen2 could support interlaced mode, but currently we don't support any encoders that do. - tv out - despite that the tv dac sends out an interlaced signal it expects a progressive mode pipe configuration. All these encoders enforce progressive modes by resetting interlace_allowed. Hence we always want crtc vertical timings in frames. Enforce this in our crtc mode_fixup function and rip out any redudant timing computations from the encoders' mode_fixup function. v2-4: Adjust the vertical timings a bit. v5: Split out the 'subtract-one for interlaced' fixes. v6: Clarify issues around tv-out and gen2. Reviewed-by: Eugeni Dodonov Reviewed-by: Paulo Zanoni Tested-by: Paulo Zanoni Tested-by: Christopher Egert Tested-by: Alfonso Fiore Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 7 ++----- drivers/gpu/drm/i915/intel_dvo.c | 1 - drivers/gpu/drm/i915/intel_overlay.c | 2 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 1 - drivers/gpu/drm/i915/intel_tv.c | 2 +- 6 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index efe56a2c4f4b..41d4e82f412a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3437,11 +3437,8 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, return false; } - /* XXX some encoders set the crtcinfo, others don't. - * Obviously we need some form of conflict resolution here... - */ - if (adjusted_mode->crtc_htotal == 0) - drm_mode_set_crtcinfo(adjusted_mode, 0); + /* All interlaced capable intel hw wants timings in frames. */ + drm_mode_set_crtcinfo(adjusted_mode, 0); return true; } diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 6eda1b51c636..020a7d7f744d 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -157,7 +157,6 @@ static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, C(vsync_end); C(vtotal); C(clock); - drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); #undef C } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 23a543cdfa99..5542e9006f96 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -264,7 +264,7 @@ i830_activate_pipe_a(struct drm_device *dev) DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n"); mode = drm_mode_duplicate(dev, &vesa_640x480); - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + drm_mode_set_crtcinfo(mode, 0); if (!drm_crtc_helper_set_mode(&crtc->base, mode, crtc->base.x, crtc->base.y, crtc->base.fb)) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index c935cdaa2154..230a141dbea3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -48,7 +48,7 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, adjusted_mode->clock = fixed_mode->clock; - drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); + drm_mode_set_crtcinfo(adjusted_mode, 0); } /* adjusted_mode has been preset to be the panel's fixed mode */ diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e334ec33a47d..5b480bbad68c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -944,7 +944,6 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); - drm_mode_set_crtcinfo(adjusted_mode, 0); return true; } diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 1571be37ce3e..05f765ef5464 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1240,7 +1240,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) int type; mode = reported_modes[0]; - drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); + drm_mode_set_crtcinfo(&mode, 0); if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) { type = intel_tv_detect_type(intel_tv, connector);