aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c79
1 files changed, 39 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index fb4801c7d9e4..17d8fcb1b6f7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -621,36 +621,15 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
621#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__)) 621#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
622#define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__)) 622#define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__))
623 623
624static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe) 624static bool ilk_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
625{ 625{
626 struct drm_i915_private *dev_priv = dev->dev_private; 626 struct drm_i915_private *dev_priv = dev->dev_private;
627 uint32_t status; 627 uint32_t status;
628 int reg;
629 628
630 if (IS_VALLEYVIEW(dev)) { 629 if (INTEL_INFO(dev)->gen < 7) {
631 status = pipe == PIPE_A ?
632 I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
633 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
634
635 reg = VLV_ISR;
636 } else if (IS_GEN2(dev)) {
637 status = pipe == PIPE_A ?
638 I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
639 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
640
641 reg = ISR;
642 } else if (INTEL_INFO(dev)->gen < 5) {
643 status = pipe == PIPE_A ?
644 I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
645 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
646
647 reg = ISR;
648 } else if (INTEL_INFO(dev)->gen < 7) {
649 status = pipe == PIPE_A ? 630 status = pipe == PIPE_A ?
650 DE_PIPEA_VBLANK : 631 DE_PIPEA_VBLANK :
651 DE_PIPEB_VBLANK; 632 DE_PIPEB_VBLANK;
652
653 reg = DEISR;
654 } else { 633 } else {
655 switch (pipe) { 634 switch (pipe) {
656 default: 635 default:
@@ -664,14 +643,9 @@ static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
664 status = DE_PIPEC_VBLANK_IVB; 643 status = DE_PIPEC_VBLANK_IVB;
665 break; 644 break;
666 } 645 }
667
668 reg = DEISR;
669 } 646 }
670 647
671 if (IS_GEN2(dev)) 648 return __raw_i915_read32(dev_priv, DEISR) & status;
672 return __raw_i915_read16(dev_priv, reg) & status;
673 else
674 return __raw_i915_read32(dev_priv, reg) & status;
675} 649}
676 650
677static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, 651static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
@@ -729,17 +703,42 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
729 else 703 else
730 position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; 704 position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
731 705
732 /* 706 if (HAS_PCH_SPLIT(dev)) {
733 * The scanline counter increments at the leading edge 707 /*
734 * of hsync, ie. it completely misses the active portion 708 * The scanline counter increments at the leading edge
735 * of the line. Fix up the counter at both edges of vblank 709 * of hsync, ie. it completely misses the active portion
736 * to get a more accurate picture whether we're in vblank 710 * of the line. Fix up the counter at both edges of vblank
737 * or not. 711 * to get a more accurate picture whether we're in vblank
738 */ 712 * or not.
739 in_vbl = intel_pipe_in_vblank_locked(dev, pipe); 713 */
740 if ((in_vbl && position == vbl_start - 1) || 714 in_vbl = ilk_pipe_in_vblank_locked(dev, pipe);
741 (!in_vbl && position == vbl_end - 1)) 715 if ((in_vbl && position == vbl_start - 1) ||
742 position = (position + 1) % vtotal; 716 (!in_vbl && position == vbl_end - 1))
717 position = (position + 1) % vtotal;
718 } else {
719 /*
720 * ISR vblank status bits don't work the way we'd want
721 * them to work on non-PCH platforms (for
722 * ilk_pipe_in_vblank_locked()), and there doesn't
723 * appear any other way to determine if we're currently
724 * in vblank.
725 *
726 * Instead let's assume that we're already in vblank if
727 * we got called from the vblank interrupt and the
728 * scanline counter value indicates that we're on the
729 * line just prior to vblank start. This should result
730 * in the correct answer, unless the vblank interrupt
731 * delivery really got delayed for almost exactly one
732 * full frame/field.
733 */
734 if (flags & DRM_CALLED_FROM_VBLIRQ &&
735 position == vbl_start - 1) {
736 position = (position + 1) % vtotal;
737
738 /* Signal this correction as "applied". */
739 ret |= 0x8;
740 }
741 }
743 } else { 742 } else {
744 /* Have access to pixelcount since start of frame. 743 /* Have access to pixelcount since start of frame.
745 * We can split this into vertical and horizontal 744 * We can split this into vertical and horizontal