diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 56 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 |
2 files changed, 43 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a72e635a88b8..ed30a5ec2f3d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -751,6 +751,34 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) /* raw reads, only for fast reads of display block, no need for forcewake etc. */ #define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__)) +static int __intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + const struct drm_display_mode *mode = &crtc->config.adjusted_mode; + enum pipe pipe = crtc->pipe; + int vtotal = mode->crtc_vtotal; + int position; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vtotal /= 2; + + if (IS_GEN2(dev)) + position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; + else + position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; + + /* + * Scanline counter increments at leading edge of hsync, and + * it starts counting from vtotal-1 on the first active line. + * That means the scanline counter value is always one less + * than what we would expect. Ie. just after start of vblank, + * which also occurs at start of hsync (on the last active line), + * the scanline counter will read vblank_start-1. + */ + return (position + 1) % vtotal; +} + static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) @@ -802,20 +830,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, /* No obvious pixelcount register. Only query vertical * scanout position from Display scan line register. */ - if (IS_GEN2(dev)) - position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; - else - position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; - - /* - * Scanline counter increments at leading edge of hsync, and - * it starts counting from vtotal-1 on the first active line. - * That means the scanline counter value is always one less - * than what we would expect. Ie. just after start of vblank, - * which also occurs at start of hsync (on the last active line), - * the scanline counter will read vblank_start-1. - */ - position = (position + 1) % vtotal; + position = __intel_get_crtc_scanline(intel_crtc); } else { /* Have access to pixelcount since start of frame. * We can split this into vertical and horizontal @@ -876,6 +891,19 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, return ret; } +int intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + unsigned long irqflags; + int position; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + position = __intel_get_crtc_scanline(crtc); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + return position; +} + static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, int *max_error, struct timeval *vblank_time, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bc777056a767..96ae78d0e975 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -653,6 +653,7 @@ void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void intel_runtime_pm_disable_interrupts(struct drm_device *dev); void intel_runtime_pm_restore_interrupts(struct drm_device *dev); +int intel_get_crtc_scanline(struct intel_crtc *crtc); /* intel_crt.c */ |