From dbff2dee9f8561710fcfe7f6623dd272ddca5a27 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2012 18:16:37 +1000 Subject: [PATCH] drm/nve0/fifo: support engine selection when creating fifo channels Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 45 +++++++++++++++++++--- drivers/gpu/drm/nouveau/core/include/core/class.h | 21 +++++++++- drivers/gpu/drm/nouveau/core/include/core/device.h | 2 +- drivers/gpu/drm/nouveau/nouveau_chan.c | 3 +- 7 files changed, 64 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 4914c3b..5b80f3e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -182,7 +182,7 @@ nv50_fifo_chan_ctor(struct nouveau_object *parent, struct nouveau_oclass *oclass, void *data, u32 size, 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 nv50_fifo_base *base = (void *)parent; struct nv50_fifo_chan *chan; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 765affb..d3b0356 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -150,7 +150,7 @@ nv84_fifo_chan_ctor(struct nouveau_object *parent, struct nouveau_bar *bar = nouveau_bar(parent); struct nv50_fifo_base *base = (void *)parent; struct nv50_fifo_chan *chan; - struct nv_channel_ind_class *args = data; + struct nv50_channel_ind_class *args = data; u64 ioffset, ilength; int ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index ef403fe..a4ae2bf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -163,7 +163,7 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent, struct nvc0_fifo_priv *priv = (void *)engine; struct nvc0_fifo_base *base = (void *)parent; struct nvc0_fifo_chan *chan; - struct nv_channel_ind_class *args = data; + struct nv50_channel_ind_class *args = data; u64 usermem, ioffset, ilength; int ret, i; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index aaff086..c3f4955 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -38,6 +38,22 @@ #include #include +#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 nouveau_gpuobj *playlist[2]; int cur_playlist; @@ -45,7 +61,7 @@ struct nve0_fifo_engn { struct nve0_fifo_priv { struct nouveau_fifo base; - struct nve0_fifo_engn engine[16]; + struct nve0_fifo_engn engine[FIFO_ENGINE_NR]; struct { struct nouveau_gpuobj *mem; struct nouveau_vma bar; @@ -119,7 +135,9 @@ nve0_fifo_context_attach(struct nouveau_object *parent, switch (nv_engidx(object->engine)) { 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: return -EINVAL; } @@ -149,7 +167,9 @@ nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend, switch (nv_engidx(object->engine)) { 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: return -EINVAL; } @@ -178,24 +198,36 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent, struct nve0_fifo_priv *priv = (void *)engine; struct nve0_fifo_base *base = (void *)parent; struct nve0_fifo_chan *chan; - struct nv_channel_ind_class *args = data; + struct nve0_channel_ind_class *args = data; u64 usermem, ioffset, ilength; int ret, i; if (size < sizeof(*args)) 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, priv->user.bar.offset, 0x200, args->pushbuf, - (1 << NVDEV_ENGINE_SW) | - (1 << NVDEV_ENGINE_GR), &chan); + fifo_engine[i].mask, &chan); *pobject = nv_object(chan); if (ret) return ret; nv_parent(chan)->context_attach = nve0_fifo_context_attach; nv_parent(chan)->context_detach = nve0_fifo_context_detach; + chan->engine = i; usermem = chan->base.chid * 0x200; ioffset = args->ioffset; @@ -235,6 +267,7 @@ nve0_fifo_chan_init(struct nouveau_object *object) if (ret) return ret; + nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16); nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12); nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); nve0_fifo_playlist_update(priv, chan->engine); diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 17326dd..9c6b0eb 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -65,13 +65,30 @@ struct nv_channel_dma_class { /* 506f: NV50_CHANNEL_IND * 826f: NV84_CHANNEL_IND * 906f: NVC0_CHANNEL_IND - * a06f: NVE0_CHANNEL_IND */ -struct nv_channel_ind_class { +struct nv50_channel_ind_class { u32 pushbuf; u32 ilength; 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 diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 4db7b01..1305593 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -36,7 +36,7 @@ enum nv_subdev_type { NVDEV_ENGINE_COPY0, NVDEV_ENGINE_COPY1, NVDEV_ENGINE_UNK1C1, - NVDEV_ENGINE_FENCE, + NVDEV_ENGINE_VENC, NVDEV_ENGINE_DISP, NVDEV_SUBDEV_NR, }; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 3dd5f71..b1eea19 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -188,7 +188,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, { static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 }; const u16 *oclass = oclasses; - struct nv_channel_ind_class args; + struct nve0_channel_ind_class args; struct nouveau_channel *chan; int ret; @@ -202,6 +202,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, args.pushbuf = chan->push.handle; args.ioffset = 0x10000 + chan->push.vma.offset; args.ilength = 0x02000; + args.engine = NVE0_CHANNEL_IND_ENGINE_GR; do { ret = nouveau_object_new(nv_object(cli), parent, handle, -- 2.7.4