diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 1d3756d3176ce58656999f8103a98e6256f9b2a5..55923d00bd52a78b534a842795d65b9e4ff71c8a 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -3386,6 +3386,7 @@ void (*disable_vblank) (struct drm_device *dev, int crtc);
by scheduling a timer. The delay is accessible through the vblankoffdelay
module parameter or the drm_vblank_offdelay global
variable and expressed in milliseconds. Its default value is 5000 ms.
+ Zero means never disable, and a negative value means disable immediately.
When a vertical blanking interrupt occurs drivers only need to call the
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 92bc6b1d96463e9d260cf808407ab84b9947fd4e..db03e16ca81723c5cd92472d22912f945c15a81b 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -39,7 +39,7 @@
unsigned int drm_debug = 0; /* 1 to enable debug output */
EXPORT_SYMBOL(drm_debug);
-unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
+int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
@@ -53,7 +53,7 @@ MODULE_AUTHOR(CORE_AUTHOR);
MODULE_DESCRIPTION(CORE_DESC);
MODULE_LICENSE("GPL and additional rights");
MODULE_PARM_DESC(debug, "Enable debug output");
-MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
+MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index b2428cb0c64d1895f406404a1fdedba3f9842a7d..99145c4d536ba653a178b37f6ed35e8c21310c81 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -993,10 +993,13 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
BUG_ON(atomic_read(&vblank->refcount) == 0);
/* Last user schedules interrupt disable */
- if (atomic_dec_and_test(&vblank->refcount) &&
- (drm_vblank_offdelay > 0))
- mod_timer(&vblank->disable_timer,
- jiffies + ((drm_vblank_offdelay * HZ)/1000));
+ if (atomic_dec_and_test(&vblank->refcount)) {
+ if (drm_vblank_offdelay < 0)
+ vblank_disable_fn((unsigned long)vblank);
+ else if (drm_vblank_offdelay > 0)
+ mod_timer(&vblank->disable_timer,
+ jiffies + ((drm_vblank_offdelay * HZ)/1000));
+ }
}
EXPORT_SYMBOL(drm_vblank_put);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index a576463820862a305a308ca2d5ddff2c61f08bad..24b32d453c60da7a855614a1798a3c7b884c5f16 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1345,7 +1345,7 @@ extern void drm_put_dev(struct drm_device *dev);
extern void drm_unplug_dev(struct drm_device *dev);
extern unsigned int drm_debug;
-extern unsigned int drm_vblank_offdelay;
+extern int drm_vblank_offdelay;
extern unsigned int drm_timestamp_precision;
extern unsigned int drm_timestamp_monotonic;