aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_irq.c
diff options
context:
space:
mode:
author=?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com>2006-10-24 08:24:38 -0400
committerairlied <airlied@linux.ie>2006-12-06 23:53:28 -0500
commit776c9443e28dddbde9b513db6cb8221c45b3a269 (patch)
tree41b753829e949371ee01d2930f5be1185f29b737 /drivers/char/drm/drm_irq.c
parent620034c84d1d939717bdfbe02c51a3fee43541c3 (diff)
drm: add support for secondary vertical blank interrupt to DRM core
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/drm_irq.c')
-rw-r--r--drivers/char/drm/drm_irq.c72
1 files changed, 49 insertions, 23 deletions
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 4553a3a1e496..3c77756aad9c 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -121,6 +121,7 @@ static int drm_irq_install(drm_device_t * dev)
121 spin_lock_init(&dev->vbl_lock); 121 spin_lock_init(&dev->vbl_lock);
122 122
123 INIT_LIST_HEAD(&dev->vbl_sigs.head); 123 INIT_LIST_HEAD(&dev->vbl_sigs.head);
124 INIT_LIST_HEAD(&dev->vbl_sigs2.head);
124 125
125 dev->vbl_pending = 0; 126 dev->vbl_pending = 0;
126 } 127 }
@@ -248,9 +249,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
248 struct timeval now; 249 struct timeval now;
249 int ret = 0; 250 int ret = 0;
250 unsigned int flags; 251 unsigned int flags;
251 252 atomic_t *seq;
252 if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL))
253 return -EINVAL;
254 253
255 if (!dev->irq) 254 if (!dev->irq)
256 return -EINVAL; 255 return -EINVAL;
@@ -258,9 +257,26 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
258 if (copy_from_user(&vblwait, argp, sizeof(vblwait))) 257 if (copy_from_user(&vblwait, argp, sizeof(vblwait)))
259 return -EFAULT; 258 return -EFAULT;
260 259
261 switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) { 260 if (vblwait.request.type &
261 ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
262 DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
263 vblwait.request.type,
264 (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
265 return -EINVAL;
266 }
267
268 flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
269
270 if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
271 DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
272 return -EINVAL;
273
274 seq = (flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 :
275 &dev->vbl_received;
276
277 switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
262 case _DRM_VBLANK_RELATIVE: 278 case _DRM_VBLANK_RELATIVE:
263 vblwait.request.sequence += atomic_read(&dev->vbl_received); 279 vblwait.request.sequence += atomic_read(seq);
264 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; 280 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
265 case _DRM_VBLANK_ABSOLUTE: 281 case _DRM_VBLANK_ABSOLUTE:
266 break; 282 break;
@@ -268,13 +284,13 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
268 return -EINVAL; 284 return -EINVAL;
269 } 285 }
270 286
271 flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
272
273 if (flags & _DRM_VBLANK_SIGNAL) { 287 if (flags & _DRM_VBLANK_SIGNAL) {
274 unsigned long irqflags; 288 unsigned long irqflags;
289 drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
290 ? &dev->vbl_sigs2 : &dev->vbl_sigs;
275 drm_vbl_sig_t *vbl_sig; 291 drm_vbl_sig_t *vbl_sig;
276 292
277 vblwait.reply.sequence = atomic_read(&dev->vbl_received); 293 vblwait.reply.sequence = atomic_read(seq);
278 294
279 spin_lock_irqsave(&dev->vbl_lock, irqflags); 295 spin_lock_irqsave(&dev->vbl_lock, irqflags);
280 296
@@ -282,7 +298,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
282 * for the same vblank sequence number; nothing to be done in 298 * for the same vblank sequence number; nothing to be done in
283 * that case 299 * that case
284 */ 300 */
285 list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) { 301 list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {
286 if (vbl_sig->sequence == vblwait.request.sequence 302 if (vbl_sig->sequence == vblwait.request.sequence
287 && vbl_sig->info.si_signo == vblwait.request.signal 303 && vbl_sig->info.si_signo == vblwait.request.signal
288 && vbl_sig->task == current) { 304 && vbl_sig->task == current) {
@@ -315,11 +331,14 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
315 331
316 spin_lock_irqsave(&dev->vbl_lock, irqflags); 332 spin_lock_irqsave(&dev->vbl_lock, irqflags);
317 333
318 list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head); 334 list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);
319 335
320 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 336 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
321 } else { 337 } else {
322 if (dev->driver->vblank_wait) 338 if (flags & _DRM_VBLANK_SECONDARY) {
339 if (dev->driver->vblank_wait2)
340 ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence);
341 } else if (dev->driver->vblank_wait)
323 ret = 342 ret =
324 dev->driver->vblank_wait(dev, 343 dev->driver->vblank_wait(dev,
325 &vblwait.request.sequence); 344 &vblwait.request.sequence);
@@ -347,25 +366,32 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
347 */ 366 */
348void drm_vbl_send_signals(drm_device_t * dev) 367void drm_vbl_send_signals(drm_device_t * dev)
349{ 368{
350 struct list_head *list, *tmp;
351 drm_vbl_sig_t *vbl_sig;
352 unsigned int vbl_seq = atomic_read(&dev->vbl_received);
353 unsigned long flags; 369 unsigned long flags;
370 int i;
354 371
355 spin_lock_irqsave(&dev->vbl_lock, flags); 372 spin_lock_irqsave(&dev->vbl_lock, flags);
356 373
357 list_for_each_safe(list, tmp, &dev->vbl_sigs.head) { 374 for (i = 0; i < 2; i++) {
358 vbl_sig = list_entry(list, drm_vbl_sig_t, head); 375 struct list_head *list, *tmp;
359 if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { 376 drm_vbl_sig_t *vbl_sig;
360 vbl_sig->info.si_code = vbl_seq; 377 drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
361 send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info, 378 unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
362 vbl_sig->task); 379 &dev->vbl_received);
380
381 list_for_each_safe(list, tmp, &vbl_sigs->head) {
382 vbl_sig = list_entry(list, drm_vbl_sig_t, head);
383 if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
384 vbl_sig->info.si_code = vbl_seq;
385 send_sig_info(vbl_sig->info.si_signo,
386 &vbl_sig->info, vbl_sig->task);
363 387
364 list_del(list); 388 list_del(list);
365 389
366 drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER); 390 drm_free(vbl_sig, sizeof(*vbl_sig),
391 DRM_MEM_DRIVER);
367 392
368 dev->vbl_pending--; 393 dev->vbl_pending--;
394 }
369 } 395 }
370 } 396 }
371 397