summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_irq.c18
2 files changed, 17 insertions, 3 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 6e4d6dda..19168cd7 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -848,6 +848,8 @@ struct drm_device {
atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */
u32 *last_vblank; /* protected by dev->vbl_lock, used */
/* for wraparound handling */
+ int *vblank_enabled; /* so we don't call enable more than
+ once per disable */
int *vblank_inmodeset; /* Display driver is setting mode */
struct timer_list vblank_disable_timer;
diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c
index 7c056114..d0d6f987 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -82,11 +82,13 @@ static void vblank_disable_fn(unsigned long arg)
for (i = 0; i < dev->num_crtcs; i++) {
spin_lock_irqsave(&dev->vbl_lock, irqflags);
- if (atomic_read(&dev->vblank_refcount[i]) == 0) {
+ if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
+ dev->vblank_enabled[i]) {
DRM_DEBUG("disabling vblank on crtc %d\n", i);
dev->last_vblank[i] =
dev->driver->get_vblank_counter(dev, i);
dev->driver->disable_vblank(dev, i);
+ dev->vblank_enabled[i] = 0;
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
@@ -110,6 +112,8 @@ static void drm_vblank_cleanup(struct drm_device *dev)
dev->num_crtcs, DRM_MEM_DRIVER);
drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
dev->num_crtcs, DRM_MEM_DRIVER);
+ drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
+ dev->num_crtcs, DRM_MEM_DRIVER);
drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
DRM_MEM_DRIVER);
drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
@@ -148,6 +152,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
if (!dev->vblank_refcount)
goto err;
+ dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
+ DRM_MEM_DRIVER);
+ if (!dev->vblank_enabled)
+ goto err;
+
dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
if (!dev->last_vblank)
goto err;
@@ -387,12 +396,15 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* Going from 0->1 means we have to enable interrupts again */
- if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
+ if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
+ !dev->vblank_enabled[crtc]) {
ret = dev->driver->enable_vblank(dev, crtc);
if (ret)
atomic_dec(&dev->vblank_refcount[crtc]);
- else
+ else {
+ dev->vblank_enabled[crtc] = 1;
drm_update_vblank_count(dev, crtc);
+ }
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);