vblank: Don't wait or update the counter while the CRTC is supposedly disabled.
Without kernel modesetting, this requires cooperation of the userspace modesetting driver. We may have to leave the vblank interrupt enabled otherwise to avoid problems.main
parent
237172b767
commit
ba7263b8c2
|
@ -843,6 +843,7 @@ struct drm_device {
|
||||||
int *vblank_enabled; /* so we don't call enable more than
|
int *vblank_enabled; /* so we don't call enable more than
|
||||||
once per disable */
|
once per disable */
|
||||||
u32 *vblank_premodeset; /* for compensation of spurious wraparounds */
|
u32 *vblank_premodeset; /* for compensation of spurious wraparounds */
|
||||||
|
int *vblank_suspend; /* Don't wait while crtc is likely disabled */
|
||||||
struct timer_list vblank_disable_timer;
|
struct timer_list vblank_disable_timer;
|
||||||
|
|
||||||
u32 max_vblank_count; /**< size of vblank counter register */
|
u32 max_vblank_count; /**< size of vblank counter register */
|
||||||
|
|
|
@ -112,6 +112,8 @@ static void drm_vblank_cleanup(struct drm_device *dev)
|
||||||
DRM_MEM_DRIVER);
|
DRM_MEM_DRIVER);
|
||||||
drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
|
drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
|
||||||
dev->num_crtcs, DRM_MEM_DRIVER);
|
dev->num_crtcs, DRM_MEM_DRIVER);
|
||||||
|
drm_free(dev->vblank_suspend, sizeof(*dev->vblank_suspend) *
|
||||||
|
dev->num_crtcs, DRM_MEM_DRIVER);
|
||||||
|
|
||||||
dev->num_crtcs = 0;
|
dev->num_crtcs = 0;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +162,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
||||||
if (!dev->vblank_premodeset)
|
if (!dev->vblank_premodeset)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
dev->vblank_suspend = drm_calloc(num_crtcs, sizeof(int),
|
||||||
|
DRM_MEM_DRIVER);
|
||||||
|
if (!dev->vblank_suspend)
|
||||||
|
goto err;
|
||||||
|
|
||||||
/* Zero per-crtc vblank stuff */
|
/* Zero per-crtc vblank stuff */
|
||||||
for (i = 0; i < num_crtcs; i++) {
|
for (i = 0; i < num_crtcs; i++) {
|
||||||
init_waitqueue_head(&dev->vbl_queue[i]);
|
init_waitqueue_head(&dev->vbl_queue[i]);
|
||||||
|
@ -343,6 +350,9 @@ void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
u32 cur_vblank, diff;
|
u32 cur_vblank, diff;
|
||||||
|
|
||||||
|
if (dev->vblank_suspend[crtc])
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interrupts were disabled prior to this call, so deal with counter
|
* Interrupts were disabled prior to this call, so deal with counter
|
||||||
* wrap if needed.
|
* wrap if needed.
|
||||||
|
@ -435,7 +445,6 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||||
{
|
{
|
||||||
struct drm_modeset_ctl *modeset = data;
|
struct drm_modeset_ctl *modeset = data;
|
||||||
int crtc, ret = 0;
|
int crtc, ret = 0;
|
||||||
u32 new;
|
|
||||||
|
|
||||||
crtc = modeset->crtc;
|
crtc = modeset->crtc;
|
||||||
if (crtc >= dev->num_crtcs) {
|
if (crtc >= dev->num_crtcs) {
|
||||||
|
@ -447,9 +456,11 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||||
case _DRM_PRE_MODESET:
|
case _DRM_PRE_MODESET:
|
||||||
dev->vblank_premodeset[crtc] =
|
dev->vblank_premodeset[crtc] =
|
||||||
dev->driver->get_vblank_counter(dev, crtc);
|
dev->driver->get_vblank_counter(dev, crtc);
|
||||||
|
dev->vblank_suspend[crtc] = 1;
|
||||||
break;
|
break;
|
||||||
case _DRM_POST_MODESET:
|
case _DRM_POST_MODESET:
|
||||||
new = dev->driver->get_vblank_counter(dev, crtc);
|
if (dev->vblank_suspend[crtc]) {
|
||||||
|
u32 new = dev->driver->get_vblank_counter(dev, crtc);
|
||||||
|
|
||||||
/* Compensate for spurious wraparound */
|
/* Compensate for spurious wraparound */
|
||||||
if (new < dev->vblank_premodeset[crtc]) {
|
if (new < dev->vblank_premodeset[crtc]) {
|
||||||
|
@ -462,6 +473,8 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||||
crtc, dev->max_vblank_count + new -
|
crtc, dev->max_vblank_count + new -
|
||||||
dev->vblank_premodeset[crtc]);
|
dev->vblank_premodeset[crtc]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
dev->vblank_suspend[crtc] = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -538,6 +551,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||||
struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
|
struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
|
||||||
struct drm_vbl_sig *vbl_sig;
|
struct drm_vbl_sig *vbl_sig;
|
||||||
|
|
||||||
|
if (dev->vblank_suspend[crtc])
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||||
|
|
||||||
/* Check if this task has already scheduled the same signal
|
/* Check if this task has already scheduled the same signal
|
||||||
|
@ -589,15 +605,15 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||||
|
|
||||||
vblwait->reply.sequence = seq;
|
vblwait->reply.sequence = seq;
|
||||||
} else {
|
} else {
|
||||||
unsigned long cur_vblank;
|
if (!dev->vblank_suspend[crtc]) {
|
||||||
|
|
||||||
ret = drm_vblank_get(dev, crtc);
|
ret = drm_vblank_get(dev, crtc);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
|
DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
|
||||||
(((cur_vblank = drm_vblank_count(dev, crtc))
|
((drm_vblank_count(dev, crtc)
|
||||||
- vblwait->request.sequence) <= (1 << 23)));
|
- vblwait->request.sequence) <= (1 << 23)));
|
||||||
drm_vblank_put(dev, crtc);
|
drm_vblank_put(dev, crtc);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret != -EINTR) {
|
if (ret != -EINTR) {
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
@ -606,7 +622,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||||
|
|
||||||
vblwait->reply.tval_sec = now.tv_sec;
|
vblwait->reply.tval_sec = now.tv_sec;
|
||||||
vblwait->reply.tval_usec = now.tv_usec;
|
vblwait->reply.tval_usec = now.tv_usec;
|
||||||
vblwait->reply.sequence = cur_vblank;
|
vblwait->reply.sequence = drm_vblank_count(dev, crtc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue