aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/radeon_irq.c
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/radeon_irq.c
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/radeon_irq.c')
-rw-r--r--drivers/char/drm/radeon_irq.c106
1 files changed, 95 insertions, 11 deletions
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}