aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher2009-10-16 12:21:24 -0400
committerDave Airlie2009-10-26 13:28:23 +1000
commit3e5cb98dfe87cc61d0a1119dd8aa2b1e4cfab424 (patch)
treed2ce9174cf1257cce348da291c67de9d67d2a69c
parentebbe1cb936dfc96d809ccf4d64a9755f8ba0c0ff (diff)
drm/radeon/kms: add support for msi
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>
-rw-r--r--drivers/gpu/drm/radeon/r100.c17
-rw-r--r--drivers/gpu/drm/radeon/radeon.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_reg.h6
-rw-r--r--drivers/gpu/drm/radeon/rs600.c18
5 files changed, 49 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index ed5e983d21e9..b438b520ee7f 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -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;
}
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8b60e36b20ba..ea3efd7ae85b 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -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,
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 8e0a8759e428..a0fe6232dcb6 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -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);
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index bfa1ab9c93e1..29ab75903ec1 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -290,6 +290,8 @@
#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)
@@ -297,6 +299,9 @@
# 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 */
@@ -3311,6 +3316,7 @@
#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
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 10dfa78762da..942754c39be9 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -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;
}