OSDN Git Service

drm/nouveau/mpeg: remove dependence on namedb/engctx lookup
authorBen Skeggs <bskeggs@redhat.com>
Thu, 20 Aug 2015 04:54:18 +0000 (14:54 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 28 Aug 2015 02:40:39 +0000 (12:40 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c

index 0f02b28..05597f2 100644 (file)
@@ -24,9 +24,6 @@
 #include "nv31.h"
 
 #include <core/client.h>
-#include <core/handle.h>
-#include <engine/fifo.h>
-#include <subdev/instmem.h>
 #include <subdev/fb.h>
 #include <subdev/timer.h>
 
@@ -58,44 +55,58 @@ nv31_mpeg_object_ctor(struct nvkm_object *parent,
        return 0;
 }
 
-static int
-nv31_mpeg_mthd_dma(struct nvkm_object *object, u32 mthd, void *arg, u32 len)
+static bool
+nv31_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data)
 {
-       struct nv31_mpeg *mpeg = (void *)object->engine;
-       struct nvkm_device *device = mpeg->base.engine.subdev.device;
-       struct nvkm_instmem *imem = device->imem;
-       u32 inst = *(u32 *)arg << 4;
-       u32 dma0 = imem->func->rd32(imem, inst + 0);
-       u32 dma1 = imem->func->rd32(imem, inst + 4);
-       u32 dma2 = imem->func->rd32(imem, inst + 8);
+       u32 inst = data << 4;
+       u32 dma0 = nvkm_rd32(device, 0x700000 + inst);
+       u32 dma1 = nvkm_rd32(device, 0x700004 + inst);
+       u32 dma2 = nvkm_rd32(device, 0x700008 + inst);
        u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
        u32 size = dma1 + 1;
 
        /* only allow linear DMA objects */
        if (!(dma0 & 0x00002000))
-               return -EINVAL;
+               return false;
 
        if (mthd == 0x0190) {
                /* DMA_CMD */
-               nvkm_mask(device, 0x00b300, 0x00010000, (dma0 & 0x00030000) ? 0x00010000 : 0);
+               nvkm_mask(device, 0x00b300, 0x00010000,
+                                 (dma0 & 0x00030000) ? 0x00010000 : 0);
                nvkm_wr32(device, 0x00b334, base);
                nvkm_wr32(device, 0x00b324, size);
        } else
        if (mthd == 0x01a0) {
                /* DMA_DATA */
-               nvkm_mask(device, 0x00b300, 0x00020000, (dma0 & 0x00030000) ? 0x00020000 : 0);
+               nvkm_mask(device, 0x00b300, 0x00020000,
+                                 (dma0 & 0x00030000) ? 0x00020000 : 0);
                nvkm_wr32(device, 0x00b360, base);
                nvkm_wr32(device, 0x00b364, size);
        } else {
                /* DMA_IMAGE, VRAM only */
                if (dma0 & 0x00030000)
-                       return -EINVAL;
+                       return false;
 
                nvkm_wr32(device, 0x00b370, base);
                nvkm_wr32(device, 0x00b374, size);
        }
 
-       return 0;
+       return true;
+}
+
+static bool
+nv31_mpeg_mthd(struct nv31_mpeg *mpeg, u32 mthd, u32 data)
+{
+       struct nvkm_device *device = mpeg->base.engine.subdev.device;
+       switch (mthd) {
+       case 0x190:
+       case 0x1a0:
+       case 0x1b0:
+               return mpeg->mthd_dma(device, mthd, data);
+       default:
+               break;
+       }
+       return false;
 }
 
 struct nvkm_ofuncs
@@ -108,17 +119,9 @@ nv31_mpeg_ofuncs = {
        .wr32 = _nvkm_gpuobj_wr32,
 };
 
-static struct nvkm_omthds
-nv31_mpeg_omthds[] = {
-       { 0x0190, 0x0190, nv31_mpeg_mthd_dma },
-       { 0x01a0, 0x01a0, nv31_mpeg_mthd_dma },
-       { 0x01b0, 0x01b0, nv31_mpeg_mthd_dma },
-       {}
-};
-
 struct nvkm_oclass
 nv31_mpeg_sclass[] = {
-       { 0x3174, &nv31_mpeg_ofuncs, nv31_mpeg_omthds },
+       { 0x3174, &nv31_mpeg_ofuncs },
        {}
 };
 
@@ -149,6 +152,7 @@ nv31_mpeg_context_ctor(struct nvkm_object *parent,
                *pobject = NULL;
                return -EBUSY;
        }
+       chan->fifo = nvkm_fifo_chan(parent);
        mpeg->chan = chan;
        spin_unlock_irqrestore(&nv_engine(mpeg)->lock, flags);
        return 0;
@@ -199,9 +203,6 @@ nv31_mpeg_intr(struct nvkm_subdev *subdev)
 {
        struct nv31_mpeg *mpeg = (void *)subdev;
        struct nvkm_device *device = mpeg->base.engine.subdev.device;
-       struct nvkm_fifo *fifo = device->fifo;
-       struct nvkm_handle *handle;
-       struct nvkm_object *engctx;
        u32 stat = nvkm_rd32(device, 0x00b100);
        u32 type = nvkm_rd32(device, 0x00b230);
        u32 mthd = nvkm_rd32(device, 0x00b234);
@@ -209,8 +210,7 @@ nv31_mpeg_intr(struct nvkm_subdev *subdev)
        u32 show = stat;
        unsigned long flags;
 
-       spin_lock_irqsave(&nv_engine(mpeg)->lock, flags);
-       engctx = nv_object(mpeg->chan);
+       spin_lock_irqsave(&mpeg->base.engine.lock, flags);
 
        if (stat & 0x01000000) {
                /* happens on initial binding of the object */
@@ -219,11 +219,9 @@ nv31_mpeg_intr(struct nvkm_subdev *subdev)
                        show &= ~0x01000000;
                }
 
-               if (type == 0x00000010 && engctx) {
-                       handle = nvkm_handle_get_class(engctx, 0x3174);
-                       if (handle && !nv_call(handle->object, mthd, data))
+               if (type == 0x00000010) {
+                       if (!nv31_mpeg_mthd(mpeg, mthd, data))
                                show &= ~0x01000000;
-                       nvkm_handle_put(handle);
                }
        }
 
@@ -232,11 +230,12 @@ nv31_mpeg_intr(struct nvkm_subdev *subdev)
 
        if (show) {
                nvkm_error(subdev, "ch %d [%s] %08x %08x %08x %08x\n",
-                          fifo->chid(fifo, engctx),
-                          nvkm_client_name(engctx), stat, type, mthd, data);
+                          mpeg->chan ? mpeg->chan->fifo->chid : -1,
+                          nvkm_client_name(mpeg->chan),
+                          stat, type, mthd, data);
        }
 
-       spin_unlock_irqrestore(&nv_engine(mpeg)->lock, flags);
+       spin_unlock_irqrestore(&mpeg->base.engine.lock, flags);
 }
 
 static int
@@ -252,6 +251,7 @@ nv31_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       mpeg->mthd_dma = nv31_mpeg_mthd_dma;
        nv_subdev(mpeg)->unit = 0x00000002;
        nv_subdev(mpeg)->intr = nv31_mpeg_intr;
        nv_engine(mpeg)->cclass = &nv31_mpeg_cclass;
index 022a98e..6bdd409 100644 (file)
@@ -1,13 +1,16 @@
 #ifndef __NV31_MPEG_H__
 #define __NV31_MPEG_H__
 #include <engine/mpeg.h>
+#include <engine/fifo.h>
 
 struct nv31_mpeg_chan {
        struct nvkm_object base;
+       struct nvkm_fifo_chan *fifo;
 };
 
 struct nv31_mpeg {
        struct nvkm_mpeg base;
        struct nv31_mpeg_chan *chan;
+       bool (*mthd_dma)(struct nvkm_device *, u32 mthd, u32 data);
 };
 #endif
index 7c009c3..cc167dc 100644 (file)
  * MPEG object classes
  ******************************************************************************/
 
-static int
-nv40_mpeg_mthd_dma(struct nvkm_object *object, u32 mthd, void *arg, u32 len)
+bool
+nv40_mpeg_mthd_dma(struct nvkm_device *device, u32 mthd, u32 data)
 {
-       struct nv31_mpeg *mpeg = (void *)object->engine;
-       struct nvkm_device *device = mpeg->base.engine.subdev.device;
        struct nvkm_instmem *imem = device->imem;
-       u32 inst = *(u32 *)arg << 4;
+       u32 inst = data << 4;
        u32 dma0 = imem->func->rd32(imem, inst + 0);
        u32 dma1 = imem->func->rd32(imem, inst + 4);
        u32 dma2 = imem->func->rd32(imem, inst + 8);
@@ -44,7 +42,7 @@ nv40_mpeg_mthd_dma(struct nvkm_object *object, u32 mthd, void *arg, u32 len)
 
        /* only allow linear DMA objects */
        if (!(dma0 & 0x00002000))
-               return -EINVAL;
+               return false;
 
        if (mthd == 0x0190) {
                /* DMA_CMD */
@@ -60,26 +58,18 @@ nv40_mpeg_mthd_dma(struct nvkm_object *object, u32 mthd, void *arg, u32 len)
        } else {
                /* DMA_IMAGE, VRAM only */
                if (dma0 & 0x00030000)
-                       return -EINVAL;
+                       return false;
 
                nvkm_wr32(device, 0x00b370, base);
                nvkm_wr32(device, 0x00b374, size);
        }
 
-       return 0;
+       return true;
 }
 
-static struct nvkm_omthds
-nv40_mpeg_omthds[] = {
-       { 0x0190, 0x0190, nv40_mpeg_mthd_dma },
-       { 0x01a0, 0x01a0, nv40_mpeg_mthd_dma },
-       { 0x01b0, 0x01b0, nv40_mpeg_mthd_dma },
-       {}
-};
-
 struct nvkm_oclass
 nv40_mpeg_sclass[] = {
-       { 0x3174, &nv31_mpeg_ofuncs, nv40_mpeg_omthds },
+       { 0x3174, &nv31_mpeg_ofuncs },
        {}
 };
 
@@ -116,6 +106,7 @@ nv40_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       mpeg->mthd_dma = nv40_mpeg_mthd_dma;
        nv_subdev(mpeg)->unit = 0x00000002;
        nv_subdev(mpeg)->intr = nv40_mpeg_intr;
        nv_engine(mpeg)->cclass = &nv31_mpeg_cclass;
index 9393667..1223bad 100644 (file)
 #include <engine/mpeg.h>
 
 #include <core/client.h>
-#include <core/handle.h>
 #include <engine/fifo.h>
 
+struct nv44_mpeg {
+       struct nvkm_mpeg base;
+       struct list_head chan;
+};
+
 struct nv44_mpeg_chan {
        struct nvkm_mpeg_chan base;
+       struct nvkm_fifo_chan *fifo;
+       u32 inst;
+       struct list_head head;
 };
 
+bool nv40_mpeg_mthd_dma(struct nvkm_device *, u32, u32);
+
 /*******************************************************************************
  * PMPEG context
  ******************************************************************************/
 
+static void
+nv44_mpeg_context_dtor(struct nvkm_object *object)
+{
+       struct nv44_mpeg_chan *chan = (void *)object;
+       struct nv44_mpeg *mpeg = (void *)object->engine;
+       unsigned long flags;
+       spin_lock_irqsave(&mpeg->base.engine.lock, flags);
+       list_del(&chan->head);
+       spin_unlock_irqrestore(&mpeg->base.engine.lock, flags);
+       nvkm_mpeg_context_destroy(&chan->base);
+}
+
 static int
 nv44_mpeg_context_ctor(struct nvkm_object *parent,
                       struct nvkm_object *engine,
                       struct nvkm_oclass *oclass, void *data, u32 size,
                       struct nvkm_object **pobject)
 {
+       struct nv44_mpeg *mpeg = (void *)engine;
        struct nv44_mpeg_chan *chan;
+       unsigned long flags;
        int ret;
 
        ret = nvkm_mpeg_context_create(parent, engine, oclass, NULL, 264 * 4,
@@ -50,6 +73,12 @@ nv44_mpeg_context_ctor(struct nvkm_object *parent,
        if (ret)
                return ret;
 
+       spin_lock_irqsave(&mpeg->base.engine.lock, flags);
+       chan->fifo = nvkm_fifo_chan(parent);
+       chan->inst = chan->base.base.gpuobj.addr;
+       list_add(&chan->head, &mpeg->chan);
+       spin_unlock_irqrestore(&mpeg->base.engine.lock, flags);
+
        nvkm_kmap(&chan->base.base.gpuobj);
        nvkm_wo32(&chan->base.base.gpuobj, 0x78, 0x02001ec1);
        nvkm_done(&chan->base.base.gpuobj);
@@ -77,7 +106,7 @@ nv44_mpeg_cclass = {
        .handle = NV_ENGCTX(MPEG, 0x44),
        .ofuncs = &(struct nvkm_ofuncs) {
                .ctor = nv44_mpeg_context_ctor,
-               .dtor = _nvkm_mpeg_context_dtor,
+               .dtor = nv44_mpeg_context_dtor,
                .init = _nvkm_mpeg_context_init,
                .fini = nv44_mpeg_context_fini,
                .rd32 = _nvkm_mpeg_context_rd32,
@@ -89,25 +118,45 @@ nv44_mpeg_cclass = {
  * PMPEG engine/subdev functions
  ******************************************************************************/
 
+static bool
+nv44_mpeg_mthd(struct nvkm_device *device, u32 mthd, u32 data)
+{
+       switch (mthd) {
+       case 0x190:
+       case 0x1a0:
+       case 0x1b0:
+               return nv40_mpeg_mthd_dma(device, mthd, data);
+       default:
+               break;
+       }
+       return false;
+}
+
 static void
 nv44_mpeg_intr(struct nvkm_subdev *subdev)
 {
-       struct nvkm_mpeg *mpeg = (void *)subdev;
-       struct nvkm_device *device = mpeg->engine.subdev.device;
-       struct nvkm_fifo *fifo = device->fifo;
-       struct nvkm_engine *engine = nv_engine(subdev);
-       struct nvkm_object *engctx;
-       struct nvkm_handle *handle;
+       struct nv44_mpeg *mpeg = (void *)subdev;
+       struct nv44_mpeg_chan *temp, *chan = NULL;
+       struct nvkm_device *device = mpeg->base.engine.subdev.device;
+       unsigned long flags;
        u32 inst = nvkm_rd32(device, 0x00b318) & 0x000fffff;
        u32 stat = nvkm_rd32(device, 0x00b100);
        u32 type = nvkm_rd32(device, 0x00b230);
        u32 mthd = nvkm_rd32(device, 0x00b234);
        u32 data = nvkm_rd32(device, 0x00b238);
        u32 show = stat;
-       int chid;
-
-       engctx = nvkm_engctx_get(engine, inst);
-       chid   = fifo->chid(fifo, engctx);
+       int chid = -1;
+
+       spin_lock_irqsave(&mpeg->base.engine.lock, flags);
+       list_for_each_entry(temp, &mpeg->chan, head) {
+               if (temp->inst >> 4 == inst) {
+                       chan = temp;
+                       chid = chan->fifo->chid;
+                       list_del(&chan->head);
+                       list_add(&chan->head, &mpeg->chan);
+                       break;
+               }
+       }
 
        if (stat & 0x01000000) {
                /* happens on initial binding of the object */
@@ -117,10 +166,8 @@ nv44_mpeg_intr(struct nvkm_subdev *subdev)
                }
 
                if (type == 0x00000010) {
-                       handle = nvkm_handle_get_class(engctx, 0x3174);
-                       if (handle && !nv_call(handle->object, mthd, data))
+                       if (!nv44_mpeg_mthd(subdev->device, mthd, data))
                                show &= ~0x01000000;
-                       nvkm_handle_put(handle);
                }
        }
 
@@ -128,13 +175,12 @@ nv44_mpeg_intr(struct nvkm_subdev *subdev)
        nvkm_wr32(device, 0x00b230, 0x00000001);
 
        if (show) {
-               nvkm_error(subdev,
-                          "ch %d [%08x %s] %08x %08x %08x %08x\n",
-                          chid, inst << 4, nvkm_client_name(engctx), stat,
-                          type, mthd, data);
+               nvkm_error(subdev, "ch %d [%08x %s] %08x %08x %08x %08x\n",
+                          chid, inst << 4, nvkm_client_name(chan),
+                          stat, type, mthd, data);
        }
 
-       nvkm_engctx_put(engctx);
+       spin_unlock_irqrestore(&mpeg->base.engine.lock, flags);
 }
 
 static void
@@ -158,7 +204,7 @@ nv44_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
               struct nvkm_oclass *oclass, void *data, u32 size,
               struct nvkm_object **pobject)
 {
-       struct nvkm_mpeg *mpeg;
+       struct nv44_mpeg *mpeg;
        int ret;
 
        ret = nvkm_mpeg_create(parent, engine, oclass, &mpeg);
@@ -166,6 +212,8 @@ nv44_mpeg_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       INIT_LIST_HEAD(&mpeg->chan);
+
        nv_subdev(mpeg)->unit = 0x00000002;
        nv_subdev(mpeg)->intr = nv44_mpeg_me_intr;
        nv_engine(mpeg)->cclass = &nv44_mpeg_cclass;