summaryrefslogtreecommitdiff
path: root/shared-core/nouveau_mem.c
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-06-25 04:39:32 +1000
committerMaarten Maathuis <madman2003@gmail.com>2008-07-18 17:44:51 +0200
commit4872ac9c6204c3f212fd622ed292f6fc245020bf (patch)
tree01e739e5874a220967f2167c40d5b93ee8f1f905 /shared-core/nouveau_mem.c
parenta9089c45570c7b2df9155c2cd73aeea59cc0e34e (diff)
nouveau: interface changes for nv5x 3d
Diffstat (limited to 'shared-core/nouveau_mem.c')
-rw-r--r--shared-core/nouveau_mem.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c
index 861d699f..db207e76 100644
--- a/shared-core/nouveau_mem.c
+++ b/shared-core/nouveau_mem.c
@@ -606,8 +606,11 @@ nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size,
/* Align allocation sizes to 64KiB blocks on G8x. We use a 64KiB
* page size in the GPU VM.
*/
- if (flags & NOUVEAU_MEM_FB && dev_priv->card_type >= NV_50)
- size = (size + (64 * 1024)) & ~((64 * 1024) - 1);
+ if (flags & NOUVEAU_MEM_FB && dev_priv->card_type >= NV_50) {
+ size = (size + 65535) & ~65535;
+ if (alignment < 16)
+ alignment = 16;
+ }
/*
* Warn about 0 sized allocations, but let it go through. It'll return 1 page
@@ -669,6 +672,7 @@ alloc_ok:
struct nouveau_gpuobj *pt = dev_priv->vm_vram_pt;
unsigned offset = block->start;
unsigned count = block->size / 65536;
+ unsigned tile = 0;
if (!pt) {
DRM_ERROR("vm alloc without vm pt\n");
@@ -676,11 +680,22 @@ alloc_ok:
return NULL;
}
+ /* The tiling stuff is *not* what NVIDIA does - but both the
+ * 2D and 3D engines seem happy with this simpler method.
+ * Should look into why NVIDIA do what they do at some point.
+ */
+ if (flags & NOUVEAU_MEM_TILE) {
+ if (flags & NOUVEAU_MEM_TILE_ZETA)
+ tile = 0x00002800;
+ else
+ tile = 0x00007000;
+ }
+
while (count--) {
unsigned pte = offset / 65536;
INSTANCE_WR(pt, (pte * 2) + 0, offset | 1);
- INSTANCE_WR(pt, (pte * 2) + 1, 0x00000000);
+ INSTANCE_WR(pt, (pte * 2) + 1, 0x00000000 | tile);
offset += 65536;
}
} else {
@@ -833,3 +848,53 @@ int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *
nouveau_mem_free(dev, block);
return 0;
}
+
+int
+nouveau_ioctl_mem_tile(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct drm_nouveau_mem_tile *memtile = data;
+ struct mem_block *block = NULL;
+
+ NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+ if (dev_priv->card_type < NV_50)
+ return -EINVAL;
+
+ if (memtile->flags & NOUVEAU_MEM_FB) {
+ memtile->offset -= 512*1024*1024;
+ block = find_block(dev_priv->fb_heap, memtile->offset);
+ }
+
+ if (!block)
+ return -EINVAL;
+
+ if (block->file_priv != file_priv)
+ return -EPERM;
+
+ {
+ struct nouveau_gpuobj *pt = dev_priv->vm_vram_pt;
+ unsigned offset = block->start + memtile->delta;
+ unsigned count = memtile->size / 65536;
+ unsigned tile = 0;
+
+ if (memtile->flags & NOUVEAU_MEM_TILE) {
+ if (memtile->flags & NOUVEAU_MEM_TILE_ZETA)
+ tile = 0x00002800;
+ else
+ tile = 0x00007000;
+ }
+
+ while (count--) {
+ unsigned pte = offset / 65536;
+
+ INSTANCE_WR(pt, (pte * 2) + 0, offset | 1);
+ INSTANCE_WR(pt, (pte * 2) + 1, 0x00000000 | tile);
+ offset += 65536;
+ }
+ }
+
+ return 0;
+}
+