aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2009-09-15 16:57:36 -0400
committerEric Anholt <eric@anholt.net>2009-11-05 17:47:09 -0500
commit5a5a0c64a99d7542c48c99d1a8bbb49e665842be (patch)
treef915bb581b83247df2bc508d899dd379455119e1
parent240a2d12dfff98f8fa1332dc8424284d96f0801e (diff)
drm/i915: implement fastpath for overlay flip waiting
As long as the gpu can keep up, neither the cpu (waiting for gpu) nore the gpu (waiting for vblank to do an overlay flip) stalls. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c4
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c43
4 files changed, 41 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ce03fd5b3f5b..fd6362ea865c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -808,6 +808,9 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
808int i915_gem_do_init(struct drm_device *dev, unsigned long start, 808int i915_gem_do_init(struct drm_device *dev, unsigned long start,
809 unsigned long end); 809 unsigned long end);
810int i915_gem_idle(struct drm_device *dev); 810int i915_gem_idle(struct drm_device *dev);
811uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
812 uint32_t flush_domains);
813int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible);
811int i915_lp_ring_sync(struct drm_device *dev); 814int i915_lp_ring_sync(struct drm_device *dev);
812int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 815int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
813int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, 816int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 7d1e9adf0f4c..5e579a41b6ad 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1583,7 +1583,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
1583 * 1583 *
1584 * Returned sequence numbers are nonzero on success. 1584 * Returned sequence numbers are nonzero on success.
1585 */ 1585 */
1586static uint32_t 1586uint32_t
1587i915_add_request(struct drm_device *dev, struct drm_file *file_priv, 1587i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
1588 uint32_t flush_domains) 1588 uint32_t flush_domains)
1589{ 1589{
@@ -1820,7 +1820,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
1820 mutex_unlock(&dev->struct_mutex); 1820 mutex_unlock(&dev->struct_mutex);
1821} 1821}
1822 1822
1823static int 1823int
1824i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) 1824i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
1825{ 1825{
1826 drm_i915_private_t *dev_priv = dev->dev_private; 1826 drm_i915_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c9b1b97ab792..5b503cb793ba 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -126,7 +126,9 @@ struct intel_overlay {
126 u32 flip_addr; 126 u32 flip_addr;
127 struct drm_i915_gem_object *reg_bo; 127 struct drm_i915_gem_object *reg_bo;
128 void *virt_addr; 128 void *virt_addr;
129 /* flip handling */
129 int hw_wedged; 130 int hw_wedged;
131 uint32_t last_flip_req;
130}; 132};
131 133
132struct intel_crtc { 134struct intel_crtc {
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 4e88abb423b0..85e07e4459ce 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -251,7 +251,6 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
251 drm_i915_private_t *dev_priv = dev->dev_private; 251 drm_i915_private_t *dev_priv = dev->dev_private;
252 u32 flip_addr = overlay->flip_addr; 252 u32 flip_addr = overlay->flip_addr;
253 u32 tmp; 253 u32 tmp;
254 int ret;
255 RING_LOCALS; 254 RING_LOCALS;
256 255
257 BUG_ON(!overlay->active); 256 BUG_ON(!overlay->active);
@@ -264,11 +263,40 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
264 if (tmp & (1 << 17)) 263 if (tmp & (1 << 17))
265 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); 264 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
266 265
267 BEGIN_LP_RING(6); 266 BEGIN_LP_RING(4);
268 OUT_RING(MI_FLUSH); 267 OUT_RING(MI_FLUSH);
269 OUT_RING(MI_NOOP); 268 OUT_RING(MI_NOOP);
270 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); 269 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
271 OUT_RING(flip_addr); 270 OUT_RING(flip_addr);
271 ADVANCE_LP_RING();
272
273 overlay->last_flip_req = i915_add_request(dev, NULL, 0);
274}
275
276static int intel_overlay_wait_flip(struct intel_overlay *overlay)
277{
278 struct drm_device *dev = overlay->dev;
279 drm_i915_private_t *dev_priv = dev->dev_private;
280 int ret;
281 u32 tmp;
282 RING_LOCALS;
283
284 if (overlay->last_flip_req != 0) {
285 ret = i915_do_wait_request(dev, overlay->last_flip_req, 0);
286
287 if (ret != 0)
288 return ret;
289
290 overlay->last_flip_req = 0;
291
292 tmp = I915_READ(ISR);
293
294 if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT))
295 return 0;
296 }
297
298 /* synchronous slowpath */
299 BEGIN_LP_RING(2);
272 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 300 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
273 OUT_RING(MI_NOOP); 301 OUT_RING(MI_NOOP);
274 ADVANCE_LP_RING(); 302 ADVANCE_LP_RING();
@@ -279,13 +307,8 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
279 DRM_ERROR("intel overlay: ring sync failed, hw likely wedged\n"); 307 DRM_ERROR("intel overlay: ring sync failed, hw likely wedged\n");
280 overlay->hw_wedged = 1; 308 overlay->hw_wedged = 1;
281 } 309 }
282}
283 310
284static int intel_overlay_wait_flip(struct intel_overlay *overlay) 311 return ret;
285{
286 /* don't overcomplicate things for now with asynchronous operations
287 * see comment above */
288 return 0;
289} 312}
290 313
291/* overlay needs to be disabled in OCMD reg */ 314/* overlay needs to be disabled in OCMD reg */
@@ -344,7 +367,9 @@ static int intel_overlay_off(struct intel_overlay *overlay)
344 return ret; 367 return ret;
345} 368}
346 369
347/* wait for pending overlay flip and release old frame */ 370/* Wait for pending overlay flip and release old frame.
371 * Needs to be called before the overlay register are changed
372 * via intel_overlay_(un)map_regs_atomic */
348static int intel_overlay_release_old_vid(struct intel_overlay *overlay) 373static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
349{ 374{
350 int ret; 375 int ret;