aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2007-07-10 22:16:01 -0400
committerDave Airlie <airlied@linux.ie>2007-07-10 22:16:01 -0400
commitddbee33328dcfb892cd91f2d57a1822f4d6f70d9 (patch)
tree6db71299d2cf09f22201a44487d925e222facb33 /drivers/char/drm
parent7c158acef8f0e51c3a5f71133aaf402628370a64 (diff)
radeon: add support for vblank on crtc2
This adds support for CRTC2 vblank on radeon similiar to the i915. Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/radeon_cp.c4
-rw-r--r--drivers/char/drm/radeon_drm.h6
-rw-r--r--drivers/char/drm/radeon_drv.c3
-rw-r--r--drivers/char/drm/radeon_drv.h13
-rw-r--r--drivers/char/drm/radeon_irq.c106
-rw-r--r--drivers/char/drm/radeon_state.c6
6 files changed, 124 insertions, 14 deletions
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index aac5db3a0eb0..7dd980055229 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1420,6 +1420,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1420 return DRM_ERR(EINVAL); 1420 return DRM_ERR(EINVAL);
1421 } 1421 }
1422 1422
1423 /* Enable vblank on CRTC1 for older X servers
1424 */
1425 dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
1426
1423 switch(init->func) { 1427 switch(init->func) {
1424 case RADEON_INIT_R200_CP: 1428 case RADEON_INIT_R200_CP:
1425 dev_priv->microcode_version = UCODE_R200; 1429 dev_priv->microcode_version = UCODE_R200;
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 66c4b6fed04f..04de7a15df99 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -655,6 +655,7 @@ typedef struct drm_radeon_indirect {
655#define RADEON_PARAM_GART_TEX_HANDLE 10 655#define RADEON_PARAM_GART_TEX_HANDLE 10
656#define RADEON_PARAM_SCRATCH_OFFSET 11 656#define RADEON_PARAM_SCRATCH_OFFSET 11
657#define RADEON_PARAM_CARD_TYPE 12 657#define RADEON_PARAM_CARD_TYPE 12
658#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */
658 659
659typedef struct drm_radeon_getparam { 660typedef struct drm_radeon_getparam {
660 int param; 661 int param;
@@ -708,7 +709,7 @@ typedef struct drm_radeon_setparam {
708#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ 709#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
709#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ 710#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
710#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ 711#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */
711 712#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */
712/* 1.14: Clients can allocate/free a surface 713/* 1.14: Clients can allocate/free a surface
713 */ 714 */
714typedef struct drm_radeon_surface_alloc { 715typedef struct drm_radeon_surface_alloc {
@@ -721,4 +722,7 @@ typedef struct drm_radeon_surface_free {
721 unsigned int address; 722 unsigned int address;
722} drm_radeon_surface_free_t; 723} drm_radeon_surface_free_t;
723 724
725#define DRM_RADEON_VBLANK_CRTC1 1
726#define DRM_RADEON_VBLANK_CRTC2 2
727
724#endif 728#endif
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 2eb652ec6745..349ac3d3b848 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -60,7 +60,7 @@ static struct drm_driver driver = {
60 .driver_features = 60 .driver_features =
61 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | 61 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
62 DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | 62 DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
63 DRIVER_IRQ_VBL, 63 DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
64 .dev_priv_size = sizeof(drm_radeon_buf_priv_t), 64 .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
65 .load = radeon_driver_load, 65 .load = radeon_driver_load,
66 .firstopen = radeon_driver_firstopen, 66 .firstopen = radeon_driver_firstopen,
@@ -70,6 +70,7 @@ static struct drm_driver driver = {
70 .lastclose = radeon_driver_lastclose, 70 .lastclose = radeon_driver_lastclose,
71 .unload = radeon_driver_unload, 71 .unload = radeon_driver_unload,
72 .vblank_wait = radeon_driver_vblank_wait, 72 .vblank_wait = radeon_driver_vblank_wait,
73 .vblank_wait2 = radeon_driver_vblank_wait2,
73 .dri_library_name = dri_library_name, 74 .dri_library_name = dri_library_name,
74 .irq_preinstall = radeon_driver_irq_preinstall, 75 .irq_preinstall = radeon_driver_irq_preinstall,
75 .irq_postinstall = radeon_driver_irq_postinstall, 76 .irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 54f49ef4bef0..4422ae3a68bc 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -97,9 +97,10 @@
97 * new packet type) 97 * new packet type)
98 * 1.26- Add support for variable size PCI(E) gart aperture 98 * 1.26- Add support for variable size PCI(E) gart aperture
99 * 1.27- Add support for IGP GART 99 * 1.27- Add support for IGP GART
100 * 1.28- Add support for VBL on CRTC2
100 */ 101 */
101#define DRIVER_MAJOR 1 102#define DRIVER_MAJOR 1
102#define DRIVER_MINOR 27 103#define DRIVER_MINOR 28
103#define DRIVER_PATCHLEVEL 0 104#define DRIVER_PATCHLEVEL 0
104 105
105/* 106/*
@@ -277,6 +278,9 @@ typedef struct drm_radeon_private {
277 /* SW interrupt */ 278 /* SW interrupt */
278 wait_queue_head_t swi_queue; 279 wait_queue_head_t swi_queue;
279 atomic_t swi_emitted; 280 atomic_t swi_emitted;
281 int vblank_crtc;
282 uint32_t irq_enable_reg;
283 int irq_enabled;
280 284
281 struct radeon_surface surfaces[RADEON_MAX_SURFACES]; 285 struct radeon_surface surfaces[RADEON_MAX_SURFACES];
282 struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; 286 struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
@@ -356,10 +360,14 @@ extern int radeon_irq_wait(DRM_IOCTL_ARGS);
356extern void radeon_do_release(drm_device_t * dev); 360extern void radeon_do_release(drm_device_t * dev);
357extern int radeon_driver_vblank_wait(drm_device_t * dev, 361extern int radeon_driver_vblank_wait(drm_device_t * dev,
358 unsigned int *sequence); 362 unsigned int *sequence);
363extern int radeon_driver_vblank_wait2(drm_device_t * dev,
364 unsigned int *sequence);
359extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); 365extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
360extern void radeon_driver_irq_preinstall(drm_device_t * dev); 366extern void radeon_driver_irq_preinstall(drm_device_t * dev);
361extern void radeon_driver_irq_postinstall(drm_device_t * dev); 367extern void radeon_driver_irq_postinstall(drm_device_t * dev);
362extern void radeon_driver_irq_uninstall(drm_device_t * dev); 368extern void radeon_driver_irq_uninstall(drm_device_t * dev);
369extern int radeon_vblank_crtc_get(drm_device_t *dev);
370extern int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value);
363 371
364extern int radeon_driver_load(struct drm_device *dev, unsigned long flags); 372extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
365extern int radeon_driver_unload(struct drm_device *dev); 373extern 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 504
497#define RADEON_GEN_INT_CNTL 0x0040 505#define RADEON_GEN_INT_CNTL 0x0040
498# define RADEON_CRTC_VBLANK_MASK (1 << 0) 506# define RADEON_CRTC_VBLANK_MASK (1 << 0)
507# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
499# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) 508# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
500# define RADEON_SW_INT_ENABLE (1 << 25) 509# define RADEON_SW_INT_ENABLE (1 << 25)
501 510
502#define RADEON_GEN_INT_STATUS 0x0044 511#define RADEON_GEN_INT_STATUS 0x0044
503# define RADEON_CRTC_VBLANK_STAT (1 << 0) 512# define RADEON_CRTC_VBLANK_STAT (1 << 0)
504# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) 513# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0)
514# define RADEON_CRTC2_VBLANK_STAT (1 << 9)
515# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9)
505# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) 516# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19)
506# define RADEON_SW_INT_TEST (1 << 25) 517# define RADEON_SW_INT_TEST (1 << 25)
507# define RADEON_SW_INT_TEST_ACK (1 << 25) 518# define RADEON_SW_INT_TEST_ACK (1 << 25)
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 3ff0baa2fbfa..a4be86e38121 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -73,18 +73,35 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
73 * outside the DRM 73 * outside the DRM
74 */ 74 */
75 stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | 75 stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
76 RADEON_CRTC_VBLANK_STAT)); 76 RADEON_CRTC_VBLANK_STAT |
77 RADEON_CRTC2_VBLANK_STAT));
77 if (!stat) 78 if (!stat)
78 return IRQ_NONE; 79 return IRQ_NONE;
79 80
81 stat &= dev_priv->irq_enable_reg;
82
80 /* SW interrupt */ 83 /* SW interrupt */
81 if (stat & RADEON_SW_INT_TEST) { 84 if (stat & RADEON_SW_INT_TEST) {
82 DRM_WAKEUP(&dev_priv->swi_queue); 85 DRM_WAKEUP(&dev_priv->swi_queue);
83 } 86 }
84 87
85 /* VBLANK interrupt */ 88 /* VBLANK interrupt */
86 if (stat & RADEON_CRTC_VBLANK_STAT) { 89 if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
87 atomic_inc(&dev->vbl_received); 90 int vblank_crtc = dev_priv->vblank_crtc;
91
92 if ((vblank_crtc &
93 (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
94 (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
95 if (stat & RADEON_CRTC_VBLANK_STAT)
96 atomic_inc(&dev->vbl_received);
97 if (stat & RADEON_CRTC2_VBLANK_STAT)
98 atomic_inc(&dev->vbl_received2);
99 } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
100 (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
101 ((stat & RADEON_CRTC2_VBLANK_STAT) &&
102 (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
103 atomic_inc(&dev->vbl_received);
104
88 DRM_WAKEUP(&dev->vbl_queue); 105 DRM_WAKEUP(&dev->vbl_queue);
89 drm_vbl_send_signals(dev); 106 drm_vbl_send_signals(dev);
90 } 107 }
@@ -127,19 +144,30 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
127 return ret; 144 return ret;
128} 145}
129 146
130int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) 147int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
148 int crtc)
131{ 149{
132 drm_radeon_private_t *dev_priv = 150 drm_radeon_private_t *dev_priv =
133 (drm_radeon_private_t *) dev->dev_private; 151 (drm_radeon_private_t *) dev->dev_private;
134 unsigned int cur_vblank; 152 unsigned int cur_vblank;
135 int ret = 0; 153 int ret = 0;
136 154 int ack = 0;
155 atomic_t *counter;
137 if (!dev_priv) { 156 if (!dev_priv) {
138 DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 157 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
139 return DRM_ERR(EINVAL); 158 return DRM_ERR(EINVAL);
140 } 159 }
141 160
142 radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT); 161 if (crtc == DRM_RADEON_VBLANK_CRTC1) {
162 counter = &dev->vbl_received;
163 ack |= RADEON_CRTC_VBLANK_STAT;
164 } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
165 counter = &dev->vbl_received2;
166 ack |= RADEON_CRTC2_VBLANK_STAT;
167 } else
168 return DRM_ERR(EINVAL);
169
170 radeon_acknowledge_irqs(dev_priv, ack);
143 171
144 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 172 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
145 173
@@ -148,7 +176,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
148 * using vertical blanks... 176 * using vertical blanks...
149 */ 177 */
150 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, 178 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
151 (((cur_vblank = atomic_read(&dev->vbl_received)) 179 (((cur_vblank = atomic_read(counter))
152 - *sequence) <= (1 << 23))); 180 - *sequence) <= (1 << 23)));
153 181
154 *sequence = cur_vblank; 182 *sequence = cur_vblank;
@@ -156,6 +184,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
156 return ret; 184 return ret;
157} 185}
158 186
187int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
188{
189 return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
190}
191
192int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
193{
194 return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
195}
196
159/* Needs the lock as it touches the ring. 197/* Needs the lock as it touches the ring.
160 */ 198 */
161int radeon_irq_emit(DRM_IOCTL_ARGS) 199int radeon_irq_emit(DRM_IOCTL_ARGS)
@@ -204,6 +242,21 @@ int radeon_irq_wait(DRM_IOCTL_ARGS)
204 return radeon_wait_irq(dev, irqwait.irq_seq); 242 return radeon_wait_irq(dev, irqwait.irq_seq);
205} 243}
206 244
245static void radeon_enable_interrupt(drm_device_t *dev)
246{
247 drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
248
249 dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
250 if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
251 dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
252
253 if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
254 dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
255
256 RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
257 dev_priv->irq_enabled = 1;
258}
259
207/* drm_dma.h hooks 260/* drm_dma.h hooks
208*/ 261*/
209void radeon_driver_irq_preinstall(drm_device_t * dev) 262void radeon_driver_irq_preinstall(drm_device_t * dev)
@@ -216,7 +269,8 @@ void radeon_driver_irq_preinstall(drm_device_t * dev)
216 269
217 /* Clear bits if they're already high */ 270 /* Clear bits if they're already high */
218 radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | 271 radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
219 RADEON_CRTC_VBLANK_STAT)); 272 RADEON_CRTC_VBLANK_STAT |
273 RADEON_CRTC2_VBLANK_STAT));
220} 274}
221 275
222void radeon_driver_irq_postinstall(drm_device_t * dev) 276void radeon_driver_irq_postinstall(drm_device_t * dev)
@@ -227,9 +281,7 @@ void radeon_driver_irq_postinstall(drm_device_t * dev)
227 atomic_set(&dev_priv->swi_emitted, 0); 281 atomic_set(&dev_priv->swi_emitted, 0);
228 DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); 282 DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
229 283
230 /* Turn on SW and VBL ints */ 284 radeon_enable_interrupt(dev);
231 RADEON_WRITE(RADEON_GEN_INT_CNTL,
232 RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
233} 285}
234 286
235void radeon_driver_irq_uninstall(drm_device_t * dev) 287void radeon_driver_irq_uninstall(drm_device_t * dev)
@@ -239,6 +291,38 @@ void radeon_driver_irq_uninstall(drm_device_t * dev)
239 if (!dev_priv) 291 if (!dev_priv)
240 return; 292 return;
241 293
294 dev_priv->irq_enabled = 0;
295
242 /* Disable *all* interrupts */ 296 /* Disable *all* interrupts */
243 RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); 297 RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
244} 298}
299
300
301int radeon_vblank_crtc_get(drm_device_t *dev)
302{
303 drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
304 u32 flag;
305 u32 value;
306
307 flag = RADEON_READ(RADEON_GEN_INT_CNTL);
308 value = 0;
309
310 if (flag & RADEON_CRTC_VBLANK_MASK)
311 value |= DRM_RADEON_VBLANK_CRTC1;
312
313 if (flag & RADEON_CRTC2_VBLANK_MASK)
314 value |= DRM_RADEON_VBLANK_CRTC2;
315 return value;
316}
317
318int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value)
319{
320 drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
321 if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
322 DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
323 return DRM_ERR(EINVAL);
324 }
325 dev_priv->vblank_crtc = (unsigned int)value;
326 radeon_enable_interrupt(dev);
327 return 0;
328}
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 98c5f1d3a8e7..5b89e471bc71 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -3085,6 +3085,9 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
3085 else 3085 else
3086 value = RADEON_CARD_PCI; 3086 value = RADEON_CARD_PCI;
3087 break; 3087 break;
3088 case RADEON_PARAM_VBLANK_CRTC:
3089 value = radeon_vblank_crtc_get(dev);
3090 break;
3088 default: 3091 default:
3089 DRM_DEBUG("Invalid parameter %d\n", param.param); 3092 DRM_DEBUG("Invalid parameter %d\n", param.param);
3090 return DRM_ERR(EINVAL); 3093 return DRM_ERR(EINVAL);
@@ -3141,6 +3144,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
3141 if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) 3144 if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
3142 dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; 3145 dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
3143 break; 3146 break;
3147 case RADEON_SETPARAM_VBLANK_CRTC:
3148 return radeon_vblank_crtc_set(dev, sp.value);
3149 break;
3144 default: 3150 default:
3145 DRM_DEBUG("Invalid parameter %d\n", sp.param); 3151 DRM_DEBUG("Invalid parameter %d\n", sp.param);
3146 return DRM_ERR(EINVAL); 3152 return DRM_ERR(EINVAL);