diff options
| -rw-r--r-- | linux-core/drmP.h | 4 | ||||
| -rw-r--r-- | linux-core/drm_core.h | 8 | ||||
| -rw-r--r-- | linux-core/drm_irq.c | 72 | ||||
| -rw-r--r-- | shared-core/drm.h | 4 | 
4 files changed, 60 insertions, 28 deletions
| diff --git a/linux-core/drmP.h b/linux-core/drmP.h index fd48059a..200b6493 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -110,6 +110,7 @@  #define DRIVER_IRQ_VBL     0x100  #define DRIVER_DMA_QUEUE   0x200  #define DRIVER_FB_DMA      0x400 +#define DRIVER_IRQ_VBL2    0x800  /*@}*/ @@ -582,6 +583,7 @@ struct drm_driver {  				      int new);  	void (*kernel_context_switch_unlock) (struct drm_device * dev);  	int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); +	int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);  	int (*dri_library_name) (struct drm_device * dev, char * buf);  	/** @@ -732,8 +734,10 @@ typedef struct drm_device {  	wait_queue_head_t vbl_queue;	/**< VBLANK wait queue */  	atomic_t vbl_received; +	atomic_t vbl_received2;		/**< number of secondary VBLANK interrupts */  	spinlock_t vbl_lock;  	drm_vbl_sig_t vbl_sigs;		/**< signal list to send on VBLANK */ +	drm_vbl_sig_t vbl_sigs2;	/**< signals to send on secondary VBLANK */  	unsigned int vbl_pending;  	/*@} */ diff --git a/linux-core/drm_core.h b/linux-core/drm_core.h index f5405fdf..705bbff7 100644 --- a/linux-core/drm_core.h +++ b/linux-core/drm_core.h @@ -25,11 +25,11 @@  #define CORE_NAME		"drm"  #define CORE_DESC		"DRM shared core routines" -#define CORE_DATE		"20051102" +#define CORE_DATE		"20060810"  #define DRM_IF_MAJOR	1 -#define DRM_IF_MINOR	2 +#define DRM_IF_MINOR	3  #define CORE_MAJOR	1 -#define CORE_MINOR	0 -#define CORE_PATCHLEVEL 1 +#define CORE_MINOR	1 +#define CORE_PATCHLEVEL 0 diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index c2a9e3d6..d4e5fbd5 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -120,6 +120,7 @@ static int drm_irq_install(drm_device_t * dev)  		spin_lock_init(&dev->vbl_lock);  		INIT_LIST_HEAD(&dev->vbl_sigs.head); +		INIT_LIST_HEAD(&dev->vbl_sigs2.head);  		dev->vbl_pending = 0;  	} @@ -246,9 +247,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)  	struct timeval now;  	int ret = 0;  	unsigned int flags; - -	if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL)) -		return -EINVAL; +	atomic_t *seq;  	if ((!dev->irq) || (!dev->irq_enabled))  		return -EINVAL; @@ -256,9 +255,26 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)  	if (copy_from_user(&vblwait, argp, sizeof(vblwait)))  		return -EFAULT; -	switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) { +	if (vblwait.request.type & +	    ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { +		DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", +			  vblwait.request.type, +			  (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); +		return -EINVAL; +	} + +	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + +	if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ? +				    DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL)) +		return -EINVAL; + +	seq = (flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 : +	      &dev->vbl_received; + +	switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {  	case _DRM_VBLANK_RELATIVE: -		vblwait.request.sequence += atomic_read(&dev->vbl_received); +		vblwait.request.sequence += atomic_read(seq);  		vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;  	case _DRM_VBLANK_ABSOLUTE:  		break; @@ -266,13 +282,13 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)  		return -EINVAL;  	} -	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; -  	if (flags & _DRM_VBLANK_SIGNAL) {  		unsigned long irqflags; +		drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY) +				      ? &dev->vbl_sigs2 : &dev->vbl_sigs;  		drm_vbl_sig_t *vbl_sig; -		vblwait.reply.sequence = atomic_read(&dev->vbl_received); +		vblwait.reply.sequence = atomic_read(seq);  		spin_lock_irqsave(&dev->vbl_lock, irqflags); @@ -280,7 +296,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)  		 * for the same vblank sequence number; nothing to be done in  		 * that case  		 */ -		list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) { +		list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {  			if (vbl_sig->sequence == vblwait.request.sequence  			    && vbl_sig->info.si_signo == vblwait.request.signal  			    && vbl_sig->task == current) { @@ -313,11 +329,14 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)  		spin_lock_irqsave(&dev->vbl_lock, irqflags); -		list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head); +		list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);  		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);  	} else { -		if (dev->driver->vblank_wait) +		if (flags & _DRM_VBLANK_SECONDARY) { +			if (dev->driver->vblank_wait2) +				ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence); +		} else if (dev->driver->vblank_wait)  			ret =  			    dev->driver->vblank_wait(dev,  						     &vblwait.request.sequence); @@ -345,25 +364,32 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)   */  void drm_vbl_send_signals(drm_device_t * dev)  { -	struct list_head *list, *tmp; -	drm_vbl_sig_t *vbl_sig; -	unsigned int vbl_seq = atomic_read(&dev->vbl_received);  	unsigned long flags; +	int i;  	spin_lock_irqsave(&dev->vbl_lock, flags); -	list_for_each_safe(list, tmp, &dev->vbl_sigs.head) { -		vbl_sig = list_entry(list, drm_vbl_sig_t, head); -		if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { -			vbl_sig->info.si_code = vbl_seq; -			send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info, -				      vbl_sig->task); +	for (i = 0; i < 2; i++) { +		struct list_head *list, *tmp; +		drm_vbl_sig_t *vbl_sig; +		drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs; +		unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 : +						   &dev->vbl_received); + +		list_for_each_safe(list, tmp, &vbl_sigs->head) { +			vbl_sig = list_entry(list, drm_vbl_sig_t, head); +			if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { +				vbl_sig->info.si_code = vbl_seq; +				send_sig_info(vbl_sig->info.si_signo, +					      &vbl_sig->info, vbl_sig->task); -			list_del(list); +				list_del(list); -			drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER); +				drm_free(vbl_sig, sizeof(*vbl_sig), +					 DRM_MEM_DRIVER); -			dev->vbl_pending--; +				dev->vbl_pending--; +			}  		}  	} diff --git a/shared-core/drm.h b/shared-core/drm.h index 87f8da6b..eaeb21e4 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -529,10 +529,12 @@ typedef struct drm_irq_busid {  typedef enum {  	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */  	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */ +	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */  	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking */  } drm_vblank_seq_type_t; -#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY)  struct drm_wait_vblank_request {  	drm_vblank_seq_type_t type; | 
