drm/i915/tv: Fix adjusted_mode dotclock for interlaced modes
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 29 Jan 2019 14:19:12 +0000 (16:19 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 29 Jan 2019 21:26:39 +0000 (23:26 +0200)
intel_tv_mode_to_mode() assumes the pipe will be in progressive
fetch mode, and thus when programming the pipe into interlaced
mode we have to halve the calculated dotclock to get the correct
field duration.

This becomes more important when we start to program the pipe
into interlaced mode on i965gm as we depend on the timestamps
to get accurate frame counter values. Withot halving the clock
our guesstimated frame counter would tick at twice the expected
speed.

Cc: Imre Deak <imre.deak@intel.com>
Fixes: 690157f0a9e7 ("drm/i915/tv: Fix >1024 modes on gen3")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190129141913.5515-1-ville.syrjala@linux.intel.com
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_tv.c

index 751b88dde18e0b3d7b403d5159674ddb870c64d7..3a5682f44e555f17978b5ec331a6c5de3add92d9 100644 (file)
@@ -1150,6 +1150,8 @@ intel_tv_get_config(struct intel_encoder *encoder,
                                 ypos, mode.vdisplay - ysize - ypos);
 
        adjusted_mode->crtc_clock = mode.clock;
+       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+               adjusted_mode->crtc_clock /= 2;
 
        /* pixel counter doesn't work on i965gm TV output */
        if (IS_I965GM(dev_priv))
@@ -1214,8 +1216,11 @@ intel_tv_compute_config(struct intel_encoder *encoder,
 
                tv_conn_state->bypass_vfilter = true;
 
-               if (!tv_mode->progressive)
+               if (!tv_mode->progressive) {
+                       adjusted_mode->clock /= 2;
+                       adjusted_mode->crtc_clock /= 2;
                        adjusted_mode->flags |= DRM_MODE_FLAG_INTERLACE;
+               }
        } else {
                tv_conn_state->margins.top = conn_state->tv.margins.top;
                tv_conn_state->margins.bottom = conn_state->tv.margins.bottom;