#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>
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
.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 },
{}
};
*pobject = NULL;
return -EBUSY;
}
+ chan->fifo = nvkm_fifo_chan(parent);
mpeg->chan = chan;
spin_unlock_irqrestore(&nv_engine(mpeg)->lock, flags);
return 0;
{
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);
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 */
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);
}
}
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
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;
#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
* 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);
/* only allow linear DMA objects */
if (!(dma0 & 0x00002000))
- return -EINVAL;
+ return false;
if (mthd == 0x0190) {
/* DMA_CMD */
} 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 },
{}
};
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;
#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,
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);
.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,
* 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 */
}
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);
}
}
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
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);
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;