drm: Collect per-crtc vblank stuff to a struct

drm_vblank_init() is too ugly. Make it a bit easier on the eye by
collecting all the per-crtc vblank counters, timestamps etc. to
a structure and just allocate an array of those.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Ville Syrjälä 2013-10-04 14:53:36 +03:00 коммит произвёл Dave Airlie
Родитель bf507d90cf
Коммит 5380e9293b
6 изменённых файлов: 81 добавлений и 119 удалений

Просмотреть файл

@ -163,13 +163,13 @@ int drm_vblank_info(struct seq_file *m, void *data)
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
for (crtc = 0; crtc < dev->num_crtcs; crtc++) { for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
seq_printf(m, "CRTC %d enable: %d\n", seq_printf(m, "CRTC %d enable: %d\n",
crtc, atomic_read(&dev->vblank_refcount[crtc])); crtc, atomic_read(&dev->vblank[crtc].refcount));
seq_printf(m, "CRTC %d counter: %d\n", seq_printf(m, "CRTC %d counter: %d\n",
crtc, drm_vblank_count(dev, crtc)); crtc, drm_vblank_count(dev, crtc));
seq_printf(m, "CRTC %d last wait: %d\n", seq_printf(m, "CRTC %d last wait: %d\n",
crtc, dev->last_vblank_wait[crtc]); crtc, dev->vblank[crtc].last_wait);
seq_printf(m, "CRTC %d in modeset: %d\n", seq_printf(m, "CRTC %d in modeset: %d\n",
crtc, dev->vblank_inmodeset[crtc]); crtc, dev->vblank[crtc].inmodeset);
} }
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return 0; return 0;

Просмотреть файл

@ -43,9 +43,8 @@
#include <linux/export.h> #include <linux/export.h>
/* Access macro for slots in vblank timestamp ringbuffer. */ /* Access macro for slots in vblank timestamp ringbuffer. */
#define vblanktimestamp(dev, crtc, count) ( \ #define vblanktimestamp(dev, crtc, count) \
(dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE])
((count) % DRM_VBLANKTIME_RBSIZE)])
/* Retry timestamp calculation up to 3 times to satisfy /* Retry timestamp calculation up to 3 times to satisfy
* drm_timestamp_precision before giving up. * drm_timestamp_precision before giving up.
@ -89,8 +88,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
*/ */
static void clear_vblank_timestamps(struct drm_device *dev, int crtc) static void clear_vblank_timestamps(struct drm_device *dev, int crtc)
{ {
memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0, memset(dev->vblank[crtc].time, 0, sizeof(dev->vblank[crtc].time));
DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval));
} }
/* /*
@ -115,7 +113,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
spin_lock_irqsave(&dev->vblank_time_lock, irqflags); spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
dev->driver->disable_vblank(dev, crtc); dev->driver->disable_vblank(dev, crtc);
dev->vblank_enabled[crtc] = false; dev->vblank[crtc].enabled = false;
/* No further vblank irq's will be processed after /* No further vblank irq's will be processed after
* this point. Get current hardware vblank count and * this point. Get current hardware vblank count and
@ -130,9 +128,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
* delayed gpu counter increment. * delayed gpu counter increment.
*/ */
do { do {
dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); dev->vblank[crtc].last = dev->driver->get_vblank_counter(dev, crtc);
vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
} while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); } while (dev->vblank[crtc].last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc);
if (!count) if (!count)
vblrc = 0; vblrc = 0;
@ -140,7 +138,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
/* Compute time difference to stored timestamp of last vblank /* Compute time difference to stored timestamp of last vblank
* as updated by last invocation of drm_handle_vblank() in vblank irq. * as updated by last invocation of drm_handle_vblank() in vblank irq.
*/ */
vblcount = atomic_read(&dev->_vblank_count[crtc]); vblcount = atomic_read(&dev->vblank[crtc].count);
diff_ns = timeval_to_ns(&tvblank) - diff_ns = timeval_to_ns(&tvblank) -
timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
@ -157,7 +155,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
* hope for the best. * hope for the best.
*/ */
if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) {
atomic_inc(&dev->_vblank_count[crtc]); atomic_inc(&dev->vblank[crtc].count);
smp_mb__after_atomic_inc(); smp_mb__after_atomic_inc();
} }
@ -178,8 +176,8 @@ static void vblank_disable_fn(unsigned long arg)
for (i = 0; i < dev->num_crtcs; i++) { for (i = 0; i < dev->num_crtcs; i++) {
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
if (atomic_read(&dev->vblank_refcount[i]) == 0 && if (atomic_read(&dev->vblank[i].refcount) == 0 &&
dev->vblank_enabled[i]) { dev->vblank[i].enabled) {
DRM_DEBUG("disabling vblank on crtc %d\n", i); DRM_DEBUG("disabling vblank on crtc %d\n", i);
vblank_disable_and_save(dev, i); vblank_disable_and_save(dev, i);
} }
@ -197,14 +195,7 @@ void drm_vblank_cleanup(struct drm_device *dev)
vblank_disable_fn((unsigned long)dev); vblank_disable_fn((unsigned long)dev);
kfree(dev->vbl_queue); kfree(dev->vblank);
kfree(dev->_vblank_count);
kfree(dev->vblank_refcount);
kfree(dev->vblank_enabled);
kfree(dev->last_vblank);
kfree(dev->last_vblank_wait);
kfree(dev->vblank_inmodeset);
kfree(dev->_vblank_time);
dev->num_crtcs = 0; dev->num_crtcs = 0;
} }
@ -221,40 +212,12 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
dev->num_crtcs = num_crtcs; dev->num_crtcs = num_crtcs;
dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL);
GFP_KERNEL); if (!dev->vblank)
if (!dev->vbl_queue)
goto err; goto err;
dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL); for (i = 0; i < num_crtcs; i++)
if (!dev->_vblank_count) init_waitqueue_head(&dev->vblank[i].queue);
goto err;
dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs,
GFP_KERNEL);
if (!dev->vblank_refcount)
goto err;
dev->vblank_enabled = kcalloc(num_crtcs, sizeof(bool), GFP_KERNEL);
if (!dev->vblank_enabled)
goto err;
dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
if (!dev->last_vblank)
goto err;
dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
if (!dev->last_vblank_wait)
goto err;
dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
if (!dev->vblank_inmodeset)
goto err;
dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE,
sizeof(struct timeval), GFP_KERNEL);
if (!dev->_vblank_time)
goto err;
DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n");
@ -264,13 +227,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
else else
DRM_INFO("No driver support for vblank timestamp query.\n"); DRM_INFO("No driver support for vblank timestamp query.\n");
/* Zero per-crtc vblank stuff */
for (i = 0; i < num_crtcs; i++) {
init_waitqueue_head(&dev->vbl_queue[i]);
atomic_set(&dev->_vblank_count[i], 0);
atomic_set(&dev->vblank_refcount[i], 0);
}
dev->vblank_disable_allowed = false; dev->vblank_disable_allowed = false;
return 0; return 0;
@ -411,9 +367,9 @@ int drm_irq_uninstall(struct drm_device *dev)
if (dev->num_crtcs) { if (dev->num_crtcs) {
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
for (i = 0; i < dev->num_crtcs; i++) { for (i = 0; i < dev->num_crtcs; i++) {
DRM_WAKEUP(&dev->vbl_queue[i]); DRM_WAKEUP(&dev->vblank[i].queue);
dev->vblank_enabled[i] = false; dev->vblank[i].enabled = false;
dev->last_vblank[i] = dev->vblank[i].last =
dev->driver->get_vblank_counter(dev, i); dev->driver->get_vblank_counter(dev, i);
} }
spin_unlock_irqrestore(&dev->vbl_lock, irqflags); spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@ -796,7 +752,7 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp);
*/ */
u32 drm_vblank_count(struct drm_device *dev, int crtc) u32 drm_vblank_count(struct drm_device *dev, int crtc)
{ {
return atomic_read(&dev->_vblank_count[crtc]); return atomic_read(&dev->vblank[crtc].count);
} }
EXPORT_SYMBOL(drm_vblank_count); EXPORT_SYMBOL(drm_vblank_count);
@ -825,10 +781,10 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
* a seqlock. * a seqlock.
*/ */
do { do {
cur_vblank = atomic_read(&dev->_vblank_count[crtc]); cur_vblank = atomic_read(&dev->vblank[crtc].count);
*vblanktime = vblanktimestamp(dev, crtc, cur_vblank); *vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
smp_rmb(); smp_rmb();
} while (cur_vblank != atomic_read(&dev->_vblank_count[crtc])); } while (cur_vblank != atomic_read(&dev->vblank[crtc].count));
return cur_vblank; return cur_vblank;
} }
@ -915,12 +871,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
} while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
/* Deal with counter wrap */ /* Deal with counter wrap */
diff = cur_vblank - dev->last_vblank[crtc]; diff = cur_vblank - dev->vblank[crtc].last;
if (cur_vblank < dev->last_vblank[crtc]) { if (cur_vblank < dev->vblank[crtc].last) {
diff += dev->max_vblank_count; diff += dev->max_vblank_count;
DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
crtc, dev->last_vblank[crtc], cur_vblank, diff); crtc, dev->vblank[crtc].last, cur_vblank, diff);
} }
DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
@ -931,12 +887,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
* reinitialize delayed at next vblank interrupt in that case. * reinitialize delayed at next vblank interrupt in that case.
*/ */
if (rc) { if (rc) {
tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; tslot = atomic_read(&dev->vblank[crtc].count) + diff;
vblanktimestamp(dev, crtc, tslot) = t_vblank; vblanktimestamp(dev, crtc, tslot) = t_vblank;
} }
smp_mb__before_atomic_inc(); smp_mb__before_atomic_inc();
atomic_add(diff, &dev->_vblank_count[crtc]); atomic_add(diff, &dev->vblank[crtc].count);
smp_mb__after_atomic_inc(); smp_mb__after_atomic_inc();
} }
@ -958,9 +914,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* Going from 0->1 means we have to enable interrupts again */ /* 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[crtc].refcount) == 1) {
spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
if (!dev->vblank_enabled[crtc]) { if (!dev->vblank[crtc].enabled) {
/* Enable vblank irqs under vblank_time_lock protection. /* Enable vblank irqs under vblank_time_lock protection.
* All vblank count & timestamp updates are held off * All vblank count & timestamp updates are held off
* until we are done reinitializing master counter and * until we are done reinitializing master counter and
@ -971,16 +927,16 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n",
crtc, ret); crtc, ret);
if (ret) if (ret)
atomic_dec(&dev->vblank_refcount[crtc]); atomic_dec(&dev->vblank[crtc].refcount);
else { else {
dev->vblank_enabled[crtc] = true; dev->vblank[crtc].enabled = true;
drm_update_vblank_count(dev, crtc); drm_update_vblank_count(dev, crtc);
} }
} }
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
} else { } else {
if (!dev->vblank_enabled[crtc]) { if (!dev->vblank[crtc].enabled) {
atomic_dec(&dev->vblank_refcount[crtc]); atomic_dec(&dev->vblank[crtc].refcount);
ret = -EINVAL; ret = -EINVAL;
} }
} }
@ -1000,10 +956,10 @@ EXPORT_SYMBOL(drm_vblank_get);
*/ */
void drm_vblank_put(struct drm_device *dev, int crtc) void drm_vblank_put(struct drm_device *dev, int crtc)
{ {
BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
/* Last user schedules interrupt disable */ /* Last user schedules interrupt disable */
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
(drm_vblank_offdelay > 0)) (drm_vblank_offdelay > 0))
mod_timer(&dev->vblank_disable_timer, mod_timer(&dev->vblank_disable_timer,
jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000));
@ -1026,7 +982,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
vblank_disable_and_save(dev, crtc); vblank_disable_and_save(dev, crtc);
DRM_WAKEUP(&dev->vbl_queue[crtc]); DRM_WAKEUP(&dev->vblank[crtc].queue);
/* Send any queued vblank events, lest the natives grow disquiet */ /* Send any queued vblank events, lest the natives grow disquiet */
seq = drm_vblank_count_and_time(dev, crtc, &now); seq = drm_vblank_count_and_time(dev, crtc, &now);
@ -1068,10 +1024,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
* to avoid corrupting the count if multiple, mismatch calls occur), * to avoid corrupting the count if multiple, mismatch calls occur),
* so that interrupts remain enabled in the interim. * so that interrupts remain enabled in the interim.
*/ */
if (!dev->vblank_inmodeset[crtc]) { if (!dev->vblank[crtc].inmodeset) {
dev->vblank_inmodeset[crtc] = 0x1; dev->vblank[crtc].inmodeset = 0x1;
if (drm_vblank_get(dev, crtc) == 0) if (drm_vblank_get(dev, crtc) == 0)
dev->vblank_inmodeset[crtc] |= 0x2; dev->vblank[crtc].inmodeset |= 0x2;
} }
} }
EXPORT_SYMBOL(drm_vblank_pre_modeset); EXPORT_SYMBOL(drm_vblank_pre_modeset);
@ -1084,15 +1040,15 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
if (!dev->num_crtcs) if (!dev->num_crtcs)
return; return;
if (dev->vblank_inmodeset[crtc]) { if (dev->vblank[crtc].inmodeset) {
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
dev->vblank_disable_allowed = true; dev->vblank_disable_allowed = true;
spin_unlock_irqrestore(&dev->vbl_lock, irqflags); spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
if (dev->vblank_inmodeset[crtc] & 0x2) if (dev->vblank[crtc].inmodeset & 0x2)
drm_vblank_put(dev, crtc); drm_vblank_put(dev, crtc);
dev->vblank_inmodeset[crtc] = 0; dev->vblank[crtc].inmodeset = 0;
} }
} }
EXPORT_SYMBOL(drm_vblank_post_modeset); EXPORT_SYMBOL(drm_vblank_post_modeset);
@ -1289,8 +1245,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
DRM_DEBUG("waiting on vblank count %d, crtc %d\n", DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
vblwait->request.sequence, crtc); vblwait->request.sequence, crtc);
dev->last_vblank_wait[crtc] = vblwait->request.sequence; dev->vblank[crtc].last_wait = vblwait->request.sequence;
DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ,
(((drm_vblank_count(dev, crtc) - (((drm_vblank_count(dev, crtc) -
vblwait->request.sequence) <= (1 << 23)) || vblwait->request.sequence) <= (1 << 23)) ||
!dev->irq_enabled)); !dev->irq_enabled));
@ -1368,7 +1324,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
spin_lock_irqsave(&dev->vblank_time_lock, irqflags); spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
/* Vblank irq handling disabled. Nothing to do. */ /* Vblank irq handling disabled. Nothing to do. */
if (!dev->vblank_enabled[crtc]) { if (!dev->vblank[crtc].enabled) {
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
return false; return false;
} }
@ -1378,7 +1334,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
*/ */
/* Get current timestamp and count. */ /* Get current timestamp and count. */
vblcount = atomic_read(&dev->_vblank_count[crtc]); vblcount = atomic_read(&dev->vblank[crtc].count);
drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
/* Compute time difference to timestamp of last vblank */ /* Compute time difference to timestamp of last vblank */
@ -1402,14 +1358,14 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
* the timestamp computed above. * the timestamp computed above.
*/ */
smp_mb__before_atomic_inc(); smp_mb__before_atomic_inc();
atomic_inc(&dev->_vblank_count[crtc]); atomic_inc(&dev->vblank[crtc].count);
smp_mb__after_atomic_inc(); smp_mb__after_atomic_inc();
} else { } else {
DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
crtc, (int) diff_ns); crtc, (int) diff_ns);
} }
DRM_WAKEUP(&dev->vbl_queue[crtc]); DRM_WAKEUP(&dev->vblank[crtc].queue);
drm_handle_vblank_events(dev, crtc); drm_handle_vblank_events(dev, crtc);
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);

Просмотреть файл

@ -271,15 +271,15 @@ void psb_irq_preinstall(struct drm_device *dev)
if (gma_power_is_on(dev)) if (gma_power_is_on(dev))
PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
if (dev->vblank_enabled[0]) if (dev->vblank[0].enabled)
dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
if (dev->vblank_enabled[1]) if (dev->vblank[1].enabled)
dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
/* FIXME: Handle Medfield irq mask /* FIXME: Handle Medfield irq mask
if (dev->vblank_enabled[1]) if (dev->vblank[1].enabled)
dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
if (dev->vblank_enabled[2]) if (dev->vblank[2].enabled)
dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
*/ */
@ -305,17 +305,17 @@ int psb_irq_postinstall(struct drm_device *dev)
PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
if (dev->vblank_enabled[0]) if (dev->vblank[0].enabled)
psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
else else
psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
if (dev->vblank_enabled[1]) if (dev->vblank[1].enabled)
psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
else else
psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
if (dev->vblank_enabled[2]) if (dev->vblank[2].enabled)
psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
else else
psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
@ -339,13 +339,13 @@ void psb_irq_uninstall(struct drm_device *dev)
PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
if (dev->vblank_enabled[0]) if (dev->vblank[0].enabled)
psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
if (dev->vblank_enabled[1]) if (dev->vblank[1].enabled)
psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
if (dev->vblank_enabled[2]) if (dev->vblank[2].enabled)
psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
@ -456,7 +456,7 @@ static int psb_vblank_do_wait(struct drm_device *dev,
{ {
unsigned int cur_vblank; unsigned int cur_vblank;
int ret = 0; int ret = 0;
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, DRM_WAIT_ON(ret, dev->vblank.queue, 3 * DRM_HZ,
(((cur_vblank = atomic_read(counter)) (((cur_vblank = atomic_read(counter))
- *sequence) <= (1 << 23))); - *sequence) <= (1 << 23)));
*sequence = cur_vblank; *sequence = cur_vblank;

Просмотреть файл

@ -5340,7 +5340,7 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
for_each_pipe(p) for_each_pipe(p)
if (p != PIPE_A) if (p != PIPE_A)
dev->last_vblank[p] = 0; dev->vblank[p].last = 0;
spin_unlock_irqrestore(&dev->vbl_lock, irqflags); spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
} }
} }

Просмотреть файл

@ -307,9 +307,9 @@ int omap_drm_irq_uninstall(struct drm_device *dev)
if (dev->num_crtcs) { if (dev->num_crtcs) {
spin_lock_irqsave(&dev->vbl_lock, irqflags); spin_lock_irqsave(&dev->vbl_lock, irqflags);
for (i = 0; i < dev->num_crtcs; i++) { for (i = 0; i < dev->num_crtcs; i++) {
DRM_WAKEUP(&dev->vbl_queue[i]); DRM_WAKEUP(&dev->vblank[i].queue);
dev->vblank_enabled[i] = false; dev->vblank[i].enabled = false;
dev->last_vblank[i] = dev->vblank[i].last =
dev->driver->get_vblank_counter(dev, i); dev->driver->get_vblank_counter(dev, i);
} }
spin_unlock_irqrestore(&dev->vbl_lock, irqflags); spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

Просмотреть файл

@ -1078,6 +1078,19 @@ struct drm_pending_vblank_event {
struct drm_event_vblank event; struct drm_event_vblank event;
}; };
struct drm_vblank_crtc {
wait_queue_head_t queue; /**< VBLANK wait queue */
struct timeval time[DRM_VBLANKTIME_RBSIZE]; /**< timestamp of current count */
atomic_t count; /**< number of VBLANK interrupts */
atomic_t refcount; /* number of users of vblank interruptsper crtc */
u32 last; /* protected by dev->vbl_lock, used */
/* for wraparound handling */
u32 last_wait; /* Last vblank seqno waited per CRTC */
unsigned int inmodeset; /* Display driver is setting mode */
bool enabled; /* so we don't call enable more than
once per disable */
};
/** /**
* DRM device structure. This structure represent a complete card that * DRM device structure. This structure represent a complete card that
* may contain multiple heads. * may contain multiple heads.
@ -1153,18 +1166,11 @@ struct drm_device {
*/ */
bool vblank_disable_allowed; bool vblank_disable_allowed;
wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ /* array of size num_crtcs */
atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ struct drm_vblank_crtc *vblank;
struct timeval *_vblank_time; /**< timestamp of current vblank_count (drivers must alloc right number of fields) */
spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */ spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */
spinlock_t vbl_lock; spinlock_t vbl_lock;
atomic_t *vblank_refcount; /* number of users of vblank interruptsper crtc */
u32 *last_vblank; /* protected by dev->vbl_lock, used */
/* for wraparound handling */
bool *vblank_enabled; /* so we don't call enable more than
once per disable */
unsigned int *vblank_inmodeset; /* Display driver is setting mode */
u32 *last_vblank_wait; /* Last vblank seqno waited per CRTC */
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 */