drm/radeon: Use direct mapping for fast fb access on RS780/RS880 (v2)
authorSamuel Li <samuel.li@amd.com>
Fri, 5 Apr 2013 21:50:53 +0000 (17:50 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 3 Jun 2013 14:36:21 +0000 (10:36 -0400)
v2: fix trailing whitespace

Signed-off-by: Samuel Li <samuel.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h

index 0f30d0df1e077dc9031808782edfc7ec0ace306d..0e5341695922b504298b103df17c936e95a34d0a 100644 (file)
@@ -1046,6 +1046,24 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev)
        return -1;
 }
 
+uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+       uint32_t r;
+
+       WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg));
+       r = RREG32(R_0028FC_MC_DATA);
+       WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR);
+       return r;
+}
+
+void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+       WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) |
+               S_0028F8_MC_IND_WR_EN(1));
+       WREG32(R_0028FC_MC_DATA, v);
+       WREG32(R_0028F8_MC_INDEX, 0x7F);
+}
+
 static void r600_mc_program(struct radeon_device *rdev)
 {
        struct rv515_mc_save save;
@@ -1181,6 +1199,8 @@ static int r600_mc_init(struct radeon_device *rdev)
 {
        u32 tmp;
        int chansize, numchan;
+       uint32_t h_addr, l_addr;
+       unsigned long long k8_addr;
 
        /* Get VRAM informations */
        rdev->mc.vram_is_ddr = true;
@@ -1221,7 +1241,30 @@ static int r600_mc_init(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_IGP) {
                rs690_pm_info(rdev);
                rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+
+               if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
+                       /* Use K8 direct mapping for fast fb access. */
+                       rdev->fastfb_working = false;
+                       h_addr = G_000012_K8_ADDR_EXT(RREG32_MC(R_000012_MC_MISC_UMA_CNTL));
+                       l_addr = RREG32_MC(R_000011_K8_FB_LOCATION);
+                       k8_addr = ((unsigned long long)h_addr) << 32 | l_addr;
+#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
+                       if (k8_addr + rdev->mc.visible_vram_size < 0x100000000ULL)
+#endif
+                       {
+                               /* FastFB shall be used with UMA memory. Here it is simply disabled when sideport
+                               * memory is present.
+                               */
+                               if (rdev->mc.igp_sideport_enabled == false && radeon_fastfb == 1) {
+                                       DRM_INFO("Direct mapping: aper base at 0x%llx, replaced by direct mapping base 0x%llx.\n",
+                                               (unsigned long long)rdev->mc.aper_base, k8_addr);
+                                       rdev->mc.aper_base = (resource_size_t)k8_addr;
+                                       rdev->fastfb_working = true;
+                               }
+                       }
+               }
        }
+
        radeon_update_bandwidth_info(rdev);
        return 0;
 }
index acb146c06973301fed6654e7b7448983a91fcb08..79df558f8c4088ebe21929034c15bc5fd2c94d16 100644 (file)
 #define        PACKET3_STRMOUT_BASE_UPDATE                     0x72 /* r7xx */
 #define        PACKET3_SURFACE_BASE_UPDATE                     0x73
 
+#define R_000011_K8_FB_LOCATION                 0x11
+#define R_000012_MC_MISC_UMA_CNTL               0x12
+#define   G_000012_K8_ADDR_EXT(x)               (((x) >> 0) & 0xFF)
+#define R_0028F8_MC_INDEX                      0x28F8
+#define        S_0028F8_MC_IND_ADDR(x)                 (((x) & 0x1FF) << 0)
+#define        C_0028F8_MC_IND_ADDR                    0xFFFFFE00
+#define        S_0028F8_MC_IND_WR_EN(x)                (((x) & 0x1) << 9)
+#define R_0028FC_MC_DATA                        0x28FC
 
 #define        R_008020_GRBM_SOFT_RESET                0x8020
 #define                S_008020_SOFT_RESET_CP(x)               (((x) & 1) << 0)
index 06b8c19ab19e7cda0de46325d15291adc8eabf79..a2802b47ee958e230d754f105214070f91ef1f23 100644 (file)
@@ -122,6 +122,10 @@ static void radeon_register_accessor_init(struct radeon_device *rdev)
                rdev->mc_rreg = &rs600_mc_rreg;
                rdev->mc_wreg = &rs600_mc_wreg;
        }
+       if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
+               rdev->mc_rreg = &rs780_mc_rreg;
+               rdev->mc_wreg = &rs780_mc_wreg;
+       }
        if (rdev->family >= CHIP_R600) {
                rdev->pciep_rreg = &r600_pciep_rreg;
                rdev->pciep_wreg = &r600_pciep_wreg;
index 2c87365d345fcf3a5128c9da26dd7b12df6ce757..a72759ede7538390a9360c0764670fcf161018c7 100644 (file)
@@ -347,6 +347,8 @@ extern bool r600_gui_idle(struct radeon_device *rdev);
 extern void r600_pm_misc(struct radeon_device *rdev);
 extern void r600_pm_init_profile(struct radeon_device *rdev);
 extern void rs780_pm_init_profile(struct radeon_device *rdev);
+extern uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+extern void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int r600_get_pcie_lanes(struct radeon_device *rdev);