drm/nouveau: port all engines to new engine module format
[deliverable/linux.git] / drivers / gpu / drm / nouveau / core / engine / copy / nvc0.c
index f39de5a593d6d589b82d4b2e9c2ba67107413d85..ecc8faac3a2a02923e86fe2084d521cf5ccecabe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Red Hat Inc.
+ * Copyright 2012 Red Hat Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * Authors: Ben Skeggs
  */
 
-#include <linux/firmware.h>
-#include "drmP.h"
-#include "nouveau_drv.h"
-#include "nouveau_util.h"
-#include <core/ramht.h>
+#include <core/os.h>
+#include <core/enum.h>
+#include <core/class.h>
+#include <core/engctx.h>
+
+#include <engine/copy.h>
+
 #include "fuc/nvc0.fuc.h"
 
-struct nvc0_copy_engine {
-       struct nouveau_exec_engine base;
-       u32 irq;
-       u32 pmc;
-       u32 fuc;
-       u32 ctx;
+struct nvc0_copy_priv {
+       struct nouveau_copy base;
 };
 
 struct nvc0_copy_chan {
-       struct nouveau_gpuobj *mem;
-       struct nouveau_vma vma;
+       struct nouveau_copy_chan base;
 };
 
-static int
-nvc0_copy_context_new(struct nouveau_channel *chan, int engine)
-{
-       struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine);
-       struct nvc0_copy_chan *cctx;
-       struct drm_device *dev = chan->dev;
-       struct nouveau_gpuobj *ramin = chan->ramin;
-       int ret;
-
-       cctx = chan->engctx[engine] = kzalloc(sizeof(*cctx), GFP_KERNEL);
-       if (!cctx)
-               return -ENOMEM;
+/*******************************************************************************
+ * Copy object classes
+ ******************************************************************************/
 
-       ret = nouveau_gpuobj_new(dev, NULL, 256, 256,
-                                NVOBJ_FLAG_ZERO_ALLOC, &cctx->mem);
-       if (ret)
-               return ret;
+static struct nouveau_oclass
+nvc0_copy0_sclass[] = {
+       { 0x90b5, &nouveau_object_ofuncs },
+       {},
+};
 
-       ret = nouveau_gpuobj_map_vm(cctx->mem, chan->vm, NV_MEM_ACCESS_RW,
-                                  &cctx->vma);
-       if (ret)
-               return ret;
+static struct nouveau_oclass
+nvc0_copy1_sclass[] = {
+       { 0x90b8, &nouveau_object_ofuncs },
+       {},
+};
 
-       nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(cctx->vma.offset));
-       nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(cctx->vma.offset));
-       nvimem_flush(dev);
-       return 0;
-}
+/*******************************************************************************
+ * PCOPY context
+ ******************************************************************************/
 
 static int
-nvc0_copy_object_new(struct nouveau_channel *chan, int engine,
-                    u32 handle, u16 class)
-{
-       return 0;
-}
-
-static void
-nvc0_copy_context_del(struct nouveau_channel *chan, int engine)
+nvc0_copy_context_ctor(struct nouveau_object *parent,
+                      struct nouveau_object *engine,
+                      struct nouveau_oclass *oclass, void *data, u32 size,
+                      struct nouveau_object **pobject)
 {
-       struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine);
-       struct nvc0_copy_chan *cctx = chan->engctx[engine];
-       struct drm_device *dev = chan->dev;
-       u32 inst;
-
-       inst  = (chan->ramin->addr >> 12);
-       inst |= 0x40000000;
-
-       /* disable fifo access */
-       nv_wr32(dev, pcopy->fuc + 0x048, 0x00000000);
-       /* mark channel as unloaded if it's currently active */
-       if (nv_rd32(dev, pcopy->fuc + 0x050) == inst)
-               nv_mask(dev, pcopy->fuc + 0x050, 0x40000000, 0x00000000);
-       /* mark next channel as invalid if it's about to be loaded */
-       if (nv_rd32(dev, pcopy->fuc + 0x054) == inst)
-               nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000);
-       /* restore fifo access */
-       nv_wr32(dev, pcopy->fuc + 0x048, 0x00000003);
-
-       nv_wo32(chan->ramin, pcopy->ctx + 0, 0x00000000);
-       nv_wo32(chan->ramin, pcopy->ctx + 4, 0x00000000);
-
-       nouveau_gpuobj_unmap(&cctx->vma);
-       nouveau_gpuobj_ref(NULL, &cctx->mem);
-
-       kfree(cctx);
-       chan->engctx[engine] = NULL;
-}
-
-static int
-nvc0_copy_init(struct drm_device *dev, int engine)
-{
-       struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
-       int i;
-
-       nv_mask(dev, 0x000200, pcopy->pmc, 0x00000000);
-       nv_mask(dev, 0x000200, pcopy->pmc, pcopy->pmc);
-       nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff);
-
-       nv_wr32(dev, pcopy->fuc + 0x1c0, 0x01000000);
-       for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++)
-               nv_wr32(dev, pcopy->fuc + 0x1c4, nvc0_pcopy_data[i]);
+       struct nvc0_copy_chan *priv;
+       int ret;
 
-       nv_wr32(dev, pcopy->fuc + 0x180, 0x01000000);
-       for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) {
-               if ((i & 0x3f) == 0)
-                       nv_wr32(dev, pcopy->fuc + 0x188, i >> 6);
-               nv_wr32(dev, pcopy->fuc + 0x184, nvc0_pcopy_code[i]);
-       }
+       ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256,
+                                         256, NVOBJ_FLAG_ZERO_ALLOC, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
 
-       nv_wr32(dev, pcopy->fuc + 0x084, engine - NVOBJ_ENGINE_COPY0);
-       nv_wr32(dev, pcopy->fuc + 0x10c, 0x00000000);
-       nv_wr32(dev, pcopy->fuc + 0x104, 0x00000000); /* ENTRY */
-       nv_wr32(dev, pcopy->fuc + 0x100, 0x00000002); /* TRIGGER */
        return 0;
 }
 
-static int
-nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend)
-{
-       struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
+static struct nouveau_ofuncs
+nvc0_copy_context_ofuncs = {
+       .ctor = nvc0_copy_context_ctor,
+       .dtor = _nouveau_copy_context_dtor,
+       .init = _nouveau_copy_context_init,
+       .fini = _nouveau_copy_context_fini,
+       .rd32 = _nouveau_copy_context_rd32,
+       .wr32 = _nouveau_copy_context_wr32,
+};
 
-       nv_mask(dev, pcopy->fuc + 0x048, 0x00000003, 0x00000000);
+static struct nouveau_oclass
+nvc0_copy0_cclass = {
+       .handle = NV_ENGCTX(COPY0, 0xc0),
+       .ofuncs = &nvc0_copy_context_ofuncs,
+};
 
-       /* trigger fuc context unload */
-       nv_wait(dev, pcopy->fuc + 0x008, 0x0000000c, 0x00000000);
-       nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000);
-       nv_wr32(dev, pcopy->fuc + 0x000, 0x00000008);
-       nv_wait(dev, pcopy->fuc + 0x008, 0x00000008, 0x00000000);
+static struct nouveau_oclass
+nvc0_copy1_cclass = {
+       .handle = NV_ENGCTX(COPY1, 0xc0),
+       .ofuncs = &nvc0_copy_context_ofuncs,
+};
 
-       nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff);
-       return 0;
-}
+/*******************************************************************************
+ * PCOPY engine/subdev functions
+ ******************************************************************************/
 
 static struct nouveau_enum nvc0_copy_isr_error_name[] = {
        { 0x0001, "ILLEGAL_MTHD" },
@@ -163,93 +111,145 @@ static struct nouveau_enum nvc0_copy_isr_error_name[] = {
 };
 
 static void
-nvc0_copy_isr(struct drm_device *dev, int engine)
+nvc0_copy_intr(struct nouveau_subdev *subdev)
 {
-       struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
-       u32 disp = nv_rd32(dev, pcopy->fuc + 0x01c);
-       u32 stat = nv_rd32(dev, pcopy->fuc + 0x008) & disp & ~(disp >> 16);
-       u64 inst = (u64)(nv_rd32(dev, pcopy->fuc + 0x050) & 0x0fffffff) << 12;
-       u32 chid = nvc0_graph_isr_chid(dev, inst);
-       u32 ssta = nv_rd32(dev, pcopy->fuc + 0x040) & 0x0000ffff;
-       u32 addr = nv_rd32(dev, pcopy->fuc + 0x040) >> 16;
+       int idx = nv_engidx(nv_object(subdev)) - NVDEV_ENGINE_COPY0;
+       struct nvc0_copy_priv *priv = (void *)subdev;
+       u32 disp = nv_rd32(priv, 0x10401c + (idx * 0x1000));
+       u32 intr = nv_rd32(priv, 0x104008 + (idx * 0x1000));
+       u32 stat = intr & disp & ~(disp >> 16);
+       u64 inst = nv_rd32(priv, 0x104050 + (idx * 0x1000)) & 0x0fffffff;
+       u32 ssta = nv_rd32(priv, 0x104040 + (idx * 0x1000)) & 0x0000ffff;
+       u32 addr = nv_rd32(priv, 0x104040 + (idx * 0x1000)) >> 16;
        u32 mthd = (addr & 0x07ff) << 2;
        u32 subc = (addr & 0x3800) >> 11;
-       u32 data = nv_rd32(dev, pcopy->fuc + 0x044);
+       u32 data = nv_rd32(priv, 0x104044 + (idx * 0x1000));
 
        if (stat & 0x00000040) {
-               NV_INFO(dev, "PCOPY: DISPATCH_ERROR [");
+               nv_error(priv, "DISPATCH_ERROR [");
                nouveau_enum_print(nvc0_copy_isr_error_name, ssta);
-               printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n",
-                       chid, inst, subc, mthd, data);
-               nv_wr32(dev, pcopy->fuc + 0x004, 0x00000040);
+               printk("] ch 0x%010llx subc %d mthd 0x%04x data 0x%08x\n",
+                      (u64)inst << 12, subc, mthd, data);
+               nv_wr32(priv, 0x104004 + (idx * 0x1000), 0x00000040);
                stat &= ~0x00000040;
        }
 
        if (stat) {
-               NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat);
-               nv_wr32(dev, pcopy->fuc + 0x004, stat);
+               nv_error(priv, "unhandled intr 0x%08x\n", stat);
+               nv_wr32(priv, 0x104004 + (idx * 0x1000), stat);
        }
 }
 
-static void
-nvc0_copy_isr_0(struct drm_device *dev)
+static int
+nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
 {
-       nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY0);
-}
+       struct nvc0_copy_priv *priv;
+       int ret;
 
-static void
-nvc0_copy_isr_1(struct drm_device *dev)
-{
-       nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY1);
+       if (nv_rd32(parent, 0x022500) & 0x00000100)
+               return -ENODEV;
+
+       ret = nouveau_copy_create(parent, engine, oclass, true, 0, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       nv_subdev(priv)->unit = 0x00000040;
+       nv_subdev(priv)->intr = nvc0_copy_intr;
+       nv_engine(priv)->cclass = &nvc0_copy0_cclass;
+       nv_engine(priv)->sclass = nvc0_copy0_sclass;
+       return 0;
 }
 
-static void
-nvc0_copy_destroy(struct drm_device *dev, int engine)
+static int
+nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
 {
-       struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
+       struct nvc0_copy_priv *priv;
+       int ret;
 
-       nouveau_irq_unregister(dev, pcopy->irq);
+       if (nv_rd32(parent, 0x022500) & 0x00000200)
+               return -ENODEV;
 
-       if (engine == NVOBJ_ENGINE_COPY0)
-               NVOBJ_ENGINE_DEL(dev, COPY0);
-       else
-               NVOBJ_ENGINE_DEL(dev, COPY1);
-       kfree(pcopy);
+       ret = nouveau_copy_create(parent, engine, oclass, true, 1, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       nv_subdev(priv)->unit = 0x00000080;
+       nv_subdev(priv)->intr = nvc0_copy_intr;
+       nv_engine(priv)->cclass = &nvc0_copy1_cclass;
+       nv_engine(priv)->sclass = nvc0_copy1_sclass;
+       return 0;
 }
 
-int
-nvc0_copy_create(struct drm_device *dev, int engine)
+static int
+nvc0_copy_init(struct nouveau_object *object)
 {
-       struct nvc0_copy_engine *pcopy;
-
-       pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL);
-       if (!pcopy)
-               return -ENOMEM;
-
-       pcopy->base.destroy = nvc0_copy_destroy;
-       pcopy->base.init = nvc0_copy_init;
-       pcopy->base.fini = nvc0_copy_fini;
-       pcopy->base.context_new = nvc0_copy_context_new;
-       pcopy->base.context_del = nvc0_copy_context_del;
-       pcopy->base.object_new = nvc0_copy_object_new;
-
-       if (engine == 0) {
-               pcopy->irq = 5;
-               pcopy->pmc = 0x00000040;
-               pcopy->fuc = 0x104000;
-               pcopy->ctx = 0x0230;
-               nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_0);
-               NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base);
-               NVOBJ_CLASS(dev, 0x90b5, COPY0);
-       } else {
-               pcopy->irq = 6;
-               pcopy->pmc = 0x00000080;
-               pcopy->fuc = 0x105000;
-               pcopy->ctx = 0x0240;
-               nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_1);
-               NVOBJ_ENGINE_ADD(dev, COPY1, &pcopy->base);
-               NVOBJ_CLASS(dev, 0x90b8, COPY1);
+       int idx = nv_engidx(object) - NVDEV_ENGINE_COPY0;
+       struct nvc0_copy_priv *priv = (void *)object;
+       int ret, i;
+
+       ret = nouveau_copy_init(&priv->base);
+       if (ret)
+               return ret;
+
+       /* disable all interrupts */
+       nv_wr32(priv, 0x104014 + (idx * 0x1000), 0xffffffff);
+
+       /* upload ucode */
+       nv_wr32(priv, 0x1041c0 + (idx * 0x1000), 0x01000000);
+       for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++)
+               nv_wr32(priv, 0x1041c4 + (idx * 0x1000), nvc0_pcopy_data[i]);
+
+       nv_wr32(priv, 0x104180 + (idx * 0x1000), 0x01000000);
+       for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) {
+               if ((i & 0x3f) == 0)
+                       nv_wr32(priv, 0x104188 + (idx * 0x1000), i >> 6);
+               nv_wr32(priv, 0x104184 + (idx * 0x1000), nvc0_pcopy_code[i]);
        }
 
+       /* start it running */
+       nv_wr32(priv, 0x104084 + (idx * 0x1000), idx);
+       nv_wr32(priv, 0x10410c + (idx * 0x1000), 0x00000000);
+       nv_wr32(priv, 0x104104 + (idx * 0x1000), 0x00000000); /* ENTRY */
+       nv_wr32(priv, 0x104100 + (idx * 0x1000), 0x00000002); /* TRIGGER */
        return 0;
 }
+
+static int
+nvc0_copy_fini(struct nouveau_object *object, bool suspend)
+{
+       int idx = nv_engidx(object) - NVDEV_ENGINE_COPY0;
+       struct nvc0_copy_priv *priv = (void *)object;
+
+       nv_mask(priv, 0x104048 + (idx * 0x1000), 0x00000003, 0x00000000);
+       nv_wr32(priv, 0x104014 + (idx * 0x1000), 0xffffffff);
+
+       return nouveau_copy_fini(&priv->base, suspend);
+}
+
+struct nouveau_oclass
+nvc0_copy0_oclass = {
+       .handle = NV_ENGINE(COPY0, 0xc0),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_copy0_ctor,
+               .dtor = _nouveau_copy_dtor,
+               .init = nvc0_copy_init,
+               .fini = nvc0_copy_fini,
+       },
+};
+
+struct nouveau_oclass
+nvc0_copy1_oclass = {
+       .handle = NV_ENGINE(COPY1, 0xc0),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_copy1_ctor,
+               .dtor = _nouveau_copy_dtor,
+               .init = nvc0_copy_init,
+               .fini = nvc0_copy_fini,
+       },
+};
This page took 0.031146 seconds and 5 git commands to generate.