Signed-off-by: Alex Deucher <alexdeuc...@gmail.com>
---
 drivers/gpu/drm/radeon/evergreen.c      |  228 ++++++++++++++++++++-----------
 drivers/gpu/drm/radeon/r600.c           |  120 ++++++++++-------
 drivers/gpu/drm/radeon/r600d.h          |    9 ++
 drivers/gpu/drm/radeon/radeon.h         |   35 +++++
 drivers/gpu/drm/radeon/radeon_irq_kms.c |    8 +-
 drivers/gpu/drm/radeon/rs600.c          |   37 +++---
 6 files changed, 291 insertions(+), 146 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index f12a5b3..242055a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2031,6 +2031,7 @@ int evergreen_irq_set(struct radeon_device *rdev)
        u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
        u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
        u32 grbm_int_cntl = 0;
+       u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
 
        if (!rdev->irq.installed) {
                WARN(1, "Can't enable IRQ/MSI because no handler is 
installed.\n");
@@ -2108,6 +2109,30 @@ int evergreen_irq_set(struct radeon_device *rdev)
                DRM_DEBUG("gui idle\n");
                grbm_int_cntl |= GUI_IDLE_INT_ENABLE;
        }
+       if (rdev->irq.pflip[0]) {
+               DRM_DEBUG("pflip 0\n");
+               grph1 |= GRPH_PFLIP_INT_MASK;
+       }
+       if (rdev->irq.pflip[1]) {
+               DRM_DEBUG("pflip 1\n");
+               grph2 |= GRPH_PFLIP_INT_MASK;
+       }
+       if (rdev->irq.pflip[2]) {
+               DRM_DEBUG("pflip 2\n");
+               grph3 |= GRPH_PFLIP_INT_MASK;
+       }
+       if (rdev->irq.pflip[3]) {
+               DRM_DEBUG("pflip 3\n");
+               grph4 |= GRPH_PFLIP_INT_MASK;
+       }
+       if (rdev->irq.pflip[4]) {
+               DRM_DEBUG("pflip 4\n");
+               grph5 |= GRPH_PFLIP_INT_MASK;
+       }
+       if (rdev->irq.pflip[5]) {
+               DRM_DEBUG("pflip 5\n");
+               grph6 |= GRPH_PFLIP_INT_MASK;
+       }
 
        WREG32(CP_INT_CNTL, cp_int_cntl);
        WREG32(GRBM_INT_CNTL, grbm_int_cntl);
@@ -2119,6 +2144,13 @@ int evergreen_irq_set(struct radeon_device *rdev)
        WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5);
        WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
 
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2);
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3);
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4);
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5);
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6);
+
        WREG32(DC_HPD1_INT_CONTROL, hpd1);
        WREG32(DC_HPD2_INT_CONTROL, hpd2);
        WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -2129,79 +2161,92 @@ int evergreen_irq_set(struct radeon_device *rdev)
        return 0;
 }
 
-static inline void evergreen_irq_ack(struct radeon_device *rdev,
-                                    u32 *disp_int,
-                                    u32 *disp_int_cont,
-                                    u32 *disp_int_cont2,
-                                    u32 *disp_int_cont3,
-                                    u32 *disp_int_cont4,
-                                    u32 *disp_int_cont5)
+static inline void evergreen_irq_ack(struct radeon_device *rdev)
 {
        u32 tmp;
 
-       *disp_int = RREG32(DISP_INTERRUPT_STATUS);
-       *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
-       *disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2);
-       *disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3);
-       *disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4);
-       *disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
-
-       if (*disp_int & LB_D1_VBLANK_INTERRUPT)
+       rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS);
+       rdev->irq.stat_regs.evergreen.disp_int_cont = 
RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
+       rdev->irq.stat_regs.evergreen.disp_int_cont2 = 
RREG32(DISP_INTERRUPT_STATUS_CONTINUE2);
+       rdev->irq.stat_regs.evergreen.disp_int_cont3 = 
RREG32(DISP_INTERRUPT_STATUS_CONTINUE3);
+       rdev->irq.stat_regs.evergreen.disp_int_cont4 = 
RREG32(DISP_INTERRUPT_STATUS_CONTINUE4);
+       rdev->irq.stat_regs.evergreen.disp_int_cont5 = 
RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
+       rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + 
EVERGREEN_CRTC0_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + 
EVERGREEN_CRTC1_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + 
EVERGREEN_CRTC2_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + 
EVERGREEN_CRTC3_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + 
EVERGREEN_CRTC4_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + 
EVERGREEN_CRTC5_REGISTER_OFFSET);
+
+       if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, 
GRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, 
GRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, 
GRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, 
GRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, 
GRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, 
GRPH_PFLIP_INT_CLEAR);
+
+       if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
                WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, 
VBLANK_ACK);
-       if (*disp_int & LB_D1_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
                WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, 
VLINE_ACK);
 
-       if (*disp_int_cont & LB_D2_VBLANK_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont & 
LB_D2_VBLANK_INTERRUPT)
                WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, 
VBLANK_ACK);
-       if (*disp_int_cont & LB_D2_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)
                WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, 
VLINE_ACK);
 
-       if (*disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & 
LB_D3_VBLANK_INTERRUPT)
                WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, 
VBLANK_ACK);
-       if (*disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & 
LB_D3_VLINE_INTERRUPT)
                WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, 
VLINE_ACK);
 
-       if (*disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & 
LB_D4_VBLANK_INTERRUPT)
                WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, 
VBLANK_ACK);
-       if (*disp_int_cont3 & LB_D4_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & 
LB_D4_VLINE_INTERRUPT)
                WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, 
VLINE_ACK);
 
-       if (*disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & 
LB_D5_VBLANK_INTERRUPT)
                WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, 
VBLANK_ACK);
-       if (*disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & 
LB_D5_VLINE_INTERRUPT)
                WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, 
VLINE_ACK);
 
-       if (*disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & 
LB_D6_VBLANK_INTERRUPT)
                WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, 
VBLANK_ACK);
-       if (*disp_int_cont5 & LB_D6_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & 
LB_D6_VLINE_INTERRUPT)
                WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, 
VLINE_ACK);
 
-       if (*disp_int & DC_HPD1_INTERRUPT) {
+       if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) {
                tmp = RREG32(DC_HPD1_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD1_INT_CONTROL, tmp);
        }
-       if (*disp_int_cont & DC_HPD2_INTERRUPT) {
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) {
                tmp = RREG32(DC_HPD2_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD2_INT_CONTROL, tmp);
        }
-       if (*disp_int_cont2 & DC_HPD3_INTERRUPT) {
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) {
                tmp = RREG32(DC_HPD3_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD3_INT_CONTROL, tmp);
        }
-       if (*disp_int_cont3 & DC_HPD4_INTERRUPT) {
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) {
                tmp = RREG32(DC_HPD4_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD4_INT_CONTROL, tmp);
        }
-       if (*disp_int_cont4 & DC_HPD5_INTERRUPT) {
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) {
                tmp = RREG32(DC_HPD5_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD5_INT_CONTROL, tmp);
        }
-       if (*disp_int_cont5 & DC_HPD6_INTERRUPT) {
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
                tmp = RREG32(DC_HPD5_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
@@ -2210,14 +2255,10 @@ static inline void evergreen_irq_ack(struct 
radeon_device *rdev,
 
 void evergreen_irq_disable(struct radeon_device *rdev)
 {
-       u32 disp_int, disp_int_cont, disp_int_cont2;
-       u32 disp_int_cont3, disp_int_cont4, disp_int_cont5;
-
        r600_disable_interrupts(rdev);
        /* Wait and acknowledge irq */
        mdelay(1);
-       evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2,
-                         &disp_int_cont3, &disp_int_cont4, &disp_int_cont5);
+       evergreen_irq_ack(rdev);
        evergreen_disable_interrupt_state(rdev);
 }
 
@@ -2257,8 +2298,6 @@ int evergreen_irq_process(struct radeon_device *rdev)
        u32 rptr = rdev->ih.rptr;
        u32 src_id, src_data;
        u32 ring_index;
-       u32 disp_int, disp_int_cont, disp_int_cont2;
-       u32 disp_int_cont3, disp_int_cont4, disp_int_cont5;
        unsigned long flags;
        bool queue_hotplug = false;
 
@@ -2279,8 +2318,7 @@ int evergreen_irq_process(struct radeon_device *rdev)
 
 restart_ih:
        /* display interrupts */
-       evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2,
-                         &disp_int_cont3, &disp_int_cont4, &disp_int_cont5);
+       evergreen_irq_ack(rdev);
 
        rdev->ih.wptr = wptr;
        while (rptr != wptr) {
@@ -2293,16 +2331,16 @@ restart_ih:
                case 1: /* D1 vblank/vline */
                        switch (src_data) {
                        case 0: /* D1 vblank */
-                               if (disp_int & LB_D1_VBLANK_INTERRUPT) {
+                               if (rdev->irq.stat_regs.evergreen.disp_int & 
LB_D1_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 0);
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int &= ~LB_D1_VBLANK_INTERRUPT;
+                                       rdev->irq.stat_regs.evergreen.disp_int 
&= ~LB_D1_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D1 vblank\n");
                                }
                                break;
                        case 1: /* D1 vline */
-                               if (disp_int & LB_D1_VLINE_INTERRUPT) {
-                                       disp_int &= ~LB_D1_VLINE_INTERRUPT;
+                               if (rdev->irq.stat_regs.evergreen.disp_int & 
LB_D1_VLINE_INTERRUPT) {
+                                       rdev->irq.stat_regs.evergreen.disp_int 
&= ~LB_D1_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D1 vline\n");
                                }
                                break;
@@ -2314,16 +2352,16 @@ restart_ih:
                case 2: /* D2 vblank/vline */
                        switch (src_data) {
                        case 0: /* D2 vblank */
-                               if (disp_int_cont & LB_D2_VBLANK_INTERRUPT) {
+                               if (rdev->irq.stat_regs.evergreen.disp_int_cont 
& LB_D2_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 1);
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int_cont &= 
~LB_D2_VBLANK_INTERRUPT;
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D2 vblank\n");
                                }
                                break;
                        case 1: /* D2 vline */
-                               if (disp_int_cont & LB_D2_VLINE_INTERRUPT) {
-                                       disp_int_cont &= ~LB_D2_VLINE_INTERRUPT;
+                               if (rdev->irq.stat_regs.evergreen.disp_int_cont 
& LB_D2_VLINE_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D2 vline\n");
                                }
                                break;
@@ -2335,16 +2373,16 @@ restart_ih:
                case 3: /* D3 vblank/vline */
                        switch (src_data) {
                        case 0: /* D3 vblank */
-                               if (disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) {
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 2);
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int_cont2 &= 
~LB_D3_VBLANK_INTERRUPT;
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D3 vblank\n");
                                }
                                break;
                        case 1: /* D3 vline */
-                               if (disp_int_cont2 & LB_D3_VLINE_INTERRUPT) {
-                                       disp_int_cont2 &= 
~LB_D3_VLINE_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D3 vline\n");
                                }
                                break;
@@ -2356,16 +2394,16 @@ restart_ih:
                case 4: /* D4 vblank/vline */
                        switch (src_data) {
                        case 0: /* D4 vblank */
-                               if (disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) {
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 3);
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int_cont3 &= 
~LB_D4_VBLANK_INTERRUPT;
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D4 vblank\n");
                                }
                                break;
                        case 1: /* D4 vline */
-                               if (disp_int_cont3 & LB_D4_VLINE_INTERRUPT) {
-                                       disp_int_cont3 &= 
~LB_D4_VLINE_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D4 vline\n");
                                }
                                break;
@@ -2377,16 +2415,16 @@ restart_ih:
                case 5: /* D5 vblank/vline */
                        switch (src_data) {
                        case 0: /* D5 vblank */
-                               if (disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) {
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 4);
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int_cont4 &= 
~LB_D5_VBLANK_INTERRUPT;
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D5 vblank\n");
                                }
                                break;
                        case 1: /* D5 vline */
-                               if (disp_int_cont4 & LB_D5_VLINE_INTERRUPT) {
-                                       disp_int_cont4 &= 
~LB_D5_VLINE_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D5 vline\n");
                                }
                                break;
@@ -2398,16 +2436,16 @@ restart_ih:
                case 6: /* D6 vblank/vline */
                        switch (src_data) {
                        case 0: /* D6 vblank */
-                               if (disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) {
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 5);
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int_cont5 &= 
~LB_D6_VBLANK_INTERRUPT;
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D6 vblank\n");
                                }
                                break;
                        case 1: /* D6 vline */
-                               if (disp_int_cont5 & LB_D6_VLINE_INTERRUPT) {
-                                       disp_int_cont5 &= 
~LB_D6_VLINE_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D6 vline\n");
                                }
                                break;
@@ -2416,46 +2454,82 @@ restart_ih:
                                break;
                        }
                        break;
+               case 8: /* D1 pflip */
+                       if (rdev->irq.stat_regs.evergreen.d1grph_int & 
GRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.evergreen.d1grph_int &= 
~GRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D1 pflip\n");
+                       }
+                       break;
+               case 10: /* D2 pflip */
+                       if (rdev->irq.stat_regs.evergreen.d2grph_int & 
GRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.evergreen.d2grph_int &= 
~GRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D2 pflip\n");
+                       }
+                       break;
+               case 12: /* D3 pflip */
+                       if (rdev->irq.stat_regs.evergreen.d3grph_int & 
GRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.evergreen.d3grph_int &= 
~GRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D3 pflip\n");
+                       }
+                       break;
+               case 14: /* D4 pflip */
+                       if (rdev->irq.stat_regs.evergreen.d4grph_int & 
GRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.evergreen.d4grph_int &= 
~GRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D4 pflip\n");
+                       }
+                       break;
+               case 16: /* D5 pflip */
+                       if (rdev->irq.stat_regs.evergreen.d5grph_int & 
GRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.evergreen.d5grph_int &= 
~GRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D5 pflip\n");
+                       }
+                       break;
+               case 18: /* D6 pflip */
+                       if (rdev->irq.stat_regs.evergreen.d6grph_int & 
GRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.evergreen.d6grph_int &= 
~GRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D6 pflip\n");
+                       }
+                       break;
                case 42: /* HPD hotplug */
                        switch (src_data) {
                        case 0:
-                               if (disp_int & DC_HPD1_INTERRUPT) {
-                                       disp_int &= ~DC_HPD1_INTERRUPT;
+                               if (rdev->irq.stat_regs.evergreen.disp_int & 
DC_HPD1_INTERRUPT) {
+                                       rdev->irq.stat_regs.evergreen.disp_int 
&= ~DC_HPD1_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD1\n");
                                }
                                break;
                        case 1:
-                               if (disp_int_cont & DC_HPD2_INTERRUPT) {
-                                       disp_int_cont &= ~DC_HPD2_INTERRUPT;
+                               if (rdev->irq.stat_regs.evergreen.disp_int_cont 
& DC_HPD2_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD2\n");
                                }
                                break;
                        case 2:
-                               if (disp_int_cont2 & DC_HPD3_INTERRUPT) {
-                                       disp_int_cont2 &= ~DC_HPD3_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD3\n");
                                }
                                break;
                        case 3:
-                               if (disp_int_cont3 & DC_HPD4_INTERRUPT) {
-                                       disp_int_cont3 &= ~DC_HPD4_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD4\n");
                                }
                                break;
                        case 4:
-                               if (disp_int_cont4 & DC_HPD5_INTERRUPT) {
-                                       disp_int_cont4 &= ~DC_HPD5_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD5\n");
                                }
                                break;
                        case 5:
-                               if (disp_int_cont5 & DC_HPD6_INTERRUPT) {
-                                       disp_int_cont5 &= ~DC_HPD6_INTERRUPT;
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD6\n");
                                }
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 33952a1..d1d91e9 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2869,6 +2869,8 @@ static void r600_disable_interrupt_state(struct 
radeon_device *rdev)
        WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
        WREG32(GRBM_INT_CNTL, 0);
        WREG32(DxMODE_INT_MASK, 0);
+       WREG32(D1GRPH_INTERRUPT_CONTROL, 0);
+       WREG32(D2GRPH_INTERRUPT_CONTROL, 0);
        if (ASIC_IS_DCE3(rdev)) {
                WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0);
                WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0);
@@ -2993,6 +2995,7 @@ int r600_irq_set(struct radeon_device *rdev)
        u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
        u32 grbm_int_cntl = 0;
        u32 hdmi1, hdmi2;
+       u32 d1grph = 0, d2grph = 0;
 
        if (!rdev->irq.installed) {
                WARN(1, "Can't enable IRQ/MSI because no handler is 
installed.\n");
@@ -3073,9 +3076,19 @@ int r600_irq_set(struct radeon_device *rdev)
                DRM_DEBUG("gui idle\n");
                grbm_int_cntl |= GUI_IDLE_INT_ENABLE;
        }
+       if (rdev->irq.pflip[0]) {
+               DRM_DEBUG("pflip 0\n");
+               d1grph |= DxGRPH_PFLIP_INT_MASK;
+       }
+       if (rdev->irq.pflip[1]) {
+               DRM_DEBUG("pflip 1\n");
+               d2grph |= DxGRPH_PFLIP_INT_MASK;
+       }
 
        WREG32(CP_INT_CNTL, cp_int_cntl);
        WREG32(DxMODE_INT_MASK, mode_int);
+       WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph);
+       WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph);
        WREG32(GRBM_INT_CNTL, grbm_int_cntl);
        WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1);
        if (ASIC_IS_DCE3(rdev)) {
@@ -3098,32 +3111,35 @@ int r600_irq_set(struct radeon_device *rdev)
        return 0;
 }
 
-static inline void r600_irq_ack(struct radeon_device *rdev,
-                               u32 *disp_int,
-                               u32 *disp_int_cont,
-                               u32 *disp_int_cont2)
+static inline void r600_irq_ack(struct radeon_device *rdev)
 {
        u32 tmp;
 
        if (ASIC_IS_DCE3(rdev)) {
-               *disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
-               *disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
-               *disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
+               rdev->irq.stat_regs.r600.disp_int = 
RREG32(DCE3_DISP_INTERRUPT_STATUS);
+               rdev->irq.stat_regs.r600.disp_int_cont = 
RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
+               rdev->irq.stat_regs.r600.disp_int_cont2 = 
RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
        } else {
-               *disp_int = RREG32(DISP_INTERRUPT_STATUS);
-               *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
-               *disp_int_cont2 = 0;
-       }
-
-       if (*disp_int & LB_D1_VBLANK_INTERRUPT)
+               rdev->irq.stat_regs.r600.disp_int = 
RREG32(DISP_INTERRUPT_STATUS);
+               rdev->irq.stat_regs.r600.disp_int_cont = 
RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
+               rdev->irq.stat_regs.r600.disp_int_cont2 = 0;
+       }
+       rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
+       rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
+
+       if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED)
+               WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED)
+               WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)
                WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
-       if (*disp_int & LB_D1_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)
                WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
-       if (*disp_int & LB_D2_VBLANK_INTERRUPT)
+       if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)
                WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
-       if (*disp_int & LB_D2_VLINE_INTERRUPT)
+       if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)
                WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
-       if (*disp_int & DC_HPD1_INTERRUPT) {
+       if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) {
                if (ASIC_IS_DCE3(rdev)) {
                        tmp = RREG32(DC_HPD1_INT_CONTROL);
                        tmp |= DC_HPDx_INT_ACK;
@@ -3134,7 +3150,7 @@ static inline void r600_irq_ack(struct radeon_device 
*rdev,
                        WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
                }
        }
-       if (*disp_int & DC_HPD2_INTERRUPT) {
+       if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) {
                if (ASIC_IS_DCE3(rdev)) {
                        tmp = RREG32(DC_HPD2_INT_CONTROL);
                        tmp |= DC_HPDx_INT_ACK;
@@ -3145,7 +3161,7 @@ static inline void r600_irq_ack(struct radeon_device 
*rdev,
                        WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
                }
        }
-       if (*disp_int_cont & DC_HPD3_INTERRUPT) {
+       if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) {
                if (ASIC_IS_DCE3(rdev)) {
                        tmp = RREG32(DC_HPD3_INT_CONTROL);
                        tmp |= DC_HPDx_INT_ACK;
@@ -3156,18 +3172,18 @@ static inline void r600_irq_ack(struct radeon_device 
*rdev,
                        WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
                }
        }
-       if (*disp_int_cont & DC_HPD4_INTERRUPT) {
+       if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) {
                tmp = RREG32(DC_HPD4_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD4_INT_CONTROL, tmp);
        }
        if (ASIC_IS_DCE32(rdev)) {
-               if (*disp_int_cont2 & DC_HPD5_INTERRUPT) {
+               if (rdev->irq.stat_regs.r600.disp_int_cont2 & 
DC_HPD5_INTERRUPT) {
                        tmp = RREG32(DC_HPD5_INT_CONTROL);
                        tmp |= DC_HPDx_INT_ACK;
                        WREG32(DC_HPD5_INT_CONTROL, tmp);
                }
-               if (*disp_int_cont2 & DC_HPD6_INTERRUPT) {
+               if (rdev->irq.stat_regs.r600.disp_int_cont2 & 
DC_HPD6_INTERRUPT) {
                        tmp = RREG32(DC_HPD5_INT_CONTROL);
                        tmp |= DC_HPDx_INT_ACK;
                        WREG32(DC_HPD6_INT_CONTROL, tmp);
@@ -3189,12 +3205,10 @@ static inline void r600_irq_ack(struct radeon_device 
*rdev,
 
 void r600_irq_disable(struct radeon_device *rdev)
 {
-       u32 disp_int, disp_int_cont, disp_int_cont2;
-
        r600_disable_interrupts(rdev);
        /* Wait and acknowledge irq */
        mdelay(1);
-       r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
+       r600_irq_ack(rdev);
        r600_disable_interrupt_state(rdev);
 }
 
@@ -3257,7 +3271,7 @@ int r600_irq_process(struct radeon_device *rdev)
        u32 wptr = r600_get_ih_wptr(rdev);
        u32 rptr = rdev->ih.rptr;
        u32 src_id, src_data;
-       u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
+       u32 ring_index;
        unsigned long flags;
        bool queue_hotplug = false;
 
@@ -3278,7 +3292,7 @@ int r600_irq_process(struct radeon_device *rdev)
 
 restart_ih:
        /* display interrupts */
-       r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
+       r600_irq_ack(rdev);
 
        rdev->ih.wptr = wptr;
        while (rptr != wptr) {
@@ -3291,17 +3305,17 @@ restart_ih:
                case 1: /* D1 vblank/vline */
                        switch (src_data) {
                        case 0: /* D1 vblank */
-                               if (disp_int & LB_D1_VBLANK_INTERRUPT) {
+                               if (rdev->irq.stat_regs.r600.disp_int & 
LB_D1_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 0);
                                        rdev->pm.vblank_sync = true;
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int &= ~LB_D1_VBLANK_INTERRUPT;
+                                       rdev->irq.stat_regs.r600.disp_int &= 
~LB_D1_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D1 vblank\n");
                                }
                                break;
                        case 1: /* D1 vline */
-                               if (disp_int & LB_D1_VLINE_INTERRUPT) {
-                                       disp_int &= ~LB_D1_VLINE_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int & 
LB_D1_VLINE_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int &= 
~LB_D1_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D1 vline\n");
                                }
                                break;
@@ -3313,17 +3327,17 @@ restart_ih:
                case 5: /* D2 vblank/vline */
                        switch (src_data) {
                        case 0: /* D2 vblank */
-                               if (disp_int & LB_D2_VBLANK_INTERRUPT) {
+                               if (rdev->irq.stat_regs.r600.disp_int & 
LB_D2_VBLANK_INTERRUPT) {
                                        drm_handle_vblank(rdev->ddev, 1);
                                        rdev->pm.vblank_sync = true;
                                        wake_up(&rdev->irq.vblank_queue);
-                                       disp_int &= ~LB_D2_VBLANK_INTERRUPT;
+                                       rdev->irq.stat_regs.r600.disp_int &= 
~LB_D2_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D2 vblank\n");
                                }
                                break;
                        case 1: /* D1 vline */
-                               if (disp_int & LB_D2_VLINE_INTERRUPT) {
-                                       disp_int &= ~LB_D2_VLINE_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int & 
LB_D2_VLINE_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int &= 
~LB_D2_VLINE_INTERRUPT;
                                        DRM_DEBUG("IH: D2 vline\n");
                                }
                                break;
@@ -3332,46 +3346,58 @@ restart_ih:
                                break;
                        }
                        break;
+               case 9: /* D1 pflip */
+                       if (rdev->irq.stat_regs.r600.d1grph_int & 
DxGRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.r600.d1grph_int &= 
~DxGRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D1 pflip\n");
+                       }
+                       break;
+               case 11: /* D2 pflip */
+                       if (rdev->irq.stat_regs.r600.d2grph_int & 
DxGRPH_PFLIP_INT_OCCURRED) {
+                               rdev->irq.stat_regs.r600.d2grph_int &= 
~DxGRPH_PFLIP_INT_OCCURRED;
+                               DRM_DEBUG("IH: D2 pflip\n");
+                       }
+                       break;
                case 19: /* HPD/DAC hotplug */
                        switch (src_data) {
                        case 0:
-                               if (disp_int & DC_HPD1_INTERRUPT) {
-                                       disp_int &= ~DC_HPD1_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int & 
DC_HPD1_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int &= 
~DC_HPD1_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD1\n");
                                }
                                break;
                        case 1:
-                               if (disp_int & DC_HPD2_INTERRUPT) {
-                                       disp_int &= ~DC_HPD2_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int & 
DC_HPD2_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int &= 
~DC_HPD2_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD2\n");
                                }
                                break;
                        case 4:
-                               if (disp_int_cont & DC_HPD3_INTERRUPT) {
-                                       disp_int_cont &= ~DC_HPD3_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int_cont & 
DC_HPD3_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int_cont 
&= ~DC_HPD3_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD3\n");
                                }
                                break;
                        case 5:
-                               if (disp_int_cont & DC_HPD4_INTERRUPT) {
-                                       disp_int_cont &= ~DC_HPD4_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int_cont & 
DC_HPD4_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int_cont 
&= ~DC_HPD4_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD4\n");
                                }
                                break;
                        case 10:
-                               if (disp_int_cont2 & DC_HPD5_INTERRUPT) {
-                                       disp_int_cont2 &= ~DC_HPD5_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int_cont2 & 
DC_HPD5_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int_cont2 
&= ~DC_HPD5_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD5\n");
                                }
                                break;
                        case 12:
-                               if (disp_int_cont2 & DC_HPD6_INTERRUPT) {
-                                       disp_int_cont2 &= ~DC_HPD6_INTERRUPT;
+                               if (rdev->irq.stat_regs.r600.disp_int_cont2 & 
DC_HPD6_INTERRUPT) {
+                                       rdev->irq.stat_regs.r600.disp_int_cont2 
&= ~DC_HPD6_INTERRUPT;
                                        queue_hotplug = true;
                                        DRM_DEBUG("IH: HPD6\n");
                                }
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 966a793..45995b4 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -722,6 +722,15 @@
 /* DCE 3.2 */
 #       define DC_HPDx_EN                                 (1 << 28)
 
+#define D1GRPH_INTERRUPT_STATUS                           0x6158
+#define D2GRPH_INTERRUPT_STATUS                           0x6958
+#       define DxGRPH_PFLIP_INT_OCCURRED                  (1 << 0)
+#       define DxGRPH_PFLIP_INT_CLEAR                     (1 << 8)
+#define D1GRPH_INTERRUPT_CONTROL                          0x615c
+#define D2GRPH_INTERRUPT_CONTROL                          0x695c
+#       define DxGRPH_PFLIP_INT_MASK                      (1 << 0)
+#       define DxGRPH_PFLIP_INT_TYPE                      (1 << 8)
+
 /*
  * PM4
  */
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 73f600d..94474e6 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -377,11 +377,45 @@ void radeon_scratch_free(struct radeon_device *rdev, 
uint32_t reg);
 /*
  * IRQS.
  */
+struct r500_irq_stat_regs {
+       u32 disp_int;
+};
+
+struct r600_irq_stat_regs {
+       u32 disp_int;
+       u32 disp_int_cont;
+       u32 disp_int_cont2;
+       u32 d1grph_int;
+       u32 d2grph_int;
+};
+
+struct evergreen_irq_stat_regs {
+       u32 disp_int;
+       u32 disp_int_cont;
+       u32 disp_int_cont2;
+       u32 disp_int_cont3;
+       u32 disp_int_cont4;
+       u32 disp_int_cont5;
+       u32 d1grph_int;
+       u32 d2grph_int;
+       u32 d3grph_int;
+       u32 d4grph_int;
+       u32 d5grph_int;
+       u32 d6grph_int;
+};
+
+union radeon_irq_stat_regs {
+       struct r500_irq_stat_regs r500;
+       struct r600_irq_stat_regs r600;
+       struct evergreen_irq_stat_regs evergreen;
+};
+
 struct radeon_irq {
        bool            installed;
        bool            sw_int;
        /* FIXME: use a define max crtc rather than hardcode it */
        bool            crtc_vblank_int[6];
+       bool            pflip[6];
        wait_queue_head_t       vblank_queue;
        /* FIXME: use defines for max hpd/dacs */
        bool            hpd[6];
@@ -392,6 +426,7 @@ struct radeon_irq {
        bool            hdmi[2];
        spinlock_t sw_lock;
        int sw_refcount;
+       union radeon_irq_stat_regs stat_regs;
 };
 
 int radeon_irq_kms_init(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c 
b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index a108c7e..d2c9647 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -71,8 +71,10 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
        rdev->irq.gui_idle = false;
        for (i = 0; i < rdev->num_crtc; i++)
                rdev->irq.crtc_vblank_int[i] = false;
-       for (i = 0; i < 6; i++)
+       for (i = 0; i < 6; i++) {
                rdev->irq.hpd[i] = false;
+               rdev->irq.pflip[i] = false;
+       }
        radeon_irq_set(rdev);
        /* Clear bits */
        radeon_irq_process(rdev);
@@ -101,8 +103,10 @@ void radeon_driver_irq_uninstall_kms(struct drm_device 
*dev)
        rdev->irq.gui_idle = false;
        for (i = 0; i < rdev->num_crtc; i++)
                rdev->irq.crtc_vblank_int[i] = false;
-       for (i = 0; i < 6; i++)
+       for (i = 0; i < 6; i++) {
                rdev->irq.hpd[i] = false;
+               rdev->irq.pflip[i] = false;
+       }
        radeon_irq_set(rdev);
 }
 
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index b091a1f..834a3a9 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -534,7 +534,7 @@ int rs600_irq_set(struct radeon_device *rdev)
        return 0;
 }
 
-static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 
*r500_disp_int)
+static inline u32 rs600_irq_ack(struct radeon_device *rdev)
 {
        uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS);
        uint32_t irq_mask = S_000044_SW_INT(1);
@@ -547,27 +547,27 @@ static inline uint32_t rs600_irq_ack(struct radeon_device 
*rdev, u32 *r500_disp_
        }
 
        if (G_000044_DISPLAY_INT_STAT(irqs)) {
-               *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
-               if (G_007EDC_LB_D1_VBLANK_INTERRUPT(*r500_disp_int)) {
+               rdev->irq.stat_regs.r500.disp_int = 
RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
+               if 
(G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        WREG32(R_006534_D1MODE_VBLANK_STATUS,
                                S_006534_D1MODE_VBLANK_ACK(1));
                }
-               if (G_007EDC_LB_D2_VBLANK_INTERRUPT(*r500_disp_int)) {
+               if 
(G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        WREG32(R_006D34_D2MODE_VBLANK_STATUS,
                                S_006D34_D2MODE_VBLANK_ACK(1));
                }
-               if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) {
+               if 
(G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
                        tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1);
                        WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
                }
-               if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) {
+               if 
(G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
                        tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1);
                        WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
                }
        } else {
-               *r500_disp_int = 0;
+               rdev->irq.stat_regs.r500.disp_int = 0;
        }
 
        if (irqs) {
@@ -578,29 +578,26 @@ static inline uint32_t rs600_irq_ack(struct radeon_device 
*rdev, u32 *r500_disp_
 
 void rs600_irq_disable(struct radeon_device *rdev)
 {
-       u32 tmp;
-
        WREG32(R_000040_GEN_INT_CNTL, 0);
        WREG32(R_006540_DxMODE_INT_MASK, 0);
        /* Wait and acknowledge irq */
        mdelay(1);
-       rs600_irq_ack(rdev, &tmp);
+       rs600_irq_ack(rdev);
 }
 
 int rs600_irq_process(struct radeon_device *rdev)
 {
-       uint32_t status, msi_rearm;
-       uint32_t r500_disp_int;
+       u32 status, msi_rearm;
        bool queue_hotplug = false;
 
        /* reset gui idle ack.  the status bit is broken */
        rdev->irq.gui_idle_acked = false;
 
-       status = rs600_irq_ack(rdev, &r500_disp_int);
-       if (!status && !r500_disp_int) {
+       status = rs600_irq_ack(rdev);
+       if (!status && !rdev->irq.stat_regs.r500.disp_int) {
                return IRQ_NONE;
        }
-       while (status || r500_disp_int) {
+       while (status || rdev->irq.stat_regs.r500.disp_int) {
                /* SW interrupt */
                if (G_000044_SW_INT(status))
                        radeon_fence_process(rdev);
@@ -611,25 +608,25 @@ int rs600_irq_process(struct radeon_device *rdev)
                        wake_up(&rdev->irq.idle_queue);
                }
                /* Vertical blank interrupts */
-               if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) {
+               if 
(G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        drm_handle_vblank(rdev->ddev, 0);
                        rdev->pm.vblank_sync = true;
                        wake_up(&rdev->irq.vblank_queue);
                }
-               if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) {
+               if 
(G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        drm_handle_vblank(rdev->ddev, 1);
                        rdev->pm.vblank_sync = true;
                        wake_up(&rdev->irq.vblank_queue);
                }
-               if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {
+               if 
(G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        queue_hotplug = true;
                        DRM_DEBUG("HPD1\n");
                }
-               if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) {
+               if 
(G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
                        queue_hotplug = true;
                        DRM_DEBUG("HPD2\n");
                }
-               status = rs600_irq_ack(rdev, &r500_disp_int);
+               status = rs600_irq_ack(rdev);
        }
        /* reset gui idle ack.  the status bit is broken */
        rdev->irq.gui_idle_acked = false;
-- 
1.7.1.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to