| From b48f9c9e051f2629ce67a21d6c8bb67bbd627674 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> |
| Date: Wed, 25 Sep 2013 19:55:26 +0300 |
| Subject: drm/i915: Fix pre-CTG vblank counter |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| The old style frame counter increments at the start of active video. |
| However for i915_get_vblank_counter() we want a counter that increments |
| at the start of vblank. |
| |
| Fortunately the low frame counter register also contains the pixel |
| counter for the current frame. We can can compare that against the |
| vblank start pixel count to determine if we need to increment the |
| frame counter by 1 to get the correct answer. |
| |
| Also reorganize the function pointer assignments in intel_irq_init() a |
| bit to avoid confusing people. |
| |
| Cc: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> |
| Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| (cherry picked from commit 391f75e2bf13f105d9e4a120736ccdd8e3bc638b) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/i915_irq.c | 36 +++++++++++++++++++++++++++++++----- |
| 1 file changed, 31 insertions(+), 5 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c |
| index 36279202ddc0..1f91e1a8bfd1 100644 |
| --- a/drivers/gpu/drm/i915/i915_irq.c |
| +++ b/drivers/gpu/drm/i915/i915_irq.c |
| @@ -526,7 +526,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) |
| drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| unsigned long high_frame; |
| unsigned long low_frame; |
| - u32 high1, high2, low; |
| + u32 high1, high2, low, pixel, vbl_start; |
| |
| if (!i915_pipe_enabled(dev, pipe)) { |
| DRM_DEBUG_DRIVER("trying to get vblank count for disabled " |
| @@ -534,6 +534,24 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) |
| return 0; |
| } |
| |
| + if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| + struct intel_crtc *intel_crtc = |
| + to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
| + const struct drm_display_mode *mode = |
| + &intel_crtc->config.adjusted_mode; |
| + |
| + vbl_start = mode->crtc_vblank_start * mode->crtc_htotal; |
| + } else { |
| + enum transcoder cpu_transcoder = |
| + intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
| + u32 htotal; |
| + |
| + htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1; |
| + vbl_start = (I915_READ(VBLANK(cpu_transcoder)) & 0x1fff) + 1; |
| + |
| + vbl_start *= htotal; |
| + } |
| + |
| high_frame = PIPEFRAME(pipe); |
| low_frame = PIPEFRAMEPIXEL(pipe); |
| |
| @@ -544,13 +562,20 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) |
| */ |
| do { |
| high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; |
| - low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK; |
| + low = I915_READ(low_frame); |
| high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; |
| } while (high1 != high2); |
| |
| high1 >>= PIPE_FRAME_HIGH_SHIFT; |
| + pixel = low & PIPE_PIXEL_MASK; |
| low >>= PIPE_FRAME_LOW_SHIFT; |
| - return (high1 << 8) | low; |
| + |
| + /* |
| + * The frame counter increments at beginning of active. |
| + * Cook up a vblank counter by also checking the pixel |
| + * counter against vblank start. |
| + */ |
| + return ((high1 << 8) | low) + (pixel >= vbl_start); |
| } |
| |
| static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) |
| @@ -3155,11 +3180,12 @@ void intel_irq_init(struct drm_device *dev) |
| |
| pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); |
| |
| - dev->driver->get_vblank_counter = i915_get_vblank_counter; |
| - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
| if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { |
| dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ |
| dev->driver->get_vblank_counter = gm45_get_vblank_counter; |
| + } else { |
| + dev->driver->get_vblank_counter = i915_get_vblank_counter; |
| + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
| } |
| |
| if (drm_core_check_feature(dev, DRIVER_MODESET)) |
| -- |
| 1.8.5.rc3 |
| |