Allow cmdbuf location(AGP,VRAM) and size to be configured.
authorBen Skeggs <darktama@iinet.net.au>
Sat, 2 Sep 2006 20:36:06 +0000 (06:36 +1000)
committerBen Skeggs <darktama@iinet.net.au>
Sat, 2 Sep 2006 20:36:06 +0000 (06:36 +1000)
shared-core/nouveau_drm.h
shared-core/nouveau_drv.h
shared-core/nouveau_fifo.c
shared-core/nouveau_state.c

index 76fb3a1..1180a13 100644 (file)
@@ -85,6 +85,8 @@ typedef struct drm_nouveau_getparam {
 }
 drm_nouveau_getparam_t;
 
+#define NOUVEAU_SETPARAM_CMDBUF_LOCATION 1
+#define NOUVEAU_SETPARAM_CMDBUF_SIZE     2
 typedef struct drm_nouveau_setparam {
        unsigned int param;
        unsigned int value;
index d701401..7af9c61 100644 (file)
@@ -97,6 +97,13 @@ struct mem_block {
        drm_local_map_t *map;
 };
 
+struct nouveau_config {
+       struct {
+               int location;
+               int size;
+       } cmdbuf;
+};
+
 typedef struct drm_nouveau_private {
        /* the card type, takes NV_* as values */
        int card_type;
@@ -111,9 +118,7 @@ typedef struct drm_nouveau_private {
 
        struct nouveau_object *fb_obj;
        struct nouveau_object *cmdbuf_obj;
-       int      cmdbuf_location;
-       int      cmdbuf_base;
-       int      cmdbuf_ch_size;
+       int               cmdbuf_ch_size;
        struct mem_block* cmdbuf_alloc;
 
        struct nouveau_fifo fifos[NV_MAX_FIFO_NUMBER];
@@ -123,6 +128,7 @@ typedef struct drm_nouveau_private {
        struct mem_block *fb_heap;
        struct mem_block *fb_nomap_heap;
 
+       struct nouveau_config config;
 }
 drm_nouveau_private_t;
 
@@ -133,6 +139,7 @@ extern int nouveau_firstopen(struct drm_device *dev);
 extern int nouveau_unload(struct drm_device *dev);
 extern int nouveau_ioctl_getparam(DRM_IOCTL_ARGS);
 extern int nouveau_ioctl_setparam(DRM_IOCTL_ARGS);
+extern int nouveau_dma_init(struct drm_device *dev);
 
 /* nouveau_mem.c */
 extern uint64_t          nouveau_mem_fb_amount(struct drm_device *dev);
index c0d54b3..67ee6c7 100644 (file)
@@ -77,6 +77,15 @@ static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DR
        int ret;
        drm_nouveau_private_t *dev_priv = dev->dev_private;
 
+       /* Init cmdbuf on first FIFO init, this is delayed until now to
+        * give the ddx a chance to configure the cmdbuf with SETPARAM
+        */
+       if (!dev_priv->cmdbuf_alloc) {
+               ret = nouveau_dma_init(dev);
+               if (ret)
+                       return ret;
+       }
+
        /*
         * Alright, here is the full story
         * Nvidia cards have multiple hw fifo contexts (praise them for that, 
@@ -120,7 +129,7 @@ static int nouveau_fifo_init(drm_device_t* dev,drm_nouveau_fifo_init_t* init, DR
                return ret;
 
        /* then, the fifo itself */
-       init->cmdbuf       = dev_priv->cmdbuf_base;
+       init->cmdbuf       = dev_priv->cmdbuf_alloc->start;
        init->cmdbuf      += init->channel * dev_priv->cmdbuf_ch_size;
        init->cmdbuf_size  = dev_priv->cmdbuf_ch_size;
        ret = drm_addmap(dev, init->cmdbuf, init->cmdbuf_size, _DRM_REGISTERS,
@@ -157,8 +166,9 @@ void nouveau_fifo_cleanup(drm_device_t * dev, DRMFILE filp)
                DRM_DEBUG("%s: new cur_fifo is %d\n", __func__, i);
                dev_priv->cur_fifo = i;
        }
-       
-       nouveau_pfifo_init(dev);
+
+       if (dev_priv->cmdbuf_alloc)
+               nouveau_pfifo_init(dev);
 //     nouveau_fifo_enable(dev);
 }
 
index 01ebbc8..fbe9464 100644 (file)
@@ -76,32 +76,6 @@ int nouveau_firstopen(struct drm_device *dev)
                                0, nouveau_mem_fb_amount(dev),
                                NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM);
 
-       /* allocate one buffer for all the fifos */
-       dev_priv->cmdbuf_alloc = nouveau_mem_alloc(dev, 0, 1024*1024, NOUVEAU_MEM_FB, (DRMFILE)-2);
-
-       if (dev_priv->cmdbuf_alloc->flags&NOUVEAU_MEM_AGP) {
-               dev_priv->cmdbuf_location = NV_DMA_TARGET_AGP;
-               dev_priv->cmdbuf_ch_size  = NV03_FIFO_SIZE;
-               dev_priv->cmdbuf_base     = dev_priv->cmdbuf_alloc->start;
-               dev_priv->cmdbuf_obj = nouveau_dma_object_create(dev,
-                               dev_priv->cmdbuf_base, nouveau_fifo_number(dev)*NV03_FIFO_SIZE,
-                               NV_DMA_ACCESS_RO, dev_priv->cmdbuf_location);
-       } else { /* NOUVEAU_MEM_FB */
-               dev_priv->cmdbuf_location = NV_DMA_TARGET_VIDMEM;
-               dev_priv->cmdbuf_ch_size  = NV03_FIFO_SIZE;
-               dev_priv->cmdbuf_base     = dev_priv->cmdbuf_alloc->start;
-               dev_priv->cmdbuf_obj = nouveau_dma_object_create(dev,
-                               dev_priv->cmdbuf_base - drm_get_resource_start(dev, 1),
-                               nouveau_fifo_number(dev)*NV03_FIFO_SIZE,
-                               NV_DMA_ACCESS_RO, dev_priv->cmdbuf_location);
-       }
-
-       DRM_INFO("DMA command buffer is %dKiB at 0x%08x(%s)\n",
-                       (nouveau_fifo_number(dev)*dev_priv->cmdbuf_ch_size)/1024,
-                       dev_priv->cmdbuf_base,
-                       dev_priv->cmdbuf_location == NV_DMA_TARGET_AGP ? "AGP" : "VRAM"
-                       );
-
        return 0;
 }
 
@@ -154,12 +128,27 @@ int nouveau_ioctl_getparam(DRM_IOCTL_ARGS)
 int nouveau_ioctl_setparam(DRM_IOCTL_ARGS)
 {
        DRM_DEVICE;
+       drm_nouveau_private_t *dev_priv = dev->dev_private;
        drm_nouveau_setparam_t setparam;
 
        DRM_COPY_FROM_USER_IOCTL(setparam, (drm_nouveau_setparam_t __user *)data,
                        sizeof(setparam));
 
        switch (setparam.param) {
+       case NOUVEAU_SETPARAM_CMDBUF_LOCATION:
+               switch (setparam.value) {
+               case NOUVEAU_MEM_AGP:
+               case NOUVEAU_MEM_FB:
+                       break;
+               default:
+                       DRM_ERROR("invalid CMDBUF_LOCATION value=%d\n", setparam.value);
+                       return DRM_ERR(EINVAL);
+               }
+               dev_priv->config.cmdbuf.location = setparam.value;
+               break;
+       case NOUVEAU_SETPARAM_CMDBUF_SIZE:
+               dev_priv->config.cmdbuf.size = setparam.value;
+               break;
        default:
                DRM_ERROR("unknown parameter %d\n", setparam.param);
                return DRM_ERR(EINVAL);
@@ -168,3 +157,51 @@ int nouveau_ioctl_setparam(DRM_IOCTL_ARGS)
        return 0;
 }
 
+int nouveau_dma_init(struct drm_device *dev)
+{
+       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct nouveau_config *config = &dev_priv->config;
+       struct mem_block *cb;
+       int cb_min_size = nouveau_fifo_number(dev) * NV03_FIFO_SIZE;
+
+       /* allocate one buffer for all the fifos */
+       dev_priv->cmdbuf_alloc = nouveau_mem_alloc(dev, 0, 1024*1024, NOUVEAU_MEM_FB, (DRMFILE)-2);
+
+       /* Defaults for unconfigured values */
+       if (!config->cmdbuf.location)
+               config->cmdbuf.location = NOUVEAU_MEM_FB;
+       if (!config->cmdbuf.size || config->cmdbuf.size < cb_min_size)
+               config->cmdbuf.size = cb_min_size;
+
+       cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
+                       config->cmdbuf.location, (DRMFILE)-2);
+       /* Try defaults if that didn't succeed */
+       if (!cb) {
+               config->cmdbuf.location = NOUVEAU_MEM_FB;
+               config->cmdbuf.size = cb_min_size;
+               cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
+                               config->cmdbuf.location, (DRMFILE)-2);
+       }
+       if (!cb) {
+               DRM_ERROR("Couldn't allocate DMA command buffer.\n");
+               return DRM_ERR(ENOMEM);
+       }
+
+       if (config->cmdbuf.location == NOUVEAU_MEM_AGP)
+               dev_priv->cmdbuf_obj = nouveau_dma_object_create(dev,
+                               cb->start, cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP);
+       else
+               dev_priv->cmdbuf_obj = nouveau_dma_object_create(dev,
+                               cb->start - drm_get_resource_start(dev, 1),
+                               cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM);
+       dev_priv->cmdbuf_ch_size = cb->size / nouveau_fifo_number(dev);
+       dev_priv->cmdbuf_alloc = cb;
+
+       DRM_INFO("DMA command buffer is %dKiB at 0x%08x(%s)\n",
+                       (uint32_t)cb->size>>10, (uint32_t)cb->start,
+                       config->cmdbuf.location == NOUVEAU_MEM_FB ? "VRAM" : "AGP");
+       DRM_INFO("FIFO size is %dKiB\n", dev_priv->cmdbuf_ch_size>>10);
+
+       return 0;
+}
+