drm/radeon/kms: add trivial debugging for voltage
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / rv770.c
index 57765f6..cec536c 100644 (file)
  */
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include "drmP.h"
 #include "radeon.h"
-#include "radeon_share.h"
+#include "radeon_asic.h"
+#include "radeon_drm.h"
 #include "rv770d.h"
-#include "avivod.h"
 #include "atom.h"
+#include "avivod.h"
 
 #define R700_PFP_UCODE_SIZE 848
 #define R700_PM4_UCODE_SIZE 1360
 static void rv770_gpu_init(struct radeon_device *rdev);
 void rv770_fini(struct radeon_device *rdev);
 
+void rv770_pm_misc(struct radeon_device *rdev)
+{
+       int req_ps_idx = rdev->pm.requested_power_state_index;
+       int req_cm_idx = rdev->pm.requested_clock_mode_index;
+       struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
+       struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
+
+       if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+               if (voltage->voltage != rdev->pm.current_vddc) {
+                       radeon_atom_set_voltage(rdev, voltage->voltage);
+                       rdev->pm.current_vddc = voltage->voltage;
+                       DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+               }
+       }
+}
 
 /*
  * GART
@@ -49,18 +66,14 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
        u32 tmp;
        int r, i;
 
-       /* Initialize common gart structure */
-       r = radeon_gart_init(rdev);
-       if (r) {
-               return r;
+       if (rdev->gart.table.vram.robj == NULL) {
+               dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
+               return -EINVAL;
        }
-       rdev->gart.table_size = rdev->gart.num_gpu_pages * 8;
-       r = radeon_gart_table_vram_alloc(rdev);
-       if (r) {
+       r = radeon_gart_table_vram_pin(rdev);
+       if (r)
                return r;
-       }
-       for (i = 0; i < rdev->gart.num_gpu_pages; i++)
-               r600_gart_clear_page(rdev, i);
+       radeon_gart_restore(rdev);
        /* Setup L2 cache */
        WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
                                ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
@@ -80,7 +93,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
        WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
-       WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end - 1) >> 12);
+       WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
        WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
        WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
                                RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
@@ -97,12 +110,8 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
 void rv770_pcie_gart_disable(struct radeon_device *rdev)
 {
        u32 tmp;
-       int i;
+       int i, r;
 
-       /* Clear ptes*/
-       for (i = 0; i < rdev->gart.num_gpu_pages; i++)
-               r600_gart_clear_page(rdev, i);
-       r600_pcie_gart_tlb_flush(rdev);
        /* Disable all tables */
        for (i = 0; i < 7; i++)
                WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
@@ -121,20 +130,54 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev)
        WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
+       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);
+               }
+       }
 }
 
+void rv770_pcie_gart_fini(struct radeon_device *rdev)
+{
+       radeon_gart_fini(rdev);
+       rv770_pcie_gart_disable(rdev);
+       radeon_gart_table_vram_free(rdev);
+}
 
-/*
- * MC
- */
-static void rv770_mc_resume(struct radeon_device *rdev)
+
+void rv770_agp_enable(struct radeon_device *rdev)
+{
+       u32 tmp;
+       int i;
+
+       /* Setup L2 cache */
+       WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
+                               ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+                               EFFECTIVE_L2_QUEUE_SIZE(7));
+       WREG32(VM_L2_CNTL2, 0);
+       WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
+       /* Setup TLB control */
+       tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
+               SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+               SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
+               EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
+       WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+       WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+       WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
+       WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
+       for (i = 0; i < 7; i++)
+               WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
+}
+
+static void rv770_mc_program(struct radeon_device *rdev)
 {
-       u32 d1vga_control, d2vga_control;
-       u32 vga_render_control, vga_hdp_control;
-       u32 d1crtc_control, d2crtc_control;
-       u32 new_d1grph_primary, new_d1grph_secondary;
-       u32 new_d2grph_primary, new_d2grph_secondary;
-       u64 old_vram_start;
+       struct rv515_mc_save save;
        u32 tmp;
        int i, j;
 
@@ -148,53 +191,42 @@ static void rv770_mc_resume(struct radeon_device *rdev)
        }
        WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
 
-       d1vga_control = RREG32(D1VGA_CONTROL);
-       d2vga_control = RREG32(D2VGA_CONTROL);
-       vga_render_control = RREG32(VGA_RENDER_CONTROL);
-       vga_hdp_control = RREG32(VGA_HDP_CONTROL);
-       d1crtc_control = RREG32(D1CRTC_CONTROL);
-       d2crtc_control = RREG32(D2CRTC_CONTROL);
-       old_vram_start = (u64)(RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
-       new_d1grph_primary = RREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS);
-       new_d1grph_secondary = RREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS);
-       new_d1grph_primary += rdev->mc.vram_start - old_vram_start;
-       new_d1grph_secondary += rdev->mc.vram_start - old_vram_start;
-       new_d2grph_primary = RREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS);
-       new_d2grph_secondary = RREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS);
-       new_d2grph_primary += rdev->mc.vram_start - old_vram_start;
-       new_d2grph_secondary += rdev->mc.vram_start - old_vram_start;
-
-       /* Stop all video */
-       WREG32(D1VGA_CONTROL, 0);
-       WREG32(D2VGA_CONTROL, 0);
-       WREG32(VGA_RENDER_CONTROL, 0);
-       WREG32(D1CRTC_UPDATE_LOCK, 1);
-       WREG32(D2CRTC_UPDATE_LOCK, 1);
-       WREG32(D1CRTC_CONTROL, 0);
-       WREG32(D2CRTC_CONTROL, 0);
-       WREG32(D1CRTC_UPDATE_LOCK, 0);
-       WREG32(D2CRTC_UPDATE_LOCK, 0);
-
-       mdelay(1);
+       rv515_mc_stop(rdev, &save);
        if (r600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "[drm] MC not idle !\n");
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
-
        /* Lockout access through VGA aperture*/
        WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
-
        /* Update configuration */
-       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
-       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (rdev->mc.vram_end - 1) >> 12);
+       if (rdev->flags & RADEON_IS_AGP) {
+               if (rdev->mc.vram_start < rdev->mc.gtt_start) {
+                       /* VRAM before AGP */
+                       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                               rdev->mc.vram_start >> 12);
+                       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                               rdev->mc.gtt_end >> 12);
+               } else {
+                       /* VRAM after AGP */
+                       WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                               rdev->mc.gtt_start >> 12);
+                       WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                               rdev->mc.vram_end >> 12);
+               }
+       } else {
+               WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+                       rdev->mc.vram_start >> 12);
+               WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+                       rdev->mc.vram_end >> 12);
+       }
        WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
-       tmp = (((rdev->mc.vram_end - 1) >> 24) & 0xFFFF) << 16;
+       tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
        tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
        WREG32(MC_VM_FB_LOCATION, tmp);
        WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
        WREG32(HDP_NONSURFACE_INFO, (2 << 7));
        WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
        if (rdev->flags & RADEON_IS_AGP) {
-               WREG32(MC_VM_AGP_TOP, (rdev->mc.gtt_end - 1) >> 16);
+               WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
                WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
                WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22);
        } else {
@@ -202,30 +234,13 @@ static void rv770_mc_resume(struct radeon_device *rdev)
                WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
                WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
        }
-       WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS, new_d1grph_primary);
-       WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS, new_d1grph_secondary);
-       WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS, new_d2grph_primary);
-       WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS, new_d2grph_secondary);
-       WREG32(VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start);
-
-       /* Unlock host access */
-       WREG32(VGA_HDP_CONTROL, vga_hdp_control);
-
-       mdelay(1);
        if (r600_mc_wait_for_idle(rdev)) {
-               printk(KERN_WARNING "[drm] MC not idle !\n");
-       }
-
-       /* Restore video state */
-       WREG32(D1CRTC_UPDATE_LOCK, 1);
-       WREG32(D2CRTC_UPDATE_LOCK, 1);
-       WREG32(D1CRTC_CONTROL, d1crtc_control);
-       WREG32(D2CRTC_CONTROL, d2crtc_control);
-       WREG32(D1CRTC_UPDATE_LOCK, 0);
-       WREG32(D2CRTC_UPDATE_LOCK, 0);
-       WREG32(D1VGA_CONTROL, d1vga_control);
-       WREG32(D2VGA_CONTROL, d2vga_control);
-       WREG32(VGA_RENDER_CONTROL, vga_render_control);
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
+       rv515_mc_resume(rdev, &save);
+       /* we need to own VRAM, so turn off the VGA renderer here
+        * to stop it overwriting our objects */
+       rv515_vga_render_disable(rdev);
 }
 
 
@@ -237,7 +252,6 @@ void r700_cp_stop(struct radeon_device *rdev)
        WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
 }
 
-
 static int rv770_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -272,13 +286,19 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev)
        return 0;
 }
 
+void r700_cp_fini(struct radeon_device *rdev)
+{
+       r700_cp_stop(rdev);
+       radeon_ring_fini(rdev);
+}
 
 /*
  * Core functions
  */
-static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
-                                               u32 num_backends,
-                                               u32 backend_disable_mask)
+static u32 r700_get_tile_pipe_to_backend_map(struct radeon_device *rdev,
+                                            u32 num_tile_pipes,
+                                            u32 num_backends,
+                                            u32 backend_disable_mask)
 {
        u32 backend_map = 0;
        u32 enabled_backends_mask;
@@ -287,6 +307,7 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
        u32 swizzle_pipe[R7XX_MAX_PIPES];
        u32 cur_backend;
        u32 i;
+       bool force_no_swizzle;
 
        if (num_tile_pipes > R7XX_MAX_PIPES)
                num_tile_pipes = R7XX_MAX_PIPES;
@@ -316,6 +337,18 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
        if (enabled_backends_count != num_backends)
                num_backends = enabled_backends_count;
 
+       switch (rdev->family) {
+       case CHIP_RV770:
+       case CHIP_RV730:
+               force_no_swizzle = false;
+               break;
+       case CHIP_RV710:
+       case CHIP_RV740:
+       default:
+               force_no_swizzle = true;
+               break;
+       }
+
        memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
        switch (num_tile_pipes) {
        case 1:
@@ -326,49 +359,100 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
                swizzle_pipe[1] = 1;
                break;
        case 3:
-               swizzle_pipe[0] = 0;
-               swizzle_pipe[1] = 2;
-               swizzle_pipe[2] = 1;
+               if (force_no_swizzle) {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 1;
+                       swizzle_pipe[2] = 2;
+               } else {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 2;
+                       swizzle_pipe[2] = 1;
+               }
                break;
        case 4:
-               swizzle_pipe[0] = 0;
-               swizzle_pipe[1] = 2;
-               swizzle_pipe[2] = 3;
-               swizzle_pipe[3] = 1;
+               if (force_no_swizzle) {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 1;
+                       swizzle_pipe[2] = 2;
+                       swizzle_pipe[3] = 3;
+               } else {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 2;
+                       swizzle_pipe[2] = 3;
+                       swizzle_pipe[3] = 1;
+               }
                break;
        case 5:
-               swizzle_pipe[0] = 0;
-               swizzle_pipe[1] = 2;
-               swizzle_pipe[2] = 4;
-               swizzle_pipe[3] = 1;
-               swizzle_pipe[4] = 3;
+               if (force_no_swizzle) {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 1;
+                       swizzle_pipe[2] = 2;
+                       swizzle_pipe[3] = 3;
+                       swizzle_pipe[4] = 4;
+               } else {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 2;
+                       swizzle_pipe[2] = 4;
+                       swizzle_pipe[3] = 1;
+                       swizzle_pipe[4] = 3;
+               }
                break;
        case 6:
-               swizzle_pipe[0] = 0;
-               swizzle_pipe[1] = 2;
-               swizzle_pipe[2] = 4;
-               swizzle_pipe[3] = 5;
-               swizzle_pipe[4] = 3;
-               swizzle_pipe[5] = 1;
+               if (force_no_swizzle) {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 1;
+                       swizzle_pipe[2] = 2;
+                       swizzle_pipe[3] = 3;
+                       swizzle_pipe[4] = 4;
+                       swizzle_pipe[5] = 5;
+               } else {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 2;
+                       swizzle_pipe[2] = 4;
+                       swizzle_pipe[3] = 5;
+                       swizzle_pipe[4] = 3;
+                       swizzle_pipe[5] = 1;
+               }
                break;
        case 7:
-               swizzle_pipe[0] = 0;
-               swizzle_pipe[1] = 2;
-               swizzle_pipe[2] = 4;
-               swizzle_pipe[3] = 6;
-               swizzle_pipe[4] = 3;
-               swizzle_pipe[5] = 1;
-               swizzle_pipe[6] = 5;
+               if (force_no_swizzle) {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 1;
+                       swizzle_pipe[2] = 2;
+                       swizzle_pipe[3] = 3;
+                       swizzle_pipe[4] = 4;
+                       swizzle_pipe[5] = 5;
+                       swizzle_pipe[6] = 6;
+               } else {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 2;
+                       swizzle_pipe[2] = 4;
+                       swizzle_pipe[3] = 6;
+                       swizzle_pipe[4] = 3;
+                       swizzle_pipe[5] = 1;
+                       swizzle_pipe[6] = 5;
+               }
                break;
        case 8:
-               swizzle_pipe[0] = 0;
-               swizzle_pipe[1] = 2;
-               swizzle_pipe[2] = 4;
-               swizzle_pipe[3] = 6;
-               swizzle_pipe[4] = 3;
-               swizzle_pipe[5] = 1;
-               swizzle_pipe[6] = 7;
-               swizzle_pipe[7] = 5;
+               if (force_no_swizzle) {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 1;
+                       swizzle_pipe[2] = 2;
+                       swizzle_pipe[3] = 3;
+                       swizzle_pipe[4] = 4;
+                       swizzle_pipe[5] = 5;
+                       swizzle_pipe[6] = 6;
+                       swizzle_pipe[7] = 7;
+               } else {
+                       swizzle_pipe[0] = 0;
+                       swizzle_pipe[1] = 2;
+                       swizzle_pipe[2] = 4;
+                       swizzle_pipe[3] = 6;
+                       swizzle_pipe[4] = 3;
+                       swizzle_pipe[5] = 1;
+                       swizzle_pipe[6] = 7;
+                       swizzle_pipe[7] = 5;
+               }
                break;
        }
 
@@ -388,8 +472,10 @@ static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
 static void rv770_gpu_init(struct radeon_device *rdev)
 {
        int i, j, num_qd_pipes;
+       u32 ta_aux_cntl;
        u32 sx_debug_1;
        u32 smx_dc_ctl0;
+       u32 db_debug3;
        u32 num_gs_verts_per_thread;
        u32 vgt_gs_per_es;
        u32 gs_prim_buffer_depth = 0;
@@ -518,6 +604,7 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
        switch (rdev->config.rv770.max_tile_pipes) {
        case 1:
+       default:
                gb_tiling_config |= PIPE_TILING(0);
                break;
        case 2:
@@ -529,18 +616,19 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        case 8:
                gb_tiling_config |= PIPE_TILING(3);
                break;
-       default:
-               break;
        }
+       rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes;
 
        if (rdev->family == CHIP_RV770)
                gb_tiling_config |= BANK_TILING(1);
        else
-               gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_SHIFT) >> NOOFBANK_MASK);
+               gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
+       rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3);
 
        gb_tiling_config |= GROUP_SIZE(0);
+       rdev->config.rv770.tiling_group_size = 256;
 
-       if (((mc_arb_ramcfg & NOOFROWS_MASK) & NOOFROWS_SHIFT) > 3) {
+       if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) {
                gb_tiling_config |= ROW_TILING(3);
                gb_tiling_config |= SAMPLE_SPLIT(3);
        } else {
@@ -552,18 +640,27 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
        gb_tiling_config |= BANK_SWAPS(1);
 
-       backend_map = r700_get_tile_pipe_to_backend_map(rdev->config.rv770.max_tile_pipes,
-                                                       rdev->config.rv770.max_backends,
-                                                       (0xff << rdev->config.rv770.max_backends) & 0xff);
-       gb_tiling_config |= BACKEND_MAP(backend_map);
+       cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
+       cc_rb_backend_disable |=
+               BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK);
 
-       cc_gc_shader_pipe_config =
+       cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
+       cc_gc_shader_pipe_config |=
                INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << rdev->config.rv770.max_pipes) & R7XX_MAX_PIPES_MASK);
        cc_gc_shader_pipe_config |=
                INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << rdev->config.rv770.max_simds) & R7XX_MAX_SIMDS_MASK);
 
-       cc_rb_backend_disable =
-               BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK);
+       if (rdev->family == CHIP_RV740)
+               backend_map = 0x28;
+       else
+               backend_map = r700_get_tile_pipe_to_backend_map(rdev,
+                                                               rdev->config.rv770.max_tile_pipes,
+                                                               (R7XX_MAX_BACKENDS -
+                                                                r600_count_pipe_bits((cc_rb_backend_disable &
+                                                                                      R7XX_MAX_BACKENDS_MASK) >> 16)),
+                                                               (cc_rb_backend_disable >> 16));
+       gb_tiling_config |= BACKEND_MAP(backend_map);
+
 
        WREG32(GB_TILING_CONFIG, gb_tiling_config);
        WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));
@@ -572,28 +669,26 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        WREG32(CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
        WREG32(CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
        WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
+       WREG32(CC_SYS_RB_BACKEND_DISABLE,  cc_rb_backend_disable);
 
-       WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
        WREG32(CGTS_SYS_TCC_DISABLE, 0);
        WREG32(CGTS_TCC_DISABLE, 0);
        WREG32(CGTS_USER_SYS_TCC_DISABLE, 0);
        WREG32(CGTS_USER_TCC_DISABLE, 0);
 
        num_qd_pipes =
-               R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK);
+               R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
        WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK);
        WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK);
 
        /* set HW defaults for 3D engine */
        WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) |
-                                               ROQ_IB2_START(0x2b)));
+                                    ROQ_IB2_START(0x2b)));
 
        WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30));
 
-       WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO |
-                                       SYNC_GRADIENT |
-                                       SYNC_WALKER |
-                                       SYNC_ALIGNER));
+       ta_aux_cntl = RREG32(TA_CNTL_AUX);
+       WREG32(TA_CNTL_AUX, ta_aux_cntl | DISABLE_CUBE_ANISO);
 
        sx_debug_1 = RREG32(SX_DEBUG_1);
        sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
@@ -604,26 +699,40 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        smx_dc_ctl0 |= CACHE_DEPTH((rdev->config.rv770.sx_num_of_sets * 64) - 1);
        WREG32(SMX_DC_CTL0, smx_dc_ctl0);
 
-       WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
-                                         GS_FLUSH_CTL(4) |
-                                         ACK_FLUSH_CTL(3) |
-                                         SYNC_FLUSH_CTL));
+       if (rdev->family != CHIP_RV740)
+               WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
+                                      GS_FLUSH_CTL(4) |
+                                      ACK_FLUSH_CTL(3) |
+                                      SYNC_FLUSH_CTL));
 
-       if (rdev->family == CHIP_RV770)
-               WREG32(DB_DEBUG3, DB_CLK_OFF_DELAY(0x1f));
-       else {
+       db_debug3 = RREG32(DB_DEBUG3);
+       db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f);
+       switch (rdev->family) {
+       case CHIP_RV770:
+       case CHIP_RV740:
+               db_debug3 |= DB_CLK_OFF_DELAY(0x1f);
+               break;
+       case CHIP_RV710:
+       case CHIP_RV730:
+       default:
+               db_debug3 |= DB_CLK_OFF_DELAY(2);
+               break;
+       }
+       WREG32(DB_DEBUG3, db_debug3);
+
+       if (rdev->family != CHIP_RV770) {
                db_debug4 = RREG32(DB_DEBUG4);
                db_debug4 |= DISABLE_TILE_COVERED_FOR_PS_ITER;
                WREG32(DB_DEBUG4, db_debug4);
        }
 
        WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.rv770.sx_max_export_size / 4) - 1) |
-                                                  POSITION_BUFFER_SIZE((rdev->config.rv770.sx_max_export_pos_size / 4) - 1) |
-                                                  SMX_BUFFER_SIZE((rdev->config.rv770.sx_max_export_smx_size / 4) - 1)));
+                                       POSITION_BUFFER_SIZE((rdev->config.rv770.sx_max_export_pos_size / 4) - 1) |
+                                       SMX_BUFFER_SIZE((rdev->config.rv770.sx_max_export_smx_size / 4) - 1)));
 
        WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.rv770.sc_prim_fifo_size) |
-                                                SC_HIZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_hiz_tile_fifo_size) |
-                                                SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_earlyz_tile_fifo_fize)));
+                                SC_HIZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_hiz_tile_fifo_size) |
+                                SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_earlyz_tile_fifo_fize)));
 
        WREG32(PA_SC_MULTI_CHIP_CNTL, 0);
 
@@ -640,10 +749,10 @@ static void rv770_gpu_init(struct radeon_device *rdev)
                            ALU_UPDATE_FIFO_HIWATER(0x8));
        switch (rdev->family) {
        case CHIP_RV770:
-               sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1);
-               break;
        case CHIP_RV730:
        case CHIP_RV710:
+               sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1);
+               break;
        case CHIP_RV740:
        default:
                sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x4);
@@ -673,11 +782,11 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        WREG32(SQ_CONFIG, sq_config);
 
        WREG32(SQ_GPR_RESOURCE_MGMT_1,  (NUM_PS_GPRS((rdev->config.rv770.max_gprs * 24)/64) |
-                                                   NUM_VS_GPRS((rdev->config.rv770.max_gprs * 24)/64) |
-                                                   NUM_CLAUSE_TEMP_GPRS(((rdev->config.rv770.max_gprs * 24)/64)/2)));
+                                        NUM_VS_GPRS((rdev->config.rv770.max_gprs * 24)/64) |
+                                        NUM_CLAUSE_TEMP_GPRS(((rdev->config.rv770.max_gprs * 24)/64)/2)));
 
        WREG32(SQ_GPR_RESOURCE_MGMT_2,  (NUM_GS_GPRS((rdev->config.rv770.max_gprs * 7)/64) |
-                                                   NUM_ES_GPRS((rdev->config.rv770.max_gprs * 7)/64)));
+                                        NUM_ES_GPRS((rdev->config.rv770.max_gprs * 7)/64)));
 
        sq_thread_resource_mgmt = (NUM_PS_THREADS((rdev->config.rv770.max_threads * 4)/8) |
                                   NUM_VS_THREADS((rdev->config.rv770.max_threads * 2)/8) |
@@ -709,14 +818,14 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0);
 
        WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
-                                                    FORCE_EOV_MAX_REZ_CNT(255)));
+                                         FORCE_EOV_MAX_REZ_CNT(255)));
 
        if (rdev->family == CHIP_RV710)
                WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(TC_ONLY) |
-                                                          AUTO_INVLD_EN(ES_AND_GS_AUTO)));
+                                               AUTO_INVLD_EN(ES_AND_GS_AUTO)));
        else
                WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(VC_AND_TC) |
-                                                          AUTO_INVLD_EN(ES_AND_GS_AUTO)));
+                                               AUTO_INVLD_EN(ES_AND_GS_AUTO)));
 
        switch (rdev->family) {
        case CHIP_RV770:
@@ -779,80 +888,98 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
 int rv770_mc_init(struct radeon_device *rdev)
 {
-       fixed20_12 a;
        u32 tmp;
-       int r;
+       int chansize, numchan;
 
        /* Get VRAM informations */
-       /* FIXME: Don't know how to determine vram width, need to check
-        * vram_width usage
-        */
-       rdev->mc.vram_width = 128;
        rdev->mc.vram_is_ddr = true;
+       tmp = RREG32(MC_ARB_RAMCFG);
+       if (tmp & CHANSIZE_OVERRIDE) {
+               chansize = 16;
+       } else if (tmp & CHANSIZE_MASK) {
+               chansize = 64;
+       } else {
+               chansize = 32;
+       }
+       tmp = RREG32(MC_SHARED_CHMAP);
+       switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+       case 0:
+       default:
+               numchan = 1;
+               break;
+       case 1:
+               numchan = 2;
+               break;
+       case 2:
+               numchan = 4;
+               break;
+       case 3:
+               numchan = 8;
+               break;
+       }
+       rdev->mc.vram_width = numchan * chansize;
        /* Could aper size report 0 ? */
        rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
        rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
        /* Setup GPU memory space */
        rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
        rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
-       if (rdev->flags & RADEON_IS_AGP) {
-               r = radeon_agp_init(rdev);
-               if (r)
-                       return r;
-               /* gtt_size is setup by radeon_agp_init */
-               rdev->mc.gtt_location = rdev->mc.agp_base;
-               tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
-               /* Try to put vram before or after AGP because we
-                * we want SYSTEM_APERTURE to cover both VRAM and
-                * AGP so that GPU can catch out of VRAM/AGP access
-                */
-               if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
-                       /* Enought place before */
-                       rdev->mc.vram_location = rdev->mc.gtt_location -
-                                                       rdev->mc.mc_vram_size;
-               } else if (tmp > rdev->mc.mc_vram_size) {
-                       /* Enought place after */
-                       rdev->mc.vram_location = rdev->mc.gtt_location +
-                                                       rdev->mc.gtt_size;
-               } else {
-                       /* Try to setup VRAM then AGP might not
-                        * not work on some card
-                        */
-                       rdev->mc.vram_location = 0x00000000UL;
-                       rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-               }
-       } else {
-               rdev->mc.vram_location = 0x00000000UL;
-               rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-               rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-       }
-       rdev->mc.vram_start = rdev->mc.vram_location;
-       rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size;
-       rdev->mc.gtt_start = rdev->mc.gtt_location;
-       rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size;
-       /* FIXME: we should enforce default clock in case GPU is not in
-        * default setup
-        */
-       a.full = rfixed_const(100);
-       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
-       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
-       return 0;
-}
-int rv770_gpu_reset(struct radeon_device *rdev)
-{
-       /* FIXME: implement */
+       rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       r600_vram_gtt_location(rdev, &rdev->mc);
+       radeon_update_bandwidth_info(rdev);
+
        return 0;
 }
 
-int rv770_resume(struct radeon_device *rdev)
+static int rv770_startup(struct radeon_device *rdev)
 {
        int r;
 
-       rv770_mc_resume(rdev);
-       r = rv770_pcie_gart_enable(rdev);
-       if (r)
-               return r;
+       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+               r = r600_init_microcode(rdev);
+               if (r) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       return r;
+               }
+       }
+
+       rv770_mc_program(rdev);
+       if (rdev->flags & RADEON_IS_AGP) {
+               rv770_agp_enable(rdev);
+       } else {
+               r = rv770_pcie_gart_enable(rdev);
+               if (r)
+                       return r;
+       }
        rv770_gpu_init(rdev);
+       r = r600_blit_init(rdev);
+       if (r) {
+               r600_blit_fini(rdev);
+               rdev->asic->copy = NULL;
+               dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
+       }
+       /* pin copy shader into vram */
+       if (rdev->r600_blit.shader_obj) {
+               r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+               if (unlikely(r != 0))
+                       return r;
+               r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
+                               &rdev->r600_blit.shader_gpu_addr);
+               radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+               if (r) {
+                       DRM_ERROR("failed to pin blit object %d\n", r);
+                       return r;
+               }
+       }
+       /* Enable IRQ */
+       r = r600_irq_init(rdev);
+       if (r) {
+               DRM_ERROR("radeon: IH init failed (%d).\n", r);
+               radeon_irq_kms_fini(rdev);
+               return r;
+       }
+       r600_irq_set(rdev);
+
        r = radeon_ring_init(rdev, rdev->cp.ring_size);
        if (r)
                return r;
@@ -862,16 +989,68 @@ int rv770_resume(struct radeon_device *rdev)
        r = r600_cp_resume(rdev);
        if (r)
                return r;
-       r = r600_wb_init(rdev);
-       if (r)
-               return r;
+       /* write back buffer are not vital so don't worry about failure */
+       r600_wb_enable(rdev);
        return 0;
 }
 
+int rv770_resume(struct radeon_device *rdev)
+{
+       int r;
+
+       /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
+        * posting will perform necessary task to bring back GPU into good
+        * shape.
+        */
+       /* post card */
+       atom_asic_init(rdev->mode_info.atom_context);
+       /* Initialize clocks */
+       r = radeon_clocks_init(rdev);
+       if (r) {
+               return r;
+       }
+
+       r = rv770_startup(rdev);
+       if (r) {
+               DRM_ERROR("r600 startup failed on resume\n");
+               return r;
+       }
+
+       r = r600_ib_test(rdev);
+       if (r) {
+               DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+               return r;
+       }
+
+       r = r600_audio_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "radeon: audio init failed\n");
+               return r;
+       }
+
+       return r;
+
+}
+
 int rv770_suspend(struct radeon_device *rdev)
 {
+       int r;
+
+       r600_audio_fini(rdev);
        /* FIXME: we should wait for ring to be empty */
        r700_cp_stop(rdev);
+       rdev->cp.ready = false;
+       r600_irq_suspend(rdev);
+       r600_wb_disable(rdev);
+       rv770_pcie_gart_disable(rdev);
+       /* unpin shaders bo */
+       if (rdev->r600_blit.shader_obj) {
+               r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+               if (likely(r == 0)) {
+                       radeon_bo_unpin(rdev->r600_blit.shader_obj);
+                       radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+               }
+       }
        return 0;
 }
 
@@ -885,7 +1064,6 @@ int rv770_init(struct radeon_device *rdev)
 {
        int r;
 
-       rdev->new_init_path = true;
        r = radeon_dummy_page_init(rdev);
        if (r)
                return r;
@@ -899,13 +1077,19 @@ int rv770_init(struct radeon_device *rdev)
                        return -EINVAL;
        }
        /* Must be an ATOMBIOS */
-       if (!rdev->is_atom_bios)
+       if (!rdev->is_atom_bios) {
+               dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
                return -EINVAL;
+       }
        r = radeon_atombios_init(rdev);
        if (r)
                return r;
        /* Post card if necessary */
-       if (!r600_card_posted(rdev) && rdev->bios) {
+       if (!r600_card_posted(rdev)) {
+               if (!rdev->bios) {
+                       dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+                       return -EINVAL;
+               }
                DRM_INFO("GPU not posted. posting now...\n");
                atom_asic_init(rdev->mode_info.atom_context);
        }
@@ -913,6 +1097,8 @@ int rv770_init(struct radeon_device *rdev)
        r600_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* Initialize clocks */
+       radeon_get_clock_info(rdev->ddev);
        r = radeon_clocks_init(rdev);
        if (r)
                return r;
@@ -920,79 +1106,82 @@ int rv770_init(struct radeon_device *rdev)
        r = radeon_fence_driver_init(rdev);
        if (r)
                return r;
+       /* initialize AGP */
+       if (rdev->flags & RADEON_IS_AGP) {
+               r = radeon_agp_init(rdev);
+               if (r)
+                       radeon_agp_disable(rdev);
+       }
        r = rv770_mc_init(rdev);
-       if (r) {
-               if (rdev->flags & RADEON_IS_AGP) {
-                       /* Retry with disabling AGP */
-                       rv770_fini(rdev);
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       return rv770_init(rdev);
-               }
+       if (r)
                return r;
-       }
        /* Memory manager */
-       r = radeon_object_init(rdev);
+       r = radeon_bo_init(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);
 
-       if (!rdev->me_fw || !rdev->pfp_fw) {
-               r = r600_cp_init_microcode(rdev);
-               if (r) {
-                       DRM_ERROR("Failed to load firmware!\n");
-                       return r;
-               }
-       }
+       rdev->ih.ring_obj = NULL;
+       r600_ih_ring_init(rdev, 64 * 1024);
 
-       r = rv770_resume(rdev);
-       if (r) {
-               if (rdev->flags & RADEON_IS_AGP) {
-                       /* Retry with disabling AGP */
-                       rv770_fini(rdev);
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       return rv770_init(rdev);
-               }
+       r = r600_pcie_gart_init(rdev);
+       if (r)
                return r;
-       }
-       r = r600_blit_init(rdev);
+
+       rdev->accel_working = true;
+       r = rv770_startup(rdev);
        if (r) {
-               DRM_ERROR("radeon: failled blitter (%d).\n", r);
-               return r;
+               dev_err(rdev->dev, "disabling GPU acceleration\n");
+               r700_cp_fini(rdev);
+               r600_wb_fini(rdev);
+               r600_irq_fini(rdev);
+               radeon_irq_kms_fini(rdev);
+               rv770_pcie_gart_fini(rdev);
+               rdev->accel_working = false;
        }
-       r = radeon_ib_pool_init(rdev);
-       if (r) {
-               DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
-               return r;
+       if (rdev->accel_working) {
+               r = radeon_ib_pool_init(rdev);
+               if (r) {
+                       dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
+                       rdev->accel_working = false;
+               } else {
+                       r = r600_ib_test(rdev);
+                       if (r) {
+                               dev_err(rdev->dev, "IB test failed (%d).\n", r);
+                               rdev->accel_working = false;
+                       }
+               }
        }
-       r = radeon_ib_test(rdev);
+
+       r = r600_audio_init(rdev);
        if (r) {
-               DRM_ERROR("radeon: failled testing IB (%d).\n", r);
-                       return r;
+               dev_err(rdev->dev, "radeon: audio init failed\n");
+               return r;
        }
+
        return 0;
 }
 
 void rv770_fini(struct radeon_device *rdev)
 {
        r600_blit_fini(rdev);
-       radeon_ring_fini(rdev);
-       rv770_pcie_gart_disable(rdev);
-       radeon_gart_table_vram_free(rdev);
-       radeon_gart_fini(rdev);
+       r700_cp_fini(rdev);
+       r600_wb_fini(rdev);
+       r600_irq_fini(rdev);
+       radeon_irq_kms_fini(rdev);
+       rv770_pcie_gart_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_clocks_fini(rdev);
-#if __OS_HAS_AGP
-       if (rdev->flags & RADEON_IS_AGP)
-               radeon_agp_fini(rdev);
-#endif
-       radeon_object_fini(rdev);
-       if (rdev->is_atom_bios) {
-               radeon_atombios_fini(rdev);
-       } else {
-               radeon_combios_fini(rdev);
-       }
+       radeon_agp_fini(rdev);
+       radeon_bo_fini(rdev);
+       radeon_atombios_fini(rdev);
        kfree(rdev->bios);
        rdev->bios = NULL;
        radeon_dummy_page_fini(rdev);