diff options
author | Ben Skeggs <darktama@iinet.net.au> | 2007-01-02 14:41:34 +1100 |
---|---|---|
committer | Ben Skeggs <darktama@iinet.net.au> | 2007-01-02 14:41:34 +1100 |
commit | 2c3bc69ba2b60e4f89b93332fa8da758170b2285 (patch) | |
tree | 99ed2115dd00778b154e27c7ca46869fe9b88880 | |
parent | 2dcbf6a59918761cffb27e027b1235c551ed03dd (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.c | 76 |
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); |