drm/nouveau: port all engines to new engine module format
[linux-3.10.git] / drivers / gpu / drm / nouveau / core / engine / copy / nva3.c
index 9150c5e..debb828 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 "fuc/nva3.fuc.h"
-
-struct nva3_copy_engine {
-       struct nouveau_exec_engine base;
-};
-
-static int
-nva3_copy_context_new(struct nouveau_channel *chan, int engine)
-{
-       struct drm_device *dev = chan->dev;
-       struct nouveau_gpuobj *ramin = chan->ramin;
-       struct nouveau_gpuobj *ctx = NULL;
-       int ret;
-
-       NV_DEBUG(dev, "ch%d\n", chan->id);
+#include <core/os.h>
+#include <core/enum.h>
+#include <core/class.h>
+#include <core/engctx.h>
 
-       ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC |
-                                NVOBJ_FLAG_ZERO_FREE, &ctx);
-       if (ret)
-               return ret;
+#include <subdev/fb.h>
+#include <subdev/vm.h>
 
-       nv_wo32(ramin, 0xc0, 0x00190000);
-       nv_wo32(ramin, 0xc4, ctx->addr + ctx->size - 1);
-       nv_wo32(ramin, 0xc8, ctx->addr);
-       nv_wo32(ramin, 0xcc, 0x00000000);
-       nv_wo32(ramin, 0xd0, 0x00000000);
-       nv_wo32(ramin, 0xd4, 0x00000000);
-       nvimem_flush(dev);
+#include <engine/copy.h>
 
-       nvvm_engref(chan->vm, engine, 1);
-       chan->engctx[engine] = ctx;
-       return 0;
-}
-
-static int
-nva3_copy_object_new(struct nouveau_channel *chan, int engine,
-                    u32 handle, u16 class)
-{
-       struct nouveau_gpuobj *ctx = chan->engctx[engine];
+#include "fuc/nva3.fuc.h"
 
-       /* fuc engine doesn't need an object, our ramht code does.. */
-       ctx->engine = 3;
-       ctx->class  = class;
-       return nouveau_ramht_insert(chan, handle, ctx);
-}
+struct nva3_copy_priv {
+       struct nouveau_copy base;
+};
 
-static void
-nva3_copy_context_del(struct nouveau_channel *chan, int engine)
-{
-       struct nouveau_gpuobj *ctx = chan->engctx[engine];
-       int i;
+struct nva3_copy_chan {
+       struct nouveau_copy_chan base;
+};
 
-       for (i = 0xc0; i <= 0xd4; i += 4)
-               nv_wo32(chan->ramin, i, 0x00000000);
+/*******************************************************************************
+ * Copy object classes
+ ******************************************************************************/
 
-       nvvm_engref(chan->vm, engine, -1);
-       nouveau_gpuobj_ref(NULL, &ctx);
-       chan->engctx[engine] = ctx;
-}
+static struct nouveau_oclass
+nva3_copy_sclass[] = {
+       { 0x85b5, &nouveau_object_ofuncs },
+       {}
+};
 
-static void
-nva3_copy_tlb_flush(struct drm_device *dev, int engine)
-{
-       nv50_vm_flush_engine(dev, 0x0d);
-}
+/*******************************************************************************
+ * PCOPY context
+ ******************************************************************************/
 
 static int
-nva3_copy_init(struct drm_device *dev, int engine)
+nva3_copy_context_ctor(struct nouveau_object *parent,
+                      struct nouveau_object *engine,
+                      struct nouveau_oclass *oclass, void *data, u32 size,
+                      struct nouveau_object **pobject)
 {
-       int i;
-
-       nv_mask(dev, 0x000200, 0x00002000, 0x00000000);
-       nv_mask(dev, 0x000200, 0x00002000, 0x00002000);
-       nv_wr32(dev, 0x104014, 0xffffffff); /* disable all interrupts */
-
-       /* upload ucode */
-       nv_wr32(dev, 0x1041c0, 0x01000000);
-       for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++)
-               nv_wr32(dev, 0x1041c4, nva3_pcopy_data[i]);
+       struct nva3_copy_chan *priv;
+       int ret;
 
-       nv_wr32(dev, 0x104180, 0x01000000);
-       for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) {
-               if ((i & 0x3f) == 0)
-                       nv_wr32(dev, 0x104188, i >> 6);
-               nv_wr32(dev, 0x104184, nva3_pcopy_code[i]);
-       }
+       ret = nouveau_copy_context_create(parent, engine, oclass, NULL, 256, 0,
+                                         NVOBJ_FLAG_ZERO_ALLOC, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
 
-       /* start it running */
-       nv_wr32(dev, 0x10410c, 0x00000000);
-       nv_wr32(dev, 0x104104, 0x00000000); /* ENTRY */
-       nv_wr32(dev, 0x104100, 0x00000002); /* TRIGGER */
        return 0;
 }
 
-static int
-nva3_copy_fini(struct drm_device *dev, int engine, bool suspend)
-{
-       nv_mask(dev, 0x104048, 0x00000003, 0x00000000);
-       nv_wr32(dev, 0x104014, 0xffffffff);
-       return 0;
-}
+static struct nouveau_oclass
+nva3_copy_cclass = {
+       .handle = NV_ENGCTX(COPY0, 0xa3),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nva3_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,
+
+       },
+};
+
+/*******************************************************************************
+ * PCOPY engine/subdev functions
+ ******************************************************************************/
 
 static struct nouveau_enum nva3_copy_isr_error_name[] = {
        { 0x0001, "ILLEGAL_MTHD" },
@@ -137,65 +100,114 @@ static struct nouveau_enum nva3_copy_isr_error_name[] = {
 };
 
 static void
-nva3_copy_isr(struct drm_device *dev)
+nva3_copy_intr(struct nouveau_subdev *subdev)
 {
-       u32 dispatch = nv_rd32(dev, 0x10401c);
-       u32 stat = nv_rd32(dev, 0x104008) & dispatch & ~(dispatch >> 16);
-       u32 inst = nv_rd32(dev, 0x104050) & 0x3fffffff;
-       u32 ssta = nv_rd32(dev, 0x104040) & 0x0000ffff;
-       u32 addr = nv_rd32(dev, 0x104040) >> 16;
+       struct nva3_copy_priv *priv = (void *)subdev;
+       u32 dispatch = nv_rd32(priv, 0x10401c);
+       u32 stat = nv_rd32(priv, 0x104008) & dispatch & ~(dispatch >> 16);
+       u32 inst = nv_rd32(priv, 0x104050) & 0x3fffffff;
+       u32 ssta = nv_rd32(priv, 0x104040) & 0x0000ffff;
+       u32 addr = nv_rd32(priv, 0x104040) >> 16;
        u32 mthd = (addr & 0x07ff) << 2;
        u32 subc = (addr & 0x3800) >> 11;
-       u32 data = nv_rd32(dev, 0x104044);
-       int chid = nv50_graph_isr_chid(dev, inst);
+       u32 data = nv_rd32(priv, 0x104044);
 
        if (stat & 0x00000040) {
-               NV_INFO(dev, "PCOPY: DISPATCH_ERROR [");
+               nv_error(priv, "DISPATCH_ERROR [");
                nouveau_enum_print(nva3_copy_isr_error_name, ssta);
-               printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n",
-                       chid, inst, subc, mthd, data);
-               nv_wr32(dev, 0x104004, 0x00000040);
+               printk("] ch 0x%08x subc %d mthd 0x%04x data 0x%08x\n",
+                      inst, subc, mthd, data);
+               nv_wr32(priv, 0x104004, 0x00000040);
                stat &= ~0x00000040;
        }
 
        if (stat) {
-               NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat);
-               nv_wr32(dev, 0x104004, stat);
+               nv_error(priv, "unhandled intr 0x%08x\n", stat);
+               nv_wr32(priv, 0x104004, stat);
        }
-       nv50_fb_vm_trap(dev, 1);
+
+       nv50_fb_trap(nouveau_fb(priv), 1);
 }
 
-static void
-nva3_copy_destroy(struct drm_device *dev, int engine)
+static int
+nva3_copy_tlb_flush(struct nouveau_engine *engine)
 {
-       struct nva3_copy_engine *pcopy = nv_engine(dev, engine);
+       nv50_vm_flush_engine(&engine->base, 0x0d);
+       return 0;
+}
 
-       nouveau_irq_unregister(dev, 22);
+static int
+nva3_copy_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
+{
+       bool enable = (nv_device(parent)->chipset != 0xaf);
+       struct nva3_copy_priv *priv;
+       int ret;
 
-       NVOBJ_ENGINE_DEL(dev, COPY0);
-       kfree(pcopy);
+       ret = nouveau_copy_create(parent, engine, oclass, enable, 0, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       nv_subdev(priv)->unit = 0x00802000;
+       nv_subdev(priv)->intr = nva3_copy_intr;
+       nv_engine(priv)->cclass = &nva3_copy_cclass;
+       nv_engine(priv)->sclass = nva3_copy_sclass;
+       nv_engine(priv)->tlb_flush = nva3_copy_tlb_flush;
+       return 0;
 }
 
-int
-nva3_copy_create(struct drm_device *dev)
+static int
+nva3_copy_init(struct nouveau_object *object)
 {
-       struct nva3_copy_engine *pcopy;
+       struct nva3_copy_priv *priv = (void *)object;
+       int ret, i;
 
-       pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL);
-       if (!pcopy)
-               return -ENOMEM;
+       ret = nouveau_copy_init(&priv->base);
+       if (ret)
+               return ret;
 
-       pcopy->base.destroy = nva3_copy_destroy;
-       pcopy->base.init = nva3_copy_init;
-       pcopy->base.fini = nva3_copy_fini;
-       pcopy->base.context_new = nva3_copy_context_new;
-       pcopy->base.context_del = nva3_copy_context_del;
-       pcopy->base.object_new = nva3_copy_object_new;
-       pcopy->base.tlb_flush = nva3_copy_tlb_flush;
+       /* disable all interrupts */
+       nv_wr32(priv, 0x104014, 0xffffffff);
 
-       nouveau_irq_register(dev, 22, nva3_copy_isr);
+       /* upload ucode */
+       nv_wr32(priv, 0x1041c0, 0x01000000);
+       for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++)
+               nv_wr32(priv, 0x1041c4, nva3_pcopy_data[i]);
+
+       nv_wr32(priv, 0x104180, 0x01000000);
+       for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) {
+               if ((i & 0x3f) == 0)
+                       nv_wr32(priv, 0x104188, i >> 6);
+               nv_wr32(priv, 0x104184, nva3_pcopy_code[i]);
+       }
 
-       NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base);
-       NVOBJ_CLASS(dev, 0x85b5, COPY0);
+       /* start it running */
+       nv_wr32(priv, 0x10410c, 0x00000000);
+       nv_wr32(priv, 0x104104, 0x00000000); /* ENTRY */
+       nv_wr32(priv, 0x104100, 0x00000002); /* TRIGGER */
        return 0;
 }
+
+static int
+nva3_copy_fini(struct nouveau_object *object, bool suspend)
+{
+       struct nva3_copy_priv *priv = (void *)object;
+
+       nv_mask(priv, 0x104048, 0x00000003, 0x00000000);
+       nv_wr32(priv, 0x104014, 0xffffffff);
+
+       return nouveau_copy_fini(&priv->base, suspend);
+}
+
+struct nouveau_oclass
+nva3_copy_oclass = {
+       .handle = NV_ENGINE(COPY0, 0xa3),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nva3_copy_ctor,
+               .dtor = _nouveau_copy_dtor,
+               .init = nva3_copy_init,
+               .fini = nva3_copy_fini,
+       },
+};