diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-08-08 05:15:59 -0400 |
|---|---|---|
| committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-07 06:13:00 -0400 |
| commit | 52e68630d13f9668f8f4dd6978fa41039bacfaf6 (patch) | |
| tree | ca2b2b88d5f09592c35553b1802f6c8c6204ac5a | |
| parent | c96c3a8cb7fadcb33d9a5ebe35fcee8b7d0a7946 (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.c | 67 |
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 | ||
