drm/radeon/kms: fix r6xx+ scanout on BE systems
authorAlex Deucher <alexdeucher@gmail.com>
Tue, 25 Jan 2011 16:55:50 +0000 (11:55 -0500)
committerDave Airlie <airlied@gmail.com>
Thu, 27 Jan 2011 03:54:13 +0000 (13:54 +1000)
R6xx+ have per-block swappers.  BE content in the
framebuffer will now be swapped properly during scanout.
Untested, however, the same code is reported working in
the UMS ddx.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@gmail.com>
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/r600_reg.h

index d3ca170..842954f 100644 (file)
@@ -994,6 +994,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
        struct radeon_bo *rbo;
        uint64_t fb_location;
        uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+       u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
        int r;
 
        /* no fb bound */
@@ -1045,11 +1046,17 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
        case 16:
                fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
                             EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
+#ifdef __BIG_ENDIAN
+               fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+#endif
                break;
        case 24:
        case 32:
                fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
                             EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
+#ifdef __BIG_ENDIAN
+               fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+#endif
                break;
        default:
                DRM_ERROR("Unsupported screen depth %d\n",
@@ -1094,6 +1101,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
               (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
        WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
+       WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
 
        WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
        WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
@@ -1150,6 +1158,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        struct drm_framebuffer *target_fb;
        uint64_t fb_location;
        uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+       u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
        int r;
 
        /* no fb bound */
@@ -1203,12 +1212,18 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
                fb_format =
                    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
                    AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
+#ifdef __BIG_ENDIAN
+               fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT;
+#endif
                break;
        case 24:
        case 32:
                fb_format =
                    AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
                    AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
+#ifdef __BIG_ENDIAN
+               fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT;
+#endif
                break;
        default:
                DRM_ERROR("Unsupported screen depth %d\n",
@@ -1248,6 +1263,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
        WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
               radeon_crtc->crtc_offset, (u32) fb_location);
        WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
+       if (rdev->family >= CHIP_R600)
+               WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap);
 
        WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
        WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
index 33cda01..f869897 100644 (file)
 #define R600_MEDIUM_VID_LOWER_GPIO_CNTL                            0x720
 #define R600_LOW_VID_LOWER_GPIO_CNTL                               0x724
 
-
+#define R600_D1GRPH_SWAP_CONTROL                               0x610C
+#       define R600_D1GRPH_SWAP_ENDIAN_NONE                    (0 << 0)
+#       define R600_D1GRPH_SWAP_ENDIAN_16BIT                   (1 << 0)
+#       define R600_D1GRPH_SWAP_ENDIAN_32BIT                   (2 << 0)
+#       define R600_D1GRPH_SWAP_ENDIAN_64BIT                   (3 << 0)
 
 #define R600_HDP_NONSURFACE_BASE                                0x2c04