From 590801c1a3b19883b0d0e4c60241cbed8a916d47 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 20 Aug 2015 14:54:18 +1000 Subject: [PATCH] drm/nouveau/mpeg: remove dependence on namedb/engctx lookup Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c | 76 ++++++++++----------- drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h | 3 + drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c | 25 +++---- drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c | 90 +++++++++++++++++++------ 4 files changed, 118 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c index 0f02b28..05597f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c @@ -24,9 +24,6 @@ #include "nv31.h" #include -#include -#include -#include #include #include @@ -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; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h index 022a98e6..6bdd409 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h @@ -1,13 +1,16 @@ #ifndef __NV31_MPEG_H__ #define __NV31_MPEG_H__ #include +#include 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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c index 7c009c3..cc167dc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c @@ -29,13 +29,11 @@ * 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; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c index 9393667..1223bad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c @@ -24,24 +24,47 @@ #include #include -#include #include +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; -- 2.7.4