aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
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
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')
-rw-r--r--drivers/char/drm/drm.h4
-rw-r--r--drivers/char/drm/drmP.h4
-rw-r--r--drivers/char/drm/drm_core.h8
-rw-r--r--drivers/char/drm/drm_irq.c72
4 files changed, 60 insertions, 28 deletions
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 5642ac43e0f5..077d0b1914ab 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -465,10 +465,12 @@ typedef struct drm_irq_busid {
465typedef enum { 465typedef enum {
466 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ 466 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
467 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ 467 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
468 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
468 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ 469 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
469} drm_vblank_seq_type_t; 470} drm_vblank_seq_type_t;
470 471
471#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL 472#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
473#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY)
472 474
473struct drm_wait_vblank_request { 475struct drm_wait_vblank_request {
474 drm_vblank_seq_type_t type; 476 drm_vblank_seq_type_t type;
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 7690a59ace04..d7135d41a42a 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -97,6 +97,7 @@
97#define DRIVER_IRQ_VBL 0x100 97#define DRIVER_IRQ_VBL 0x100
98#define DRIVER_DMA_QUEUE 0x200 98#define DRIVER_DMA_QUEUE 0x200
99#define DRIVER_FB_DMA 0x400 99#define DRIVER_FB_DMA 0x400
100#define DRIVER_IRQ_VBL2 0x800
100 101
101/***********************************************************************/ 102/***********************************************************************/
102/** \name Begin the DRM... */ 103/** \name Begin the DRM... */
@@ -562,6 +563,7 @@ struct drm_driver {
562 void (*kernel_context_switch_unlock) (struct drm_device * dev, 563 void (*kernel_context_switch_unlock) (struct drm_device * dev,
563 drm_lock_t *lock); 564 drm_lock_t *lock);
564 int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); 565 int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
566 int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);
565 int (*dri_library_name) (struct drm_device *dev, char *buf); 567 int (*dri_library_name) (struct drm_device *dev, char *buf);
566 568
567 /** 569 /**
@@ -708,8 +710,10 @@ typedef struct drm_device {
708 710
709 wait_queue_head_t vbl_queue; /**< VBLANK wait queue */ 711 wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
710 atomic_t vbl_received; 712 atomic_t vbl_received;
713 atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
711 spinlock_t vbl_lock; 714 spinlock_t vbl_lock;
712 drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */ 715 drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
716 drm_vbl_sig_t vbl_sigs2; /**< signals to send on secondary VBLANK */
713 unsigned int vbl_pending; 717 unsigned int vbl_pending;
714 718
715 /*@} */ 719 /*@} */
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
index f4f9db6c7ed4..316739036079 100644
--- a/drivers/char/drm/drm_core.h
+++ b/drivers/char/drm/drm_core.h
@@ -24,11 +24,11 @@
24 24
25#define CORE_NAME "drm" 25#define CORE_NAME "drm"
26#define CORE_DESC "DRM shared core routines" 26#define CORE_DESC "DRM shared core routines"
27#define CORE_DATE "20051102" 27#define CORE_DATE "20060810"
28 28
29#define DRM_IF_MAJOR 1 29#define DRM_IF_MAJOR 1
30#define DRM_IF_MINOR 2 30#define DRM_IF_MINOR 3
31 31
32#define CORE_MAJOR 1 32#define CORE_MAJOR 1
33#define CORE_MINOR 0 33#define CORE_MINOR 1
34#define CORE_PATCHLEVEL 1 34#define CORE_PATCHLEVEL 0
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