drm/radeon/kms: clear confusion in GART init/deinit path
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / r300.c
index a5f82f7..bb151ec 100644 (file)
@@ -31,7 +31,6 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 #include "radeon_drm.h"
-#include "radeon_share.h"
 #include "r100_track.h"
 #include "r300d.h"
 
@@ -43,7 +42,6 @@ int r100_cp_reset(struct radeon_device *rdev);
 int r100_rb2d_reset(struct radeon_device *rdev);
 int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
 int r100_pci_gart_enable(struct radeon_device *rdev);
-void r100_pci_gart_disable(struct radeon_device *rdev);
 void r100_mc_setup(struct radeon_device *rdev);
 void r100_mc_disable_clients(struct radeon_device *rdev);
 int r100_gui_wait_for_idle(struct radeon_device *rdev);
@@ -87,26 +85,57 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
        mb();
 }
 
-int rv370_pcie_gart_enable(struct radeon_device *rdev)
+int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
+{
+       void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+
+       if (i < 0 || i > rdev->gart.num_gpu_pages) {
+               return -EINVAL;
+       }
+       addr = (lower_32_bits(addr) >> 8) |
+              ((upper_32_bits(addr) & 0xff) << 24) |
+              0xc;
+       /* on x86 we want this to be CPU endian, on powerpc
+        * on powerpc without HW swappers, it'll get swapped on way
+        * into VRAM - so no need for cpu_to_le32 on VRAM tables */
+       writel(addr, ((void __iomem *)ptr) + (i * 4));
+       return 0;
+}
+
+int rv370_pcie_gart_init(struct radeon_device *rdev)
 {
-       uint32_t table_addr;
-       uint32_t tmp;
        int r;
 
+       if (rdev->gart.table.vram.robj) {
+               WARN(1, "RV370 PCIE GART already initialized.\n");
+               return 0;
+       }
        /* Initialize common gart structure */
        r = radeon_gart_init(rdev);
-       if (r) {
+       if (r)
                return r;
-       }
        r = rv370_debugfs_pcie_gart_info_init(rdev);
-       if (r) {
+       if (r)
                DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
-       }
        rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
-       r = radeon_gart_table_vram_alloc(rdev);
-       if (r) {
-               return r;
+       rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
+       rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
+       return radeon_gart_table_vram_alloc(rdev);
+}
+
+int rv370_pcie_gart_enable(struct radeon_device *rdev)
+{
+       uint32_t table_addr;
+       uint32_t tmp;
+       int r;
+
+       if (rdev->gart.table.vram.robj == NULL) {
+               dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
+               return -EINVAL;
        }
+       r = radeon_gart_table_vram_pin(rdev);
+       if (r)
+               return r;
        /* discard memory request outside of configured range */
        tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
        WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
@@ -146,45 +175,13 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
        }
 }
 
-int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
-{
-       void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
-
-       if (i < 0 || i > rdev->gart.num_gpu_pages) {
-               return -EINVAL;
-       }
-       addr = (lower_32_bits(addr) >> 8) |
-              ((upper_32_bits(addr) & 0xff) << 24) |
-              0xc;
-       /* on x86 we want this to be CPU endian, on powerpc
-        * on powerpc without HW swappers, it'll get swapped on way
-        * into VRAM - so no need for cpu_to_le32 on VRAM tables */
-       writel(addr, ((void __iomem *)ptr) + (i * 4));
-       return 0;
-}
-
-int r300_gart_enable(struct radeon_device *rdev)
+void rv370_pcie_gart_fini(struct radeon_device *rdev)
 {
-#if __OS_HAS_AGP
-       if (rdev->flags & RADEON_IS_AGP) {
-               if (rdev->family > CHIP_RV350) {
-                       rv370_pcie_gart_disable(rdev);
-               } else {
-                       r100_pci_gart_disable(rdev);
-               }
-               return 0;
-       }
-#endif
-       if (rdev->flags & RADEON_IS_PCIE) {
-               rdev->asic->gart_disable = &rv370_pcie_gart_disable;
-               rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
-               rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
-               return rv370_pcie_gart_enable(rdev);
-       }
-       return r100_pci_gart_enable(rdev);
+       rv370_pcie_gart_disable(rdev);
+       radeon_gart_table_vram_free(rdev);
+       radeon_gart_fini(rdev);
 }
 
-
 /*
  * MC
  */
@@ -232,14 +229,6 @@ int r300_mc_init(struct radeon_device *rdev)
 
 void r300_mc_fini(struct radeon_device *rdev)
 {
-       if (rdev->flags & RADEON_IS_PCIE) {
-               rv370_pcie_gart_disable(rdev);
-               radeon_gart_table_vram_free(rdev);
-       } else {
-               r100_pci_gart_disable(rdev);
-               radeon_gart_table_ram_free(rdev);
-       }
-       radeon_gart_fini(rdev);
 }
 
 
@@ -1235,11 +1224,12 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
 int r300_cs_parse(struct radeon_cs_parser *p)
 {
        struct radeon_cs_packet pkt;
-       struct r100_cs_track track;
+       struct r100_cs_track *track;
        int r;
 
-       r100_cs_track_clear(p->rdev, &track);
-       p->track = &track;
+       track = kzalloc(sizeof(*track), GFP_KERNEL);
+       r100_cs_track_clear(p->rdev, track);
+       p->track = track;
        do {
                r = r100_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
@@ -1269,9 +1259,48 @@ int r300_cs_parse(struct radeon_cs_parser *p)
        return 0;
 }
 
-int r300_init(struct radeon_device *rdev)
+void r300_set_reg_safe(struct radeon_device *rdev)
 {
        rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
        rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
+}
+
+int r300_init(struct radeon_device *rdev)
+{
+       r300_set_reg_safe(rdev);
        return 0;
 }
+
+void r300_mc_program(struct radeon_device *rdev)
+{
+       struct r100_mc_save save;
+       int r;
+
+       r = r100_debugfs_mc_info_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n");
+       }
+
+       /* Stops all mc clients */
+       r100_mc_stop(rdev, &save);
+       if (rdev->flags & RADEON_IS_AGP) {
+               WREG32(R_00014C_MC_AGP_LOCATION,
+                       S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) |
+                       S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
+               WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
+               WREG32(R_00015C_AGP_BASE_2,
+                       upper_32_bits(rdev->mc.agp_base) & 0xff);
+       } else {
+               WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF);
+               WREG32(R_000170_AGP_BASE, 0);
+               WREG32(R_00015C_AGP_BASE_2, 0);
+       }
+       /* Wait for mc idle */
+       if (r300_mc_wait_for_idle(rdev))
+               DRM_INFO("Failed to wait MC idle before programming MC.\n");
+       /* Program MC, should be a 32bits limited address space */
+       WREG32(R_000148_MC_FB_LOCATION,
+               S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
+               S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
+       r100_mc_resume(rdev, &save);
+}