aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/copy/nva3.c')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nva3.c268
1 files changed, 140 insertions, 128 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
index 9150c5ed16c3..debb82830b66 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
@@ -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"),
@@ -22,112 +22,75 @@
* 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,
+ },
+};