drm/nouveau/fifo: turn all fifo modules into engine modules
[deliverable/linux.git] / drivers / gpu / drm / nouveau / nvc0_fifo.c
index 471723eaf8ad5ceb3daf59953f944fbf410c8919..7d85553d518c42ee5826c0cf516086cf01ce1534 100644 (file)
 
 #include "nouveau_drv.h"
 #include "nouveau_mm.h"
+#include "nouveau_fifo.h"
 
 static void nvc0_fifo_isr(struct drm_device *);
 
 struct nvc0_fifo_priv {
+       struct nouveau_fifo_priv base;
        struct nouveau_gpuobj *playlist[2];
        int cur_playlist;
        struct nouveau_vma user_vma;
@@ -37,8 +39,8 @@ struct nvc0_fifo_priv {
 };
 
 struct nvc0_fifo_chan {
+       struct nouveau_fifo_chan base;
        struct nouveau_gpuobj *user;
-       struct nouveau_gpuobj *ramfc;
 };
 
 static void
@@ -46,8 +48,7 @@ nvc0_fifo_playlist_update(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
-       struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
-       struct nvc0_fifo_priv *priv = pfifo->priv;
+       struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO);
        struct nouveau_gpuobj *cur;
        int i, p;
 
@@ -69,31 +70,20 @@ nvc0_fifo_playlist_update(struct drm_device *dev)
                NV_ERROR(dev, "PFIFO - playlist update failed\n");
 }
 
-int
-nvc0_fifo_create_context(struct nouveau_channel *chan)
+static int
+nvc0_fifo_context_new(struct nouveau_channel *chan, int engine)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
-       struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
-       struct nvc0_fifo_priv *priv = pfifo->priv;
-       struct nvc0_fifo_chan *fifoch;
+       struct nvc0_fifo_priv *priv = nv_engine(dev, engine);
+       struct nvc0_fifo_chan *fctx;
        u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4;
-       int ret;
+       int ret, i;
 
-       chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL);
-       if (!chan->fifo_priv)
+       fctx = chan->engctx[engine] = kzalloc(sizeof(*fctx), GFP_KERNEL);
+       if (!fctx)
                return -ENOMEM;
-       fifoch = chan->fifo_priv;
-
-       /* allocate vram for control regs, map into polling area */
-       ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000,
-                                NVOBJ_FLAG_ZERO_ALLOC, &fifoch->user);
-       if (ret)
-               goto error;
-
-       nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000,
-                         *(struct nouveau_mem **)fifoch->user->node);
 
        chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) +
                                priv->user_vma.offset + (chan->id * 0x1000),
@@ -103,175 +93,77 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
                goto error;
        }
 
-       /* ramfc */
-       ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst,
-                                     chan->ramin->vinst, 0x100,
-                                     NVOBJ_FLAG_ZERO_ALLOC, &fifoch->ramfc);
+       /* allocate vram for control regs, map into polling area */
+       ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000,
+                                NVOBJ_FLAG_ZERO_ALLOC, &fctx->user);
        if (ret)
                goto error;
 
-       nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(fifoch->user->vinst));
-       nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(fifoch->user->vinst));
-       nv_wo32(fifoch->ramfc, 0x10, 0x0000face);
-       nv_wo32(fifoch->ramfc, 0x30, 0xfffff902);
-       nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt));
-       nv_wo32(fifoch->ramfc, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 |
+       nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000,
+                         *(struct nouveau_mem **)fctx->user->node);
+
+       for (i = 0; i < 0x100; i += 4)
+               nv_wo32(chan->ramin, i, 0x00000000);
+       nv_wo32(chan->ramin, 0x08, lower_32_bits(fctx->user->vinst));
+       nv_wo32(chan->ramin, 0x0c, upper_32_bits(fctx->user->vinst));
+       nv_wo32(chan->ramin, 0x10, 0x0000face);
+       nv_wo32(chan->ramin, 0x30, 0xfffff902);
+       nv_wo32(chan->ramin, 0x48, lower_32_bits(ib_virt));
+       nv_wo32(chan->ramin, 0x4c, drm_order(chan->dma.ib_max + 1) << 16 |
                                   upper_32_bits(ib_virt));
-       nv_wo32(fifoch->ramfc, 0x54, 0x00000002);
-       nv_wo32(fifoch->ramfc, 0x84, 0x20400000);
-       nv_wo32(fifoch->ramfc, 0x94, 0x30000001);
-       nv_wo32(fifoch->ramfc, 0x9c, 0x00000100);
-       nv_wo32(fifoch->ramfc, 0xa4, 0x1f1f1f1f);
-       nv_wo32(fifoch->ramfc, 0xa8, 0x1f1f1f1f);
-       nv_wo32(fifoch->ramfc, 0xac, 0x0000001f);
-       nv_wo32(fifoch->ramfc, 0xb8, 0xf8000000);
-       nv_wo32(fifoch->ramfc, 0xf8, 0x10003080); /* 0x002310 */
-       nv_wo32(fifoch->ramfc, 0xfc, 0x10000010); /* 0x002350 */
+       nv_wo32(chan->ramin, 0x54, 0x00000002);
+       nv_wo32(chan->ramin, 0x84, 0x20400000);
+       nv_wo32(chan->ramin, 0x94, 0x30000001);
+       nv_wo32(chan->ramin, 0x9c, 0x00000100);
+       nv_wo32(chan->ramin, 0xa4, 0x1f1f1f1f);
+       nv_wo32(chan->ramin, 0xa8, 0x1f1f1f1f);
+       nv_wo32(chan->ramin, 0xac, 0x0000001f);
+       nv_wo32(chan->ramin, 0xb8, 0xf8000000);
+       nv_wo32(chan->ramin, 0xf8, 0x10003080); /* 0x002310 */
+       nv_wo32(chan->ramin, 0xfc, 0x10000010); /* 0x002350 */
        pinstmem->flush(dev);
 
        nv_wr32(dev, 0x003000 + (chan->id * 8), 0xc0000000 |
                                                (chan->ramin->vinst >> 12));
        nv_wr32(dev, 0x003004 + (chan->id * 8), 0x001f0001);
        nvc0_fifo_playlist_update(dev);
-       return 0;
 
 error:
-       pfifo->destroy_context(chan);
+       if (ret)
+               priv->base.base.context_del(chan, engine);
        return ret;
 }
 
-void
-nvc0_fifo_destroy_context(struct nouveau_channel *chan)
+static void
+nvc0_fifo_context_del(struct nouveau_channel *chan, int engine)
 {
+       struct nvc0_fifo_chan *fctx = chan->engctx[engine];
        struct drm_device *dev = chan->dev;
-       struct nvc0_fifo_chan *fifoch;
 
        nv_mask(dev, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000);
        nv_wr32(dev, 0x002634, chan->id);
        if (!nv_wait(dev, 0x0002634, 0xffffffff, chan->id))
                NV_WARN(dev, "0x2634 != chid: 0x%08x\n", nv_rd32(dev, 0x2634));
-
        nvc0_fifo_playlist_update(dev);
-
        nv_wr32(dev, 0x003000 + (chan->id * 8), 0x00000000);
 
+       nouveau_gpuobj_ref(NULL, &fctx->user);
        if (chan->user) {
                iounmap(chan->user);
                chan->user = NULL;
        }
 
-       fifoch = chan->fifo_priv;
-       chan->fifo_priv = NULL;
-       if (!fifoch)
-               return;
-
-       nouveau_gpuobj_ref(NULL, &fifoch->ramfc);
-       nouveau_gpuobj_ref(NULL, &fifoch->user);
-       kfree(fifoch);
-}
-
-int
-nvc0_fifo_load_context(struct nouveau_channel *chan)
-{
-       return 0;
-}
-
-int
-nvc0_fifo_unload_context(struct drm_device *dev)
-{
-       int i;
-
-       for (i = 0; i < 128; i++) {
-               if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1))
-                       continue;
-
-               nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000);
-               nv_wr32(dev, 0x002634, i);
-               if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
-                       NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
-                               i, nv_rd32(dev, 0x002634));
-                       return -EBUSY;
-               }
-       }
-
-       return 0;
-}
-
-static void
-nvc0_fifo_destroy(struct drm_device *dev)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
-       struct nvc0_fifo_priv *priv;
-
-       priv = pfifo->priv;
-       if (!priv)
-               return;
-
-       nouveau_vm_put(&priv->user_vma);
-       nouveau_gpuobj_ref(NULL, &priv->playlist[1]);
-       nouveau_gpuobj_ref(NULL, &priv->playlist[0]);
-       kfree(priv);
-}
-
-void
-nvc0_fifo_takedown(struct drm_device *dev)
-{
-       nv_wr32(dev, 0x002140, 0x00000000);
-       nvc0_fifo_destroy(dev);
+       chan->engctx[engine] = NULL;
+       kfree(fctx);
 }
 
 static int
-nvc0_fifo_create(struct drm_device *dev)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
-       struct nvc0_fifo_priv *priv;
-       int ret;
-
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-       pfifo->priv = priv;
-
-       ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0,
-                                &priv->playlist[0]);
-       if (ret)
-               goto error;
-
-       ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000, 0,
-                                &priv->playlist[1]);
-       if (ret)
-               goto error;
-
-       ret = nouveau_vm_get(dev_priv->bar1_vm, pfifo->channels * 0x1000,
-                            12, NV_MEM_ACCESS_RW, &priv->user_vma);
-       if (ret)
-               goto error;
-
-       nouveau_irq_register(dev, 8, nvc0_fifo_isr);
-       return 0;
-
-error:
-       nvc0_fifo_destroy(dev);
-       return ret;
-}
-
-int
-nvc0_fifo_init(struct drm_device *dev)
+nvc0_fifo_init(struct drm_device *dev, int engine)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+       struct nvc0_fifo_priv *priv = nv_engine(dev, engine);
        struct nouveau_channel *chan;
-       struct nvc0_fifo_priv *priv;
-       int ret, i;
-
-       if (!pfifo->priv) {
-               ret = nvc0_fifo_create(dev);
-               if (ret)
-                       return ret;
-       }
-       priv = pfifo->priv;
+       int i;
 
        /* reset PFIFO, enable all available PSUBFIFO areas */
        nv_mask(dev, 0x000200, 0x00000100, 0x00000000);
@@ -309,7 +201,7 @@ nvc0_fifo_init(struct drm_device *dev)
        /* restore PFIFO context table */
        for (i = 0; i < 128; i++) {
                chan = dev_priv->channels.ptr[i];
-               if (!chan || !chan->fifo_priv)
+               if (!chan || !chan->engctx[engine])
                        continue;
 
                nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 |
@@ -321,6 +213,29 @@ nvc0_fifo_init(struct drm_device *dev)
        return 0;
 }
 
+static int
+nvc0_fifo_fini(struct drm_device *dev, int engine, bool suspend)
+{
+       int i;
+
+       for (i = 0; i < 128; i++) {
+               if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1))
+                       continue;
+
+               nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000);
+               nv_wr32(dev, 0x002634, i);
+               if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
+                       NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
+                               i, nv_rd32(dev, 0x002634));
+                       return -EBUSY;
+               }
+       }
+
+       nv_wr32(dev, 0x002140, 0x00000000);
+       return 0;
+}
+
+
 struct nouveau_enum nvc0_fifo_fault_unit[] = {
        { 0x00, "PGRAPH" },
        { 0x03, "PEEPHOLE" },
@@ -410,13 +325,14 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit)
 static int
 nvc0_fifo_page_flip(struct drm_device *dev, u32 chid)
 {
+       struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO);
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_channel *chan = NULL;
        unsigned long flags;
        int ret = -EINVAL;
 
        spin_lock_irqsave(&dev_priv->channels.lock, flags);
-       if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels)) {
+       if (likely(chid >= 0 && chid < priv->base.channels)) {
                chan = dev_priv->channels.ptr[chid];
                if (likely(chan))
                        ret = nouveau_finish_page_flip(chan, NULL);
@@ -505,3 +421,56 @@ nvc0_fifo_isr(struct drm_device *dev)
                nv_wr32(dev, 0x002140, 0);
        }
 }
+
+static void
+nvc0_fifo_destroy(struct drm_device *dev, int engine)
+{
+       struct nvc0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO);
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       nouveau_vm_put(&priv->user_vma);
+       nouveau_gpuobj_ref(NULL, &priv->playlist[1]);
+       nouveau_gpuobj_ref(NULL, &priv->playlist[0]);
+
+       dev_priv->eng[engine] = NULL;
+       kfree(priv);
+}
+
+int
+nvc0_fifo_create(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nvc0_fifo_priv *priv;
+       int ret;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->base.base.destroy = nvc0_fifo_destroy;
+       priv->base.base.init = nvc0_fifo_init;
+       priv->base.base.fini = nvc0_fifo_fini;
+       priv->base.base.context_new = nvc0_fifo_context_new;
+       priv->base.base.context_del = nvc0_fifo_context_del;
+       priv->base.channels = 128;
+       dev_priv->eng[NVOBJ_ENGINE_FIFO] = &priv->base.base;
+
+       ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[0]);
+       if (ret)
+               goto error;
+
+       ret = nouveau_gpuobj_new(dev, NULL, 4096, 4096, 0, &priv->playlist[1]);
+       if (ret)
+               goto error;
+
+       ret = nouveau_vm_get(dev_priv->bar1_vm, priv->base.channels * 0x1000,
+                            12, NV_MEM_ACCESS_RW, &priv->user_vma);
+       if (ret)
+               goto error;
+
+       nouveau_irq_register(dev, 8, nvc0_fifo_isr);
+error:
+       if (ret)
+               priv->base.base.destroy(dev, NVOBJ_ENGINE_FIFO);
+       return ret;
+}
This page took 0.029102 seconds and 5 git commands to generate.