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