OSDN Git Service

nouveau: interface changes for nv5x 3d
authorBen Skeggs <skeggsb@gmail.com>
Tue, 24 Jun 2008 18:39:32 +0000 (04:39 +1000)
committerBen Skeggs <skeggsb@gmail.com>
Tue, 8 Jul 2008 02:35:50 +0000 (12:35 +1000)
shared-core/nouveau_drm.h
shared-core/nouveau_drv.h
shared-core/nouveau_fifo.c
shared-core/nouveau_mem.c

index bbb51bc..4b5869a 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef __NOUVEAU_DRM_H__
 #define __NOUVEAU_DRM_H__
 
-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 11
 
 struct drm_nouveau_channel_alloc {
        uint32_t     fb_ctxdma_handle;
@@ -85,10 +85,12 @@ struct drm_nouveau_gpuobj_free {
 #define NOUVEAU_MEM_PINNED             0x00000040
 #define NOUVEAU_MEM_USER_BACKED                0x00000080
 #define NOUVEAU_MEM_MAPPED             0x00000100
-#define NOUVEAU_MEM_INSTANCE           0x00000200 /* internal */
-#define NOUVEAU_MEM_NOTIFIER            0x00000400 /* internal */
-#define NOUVEAU_MEM_NOVM               0x00000800 /* internal */
-#define NOUVEAU_MEM_USER               0x00001000 /* internal */
+#define NOUVEAU_MEM_TILE               0x00000200
+#define NOUVEAU_MEM_TILE_ZETA          0x00000400
+#define NOUVEAU_MEM_INSTANCE           0x01000000 /* internal */
+#define NOUVEAU_MEM_NOTIFIER            0x02000000 /* internal */
+#define NOUVEAU_MEM_NOVM               0x04000000 /* internal */
+#define NOUVEAU_MEM_USER               0x08000000 /* internal */
 #define NOUVEAU_MEM_INTERNAL (NOUVEAU_MEM_INSTANCE | \
                              NOUVEAU_MEM_NOTIFIER | \
                              NOUVEAU_MEM_NOVM | \
@@ -107,6 +109,13 @@ struct drm_nouveau_mem_free {
        int flags;
 };
 
+struct drm_nouveau_mem_tile {
+       uint64_t offset;
+       uint64_t delta;
+       uint64_t size;
+       int flags;
+};
+
 /* FIXME : maybe unify {GET,SET}PARAMs */
 #define NOUVEAU_GETPARAM_PCI_VENDOR      3
 #define NOUVEAU_GETPARAM_PCI_DEVICE      4
@@ -168,5 +177,6 @@ struct drm_nouveau_sarea {
 #define DRM_NOUVEAU_GPUOBJ_FREE        0x07
 #define DRM_NOUVEAU_MEM_ALLOC          0x08
 #define DRM_NOUVEAU_MEM_FREE           0x09
+#define DRM_NOUVEAU_MEM_TILE           0x0a
 
 #endif /* __NOUVEAU_DRM_H__ */
index 1aaf1d7..cd5f9cf 100644 (file)
@@ -34,7 +34,7 @@
 
 #define DRIVER_MAJOR           0
 #define DRIVER_MINOR           0
-#define DRIVER_PATCHLEVEL      10
+#define DRIVER_PATCHLEVEL      11
 
 #define NOUVEAU_FAMILY   0x0000FFFF
 #define NOUVEAU_FLAGS    0xFFFF0000
@@ -359,6 +359,8 @@ extern int  nouveau_ioctl_mem_alloc(struct drm_device *, void *data,
                                    struct drm_file *);
 extern int  nouveau_ioctl_mem_free(struct drm_device *, void *data,
                                   struct drm_file *);
+extern int  nouveau_ioctl_mem_tile(struct drm_device *, void *data,
+                                  struct drm_file *);
 extern struct mem_block* nouveau_mem_alloc(struct drm_device *,
                                           int alignment, uint64_t size,
                                           int flags, struct drm_file *);
index d8fda27..085336a 100644 (file)
@@ -593,6 +593,7 @@ struct drm_ioctl_desc nouveau_ioctls[] = {
        DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_TILE, nouveau_ioctl_mem_tile, DRM_AUTH),
 };
 
 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
index 5894282..d79c1a5 100644 (file)
@@ -594,7 +594,7 @@ nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size,
         * page size in the GPU VM.
         */
        if (flags & NOUVEAU_MEM_FB && dev_priv->card_type >= NV_50) {
-               size = (size + (64 * 1024)) & ~((64 * 1024) - 1);
+               size = (size + 65535) & ~65535;
                if (alignment < 16)
                        alignment = 16;
        }
@@ -659,6 +659,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");
@@ -666,11 +667,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 {
@@ -808,3 +820,53 @@ nouveau_ioctl_mem_free(struct drm_device *dev, void *data,
        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;
+}
+