drm/nve0/fifo: support engine selection when creating fifo channels
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
@@ -182,7 +182,7 @@ nv50_fifo_chan_ctor(struct nouveau_object *parent,
|
|||||||
struct nouveau_oclass *oclass, void *data, u32 size,
|
struct nouveau_oclass *oclass, void *data, u32 size,
|
||||||
struct nouveau_object **pobject)
|
struct nouveau_object **pobject)
|
||||||
{
|
{
|
||||||
struct nv_channel_ind_class *args = data;
|
struct nv50_channel_ind_class *args = data;
|
||||||
struct nouveau_bar *bar = nouveau_bar(parent);
|
struct nouveau_bar *bar = nouveau_bar(parent);
|
||||||
struct nv50_fifo_base *base = (void *)parent;
|
struct nv50_fifo_base *base = (void *)parent;
|
||||||
struct nv50_fifo_chan *chan;
|
struct nv50_fifo_chan *chan;
|
||||||
|
@@ -150,7 +150,7 @@ nv84_fifo_chan_ctor(struct nouveau_object *parent,
|
|||||||
struct nouveau_bar *bar = nouveau_bar(parent);
|
struct nouveau_bar *bar = nouveau_bar(parent);
|
||||||
struct nv50_fifo_base *base = (void *)parent;
|
struct nv50_fifo_base *base = (void *)parent;
|
||||||
struct nv50_fifo_chan *chan;
|
struct nv50_fifo_chan *chan;
|
||||||
struct nv_channel_ind_class *args = data;
|
struct nv50_channel_ind_class *args = data;
|
||||||
u64 ioffset, ilength;
|
u64 ioffset, ilength;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@@ -163,7 +163,7 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
|
|||||||
struct nvc0_fifo_priv *priv = (void *)engine;
|
struct nvc0_fifo_priv *priv = (void *)engine;
|
||||||
struct nvc0_fifo_base *base = (void *)parent;
|
struct nvc0_fifo_base *base = (void *)parent;
|
||||||
struct nvc0_fifo_chan *chan;
|
struct nvc0_fifo_chan *chan;
|
||||||
struct nv_channel_ind_class *args = data;
|
struct nv50_channel_ind_class *args = data;
|
||||||
u64 usermem, ioffset, ilength;
|
u64 usermem, ioffset, ilength;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
@@ -38,6 +38,22 @@
|
|||||||
#include <engine/dmaobj.h>
|
#include <engine/dmaobj.h>
|
||||||
#include <engine/fifo.h>
|
#include <engine/fifo.h>
|
||||||
|
|
||||||
|
#define _(a,b) { (a), ((1 << (a)) | (b)) }
|
||||||
|
static const struct {
|
||||||
|
int subdev;
|
||||||
|
u32 mask;
|
||||||
|
} fifo_engine[] = {
|
||||||
|
_(NVDEV_ENGINE_GR , (1 << NVDEV_ENGINE_SW)),
|
||||||
|
_(NVDEV_ENGINE_VP , 0),
|
||||||
|
_(NVDEV_ENGINE_PPP , 0),
|
||||||
|
_(NVDEV_ENGINE_BSP , 0),
|
||||||
|
_(NVDEV_ENGINE_COPY0 , 0),
|
||||||
|
_(NVDEV_ENGINE_COPY1 , 0),
|
||||||
|
_(NVDEV_ENGINE_VENC , 0),
|
||||||
|
};
|
||||||
|
#undef _
|
||||||
|
#define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
|
||||||
|
|
||||||
struct nve0_fifo_engn {
|
struct nve0_fifo_engn {
|
||||||
struct nouveau_gpuobj *playlist[2];
|
struct nouveau_gpuobj *playlist[2];
|
||||||
int cur_playlist;
|
int cur_playlist;
|
||||||
@@ -45,7 +61,7 @@ struct nve0_fifo_engn {
|
|||||||
|
|
||||||
struct nve0_fifo_priv {
|
struct nve0_fifo_priv {
|
||||||
struct nouveau_fifo base;
|
struct nouveau_fifo base;
|
||||||
struct nve0_fifo_engn engine[16];
|
struct nve0_fifo_engn engine[FIFO_ENGINE_NR];
|
||||||
struct {
|
struct {
|
||||||
struct nouveau_gpuobj *mem;
|
struct nouveau_gpuobj *mem;
|
||||||
struct nouveau_vma bar;
|
struct nouveau_vma bar;
|
||||||
@@ -119,7 +135,9 @@ nve0_fifo_context_attach(struct nouveau_object *parent,
|
|||||||
|
|
||||||
switch (nv_engidx(object->engine)) {
|
switch (nv_engidx(object->engine)) {
|
||||||
case NVDEV_ENGINE_SW : return 0;
|
case NVDEV_ENGINE_SW : return 0;
|
||||||
case NVDEV_ENGINE_GR : addr = 0x0210; break;
|
case NVDEV_ENGINE_GR :
|
||||||
|
case NVDEV_ENGINE_COPY0:
|
||||||
|
case NVDEV_ENGINE_COPY1: addr = 0x0210; break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -149,7 +167,9 @@ nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend,
|
|||||||
|
|
||||||
switch (nv_engidx(object->engine)) {
|
switch (nv_engidx(object->engine)) {
|
||||||
case NVDEV_ENGINE_SW : return 0;
|
case NVDEV_ENGINE_SW : return 0;
|
||||||
case NVDEV_ENGINE_GR : addr = 0x0210; break;
|
case NVDEV_ENGINE_GR :
|
||||||
|
case NVDEV_ENGINE_COPY0:
|
||||||
|
case NVDEV_ENGINE_COPY1: addr = 0x0210; break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -178,24 +198,36 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent,
|
|||||||
struct nve0_fifo_priv *priv = (void *)engine;
|
struct nve0_fifo_priv *priv = (void *)engine;
|
||||||
struct nve0_fifo_base *base = (void *)parent;
|
struct nve0_fifo_base *base = (void *)parent;
|
||||||
struct nve0_fifo_chan *chan;
|
struct nve0_fifo_chan *chan;
|
||||||
struct nv_channel_ind_class *args = data;
|
struct nve0_channel_ind_class *args = data;
|
||||||
u64 usermem, ioffset, ilength;
|
u64 usermem, ioffset, ilength;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
if (size < sizeof(*args))
|
if (size < sizeof(*args))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < FIFO_ENGINE_NR; i++) {
|
||||||
|
if (args->engine & (1 << i)) {
|
||||||
|
if (nouveau_engine(parent, fifo_engine[i].subdev)) {
|
||||||
|
args->engine = (1 << i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == FIFO_ENGINE_NR)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
|
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
|
||||||
priv->user.bar.offset, 0x200,
|
priv->user.bar.offset, 0x200,
|
||||||
args->pushbuf,
|
args->pushbuf,
|
||||||
(1 << NVDEV_ENGINE_SW) |
|
fifo_engine[i].mask, &chan);
|
||||||
(1 << NVDEV_ENGINE_GR), &chan);
|
|
||||||
*pobject = nv_object(chan);
|
*pobject = nv_object(chan);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
nv_parent(chan)->context_attach = nve0_fifo_context_attach;
|
nv_parent(chan)->context_attach = nve0_fifo_context_attach;
|
||||||
nv_parent(chan)->context_detach = nve0_fifo_context_detach;
|
nv_parent(chan)->context_detach = nve0_fifo_context_detach;
|
||||||
|
chan->engine = i;
|
||||||
|
|
||||||
usermem = chan->base.chid * 0x200;
|
usermem = chan->base.chid * 0x200;
|
||||||
ioffset = args->ioffset;
|
ioffset = args->ioffset;
|
||||||
@@ -235,6 +267,7 @@ nve0_fifo_chan_init(struct nouveau_object *object)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
|
||||||
nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
|
nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
|
||||||
nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
|
nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
|
||||||
nve0_fifo_playlist_update(priv, chan->engine);
|
nve0_fifo_playlist_update(priv, chan->engine);
|
||||||
|
@@ -65,13 +65,30 @@ struct nv_channel_dma_class {
|
|||||||
/* 506f: NV50_CHANNEL_IND
|
/* 506f: NV50_CHANNEL_IND
|
||||||
* 826f: NV84_CHANNEL_IND
|
* 826f: NV84_CHANNEL_IND
|
||||||
* 906f: NVC0_CHANNEL_IND
|
* 906f: NVC0_CHANNEL_IND
|
||||||
* a06f: NVE0_CHANNEL_IND
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct nv_channel_ind_class {
|
struct nv50_channel_ind_class {
|
||||||
u32 pushbuf;
|
u32 pushbuf;
|
||||||
u32 ilength;
|
u32 ilength;
|
||||||
u64 ioffset;
|
u64 ioffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* a06f: NVE0_CHANNEL_IND
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NVE0_CHANNEL_IND_ENGINE_GR 0x00000001
|
||||||
|
#define NVE0_CHANNEL_IND_ENGINE_VP 0x00000002
|
||||||
|
#define NVE0_CHANNEL_IND_ENGINE_PPP 0x00000004
|
||||||
|
#define NVE0_CHANNEL_IND_ENGINE_BSP 0x00000008
|
||||||
|
#define NVE0_CHANNEL_IND_ENGINE_CE0 0x00000010
|
||||||
|
#define NVE0_CHANNEL_IND_ENGINE_CE1 0x00000020
|
||||||
|
#define NVE0_CHANNEL_IND_ENGINE_ENC 0x00000040
|
||||||
|
|
||||||
|
struct nve0_channel_ind_class {
|
||||||
|
u32 pushbuf;
|
||||||
|
u32 ilength;
|
||||||
|
u64 ioffset;
|
||||||
|
u32 engine;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -36,7 +36,7 @@ enum nv_subdev_type {
|
|||||||
NVDEV_ENGINE_COPY0,
|
NVDEV_ENGINE_COPY0,
|
||||||
NVDEV_ENGINE_COPY1,
|
NVDEV_ENGINE_COPY1,
|
||||||
NVDEV_ENGINE_UNK1C1,
|
NVDEV_ENGINE_UNK1C1,
|
||||||
NVDEV_ENGINE_FENCE,
|
NVDEV_ENGINE_VENC,
|
||||||
NVDEV_ENGINE_DISP,
|
NVDEV_ENGINE_DISP,
|
||||||
NVDEV_SUBDEV_NR,
|
NVDEV_SUBDEV_NR,
|
||||||
};
|
};
|
||||||
|
@@ -188,7 +188,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli,
|
|||||||
{
|
{
|
||||||
static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 };
|
static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 };
|
||||||
const u16 *oclass = oclasses;
|
const u16 *oclass = oclasses;
|
||||||
struct nv_channel_ind_class args;
|
struct nve0_channel_ind_class args;
|
||||||
struct nouveau_channel *chan;
|
struct nouveau_channel *chan;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -202,6 +202,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli,
|
|||||||
args.pushbuf = chan->push.handle;
|
args.pushbuf = chan->push.handle;
|
||||||
args.ioffset = 0x10000 + chan->push.vma.offset;
|
args.ioffset = 0x10000 + chan->push.vma.offset;
|
||||||
args.ilength = 0x02000;
|
args.ilength = 0x02000;
|
||||||
|
args.engine = NVE0_CHANNEL_IND_ENGINE_GR;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = nouveau_object_new(nv_object(cli), parent, handle,
|
ret = nouveau_object_new(nv_object(cli), parent, handle,
|
||||||
|
Reference in New Issue
Block a user