summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <darktama@iinet.net.au>2007-01-02 14:41:34 +1100
committerBen Skeggs <darktama@iinet.net.au>2007-01-02 14:41:34 +1100
commit2c3bc69ba2b60e4f89b93332fa8da758170b2285 (patch)
tree99ed2115dd00778b154e27c7ca46869fe9b88880
parent2dcbf6a59918761cffb27e027b1235c551ed03dd (diff)
nouveau: Only clobber PFIFO if no channels are already alloc'd
With this change the GPU is responsible for doing the channel switch itself. This is needed for the upcoming NV4x PGRAPH context work as we don't yet know enough to manually swap PGRAPH contexts.
-rw-r--r--shared-core/nouveau_fifo.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 1014d8a6..9cc579f9 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -414,6 +414,43 @@ static void nouveau_nv40_context_save(drm_device_t *dev)
}
#undef RAMFC_WR
+/* This function should load values from RAMFC into PFIFO, but for now
+ * it just clobbers PFIFO with what nouveau_fifo_alloc used to setup
+ * unconditionally.
+ */
+static void
+nouveau_fifo_context_restore(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ uint32_t cb_inst;
+
+ cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
+
+ // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF);
+
+ if (dev_priv->card_type >= NV_40)
+ NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00010000|channel);
+ else
+ NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00000100|channel);
+
+ NV_WRITE(NV_PFIFO_CACH1_DMAP, 0 /*RAMFC_DMA_PUT*/);
+ NV_WRITE(NV_PFIFO_CACH1_DMAG, 0 /*RAMFC_DMA_GET*/);
+ NV_WRITE(NV_PFIFO_CACH1_DMAI, cb_inst);
+ NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF);
+ NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF);
+
+ NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001);
+ NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000);
+ NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000000);
+ NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000);
+#ifdef __BIG_ENDIAN
+ NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN);
+#else
+ NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4);
+#endif
+}
+
/* allocates and initializes a fifo for user space consumption */
static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init, DRMFILE filp)
{
@@ -460,52 +497,29 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,
NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000000);
NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000);
- /* Save current channel's state to it's RAMFC entry.
- *
- * Then, construct inital RAMFC for new channel, I'm not entirely
- * sure this is needed if we activate the channel immediately.
- * My understanding is that the GPU will fill RAMFC itself when
- * it switches away from the channel
- */
+ /* Construct inital RAMFC for new channel */
if (dev_priv->card_type < NV_10) {
nouveau_context_init(dev, init);
} else if (dev_priv->card_type < NV_40) {
- nouveau_nv10_context_save(dev);
nouveau_nv10_context_init(dev, init);
} else {
- nouveau_nv40_context_save(dev);
nouveau_nv40_context_init(dev, init);
}
/* enable the fifo dma operation */
NV_WRITE(NV_PFIFO_MODE,NV_READ(NV_PFIFO_MODE)|(1<<init->channel));
+ /* setup channel's default get/put values */
NV_WRITE(NV03_FIFO_REGS_DMAPUT(init->channel), init->put_base);
NV_WRITE(NV03_FIFO_REGS_DMAGET(init->channel), init->put_base);
- // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF);
-
- if (dev_priv->card_type >= NV_40)
- NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00010000|dev_priv->cur_fifo);
- else
- NV_WRITE(NV_PFIFO_CACH1_PSH1, 0x00000100|dev_priv->cur_fifo);
-
- NV_WRITE(NV_PFIFO_CACH1_DMAP, init->put_base);
- NV_WRITE(NV_PFIFO_CACH1_DMAG, init->put_base);
- NV_WRITE(NV_PFIFO_CACH1_DMAI,
- nouveau_chip_instance_get(dev, cb_obj->instance));
- NV_WRITE(NV_PFIFO_SIZE , 0x0000FFFF);
- NV_WRITE(NV_PFIFO_CACH1_HASH, 0x0000FFFF);
+ /* If this is the first channel, setup PFIFO ourselves. For any
+ * other case, the GPU will handle this when it switches contexts.
+ */
+ if (dev_priv->fifo_alloc_count == 0) {
+ nouveau_fifo_context_restore(dev, init->channel);
+ }
- NV_WRITE(NV_PFIFO_CACH0_PUL1, 0x00000001);
- NV_WRITE(NV_PFIFO_CACH1_DMAC, 0x00000000);
- NV_WRITE(NV_PFIFO_CACH1_DMAS, 0x00000000);
- NV_WRITE(NV_PFIFO_CACH1_ENG, 0x00000000);
-#ifdef __BIG_ENDIAN
- NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4|NV_PFIFO_CACH1_BIG_ENDIAN);
-#else
- NV_WRITE(NV_PFIFO_CACH1_DMAF, NV_PFIFO_CACH1_DMAF_TRIG_112_BYTES|NV_PFIFO_CACH1_DMAF_SIZE_128_BYTES|NV_PFIFO_CACH1_DMAF_MAX_REQS_4);
-#endif
NV_WRITE(NV_PFIFO_CACH1_DMAPSH, 0x00000001);
NV_WRITE(NV_PFIFO_CACH1_PSH0, 0x00000001);
NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001);