drm/radeon: handle vfct with multiple vbios images
[pandora-kernel.git] / drivers / gpu / drm / radeon / evergreen.c
index 92c9628..5d78973 100644 (file)
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
 
+static const u32 crtc_offsets[6] =
+{
+       EVERGREEN_CRTC0_REGISTER_OFFSET,
+       EVERGREEN_CRTC1_REGISTER_OFFSET,
+       EVERGREEN_CRTC2_REGISTER_OFFSET,
+       EVERGREEN_CRTC3_REGISTER_OFFSET,
+       EVERGREEN_CRTC4_REGISTER_OFFSET,
+       EVERGREEN_CRTC5_REGISTER_OFFSET
+};
+
 static void evergreen_gpu_init(struct radeon_device *rdev);
 void evergreen_fini(struct radeon_device *rdev);
 void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
@@ -66,6 +76,27 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
        }
 }
 
+void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
+{
+       int i;
+
+       if (crtc >= rdev->num_crtc)
+               return;
+
+       if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) {
+               for (i = 0; i < rdev->usec_timeout; i++) {
+                       if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK))
+                               break;
+                       udelay(1);
+               }
+               for (i = 0; i < rdev->usec_timeout; i++) {
+                       if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
+                               break;
+                       udelay(1);
+               }
+       }
+}
+
 void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
        /* enable the pflip int */
@@ -381,6 +412,16 @@ void evergreen_hpd_init(struct radeon_device *rdev)
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+               if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+                   connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+                       /* don't try to enable hpd on eDP or LVDS avoid breaking the
+                        * aux dp channel on imac and help (but not completely fix)
+                        * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+                        * also avoid interrupt storms during dpms.
+                        */
+                       continue;
+               }
                switch (radeon_connector->hpd.hpd) {
                case RADEON_HPD_1:
                        WREG32(DC_HPD1_CONTROL, tmp);
@@ -460,7 +501,8 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev,
                                        struct drm_display_mode *mode,
                                        struct drm_display_mode *other_mode)
 {
-       u32 tmp;
+       u32 tmp, buffer_alloc, i;
+       u32 pipe_offset = radeon_crtc->crtc_id * 0x20;
        /*
         * Line Buffer Setup
         * There are 3 line buffers, each one shared by 2 display controllers.
@@ -483,18 +525,34 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev,
         * non-linked crtcs for maximum line buffer allocation.
         */
        if (radeon_crtc->base.enabled && mode) {
-               if (other_mode)
+               if (other_mode) {
                        tmp = 0; /* 1/2 */
-               else
+                       buffer_alloc = 1;
+               } else {
                        tmp = 2; /* whole */
-       } else
+                       buffer_alloc = 2;
+               }
+       } else {
                tmp = 0;
+               buffer_alloc = 0;
+       }
 
        /* second controller of the pair uses second half of the lb */
        if (radeon_crtc->crtc_id % 2)
                tmp += 4;
        WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp);
 
+       if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+               WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
+                      DMIF_BUFFERS_ALLOCATED(buffer_alloc));
+               for (i = 0; i < rdev->usec_timeout; i++) {
+                       if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
+                           DMIF_BUFFERS_ALLOCATED_COMPLETED)
+                               break;
+                       udelay(1);
+               }
+       }
+
        if (radeon_crtc->base.enabled && mode) {
                switch (tmp) {
                case 0:
@@ -977,6 +1035,11 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
                WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
                WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
                WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+               if ((rdev->family == CHIP_JUNIPER) ||
+                   (rdev->family == CHIP_CYPRESS) ||
+                   (rdev->family == CHIP_HEMLOCK) ||
+                   (rdev->family == CHIP_BARTS))
+                       WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp);
        }
        WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
@@ -1060,175 +1123,94 @@ void evergreen_agp_enable(struct radeon_device *rdev)
 
 void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
 {
-       save->vga_control[0] = RREG32(D1VGA_CONTROL);
-       save->vga_control[1] = RREG32(D2VGA_CONTROL);
+       u32 crtc_enabled, tmp, frame_count, blackout;
+       int i, j;
+
        save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
        save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
-       save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
-       save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
-       if (rdev->num_crtc >= 4) {
-               save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL);
-               save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);
-               save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
-               save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
-       }
-       if (rdev->num_crtc >= 6) {
-               save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL);
-               save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);
-               save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
-               save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
-       }
 
-       /* Stop all video */
+       /* disable VGA render */
        WREG32(VGA_RENDER_CONTROL, 0);
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
-       }
-       WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
-       WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
-       }
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+       /* blank the display controllers */
+       for (i = 0; i < rdev->num_crtc; i++) {
+               crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN;
+               if (crtc_enabled) {
+                       save->crtc_enabled[i] = true;
+                       tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
+                       if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) {
+                               dce4_wait_for_vblank(rdev, i);
+                               tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
+                               WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+                       }
+                       /* wait for the next frame */
+                       frame_count = radeon_get_vblank_counter(rdev, i);
+                       for (j = 0; j < rdev->usec_timeout; j++) {
+                               if (radeon_get_vblank_counter(rdev, i) != frame_count)
+                                       break;
+                               udelay(1);
+                       }
+               } else {
+                       save->crtc_enabled[i] = false;
+               }
        }
 
-       WREG32(D1VGA_CONTROL, 0);
-       WREG32(D2VGA_CONTROL, 0);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_D3VGA_CONTROL, 0);
-               WREG32(EVERGREEN_D4VGA_CONTROL, 0);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_D5VGA_CONTROL, 0);
-               WREG32(EVERGREEN_D6VGA_CONTROL, 0);
+       evergreen_mc_wait_for_idle(rdev);
+
+       blackout = RREG32(MC_SHARED_BLACKOUT_CNTL);
+       if ((blackout & BLACKOUT_MODE_MASK) != 1) {
+               /* Block CPU access */
+               WREG32(BIF_FB_EN, 0);
+               /* blackout the MC */
+               blackout &= ~BLACKOUT_MODE_MASK;
+               WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);
        }
+       /* wait for the MC to settle */
+       udelay(100);
 }
 
 void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
 {
-       WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
-              upper_32_bits(rdev->mc.vram_start));
-       WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
-              upper_32_bits(rdev->mc.vram_start));
-       WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET,
-              (u32)rdev->mc.vram_start);
-       WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET,
-              (u32)rdev->mc.vram_start);
-
-       WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET,
-              upper_32_bits(rdev->mc.vram_start));
-       WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET,
-              upper_32_bits(rdev->mc.vram_start));
-       WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
-              (u32)rdev->mc.vram_start);
-       WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
-              (u32)rdev->mc.vram_start);
-
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
-                      upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
-                      upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
-                      (u32)rdev->mc.vram_start);
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
-                      (u32)rdev->mc.vram_start);
-
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
-                      upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
-                      upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
-                      (u32)rdev->mc.vram_start);
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
-                      (u32)rdev->mc.vram_start);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
-                      upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
-                      upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
-                      (u32)rdev->mc.vram_start);
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
-                      (u32)rdev->mc.vram_start);
+       u32 tmp, frame_count;
+       int i, j;
 
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
+       /* update crtc base addresses */
+       for (i = 0; i < rdev->num_crtc; i++) {
+               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
                       upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
+               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
                       upper_32_bits(rdev->mc.vram_start));
-               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
+               WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
                       (u32)rdev->mc.vram_start);
-               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
+               WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
                       (u32)rdev->mc.vram_start);
        }
-
        WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
        WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
-       /* Unlock host access */
+
+       /* unblackout the MC */
+       tmp = RREG32(MC_SHARED_BLACKOUT_CNTL);
+       tmp &= ~BLACKOUT_MODE_MASK;
+       WREG32(MC_SHARED_BLACKOUT_CNTL, tmp);
+       /* allow CPU access */
+       WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
+
+       for (i = 0; i < rdev->num_crtc; i++) {
+               if (save->crtc_enabled[i]) {
+                       tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
+                       tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
+                       WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+                       /* wait for the next frame */
+                       frame_count = radeon_get_vblank_counter(rdev, i);
+                       for (j = 0; j < rdev->usec_timeout; j++) {
+                               if (radeon_get_vblank_counter(rdev, i) != frame_count)
+                                       break;
+                               udelay(1);
+                       }
+               }
+       }
+       /* Unlock vga access */
        WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
        mdelay(1);
-       /* Restore video state */
-       WREG32(D1VGA_CONTROL, save->vga_control[0]);
-       WREG32(D2VGA_CONTROL, save->vga_control[1]);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]);
-               WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]);
-               WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
-       }
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
-       }
-       WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);
-       WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
-               WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
-       }
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
-       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
-       if (rdev->num_crtc >= 4) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
-       }
-       if (rdev->num_crtc >= 6) {
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
-               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
-       }
        WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
 }
 
@@ -1777,7 +1759,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        case CHIP_SUMO:
                rdev->config.evergreen.num_ses = 1;
                rdev->config.evergreen.max_pipes = 4;
-               rdev->config.evergreen.max_tile_pipes = 2;
+               rdev->config.evergreen.max_tile_pipes = 4;
                if (rdev->pdev->device == 0x9648)
                        rdev->config.evergreen.max_simds = 3;
                else if ((rdev->pdev->device == 0x9647) ||
@@ -1815,7 +1797,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                rdev->config.evergreen.sx_max_export_size = 256;
                rdev->config.evergreen.sx_max_export_pos_size = 64;
                rdev->config.evergreen.sx_max_export_smx_size = 192;
-               rdev->config.evergreen.max_hw_contexts = 8;
+               rdev->config.evergreen.max_hw_contexts = 4;
                rdev->config.evergreen.sq_num_cf_insts = 2;
 
                rdev->config.evergreen.sc_prim_fifo_size = 0x40;
@@ -1866,7 +1848,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                break;
        case CHIP_CAICOS:
                rdev->config.evergreen.num_ses = 1;
-               rdev->config.evergreen.max_pipes = 4;
+               rdev->config.evergreen.max_pipes = 2;
                rdev->config.evergreen.max_tile_pipes = 2;
                rdev->config.evergreen.max_simds = 2;
                rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses;
@@ -2074,9 +2056,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */
        if (rdev->flags & RADEON_IS_IGP)
                rdev->config.evergreen.tile_config |= 1 << 4;
-       else
-               rdev->config.evergreen.tile_config |=
-                       ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
+       else {
+               switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
+               case 0: /* four banks */
+                       rdev->config.evergreen.tile_config |= 0 << 4;
+                       break;
+               case 1: /* eight banks */
+                       rdev->config.evergreen.tile_config |= 1 << 4;
+                       break;
+               case 2: /* sixteen banks */
+               default:
+                       rdev->config.evergreen.tile_config |= 2 << 4;
+                       break;
+               }
+       }
        rdev->config.evergreen.tile_config |=
                ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8;
        rdev->config.evergreen.tile_config |=
@@ -2108,9 +2101,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                WREG32(CC_SYS_RB_BACKEND_DISABLE, rb);
                WREG32(GC_USER_RB_BACKEND_DISABLE, rb);
                WREG32(CC_GC_SHADER_PIPE_CONFIG, sp);
-        }
+       }
 
-       grbm_gfx_index |= SE_BROADCAST_WRITES;
+       grbm_gfx_index = INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES;
        WREG32(GRBM_GFX_INDEX, grbm_gfx_index);
        WREG32(RLC_GFX_INDEX, grbm_gfx_index);
 
@@ -2140,6 +2133,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets);
        WREG32(SMX_DC_CTL0, smx_dc_ctl0);
 
+       if (rdev->family <= CHIP_SUMO2)
+               WREG32(SMX_SAR_CTL0, 0x00010000);
+
        WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) |
                                        POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) |
                                        SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1)));
@@ -2635,6 +2631,9 @@ int evergreen_irq_set(struct radeon_device *rdev)
        WREG32(DC_HPD5_INT_CONTROL, hpd5);
        WREG32(DC_HPD6_INT_CONTROL, hpd6);
 
+       /* posting read */
+       RREG32(SRBM_STATUS);
+
        return 0;
 }
 
@@ -2769,6 +2768,7 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
                tmp = RREG32(IH_RB_CNTL);
                tmp |= IH_WPTR_OVERFLOW_CLEAR;
                WREG32(IH_RB_CNTL, tmp);
+               wptr &= ~RB_OVERFLOW;
        }
        return (wptr & rdev->ih.ptr_mask);
 }
@@ -3057,6 +3057,8 @@ static int evergreen_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        evergreen_pcie_gen2_enable(rdev);
 
+       evergreen_mc_program(rdev);
+
        if (ASIC_IS_DCE5(rdev)) {
                if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
                        r = ni_init_microcode(rdev);
@@ -3084,7 +3086,6 @@ static int evergreen_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       evergreen_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                evergreen_agp_enable(rdev);
        } else {
@@ -3107,6 +3108,12 @@ static int evergreen_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);
@@ -3239,10 +3246,6 @@ int evergreen_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);