diff options
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 40 | ||||
-rw-r--r-- | include/drm/drmP.h | 4 |
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 | ||
141 | static void vblank_disable_fn(unsigned long arg) | 141 | static 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 | ||
161 | void drm_vblank_cleanup(struct drm_device *dev) | 159 | void 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 | } |
906 | EXPORT_SYMBOL(drm_vblank_put); | 910 | EXPORT_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 | */ |
915 | void drm_vblank_off(struct drm_device *dev, int crtc) | 917 | void 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 | ||
1026 | struct drm_vblank_crtc { | 1026 | struct 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 | ||