diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/drmP.h | 1 | ||||
| -rw-r--r-- | linux-core/drm_irq.c | 17 | 
2 files changed, 16 insertions, 2 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index cf1c0fd7..0ab69feb 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -832,6 +832,7 @@ typedef struct drm_device {  					/* for wraparound handling */  	u32 *vblank_offset;		/* used to track how many vblanks */  	u32 *vblank_premodeset;		/*  were lost during modeset */ +	struct timer_list vblank_disable_timer;  	unsigned long max_vblank_count; /**< size of vblank counter register */  	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */ diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index c9d1c0d2..1e1b7f4d 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -77,10 +77,22 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,  	return 0;  } +static void vblank_disable_fn(unsigned long arg) +{ +	drm_device_t *dev = (drm_device_t *)arg; +	int i; + +	for (i = 0; i < dev->num_crtcs; i++) +		if (atomic_read(&dev->vblank_refcount[i]) == 0) +			dev->driver->disable_vblank(dev, i); +} +  int drm_vblank_init(drm_device_t *dev, int num_crtcs)  {  	int i, ret = -ENOMEM; +	setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,\ +		    (unsigned long)dev);  	spin_lock_init(&dev->vbl_lock);  	atomic_set(&dev->vbl_signal_pending, 0);  	dev->num_crtcs = num_crtcs; @@ -377,9 +389,10 @@ EXPORT_SYMBOL(drm_vblank_get);   */  void drm_vblank_put(drm_device_t *dev, int crtc)  { -	/* Last user can disable interrupts */ +	/* Last user schedules interrupt disable */  	if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) -		dev->driver->disable_vblank(dev, crtc); +		mod_timer(&dev->vblank_disable_timer, +			  round_jiffies_relative(DRM_HZ));  }  EXPORT_SYMBOL(drm_vblank_put);  | 
