drm/radeon/kms: add support for msi
authorAlex Deucher <alexdeucher@gmail.com>
Fri, 16 Oct 2009 16:21:24 +0000 (12:21 -0400)
committerDave Airlie <airlied@redhat.com>
Mon, 26 Oct 2009 03:28:23 +0000 (13:28 +1000)
Try to enable msi on chips that support it.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_reg.h
drivers/gpu/drm/radeon/rs600.c

index ed5e983d21e9e2e8e2cc94c2c017f645054a7f97..b438b520ee7f706e16c570a465b4c825da14fbcd 100644 (file)
@@ -186,7 +186,7 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
 
 int r100_irq_process(struct radeon_device *rdev)
 {
-       uint32_t status;
+       uint32_t status, msi_rearm;
 
        status = r100_irq_ack(rdev);
        if (!status) {
@@ -209,6 +209,21 @@ int r100_irq_process(struct radeon_device *rdev)
                }
                status = r100_irq_ack(rdev);
        }
+       if (rdev->msi_enabled) {
+               switch (rdev->family) {
+               case CHIP_RS400:
+               case CHIP_RS480:
+                       msi_rearm = RREG32(RADEON_AIC_CNTL) & ~RS400_MSI_REARM;
+                       WREG32(RADEON_AIC_CNTL, msi_rearm);
+                       WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM);
+                       break;
+               default:
+                       msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm);
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+                       break;
+               }
+       }
        return IRQ_HANDLED;
 }
 
index 8b60e36b20ba11ad4d5c94e081914f4e45467f5e..ea3efd7ae85bb857c1154e11771897c8e359dcea 100644 (file)
@@ -784,6 +784,7 @@ struct radeon_device {
        const struct firmware *me_fw;   /* all family ME firmware */
        const struct firmware *pfp_fw;  /* r6/700 PFP firmware */
        struct r600_blit r600_blit;
+       int msi_enabled; /* msi enabled */
 };
 
 int radeon_device_init(struct radeon_device *rdev,
index 8e0a8759e428e85a62289b6616352c22d2376e57..a0fe6232dcb6fc8b9ab803ce4b5b7111fae435de 100644 (file)
@@ -92,6 +92,13 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
        if (r) {
                return r;
        }
+       /* enable msi */
+       rdev->msi_enabled = 0;
+       if (rdev->family >= CHIP_RV380) {
+               int ret = pci_enable_msi(rdev->pdev);
+               if (!ret)
+                       rdev->msi_enabled = 1;
+       }
        drm_irq_install(rdev->ddev);
        rdev->irq.installed = true;
        DRM_INFO("radeon: irq initialized.\n");
@@ -103,5 +110,7 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
        if (rdev->irq.installed) {
                rdev->irq.installed = false;
                drm_irq_uninstall(rdev->ddev);
+               if (rdev->msi_enabled)
+                       pci_disable_msi(rdev->pdev);
        }
 }
index bfa1ab9c93e123bd0e066319822af3ba8e880112..29ab75903ec143a42446adff7d75741521d0eb23 100644 (file)
 #define RADEON_BUS_CNTL                     0x0030
 #       define RADEON_BUS_MASTER_DIS         (1 << 6)
 #       define RADEON_BUS_BIOS_DIS_ROM       (1 << 12)
+#      define RS600_BUS_MASTER_DIS          (1 << 14)
+#      define RS600_MSI_REARM               (1 << 20) /* rs600/rs690/rs740 */
 #       define RADEON_BUS_RD_DISCARD_EN      (1 << 24)
 #       define RADEON_BUS_RD_ABORT_EN        (1 << 25)
 #       define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28)
 #       define RADEON_BUS_READ_BURST         (1 << 30)
 #define RADEON_BUS_CNTL1                    0x0034
 #       define RADEON_BUS_WAIT_ON_LOCK_EN    (1 << 4)
+/* rv370/rv380, rv410, r423/r430/r480, r5xx */
+#define RADEON_MSI_REARM_EN                0x0160
+#      define RV370_MSI_REARM_EN            (1 << 0)
 
 /* #define RADEON_PCIE_INDEX                   0x0030 */
 /* #define RADEON_PCIE_DATA                    0x0034 */
 #define RADEON_AIC_CNTL                     0x01d0
 #       define RADEON_PCIGART_TRANSLATE_EN     (1 << 0)
 #       define RADEON_DIS_OUT_OF_PCI_GART_ACCESS     (1 << 1)
+#      define RS400_MSI_REARM                  (1 << 3) /* rs400/rs480 */
 #define RADEON_AIC_LO_ADDR                  0x01dc
 #define RADEON_AIC_PT_BASE             0x01d8
 #define RADEON_AIC_HI_ADDR             0x01e0
index 10dfa78762da22cbac4bd95ba366ae6644417e18..942754c39be9639ec1218d17d9e1b4e55ac006fe 100644 (file)
@@ -242,7 +242,7 @@ void rs600_irq_disable(struct radeon_device *rdev)
 
 int rs600_irq_process(struct radeon_device *rdev)
 {
-       uint32_t status;
+       uint32_t status, msi_rearm;
        uint32_t r500_disp_int;
 
        status = rs600_irq_ack(rdev, &r500_disp_int);
@@ -260,6 +260,22 @@ int rs600_irq_process(struct radeon_device *rdev)
                        drm_handle_vblank(rdev->ddev, 1);
                status = rs600_irq_ack(rdev, &r500_disp_int);
        }
+       if (rdev->msi_enabled) {
+               switch (rdev->family) {
+               case CHIP_RS600:
+               case CHIP_RS690:
+               case CHIP_RS740:
+                       msi_rearm = RREG32(RADEON_BUS_CNTL) & ~RS600_MSI_REARM;
+                       WREG32(RADEON_BUS_CNTL, msi_rearm);
+                       WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM);
+                       break;
+               default:
+                       msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm);
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+                       break;
+               }
+       }
        return IRQ_HANDLED;
 }