Merge tag 'v2.6.35-rc6' into drm-radeon-next
[sfrench/cifs-2.6.git] / drivers / gpu / drm / radeon / r100.c
index cf89aa2eb28c07cb61054f43db647c5ec4ff9f59..e115583f84fb03dd48f9716694668a8268d54a60 100644 (file)
@@ -1230,7 +1230,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
        header = radeon_get_ib_value(p, h_idx);
        crtc_id = radeon_get_ib_value(p, h_idx + 5);
        reg = CP_PACKET0_GET_REG(header);
-       mutex_lock(&p->rdev->ddev->mode_config.mutex);
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
                DRM_ERROR("cannot find crtc %d\n", crtc_id);
@@ -1264,7 +1263,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
                ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
        }
 out:
-       mutex_unlock(&p->rdev->ddev->mode_config.mutex);
        return r;
 }
 
@@ -1628,6 +1626,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case RADEON_TXFORMAT_RGB332:
                case RADEON_TXFORMAT_Y8:
                        track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_AI88:
                case RADEON_TXFORMAT_ARGB1555:
@@ -1639,12 +1638,14 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case RADEON_TXFORMAT_LDUDV655:
                case RADEON_TXFORMAT_DUDV88:
                        track->textures[i].cpp = 2;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_ARGB8888:
                case RADEON_TXFORMAT_RGBA8888:
                case RADEON_TXFORMAT_SHADOW32:
                case RADEON_TXFORMAT_LDUDUV8888:
                        track->textures[i].cpp = 4;
+                       track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                        break;
                case RADEON_TXFORMAT_DXT1:
                        track->textures[i].cpp = 1;
@@ -2294,8 +2295,8 @@ 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)
@@ -2351,6 +2352,7 @@ void r100_mc_init(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_IGP)
                base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
        radeon_vram_location(rdev, &rdev->mc, base);
+       rdev->mc.gtt_base_align = 0;
        if (!(rdev->flags & RADEON_IS_AGP))
                radeon_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
@@ -2362,11 +2364,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)
@@ -2604,12 +2605,6 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
        int surf_index = reg * 16;
        int flags = 0;
 
-       /* r100/r200 divide by 16 */
-       if (rdev->family < CHIP_R300)
-               flags = pitch / 16;
-       else
-               flags = pitch / 8;
-
        if (rdev->family <= CHIP_RS200) {
                if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
                                 == (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
@@ -2633,6 +2628,20 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
        if (tiling_flags & RADEON_TILING_SWAP_32BIT)
                flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
 
+       /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */
+       if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) {
+               if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)))
+                       if (ASIC_IS_RN50(rdev))
+                               pitch /= 16;
+       }
+
+       /* r100/r200 divide by 16 */
+       if (rdev->family < CHIP_R300)
+               flags |= pitch / 16;
+       else
+               flags |= pitch / 8;
+
+
        DRM_DEBUG("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);
@@ -3147,33 +3156,6 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
        DRM_ERROR("compress format            %d\n", t->compress_format);
 }
 
-static int r100_cs_track_cube(struct radeon_device *rdev,
-                             struct r100_cs_track *track, unsigned idx)
-{
-       unsigned face, w, h;
-       struct radeon_bo *cube_robj;
-       unsigned long size;
-
-       for (face = 0; face < 5; face++) {
-               cube_robj = track->textures[idx].cube_info[face].robj;
-               w = track->textures[idx].cube_info[face].width;
-               h = track->textures[idx].cube_info[face].height;
-
-               size = w * h;
-               size *= track->textures[idx].cpp;
-
-               size += track->textures[idx].cube_info[face].offset;
-
-               if (size > radeon_bo_size(cube_robj)) {
-                       DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
-                                 size, radeon_bo_size(cube_robj));
-                       r100_cs_track_texture_print(&track->textures[idx]);
-                       return -1;
-               }
-       }
-       return 0;
-}
-
 static int r100_track_compress_size(int compress_format, int w, int h)
 {
        int block_width, block_height, block_bytes;
@@ -3204,6 +3186,37 @@ static int r100_track_compress_size(int compress_format, int w, int h)
        return sz;
 }
 
+static int r100_cs_track_cube(struct radeon_device *rdev,
+                             struct r100_cs_track *track, unsigned idx)
+{
+       unsigned face, w, h;
+       struct radeon_bo *cube_robj;
+       unsigned long size;
+       unsigned compress_format = track->textures[idx].compress_format;
+
+       for (face = 0; face < 5; face++) {
+               cube_robj = track->textures[idx].cube_info[face].robj;
+               w = track->textures[idx].cube_info[face].width;
+               h = track->textures[idx].cube_info[face].height;
+
+               if (compress_format) {
+                       size = r100_track_compress_size(compress_format, w, h);
+               } else
+                       size = w * h;
+               size *= track->textures[idx].cpp;
+
+               size += track->textures[idx].cube_info[face].offset;
+
+               if (size > radeon_bo_size(cube_robj)) {
+                       DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
+                                 size, radeon_bo_size(cube_robj));
+                       r100_cs_track_texture_print(&track->textures[idx]);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
 static int r100_cs_track_texture_check(struct radeon_device *rdev,
                                       struct r100_cs_track *track)
 {
@@ -3795,6 +3808,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;
@@ -3807,6 +3845,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)) {