diff mbox

radeon/kms: set/get the scanout flag using the set/get_tiling ioctls

Message ID 1376331563-1244-1-git-send-email-marek.olsak@amd.com (mailing list archive)
State New, archived
Headers show

Commit Message

Marek Olšák Aug. 12, 2013, 6:19 p.m. UTC
Basically just pass RADEON_TILING_R600_SCANOUT everywhere.
Hopefully I didn't miss anything. This is only compile-tested.

Signed-off-by: Marek Olšák <marek.olsak@amd.com>
---
 src/drmmode_display.c  | 44 +++++++++++++++++++++++++++++++++-----------
 src/radeon_bo_helper.c | 11 +++++++++--
 src/radeon_drm.h       |  5 +++--
 src/radeon_kms.c       | 28 +++++++++++++++++++---------
 4 files changed, 64 insertions(+), 24 deletions(-)

Comments

Marek Olšák Aug. 13, 2013, 11:35 a.m. UTC | #1
Please disregard this patch and the related patches. It causes a
regression which I haven't been able to fix yet.

Marek

On Mon, Aug 12, 2013 at 8:19 PM, Marek Olšák <maraeo@gmail.com> wrote:
> Basically just pass RADEON_TILING_R600_SCANOUT everywhere.
> Hopefully I didn't miss anything. This is only compile-tested.
>
> Signed-off-by: Marek Olšák <marek.olsak@amd.com>
> ---
>  src/drmmode_display.c  | 44 +++++++++++++++++++++++++++++++++-----------
>  src/radeon_bo_helper.c | 11 +++++++++--
>  src/radeon_drm.h       |  5 +++--
>  src/radeon_kms.c       | 28 +++++++++++++++++++---------
>  4 files changed, 64 insertions(+), 24 deletions(-)
>
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index 3a0187e..7c055d3 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -123,7 +123,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
>                         surface->last_level = 0;
>                         surface->bpe = bpp / 8;
>                         surface->nsamples = 1;
> -                       surface->flags = RADEON_SURF_SCANOUT;
> +                       surface->flags = 0;
>                         /* we are requiring a recent enough libdrm version */
>                         surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
>                         surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
> @@ -136,6 +136,9 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
>                                 surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
>                                 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
>                         }
> +                       if (tiling & RADEON_TILING_R600_SCANOUT) {
> +                               surface->flags |= RADEON_SURF_SCANOUT;
> +                       }
>                         if (radeon_surface_best(info->surf_man, surface)) {
>                                 return NULL;
>                         }
> @@ -313,6 +316,8 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
>         struct radeon_bo *bo;
>         drmModeFBPtr fbcon;
>         struct drm_gem_flink flink;
> +       unsigned tiling = 0;
> +       RADEONInfoPtr info = RADEONPTR(pScrn);
>
>         fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
>         if (fbcon == NULL)
> @@ -337,9 +342,13 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
>                 goto out_free_fb;
>         }
>
> +       if (info->ChipFamily >= CHIP_FAMILY_R600) {
> +               tiling |= RADEON_TILING_R600_SCANOUT;
> +       }
> +
>         pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
>                                           fbcon->depth, fbcon->bpp,
> -                                         fbcon->pitch, 0, bo, NULL);
> +                                         fbcon->pitch, tiling, bo, NULL);
>         radeon_bo_unref(bo);
>  out_free_fb:
>         drmModeFreeFB(fbcon);
> @@ -399,6 +408,10 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
>                              drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
>                 info->pixel_bytes;
>
> +       if (info->ChipFamily >= CHIP_FAMILY_R600) {
> +               tiling_flags |= RADEON_TILING_R600_SCANOUT;
> +       }
> +
>         dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX,
>                                        pScrn->virtualY, pScrn->depth,
>                                        pScrn->bitsPerPixel, pitch,
> @@ -1418,6 +1431,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
>                         tiling_flags |= RADEON_TILING_MACRO;
>         }
>
> +       if (info->ChipFamily >= CHIP_FAMILY_R600) {
> +               tiling_flags |= RADEON_TILING_R600_SCANOUT;
> +       }
> +
>         pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
>         height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
>         screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
> @@ -1434,7 +1451,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
>                 surface.last_level = 0;
>                 surface.bpe = cpp;
>                 surface.nsamples = 1;
> -               surface.flags = RADEON_SURF_SCANOUT;
> +               surface.flags = 0;
>                 /* we are requiring a recent enough libdrm version */
>                 surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
>                 surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
> @@ -1447,6 +1464,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
>                         surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
>                         surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
>                 }
> +               if (tiling_flags & RADEON_TILING_R600_SCANOUT) {
> +                       surface.flags |= RADEON_SURF_SCANOUT;
> +               }
>                 if (radeon_surface_best(info->surf_man, &surface)) {
>                         return FALSE;
>                 }
> @@ -1456,7 +1476,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
>                 screen_size = surface.bo_size;
>                 base_align = surface.bo_alignment;
>                 pitch = surface.level[0].pitch_bytes;
> -               tiling_flags = 0;
> +               tiling_flags = RADEON_TILING_R600_SCANOUT;
>                 switch (surface.level[0].mode) {
>                 case RADEON_SURF_MODE_2D:
>                         tiling_flags |= RADEON_TILING_MACRO;
> @@ -1493,13 +1513,15 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
>                 goto fail;
>
>  #if X_BYTE_ORDER == X_BIG_ENDIAN
> -       switch (cpp) {
> -       case 4:
> -           tiling_flags |= RADEON_TILING_SWAP_32BIT;
> -           break;
> -       case 2:
> -           tiling_flags |= RADEON_TILING_SWAP_16BIT;
> -           break;
> +       if (info->ChipFamily < CHIP_FAMILY_R600) {
> +               switch (cpp) {
> +               case 4:
> +                   tiling_flags |= RADEON_TILING_SWAP_32BIT;
> +                   break;
> +               case 2:
> +                   tiling_flags |= RADEON_TILING_SWAP_16BIT;
> +                   break;
> +               }
>         }
>  #endif
>         if (tiling_flags)
> diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
> index 539590c..9ba7282 100644
> --- a/src/radeon_bo_helper.c
> +++ b/src/radeon_bo_helper.c
> @@ -105,6 +105,10 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
>          tiling &= ~RADEON_TILING_MACRO;
>      }
>
> +    if (info->ChipFamily >= CHIP_FAMILY_R600) {
> +           tiling |= RADEON_TILING_R600_SCANOUT;
> +    }
> +
>      heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
>      pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
>      base_align = drmmode_get_base_align(pScrn, cpp, tiling);
> @@ -131,7 +135,7 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
>                                  */
>                                 tiling &= ~RADEON_TILING_MACRO;
>                         }
> -                       surface.flags = RADEON_SURF_SCANOUT;
> +                       surface.flags = 0;
>                         /* we are requiring a recent enough libdrm version */
>                         surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
>                         surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
> @@ -144,6 +148,9 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
>                                 surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
>                                 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
>                         }
> +                       if (tiling & RADEON_TILING_R600_SCANOUT) {
> +                               surface.flags |= RADEON_SURF_SCANOUT;
> +                       }
>                         if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
>                                 surface.flags |= RADEON_SURF_ZBUFFER;
>                                 surface.flags |= RADEON_SURF_SBUFFER;
> @@ -157,7 +164,7 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
>                         size = surface.bo_size;
>                         base_align = surface.bo_alignment;
>                         pitch = surface.level[0].pitch_bytes;
> -                       tiling = 0;
> +                       tiling = RADEON_TILING_R600_SCANOUT;
>                         switch (surface.level[0].mode) {
>                         case RADEON_SURF_MODE_2D:
>                                 tiling |= RADEON_TILING_MACRO;
> diff --git a/src/radeon_drm.h b/src/radeon_drm.h
> index 042e822..1fe3d50 100644
> --- a/src/radeon_drm.h
> +++ b/src/radeon_drm.h
> @@ -802,8 +802,9 @@ struct drm_radeon_gem_create {
>
>  #define RADEON_TILING_MACRO                            0x1
>  #define RADEON_TILING_MICRO                            0x2
> -#define RADEON_TILING_SWAP_16BIT                       0x4
> -#define RADEON_TILING_SWAP_32BIT                       0x8
> +#define RADEON_TILING_R600_SCANOUT                     0x4 /* r600 and later */
> +#define RADEON_TILING_SWAP_16BIT                       0x4 /* r100-r500 */
> +#define RADEON_TILING_SWAP_32BIT                       0x8 /* r100-r500 */
>  /* this object requires a surface when mapped - i.e. front buffer */
>  #define RADEON_TILING_SURFACE                          0x10
>  #define RADEON_TILING_MICRO_SQUARE                     0x20
> diff --git a/src/radeon_kms.c b/src/radeon_kms.c
> index c3f50d5..87c5ca0 100644
> --- a/src/radeon_kms.c
> +++ b/src/radeon_kms.c
> @@ -1477,6 +1477,11 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
>         } else
>             tiling_flags |= RADEON_TILING_MACRO;
>      }
> +
> +    if (info->ChipFamily >= CHIP_FAMILY_R600) {
> +           tiling_flags |= RADEON_TILING_R600_SCANOUT;
> +    }
> +
>      pitch = RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp;
>      screen_size = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)) * pitch;
>      base_align = drmmode_get_base_align(pScrn, cpp, tiling_flags);
> @@ -1497,7 +1502,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
>                 surface.last_level = 0;
>                 surface.bpe = cpp;
>                 surface.nsamples = 1;
> -               surface.flags = RADEON_SURF_SCANOUT;
> +               surface.flags = 0;
>                 /* we are requiring a recent enough libdrm version */
>                 surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
>                 surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
> @@ -1510,6 +1515,9 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
>                         surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
>                         surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
>                 }
> +               if (tiling_flags & RADEON_TILING_R600_SCANOUT) {
> +                       surface.flags |= RADEON_SURF_SCANOUT;
> +               }
>                 if (radeon_surface_best(info->surf_man, &surface)) {
>                         xf86DrvMsg(pScreen->myNum, X_ERROR,
>                                    "radeon_surface_best failed\n");
> @@ -1523,7 +1531,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
>                 pitch = surface.level[0].pitch_bytes;
>                 screen_size = surface.bo_size;
>                 base_align = surface.bo_alignment;
> -               tiling_flags = 0;
> +               tiling_flags = RADEON_TILING_R600_SCANOUT;
>                 switch (surface.level[0].mode) {
>                 case RADEON_SURF_MODE_2D:
>                         tiling_flags |= RADEON_TILING_MACRO;
> @@ -1577,13 +1585,15 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
>              }
>          }
>  #if X_BYTE_ORDER == X_BIG_ENDIAN
> -       switch (cpp) {
> -       case 4:
> -           tiling_flags |= RADEON_TILING_SWAP_32BIT;
> -           break;
> -       case 2:
> -           tiling_flags |= RADEON_TILING_SWAP_16BIT;
> -           break;
> +       if (info->ChipFamily < CHIP_FAMILY_R600) {
> +               switch (cpp) {
> +               case 4:
> +                   tiling_flags |= RADEON_TILING_SWAP_32BIT;
> +                   break;
> +               case 2:
> +                   tiling_flags |= RADEON_TILING_SWAP_16BIT;
> +                   break;
> +               }
>         }
>  #endif
>         if (tiling_flags)
> --
> 1.8.1.2
>
diff mbox

Patch

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3a0187e..7c055d3 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -123,7 +123,7 @@  static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 			surface->last_level = 0;
 			surface->bpe = bpp / 8;
 			surface->nsamples = 1;
-			surface->flags = RADEON_SURF_SCANOUT;
+			surface->flags = 0;
 			/* we are requiring a recent enough libdrm version */
 			surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
 			surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
@@ -136,6 +136,9 @@  static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
 				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
 			}
+			if (tiling & RADEON_TILING_R600_SCANOUT) {
+				surface->flags |= RADEON_SURF_SCANOUT;
+			}
 			if (radeon_surface_best(info->surf_man, surface)) {
 				return NULL;
 			}
@@ -313,6 +316,8 @@  create_pixmap_for_fbcon(drmmode_ptr drmmode,
 	struct radeon_bo *bo;
 	drmModeFBPtr fbcon;
 	struct drm_gem_flink flink;
+	unsigned tiling = 0;
+	RADEONInfoPtr info = RADEONPTR(pScrn);
 
 	fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
 	if (fbcon == NULL)
@@ -337,9 +342,13 @@  create_pixmap_for_fbcon(drmmode_ptr drmmode,
 		goto out_free_fb;
 	}
 
+	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		tiling |= RADEON_TILING_R600_SCANOUT;
+	}
+
 	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
 					  fbcon->depth, fbcon->bpp,
-					  fbcon->pitch, 0, bo, NULL);
+					  fbcon->pitch, tiling, bo, NULL);
 	radeon_bo_unref(bo);
 out_free_fb:
 	drmModeFreeFB(fbcon);
@@ -399,6 +408,10 @@  void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 			     drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
 		info->pixel_bytes;
 
+	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		tiling_flags |= RADEON_TILING_R600_SCANOUT;
+	}
+
 	dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX,
 				       pScrn->virtualY, pScrn->depth,
 				       pScrn->bitsPerPixel, pitch,
@@ -1418,6 +1431,10 @@  drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 			tiling_flags |= RADEON_TILING_MACRO;
 	}
 
+	if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		tiling_flags |= RADEON_TILING_R600_SCANOUT;
+	}
+
 	pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
 	height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
 	screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
@@ -1434,7 +1451,7 @@  drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		surface.last_level = 0;
 		surface.bpe = cpp;
 		surface.nsamples = 1;
-		surface.flags = RADEON_SURF_SCANOUT;
+		surface.flags = 0;
 		/* we are requiring a recent enough libdrm version */
 		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
 		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
@@ -1447,6 +1464,9 @@  drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
 			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
 		}
+		if (tiling_flags & RADEON_TILING_R600_SCANOUT) {
+			surface.flags |= RADEON_SURF_SCANOUT;
+		}
 		if (radeon_surface_best(info->surf_man, &surface)) {
 			return FALSE;
 		}
@@ -1456,7 +1476,7 @@  drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		screen_size = surface.bo_size;
 		base_align = surface.bo_alignment;
 		pitch = surface.level[0].pitch_bytes;
-		tiling_flags = 0;
+		tiling_flags = RADEON_TILING_R600_SCANOUT;
 		switch (surface.level[0].mode) {
 		case RADEON_SURF_MODE_2D:
 			tiling_flags |= RADEON_TILING_MACRO;
@@ -1493,13 +1513,15 @@  drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 		goto fail;
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	switch (cpp) {
-	case 4:
-	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
-	    break;
-	case 2:
-	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
-	    break;
+	if (info->ChipFamily < CHIP_FAMILY_R600) {
+		switch (cpp) {
+		case 4:
+		    tiling_flags |= RADEON_TILING_SWAP_32BIT;
+		    break;
+		case 2:
+		    tiling_flags |= RADEON_TILING_SWAP_16BIT;
+		    break;
+		}
 	}
 #endif
 	if (tiling_flags)
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
index 539590c..9ba7282 100644
--- a/src/radeon_bo_helper.c
+++ b/src/radeon_bo_helper.c
@@ -105,6 +105,10 @@  radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
         tiling &= ~RADEON_TILING_MACRO;
     }
 
+    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	    tiling |= RADEON_TILING_R600_SCANOUT;
+    }
+
     heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
     pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
     base_align = drmmode_get_base_align(pScrn, cpp, tiling);
@@ -131,7 +135,7 @@  radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 				 */
 				tiling &= ~RADEON_TILING_MACRO;
 			}
-			surface.flags = RADEON_SURF_SCANOUT;
+			surface.flags = 0;
 			/* we are requiring a recent enough libdrm version */
 			surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
 			surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
@@ -144,6 +148,9 @@  radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 				surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
 				surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
 			}
+			if (tiling & RADEON_TILING_R600_SCANOUT) {
+				surface.flags |= RADEON_SURF_SCANOUT;
+			}
 			if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
 				surface.flags |= RADEON_SURF_ZBUFFER;
 				surface.flags |= RADEON_SURF_SBUFFER;
@@ -157,7 +164,7 @@  radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
 			size = surface.bo_size;
 			base_align = surface.bo_alignment;
 			pitch = surface.level[0].pitch_bytes;
-			tiling = 0;
+			tiling = RADEON_TILING_R600_SCANOUT;
 			switch (surface.level[0].mode) {
 			case RADEON_SURF_MODE_2D:
 				tiling |= RADEON_TILING_MACRO;
diff --git a/src/radeon_drm.h b/src/radeon_drm.h
index 042e822..1fe3d50 100644
--- a/src/radeon_drm.h
+++ b/src/radeon_drm.h
@@ -802,8 +802,9 @@  struct drm_radeon_gem_create {
 
 #define RADEON_TILING_MACRO				0x1
 #define RADEON_TILING_MICRO				0x2
-#define RADEON_TILING_SWAP_16BIT			0x4
-#define RADEON_TILING_SWAP_32BIT			0x8
+#define RADEON_TILING_R600_SCANOUT			0x4 /* r600 and later */
+#define RADEON_TILING_SWAP_16BIT			0x4 /* r100-r500 */
+#define RADEON_TILING_SWAP_32BIT			0x8 /* r100-r500 */
 /* this object requires a surface when mapped - i.e. front buffer */
 #define RADEON_TILING_SURFACE				0x10
 #define RADEON_TILING_MICRO_SQUARE			0x20
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index c3f50d5..87c5ca0 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -1477,6 +1477,11 @@  static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 	} else
 	    tiling_flags |= RADEON_TILING_MACRO;
     }
+
+    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	    tiling_flags |= RADEON_TILING_R600_SCANOUT;
+    }
+
     pitch = RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp;
     screen_size = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)) * pitch;
     base_align = drmmode_get_base_align(pScrn, cpp, tiling_flags);
@@ -1497,7 +1502,7 @@  static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 		surface.last_level = 0;
 		surface.bpe = cpp;
 		surface.nsamples = 1;
-		surface.flags = RADEON_SURF_SCANOUT;
+		surface.flags = 0;
 		/* we are requiring a recent enough libdrm version */
 		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
 		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
@@ -1510,6 +1515,9 @@  static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
 			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
 		}
+		if (tiling_flags & RADEON_TILING_R600_SCANOUT) {
+			surface.flags |= RADEON_SURF_SCANOUT;
+		}
 		if (radeon_surface_best(info->surf_man, &surface)) {
 			xf86DrvMsg(pScreen->myNum, X_ERROR,
 				   "radeon_surface_best failed\n");
@@ -1523,7 +1531,7 @@  static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 		pitch = surface.level[0].pitch_bytes;
 		screen_size = surface.bo_size;
 		base_align = surface.bo_alignment;
-		tiling_flags = 0;
+		tiling_flags = RADEON_TILING_R600_SCANOUT;
 		switch (surface.level[0].mode) {
 		case RADEON_SURF_MODE_2D:
 			tiling_flags |= RADEON_TILING_MACRO;
@@ -1577,13 +1585,15 @@  static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
             }
         }
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	switch (cpp) {
-	case 4:
-	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
-	    break;
-	case 2:
-	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
-	    break;
+	if (info->ChipFamily < CHIP_FAMILY_R600) {
+		switch (cpp) {
+		case 4:
+		    tiling_flags |= RADEON_TILING_SWAP_32BIT;
+		    break;
+		case 2:
+		    tiling_flags |= RADEON_TILING_SWAP_16BIT;
+		    break;
+		}
 	}
 #endif
 	if (tiling_flags)