aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Peng <peng.li@linux.intel.com>2009-11-08 23:51:22 -0500
committerEric Anholt <eric@anholt.net>2009-12-01 13:27:40 -0500
commit778c902640530371a169ad1c03566e7c51b09874 (patch)
tree4230fb7e4f79e00931c1efcf2b88cfec285ae7ff
parent27dfaf4f5825a119305db1bc63bef30ed400e376 (diff)
drm/i915: Fix sync to vblank when VGA output is turned off
In current vblank-wait implementation, if we turn off VGA output, drm_wait_vblank will still wait on the disabled pipe until timeout, because vblank on the pipe is assumed be enabled. This would cause slow system response on some system such as moblin. This patch resolve the issue by adding a drm helper function drm_vblank_off which explicitly clear vblank_enabled[crtc], wake up any waiting queue and save last vblank counter before turning off crtc. It also slightly change drm_vblank_get to ensure that we will will return immediately if trying to wait on a disabled pipe. Signed-off-by: Li Peng <peng.li@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> [anholt: hand-applied for conflicts with overlay changes] Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/drm_irq.c34
-rw-r--r--drivers/gpu/drm/i915/intel_display.c1
-rw-r--r--include/drm/drmP.h1
3 files changed, 28 insertions, 8 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 6b3ce6d38848..7998ee66b317 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -429,15 +429,21 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
429 429
430 spin_lock_irqsave(&dev->vbl_lock, irqflags); 430 spin_lock_irqsave(&dev->vbl_lock, irqflags);
431 /* Going from 0->1 means we have to enable interrupts again */ 431 /* Going from 0->1 means we have to enable interrupts again */
432 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 && 432 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
433 !dev->vblank_enabled[crtc]) { 433 if (!dev->vblank_enabled[crtc]) {
434 ret = dev->driver->enable_vblank(dev, crtc); 434 ret = dev->driver->enable_vblank(dev, crtc);
435 DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); 435 DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
436 if (ret) 436 if (ret)
437 atomic_dec(&dev->vblank_refcount[crtc]);
438 else {
439 dev->vblank_enabled[crtc] = 1;
440 drm_update_vblank_count(dev, crtc);
441 }
442 }
443 } else {
444 if (!dev->vblank_enabled[crtc]) {
437 atomic_dec(&dev->vblank_refcount[crtc]); 445 atomic_dec(&dev->vblank_refcount[crtc]);
438 else { 446 ret = -EINVAL;
439 dev->vblank_enabled[crtc] = 1;
440 drm_update_vblank_count(dev, crtc);
441 } 447 }
442 } 448 }
443 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 449 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -464,6 +470,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
464} 470}
465EXPORT_SYMBOL(drm_vblank_put); 471EXPORT_SYMBOL(drm_vblank_put);
466 472
473void drm_vblank_off(struct drm_device *dev, int crtc)
474{
475 unsigned long irqflags;
476
477 spin_lock_irqsave(&dev->vbl_lock, irqflags);
478 DRM_WAKEUP(&dev->vbl_queue[crtc]);
479 dev->vblank_enabled[crtc] = 0;
480 dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
481 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
482}
483EXPORT_SYMBOL(drm_vblank_off);
484
467/** 485/**
468 * drm_vblank_pre_modeset - account for vblanks across mode sets 486 * drm_vblank_pre_modeset - account for vblanks across mode sets
469 * @dev: DRM device 487 * @dev: DRM device
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 267adc6fbfc1..65b76fffd9e3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1924,6 +1924,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
1924 1924
1925 /* Give the overlay scaler a chance to disable if it's on this pipe */ 1925 /* Give the overlay scaler a chance to disable if it's on this pipe */
1926 intel_crtc_dpms_overlay(intel_crtc, false); 1926 intel_crtc_dpms_overlay(intel_crtc, false);
1927 drm_vblank_off(dev, pipe);
1927 1928
1928 if (dev_priv->cfb_plane == plane && 1929 if (dev_priv->cfb_plane == plane &&
1929 dev_priv->display.disable_fbc) 1930 dev_priv->display.disable_fbc)
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index febf6c530c66..fd919959d146 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1288,6 +1288,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
1288extern void drm_handle_vblank(struct drm_device *dev, int crtc); 1288extern void drm_handle_vblank(struct drm_device *dev, int crtc);
1289extern int drm_vblank_get(struct drm_device *dev, int crtc); 1289extern int drm_vblank_get(struct drm_device *dev, int crtc);
1290extern void drm_vblank_put(struct drm_device *dev, int crtc); 1290extern void drm_vblank_put(struct drm_device *dev, int crtc);
1291extern void drm_vblank_off(struct drm_device *dev, int crtc);
1291extern void drm_vblank_cleanup(struct drm_device *dev); 1292extern void drm_vblank_cleanup(struct drm_device *dev);
1292/* Modesetting support */ 1293/* Modesetting support */
1293extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); 1294extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);