diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/rs600.c')
-rw-r--r-- | drivers/gpu/drm/radeon/rs600.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index bbea6dee4a94..7e8ce983a908 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -240,6 +240,88 @@ void rs600_mc_fini(struct radeon_device *rdev) | |||
240 | 240 | ||
241 | 241 | ||
242 | /* | 242 | /* |
243 | * Interrupts | ||
244 | */ | ||
245 | int rs600_irq_set(struct radeon_device *rdev) | ||
246 | { | ||
247 | uint32_t tmp = 0; | ||
248 | uint32_t mode_int = 0; | ||
249 | |||
250 | if (rdev->irq.sw_int) { | ||
251 | tmp |= RADEON_SW_INT_ENABLE; | ||
252 | } | ||
253 | if (rdev->irq.crtc_vblank_int[0]) { | ||
254 | tmp |= AVIVO_DISPLAY_INT_STATUS; | ||
255 | mode_int |= AVIVO_D1MODE_INT_MASK; | ||
256 | } | ||
257 | if (rdev->irq.crtc_vblank_int[1]) { | ||
258 | tmp |= AVIVO_DISPLAY_INT_STATUS; | ||
259 | mode_int |= AVIVO_D2MODE_INT_MASK; | ||
260 | } | ||
261 | WREG32(RADEON_GEN_INT_CNTL, tmp); | ||
262 | WREG32(AVIVO_DxMODE_INT_MASK, mode_int); | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int) | ||
267 | { | ||
268 | uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); | ||
269 | uint32_t irq_mask = RADEON_SW_INT_TEST; | ||
270 | |||
271 | if (irqs & AVIVO_DISPLAY_INT_STATUS) { | ||
272 | *r500_disp_int = RREG32(AVIVO_DISP_INTERRUPT_STATUS); | ||
273 | if (*r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) { | ||
274 | WREG32(AVIVO_D1MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK); | ||
275 | } | ||
276 | if (*r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) { | ||
277 | WREG32(AVIVO_D2MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK); | ||
278 | } | ||
279 | } else { | ||
280 | *r500_disp_int = 0; | ||
281 | } | ||
282 | |||
283 | if (irqs) { | ||
284 | WREG32(RADEON_GEN_INT_STATUS, irqs); | ||
285 | } | ||
286 | return irqs & irq_mask; | ||
287 | } | ||
288 | |||
289 | int rs600_irq_process(struct radeon_device *rdev) | ||
290 | { | ||
291 | uint32_t status; | ||
292 | uint32_t r500_disp_int; | ||
293 | |||
294 | status = rs600_irq_ack(rdev, &r500_disp_int); | ||
295 | if (!status && !r500_disp_int) { | ||
296 | return IRQ_NONE; | ||
297 | } | ||
298 | while (status || r500_disp_int) { | ||
299 | /* SW interrupt */ | ||
300 | if (status & RADEON_SW_INT_TEST) { | ||
301 | radeon_fence_process(rdev); | ||
302 | } | ||
303 | /* Vertical blank interrupts */ | ||
304 | if (r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) { | ||
305 | drm_handle_vblank(rdev->ddev, 0); | ||
306 | } | ||
307 | if (r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) { | ||
308 | drm_handle_vblank(rdev->ddev, 1); | ||
309 | } | ||
310 | status = rs600_irq_ack(rdev, &r500_disp_int); | ||
311 | } | ||
312 | return IRQ_HANDLED; | ||
313 | } | ||
314 | |||
315 | u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc) | ||
316 | { | ||
317 | if (crtc == 0) | ||
318 | return RREG32(AVIVO_D1CRTC_FRAME_COUNT); | ||
319 | else | ||
320 | return RREG32(AVIVO_D2CRTC_FRAME_COUNT); | ||
321 | } | ||
322 | |||
323 | |||
324 | /* | ||
243 | * Global GPU functions | 325 | * Global GPU functions |
244 | */ | 326 | */ |
245 | void rs600_disable_vga(struct radeon_device *rdev) | 327 | void rs600_disable_vga(struct radeon_device *rdev) |