[PATCH 1/4] drm/i915: fixup interlaced vertical timings confusion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

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.

On gen2 we only support interlaced through dvo add-ons. The
corresponding mode_fixup wants vertical timings in fields, so use that
unconditionally.

There are a few other place that demand vertical timings in fields
but never actually deal with interlaced modes (like panels), so use
frame timings for consistency, too.

That leaves us with native TV out support: I honestly have no clue
what this needs, but suspect that it simply ignores the pipe's timing
and uses the special TV timings (which are per-field). These are
programmed with fixed timing informations out of a pre-defined list of
struct tv_mode.

After all this we also have to fix-up the interlaced timing
adjustements and substract 2 half-lines (instead of 1 with the halfed
timings). According to Peter Ross, this is actually what Windows does.

Patch is completely untested because I don't have a TV. So please go
wild.

Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c |   35 ++++++++++++++++++---------------
 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 -
 5 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index de26748..be078cb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3425,10 +3425,13 @@ 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)
+	/* gen2 needs vertical crtc timing information in fields because that's
+	 * what dvo outputs want - the chip itself can't do interlaced. All
+	 * later generations can do interlaced natively and want timings in
+	 * full frames. */
+	if (IS_GEN2(dev))
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+	else
 		drm_mode_set_crtcinfo(adjusted_mode, 0);
 
 	return true;
@@ -5369,12 +5372,12 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
 		/* the chip adds 2 halflines automatically */
-		adjusted_mode->crtc_vdisplay -= 1;
-		adjusted_mode->crtc_vtotal -= 1;
-		adjusted_mode->crtc_vblank_start -= 1;
-		adjusted_mode->crtc_vblank_end -= 1;
-		adjusted_mode->crtc_vsync_end -= 1;
-		adjusted_mode->crtc_vsync_start -= 1;
+		adjusted_mode->crtc_vdisplay -= 2;
+		adjusted_mode->crtc_vtotal -= 2;
+		adjusted_mode->crtc_vblank_start -= 2;
+		adjusted_mode->crtc_vblank_end -= 2;
+		adjusted_mode->crtc_vsync_end -= 2;
+		adjusted_mode->crtc_vsync_start -= 2;
 	} else
 		pipeconf |= PIPECONF_PROGRESSIVE;
 
@@ -5962,12 +5965,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
 		/* the chip adds 2 halflines automatically */
-		adjusted_mode->crtc_vdisplay -= 1;
-		adjusted_mode->crtc_vtotal -= 1;
-		adjusted_mode->crtc_vblank_start -= 1;
-		adjusted_mode->crtc_vblank_end -= 1;
-		adjusted_mode->crtc_vsync_end -= 1;
-		adjusted_mode->crtc_vsync_start -= 1;
+		adjusted_mode->crtc_vdisplay -= 2;
+		adjusted_mode->crtc_vtotal -= 2;
+		adjusted_mode->crtc_vblank_start -= 2;
+		adjusted_mode->crtc_vblank_end -= 2;
+		adjusted_mode->crtc_vsync_end -= 2;
+		adjusted_mode->crtc_vsync_start -= 2;
 	} else
 		pipeconf |= PIPECONF_PROGRESSIVE;
 
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 6eda1b5..020a7d7 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 cdf17d4..aac74ec 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -263,7 +263,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 c935cda..230a141 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 e334ec3..5b480bb 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;
 }
 
-- 
1.7.7.5



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux