Loading drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +38 −38 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading @@ -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 }, {} }; Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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 */ Loading @@ -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); } } Loading @@ -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 Loading @@ -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; Loading drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h +3 −0 Original line number Diff line number Diff line #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 drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c +8 −17 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 */ Loading @@ -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 }, {} }; Loading Loading @@ -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; Loading drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +69 −21 Original line number Diff line number Diff line Loading @@ -24,24 +24,47 @@ #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, Loading @@ -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); Loading Loading @@ -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, Loading @@ -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 */ Loading @@ -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); } } Loading @@ -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 Loading @@ -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); Loading @@ -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; Loading Loading
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +38 −38 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading @@ -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 }, {} }; Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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 */ Loading @@ -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); } } Loading @@ -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 Loading @@ -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; Loading
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h +3 −0 Original line number Diff line number Diff line #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
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv40.c +8 −17 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 */ Loading @@ -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 }, {} }; Loading Loading @@ -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; Loading
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +69 −21 Original line number Diff line number Diff line Loading @@ -24,24 +24,47 @@ #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, Loading @@ -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); Loading Loading @@ -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, Loading @@ -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 */ Loading @@ -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); } } Loading @@ -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 Loading @@ -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); Loading @@ -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; Loading