#include "drmP.h"
#include "drm.h"
#include "nouveau_drv.h"
#include "nouveau_drm.h"
/*
* NV20
* -----
* There are 3 families :
* NV20 is 0x10de:0x020*
* NV25/28 is 0x10de:0x025* / 0x10de:0x028*
* NV2A is 0x10de:0x02A0
*
* NV30
* -----
* There are 3 families :
* NV30/31 is 0x10de:0x030* / 0x10de:0x031*
* NV34 is 0x10de:0x032*
* NV35/36 is 0x10de:0x033* / 0x10de:0x034*
*
* Not seen in the wild, no dumps (probably NV35) :
* NV37 is 0x10de:0x00fc, 0x10de:0x00fd
* NV38 is 0x10de:0x0333, 0x10de:0x00fe
*
*/
struct nv20_graph_engine {
struct nouveau_exec_engine base;
struct nouveau_gpuobj *ctxtab;
void (*grctx_init)(struct nouveau_gpuobj *);
u32 grctx_size;
u32 grctx_user;
};
#define NV20_GRCTX_SIZE (3580*4)
#define NV25_GRCTX_SIZE (3529*4)
#define NV2A_GRCTX_SIZE (3500*4)
#define NV30_31_GRCTX_SIZE (24392)
#define NV34_GRCTX_SIZE (18140)
#define NV35_36_GRCTX_SIZE (22396)
int
nv20_graph_unload_context(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
struct nouveau_channel *chan;
struct nouveau_gpuobj *grctx;
u32 tmp;
chan = nv10_graph_channel(dev);
if (!chan)
return 0;
grctx = chan->engctx[NVOBJ_ENGINE_GR];
nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->pinst >> 4);
nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER,
NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE);
nouveau_wait_for_idle(dev);
nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
tmp |= (pfifo->channels - 1) << 24;
nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
return 0;
}
static void
nv20_graph_rdi(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
int i, writecount = 32;
uint32_t rdi_index = 0x2c80000;
if (dev_priv->chipset == 0x20) {
rdi_index = 0x3d0000;
writecount = 15;
}
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index);
for (i = 0; i < writecount; i++)
nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0);
nouveau_wait_for_idle(dev);
}
static void
nv20_graph_context_init(struct nouveau_gpuobj *ctx)
{
int i;
nv_wo32(ctx, 0x033c, 0xffff0000);
nv_wo32(ctx, 0x03a0, 0x0fff0000);
nv_wo32(ctx, 0x03a4, 0x0fff0000);
nv_wo32(ctx, 0x047c, 0x00000101);
nv_wo32(ctx, 0x0490, 0x00000111);
nv_wo32(ctx, 0x04a8, 0x44400000);
for (i = 0x04d4; i <= 0x04e0; i += 4)
nv_wo32(ctx, i, 0x00030303);
for (i = 0x04f4; i <= 0x0500; i += 4)
nv_wo32(ctx, i, 0x00080000);
for (i = 0x050c; i <= 0x0518; i += 4)
nv_wo32(ctx, i, 0x01012000);
for (i = 0x051c; i <= 0x0528; i += 4)
nv_wo32(ctx, i, 0x000105b8);
for (i = 0x052c; i <= 0x0538; i += 4)
nv_wo32(ctx, i, 0x00080008);
for (i = 0x055c; i <= 0x0598; i += 4)
nv_wo32(ctx, i, 0x07ff0000);
nv_wo32(ctx, 0x05a4, 0x4b7fffff);
nv_wo32(ctx, 0x05fc, 0x00000001);
nv_wo32(ctx, 0x0604, 0x00004000);
nv_wo32(ctx, 0x0610, 0x00000001);
nv_wo32(ctx, 0x0618, 0x00040000);
nv_wo32(ctx, 0x061c, 0x00010000);
for (i = 0x1c1c; i <= 0x248c; i += 16) {
nv_wo32(ctx, (i + 0), 0x10700ff9);
nv_wo32(ctx, (i + 4), 0x0436086c);
nv_wo32(ctx, (i + 8), 0x000c001b);
}
nv_wo32(ctx, 0x281c, 0x3f800000);
nv_wo32(ctx, 0x2830, 0x3f800000);
nv_wo32(ctx, 0x285c, 0x40000000);
nv_wo32(ctx, 0x2860, 0x3f800000);
nv_wo32(ctx, 0x2864, 0x3f000000);
nv_wo32(ctx, 0x286c, 0x40000000);
nv_wo32(ctx, 0x2870, 0x3f800000);
nv_wo32(ctx, 0x2878, 0xbf800000);
nv_wo32(ctx, 0x2880, 0xbf800000);
nv_wo32(ctx, 0x34a4, 0x000fe000);
nv_wo32(ctx, 0x3530, 0x000003f8);
nv_wo32(ctx, 0x3540, 0x002fe000);
for (i = 0x355c; i <= 0x3578; i += 4)
nv_wo32(ctx, i, 0x001c527c);
}
static void
nv25_graph_context_init(struct nouveau_gpuobj *ctx)
{
int i;
nv_wo32(ctx, 0x035c, 0xffff0000);
nv_wo32(ctx, 0x03c0, 0x0fff0000);
nv_wo32(ctx, 0x03c4, 0x0fff0000);
nv_wo32(ctx, 0x049c, 0x00000101);
nv_wo32(ctx, 0x04b0, 0x00000111);
nv_wo32(ctx, 0x04c8, 0x00000080);