Allow cmdbuf location(AGP,VRAM) and size to be configured.
parent
97291a6ad0
commit
b119966ae6
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue