|
@@ -429,15 +429,21 @@ 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 &&
|
|
|
- !dev->vblank_enabled[crtc]) {
|
|
|
- ret = dev->driver->enable_vblank(dev, crtc);
|
|
|
- DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
|
|
|
- if (ret)
|
|
|
+ if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
|
|
|
+ if (!dev->vblank_enabled[crtc]) {
|
|
|
+ ret = dev->driver->enable_vblank(dev, crtc);
|
|
|
+ DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
|
|
|
+ if (ret)
|
|
|
+ atomic_dec(&dev->vblank_refcount[crtc]);
|
|
|
+ else {
|
|
|
+ dev->vblank_enabled[crtc] = 1;
|
|
|
+ drm_update_vblank_count(dev, crtc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (!dev->vblank_enabled[crtc]) {
|
|
|
atomic_dec(&dev->vblank_refcount[crtc]);
|
|
|
- else {
|
|
|
- dev->vblank_enabled[crtc] = 1;
|
|
|
- drm_update_vblank_count(dev, crtc);
|
|
|
+ ret = -EINVAL;
|
|
|
}
|
|
|
}
|
|
|
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
|
@@ -464,6 +470,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_vblank_put);
|
|
|
|
|
|
+void drm_vblank_off(struct drm_device *dev, int crtc)
|
|
|
+{
|
|
|
+ unsigned long irqflags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
|
|
+ DRM_WAKEUP(&dev->vbl_queue[crtc]);
|
|
|
+ dev->vblank_enabled[crtc] = 0;
|
|
|
+ dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
|
|
|
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(drm_vblank_off);
|
|
|
+
|
|
|
/**
|
|
|
* drm_vblank_pre_modeset - account for vblanks across mode sets
|
|
|
* @dev: DRM device
|