drm/radeon: handle vfct with multiple vbios images
[pandora-kernel.git] / drivers / gpu / drm / radeon / ni.c
index 556b7bc..77e6fb1 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include "drmP.h"
 #include "radeon.h"
 #include "radeon_asic.h"
@@ -261,8 +262,11 @@ int ni_mc_load_microcode(struct radeon_device *rdev)
                WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
 
                /* wait for training to complete */
-               while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD))
-                       udelay(10);
+               for (i = 0; i < rdev->usec_timeout; i++) {
+                       if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
+                               break;
+                       udelay(1);
+               }
 
                if (running)
                        WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
@@ -800,8 +804,18 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                rdev->config.cayman.tile_config |= (3 << 0);
                break;
        }
-       rdev->config.cayman.tile_config |=
-               ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
+       switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
+       case 0: /* four banks */
+               rdev->config.cayman.tile_config |= 0 << 4;
+               break;
+       case 1: /* eight banks */
+               rdev->config.cayman.tile_config |= 1 << 4;
+               break;
+       case 2: /* sixteen banks */
+       default:
+               rdev->config.cayman.tile_config |= 2 << 4;
+               break;
+       }
        rdev->config.cayman.tile_config |=
                ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
        rdev->config.cayman.tile_config |=
@@ -932,7 +946,7 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.vram.robj == NULL) {
+       if (rdev->gart.robj == NULL) {
                dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
                return -EINVAL;
        }
@@ -977,8 +991,6 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev)
 
 void cayman_pcie_gart_disable(struct radeon_device *rdev)
 {
-       int r;
-
        /* Disable all tables */
        WREG32(VM_CONTEXT0_CNTL, 0);
        WREG32(VM_CONTEXT1_CNTL, 0);
@@ -994,14 +1006,7 @@ void cayman_pcie_gart_disable(struct radeon_device *rdev)
        WREG32(VM_L2_CNTL2, 0);
        WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
               L2_CACHE_BIGK_FRAGMENT_SIZE(6));
-       if (rdev->gart.table.vram.robj) {
-               r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
-               if (likely(r == 0)) {
-                       radeon_bo_kunmap(rdev->gart.table.vram.robj);
-                       radeon_bo_unpin(rdev->gart.table.vram.robj);
-                       radeon_bo_unreserve(rdev->gart.table.vram.robj);
-               }
-       }
+       radeon_gart_table_vram_unpin(rdev);
 }
 
 void cayman_pcie_gart_fini(struct radeon_device *rdev)
@@ -1348,6 +1353,8 @@ static int cayman_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        evergreen_pcie_gen2_enable(rdev);
 
+       evergreen_mc_program(rdev);
+
        if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
                r = ni_init_microcode(rdev);
                if (r) {
@@ -1361,7 +1368,10 @@ static int cayman_startup(struct radeon_device *rdev)
                return r;
        }
 
-       evergreen_mc_program(rdev);
+       r = r600_vram_scratch_init(rdev);
+       if (r)
+               return r;
+
        r = cayman_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -1380,6 +1390,12 @@ static int cayman_startup(struct radeon_device *rdev)
                return r;
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r = r600_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -1497,10 +1513,6 @@ int cayman_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_irq_kms_init(rdev);
-       if (r)
-               return r;
-
        rdev->cp.ring_obj = NULL;
        r600_ring_init(rdev, 1024 * 1024);
 
@@ -1556,6 +1568,7 @@ void cayman_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        cayman_pcie_gart_fini(rdev);
+       r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);