Commit ddbee333 authored by Dave Airlie's avatar Dave Airlie

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
...@@ -1420,6 +1420,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1420,6 +1420,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
/* Enable vblank on CRTC1 for older X servers
*/
dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
switch(init->func) { switch(init->func) {
case RADEON_INIT_R200_CP: case RADEON_INIT_R200_CP:
dev_priv->microcode_version = UCODE_R200; dev_priv->microcode_version = UCODE_R200;
......
...@@ -655,6 +655,7 @@ typedef struct drm_radeon_indirect { ...@@ -655,6 +655,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_GART_TEX_HANDLE 10 #define RADEON_PARAM_GART_TEX_HANDLE 10
#define RADEON_PARAM_SCRATCH_OFFSET 11 #define RADEON_PARAM_SCRATCH_OFFSET 11
#define RADEON_PARAM_CARD_TYPE 12 #define RADEON_PARAM_CARD_TYPE 12
#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */
typedef struct drm_radeon_getparam { typedef struct drm_radeon_getparam {
int param; int param;
...@@ -708,7 +709,7 @@ typedef struct drm_radeon_setparam { ...@@ -708,7 +709,7 @@ typedef struct drm_radeon_setparam {
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ #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 /* 1.14: Clients can allocate/free a surface
*/ */
typedef struct drm_radeon_surface_alloc { typedef struct drm_radeon_surface_alloc {
...@@ -721,4 +722,7 @@ typedef struct drm_radeon_surface_free { ...@@ -721,4 +722,7 @@ typedef struct drm_radeon_surface_free {
unsigned int address; unsigned int address;
} drm_radeon_surface_free_t; } drm_radeon_surface_free_t;
#define DRM_RADEON_VBLANK_CRTC1 1
#define DRM_RADEON_VBLANK_CRTC2 2
#endif #endif
...@@ -60,7 +60,7 @@ static struct drm_driver driver = { ...@@ -60,7 +60,7 @@ static struct drm_driver driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | 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), .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.load = radeon_driver_load, .load = radeon_driver_load,
.firstopen = radeon_driver_firstopen, .firstopen = radeon_driver_firstopen,
...@@ -70,6 +70,7 @@ static struct drm_driver driver = { ...@@ -70,6 +70,7 @@ static struct drm_driver driver = {
.lastclose = radeon_driver_lastclose, .lastclose = radeon_driver_lastclose,
.unload = radeon_driver_unload, .unload = radeon_driver_unload,
.vblank_wait = radeon_driver_vblank_wait, .vblank_wait = radeon_driver_vblank_wait,
.vblank_wait2 = radeon_driver_vblank_wait2,
.dri_library_name = dri_library_name, .dri_library_name = dri_library_name,
.irq_preinstall = radeon_driver_irq_preinstall, .irq_preinstall = radeon_driver_irq_preinstall,
.irq_postinstall = radeon_driver_irq_postinstall, .irq_postinstall = radeon_driver_irq_postinstall,
......
...@@ -97,9 +97,10 @@ ...@@ -97,9 +97,10 @@
* new packet type) * new packet type)
* 1.26- Add support for variable size PCI(E) gart aperture * 1.26- Add support for variable size PCI(E) gart aperture
* 1.27- Add support for IGP GART * 1.27- Add support for IGP GART
* 1.28- Add support for VBL on CRTC2
*/ */
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 27 #define DRIVER_MINOR 28
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 0
/* /*
...@@ -277,6 +278,9 @@ typedef struct drm_radeon_private { ...@@ -277,6 +278,9 @@ typedef struct drm_radeon_private {
/* SW interrupt */ /* SW interrupt */
wait_queue_head_t swi_queue; wait_queue_head_t swi_queue;
atomic_t swi_emitted; atomic_t swi_emitted;
int vblank_crtc;
uint32_t irq_enable_reg;
int irq_enabled;
struct radeon_surface surfaces[RADEON_MAX_SURFACES]; struct radeon_surface surfaces[RADEON_MAX_SURFACES];
struct radeon_virt_surface virt_surfaces[2 * 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); ...@@ -356,10 +360,14 @@ extern int radeon_irq_wait(DRM_IOCTL_ARGS);
extern void radeon_do_release(drm_device_t * dev); extern void radeon_do_release(drm_device_t * dev);
extern int radeon_driver_vblank_wait(drm_device_t * dev, extern int radeon_driver_vblank_wait(drm_device_t * dev,
unsigned int *sequence); 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 irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
extern void radeon_driver_irq_preinstall(drm_device_t * dev); 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_postinstall(drm_device_t * dev);
extern void radeon_driver_irq_uninstall(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_load(struct drm_device *dev, unsigned long flags);
extern int radeon_driver_unload(struct drm_device *dev); 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, ...@@ -496,12 +504,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
#define RADEON_GEN_INT_CNTL 0x0040 #define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0) # define RADEON_CRTC_VBLANK_MASK (1 << 0)
# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) # define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
# define RADEON_SW_INT_ENABLE (1 << 25) # define RADEON_SW_INT_ENABLE (1 << 25)
#define RADEON_GEN_INT_STATUS 0x0044 #define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_CRTC_VBLANK_STAT (1 << 0) # define RADEON_CRTC_VBLANK_STAT (1 << 0)
# define RADEON_CRTC_VBLANK_STAT_ACK (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_GUI_IDLE_INT_TEST_ACK (1 << 19)
# define RADEON_SW_INT_TEST (1 << 25) # define RADEON_SW_INT_TEST (1 << 25)
# define RADEON_SW_INT_TEST_ACK (1 << 25) # define RADEON_SW_INT_TEST_ACK (1 << 25)
......
...@@ -73,18 +73,35 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -73,18 +73,35 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
* outside the DRM * outside the DRM
*/ */
stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | 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) if (!stat)
return IRQ_NONE; return IRQ_NONE;
stat &= dev_priv->irq_enable_reg;
/* SW interrupt */ /* SW interrupt */
if (stat & RADEON_SW_INT_TEST) { if (stat & RADEON_SW_INT_TEST) {
DRM_WAKEUP(&dev_priv->swi_queue); DRM_WAKEUP(&dev_priv->swi_queue);
} }
/* VBLANK interrupt */ /* 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); atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue); DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev); drm_vbl_send_signals(dev);
} }
...@@ -127,19 +144,30 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr) ...@@ -127,19 +144,30 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
return ret; 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_priv =
(drm_radeon_private_t *) dev->dev_private; (drm_radeon_private_t *) dev->dev_private;
unsigned int cur_vblank; unsigned int cur_vblank;
int ret = 0; int ret = 0;
int ack = 0;
atomic_t *counter;
if (!dev_priv) { if (!dev_priv) {
DRM_ERROR("%s called with no initialization\n", __FUNCTION__); DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL); 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; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
...@@ -148,7 +176,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) ...@@ -148,7 +176,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
* using vertical blanks... * using vertical blanks...
*/ */
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, 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) <= (1 << 23)));
*sequence = cur_vblank; *sequence = cur_vblank;
...@@ -156,6 +184,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) ...@@ -156,6 +184,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret; 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. /* Needs the lock as it touches the ring.
*/ */
int radeon_irq_emit(DRM_IOCTL_ARGS) int radeon_irq_emit(DRM_IOCTL_ARGS)
...@@ -204,6 +242,21 @@ int radeon_irq_wait(DRM_IOCTL_ARGS) ...@@ -204,6 +242,21 @@ int radeon_irq_wait(DRM_IOCTL_ARGS)
return radeon_wait_irq(dev, irqwait.irq_seq); 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 /* drm_dma.h hooks
*/ */
void radeon_driver_irq_preinstall(drm_device_t * dev) void radeon_driver_irq_preinstall(drm_device_t * dev)
...@@ -216,7 +269,8 @@ 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 */ /* Clear bits if they're already high */
radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | 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) void radeon_driver_irq_postinstall(drm_device_t * dev)
...@@ -227,9 +281,7 @@ 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); atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
/* Turn on SW and VBL ints */ radeon_enable_interrupt(dev);
RADEON_WRITE(RADEON_GEN_INT_CNTL,
RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
} }
void radeon_driver_irq_uninstall(drm_device_t * dev) void radeon_driver_irq_uninstall(drm_device_t * dev)
...@@ -239,6 +291,38 @@ 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) if (!dev_priv)
return; return;
dev_priv->irq_enabled = 0;
/* Disable *all* interrupts */ /* Disable *all* interrupts */
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); 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;
}
...@@ -3085,6 +3085,9 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) ...@@ -3085,6 +3085,9 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
else else
value = RADEON_CARD_PCI; value = RADEON_CARD_PCI;
break; break;
case RADEON_PARAM_VBLANK_CRTC:
value = radeon_vblank_crtc_get(dev);
break;
default: default:
DRM_DEBUG("Invalid parameter %d\n", param.param); DRM_DEBUG("Invalid parameter %d\n", param.param);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
...@@ -3141,6 +3144,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) ...@@ -3141,6 +3144,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
break; break;
case RADEON_SETPARAM_VBLANK_CRTC:
return radeon_vblank_crtc_set(dev, sp.value);
break;
default: default:
DRM_DEBUG("Invalid parameter %d\n", sp.param); DRM_DEBUG("Invalid parameter %d\n", sp.param);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment