aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2014-04-29 06:35:45 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-05-05 03:09:26 -0400
commita225f0795714efbbd1b558e1be4dc368d038e105 (patch)
tree4a3fdf6b09f93c4a3ec845b0bb2b8b2bd6cc9181
parent78e8fc6b2e3bbce6170d2ead2406d29930077735 (diff)
drm/i915: Add intel_get_crtc_scanline()
Add a new function intel_get_crtc_scanline() that returns the current scanline counter for the crtc. v2: Rebase after vblank timestamp changes. Use intel_ prefix instead of i915_ as is more customary for display related functions. Include DRM_SCANOUTPOS_INVBL in the return value even w/o adjustments, for a bit of extra consistency. v3: Change the implementation to be based on DSL on all gens, since that's enough for the needs of atomic updates, and it will avoid complicating the scanout position calculations for the vblank timestamps v4: Don't break scanline wraparound for interlaced modes Reviewed-by: Sourab Gupta <sourabgupta@gmail.com> Reviewed-by: Akash Goel <akash.goels@gmail.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c56
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
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)
751/* raw reads, only for fast reads of display block, no need for forcewake etc. */ 751/* raw reads, only for fast reads of display block, no need for forcewake etc. */
752#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__)) 752#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
753 753
754static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
755{
756 struct drm_device *dev = crtc->base.dev;
757 struct drm_i915_private *dev_priv = dev->dev_private;
758 const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
759 enum pipe pipe = crtc->pipe;
760 int vtotal = mode->crtc_vtotal;
761 int position;
762
763 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
764 vtotal /= 2;
765
766 if (IS_GEN2(dev))
767 position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
768 else
769 position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
770
771 /*
772 * Scanline counter increments at leading edge of hsync, and
773 * it starts counting from vtotal-1 on the first active line.
774 * That means the scanline counter value is always one less
775 * than what we would expect. Ie. just after start of vblank,
776 * which also occurs at start of hsync (on the last active line),
777 * the scanline counter will read vblank_start-1.
778 */
779 return (position + 1) % vtotal;
780}
781
754static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, 782static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
755 unsigned int flags, int *vpos, int *hpos, 783 unsigned int flags, int *vpos, int *hpos,
756 ktime_t *stime, ktime_t *etime) 784 ktime_t *stime, ktime_t *etime)
@@ -802,20 +830,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
802 /* No obvious pixelcount register. Only query vertical 830 /* No obvious pixelcount register. Only query vertical
803 * scanout position from Display scan line register. 831 * scanout position from Display scan line register.
804 */ 832 */
805 if (IS_GEN2(dev)) 833 position = __intel_get_crtc_scanline(intel_crtc);
806 position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
807 else
808 position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
809
810 /*
811 * Scanline counter increments at leading edge of hsync, and
812 * it starts counting from vtotal-1 on the first active line.
813 * That means the scanline counter value is always one less
814 * than what we would expect. Ie. just after start of vblank,
815 * which also occurs at start of hsync (on the last active line),
816 * the scanline counter will read vblank_start-1.
817 */
818 position = (position + 1) % vtotal;
819 } else { 834 } else {
820 /* Have access to pixelcount since start of frame. 835 /* Have access to pixelcount since start of frame.
821 * We can split this into vertical and horizontal 836 * We can split this into vertical and horizontal
@@ -876,6 +891,19 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
876 return ret; 891 return ret;
877} 892}
878 893
894int intel_get_crtc_scanline(struct intel_crtc *crtc)
895{
896 struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
897 unsigned long irqflags;
898 int position;
899
900 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
901 position = __intel_get_crtc_scanline(crtc);
902 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
903
904 return position;
905}
906
879static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, 907static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
880 int *max_error, 908 int *max_error,
881 struct timeval *vblank_time, 909 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);
653void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); 653void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
654void intel_runtime_pm_disable_interrupts(struct drm_device *dev); 654void intel_runtime_pm_disable_interrupts(struct drm_device *dev);
655void intel_runtime_pm_restore_interrupts(struct drm_device *dev); 655void intel_runtime_pm_restore_interrupts(struct drm_device *dev);
656int intel_get_crtc_scanline(struct intel_crtc *crtc);
656 657
657 658
658/* intel_crt.c */ 659/* intel_crt.c */