aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-08-08 05:15:59 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-09-07 06:13:00 -0400
commit52e68630d13f9668f8f4dd6978fa41039bacfaf6 (patch)
treeca2b2b88d5f09592c35553b1802f6c8c6204ac5a
parentc96c3a8cb7fadcb33d9a5ebe35fcee8b7d0a7946 (diff)
drm/i915: Fix offset page-flips on i965+
i965 uses the Display Registers to compute the offset from the display base so the new base does not need adjusting when flipping. The older chipsets use a fence to access the display and so do perceive the surface as linear and have a single base register which is reprogrammed using the flip. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Reported-by: Marty Jack <martyj19@comcast.net> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c67
1 files changed, 48 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3fc767bcbaa0..334665cbe7df 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5042,9 +5042,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
5042 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 5042 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
5043 struct intel_unpin_work *work; 5043 struct intel_unpin_work *work;
5044 unsigned long flags, offset; 5044 unsigned long flags, offset;
5045 int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; 5045 int pipe = intel_crtc->pipe;
5046 int ret, pipesrc; 5046 u32 pf, pipesrc;
5047 u32 flip_mask; 5047 int ret;
5048 5048
5049 work = kzalloc(sizeof *work, GFP_KERNEL); 5049 work = kzalloc(sizeof *work, GFP_KERNEL);
5050 if (work == NULL) 5050 if (work == NULL)
@@ -5093,12 +5093,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
5093 atomic_inc(&obj_priv->pending_flip); 5093 atomic_inc(&obj_priv->pending_flip);
5094 work->pending_flip_obj = obj; 5094 work->pending_flip_obj = obj;
5095 5095
5096 if (intel_crtc->plane)
5097 flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
5098 else
5099 flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
5100
5101 if (IS_GEN3(dev) || IS_GEN2(dev)) { 5096 if (IS_GEN3(dev) || IS_GEN2(dev)) {
5097 u32 flip_mask;
5098
5099 if (intel_crtc->plane)
5100 flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
5101 else
5102 flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
5103
5102 BEGIN_LP_RING(2); 5104 BEGIN_LP_RING(2);
5103 OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); 5105 OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
5104 OUT_RING(0); 5106 OUT_RING(0);
@@ -5106,29 +5108,56 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
5106 } 5108 }
5107 5109
5108 /* Offset into the new buffer for cases of shared fbs between CRTCs */ 5110 /* Offset into the new buffer for cases of shared fbs between CRTCs */
5109 offset = obj_priv->gtt_offset; 5111 offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
5110 offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8);
5111 5112
5112 BEGIN_LP_RING(4); 5113 BEGIN_LP_RING(4);
5113 if (IS_I965G(dev)) { 5114 switch(INTEL_INFO(dev)->gen) {
5115 case 2:
5114 OUT_RING(MI_DISPLAY_FLIP | 5116 OUT_RING(MI_DISPLAY_FLIP |
5115 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); 5117 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
5116 OUT_RING(fb->pitch); 5118 OUT_RING(fb->pitch);
5117 OUT_RING(offset | obj_priv->tiling_mode); 5119 OUT_RING(obj_priv->gtt_offset + offset);
5118 pipesrc = I915_READ(pipesrc_reg); 5120 OUT_RING(MI_NOOP);
5119 OUT_RING(pipesrc & 0x0fff0fff); 5121 break;
5120 } else if (IS_GEN3(dev)) { 5122
5123 case 3:
5121 OUT_RING(MI_DISPLAY_FLIP_I915 | 5124 OUT_RING(MI_DISPLAY_FLIP_I915 |
5122 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); 5125 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
5123 OUT_RING(fb->pitch); 5126 OUT_RING(fb->pitch);
5124 OUT_RING(offset); 5127 OUT_RING(obj_priv->gtt_offset + offset);
5125 OUT_RING(MI_NOOP); 5128 OUT_RING(MI_NOOP);
5126 } else { 5129 break;
5130
5131 case 4:
5132 case 5:
5133 /* i965+ uses the linear or tiled offsets from the
5134 * Display Registers (which do not change across a page-flip)
5135 * so we need only reprogram the base address.
5136 */
5127 OUT_RING(MI_DISPLAY_FLIP | 5137 OUT_RING(MI_DISPLAY_FLIP |
5128 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); 5138 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
5129 OUT_RING(fb->pitch); 5139 OUT_RING(fb->pitch);
5130 OUT_RING(offset); 5140 OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
5131 OUT_RING(MI_NOOP); 5141
5142 /* XXX Enabling the panel-fitter across page-flip is so far
5143 * untested on non-native modes, so ignore it for now.
5144 * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
5145 */
5146 pf = 0;
5147 pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
5148 OUT_RING(pf | pipesrc);
5149 break;
5150
5151 case 6:
5152 OUT_RING(MI_DISPLAY_FLIP |
5153 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
5154 OUT_RING(fb->pitch | obj_priv->tiling_mode);
5155 OUT_RING(obj_priv->gtt_offset);
5156
5157 pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
5158 pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
5159 OUT_RING(pf | pipesrc);
5160 break;
5132 } 5161 }
5133 ADVANCE_LP_RING(); 5162 ADVANCE_LP_RING();
5134 5163