summaryrefslogtreecommitdiff
path: root/shared-core/nv50_fifo.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>2007-09-24 14:41:46 -0700
committerJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>2007-09-24 14:41:46 -0700
commit5cc3083179b19678456905a9122a3d0f04e6f623 (patch)
tree9b776bdd317aa5af68b7cbf8fabde12e20eccf8a /shared-core/nv50_fifo.c
parent2a2d02bbc500140a861380df52ce66abcac39312 (diff)
parent54df1b9ff3b79097fedd8ed7bf54aca30a660cbd (diff)
Merge branch 'master' into modesetting-101 - TTM & typedef removal
Conflicts: linux-core/drmP.h linux-core/drm_bo.c linux-core/drm_drv.c linux-core/drm_objects.h shared-core/drm.h shared-core/i915_dma.c shared-core/i915_drv.h shared-core/i915_irq.c Mostly removing typedefs that snuck into the modesetting code and updating to the latest TTM APIs. As of today, the i915 driver builds, but there are likely to be problems, so debugging and bugfixes will come next.
Diffstat (limited to 'shared-core/nv50_fifo.c')
-rw-r--r--shared-core/nv50_fifo.c268
1 files changed, 256 insertions, 12 deletions
diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c
index e5d37949..7859544a 100644
--- a/shared-core/nv50_fifo.c
+++ b/shared-core/nv50_fifo.c
@@ -28,55 +28,299 @@
#include "drm.h"
#include "nouveau_drv.h"
+typedef struct {
+ struct nouveau_gpuobj_ref *thingo;
+} nv50_fifo_priv;
+
+#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
+
static void
-nv50_fifo_init_reset(drm_device_t *dev)
+nv50_fifo_init_thingo(struct drm_device *dev)
{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
+ struct nouveau_gpuobj_ref *thingo = priv->thingo;
+ int i, fi=2;
+
+ DRM_DEBUG("\n");
+
+ INSTANCE_WR(thingo->gpuobj, 0, 0x7e);
+ INSTANCE_WR(thingo->gpuobj, 1, 0x7e);
+ for (i = 1; i < 127; i++, fi) {
+ if (dev_priv->fifos[i]) {
+ INSTANCE_WR(thingo->gpuobj, fi, i);
+ fi++;
+ }
+ }
+
+ NV_WRITE(0x32f4, thingo->instance >> 12);
+ NV_WRITE(0x32ec, fi);
+ NV_WRITE(0x2500, 0x101);
+}
+
+static int
+nv50_fifo_channel_enable(struct drm_device *dev, int channel, int nt)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_channel *chan = dev_priv->fifos[channel];
+ uint32_t inst;
+
+ DRM_DEBUG("ch%d\n", channel);
+
+ if (!chan->ramfc)
+ return -EINVAL;
+
+ if (IS_G80) inst = chan->ramfc->instance >> 12;
+ else inst = chan->ramfc->instance >> 8;
+ NV_WRITE(NV50_PFIFO_CTX_TABLE(channel),
+ inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
+
+ if (!nt) nv50_fifo_init_thingo(dev);
+ return 0;
+}
+
+static void
+nv50_fifo_channel_disable(struct drm_device *dev, int channel, int nt)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ uint32_t inst;
+
+ DRM_DEBUG("ch%d, nt=%d\n", channel, nt);
+
+ if (IS_G80) inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80;
+ else inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84;
+ NV_WRITE(NV50_PFIFO_CTX_TABLE(channel), inst);
+
+ if (!nt) nv50_fifo_init_thingo(dev);
+}
+
+static void
+nv50_fifo_init_reset(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t pmc_e;
+ DRM_DEBUG("\n");
+
pmc_e = NV_READ(NV03_PMC_ENABLE);
NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PFIFO);
pmc_e = NV_READ(NV03_PMC_ENABLE);
NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PFIFO);
}
+static void
+nv50_fifo_init_intr(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("\n");
+
+ NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
+ NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
+}
+
+static void
+nv50_fifo_init_context_table(struct drm_device *dev)
+{
+ int i;
+
+ DRM_DEBUG("\n");
+
+ for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++)
+ nv50_fifo_channel_disable(dev, i, 1);
+ nv50_fifo_init_thingo(dev);
+}
+
+static void
+nv50_fifo_init_regs__nv(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("\n");
+
+ NV_WRITE(0x250c, 0x6f3cfc34);
+}
+
+static int
+nv50_fifo_init_regs(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+ DRM_DEBUG("\n");
+
+ NV_WRITE(0x2500, 0);
+ NV_WRITE(0x3250, 0);
+ NV_WRITE(0x3220, 0);
+ NV_WRITE(0x3204, 0);
+ NV_WRITE(0x3210, 0);
+ NV_WRITE(0x3270, 0);
+
+ /* Enable dummy channels setup by nv50_instmem.c */
+ nv50_fifo_channel_enable(dev, 0, 1);
+ nv50_fifo_channel_enable(dev, 127, 1);
+
+ return 0;
+}
+
int
-nv50_fifo_init(drm_device_t *dev)
+nv50_fifo_init(struct drm_device *dev)
{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ nv50_fifo_priv *priv;
+ int ret;
+
+ DRM_DEBUG("\n");
+
+ priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER);
+ if (!priv)
+ return -ENOMEM;
+ dev_priv->Engine.fifo.priv = priv;
+
nv50_fifo_init_reset(dev);
+ nv50_fifo_init_intr(dev);
+
+ if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000,
+ NVOBJ_FLAG_ZERO_ALLOC,
+ &priv->thingo))) {
+ DRM_ERROR("error creating thingo: %d\n", ret);
+ return ret;
+ }
+
+ nv50_fifo_init_context_table(dev);
+
+ nv50_fifo_init_regs__nv(dev);
+ if ((ret = nv50_fifo_init_regs(dev)))
+ return ret;
- DRM_ERROR("stub!\n");
return 0;
}
void
-nv50_fifo_takedown(drm_device_t *dev)
+nv50_fifo_takedown(struct drm_device *dev)
{
- DRM_ERROR("stub!\n");
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
+
+ DRM_DEBUG("\n");
+
+ if (!priv)
+ return;
+
+ nouveau_gpuobj_ref_del(dev, &priv->thingo);
+
+ dev_priv->Engine.fifo.priv = NULL;
+ drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
}
int
-nv50_fifo_create_context(drm_device_t *dev, int channel)
+nv50_fifo_create_context(struct nouveau_channel *chan)
{
- DRM_ERROR("stub!\n");
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_gpuobj *ramfc = NULL;
+ int ret;
+
+ DRM_DEBUG("ch%d\n", chan->id);
+
+ if (IS_G80) {
+ uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start;
+ uint32_t vram_offset = chan->ramin->gpuobj->im_backing->start;
+ if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset,
+ vram_offset, 0x100,
+ NVOBJ_FLAG_ZERO_ALLOC |
+ NVOBJ_FLAG_ZERO_FREE,
+ &ramfc, &chan->ramfc)))
+ return ret;
+ } else {
+ if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100,
+ 256,
+ NVOBJ_FLAG_ZERO_ALLOC |
+ NVOBJ_FLAG_ZERO_FREE,
+ &chan->ramfc)))
+ return ret;
+ ramfc = chan->ramfc->gpuobj;
+ }
+
+ INSTANCE_WR(ramfc, 0x48/4, chan->pushbuf->instance >> 4);
+ INSTANCE_WR(ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4));
+ INSTANCE_WR(ramfc, 0x3c/4, 0x000f0078); /* fetch? */
+ INSTANCE_WR(ramfc, 0x44/4, 0x2101ffff);
+ INSTANCE_WR(ramfc, 0x60/4, 0x7fffffff);
+ INSTANCE_WR(ramfc, 0x10/4, 0x00000000);
+ INSTANCE_WR(ramfc, 0x08/4, 0x00000000);
+ INSTANCE_WR(ramfc, 0x40/4, 0x00000000);
+ INSTANCE_WR(ramfc, 0x50/4, 0x2039b2e0);
+ INSTANCE_WR(ramfc, 0x54/4, 0x000f0000);
+ INSTANCE_WR(ramfc, 0x7c/4, 0x30000001);
+ INSTANCE_WR(ramfc, 0x78/4, 0x00000000);
+ INSTANCE_WR(ramfc, 0x4c/4, chan->pushbuf_mem->size - 1);
+
+ if (!IS_G80) {
+ INSTANCE_WR(chan->ramin->gpuobj, 0, chan->id);
+ INSTANCE_WR(chan->ramin->gpuobj, 1, chan->ramfc->instance);
+
+ INSTANCE_WR(ramfc, 0x88/4, 0x3d520); /* some vram addy >> 10 */
+ INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12);
+ }
+
+ if ((ret = nv50_fifo_channel_enable(dev, chan->id, 0))) {
+ DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret);
+ nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+ return ret;
+ }
+
return 0;
}
void
-nv50_fifo_destroy_context(drm_device_t *dev, int channel)
+nv50_fifo_destroy_context(struct nouveau_channel *chan)
{
+ struct drm_device *dev = chan->dev;
+
+ DRM_DEBUG("ch%d\n", chan->id);
+
+ nv50_fifo_channel_disable(dev, chan->id, 0);
+
+ /* Dummy channel, also used on ch 127 */
+ if (chan->id == 0)
+ nv50_fifo_channel_disable(dev, 127, 0);
+
+ nouveau_gpuobj_ref_del(dev, &chan->ramfc);
}
int
-nv50_fifo_load_context(drm_device_t *dev, int channel)
+nv50_fifo_load_context(struct nouveau_channel *chan)
{
- DRM_ERROR("stub!\n");
+ struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj;
+
+ DRM_DEBUG("ch%d\n", chan->id);
+
+ /*XXX: incomplete, only touches the regs that NV does */
+
+ NV_WRITE(0x3244, 0);
+ NV_WRITE(0x3240, 0);
+
+ NV_WRITE(0x3224, INSTANCE_RD(ramfc, 0x3c/4));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, INSTANCE_RD(ramfc, 0x48/4));
+ NV_WRITE(0x3234, INSTANCE_RD(ramfc, 0x4c/4));
+ NV_WRITE(0x3254, 1);
+ NV_WRITE(NV03_PFIFO_RAMHT, INSTANCE_RD(ramfc, 0x80/4));
+
+ if (!IS_G80) {
+ NV_WRITE(0x340c, INSTANCE_RD(ramfc, 0x88/4));
+ NV_WRITE(0x3410, INSTANCE_RD(ramfc, 0x98/4));
+ }
+
+ NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
return 0;
}
int
-nv50_fifo_save_context(drm_device_t *dev, int channel)
+nv50_fifo_save_context(struct nouveau_channel *chan)
{
+ DRM_DEBUG("ch%d\n", chan->id);
DRM_ERROR("stub!\n");
return 0;
}