aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_irq.c40
-rw-r--r--include/drm/drmP.h4
2 files changed, 24 insertions, 20 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index ea20c4aa1b6b..90c59a8c820f 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -140,33 +140,34 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
140 140
141static void vblank_disable_fn(unsigned long arg) 141static void vblank_disable_fn(unsigned long arg)
142{ 142{
143 struct drm_device *dev = (struct drm_device *)arg; 143 struct drm_vblank_crtc *vblank = (void *)arg;
144 struct drm_device *dev = vblank->dev;
144 unsigned long irqflags; 145 unsigned long irqflags;
145 int i; 146 int crtc = vblank->crtc;
146 147
147 if (!dev->vblank_disable_allowed) 148 if (!dev->vblank_disable_allowed)
148 return; 149 return;
149 150
150 for (i = 0; i < dev->num_crtcs; i++) { 151 spin_lock_irqsave(&dev->vbl_lock, irqflags);
151 spin_lock_irqsave(&dev->vbl_lock, irqflags); 152 if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
152 if (atomic_read(&dev->vblank[i].refcount) == 0 && 153 DRM_DEBUG("disabling vblank on crtc %d\n", crtc);
153 dev->vblank[i].enabled) { 154 vblank_disable_and_save(dev, crtc);
154 DRM_DEBUG("disabling vblank on crtc %d\n", i);
155 vblank_disable_and_save(dev, i);
156 }
157 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
158 } 155 }
156 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
159} 157}
160 158
161void drm_vblank_cleanup(struct drm_device *dev) 159void drm_vblank_cleanup(struct drm_device *dev)
162{ 160{
161 int crtc;
162
163 /* Bail if the driver didn't call drm_vblank_init() */ 163 /* Bail if the driver didn't call drm_vblank_init() */
164 if (dev->num_crtcs == 0) 164 if (dev->num_crtcs == 0)
165 return; 165 return;
166 166
167 del_timer_sync(&dev->vblank_disable_timer); 167 for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
168 168 del_timer_sync(&dev->vblank[crtc].disable_timer);
169 vblank_disable_fn((unsigned long)dev); 169 vblank_disable_fn((unsigned long)&dev->vblank[crtc]);
170 }
170 171
171 kfree(dev->vblank); 172 kfree(dev->vblank);
172 173
@@ -178,8 +179,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
178{ 179{
179 int i, ret = -ENOMEM; 180 int i, ret = -ENOMEM;
180 181
181 setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
182 (unsigned long)dev);
183 spin_lock_init(&dev->vbl_lock); 182 spin_lock_init(&dev->vbl_lock);
184 spin_lock_init(&dev->vblank_time_lock); 183 spin_lock_init(&dev->vblank_time_lock);
185 184
@@ -189,8 +188,13 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
189 if (!dev->vblank) 188 if (!dev->vblank)
190 goto err; 189 goto err;
191 190
192 for (i = 0; i < num_crtcs; i++) 191 for (i = 0; i < num_crtcs; i++) {
192 dev->vblank[i].dev = dev;
193 dev->vblank[i].crtc = i;
193 init_waitqueue_head(&dev->vblank[i].queue); 194 init_waitqueue_head(&dev->vblank[i].queue);
195 setup_timer(&dev->vblank[i].disable_timer, vblank_disable_fn,
196 (unsigned long)&dev->vblank[i]);
197 }
194 198
195 DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); 199 DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
196 200
@@ -900,7 +904,7 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
900 /* Last user schedules interrupt disable */ 904 /* Last user schedules interrupt disable */
901 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && 905 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
902 (drm_vblank_offdelay > 0)) 906 (drm_vblank_offdelay > 0))
903 mod_timer(&dev->vblank_disable_timer, 907 mod_timer(&dev->vblank[crtc].disable_timer,
904 jiffies + ((drm_vblank_offdelay * HZ)/1000)); 908 jiffies + ((drm_vblank_offdelay * HZ)/1000));
905} 909}
906EXPORT_SYMBOL(drm_vblank_put); 910EXPORT_SYMBOL(drm_vblank_put);
@@ -909,8 +913,6 @@ EXPORT_SYMBOL(drm_vblank_put);
909 * drm_vblank_off - disable vblank events on a CRTC 913 * drm_vblank_off - disable vblank events on a CRTC
910 * @dev: DRM device 914 * @dev: DRM device
911 * @crtc: CRTC in question 915 * @crtc: CRTC in question
912 *
913 * Caller must hold event lock.
914 */ 916 */
915void drm_vblank_off(struct drm_device *dev, int crtc) 917void drm_vblank_off(struct drm_device *dev, int crtc)
916{ 918{
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 12f10bc2395f..9d982d483f12 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1024,14 +1024,17 @@ struct drm_pending_vblank_event {
1024}; 1024};
1025 1025
1026struct drm_vblank_crtc { 1026struct drm_vblank_crtc {
1027 struct drm_device *dev; /* pointer to the drm_device */
1027 wait_queue_head_t queue; /**< VBLANK wait queue */ 1028 wait_queue_head_t queue; /**< VBLANK wait queue */
1028 struct timeval time[DRM_VBLANKTIME_RBSIZE]; /**< timestamp of current count */ 1029 struct timeval time[DRM_VBLANKTIME_RBSIZE]; /**< timestamp of current count */
1030 struct timer_list disable_timer; /* delayed disable timer */
1029 atomic_t count; /**< number of VBLANK interrupts */ 1031 atomic_t count; /**< number of VBLANK interrupts */
1030 atomic_t refcount; /* number of users of vblank interruptsper crtc */ 1032 atomic_t refcount; /* number of users of vblank interruptsper crtc */
1031 u32 last; /* protected by dev->vbl_lock, used */ 1033 u32 last; /* protected by dev->vbl_lock, used */
1032 /* for wraparound handling */ 1034 /* for wraparound handling */
1033 u32 last_wait; /* Last vblank seqno waited per CRTC */ 1035 u32 last_wait; /* Last vblank seqno waited per CRTC */
1034 unsigned int inmodeset; /* Display driver is setting mode */ 1036 unsigned int inmodeset; /* Display driver is setting mode */
1037 int crtc; /* crtc index */
1035 bool enabled; /* so we don't call enable more than 1038 bool enabled; /* so we don't call enable more than
1036 once per disable */ 1039 once per disable */
1037}; 1040};
@@ -1119,7 +1122,6 @@ struct drm_device {
1119 1122
1120 spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */ 1123 spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */
1121 spinlock_t vbl_lock; 1124 spinlock_t vbl_lock;
1122 struct timer_list vblank_disable_timer;
1123 1125
1124 u32 max_vblank_count; /**< size of vblank counter register */ 1126 u32 max_vblank_count; /**< size of vblank counter register */
1125 1127