diff options
| -rw-r--r-- | linux-core/radeon_drv.c | 8 | ||||
| -rw-r--r-- | shared-core/radeon_drv.h | 12 | ||||
| -rw-r--r-- | shared-core/radeon_irq.c | 158 | 
3 files changed, 79 insertions, 99 deletions
| diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index 327a6a97..39c35134 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -60,8 +60,7 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);  static struct drm_driver driver = {  	.driver_features =  	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | -	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | -	    DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2, +	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,  	.dev_priv_size = sizeof(drm_radeon_buf_priv_t),  	.load = radeon_driver_load,  	.firstopen = radeon_driver_firstopen, @@ -70,8 +69,9 @@ static struct drm_driver driver = {  	.postclose = radeon_driver_postclose,  	.lastclose = radeon_driver_lastclose,  	.unload = radeon_driver_unload, -	.vblank_wait = radeon_driver_vblank_wait, -	.vblank_wait2 = radeon_driver_vblank_wait2, +	.get_vblank_counter = radeon_get_vblank_counter, +	.enable_vblank = radeon_enable_vblank, +	.disable_vblank = radeon_disable_vblank,  	.dri_library_name = dri_library_name,  	.irq_preinstall = radeon_driver_irq_preinstall,  	.irq_postinstall = radeon_driver_irq_postinstall, diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 283dee33..5f671df6 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -366,13 +366,12 @@ extern int radeon_irq_emit(DRM_IOCTL_ARGS);  extern int radeon_irq_wait(DRM_IOCTL_ARGS);  extern void radeon_do_release(drm_device_t * dev); -extern int radeon_driver_vblank_wait(drm_device_t * dev, -				     unsigned int *sequence, int relative); -extern int radeon_driver_vblank_wait2(drm_device_t * dev, -				      unsigned int *sequence, int relative); +extern u32 radeon_get_vblank_counter(drm_device_t *dev, int crtc); +extern int radeon_enable_vblank(drm_device_t *dev, int crtc); +extern void radeon_disable_vblank(drm_device_t *dev, int crtc);  extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);  extern void radeon_driver_irq_preinstall(drm_device_t * dev); -extern void radeon_driver_irq_postinstall(drm_device_t * dev); +extern int radeon_driver_irq_postinstall(drm_device_t * dev);  extern void radeon_driver_irq_uninstall(drm_device_t * dev);  extern int radeon_vblank_crtc_get(drm_device_t *dev);  extern int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value); @@ -513,6 +512,9 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp,  #define RADEON_CRTC_CRNT_FRAME 0x0214  #define RADEON_CRTC2_CRNT_FRAME 0x0314 +#define RADEON_CRTC_CRNT_FRAME              0x0214 +#define RADEON_CRTC2_CRNT_FRAME              0x0314 +  #define RADEON_GEN_INT_CNTL		0x0040  #	define RADEON_CRTC_VBLANK_MASK		(1 << 0)  #	define RADEON_CRTC2_VBLANK_MASK		(1 << 9) diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 2534ff10..46ec035d 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -47,6 +47,50 @@ static void radeon_irq_set_state(drm_device_t *dev, u32 mask, int state)  	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);  } +int radeon_enable_vblank(drm_device_t *dev, int crtc) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	if (!(dev_priv->vblank_crtc & (1 << crtc))) +		return -EINVAL; +	 +	switch (crtc) { +	case 0: +		radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); +		break; +	case 1: +		radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); +		break; +	default: +		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", +			  crtc); +		break; +	} + +	return 0; +} + +void radeon_disable_vblank(drm_device_t *dev, int crtc) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	if (!(dev_priv->vblank_crtc & (1 << crtc))) +		return; +	 +	switch (crtc) { +	case 0: +		radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); +		break; +	case 1: +		radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); +		break; +	default: +		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", +			  crtc); +		break; +	} +} +  static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,  					      u32 mask)  { @@ -89,30 +133,14 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)  		return IRQ_NONE;  	/* SW interrupt */ -	if (stat & RADEON_SW_INT_TEST) { +	if (stat & RADEON_SW_INT_TEST)  		DRM_WAKEUP(&dev_priv->swi_queue); -	}  	/* VBLANK interrupt */ -	if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { -		int vblank_crtc = dev_priv->vblank_crtc; - -		if ((vblank_crtc & -		     (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) == -		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { -			if (stat & RADEON_CRTC_VBLANK_STAT) -				atomic_inc(&dev->vbl_received); -			if (stat & RADEON_CRTC2_VBLANK_STAT) -				atomic_inc(&dev->vbl_received2); -		} else if (((stat & RADEON_CRTC_VBLANK_STAT) && -			   (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) || -			   ((stat & RADEON_CRTC2_VBLANK_STAT) && -			    (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) -			atomic_inc(&dev->vbl_received); - -		DRM_WAKEUP(&dev->vbl_queue); -		drm_vbl_send_signals(dev); -	} +	if (stat & RADEON_CRTC_VBLANK_STAT) +		drm_handle_vblank(dev, 0); +	if (stat & RADEON_CRTC2_VBLANK_STAT) +		drm_handle_vblank(dev, 1);  	return IRQ_HANDLED;  } @@ -152,80 +180,21 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr)  	return ret;  } -int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence, -				 int crtc, int relative) +u32 radeon_get_vblank_counter(drm_device_t *dev, int crtc)  { -	drm_radeon_private_t *dev_priv = -	    (drm_radeon_private_t *) dev->dev_private; -	unsigned int cur_vblank, diff, irqflags, current_cnt; -	int ret = 0; -	int ack = 0; -	atomic_t *counter; -	unsigned int *last_cnt; -	int crtc_cnt_reg; -	 -	if (!dev_priv) { -		DRM_ERROR("%s called with no initialization\n", __FUNCTION__); -		return DRM_ERR(EINVAL); -	} +	drm_radeon_private_t *dev_priv = dev->dev_private; +	u32 crtc_cnt_reg, current_cnt; -	if (crtc == DRM_RADEON_VBLANK_CRTC1) { -		counter = &dev->vbl_received; -		ack = RADEON_CRTC_VBLANK_STAT; -		last_cnt = &dev_priv->crtc_last_cnt; +	if (crtc == DRM_RADEON_VBLANK_CRTC1)  		crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; -	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) { -		counter = &dev->vbl_received2; -		ack = RADEON_CRTC2_VBLANK_STAT; -		last_cnt = &dev_priv->crtc2_last_cnt; +	else if (crtc == DRM_RADEON_VBLANK_CRTC2)  		crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; -	} else -		return DRM_ERR(EINVAL); - -	radeon_acknowledge_irqs(dev_priv, ack); - -	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - -	if (!relative) { -		/* -		 * Assume we haven't missed more than several hours of vblank -		 * events, or that it won't matter if they're not accounted -		 * for in the master counter. -		 */ -		spin_lock_irqsave(&dev->vbl_lock, irqflags); -		current_cnt = RADEON_READ(crtc_cnt_reg); -		if (current_cnt < *last_cnt) { -			current_cnt += (1 << 21) - *last_cnt; -			*last_cnt = 0; -		} -		diff = current_cnt - *last_cnt; -		*last_cnt = RADEON_READ(crtc_cnt_reg); -		spin_unlock_irqrestore(&dev->vbl_lock, irqflags); -		atomic_add(diff, counter); -	} - -	/* Assume that the user has missed the current sequence number -	 * by about a day rather than she wants to wait for years -	 * using vertical blanks... -	 */ -	radeon_irq_set_state(dev, ack, 1); -	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, -		    (((cur_vblank = atomic_read(counter)) -		      - *sequence) <= (1 << 23))); -	radeon_irq_set_state(dev, ack, 0); -	*sequence = cur_vblank; - -	return ret; -} +	else +		return 0; -int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence, int relative) -{ -	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1, relative); -} +	current_cnt = RADEON_READ(crtc_cnt_reg); -int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence, int relative) -{ -	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2, relative); +	return current_cnt;  }  /* Needs the lock as it touches the ring. @@ -294,15 +263,24 @@ void radeon_driver_irq_preinstall(drm_device_t * dev)  					   RADEON_CRTC2_VBLANK_STAT));  } -void radeon_driver_irq_postinstall(drm_device_t * dev) +int radeon_driver_irq_postinstall(drm_device_t * dev)  {  	drm_radeon_private_t *dev_priv =  	    (drm_radeon_private_t *) dev->dev_private; +	int num_pipes = 2, ret;  	atomic_set(&dev_priv->swi_emitted, 0);  	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); +	ret = drm_vblank_init(dev, num_pipes); +	if (ret) +		return ret; + +	dev->max_vblank_count = 0xffffffff; +  	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); + +	return 0;  }  void radeon_driver_irq_uninstall(drm_device_t * dev) | 
