Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddbee333 authored by Dave Airlie's avatar Dave Airlie
Browse files

radeon: add support for vblank on crtc2



This adds support for CRTC2 vblank on radeon similiar to the i915.

Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent 7c158ace
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1420,6 +1420,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
		return DRM_ERR(EINVAL);
	}

	/* Enable vblank on CRTC1 for older X servers
	 */
	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;

	switch(init->func) {
	case RADEON_INIT_R200_CP:
		dev_priv->microcode_version = UCODE_R200;
+5 −1
Original line number Diff line number Diff line
@@ -655,6 +655,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_GART_TEX_HANDLE       10
#define RADEON_PARAM_SCRATCH_OFFSET        11
#define RADEON_PARAM_CARD_TYPE             12
#define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */

typedef struct drm_radeon_getparam {
	int param;
@@ -708,7 +709,7 @@ typedef struct drm_radeon_setparam {
#define RADEON_SETPARAM_PCIGART_LOCATION 3	/* PCI Gart Location */
#define RADEON_SETPARAM_NEW_MEMMAP 4		/* Use new memory map */
#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5    /* PCI GART Table Size */

#define RADEON_SETPARAM_VBLANK_CRTC 6           /* VBLANK CRTC */
/* 1.14: Clients can allocate/free a surface
 */
typedef struct drm_radeon_surface_alloc {
@@ -721,4 +722,7 @@ typedef struct drm_radeon_surface_free {
	unsigned int address;
} drm_radeon_surface_free_t;

#define	DRM_RADEON_VBLANK_CRTC1 	1
#define	DRM_RADEON_VBLANK_CRTC2 	2

#endif
+2 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ 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_VBL | DRIVER_IRQ_VBL2,
	.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
	.load = radeon_driver_load,
	.firstopen = radeon_driver_firstopen,
@@ -70,6 +70,7 @@ static struct drm_driver driver = {
	.lastclose = radeon_driver_lastclose,
	.unload = radeon_driver_unload,
	.vblank_wait = radeon_driver_vblank_wait,
	.vblank_wait2 = radeon_driver_vblank_wait2,
	.dri_library_name = dri_library_name,
	.irq_preinstall = radeon_driver_irq_preinstall,
	.irq_postinstall = radeon_driver_irq_postinstall,
+12 −1
Original line number Diff line number Diff line
@@ -97,9 +97,10 @@
 *       new packet type)
 * 1.26- Add support for variable size PCI(E) gart aperture
 * 1.27- Add support for IGP GART
 * 1.28- Add support for VBL on CRTC2
 */
#define DRIVER_MAJOR		1
#define DRIVER_MINOR		27
#define DRIVER_MINOR		28
#define DRIVER_PATCHLEVEL	0

/*
@@ -277,6 +278,9 @@ typedef struct drm_radeon_private {
	/* SW interrupt */
	wait_queue_head_t swi_queue;
	atomic_t swi_emitted;
	int vblank_crtc;
	uint32_t irq_enable_reg;
	int irq_enabled;

	struct radeon_surface surfaces[RADEON_MAX_SURFACES];
	struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
@@ -356,10 +360,14 @@ 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);
extern int radeon_driver_vblank_wait2(drm_device_t * dev,
				      unsigned int *sequence);
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 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);

extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
extern int radeon_driver_unload(struct drm_device *dev);
@@ -496,12 +504,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,

#define RADEON_GEN_INT_CNTL		0x0040
#	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
#	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
#	define RADEON_GUI_IDLE_INT_ENABLE	(1 << 19)
#	define RADEON_SW_INT_ENABLE		(1 << 25)

#define RADEON_GEN_INT_STATUS		0x0044
#	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
#	define RADEON_CRTC_VBLANK_STAT_ACK   	(1 << 0)
#	define RADEON_CRTC2_VBLANK_STAT		(1 << 9)
#	define RADEON_CRTC2_VBLANK_STAT_ACK   	(1 << 9)
#	define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
#	define RADEON_SW_INT_TEST		(1 << 25)
#	define RADEON_SW_INT_TEST_ACK   	(1 << 25)
+95 −11
Original line number Diff line number Diff line
@@ -73,18 +73,35 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
	 * outside the DRM
	 */
	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
						  RADEON_CRTC_VBLANK_STAT));
						  RADEON_CRTC_VBLANK_STAT |
						  RADEON_CRTC2_VBLANK_STAT));
	if (!stat)
		return IRQ_NONE;

	stat &= dev_priv->irq_enable_reg;

	/* SW interrupt */
	if (stat & RADEON_SW_INT_TEST) {
		DRM_WAKEUP(&dev_priv->swi_queue);
	}

	/* VBLANK interrupt */
	if (stat & RADEON_CRTC_VBLANK_STAT) {
	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);
	}
@@ -127,19 +144,30 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
	return ret;
}

int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
				 int crtc)
{
	drm_radeon_private_t *dev_priv =
	    (drm_radeon_private_t *) dev->dev_private;
	unsigned int cur_vblank;
	int ret = 0;

	int ack = 0;
	atomic_t *counter;
	if (!dev_priv) {
		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
		return DRM_ERR(EINVAL);
	}

	radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
	if (crtc == DRM_RADEON_VBLANK_CRTC1) {
		counter = &dev->vbl_received;
		ack |= RADEON_CRTC_VBLANK_STAT;
	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
		counter = &dev->vbl_received2;
		ack |= RADEON_CRTC2_VBLANK_STAT;
	} else
		return DRM_ERR(EINVAL);

	radeon_acknowledge_irqs(dev_priv, ack);

	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;

@@ -148,7 +176,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
	 * using vertical blanks...
	 */
	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
		    (((cur_vblank = atomic_read(&dev->vbl_received))
		    (((cur_vblank = atomic_read(counter))
		      - *sequence) <= (1 << 23)));

	*sequence = cur_vblank;
@@ -156,6 +184,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
	return ret;
}

int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
{
	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
}

int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
{
	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
}

/* Needs the lock as it touches the ring.
 */
int radeon_irq_emit(DRM_IOCTL_ARGS)
@@ -204,6 +242,21 @@ int radeon_irq_wait(DRM_IOCTL_ARGS)
	return radeon_wait_irq(dev, irqwait.irq_seq);
}

static void radeon_enable_interrupt(drm_device_t *dev)
{
	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;

	dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
		dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;

	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
		dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;

	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
	dev_priv->irq_enabled = 1;
}

/* drm_dma.h hooks
*/
void radeon_driver_irq_preinstall(drm_device_t * dev)
@@ -216,7 +269,8 @@ void radeon_driver_irq_preinstall(drm_device_t * dev)

	/* Clear bits if they're already high */
	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
					   RADEON_CRTC_VBLANK_STAT));
					   RADEON_CRTC_VBLANK_STAT |
					   RADEON_CRTC2_VBLANK_STAT));
}

void radeon_driver_irq_postinstall(drm_device_t * dev)
@@ -227,9 +281,7 @@ void radeon_driver_irq_postinstall(drm_device_t * dev)
	atomic_set(&dev_priv->swi_emitted, 0);
	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);

	/* Turn on SW and VBL ints */
	RADEON_WRITE(RADEON_GEN_INT_CNTL,
		     RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
	radeon_enable_interrupt(dev);
}

void radeon_driver_irq_uninstall(drm_device_t * dev)
@@ -239,6 +291,38 @@ void radeon_driver_irq_uninstall(drm_device_t * dev)
	if (!dev_priv)
		return;

	dev_priv->irq_enabled = 0;

	/* Disable *all* interrupts */
	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
}


int radeon_vblank_crtc_get(drm_device_t *dev)
{
	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
	u32 flag;
	u32 value;

	flag = RADEON_READ(RADEON_GEN_INT_CNTL);
	value = 0;

	if (flag & RADEON_CRTC_VBLANK_MASK)
		value |= DRM_RADEON_VBLANK_CRTC1;

	if (flag & RADEON_CRTC2_VBLANK_MASK)
		value |= DRM_RADEON_VBLANK_CRTC2;
	return value;
}

int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value)
{
	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
	if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
		DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
		return DRM_ERR(EINVAL);
	}
	dev_priv->vblank_crtc = (unsigned int)value;
	radeon_enable_interrupt(dev);
	return 0;
}
Loading