nouveau: NV04/NV10/NV20 PGRAPH engtab functions

NV04/NV10 load_context()/save_context() are stubs.  I don't know enough about
how they work to implement them sanely.  The "old" context_switch() code
remains hooked up, so it shouldn't break anything.

NV20 will probably break if load_context() works.  No inital context values
are filled in, so when the first channel is created PGRAPH will probably end
up having its state zeroed.  Some setup from nv20_graph_init() will probably
need to be moved to the per-channel context setup.
This commit is contained in:
Ben Skeggs 2007-06-24 19:00:26 +10:00
parent 5d55b0655c
commit 5f05cd7086
6 changed files with 86 additions and 46 deletions

View file

@ -275,21 +275,30 @@ extern int nv40_fifo_save_context(drm_device_t *, int channel);
/* nv04_graph.c */
extern void nouveau_nv04_context_switch(drm_device_t *dev);
extern int nv04_graph_init(drm_device_t *dev);
extern int nv04_graph_init(drm_device_t *dev);
extern void nv04_graph_takedown(drm_device_t *dev);
extern int nv04_graph_context_create(drm_device_t *dev, int channel);
extern int nv04_graph_create_context(drm_device_t *dev, int channel);
extern void nv04_graph_destroy_context(drm_device_t *dev, int channel);
extern int nv04_graph_load_context(drm_device_t *dev, int channel);
extern int nv04_graph_save_context(drm_device_t *dev, int channel);
/* nv10_graph.c */
extern void nouveau_nv10_context_switch(drm_device_t *dev);
extern int nv10_graph_init(drm_device_t *dev);
extern int nv10_graph_init(drm_device_t *dev);
extern void nv10_graph_takedown(drm_device_t *dev);
extern int nv10_graph_context_create(drm_device_t *dev, int channel);
extern int nv10_graph_create_context(drm_device_t *dev, int channel);
extern void nv10_graph_destroy_context(drm_device_t *dev, int channel);
extern int nv10_graph_load_context(drm_device_t *dev, int channel);
extern int nv10_graph_save_context(drm_device_t *dev, int channel);
/* nv20_graph.c */
extern void nouveau_nv20_context_switch(drm_device_t *dev);
extern int nv20_graph_init(drm_device_t *dev);
extern int nv20_graph_init(drm_device_t *dev);
extern void nv20_graph_takedown(drm_device_t *dev);
extern int nv20_graph_context_create(drm_device_t *dev, int channel);
extern int nv20_graph_create_context(drm_device_t *dev, int channel);
extern void nv20_graph_destroy_context(drm_device_t *dev, int channel);
extern int nv20_graph_load_context(drm_device_t *dev, int channel);
extern int nv20_graph_save_context(drm_device_t *dev, int channel);
/* nv30_graph.c */
extern int nv30_graph_init(drm_device_t *dev);

View file

@ -289,34 +289,10 @@ static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
/* Create a graphics context for new channel */
switch(dev_priv->card_type)
{
case NV_04:
case NV_05:
nv04_graph_context_create(dev, channel);
break;
case NV_10:
case NV_17:
nv10_graph_context_create(dev, channel);
break;
case NV_20:
ret = nv20_graph_context_create(dev, channel);
if (ret) {
nouveau_fifo_free(dev, channel);
return ret;
}
break;
default:
if (!engine->graph.create_context) {
DRM_ERROR("graph.create_context == NULL\n");
return DRM_ERR(EINVAL);
}
ret = engine->graph.create_context(dev, channel);
if (ret) {
nouveau_fifo_free(dev, channel);
return ret;
}
break;
ret = engine->graph.create_context(dev, channel);
if (ret) {
nouveau_fifo_free(dev, channel);
return ret;
}
/* Construct inital RAMFC for new channel */

View file

@ -88,6 +88,10 @@ static int nouveau_init_engine_ptrs(drm_device_t *dev)
engine->fb.takedown = nv04_fb_takedown;
engine->graph.init = nv04_graph_init;
engine->graph.takedown = nv04_graph_takedown;
engine->graph.create_context = nv04_graph_create_context;
engine->graph.destroy_context = nv04_graph_destroy_context;
engine->graph.load_context = nv04_graph_load_context;
engine->graph.save_context = nv04_graph_save_context;
engine->fifo.init = nouveau_fifo_init;
engine->fifo.takedown = nouveau_stub_takedown;
engine->fifo.create_context = nv04_fifo_create_context;
@ -104,6 +108,10 @@ static int nouveau_init_engine_ptrs(drm_device_t *dev)
engine->fb.takedown = nv10_fb_takedown;
engine->graph.init = nv10_graph_init;
engine->graph.takedown = nv10_graph_takedown;
engine->graph.create_context = nv10_graph_create_context;
engine->graph.destroy_context = nv10_graph_destroy_context;
engine->graph.load_context = nv10_graph_load_context;
engine->graph.save_context = nv10_graph_save_context;
engine->fifo.init = nouveau_fifo_init;
engine->fifo.takedown = nouveau_stub_takedown;
if (dev_priv->chipset < 0x17) {
@ -127,6 +135,10 @@ static int nouveau_init_engine_ptrs(drm_device_t *dev)
engine->fb.takedown = nv10_fb_takedown;
engine->graph.init = nv20_graph_init;
engine->graph.takedown = nv20_graph_takedown;
engine->graph.create_context = nv20_graph_create_context;
engine->graph.destroy_context = nv20_graph_destroy_context;
engine->graph.load_context = nv20_graph_load_context;
engine->graph.save_context = nv20_graph_save_context;
engine->fifo.init = nouveau_fifo_init;
engine->fifo.takedown = nouveau_stub_takedown;
engine->fifo.create_context = nv10_fifo_create_context;

View file

@ -336,7 +336,7 @@ void nouveau_nv04_context_switch(drm_device_t *dev)
NV_WRITE(NV04_PGRAPH_FIFO,0x1);
}
int nv04_graph_context_create(drm_device_t *dev, int channel) {
int nv04_graph_create_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("nv04_graph_context_create %d\n", channel);
@ -351,6 +351,21 @@ int nv04_graph_context_create(drm_device_t *dev, int channel) {
return 0;
}
void nv04_graph_destroy_context(drm_device_t *dev, int channel)
{
}
int nv04_graph_load_context(drm_device_t *dev, int channel)
{
DRM_ERROR("stub!\n");
return 0;
}
int nv04_graph_save_context(drm_device_t *dev, int channel)
{
DRM_ERROR("stub!\n");
return 0;
}
int nv04_graph_init(drm_device_t *dev) {
drm_nouveau_private_t *dev_priv = dev->dev_private;

View file

@ -611,7 +611,7 @@ void nouveau_nv10_context_switch(drm_device_t *dev)
if (offset > 0) \
fifo->pgraph_ctx[offset] = val; \
} while (0)
int nv10_graph_context_create(drm_device_t *dev, int channel) {
int nv10_graph_create_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv = dev->dev_private;
struct nouveau_fifo *fifo = &dev_priv->fifos[channel];
uint32_t tmp, vramsz;
@ -663,6 +663,21 @@ int nv10_graph_context_create(drm_device_t *dev, int channel) {
return 0;
}
void nv10_graph_destroy_context(drm_device_t *dev, int channel)
{
}
int nv10_graph_load_context(drm_device_t *dev, int channel)
{
DRM_ERROR("stub!\n");
return 0;
}
int nv10_graph_save_context(drm_device_t *dev, int channel)
{
DRM_ERROR("stub!\n");
return 0;
}
int nv10_graph_init(drm_device_t *dev) {
drm_nouveau_private_t *dev_priv = dev->dev_private;

View file

@ -29,7 +29,7 @@
#define NV20_GRCTX_SIZE (3529*4)
int nv20_graph_context_create(drm_device_t *dev, int channel) {
int nv20_graph_create_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
struct nouveau_fifo *chan = &dev_priv->fifos[channel];
@ -47,10 +47,21 @@ int nv20_graph_context_create(drm_device_t *dev, int channel) {
INSTANCE_WR(chan->ramin_grctx, 10, channel << 24); /* CTX_USER */
INSTANCE_WR(dev_priv->ctx_table, channel, nouveau_chip_instance_get(dev, chan->ramin_grctx));
return 0;
}
void nv20_graph_destroy_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv = dev->dev_private;
struct nouveau_fifo *chan = &dev_priv->fifos[channel];
if (chan->ramin_grctx) {
nouveau_instmem_free(dev, chan->ramin_grctx);
chan->ramin_grctx = NULL;
}
INSTANCE_WR(dev_priv->ctx_table, channel, 0);
}
static void nv20_graph_rdi(drm_device_t *dev) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
@ -65,40 +76,42 @@ static void nv20_graph_rdi(drm_device_t *dev) {
/* Save current context (from PGRAPH) into the channel's context
*/
static void nv20_graph_context_save_current(drm_device_t *dev, int channel) {
int nv20_graph_save_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
uint32_t instance;
instance = INSTANCE_RD(dev_priv->ctx_table, channel);
if (!instance) {
return;
return DRM_ERR(EINVAL);
}
if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx))
DRM_ERROR("nv20_graph_context_save_current : bad instance\n");
DRM_ERROR("nv20_graph_save_context : bad instance\n");
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance);
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 2 /* save ctx */);
return 0;
}
/* Restore the context for a specific channel into PGRAPH
*/
static void nv20_graph_context_restore(drm_device_t *dev, int channel) {
int nv20_graph_load_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
uint32_t instance;
instance = INSTANCE_RD(dev_priv->ctx_table, channel);
if (!instance) {
return;
return DRM_ERR(EINVAL);
}
if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx))
DRM_ERROR("nv20_graph_context_restore_current : bad instance\n");
DRM_ERROR("nv20_graph_load_context_current : bad instance\n");
NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24);
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance);
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */);
return 0;
}
void nouveau_nv20_context_switch(drm_device_t *dev)
@ -113,13 +126,13 @@ void nouveau_nv20_context_switch(drm_device_t *dev)
NV_WRITE(NV04_PGRAPH_FIFO,0x0);
nv20_graph_context_save_current(dev, channel_old);
nv20_graph_save_context(dev, channel_old);
nouveau_wait_for_idle(dev);
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000);
nv20_graph_context_restore(dev, channel);
nv20_graph_load_context(dev, channel);
nouveau_wait_for_idle(dev);