Commit a9c44a88 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/disp/nv50-: add channel interfaces to control error interrupts

This will be required to support Volta, but also allows us to remove code
that's duplicated for each channel type already.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 4a8621a2
......@@ -47,3 +47,16 @@ gf119_disp_chan_uevent = {
.init = gf119_disp_chan_uevent_init,
.fini = gf119_disp_chan_uevent_fini,
};
void
gf119_disp_chan_intr(struct nv50_disp_chan *chan, bool en)
{
struct nvkm_device *device = chan->disp->base.engine.subdev.device;
const u64 mask = 0x00000001 << chan->chid.user;
if (!en) {
nvkm_mask(device, 0x610090, mask, 0x00000000);
nvkm_mask(device, 0x6100a0, mask, 0x00000000);
} else {
nvkm_mask(device, 0x6100a0, mask, mask);
}
}
......@@ -162,6 +162,15 @@ nv50_disp_chan_user(struct nv50_disp_chan *chan, u64 *psize)
return 0x640000 + (chan->chid.user * 0x1000);
}
void
nv50_disp_chan_intr(struct nv50_disp_chan *chan, bool en)
{
struct nvkm_device *device = chan->disp->base.engine.subdev.device;
const u64 mask = 0x00010001 << chan->chid.user;
const u64 data = en ? 0x00010000 : 0x00000000;
nvkm_mask(device, 0x610028, mask, data);
}
static int
nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
{
......@@ -288,6 +297,7 @@ nv50_disp_chan_fini(struct nvkm_object *object, bool suspend)
{
struct nv50_disp_chan *chan = nv50_disp_chan(object);
chan->func->fini(chan);
chan->func->intr(chan, false);
return 0;
}
......@@ -295,6 +305,7 @@ static int
nv50_disp_chan_init(struct nvkm_object *object)
{
struct nv50_disp_chan *chan = nv50_disp_chan(object);
chan->func->intr(chan, true);
return chan->func->init(chan);
}
......
......@@ -25,6 +25,7 @@ struct nv50_disp_chan {
struct nv50_disp_chan_func {
int (*init)(struct nv50_disp_chan *);
void (*fini)(struct nv50_disp_chan *);
void (*intr)(struct nv50_disp_chan *, bool en);
u64 (*user)(struct nv50_disp_chan *, u64 *size);
int (*bind)(struct nv50_disp_chan *, struct nvkm_object *, u32 handle);
};
......@@ -38,12 +39,14 @@ int nv50_disp_dmac_new_(const struct nv50_disp_chan_func *,
struct nv50_disp *, int chid, int head, u64 push,
const struct nvkm_oclass *, struct nvkm_object **);
void nv50_disp_chan_intr(struct nv50_disp_chan *, bool);
u64 nv50_disp_chan_user(struct nv50_disp_chan *, u64 *);
extern const struct nv50_disp_chan_func nv50_disp_pioc_func;
extern const struct nv50_disp_chan_func nv50_disp_dmac_func;
int nv50_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32);
extern const struct nv50_disp_chan_func nv50_disp_core_func;
void gf119_disp_chan_intr(struct nv50_disp_chan *, bool);
extern const struct nv50_disp_chan_func gf119_disp_pioc_func;
extern const struct nv50_disp_chan_func gf119_disp_dmac_func;
void gf119_disp_dmac_fini(struct nv50_disp_chan *);
......
......@@ -182,10 +182,6 @@ gf119_disp_core_fini(struct nv50_disp_chan *chan)
nvkm_error(subdev, "core fini: %08x\n",
nvkm_rd32(device, 0x610490));
}
/* disable error reporting and completion notification */
nvkm_mask(device, 0x610090, 0x00000001, 0x00000000);
nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000000);
}
static int
......@@ -194,9 +190,6 @@ gf119_disp_core_init(struct nv50_disp_chan *chan)
struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
/* enable error reporting */
nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000001);
/* initialise channel for dma command submission */
nvkm_wr32(device, 0x610494, chan->push);
nvkm_wr32(device, 0x610498, 0x00010000);
......@@ -222,6 +215,7 @@ const struct nv50_disp_chan_func
gf119_disp_core_func = {
.init = gf119_disp_core_init,
.fini = gf119_disp_core_fini,
.intr = gf119_disp_chan_intr,
.user = nv50_disp_chan_user,
.bind = gf119_disp_dmac_bind,
};
......
......@@ -31,9 +31,6 @@ gp102_disp_core_init(struct nv50_disp_chan *chan)
struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
/* enable error reporting */
nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000001);
/* initialise channel for dma command submission */
nvkm_wr32(device, 0x611494, chan->push);
nvkm_wr32(device, 0x611498, 0x00010000);
......@@ -59,6 +56,7 @@ static const struct nv50_disp_chan_func
gp102_disp_core_func = {
.init = gp102_disp_core_init,
.fini = gf119_disp_core_fini,
.intr = gf119_disp_chan_intr,
.user = nv50_disp_chan_user,
.bind = gf119_disp_dmac_bind,
};
......
......@@ -179,9 +179,6 @@ nv50_disp_core_fini(struct nv50_disp_chan *chan)
nvkm_error(subdev, "core fini: %08x\n",
nvkm_rd32(device, 0x610200));
}
/* disable error reporting and completion notifications */
nvkm_mask(device, 0x610028, 0x00010001, 0x00000000);
}
static int
......@@ -190,9 +187,6 @@ nv50_disp_core_init(struct nv50_disp_chan *chan)
struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
/* enable error reporting */
nvkm_mask(device, 0x610028, 0x00010000, 0x00010000);
/* attempt to unstick channel from some unknown state */
if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000)
nvkm_mask(device, 0x610200, 0x00800000, 0x00800000);
......@@ -224,6 +218,7 @@ const struct nv50_disp_chan_func
nv50_disp_core_func = {
.init = nv50_disp_core_init,
.fini = nv50_disp_core_fini,
.intr = nv50_disp_chan_intr,
.user = nv50_disp_chan_user,
.bind = nv50_disp_dmac_bind,
};
......
......@@ -53,10 +53,6 @@ gf119_disp_dmac_fini(struct nv50_disp_chan *chan)
nvkm_error(subdev, "ch %d fini: %08x\n", user,
nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
}
/* disable error reporting and completion notification */
nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
}
static int
......@@ -67,9 +63,6 @@ gf119_disp_dmac_init(struct nv50_disp_chan *chan)
int ctrl = chan->chid.ctrl;
int user = chan->chid.user;
/* enable error reporting */
nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
/* initialise channel for dma command submission */
nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push);
nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000);
......@@ -95,6 +88,7 @@ const struct nv50_disp_chan_func
gf119_disp_dmac_func = {
.init = gf119_disp_dmac_init,
.fini = gf119_disp_dmac_fini,
.intr = gf119_disp_chan_intr,
.user = nv50_disp_chan_user,
.bind = gf119_disp_dmac_bind,
};
......@@ -33,9 +33,6 @@ gp102_disp_dmac_init(struct nv50_disp_chan *chan)
int ctrl = chan->chid.ctrl;
int user = chan->chid.user;
/* enable error reporting */
nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
/* initialise channel for dma command submission */
nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push);
nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000);
......@@ -61,6 +58,7 @@ const struct nv50_disp_chan_func
gp102_disp_dmac_func = {
.init = gp102_disp_dmac_init,
.fini = gf119_disp_dmac_fini,
.intr = gf119_disp_chan_intr,
.user = nv50_disp_chan_user,
.bind = gf119_disp_dmac_bind,
};
......@@ -96,9 +96,6 @@ nv50_disp_dmac_fini(struct nv50_disp_chan *chan)
nvkm_error(subdev, "ch %d fini timeout, %08x\n", user,
nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
}
/* disable error reporting and completion notifications */
nvkm_mask(device, 0x610028, 0x00010001 << user, 0x00000000 << user);
}
static int
......@@ -109,9 +106,6 @@ nv50_disp_dmac_init(struct nv50_disp_chan *chan)
int ctrl = chan->chid.ctrl;
int user = chan->chid.user;
/* enable error reporting */
nvkm_mask(device, 0x610028, 0x00010000 << user, 0x00010000 << user);
/* initialise channel for dma command submission */
nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push);
nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000);
......@@ -137,6 +131,7 @@ const struct nv50_disp_chan_func
nv50_disp_dmac_func = {
.init = nv50_disp_dmac_init,
.fini = nv50_disp_dmac_fini,
.intr = nv50_disp_chan_intr,
.user = nv50_disp_chan_user,
.bind = nv50_disp_dmac_bind,
};
......@@ -43,10 +43,6 @@ gf119_disp_pioc_fini(struct nv50_disp_chan *chan)
nvkm_error(subdev, "ch %d fini: %08x\n", user,
nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
}
/* disable error reporting and completion notification */
nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
}
static int
......@@ -58,9 +54,6 @@ gf119_disp_pioc_init(struct nv50_disp_chan *chan)
int ctrl = chan->chid.ctrl;
int user = chan->chid.user;
/* enable error reporting */
nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
/* activate channel */
nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001);
if (nvkm_msec(device, 2000,
......@@ -80,5 +73,6 @@ const struct nv50_disp_chan_func
gf119_disp_pioc_func = {
.init = gf119_disp_pioc_init,
.fini = gf119_disp_pioc_fini,
.intr = gf119_disp_chan_intr,
.user = nv50_disp_chan_user,
};
......@@ -82,5 +82,6 @@ const struct nv50_disp_chan_func
nv50_disp_pioc_func = {
.init = nv50_disp_pioc_init,
.fini = nv50_disp_pioc_fini,
.intr = nv50_disp_chan_intr,
.user = nv50_disp_chan_user,
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment