Skip to content

Commit

Permalink
drm/nv50: Implement ctxprog/state generation.
Browse files Browse the repository at this point in the history
This removes dependence on external firmware for NV50 generation cards.
If the generated ctxprogs don't work for you for some reason, please
report it.

Signed-off-by: Marcin Kościelnicki <koriakin@0x04.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Marcin Kościelnicki authored and Ben Skeggs committed Feb 25, 2010
1 parent be079e9 commit d5f3c90
Show file tree
Hide file tree
Showing 4 changed files with 2,411 additions and 33 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
nv04_graph.o nv10_graph.o nv20_graph.o \
nv40_graph.o nv50_graph.o \
nv40_grctx.o \
nv40_grctx.o nv50_grctx.o \
nv04_instmem.o nv50_instmem.o \
nv50_crtc.o nv50_dac.o nv50_sor.o \
nv50_cursor.o nv50_display.o nv50_fbcon.o \
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ extern void nv50_graph_destroy_context(struct nouveau_channel *);
extern int nv50_graph_load_context(struct nouveau_channel *);
extern int nv50_graph_unload_context(struct drm_device *);
extern void nv50_graph_context_switch(struct drm_device *);
extern int nv50_grctx_init(struct nouveau_grctx *);

/* nouveau_grctx.c */
extern int nouveau_grctx_prog_load(struct drm_device *);
Expand Down
74 changes: 42 additions & 32 deletions drivers/gpu/drm/nouveau/nv50_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,7 @@
#include "drm.h"
#include "nouveau_drv.h"

MODULE_FIRMWARE("nouveau/nv50.ctxprog");
MODULE_FIRMWARE("nouveau/nv50.ctxvals");
MODULE_FIRMWARE("nouveau/nv84.ctxprog");
MODULE_FIRMWARE("nouveau/nv84.ctxvals");
MODULE_FIRMWARE("nouveau/nv86.ctxprog");
MODULE_FIRMWARE("nouveau/nv86.ctxvals");
MODULE_FIRMWARE("nouveau/nv92.ctxprog");
MODULE_FIRMWARE("nouveau/nv92.ctxvals");
MODULE_FIRMWARE("nouveau/nv94.ctxprog");
MODULE_FIRMWARE("nouveau/nv94.ctxvals");
MODULE_FIRMWARE("nouveau/nv96.ctxprog");
MODULE_FIRMWARE("nouveau/nv96.ctxvals");
MODULE_FIRMWARE("nouveau/nv98.ctxprog");
MODULE_FIRMWARE("nouveau/nv98.ctxvals");
MODULE_FIRMWARE("nouveau/nva0.ctxprog");
MODULE_FIRMWARE("nouveau/nva0.ctxvals");
MODULE_FIRMWARE("nouveau/nva5.ctxprog");
MODULE_FIRMWARE("nouveau/nva5.ctxvals");
MODULE_FIRMWARE("nouveau/nva8.ctxprog");
MODULE_FIRMWARE("nouveau/nva8.ctxvals");
MODULE_FIRMWARE("nouveau/nvaa.ctxprog");
MODULE_FIRMWARE("nouveau/nvaa.ctxvals");
MODULE_FIRMWARE("nouveau/nvac.ctxprog");
MODULE_FIRMWARE("nouveau/nvac.ctxvals");
#include "nouveau_grctx.h"

#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)

Expand Down Expand Up @@ -111,9 +88,34 @@ nv50_graph_init_ctxctl(struct drm_device *dev)

NV_DEBUG(dev, "\n");

nouveau_grctx_prog_load(dev);
if (!dev_priv->engine.graph.ctxprog)
dev_priv->engine.graph.accel_blocked = true;
if (nouveau_ctxfw) {
nouveau_grctx_prog_load(dev);
dev_priv->engine.graph.grctx_size = 0x70000;
}
if (!dev_priv->engine.graph.ctxprog) {
struct nouveau_grctx ctx = {};
uint32_t *cp = kmalloc(512 * 4, GFP_KERNEL);
int i;
if (!cp) {
NV_ERROR(dev, "Couldn't alloc ctxprog! Disabling acceleration.\n");
dev_priv->engine.graph.accel_blocked = true;
return 0;
}
ctx.dev = dev;
ctx.mode = NOUVEAU_GRCTX_PROG;
ctx.data = cp;
ctx.ctxprog_max = 512;
if (!nv50_grctx_init(&ctx)) {
dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;

nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
for (i = 0; i < ctx.ctxprog_len; i++)
nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
} else {
dev_priv->engine.graph.accel_blocked = true;
}
kfree(cp);
}

nv_wr32(dev, 0x400320, 4);
nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
Expand Down Expand Up @@ -193,13 +195,13 @@ nv50_graph_create_context(struct nouveau_channel *chan)
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
struct nouveau_gpuobj *ctx;
uint32_t grctx_size = 0x70000;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
int hdr, ret;

NV_DEBUG(dev, "ch%d\n", chan->id);

ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000,
NVOBJ_FLAG_ZERO_ALLOC |
ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size,
0x1000, NVOBJ_FLAG_ZERO_ALLOC |
NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
if (ret)
return ret;
Expand All @@ -209,15 +211,23 @@ nv50_graph_create_context(struct nouveau_channel *chan)
dev_priv->engine.instmem.prepare_access(dev, true);
nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002);
nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
grctx_size - 1);
pgraph->grctx_size - 1);
nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance);
nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0);
nv_wo32(dev, ramin, (hdr + 0x10)/4, 0);
nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000);
dev_priv->engine.instmem.finish_access(dev);

dev_priv->engine.instmem.prepare_access(dev, true);
nouveau_grctx_vals_load(dev, ctx);
if (!pgraph->ctxprog) {
struct nouveau_grctx ctx = {};
ctx.dev = chan->dev;
ctx.mode = NOUVEAU_GRCTX_VALS;
ctx.data = chan->ramin_grctx->gpuobj;
nv50_grctx_init(&ctx);
} else {
nouveau_grctx_vals_load(dev, ctx);
}
nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12);
if ((dev_priv->chipset & 0xf0) == 0xa0)
nv_wo32(dev, ctx, 0x00004/4, 0x00000000);
Expand Down
Loading

0 comments on commit d5f3c90

Please sign in to comment.