From: Dave Airlie <[email protected]>

This adds color tiling support for buffers in VRAM, it enables
a color tiled fbcon and a color tiled X frontbuffer.

It changes the API:
adds two new parameters to the object creation API (is this better than
 a set/get tiling?) we probably still need a get but not sure for what yet.
relocs are required for 2D DST_PITCH_OFFSET and SRC_PITCH_OFFSET type-0,
and 3D COLORPITCH registers.

TTM:
adds a new check_tiling call to TTM, gets called at fault and around
bo moves.

Issues:
Can we integrate endian swapping in with this?
Depth buffer handling?
When we run out of surface regs - needs better handling.

Future features:
texture tiling - need to relocate texture registers TXOFFSET* with tiling info.
---
 drivers/gpu/drm/radeon/atombios_crtc.c    |   10 ++-
 drivers/gpu/drm/radeon/r100.c             |   76 +++++++++++++++++++-
 drivers/gpu/drm/radeon/r300.c             |   34 +++++++++-
 drivers/gpu/drm/radeon/r300_reg.h         |    4 +-
 drivers/gpu/drm/radeon/radeon.h           |   28 +++++++-
 drivers/gpu/drm/radeon/radeon_asic.h      |   19 +++++
 drivers/gpu/drm/radeon/radeon_benchmark.c |    6 +-
 drivers/gpu/drm/radeon/radeon_fb.c        |    9 ++-
 drivers/gpu/drm/radeon/radeon_gart.c      |    3 +-
 drivers/gpu/drm/radeon/radeon_gem.c       |    8 ++-
 drivers/gpu/drm/radeon/radeon_object.c    |  109 +++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_ring.c      |    4 +-
 drivers/gpu/drm/radeon/radeon_ttm.c       |    3 +-
 drivers/gpu/drm/ttm/ttm_bo.c              |    3 +
 drivers/gpu/drm/ttm/ttm_bo_vm.c           |    1 +
 include/drm/radeon_drm.h                  |    6 ++
 include/drm/ttm/ttm_bo_driver.h           |    8 ++
 17 files changed, 313 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
b/drivers/gpu/drm/radeon/atombios_crtc.c
index c0080cc..4544d30 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -321,7 +321,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, 
int y,
        struct drm_gem_object *obj;
        struct drm_radeon_gem_object *obj_priv;
        uint64_t fb_location;
-       uint32_t fb_format, fb_pitch_pixels;
+       uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 
        if (!crtc->fb)
                return -EINVAL;
@@ -358,7 +358,13 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, 
int y,
                return -EINVAL;
        }
 
-       /* TODO tiling */
+       tiling_flags = radeon_object_get_tiling_flags(obj->driver_private);
+       if (tiling_flags & RADEON_TILING_MACRO)
+               fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
+
+       if (tiling_flags & RADEON_TILING_MICRO)
+               fb_format |= AVIVO_D1GRPH_TILED;
+
        if (radeon_crtc->crtc_id == 0)
                WREG32(AVIVO_D1VGA_CONTROL, 0);
        else
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index c550932..6b6624f 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -280,7 +280,7 @@ int r100_wb_init(struct radeon_device *rdev)
                r = radeon_object_create(rdev, NULL, 4096,
                                         true,
                                         RADEON_GEM_DOMAIN_GTT,
-                                        false, &rdev->wb.wb_obj);
+                                        false, 0, 0, &rdev->wb.wb_obj);
                if (r) {
                        DRM_ERROR("radeon: failed to create WB buffer (%d).\n", 
r);
                        return r;
@@ -814,6 +814,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        unsigned idx;
        bool onereg;
        int r;
+       u32 tile_flags = 0;
 
        ib = p->ib->ptr;
        ib_chunk = &p->chunks[p->chunk_ib_idx];
@@ -838,7 +839,20 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                        }
                        tmp = ib_chunk->kdata[idx] & 0x003fffff;
                        tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
-                       ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
+
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= RADEON_DST_TILE_MACRO;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                               if (reg == RADEON_SRC_PITCH_OFFSET) {
+                                       DRM_ERROR("Cannot src blit from 
microtiled surface\n");
+                                       r100_cs_dump_packet(p, pkt);
+                                       return -EINVAL;
+                               }
+                               tile_flags |= RADEON_DST_TILE_MICRO;
+                       }
+
+                       tmp |= tile_flags;
+                       ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
                        break;
                case RADEON_RB3D_DEPTHOFFSET:
                case RADEON_RB3D_COLOROFFSET:
@@ -878,6 +892,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                        }
                        ib[idx] = ib_chunk->kdata[idx] + 
((u32)reloc->lobj.gpu_offset);
                        break;
+               case R300_RB3D_COLORPITCH0:
+               case RADEON_RB3D_COLORPITCH:
+                       r = r100_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                         idx, reg);
+                               r100_cs_dump_packet(p, pkt);
+                               return r;
+                       }
+
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= RADEON_COLOR_TILE_ENABLE;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                               tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
+
+                       tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+                       break;
                default:
                        /* FIXME: we don't want to allow anyothers packet */
                        break;
@@ -1533,3 +1566,42 @@ int r100_debugfs_mc_info_init(struct radeon_device *rdev)
        return 0;
 #endif
 }
+
+int r100_set_surface_reg(struct radeon_device *rdev, int reg,
+                        uint32_t tiling_flags, uint32_t pitch,
+                        uint32_t offset, uint32_t obj_size)
+{
+       int surf_index = reg * 16;
+       int flags = 0;
+
+       flags = pitch / 8;
+
+       if (rdev->family <= CHIP_RS200) {
+               if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
+                                == (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
+                       flags |= RADEON_SURF_TILE_COLOR_BOTH;
+               if (tiling_flags & RADEON_TILING_MACRO)
+                       flags |= RADEON_SURF_TILE_COLOR_MACRO;
+       } else if (rdev->family <= CHIP_RV280) {
+               if (tiling_flags & (RADEON_TILING_MACRO))
+                       flags |= R200_SURF_TILE_COLOR_MACRO;
+               if (tiling_flags & RADEON_TILING_MICRO)
+                       flags |= R200_SURF_TILE_COLOR_MICRO;
+       } else {
+               if (tiling_flags & RADEON_TILING_MACRO)
+                       flags |= R300_SURF_TILE_MACRO;
+               if (tiling_flags & RADEON_TILING_MICRO)
+                       flags |= R300_SURF_TILE_MICRO;
+       }
+
+       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);
+       return 0;
+}
+
+void r100_clear_surface_reg(struct radeon_device *rdev, int reg)
+{
+       int surf_index = reg * 16;
+       WREG32(RADEON_SURFACE0_INFO + surf_index, 0);
+}
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index e2ed5bc..98c4a11 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -30,6 +30,7 @@
 #include "drm.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_drm.h"
 
 /* r300,r350,rv350,rv370,rv380 depends on : */
 void r100_hdp_reset(struct radeon_device *rdev);
@@ -1019,7 +1020,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
        struct radeon_cs_reloc *reloc;
        struct r300_cs_track *track;
        volatile uint32_t *ib;
-       uint32_t tmp;
+       uint32_t tmp, tile_flags = 0;
        unsigned i;
        int r;
 
@@ -1038,7 +1039,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                }
                tmp = ib_chunk->kdata[idx] & 0x003fffff;
                tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
-               ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
+
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                       tile_flags |= RADEON_DST_TILE_MACRO;
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                       if (reg == RADEON_SRC_PITCH_OFFSET) {
+                               DRM_ERROR("Cannot src blit from microtiled 
surface\n");
+                               r100_cs_dump_packet(p, pkt);
+                               return -EINVAL;
+                       }
+                       tile_flags |= RADEON_DST_TILE_MICRO;
+               }
+               tmp |= tile_flags;
+               ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
                break;
        case R300_RB3D_COLOROFFSET0:
        case R300_RB3D_COLOROFFSET1:
@@ -1127,6 +1140,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                /* RB3D_COLORPITCH1 */
                /* RB3D_COLORPITCH2 */
                /* RB3D_COLORPITCH3 */
+               r = r100_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                 idx, reg);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                       tile_flags |= R300_COLOR_TILE_ENABLE;
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                       tile_flags |= R300_COLOR_MICROTILE_ENABLE;
+
+               tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+               tmp |= tile_flags;
+               ib[idx] = tmp;
+
                i = (reg - 0x4E38) >> 2;
                track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE;
                switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) {
diff --git a/drivers/gpu/drm/radeon/r300_reg.h 
b/drivers/gpu/drm/radeon/r300_reg.h
index 70f4860..4b7afef 100644
--- a/drivers/gpu/drm/radeon/r300_reg.h
+++ b/drivers/gpu/drm/radeon/r300_reg.h
@@ -27,7 +27,9 @@
 #ifndef _R300_REG_H_
 #define _R300_REG_H_
 
-
+#define R300_SURF_TILE_MACRO (1<<16)
+#define R300_SURF_TILE_MICRO (2<<16)
+#define R300_SURF_TILE_BOTH (3<<16)
 
 
 #define R300_MC_INIT_MISC_LAT_TIMER    0x180
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index d61f2fc..97067c6 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -201,6 +201,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev);
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 
+/*
+ * Tiling registers
+ */
+struct radeon_surface_reg {
+       struct radeon_object *robj;
+};
+
+#define RADEON_MAX_SURFACES 8
 
 /*
  * Radeon buffer.
@@ -213,6 +221,7 @@ struct radeon_object_list {
        uint64_t                gpu_offset;
        unsigned                rdomain;
        unsigned                wdomain;
+       uint32_t                tiling_flags;
 };
 
 int radeon_object_init(struct radeon_device *rdev);
@@ -223,6 +232,7 @@ int radeon_object_create(struct radeon_device *rdev,
                         bool kernel,
                         uint32_t domain,
                         bool interruptible,
+                        uint32_t tiling_flags, uint32_t pitch,
                         struct radeon_object **robj_ptr);
 int radeon_object_kmap(struct radeon_object *robj, void **ptr);
 void radeon_object_kunmap(struct radeon_object *robj);
@@ -242,8 +252,12 @@ void radeon_object_list_clean(struct list_head *head);
 int radeon_object_fbdev_mmap(struct radeon_object *robj,
                             struct vm_area_struct *vma);
 unsigned long radeon_object_size(struct radeon_object *robj);
-
-
+uint32_t radeon_object_get_tiling_flags(struct radeon_object *robj);
+void radeon_object_clear_surface_reg(struct radeon_object *robj);
+int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
+                              bool force_drop);
+int radeon_bo_check_tiling(struct ttm_buffer_object *bo, bool has_moved,
+                          bool force_drop);
 /*
  * GEM objects.
  */
@@ -257,6 +271,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, 
int size,
                             int alignment, int initial_domain,
                             bool discardable, bool kernel,
                             bool interruptible,
+                            uint32_t tiling_flags, uint32_t pitch,
                             struct drm_gem_object **obj);
 int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
                          uint64_t *gpu_addr);
@@ -535,6 +550,11 @@ struct radeon_asic {
        void (*set_memory_clock)(struct radeon_device *rdev, uint32_t 
mem_clock);
        void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
        void (*set_clock_gating)(struct radeon_device *rdev, int enable);
+
+       int (*set_surface_reg)(struct radeon_device *rdev, int reg,
+                              uint32_t tiling_flags, uint32_t pitch,
+                              uint32_t offset, uint32_t obj_size);
+       int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
 };
 
 union radeon_asic_config {
@@ -624,6 +644,8 @@ struct radeon_device {
        bool                            gpu_lockup;
        bool                            shutdown;
        bool                            suspend;
+
+       struct radeon_surface_reg surface_regs[RADEON_MAX_SURFACES];
 };
 
 int radeon_device_init(struct radeon_device *rdev,
@@ -796,5 +818,7 @@ static inline void radeon_ring_write(struct radeon_device 
*rdev, uint32_t v)
 #define radeon_set_memory_clock(rdev, e) 
(rdev)->asic->set_engine_clock((rdev), (e))
 #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), 
(l))
 #define radeon_set_clock_gating(rdev, e) 
(rdev)->asic->set_clock_gating((rdev), (e))
+#define radeon_set_surface_reg(rdev, r, f, p, o, s) 
((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
+#define radeon_clear_surface_reg(rdev, r) 
((rdev)->asic->clear_surface_reg((rdev), (r)))
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h 
b/drivers/gpu/drm/radeon/radeon_asic.h
index e2e5673..dd903d3 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -71,6 +71,10 @@ int r100_copy_blit(struct radeon_device *rdev,
                   uint64_t dst_offset,
                   unsigned num_pages,
                   struct radeon_fence *fence);
+int r100_set_surface_reg(struct radeon_device *rdev, int reg,
+                        uint32_t tiling_flags, uint32_t pitch,
+                        uint32_t offset, uint32_t obj_size);
+int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
 
 static struct radeon_asic r100_asic = {
        .init = &r100_init,
@@ -100,6 +104,8 @@ static struct radeon_asic r100_asic = {
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
 };
 
 
@@ -128,6 +134,7 @@ int r300_copy_dma(struct radeon_device *rdev,
                  uint64_t dst_offset,
                  unsigned num_pages,
                  struct radeon_fence *fence);
+
 static struct radeon_asic r300_asic = {
        .init = &r300_init,
        .errata = &r300_errata,
@@ -156,6 +163,8 @@ static struct radeon_asic r300_asic = {
        .set_memory_clock = NULL,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
 };
 
 /*
@@ -193,6 +202,8 @@ static struct radeon_asic r420_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
 };
 
 
@@ -237,6 +248,8 @@ static struct radeon_asic rs400_asic = {
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
 };
 
 
@@ -322,6 +335,8 @@ static struct radeon_asic rs690_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
 };
 
 
@@ -367,6 +382,8 @@ static struct radeon_asic rv515_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
 };
 
 
@@ -405,6 +422,8 @@ static struct radeon_asic r520_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
 };
 
 /*
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c 
b/drivers/gpu/drm/radeon/radeon_benchmark.c
index c44403a..476b780 100644
--- a/drivers/gpu/drm/radeon/radeon_benchmark.c
+++ b/drivers/gpu/drm/radeon/radeon_benchmark.c
@@ -41,7 +41,8 @@ void radeon_benchmark_move(struct radeon_device *rdev, 
unsigned bsize,
 
        size = bsize;
        n = 1024;
-       r = radeon_object_create(rdev, NULL, size, true, sdomain, false, &sobj);
+       r = radeon_object_create(rdev, NULL, size, true, sdomain, false,
+                                0, 0, &sobj);
        if (r) {
                goto out_cleanup;
        }
@@ -49,7 +50,8 @@ void radeon_benchmark_move(struct radeon_device *rdev, 
unsigned bsize,
        if (r) {
                goto out_cleanup;
        }
-       r = radeon_object_create(rdev, NULL, size, true, ddomain, false, &dobj);
+       r = radeon_object_create(rdev, NULL, size, true, ddomain, false,
+                                0, 0, &dobj);
        if (r) {
                goto out_cleanup;
        }
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c 
b/drivers/gpu/drm/radeon/radeon_fb.c
index fa86d39..02e4532 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -500,7 +500,9 @@ int radeonfb_create(struct radeon_device *rdev,
        ret = radeon_gem_object_create(rdev, aligned_size, 0,
                                       RADEON_GEM_DOMAIN_VRAM,
                                       false, ttm_bo_type_kernel,
-                                      false, &gobj);
+                                      false,
+                                      RADEON_TILING_MACRO,
+                                      mode_cmd.pitch, &gobj);
        if (ret) {
                printk(KERN_ERR "failed to allocate framebuffer\n");
                ret = -ENOMEM;
@@ -633,6 +635,10 @@ int radeonfb_create(struct radeon_device *rdev,
                break;
        }
 
+       ret = radeon_object_check_tiling(robj, 0, 0);
+       if (ret)
+               DRM_ERROR("failed to get surface regs\n");
+
        fb->fbdev = info;
        rfbdev->rfb = rfb;
        rfbdev->rdev = rdev;
@@ -812,6 +818,7 @@ int radeonfb_remove(struct drm_device *dev, struct 
drm_framebuffer *fb)
        if (info) {
                robj = rfb->obj->driver_private;
                unregister_framebuffer(info);
+               radeon_object_clear_surface_reg(robj);
                radeon_object_kunmap(robj);
                framebuffer_release(info);
        }
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c 
b/drivers/gpu/drm/radeon/radeon_gart.c
index d343a15..520a4ff 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -83,7 +83,8 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
                                         rdev->gart.table_size,
                                         true,
                                         RADEON_GEM_DOMAIN_VRAM,
-                                        false, &rdev->gart.table.vram.robj);
+                                        false,
+                                        0, 0, &rdev->gart.table.vram.robj);
                if (r) {
                        return r;
                }
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index eb51603..f0887cb 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -50,6 +50,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int 
size,
                             int alignment, int initial_domain,
                             bool discardable, bool kernel,
                             bool interruptible,
+                            uint32_t tiling_flags, uint32_t pitch,
                             struct drm_gem_object **obj)
 {
        struct drm_gem_object *gobj;
@@ -66,7 +67,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int 
size,
                alignment = PAGE_SIZE;
        }
        r = radeon_object_create(rdev, gobj, size, kernel, initial_domain,
-                                interruptible, &robj);
+                                interruptible, tiling_flags, pitch, &robj);
        if (r) {
                DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n",
                          size, initial_domain, alignment);
@@ -193,7 +194,10 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void 
*data,
        args->size = roundup(args->size, PAGE_SIZE);
        r = radeon_gem_object_create(rdev, args->size, args->alignment,
                                     args->initial_domain, false,
-                                    false, true, &gobj);
+                                    false, true,
+                                    args->tiling_flags,
+                                    args->pitch,
+                                    &gobj);
        if (r) {
                return r;
        }
diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
b/drivers/gpu/drm/radeon/radeon_object.c
index 983e8df..b91a15c 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -44,6 +44,9 @@ struct radeon_object {
        uint64_t                        gpu_addr;
        void                            *kptr;
        bool                            is_iomem;
+       uint32_t                        tiling_flags;
+       uint32_t                        pitch;
+       int                             surface_reg;
 };
 
 int radeon_ttm_init(struct radeon_device *rdev);
@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct 
ttm_buffer_object *tobj)
 
        robj = container_of(tobj, struct radeon_object, tobj);
        list_del_init(&robj->list);
+       radeon_object_clear_surface_reg(robj);
        kfree(robj);
 }
 
@@ -119,6 +123,7 @@ int radeon_object_create(struct radeon_device *rdev,
                         bool kernel,
                         uint32_t domain,
                         bool interruptible,
+                        uint32_t tiling_flags, uint32_t pitch,
                         struct radeon_object **robj_ptr)
 {
        struct radeon_object *robj;
@@ -141,6 +146,12 @@ int radeon_object_create(struct radeon_device *rdev,
        }
        robj->rdev = rdev;
        robj->gobj = gobj;
+       robj->tiling_flags = tiling_flags;
+       robj->pitch = pitch;
+       if (tiling_flags)
+               DRM_ERROR("setting tiling on object %x %d\n", tiling_flags,
+                         pitch);
+       robj->surface_reg = -1;
        INIT_LIST_HEAD(&robj->list);
 
        flags = radeon_object_flags_from_domain(domain);
@@ -465,6 +476,7 @@ int radeon_object_list_validate(struct list_head *head, 
void *fence)
                        radeon_object_gpu_addr(robj);
                }
                lobj->gpu_offset = robj->gpu_addr;
+               lobj->tiling_flags = robj->tiling_flags;
                if (fence) {
                        old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
                        robj->tobj.sync_obj = radeon_fence_ref(fence);
@@ -509,3 +521,100 @@ unsigned long radeon_object_size(struct radeon_object 
*robj)
 {
        return robj->tobj.num_pages << PAGE_SHIFT;
 }
+
+int radeon_object_get_surface_reg(struct radeon_object *robj)
+{
+       struct radeon_device *rdev = robj->rdev;
+       struct radeon_surface_reg *reg;
+       int avail;
+       int i;
+
+       if (!robj->tiling_flags)
+               return 0;
+
+       if (robj->surface_reg >= 0) {
+               reg = &rdev->surface_regs[robj->surface_reg];
+               i = robj->surface_reg;
+               goto out;
+       }
+
+       avail = 0;
+       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+               struct radeon_object *old_object;
+
+               reg = &rdev->surface_regs[i];
+               if (!reg->robj)
+                       break;
+
+               old_object = reg->robj;
+               if (old_object->pin_count == 0)
+                       avail++;
+       }
+
+       /* if we are all out */
+       if (i == RADEON_MAX_SURFACES) {
+               if (avail == 0)
+                       return -ENOMEM;
+       }
+
+       robj->surface_reg = i;
+       reg->robj = robj;
+
+out:
+       radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch,
+                              robj->tobj.mem.mm_node->start << PAGE_SHIFT,
+                              robj->tobj.num_pages << PAGE_SHIFT);
+       return 0;
+}
+
+void radeon_object_clear_surface_reg(struct radeon_object *robj)
+{
+       struct radeon_device *rdev = robj->rdev;
+       struct radeon_surface_reg *reg;
+
+       if (robj->surface_reg == -1)
+               return;
+
+       reg = &rdev->surface_regs[robj->surface_reg];
+       radeon_clear_surface_reg(rdev, robj->surface_reg);
+
+       reg->robj = NULL;
+       robj->surface_reg = -1;
+}
+
+uint32_t radeon_object_get_tiling_flags(struct radeon_object *robj)
+{
+       return robj->tiling_flags;
+}
+
+int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
+                              bool force_drop)
+{
+       struct radeon_device *rdev = robj->rdev;
+
+       if (force_drop) {
+               radeon_object_clear_surface_reg(robj);
+               return 0;
+       }
+
+       if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
+               if (!has_moved)
+                       return 0;
+
+               if (robj->surface_reg >= 0)
+                       radeon_object_clear_surface_reg(robj);
+               return 0;
+       }
+
+       if ((robj->surface_reg >= 0) && !has_moved)
+               return 0;
+
+       return radeon_object_get_surface_reg(robj);
+}
+
+int radeon_bo_check_tiling(struct ttm_buffer_object *bo, bool has_moved,
+                          bool force_drop)
+{
+       struct radeon_object *robj = container_of(bo, struct radeon_object, 
tobj);
+       return radeon_object_check_tiling(robj, has_moved, force_drop);
+}
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index a853261..4f9c518 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -179,7 +179,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
        INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
        r = radeon_object_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
                                 true, RADEON_GEM_DOMAIN_GTT,
-                                false, &rdev->ib_pool.robj);
+                                false, 0, 0, &rdev->ib_pool.robj);
        if (r) {
                DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
                return r;
@@ -397,7 +397,7 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned 
ring_size)
                r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
                                         true,
                                         RADEON_GEM_DOMAIN_GTT,
-                                        false,
+                                        false, 0, 0,
                                         &rdev->cp.ring_obj);
                if (r) {
                        DRM_ERROR("radeon: failed to create ring buffer 
(%d).\n", r);
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index 1227a97..b4934a3 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -429,6 +429,7 @@ static struct ttm_bo_driver radeon_bo_driver = {
        .sync_obj_flush = &radeon_sync_obj_flush,
        .sync_obj_unref = &radeon_sync_obj_unref,
        .sync_obj_ref = &radeon_sync_obj_ref,
+       .check_tiling = &radeon_bo_check_tiling,
 };
 
 int radeon_ttm_init(struct radeon_device *rdev)
@@ -455,7 +456,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
        }
        r = radeon_object_create(rdev, NULL, 256 * 1024, true,
                                 RADEON_GEM_DOMAIN_VRAM, false,
-                                &rdev->stollen_vga_memory);
+                                0, 0, &rdev->stollen_vga_memory);
        if (r) {
                return r;
        }
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index c1c407f..e440b8b 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -304,6 +304,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object 
*bo,
 
        }
 
+       /* drop tiling around bo move */
+       bdev->driver->check_tiling(bo, 0, 1);
+
        if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
            !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
                ret = ttm_bo_move_ttm(bo, evict, no_wait, mem);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 27b146c..c10d96c 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -154,6 +154,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, 
struct vm_fault *vmf)
         */
 
        if (is_iomem) {
+               bdev->driver->check_tiling(bo, 0, 0);
                vma->vm_page_prot = ttm_io_prot(bo->mem.placement,
                                                vma->vm_page_prot);
        } else {
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index 41862e9..1ed43c7 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -788,12 +788,18 @@ struct drm_radeon_gem_info {
 
 #define RADEON_GEM_NO_BACKING_STORE 1
 
+#define RADEON_TILING_MACRO 0x1
+#define RADEON_TILING_MICRO 0x2
+#define RADEON_TILING_SWAP  0x4
+
 struct drm_radeon_gem_create {
        uint64_t        size;
        uint64_t        alignment;
        uint32_t        handle;
        uint32_t        initial_domain;
        uint32_t        flags;
+       uint32_t        tiling_flags;
+       uint32_t        pitch;
 };
 
 struct drm_radeon_gem_mmap {
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 62ed733..bcee01c 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -353,6 +353,14 @@ struct ttm_bo_driver {
        int (*sync_obj_flush) (void *sync_obj, void *sync_arg);
        void (*sync_obj_unref) (void **sync_obj);
        void *(*sync_obj_ref) (void *sync_obj);
+
+       /* hook to check tiling registers are correct
+        * @bo : Pointer to a buffer object
+        * @has_moved : buffer has just been moved
+        * @force_drop: drop the surface
+        */
+       int (*check_tiling)(struct ttm_buffer_object *bo,
+                           bool has_moved, bool force_drop);
 };
 
 #define TTM_NUM_MEM_TYPES 8
-- 
1.6.2.2


------------------------------------------------------------------------------
--
_______________________________________________
Dri-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to