Allow cmdbuf location(AGP,VRAM) and size to be configured.

main
Ben Skeggs 2006-09-03 06:36:06 +10:00
parent 97291a6ad0
commit b119966ae6
4 changed files with 88 additions and 32 deletions

View 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;

View 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);

View 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);
}

View 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;
}