aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2013-09-25 12:55:26 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-11 17:41:55 -0400
commit391f75e2bf13f105d9e4a120736ccdd8e3bc638b (patch)
tree6ffaec31b1004d07d7a0438af692840664a7a6ea /drivers/gpu/drm/i915/i915_irq.c
parent0632fef669912a63c99c8ce4c2ca10c6ea04f0df (diff)
drm/i915: Fix pre-CTG vblank counter
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>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c36
1 files 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)
526 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 526 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
527 unsigned long high_frame; 527 unsigned long high_frame;
528 unsigned long low_frame; 528 unsigned long low_frame;
529 u32 high1, high2, low; 529 u32 high1, high2, low, pixel, vbl_start;
530 530
531 if (!i915_pipe_enabled(dev, pipe)) { 531 if (!i915_pipe_enabled(dev, pipe)) {
532 DRM_DEBUG_DRIVER("trying to get vblank count for disabled " 532 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)
534 return 0; 534 return 0;
535 } 535 }
536 536
537 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
538 struct intel_crtc *intel_crtc =
539 to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
540 const struct drm_display_mode *mode =
541 &intel_crtc->config.adjusted_mode;
542
543 vbl_start = mode->crtc_vblank_start * mode->crtc_htotal;
544 } else {
545 enum transcoder cpu_transcoder =
546 intel_pipe_to_cpu_transcoder(dev_priv, pipe);
547 u32 htotal;
548
549 htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1;
550 vbl_start = (I915_READ(VBLANK(cpu_transcoder)) & 0x1fff) + 1;
551
552 vbl_start *= htotal;
553 }
554
537 high_frame = PIPEFRAME(pipe); 555 high_frame = PIPEFRAME(pipe);
538 low_frame = PIPEFRAMEPIXEL(pipe); 556 low_frame = PIPEFRAMEPIXEL(pipe);
539 557
@@ -544,13 +562,20 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
544 */ 562 */
545 do { 563 do {
546 high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; 564 high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
547 low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK; 565 low = I915_READ(low_frame);
548 high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; 566 high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
549 } while (high1 != high2); 567 } while (high1 != high2);
550 568
551 high1 >>= PIPE_FRAME_HIGH_SHIFT; 569 high1 >>= PIPE_FRAME_HIGH_SHIFT;
570 pixel = low & PIPE_PIXEL_MASK;
552 low >>= PIPE_FRAME_LOW_SHIFT; 571 low >>= PIPE_FRAME_LOW_SHIFT;
553 return (high1 << 8) | low; 572
573 /*
574 * The frame counter increments at beginning of active.
575 * Cook up a vblank counter by also checking the pixel
576 * counter against vblank start.
577 */
578 return ((high1 << 8) | low) + (pixel >= vbl_start);
554} 579}
555 580
556static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) 581static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
@@ -3155,11 +3180,12 @@ void intel_irq_init(struct drm_device *dev)
3155 3180
3156 pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); 3181 pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
3157 3182
3158 dev->driver->get_vblank_counter = i915_get_vblank_counter;
3159 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
3160 if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { 3183 if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
3161 dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ 3184 dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
3162 dev->driver->get_vblank_counter = gm45_get_vblank_counter; 3185 dev->driver->get_vblank_counter = gm45_get_vblank_counter;
3186 } else {
3187 dev->driver->get_vblank_counter = i915_get_vblank_counter;
3188 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
3163 } 3189 }
3164 3190
3165 if (drm_core_check_feature(dev, DRIVER_MODESET)) 3191 if (drm_core_check_feature(dev, DRIVER_MODESET))