]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/radeon/r100.c
Merge branch 'drm-fixes' of /home/airlied/kernel/linux-2.6 into drm-core-next
[mv-sheeva.git] / drivers / gpu / drm / radeon / r100.c
index a89a15ab524d87d64f734b9475418b0538525dd2..6112ac99ccd76a3b1919ea2bd2371f64a5313bc1 100644 (file)
@@ -141,7 +141,7 @@ void r100_pm_get_dynpm_state(struct radeon_device *rdev)
        /* only one clock mode per power state */
        rdev->pm.requested_clock_mode_index = 0;
 
-       DRM_DEBUG("Requested: e: %d m: %d p: %d\n",
+       DRM_DEBUG_DRIVER("Requested: e: %d m: %d p: %d\n",
                  rdev->pm.power_state[rdev->pm.requested_power_state_index].
                  clock_info[rdev->pm.requested_clock_mode_index].sclk,
                  rdev->pm.power_state[rdev->pm.requested_power_state_index].
@@ -276,7 +276,7 @@ void r100_pm_misc(struct radeon_device *rdev)
             rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
                radeon_set_pcie_lanes(rdev,
                                      ps->pcie_lanes);
-               DRM_DEBUG("Setting: p: %d\n", ps->pcie_lanes);
+               DRM_DEBUG_DRIVER("Setting: p: %d\n", ps->pcie_lanes);
        }
 }
 
@@ -675,67 +675,6 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
 }
 
-int r100_wb_init(struct radeon_device *rdev)
-{
-       int r;
-
-       if (rdev->wb.wb_obj == NULL) {
-               r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
-                                       RADEON_GEM_DOMAIN_GTT,
-                                       &rdev->wb.wb_obj);
-               if (r) {
-                       dev_err(rdev->dev, "(%d) create WB buffer failed\n", r);
-                       return r;
-               }
-               r = radeon_bo_reserve(rdev->wb.wb_obj, false);
-               if (unlikely(r != 0))
-                       return r;
-               r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
-                                       &rdev->wb.gpu_addr);
-               if (r) {
-                       dev_err(rdev->dev, "(%d) pin WB buffer failed\n", r);
-                       radeon_bo_unreserve(rdev->wb.wb_obj);
-                       return r;
-               }
-               r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
-               radeon_bo_unreserve(rdev->wb.wb_obj);
-               if (r) {
-                       dev_err(rdev->dev, "(%d) map WB buffer failed\n", r);
-                       return r;
-               }
-       }
-       WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr);
-       WREG32(R_00070C_CP_RB_RPTR_ADDR,
-               S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + 1024) >> 2));
-       WREG32(R_000770_SCRATCH_UMSK, 0xff);
-       return 0;
-}
-
-void r100_wb_disable(struct radeon_device *rdev)
-{
-       WREG32(R_000770_SCRATCH_UMSK, 0);
-}
-
-void r100_wb_fini(struct radeon_device *rdev)
-{
-       int r;
-
-       r100_wb_disable(rdev);
-       if (rdev->wb.wb_obj) {
-               r = radeon_bo_reserve(rdev->wb.wb_obj, false);
-               if (unlikely(r != 0)) {
-                       dev_err(rdev->dev, "(%d) can't finish WB\n", r);
-                       return;
-               }
-               radeon_bo_kunmap(rdev->wb.wb_obj);
-               radeon_bo_unpin(rdev->wb.wb_obj);
-               radeon_bo_unreserve(rdev->wb.wb_obj);
-               radeon_bo_unref(&rdev->wb.wb_obj);
-               rdev->wb.wb = NULL;
-               rdev->wb.wb_obj = NULL;
-       }
-}
-
 int r100_copy_blit(struct radeon_device *rdev,
                   uint64_t src_offset,
                   uint64_t dst_offset,
@@ -849,7 +788,7 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)
        const char *fw_name = NULL;
        int err;
 
-       DRM_DEBUG("\n");
+       DRM_DEBUG_KMS("\n");
 
        pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
        err = IS_ERR(pdev);
@@ -996,20 +935,32 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
        WREG32(0x718, pre_write_timer | (pre_write_limit << 28));
        tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
               REG_SET(RADEON_RB_BLKSZ, rb_blksz) |
-              REG_SET(RADEON_MAX_FETCH, max_fetch) |
-              RADEON_RB_NO_UPDATE);
+              REG_SET(RADEON_MAX_FETCH, max_fetch));
 #ifdef __BIG_ENDIAN
        tmp |= RADEON_BUF_SWAP_32BIT;
 #endif
-       WREG32(RADEON_CP_RB_CNTL, tmp);
+       WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_NO_UPDATE);
 
        /* Set ring address */
        DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr);
        WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr);
        /* Force read & write ptr to 0 */
-       WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
+       WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA | RADEON_RB_NO_UPDATE);
        WREG32(RADEON_CP_RB_RPTR_WR, 0);
        WREG32(RADEON_CP_RB_WPTR, 0);
+
+       /* set the wb address whether it's enabled or not */
+       WREG32(R_00070C_CP_RB_RPTR_ADDR,
+               S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) >> 2));
+       WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET);
+
+       if (rdev->wb.enabled)
+               WREG32(R_000770_SCRATCH_UMSK, 0xff);
+       else {
+               tmp |= RADEON_RB_NO_UPDATE;
+               WREG32(R_000770_SCRATCH_UMSK, 0);
+       }
+
        WREG32(RADEON_CP_RB_CNTL, tmp);
        udelay(10);
        rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
@@ -1030,6 +981,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
                return r;
        }
        rdev->cp.ready = true;
+       rdev->mc.active_vram_size = rdev->mc.real_vram_size;
        return 0;
 }
 
@@ -1047,9 +999,11 @@ void r100_cp_fini(struct radeon_device *rdev)
 void r100_cp_disable(struct radeon_device *rdev)
 {
        /* Disable ring */
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        rdev->cp.ready = false;
        WREG32(RADEON_CP_CSQ_MODE, 0);
        WREG32(RADEON_CP_CSQ_CNTL, 0);
+       WREG32(R_000770_SCRATCH_UMSK, 0);
        if (r100_gui_wait_for_idle(rdev)) {
                printk(KERN_WARNING "Failed to wait GUI idle while "
                       "programming pipes. Bad things might happen.\n");
@@ -1803,6 +1757,11 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
                        return r;
                break;
                /* triggers drawing using indices to vertex buffer */
+       case PACKET3_3D_CLEAR_HIZ:
+       case PACKET3_3D_CLEAR_ZMASK:
+               if (p->rdev->hyperz_filp != p->filp)
+                       return -EINVAL;
+               break;
        case PACKET3_NOP:
                break;
        default:
@@ -2015,18 +1974,7 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l
                return false;
        }
        elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies);
-       if (elapsed >= 3000) {
-               /* very likely the improbable case where current
-                * rptr is equal to last recorded, a while ago, rptr
-                * this is more likely a false positive update tracking
-                * information which should force us to be recall at
-                * latter point
-                */
-               lockup->last_cp_rptr = cp->rptr;
-               lockup->last_jiffies = jiffies;
-               return false;
-       }
-       if (elapsed >= 1000) {
+       if (elapsed >= 10000) {
                dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed);
                return true;
        }
@@ -2295,12 +2243,13 @@ void r100_vram_init_sizes(struct radeon_device *rdev)
        u64 config_aper_size;
 
        /* work out accessible VRAM */
-       rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
-       rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+       rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
+       rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev);
        /* FIXME we don't use the second aperture yet when we could use it */
        if (rdev->mc.visible_vram_size > rdev->mc.aper_size)
                rdev->mc.visible_vram_size = rdev->mc.aper_size;
+       rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
        config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
        if (rdev->flags & RADEON_IS_IGP) {
                uint32_t tom;
@@ -2364,11 +2313,10 @@ void r100_mc_init(struct radeon_device *rdev)
  */
 void r100_pll_errata_after_index(struct radeon_device *rdev)
 {
-       if (!(rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS)) {
-               return;
+       if (rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS) {
+               (void)RREG32(RADEON_CLOCK_CNTL_DATA);
+               (void)RREG32(RADEON_CRTC_GEN_CNTL);
        }
-       (void)RREG32(RADEON_CLOCK_CNTL_DATA);
-       (void)RREG32(RADEON_CRTC_GEN_CNTL);
 }
 
 static void r100_pll_errata_after_data(struct radeon_device *rdev)
@@ -2643,7 +2591,7 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
                flags |= pitch / 8;
 
 
-       DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
+       DRM_DEBUG_KMS("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
        WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
        WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
        WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1);
@@ -3039,7 +2987,7 @@ void r100_bandwidth_update(struct radeon_device *rdev)
                }
 #endif
 
-               DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n",
+               DRM_DEBUG_KMS("GRPH_BUFFER_CNTL from to %x\n",
                          /*      (unsigned int)info->SavedReg->grph_buffer_cntl, */
                          (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL));
        }
@@ -3135,7 +3083,7 @@ void r100_bandwidth_update(struct radeon_device *rdev)
                        WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC);
                }
 
-               DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n",
+               DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n",
                          (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL));
        }
 }
@@ -3304,13 +3252,14 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track)
        unsigned long size;
        unsigned prim_walk;
        unsigned nverts;
+       unsigned num_cb = track->num_cb;
 
-       for (i = 0; i < track->num_cb; i++) {
+       if (!track->zb_cb_clear && !track->color_channel_mask &&
+           !track->blend_read_enable)
+               num_cb = 0;
+
+       for (i = 0; i < num_cb; i++) {
                if (track->cb[i].robj == NULL) {
-                       if (!(track->zb_cb_clear || track->color_channel_mask ||
-                             track->blend_read_enable)) {
-                               continue;
-                       }
                        DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
                        return -EINVAL;
                }
@@ -3740,6 +3689,12 @@ static int r100_startup(struct radeon_device *rdev)
                if (r)
                        return r;
        }
+
+       /* allocate wb buffer */
+       r = radeon_wb_init(rdev);
+       if (r)
+               return r;
+
        /* Enable IRQ */
        r100_irq_set(rdev);
        rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
@@ -3749,9 +3704,6 @@ static int r100_startup(struct radeon_device *rdev)
                dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
                return r;
        }
-       r = r100_wb_init(rdev);
-       if (r)
-               dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
        r = r100_ib_init(rdev);
        if (r) {
                dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
@@ -3785,7 +3737,7 @@ int r100_resume(struct radeon_device *rdev)
 int r100_suspend(struct radeon_device *rdev)
 {
        r100_cp_disable(rdev);
-       r100_wb_disable(rdev);
+       radeon_wb_disable(rdev);
        r100_irq_disable(rdev);
        if (rdev->flags & RADEON_IS_PCI)
                r100_pci_gart_disable(rdev);
@@ -3795,7 +3747,7 @@ int r100_suspend(struct radeon_device *rdev)
 void r100_fini(struct radeon_device *rdev)
 {
        r100_cp_fini(rdev);
-       r100_wb_fini(rdev);
+       radeon_wb_fini(rdev);
        r100_ib_fini(rdev);
        radeon_gem_fini(rdev);
        if (rdev->flags & RADEON_IS_PCI)
@@ -3809,6 +3761,31 @@ void r100_fini(struct radeon_device *rdev)
        rdev->bios = NULL;
 }
 
+/*
+ * Due to how kexec works, it can leave the hw fully initialised when it
+ * boots the new kernel. However doing our init sequence with the CP and
+ * WB stuff setup causes GPU hangs on the RN50 at least. So at startup
+ * do some quick sanity checks and restore sane values to avoid this
+ * problem.
+ */
+void r100_restore_sanity(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       tmp = RREG32(RADEON_CP_CSQ_CNTL);
+       if (tmp) {
+               WREG32(RADEON_CP_CSQ_CNTL, 0);
+       }
+       tmp = RREG32(RADEON_CP_RB_CNTL);
+       if (tmp) {
+               WREG32(RADEON_CP_RB_CNTL, 0);
+       }
+       tmp = RREG32(RADEON_SCRATCH_UMSK);
+       if (tmp) {
+               WREG32(RADEON_SCRATCH_UMSK, 0);
+       }
+}
+
 int r100_init(struct radeon_device *rdev)
 {
        int r;
@@ -3821,6 +3798,8 @@ int r100_init(struct radeon_device *rdev)
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* sanity check some register to avoid hangs like after kexec */
+       r100_restore_sanity(rdev);
        /* TODO: disable VGA need to use VGA request */
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
@@ -3881,7 +3860,7 @@ int r100_init(struct radeon_device *rdev)
                /* Somethings want wront with the accel init stop accel */
                dev_err(rdev->dev, "Disabling GPU acceleration\n");
                r100_cp_fini(rdev);
-               r100_wb_fini(rdev);
+               radeon_wb_fini(rdev);
                r100_ib_fini(rdev);
                radeon_irq_kms_fini(rdev);
                if (rdev->flags & RADEON_IS_PCI)