OSDN Git Service

Reinstate dev->vblank_enabled[].
authorMichel Dänzer <michel@tungstengraphics.com>
Mon, 21 Jul 2008 09:48:04 +0000 (11:48 +0200)
committerMichel Dänzer <michel@tungstengraphics.com>
Mon, 21 Jul 2008 09:48:04 +0000 (11:48 +0200)
I incorrectly thought it was obsolete.

linux-core/drmP.h
linux-core/drm_irq.c

index 6e4d6dd..19168cd 100644 (file)
@@ -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;
 
index 7c05611..d0d6f98 100644 (file)
@@ -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);