drm/i915: correctly program the VSYNCSHIFT register
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Sat, 28 Jan 2012 13:49:24 +0000 (14:49 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 10 Feb 2012 16:28:46 +0000 (17:28 +0100)
The hw seems to use this to correctly insert the required delay
before/after an even/odd interlaced field. This might also explain
why we need to substract 1 half-line from vtotal - if the hw just
adds the delay programmend in VSYNCSHIFT the total frame time would be
about that too long.

These registers seems to only exist on gen4 and later. For paranoia
also program it to 0 for progressive modes, but according to
documentation the hw should just ignore it in this case.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Tested-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Tested-by: Alfonso Fiore <alfonso.fiore@gmail.com>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c

index 3369f829f46f257b058973a906d1e4347416350a..7eabdf056afb526310936e68b236a831b72cc7fd 100644 (file)
 #define _VSYNC_A               0x60014
 #define _PIPEASRC      0x6001c
 #define _BCLRPAT_A     0x60020
+#define _VSYNCSHIFT_A  0x60028
 
 /* Pipe B timing regs */
 #define _HTOTAL_B      0x61000
 #define _VSYNC_B               0x61014
 #define _PIPEBSRC      0x6101c
 #define _BCLRPAT_B     0x61020
+#define _VSYNCSHIFT_B  0x61028
+
 
 #define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B)
 #define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B)
 #define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B)
 #define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B)
 #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
+#define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
 
 /* VGA port control */
 #define ADPA                   0x61100
 #define _TRANS_VSYNC_A           0xe0014
 #define  TRANS_VSYNC_END_SHIFT  16
 #define  TRANS_VSYNC_START_SHIFT 0
+#define _TRANS_VSYNCSHIFT_A    0xe0028
 
 #define _TRANSA_DATA_M1          0xe0030
 #define _TRANSA_DATA_N1          0xe0034
 #define _TRANS_VTOTAL_B          0xe100c
 #define _TRANS_VBLANK_B          0xe1010
 #define _TRANS_VSYNC_B           0xe1014
+#define _TRANS_VSYNCSHIFT_B     0xe1028
 
 #define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B)
 #define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B)
 #define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B)
 #define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B)
 #define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B)
+#define TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _TRANS_VSYNCSHIFT_A, \
+                                    _TRANS_VSYNCSHIFT_B)
 
 #define _TRANSB_DATA_M1          0xe1030
 #define _TRANSB_DATA_N1          0xe1034
index 1fde35d536083163ee6411c200bc0a4de432d741..34c63459c4841bf709bf7b045f1807eb17ad9350 100644 (file)
@@ -2973,6 +2973,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe)));
        I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));
        I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe)));
+       I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));
 
        intel_fdi_normal_train(crtc);
 
@@ -5103,7 +5104,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        int plane = intel_crtc->plane;
        int refclk, num_connectors = 0;
        intel_clock_t clock, reduced_clock;
-       u32 dpll, dspcntr, pipeconf;
+       u32 dpll, dspcntr, pipeconf, vsyncshift;
        bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
        bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
        struct drm_mode_config *mode_config = &dev->mode_config;
@@ -5391,8 +5392,15 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                /* the chip adds 2 halflines automatically */
                adjusted_mode->crtc_vtotal -= 1;
                adjusted_mode->crtc_vblank_end -= 1;
-       } else
+               vsyncshift = adjusted_mode->crtc_hsync_start
+                            - adjusted_mode->crtc_htotal/2;
+       } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
+               vsyncshift = 0;
+       }
+
+       if (!IS_GEN3(dev))
+               I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);
 
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
@@ -5980,8 +5988,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                /* the chip adds 2 halflines automatically */
                adjusted_mode->crtc_vtotal -= 1;
                adjusted_mode->crtc_vblank_end -= 1;
-       } else
+               I915_WRITE(VSYNCSHIFT(pipe),
+                          adjusted_mode->crtc_hsync_start
+                          - adjusted_mode->crtc_htotal/2);
+       } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
+               I915_WRITE(VSYNCSHIFT(pipe), 0);
+       }
 
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |