drm/nouveau: only expose the object classes that are supported by the chipset
authorBen Skeggs <bskeggs@redhat.com>
Wed, 20 Oct 2010 00:39:35 +0000 (10:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 3 Dec 2010 05:06:56 +0000 (15:06 +1000)
We previously added all the available classes for the entire generation,
even though the objects wouldn't work on the hardware.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_object.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_graph.c
drivers/gpu/drm/nouveau/nv10_graph.c
drivers/gpu/drm/nouveau/nv20_graph.c
drivers/gpu/drm/nouveau/nv40_graph.c
drivers/gpu/drm/nouveau/nv50_graph.c

index 2099f04c0b0adc47917feefb05260786fa77d683..3fb87995446b922ce1dc3668d60f3690fd589e8c 100644 (file)
@@ -316,21 +316,9 @@ struct nouveau_fifo_engine {
        void (*tlb_flush)(struct drm_device *dev);
 };
 
-struct nouveau_pgraph_object_method {
-       int id;
-       int (*exec)(struct nouveau_channel *chan, int grclass, int mthd,
-                     uint32_t data);
-};
-
-struct nouveau_pgraph_object_class {
-       int id;
-       u32 engine;
-       struct nouveau_pgraph_object_method *methods;
-};
-
 struct nouveau_pgraph_engine {
-       struct nouveau_pgraph_object_class *grclass;
        bool accel_blocked;
+       bool registered;
        int grctx_size;
 
        /* NV2x/NV3x context table (0x400780) */
@@ -584,6 +572,7 @@ struct drm_nouveau_private {
        bool ramin_available;
        struct drm_mm ramin_heap;
        struct list_head gpuobj_list;
+       struct list_head classes;
 
        struct nouveau_bo *vga_ram;
 
@@ -816,12 +805,29 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan,
                                struct nouveau_channel **pchan);
 
 /* nouveau_object.c */
+#define NVOBJ_CLASS(d,c,e) do {                                                \
+       int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e);        \
+       if (ret)                                                               \
+               return ret;                                                    \
+} while(0)
+
+#define NVOBJ_MTHD(d,c,m,e) do {                                               \
+       int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e));                 \
+       if (ret)                                                               \
+               return ret;                                                    \
+} while(0)
+
 extern int  nouveau_gpuobj_early_init(struct drm_device *);
 extern int  nouveau_gpuobj_init(struct drm_device *);
 extern void nouveau_gpuobj_takedown(struct drm_device *);
 extern int  nouveau_gpuobj_suspend(struct drm_device *dev);
 extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev);
 extern void nouveau_gpuobj_resume(struct drm_device *dev);
+extern int  nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng);
+extern int  nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd,
+                                   int (*exec)(struct nouveau_channel *,
+                                               u32 class, u32 mthd, u32 data));
+extern int  nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32);
 extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
                                       uint32_t vram_h, uint32_t tt_h);
 extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
@@ -1038,7 +1044,6 @@ extern int  nvc0_fifo_load_context(struct nouveau_channel *);
 extern int  nvc0_fifo_unload_context(struct drm_device *);
 
 /* nv04_graph.c */
-extern struct nouveau_pgraph_object_class nv04_graph_grclass[];
 extern int  nv04_graph_init(struct drm_device *);
 extern void nv04_graph_takedown(struct drm_device *);
 extern void nv04_graph_fifo_access(struct drm_device *, bool);
@@ -1050,7 +1055,6 @@ extern int  nv04_graph_unload_context(struct drm_device *);
 extern void nv04_graph_context_switch(struct drm_device *);
 
 /* nv10_graph.c */
-extern struct nouveau_pgraph_object_class nv10_graph_grclass[];
 extern int  nv10_graph_init(struct drm_device *);
 extern void nv10_graph_takedown(struct drm_device *);
 extern struct nouveau_channel *nv10_graph_channel(struct drm_device *);
@@ -1063,8 +1067,6 @@ extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t,
                                         uint32_t, uint32_t);
 
 /* nv20_graph.c */
-extern struct nouveau_pgraph_object_class nv20_graph_grclass[];
-extern struct nouveau_pgraph_object_class nv30_graph_grclass[];
 extern int  nv20_graph_create_context(struct nouveau_channel *);
 extern void nv20_graph_destroy_context(struct nouveau_channel *);
 extern int  nv20_graph_load_context(struct nouveau_channel *);
@@ -1076,7 +1078,6 @@ extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t,
                                         uint32_t, uint32_t);
 
 /* nv40_graph.c */
-extern struct nouveau_pgraph_object_class nv40_graph_grclass[];
 extern int  nv40_graph_init(struct drm_device *);
 extern void nv40_graph_takedown(struct drm_device *);
 extern struct nouveau_channel *nv40_graph_channel(struct drm_device *);
@@ -1089,7 +1090,6 @@ extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t,
                                         uint32_t, uint32_t);
 
 /* nv50_graph.c */
-extern struct nouveau_pgraph_object_class nv50_graph_grclass[];
 extern int  nv50_graph_init(struct drm_device *);
 extern void nv50_graph_takedown(struct drm_device *);
 extern void nv50_graph_fifo_access(struct drm_device *, bool);
index c5e37bc17192cdc2eb7f1c7652154ec6ea5818ac..f09151d17297e20b3b111f5cc63f4ccdcd7cf9cb 100644 (file)
@@ -80,33 +80,6 @@ nouveau_irq_uninstall(struct drm_device *dev)
        nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
 }
 
-static int
-nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data)
-{
-       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
-       struct nouveau_pgraph_object_method *grm;
-       struct nouveau_pgraph_object_class *grc;
-
-       grc = dev_priv->engine.graph.grclass;
-       while (grc->id) {
-               if (grc->id == class)
-                       break;
-               grc++;
-       }
-
-       if (grc->id != class || !grc->methods)
-               return -ENOENT;
-
-       grm = grc->methods;
-       while (grm->id) {
-               if (grm->id == mthd)
-                       return grm->exec(chan, class, mthd, data);
-               grm++;
-       }
-
-       return -ENOENT;
-}
-
 static bool
 nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
 {
@@ -142,8 +115,8 @@ nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
                if (unlikely(((engine >> (subc * 4)) & 0xf) != 0))
                        break;
 
-               if (!nouveau_call_method(chan, chan->sw_subchannel[subc],
-                                        mthd, data))
+               if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc],
+                                             mthd, data))
                        handled = true;
                break;
        }
@@ -541,6 +514,7 @@ nouveau_pgraph_intr_swmthd(struct drm_device *dev,
                           struct nouveau_pgraph_trap *trap)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_channel *chan;
        unsigned long flags;
        int ret = -EINVAL;
 
@@ -548,8 +522,8 @@ nouveau_pgraph_intr_swmthd(struct drm_device *dev,
        if (trap->channel > 0 &&
            trap->channel < dev_priv->engine.fifo.channels &&
            dev_priv->channels.ptr[trap->channel]) {
-               ret = nouveau_call_method(dev_priv->channels.ptr[trap->channel],
-                                         trap->class, trap->mthd, trap->data);
+               chan = dev_priv->channels.ptr[trap->channel];
+               ret = nouveau_gpuobj_mthd_call(chan, trap->class, trap->mthd, trap->data);
        }
        spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
 
index 9c26da4cdc004665a904c405b509caa51a0781d2..6226beb3613dc223f578b697aeadb858f07aa104 100644 (file)
 #include "nouveau_drm.h"
 #include "nouveau_ramht.h"
 
+struct nouveau_gpuobj_method {
+       struct list_head head;
+       u32 mthd;
+       int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data);
+};
+
+struct nouveau_gpuobj_class {
+       struct list_head head;
+       struct list_head methods;
+       u32 id;
+       u32 engine;
+};
+
+int
+nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj_class *oc;
+
+       oc = kzalloc(sizeof(*oc), GFP_KERNEL);
+       if (!oc)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&oc->methods);
+       oc->id = class;
+       oc->engine = engine;
+       list_add(&oc->head, &dev_priv->classes);
+       return 0;
+}
+
+int
+nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd,
+                       int (*exec)(struct nouveau_channel *, u32, u32, u32))
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj_method *om;
+       struct nouveau_gpuobj_class *oc;
+
+       list_for_each_entry(oc, &dev_priv->classes, head) {
+               if (oc->id == class)
+                       goto found;
+       }
+
+       return -EINVAL;
+
+found:
+       om = kzalloc(sizeof(*om), GFP_KERNEL);
+       if (!om)
+               return -ENOMEM;
+
+       om->mthd = mthd;
+       om->exec = exec;
+       list_add(&om->head, &oc->methods);
+       return 0;
+}
+
+int
+nouveau_gpuobj_mthd_call(struct nouveau_channel *chan,
+                        u32 class, u32 mthd, u32 data)
+{
+       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+       struct nouveau_gpuobj_method *om;
+       struct nouveau_gpuobj_class *oc;
+
+       list_for_each_entry(oc, &dev_priv->classes, head) {
+               if (oc->id != class)
+                       continue;
+
+               list_for_each_entry(om, &oc->methods, head) {
+                       if (om->mthd == mthd)
+                               return om->exec(chan, class, mthd, data);
+               }
+       }
+
+       return -ENOENT;
+}
+
 /* NVidia uses context objects to drive drawing operations.
 
    Context objects can be selected into 8 subchannels in the FIFO,
@@ -205,9 +282,20 @@ void
 nouveau_gpuobj_takedown(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj_method *om, *tm;
+       struct nouveau_gpuobj_class *oc, *tc;
 
        NV_DEBUG(dev, "\n");
 
+       list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) {
+               list_for_each_entry_safe(om, tm, &oc->methods, head) {
+                       list_del(&om->head);
+                       kfree(om);
+               }
+               list_del(&oc->head);
+               kfree(oc);
+       }
+
        BUG_ON(!list_empty(&dev_priv->gpuobj_list));
 }
 
@@ -527,26 +615,22 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
                      struct nouveau_gpuobj **gpuobj)
 {
        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
-       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-       struct nouveau_pgraph_object_class *grc;
        struct drm_device *dev = chan->dev;
+       struct nouveau_gpuobj_class *oc;
        int ret;
 
        NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);
 
-       grc = pgraph->grclass;
-       while (grc->id) {
-               if (grc->id == class)
-                       break;
-               grc++;
+       list_for_each_entry(oc, &dev_priv->classes, head) {
+               if (oc->id == class)
+                       goto found;
        }
 
-       if (!grc->id) {
-               NV_ERROR(dev, "illegal object class: 0x%x\n", class);
-               return -EINVAL;
-       }
+       NV_ERROR(dev, "illegal object class: 0x%x\n", class);
+       return -EINVAL;
 
-       if (grc->engine == NVOBJ_ENGINE_SW)
+found:
+       if (oc->engine == NVOBJ_ENGINE_SW)
                return nouveau_gpuobj_sw_new(chan, class, gpuobj);
 
        ret = nouveau_gpuobj_new(dev, chan,
@@ -585,8 +669,8 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
        }
        dev_priv->engine.instmem.flush(dev);
 
-       (*gpuobj)->engine = grc->engine;
-       (*gpuobj)->class  = class;
+       (*gpuobj)->engine = oc->engine;
+       (*gpuobj)->class  = oc->id;
        return 0;
 }
 
index 82b58188398ba3bf0fe89768383238a4a73249b8..be28754ffd50ed2cff01048a5ad12ba4ce7cb40e 100644 (file)
@@ -65,7 +65,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.takedown          = nv04_timer_takedown;
                engine->fb.init                 = nv04_fb_init;
                engine->fb.takedown             = nv04_fb_takedown;
-               engine->graph.grclass           = nv04_graph_grclass;
                engine->graph.init              = nv04_graph_init;
                engine->graph.takedown          = nv04_graph_takedown;
                engine->graph.fifo_access       = nv04_graph_fifo_access;
@@ -118,7 +117,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fb.init                 = nv10_fb_init;
                engine->fb.takedown             = nv10_fb_takedown;
                engine->fb.set_region_tiling    = nv10_fb_set_region_tiling;
-               engine->graph.grclass           = nv10_graph_grclass;
                engine->graph.init              = nv10_graph_init;
                engine->graph.takedown          = nv10_graph_takedown;
                engine->graph.channel           = nv10_graph_channel;
@@ -172,7 +170,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fb.init                 = nv10_fb_init;
                engine->fb.takedown             = nv10_fb_takedown;
                engine->fb.set_region_tiling    = nv10_fb_set_region_tiling;
-               engine->graph.grclass           = nv20_graph_grclass;
                engine->graph.init              = nv20_graph_init;
                engine->graph.takedown          = nv20_graph_takedown;
                engine->graph.channel           = nv10_graph_channel;
@@ -226,7 +223,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fb.init                 = nv30_fb_init;
                engine->fb.takedown             = nv30_fb_takedown;
                engine->fb.set_region_tiling    = nv10_fb_set_region_tiling;
-               engine->graph.grclass           = nv30_graph_grclass;
                engine->graph.init              = nv30_graph_init;
                engine->graph.takedown          = nv20_graph_takedown;
                engine->graph.fifo_access       = nv04_graph_fifo_access;
@@ -283,7 +279,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fb.init                 = nv40_fb_init;
                engine->fb.takedown             = nv40_fb_takedown;
                engine->fb.set_region_tiling    = nv40_fb_set_region_tiling;
-               engine->graph.grclass           = nv40_graph_grclass;
                engine->graph.init              = nv40_graph_init;
                engine->graph.takedown          = nv40_graph_takedown;
                engine->graph.fifo_access       = nv04_graph_fifo_access;
@@ -345,7 +340,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.takedown          = nv04_timer_takedown;
                engine->fb.init                 = nv50_fb_init;
                engine->fb.takedown             = nv50_fb_takedown;
-               engine->graph.grclass           = nv50_graph_grclass;
                engine->graph.init              = nv50_graph_init;
                engine->graph.takedown          = nv50_graph_takedown;
                engine->graph.fifo_access       = nv50_graph_fifo_access;
@@ -424,7 +418,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->timer.takedown          = nv04_timer_takedown;
                engine->fb.init                 = nvc0_fb_init;
                engine->fb.takedown             = nvc0_fb_takedown;
-               engine->graph.grclass           = NULL;  //nvc0_graph_grclass;
                engine->graph.init              = nvc0_graph_init;
                engine->graph.takedown          = nvc0_graph_takedown;
                engine->graph.fifo_access       = nvc0_graph_fifo_access;
index 5d8ab1b6b04a6d54c86d54fd2edada92b882ea67..81aba097ef950c08047bf8e975dba9d699a4d691 100644 (file)
@@ -27,6 +27,8 @@
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
 
+static int nv04_graph_register(struct drm_device *dev);
+
 static uint32_t nv04_graph_ctx_regs[] = {
        0x0040053c,
        0x00400544,
@@ -483,12 +485,17 @@ int nv04_graph_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t tmp;
+       int ret;
 
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
                        ~NV_PMC_ENABLE_PGRAPH);
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
                         NV_PMC_ENABLE_PGRAPH);
 
+       ret = nv04_graph_register(dev);
+       if (ret)
+               return ret;
+
        /* Enable PGRAPH interrupts */
        nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
@@ -539,8 +546,8 @@ nv04_graph_fifo_access(struct drm_device *dev, bool enabled)
 }
 
 static int
-nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
-                       int mthd, uint32_t data)
+nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
+                       u32 class, u32 mthd, u32 data)
 {
        atomic_set(&chan->fence.last_sequence_irq, data);
        return 0;
@@ -621,12 +628,12 @@ nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
  */
 
 static void
-nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value)
+nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value)
 {
        struct drm_device *dev = chan->dev;
-       uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
+       u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
        int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
-       uint32_t tmp;
+       u32 tmp;
 
        tmp  = nv_ri32(dev, instance);
        tmp &= ~mask;
@@ -638,11 +645,11 @@ nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value)
 }
 
 static void
-nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t value)
+nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value)
 {
        struct drm_device *dev = chan->dev;
-       uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
-       uint32_t tmp, ctx1;
+       u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
+       u32 tmp, ctx1;
        int class, op, valid = 1;
 
        ctx1 = nv_ri32(dev, instance);
@@ -687,13 +694,13 @@ nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t val
 }
 
 static int
-nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_set_operation(struct nouveau_channel *chan,
+                             u32 class, u32 mthd, u32 data)
 {
        if (data > 5)
                return 1;
        /* Old versions of the objects only accept first three operations. */
-       if (data > 2 && grclass < 0x40)
+       if (data > 2 && class < 0x40)
                return 1;
        nv04_graph_set_ctx1(chan, 0x00038000, data << 15);
        /* changing operation changes set of objects needed for validation */
@@ -702,8 +709,8 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan,
+                             u32 class, u32 mthd, u32 data)
 {
        uint32_t min = data & 0xffff, max;
        uint32_t w = data >> 16;
@@ -721,8 +728,8 @@ nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan,
+                             u32 class, u32 mthd, u32 data)
 {
        uint32_t min = data & 0xffff, max;
        uint32_t w = data >> 16;
@@ -740,8 +747,8 @@ nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan,
+                           u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -757,8 +764,8 @@ nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan,
+                                   u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -778,8 +785,8 @@ nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan,
+                              u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -793,8 +800,8 @@ nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan,
+                              u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -808,8 +815,8 @@ nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_rop(struct nouveau_channel *chan,
+                        u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -823,8 +830,8 @@ nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan,
+                          u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -838,8 +845,8 @@ nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan,
+                          u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -853,8 +860,8 @@ nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan,
+                             u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -868,8 +875,8 @@ nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan,
+                             u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -883,8 +890,8 @@ nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan,
+                               u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -898,8 +905,8 @@ nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan,
+                              u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -913,8 +920,8 @@ nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_clip(struct nouveau_channel *chan,
+                         u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -928,8 +935,8 @@ nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan,
+                           u32 class, u32 mthd, u32 data)
 {
        switch (nv_ri32(chan->dev, data << 4) & 0xff) {
        case 0x30:
@@ -945,194 +952,259 @@ nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass,
        return 1;
 }
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = {
-       { 0x0150, nv04_graph_mthd_set_ref },
-       {}
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_gdirect[] = {
-       { 0x0184, nv04_graph_mthd_bind_nv01_patt },
-       { 0x0188, nv04_graph_mthd_bind_rop },
-       { 0x018c, nv04_graph_mthd_bind_beta1 },
-       { 0x0190, nv04_graph_mthd_bind_surf_dst },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_gdirect[] = {
-       { 0x0188, nv04_graph_mthd_bind_nv04_patt },
-       { 0x018c, nv04_graph_mthd_bind_rop },
-       { 0x0190, nv04_graph_mthd_bind_beta1 },
-       { 0x0194, nv04_graph_mthd_bind_beta4 },
-       { 0x0198, nv04_graph_mthd_bind_surf2d },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_imageblit[] = {
-       { 0x0184, nv04_graph_mthd_bind_chroma },
-       { 0x0188, nv04_graph_mthd_bind_clip },
-       { 0x018c, nv04_graph_mthd_bind_nv01_patt },
-       { 0x0190, nv04_graph_mthd_bind_rop },
-       { 0x0194, nv04_graph_mthd_bind_beta1 },
-       { 0x0198, nv04_graph_mthd_bind_surf_dst },
-       { 0x019c, nv04_graph_mthd_bind_surf_src },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_imageblit_ifc[] = {
-       { 0x0184, nv04_graph_mthd_bind_chroma },
-       { 0x0188, nv04_graph_mthd_bind_clip },
-       { 0x018c, nv04_graph_mthd_bind_nv04_patt },
-       { 0x0190, nv04_graph_mthd_bind_rop },
-       { 0x0194, nv04_graph_mthd_bind_beta1 },
-       { 0x0198, nv04_graph_mthd_bind_beta4 },
-       { 0x019c, nv04_graph_mthd_bind_surf2d },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_iifc[] = {
-       { 0x0188, nv04_graph_mthd_bind_chroma },
-       { 0x018c, nv04_graph_mthd_bind_clip },
-       { 0x0190, nv04_graph_mthd_bind_nv04_patt },
-       { 0x0194, nv04_graph_mthd_bind_rop },
-       { 0x0198, nv04_graph_mthd_bind_beta1 },
-       { 0x019c, nv04_graph_mthd_bind_beta4 },
-       { 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf },
-       { 0x03e4, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_ifc[] = {
-       { 0x0184, nv04_graph_mthd_bind_chroma },
-       { 0x0188, nv04_graph_mthd_bind_clip },
-       { 0x018c, nv04_graph_mthd_bind_nv01_patt },
-       { 0x0190, nv04_graph_mthd_bind_rop },
-       { 0x0194, nv04_graph_mthd_bind_beta1 },
-       { 0x0198, nv04_graph_mthd_bind_surf_dst },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifc[] = {
-       { 0x0184, nv04_graph_mthd_bind_chroma },
-       { 0x0188, nv04_graph_mthd_bind_nv01_patt },
-       { 0x018c, nv04_graph_mthd_bind_rop },
-       { 0x0190, nv04_graph_mthd_bind_beta1 },
-       { 0x0194, nv04_graph_mthd_bind_surf_dst },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifc[] = {
-       { 0x0184, nv04_graph_mthd_bind_chroma },
-       { 0x0188, nv04_graph_mthd_bind_nv04_patt },
-       { 0x018c, nv04_graph_mthd_bind_rop },
-       { 0x0190, nv04_graph_mthd_bind_beta1 },
-       { 0x0194, nv04_graph_mthd_bind_beta4 },
-       { 0x0198, nv04_graph_mthd_bind_surf2d },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifm[] = {
-       { 0x0188, nv04_graph_mthd_bind_nv01_patt },
-       { 0x018c, nv04_graph_mthd_bind_rop },
-       { 0x0190, nv04_graph_mthd_bind_beta1 },
-       { 0x0194, nv04_graph_mthd_bind_surf_dst },
-       { 0x0304, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifm[] = {
-       { 0x0188, nv04_graph_mthd_bind_nv04_patt },
-       { 0x018c, nv04_graph_mthd_bind_rop },
-       { 0x0190, nv04_graph_mthd_bind_beta1 },
-       { 0x0194, nv04_graph_mthd_bind_beta4 },
-       { 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf },
-       { 0x0304, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_shape[] = {
-       { 0x0184, nv04_graph_mthd_bind_clip },
-       { 0x0188, nv04_graph_mthd_bind_nv01_patt },
-       { 0x018c, nv04_graph_mthd_bind_rop },
-       { 0x0190, nv04_graph_mthd_bind_beta1 },
-       { 0x0194, nv04_graph_mthd_bind_surf_dst },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_shape[] = {
-       { 0x0184, nv04_graph_mthd_bind_clip },
-       { 0x0188, nv04_graph_mthd_bind_nv04_patt },
-       { 0x018c, nv04_graph_mthd_bind_rop },
-       { 0x0190, nv04_graph_mthd_bind_beta1 },
-       { 0x0194, nv04_graph_mthd_bind_beta4 },
-       { 0x0198, nv04_graph_mthd_bind_surf2d },
-       { 0x02fc, nv04_graph_mthd_set_operation },
-       {},
-};
-
-static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_tex_tri[] = {
-       { 0x0188, nv04_graph_mthd_bind_clip },
-       { 0x018c, nv04_graph_mthd_bind_surf_color },
-       { 0x0190, nv04_graph_mthd_bind_surf_zeta },
-       {},
-};
+static int
+nv04_graph_register(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-static struct nouveau_pgraph_object_method nv04_graph_mthds_surf3d[] = {
-       { 0x02f8, nv04_graph_mthd_surf3d_clip_h },
-       { 0x02fc, nv04_graph_mthd_surf3d_clip_v },
-       {},
-};
+       if (dev_priv->engine.graph.registered)
+               return 0;
 
-struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
-       { 0x0038, NVOBJ_ENGINE_GR, NULL }, /* dvd subpicture */
-       { 0x0039, NVOBJ_ENGINE_GR, NULL }, /* m2mf */
-       { 0x004b, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv03_gdirect }, /* nv03 gdirect */
-       { 0x004a, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_gdirect }, /* nv04 gdirect */
-       { 0x001f, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv01_imageblit }, /* nv01 imageblit */
-       { 0x005f, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 imageblit */
-       { 0x0060, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_iifc }, /* nv04 iifc */
-       { 0x0064, NVOBJ_ENGINE_GR, NULL }, /* nv05 iifc */
-       { 0x0021, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv01_ifc }, /* nv01 ifc */
-       { 0x0061, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 ifc */
-       { 0x0065, NVOBJ_ENGINE_GR, NULL }, /* nv05 ifc */
-       { 0x0036, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv03_sifc }, /* nv03 sifc */
-       { 0x0076, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_sifc }, /* nv04 sifc */
-       { 0x0066, NVOBJ_ENGINE_GR, NULL }, /* nv05 sifc */
-       { 0x0037, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv03_sifm }, /* nv03 sifm */
-       { 0x0077, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_sifm }, /* nv04 sifm */
-       { 0x0030, NVOBJ_ENGINE_GR, NULL }, /* null */
-       { 0x0042, NVOBJ_ENGINE_GR, NULL }, /* surf2d */
-       { 0x0043, NVOBJ_ENGINE_GR, NULL }, /* rop */
-       { 0x0012, NVOBJ_ENGINE_GR, NULL }, /* beta1 */
-       { 0x0072, NVOBJ_ENGINE_GR, NULL }, /* beta4 */
-       { 0x0019, NVOBJ_ENGINE_GR, NULL }, /* cliprect */
-       { 0x0018, NVOBJ_ENGINE_GR, NULL }, /* nv01 pattern */
-       { 0x0044, NVOBJ_ENGINE_GR, NULL }, /* nv04 pattern */
-       { 0x0052, NVOBJ_ENGINE_GR, NULL }, /* swzsurf */
-       { 0x0053, NVOBJ_ENGINE_GR, nv04_graph_mthds_surf3d }, /* surf3d */
-       { 0x0048, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv03_tex_tri }, /* nv03 tex_tri */
-       { 0x0054, NVOBJ_ENGINE_GR, NULL }, /* tex_tri */
-       { 0x0055, NVOBJ_ENGINE_GR, NULL }, /* multitex_tri */
-       { 0x0017, NVOBJ_ENGINE_GR, NULL }, /* nv01 chroma */
-       { 0x0057, NVOBJ_ENGINE_GR, NULL }, /* nv04 chroma */
-       { 0x0058, NVOBJ_ENGINE_GR, NULL }, /* surf_dst */
-       { 0x0059, NVOBJ_ENGINE_GR, NULL }, /* surf_src */
-       { 0x005a, NVOBJ_ENGINE_GR, NULL }, /* surf_color */
-       { 0x005b, NVOBJ_ENGINE_GR, NULL }, /* surf_zeta */
-       { 0x001c, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv01_shape }, /* nv01 line */
-       { 0x005c, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_shape }, /* nv04 line */
-       { 0x001d, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv01_shape }, /* nv01 tri */
-       { 0x005d, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_shape }, /* nv04 tri */
-       { 0x001e, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv01_shape }, /* nv01 rect */
-       { 0x005e, NVOBJ_ENGINE_GR, nv04_graph_mthds_nv04_shape }, /* nv04 rect */
-       { 0x506e, NVOBJ_ENGINE_SW, nv04_graph_mthds_sw },
-       {}
+       /* dvd subpicture */
+       NVOBJ_CLASS(dev, 0x0038, GR);
+
+       /* m2mf */
+       NVOBJ_CLASS(dev, 0x0039, GR);
+
+       /* nv03 gdirect */
+       NVOBJ_CLASS(dev, 0x004b, GR);
+       NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 gdirect */
+       NVOBJ_CLASS(dev, 0x004a, GR);
+       NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d);
+       NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv01 imageblit */
+       NVOBJ_CLASS(dev, 0x001f, GR);
+       NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma);
+       NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src);
+       NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 imageblit */
+       NVOBJ_CLASS(dev, 0x005f, GR);
+       NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma);
+       NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d);
+       NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 iifc */
+       NVOBJ_CLASS(dev, 0x0060, GR);
+       NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma);
+       NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf);
+       NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation);
+
+       /* nv05 iifc */
+       NVOBJ_CLASS(dev, 0x0064, GR);
+
+       /* nv01 ifc */
+       NVOBJ_CLASS(dev, 0x0021, GR);
+       NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma);
+       NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 ifc */
+       NVOBJ_CLASS(dev, 0x0061, GR);
+       NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma);
+       NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d);
+       NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv05 ifc */
+       NVOBJ_CLASS(dev, 0x0065, GR);
+
+       /* nv03 sifc */
+       NVOBJ_CLASS(dev, 0x0036, GR);
+       NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma);
+       NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 sifc */
+       NVOBJ_CLASS(dev, 0x0076, GR);
+       NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma);
+       NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d);
+       NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv05 sifc */
+       NVOBJ_CLASS(dev, 0x0066, GR);
+
+       /* nv03 sifm */
+       NVOBJ_CLASS(dev, 0x0037, GR);
+       NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation);
+
+       /* nv04 sifm */
+       NVOBJ_CLASS(dev, 0x0077, GR);
+       NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf);
+       NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation);
+
+       /* null */
+       NVOBJ_CLASS(dev, 0x0030, GR);
+
+       /* surf2d */
+       NVOBJ_CLASS(dev, 0x0042, GR);
+
+       /* rop */
+       NVOBJ_CLASS(dev, 0x0043, GR);
+
+       /* beta1 */
+       NVOBJ_CLASS(dev, 0x0012, GR);
+
+       /* beta4 */
+       NVOBJ_CLASS(dev, 0x0072, GR);
+
+       /* cliprect */
+       NVOBJ_CLASS(dev, 0x0019, GR);
+
+       /* nv01 pattern */
+       NVOBJ_CLASS(dev, 0x0018, GR);
+
+       /* nv04 pattern */
+       NVOBJ_CLASS(dev, 0x0044, GR);
+
+       /* swzsurf */
+       NVOBJ_CLASS(dev, 0x0052, GR);
+
+       /* surf3d */
+       NVOBJ_CLASS(dev, 0x0053, GR);
+       NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h);
+       NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v);
+
+       /* nv03 tex_tri */
+       NVOBJ_CLASS(dev, 0x0048, GR);
+       NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color);
+       NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta);
+
+       /* tex_tri */
+       NVOBJ_CLASS(dev, 0x0054, GR);
+
+       /* multitex_tri */
+       NVOBJ_CLASS(dev, 0x0055, GR);
+
+       /* nv01 chroma */
+       NVOBJ_CLASS(dev, 0x0017, GR);
+
+       /* nv04 chroma */
+       NVOBJ_CLASS(dev, 0x0057, GR);
+
+       /* surf_dst */
+       NVOBJ_CLASS(dev, 0x0058, GR);
+
+       /* surf_src */
+       NVOBJ_CLASS(dev, 0x0059, GR);
+
+       /* surf_color */
+       NVOBJ_CLASS(dev, 0x005a, GR);
+
+       /* surf_zeta */
+       NVOBJ_CLASS(dev, 0x005b, GR);
+
+       /* nv01 line */
+       NVOBJ_CLASS(dev, 0x001c, GR);
+       NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 line */
+       NVOBJ_CLASS(dev, 0x005c, GR);
+       NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d);
+       NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv01 tri */
+       NVOBJ_CLASS(dev, 0x001d, GR);
+       NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 tri */
+       NVOBJ_CLASS(dev, 0x005d, GR);
+       NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d);
+       NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv01 rect */
+       NVOBJ_CLASS(dev, 0x001e, GR);
+       NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt);
+       NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst);
+       NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nv04 rect */
+       NVOBJ_CLASS(dev, 0x005e, GR);
+       NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip);
+       NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt);
+       NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop);
+       NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1);
+       NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4);
+       NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d);
+       NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation);
+
+       /* nvsw */
+       NVOBJ_CLASS(dev, 0x506e, SW);
+       NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref);
+
+       dev_priv->engine.graph.registered = true;
+       return 0;
 };
-
index ed31a622889e6292b42e062e3f1780f86110757c..17c20dbff232adf3d21f5804b8f0fcb0efd3ce74 100644 (file)
@@ -27,6 +27,8 @@
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
 
+static int nv10_graph_register(struct drm_device *);
+
 #define NV10_FIFO_NUMBER 32
 
 struct pipe_state {
@@ -914,13 +916,17 @@ int nv10_graph_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t tmp;
-       int i;
+       int ret, i;
 
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
                        ~NV_PMC_ENABLE_PGRAPH);
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
                         NV_PMC_ENABLE_PGRAPH);
 
+       ret = nv10_graph_register(dev);
+       if (ret)
+               return ret;
+
        nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -966,8 +972,8 @@ void nv10_graph_takedown(struct drm_device *dev)
 }
 
 static int
-nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass,
-                          int mthd, uint32_t data)
+nv17_graph_mthd_lma_window(struct nouveau_channel *chan,
+                          u32 class, u32 mthd, u32 data)
 {
        struct drm_device *dev = chan->dev;
        struct graph_state *ctx = chan->pgraph_ctx;
@@ -1046,8 +1052,8 @@ nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass,
-                          int mthd, uint32_t data)
+nv17_graph_mthd_lma_enable(struct nouveau_channel *chan,
+                          u32 class, u32 mthd, u32 data)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1065,36 +1071,48 @@ nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass,
        return 0;
 }
 
-static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = {
-       { 0x1638, nv17_graph_mthd_lma_window },
-       { 0x163c, nv17_graph_mthd_lma_window },
-       { 0x1640, nv17_graph_mthd_lma_window },
-       { 0x1644, nv17_graph_mthd_lma_window },
-       { 0x1658, nv17_graph_mthd_lma_enable },
-       {}
-};
+static int
+nv10_graph_register(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-struct nouveau_pgraph_object_class nv10_graph_grclass[] = {
-       { 0x506e, NVOBJ_ENGINE_SW, NULL }, /* nvsw */
-       { 0x0030, NVOBJ_ENGINE_GR, NULL }, /* null */
-       { 0x0039, NVOBJ_ENGINE_GR, NULL }, /* m2mf */
-       { 0x004a, NVOBJ_ENGINE_GR, NULL }, /* gdirect */
-       { 0x005f, NVOBJ_ENGINE_GR, NULL }, /* imageblit */
-       { 0x009f, NVOBJ_ENGINE_GR, NULL }, /* imageblit (nv12) */
-       { 0x008a, NVOBJ_ENGINE_GR, NULL }, /* ifc */
-       { 0x0089, NVOBJ_ENGINE_GR, NULL }, /* sifm */
-       { 0x0062, NVOBJ_ENGINE_GR, NULL }, /* surf2d */
-       { 0x0043, NVOBJ_ENGINE_GR, NULL }, /* rop */
-       { 0x0012, NVOBJ_ENGINE_GR, NULL }, /* beta1 */
-       { 0x0072, NVOBJ_ENGINE_GR, NULL }, /* beta4 */
-       { 0x0019, NVOBJ_ENGINE_GR, NULL }, /* cliprect */
-       { 0x0044, NVOBJ_ENGINE_GR, NULL }, /* pattern */
-       { 0x0052, NVOBJ_ENGINE_GR, NULL }, /* swzsurf */
-       { 0x0093, NVOBJ_ENGINE_GR, NULL }, /* surf3d */
-       { 0x0094, NVOBJ_ENGINE_GR, NULL }, /* tex_tri */
-       { 0x0095, NVOBJ_ENGINE_GR, NULL }, /* multitex_tri */
-       { 0x0056, NVOBJ_ENGINE_GR, NULL }, /* celcius (nv10) */
-       { 0x0096, NVOBJ_ENGINE_GR, NULL }, /* celcius (nv11) */
-       { 0x0099, NVOBJ_ENGINE_GR, nv17_graph_celsius_mthds }, /* celcius (nv17) */
-       {}
-};
+       if (dev_priv->engine.graph.registered)
+               return 0;
+
+       NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+       NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+       NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+       NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+       NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */
+       NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+       NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+       NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+       NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+       NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+       NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+       NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+       NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+       NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+       NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */
+       NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */
+       NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */
+       NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */
+
+       /* celcius */
+       if (dev_priv->chipset <= 0x10) {
+               NVOBJ_CLASS(dev, 0x0056, GR);
+       } else
+       if (dev_priv->chipset <= 0x17 || dev_priv->chipset == 0x1a) {
+               NVOBJ_CLASS(dev, 0x0096, GR);
+       } else {
+               NVOBJ_CLASS(dev, 0x0099, GR);
+               NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window);
+               NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window);
+               NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window);
+               NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window);
+               NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable);
+       }
+
+       dev_priv->engine.graph.registered = true;
+       return 0;
+}
index 872f8d059694116cae66c5af5f2ea8f5097f9c66..7720bccb3c981be3785459a9c52eddb1054a1934 100644 (file)
@@ -32,6 +32,9 @@
 #define NV34_GRCTX_SIZE    (18140)
 #define NV35_36_GRCTX_SIZE (22396)
 
+static int nv20_graph_register(struct drm_device *);
+static int nv30_graph_register(struct drm_device *);
+
 static void
 nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
@@ -572,6 +575,12 @@ nv20_graph_init(struct drm_device *dev)
 
        nv20_graph_rdi(dev);
 
+       ret = nv20_graph_register(dev);
+       if (ret) {
+               nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
+               return ret;
+       }
+
        nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
        nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -696,6 +705,12 @@ nv30_graph_init(struct drm_device *dev)
                        return ret;
        }
 
+       ret = nv30_graph_register(dev);
+       if (ret) {
+               nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
+               return ret;
+       }
+
        nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE,
                     pgraph->ctx_table->pinst >> 4);
 
@@ -756,48 +771,76 @@ nv30_graph_init(struct drm_device *dev)
        return 0;
 }
 
-struct nouveau_pgraph_object_class nv20_graph_grclass[] = {
-       { 0x506e, NVOBJ_ENGINE_SW, NULL }, /* nvsw */
-       { 0x0030, NVOBJ_ENGINE_GR, NULL }, /* null */
-       { 0x0039, NVOBJ_ENGINE_GR, NULL }, /* m2mf */
-       { 0x004a, NVOBJ_ENGINE_GR, NULL }, /* gdirect */
-       { 0x009f, NVOBJ_ENGINE_GR, NULL }, /* imageblit (nv12) */
-       { 0x008a, NVOBJ_ENGINE_GR, NULL }, /* ifc */
-       { 0x0089, NVOBJ_ENGINE_GR, NULL }, /* sifm */
-       { 0x0062, NVOBJ_ENGINE_GR, NULL }, /* surf2d */
-       { 0x0043, NVOBJ_ENGINE_GR, NULL }, /* rop */
-       { 0x0012, NVOBJ_ENGINE_GR, NULL }, /* beta1 */
-       { 0x0072, NVOBJ_ENGINE_GR, NULL }, /* beta4 */
-       { 0x0019, NVOBJ_ENGINE_GR, NULL }, /* cliprect */
-       { 0x0044, NVOBJ_ENGINE_GR, NULL }, /* pattern */
-       { 0x009e, NVOBJ_ENGINE_GR, NULL }, /* swzsurf */
-       { 0x0096, NVOBJ_ENGINE_GR, NULL }, /* celcius */
-       { 0x0097, NVOBJ_ENGINE_GR, NULL }, /* kelvin (nv20) */
-       { 0x0597, NVOBJ_ENGINE_GR, NULL }, /* kelvin (nv25) */
-       {}
-};
-
-struct nouveau_pgraph_object_class nv30_graph_grclass[] = {
-       { 0x506e, NVOBJ_ENGINE_SW, NULL }, /* nvsw */
-       { 0x0030, NVOBJ_ENGINE_GR, NULL }, /* null */
-       { 0x0039, NVOBJ_ENGINE_GR, NULL }, /* m2mf */
-       { 0x004a, NVOBJ_ENGINE_GR, NULL }, /* gdirect */
-       { 0x009f, NVOBJ_ENGINE_GR, NULL }, /* imageblit (nv12) */
-       { 0x008a, NVOBJ_ENGINE_GR, NULL }, /* ifc */
-       { 0x038a, NVOBJ_ENGINE_GR, NULL }, /* ifc (nv30) */
-       { 0x0089, NVOBJ_ENGINE_GR, NULL }, /* sifm */
-       { 0x0389, NVOBJ_ENGINE_GR, NULL }, /* sifm (nv30) */
-       { 0x0062, NVOBJ_ENGINE_GR, NULL }, /* surf2d */
-       { 0x0362, NVOBJ_ENGINE_GR, NULL }, /* surf2d (nv30) */
-       { 0x0043, NVOBJ_ENGINE_GR, NULL }, /* rop */
-       { 0x0012, NVOBJ_ENGINE_GR, NULL }, /* beta1 */
-       { 0x0072, NVOBJ_ENGINE_GR, NULL }, /* beta4 */
-       { 0x0019, NVOBJ_ENGINE_GR, NULL }, /* cliprect */
-       { 0x0044, NVOBJ_ENGINE_GR, NULL }, /* pattern */
-       { 0x039e, NVOBJ_ENGINE_GR, NULL }, /* swzsurf */
-       { 0x0397, NVOBJ_ENGINE_GR, NULL }, /* rankine (nv30) */
-       { 0x0497, NVOBJ_ENGINE_GR, NULL }, /* rankine (nv35) */
-       { 0x0697, NVOBJ_ENGINE_GR, NULL }, /* rankine (nv34) */
-       {}
-};
+static int
+nv20_graph_register(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->engine.graph.registered)
+               return 0;
 
+       NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+       NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+       NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+       NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+       NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+       NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+       NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+       NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+       NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+       NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+       NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+       NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+       NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+       NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */
+       NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */
+
+       /* kelvin */
+       if (dev_priv->chipset < 0x25)
+               NVOBJ_CLASS(dev, 0x0097, GR);
+       else
+               NVOBJ_CLASS(dev, 0x0597, GR);
+
+       dev_priv->engine.graph.registered = true;
+       return 0;
+}
+
+static int
+nv30_graph_register(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->engine.graph.registered)
+               return 0;
+
+       NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+       NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+       NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+       NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+       NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+       NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+       NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */
+       NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+       NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */
+       NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+       NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */
+       NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+       NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+       NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+       NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+       NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+       NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */
+
+       /* rankine */
+       if (0x00000003 & (1 << (dev_priv->chipset & 0x0f)))
+               NVOBJ_CLASS(dev, 0x0397, GR);
+       else
+       if (0x00000010 & (1 << (dev_priv->chipset & 0x0f)))
+               NVOBJ_CLASS(dev, 0x0697, GR);
+       else
+       if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f)))
+               NVOBJ_CLASS(dev, 0x0497, GR);
+
+       dev_priv->engine.graph.registered = true;
+       return 0;
+}
index 70d957895ceaa91832e6f6b003312ca6fd49864d..b9361e28687c7dbc0dabea5ee00f83de0e6e2a28 100644 (file)
@@ -29,6 +29,8 @@
 #include "nouveau_drv.h"
 #include "nouveau_grctx.h"
 
+static int nv40_graph_register(struct drm_device *);
+
 struct nouveau_channel *
 nv40_graph_channel(struct drm_device *dev)
 {
@@ -248,7 +250,7 @@ nv40_graph_init(struct drm_device *dev)
        struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
        struct nouveau_grctx ctx = {};
        uint32_t vramsz, *cp;
-       int i, j;
+       int ret, i, j;
 
        nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
                        ~NV_PMC_ENABLE_PGRAPH);
@@ -272,6 +274,10 @@ nv40_graph_init(struct drm_device *dev)
 
        kfree(cp);
 
+       ret = nv40_graph_register(dev);
+       if (ret)
+               return ret;
+
        /* No context present currently */
        nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
 
@@ -408,25 +414,38 @@ void nv40_graph_takedown(struct drm_device *dev)
 {
 }
 
-struct nouveau_pgraph_object_class nv40_graph_grclass[] = {
-       { 0x506e, NVOBJ_ENGINE_SW, NULL }, /* nvsw */
-       { 0x0030, NVOBJ_ENGINE_GR, NULL }, /* null */
-       { 0x0039, NVOBJ_ENGINE_GR, NULL }, /* m2mf */
-       { 0x004a, NVOBJ_ENGINE_GR, NULL }, /* gdirect */
-       { 0x009f, NVOBJ_ENGINE_GR, NULL }, /* imageblit (nv12) */
-       { 0x008a, NVOBJ_ENGINE_GR, NULL }, /* ifc */
-       { 0x0089, NVOBJ_ENGINE_GR, NULL }, /* sifm */
-       { 0x3089, NVOBJ_ENGINE_GR, NULL }, /* sifm (nv40) */
-       { 0x0062, NVOBJ_ENGINE_GR, NULL }, /* surf2d */
-       { 0x3062, NVOBJ_ENGINE_GR, NULL }, /* surf2d (nv40) */
-       { 0x0043, NVOBJ_ENGINE_GR, NULL }, /* rop */
-       { 0x0012, NVOBJ_ENGINE_GR, NULL }, /* beta1 */
-       { 0x0072, NVOBJ_ENGINE_GR, NULL }, /* beta4 */
-       { 0x0019, NVOBJ_ENGINE_GR, NULL }, /* cliprect */
-       { 0x0044, NVOBJ_ENGINE_GR, NULL }, /* pattern */
-       { 0x309e, NVOBJ_ENGINE_GR, NULL }, /* swzsurf */
-       { 0x4097, NVOBJ_ENGINE_GR, NULL }, /* curie (nv40) */
-       { 0x4497, NVOBJ_ENGINE_GR, NULL }, /* curie (nv44) */
-       {}
-};
+static int
+nv40_graph_register(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->engine.graph.registered)
+               return 0;
 
+       NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+       NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+       NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+       NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+       NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+       NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+       NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+       NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */
+       NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+       NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */
+       NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+       NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+       NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+       NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+       NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+       NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */
+
+       /* curie */
+       if (dev_priv->chipset >= 0x60 ||
+           0x00005450 & (1 << (dev_priv->chipset & 0x0f)))
+               NVOBJ_CLASS(dev, 0x4497, GR);
+       else
+               NVOBJ_CLASS(dev, 0x4097, GR);
+
+       dev_priv->engine.graph.registered = true;
+       return 0;
+}
index 01a598917e3c5d53284d8fe82fcfca9737512fd1..84ca90e91811044c508156b6dbc9c3baadb5b2f4 100644 (file)
@@ -30,6 +30,8 @@
 #include "nouveau_ramht.h"
 #include "nouveau_grctx.h"
 
+static int nv50_graph_register(struct drm_device *);
+
 static void
 nv50_graph_init_reset(struct drm_device *dev)
 {
@@ -145,12 +147,15 @@ nv50_graph_init(struct drm_device *dev)
        nv50_graph_init_reset(dev);
        nv50_graph_init_regs__nv(dev);
        nv50_graph_init_regs(dev);
-       nv50_graph_init_intr(dev);
 
        ret = nv50_graph_init_ctxctl(dev);
        if (ret)
                return ret;
 
+       ret = nv50_graph_register(dev);
+       if (ret)
+               return ret;
+       nv50_graph_init_intr(dev);
        return 0;
 }
 
@@ -333,8 +338,8 @@ nv50_graph_context_switch(struct drm_device *dev)
 }
 
 static int
-nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass,
-                          int mthd, uint32_t data)
+nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan,
+                          u32 class, u32 mthd, u32 data)
 {
        struct nouveau_gpuobj *gpuobj;
 
@@ -351,8 +356,8 @@ nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass,
-                             int mthd, uint32_t data)
+nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan,
+                             u32 class, u32 mthd, u32 data)
 {
        if (nouveau_notifier_offset(chan->nvsw.vblsem, &data))
                return -ERANGE;
@@ -362,16 +367,16 @@ nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass,
 }
 
 static int
-nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass,
-                                  int mthd, uint32_t data)
+nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan,
+                                  u32 class, u32 mthd, u32 data)
 {
        chan->nvsw.vblsem_rval = data;
        return 0;
 }
 
 static int
-nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass,
-                              int mthd, uint32_t data)
+nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan,
+                              u32 class, u32 mthd, u32 data)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -392,27 +397,53 @@ nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass,
        return 0;
 }
 
-static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = {
-       { 0x018c, nv50_graph_nvsw_dma_vblsem },
-       { 0x0400, nv50_graph_nvsw_vblsem_offset },
-       { 0x0404, nv50_graph_nvsw_vblsem_release_val },
-       { 0x0408, nv50_graph_nvsw_vblsem_release },
-       {}
-};
-
-struct nouveau_pgraph_object_class nv50_graph_grclass[] = {
-       { 0x506e, NVOBJ_ENGINE_SW, nv50_graph_nvsw_methods }, /* nvsw */
-       { 0x0030, NVOBJ_ENGINE_GR, NULL }, /* null */
-       { 0x5039, NVOBJ_ENGINE_GR, NULL }, /* m2mf */
-       { 0x502d, NVOBJ_ENGINE_GR, NULL }, /* 2d */
-       { 0x50c0, NVOBJ_ENGINE_GR, NULL }, /* compute */
-       { 0x85c0, NVOBJ_ENGINE_GR, NULL }, /* compute (nva3, nva5, nva8) */
-       { 0x5097, NVOBJ_ENGINE_GR, NULL }, /* tesla (nv50) */
-       { 0x8297, NVOBJ_ENGINE_GR, NULL }, /* tesla (nv8x/nv9x) */
-       { 0x8397, NVOBJ_ENGINE_GR, NULL }, /* tesla (nva0, nvaa, nvac) */
-       { 0x8597, NVOBJ_ENGINE_GR, NULL }, /* tesla (nva3, nva5, nva8) */
-       {}
-};
+static int
+nv50_graph_register(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->engine.graph.registered)
+               return 0;
+
+       NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+       NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem);
+       NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset);
+       NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val);
+       NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release);
+
+       NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+       NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */
+       NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */
+       NVOBJ_CLASS(dev, 0x50c0, GR); /* compute */
+       NVOBJ_CLASS(dev, 0x85c0, GR); /* compute (nva3, nva5, nva8) */
+
+       /* tesla */
+       if (dev_priv->chipset == 0x50)
+               NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */
+       else
+       if (dev_priv->chipset < 0xa0)
+               NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */
+       else {
+               switch (dev_priv->chipset) {
+               case 0xa0:
+               case 0xaa:
+               case 0xac:
+                       NVOBJ_CLASS(dev, 0x8397, GR);
+                       break;
+               case 0xa3:
+               case 0xa5:
+               case 0xa8:
+                       NVOBJ_CLASS(dev, 0x8597, GR);
+                       break;
+               case 0xaf:
+                       NVOBJ_CLASS(dev, 0x8697, GR);
+                       break;
+               }
+       }
+
+       dev_priv->engine.graph.registered = true;
+       return 0;
+}
 
 void
 nv50_graph_tlb_flush(struct drm_device *dev)