summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2017-05-19 23:59:34 +1000
committerBen Skeggs <bskeggs@redhat.com>2017-06-16 14:04:48 +1000
commita1c930789aa51b928f804c9186f9821efd070ce1 (patch)
tree383e8145267b88db8feed522b492a7fa476b35b5 /drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
parent4b2b42f8e910c65aceb8b2d12fe392a7b7955449 (diff)
downloadop-kernel-dev-a1c930789aa51b928f804c9186f9821efd070ce1.zip
op-kernel-dev-a1c930789aa51b928f804c9186f9821efd070ce1.tar.gz
drm/nouveau/disp: introduce object to track per-head functions/state
Primarily intended as a way to pass per-head state around during supervisor handling, and share logic between NV50/GF119. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index 025cc0d..9787a4c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -22,6 +22,7 @@
* Authors: Ben Skeggs
*/
#include "nv50.h"
+#include "head.h"
#include "rootnv50.h"
#include <core/client.h>
@@ -146,7 +147,7 @@ nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
int index, int heads, struct nvkm_disp **pdisp)
{
struct nv50_disp *disp;
- int ret;
+ int ret, i;
if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL)))
return -ENOMEM;
@@ -154,10 +155,16 @@ nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
disp->func = func;
*pdisp = &disp->base;
- ret = nvkm_disp_ctor(&nv50_disp_, device, index, heads, &disp->base);
+ ret = nvkm_disp_ctor(&nv50_disp_, device, index, &disp->base);
if (ret)
return ret;
+ for (i = 0; func->head.new && i < heads; i++) {
+ ret = func->head.new(&disp->base, i);
+ if (ret)
+ return ret;
+ }
+
return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent);
}
@@ -684,43 +691,43 @@ nv50_disp_super(struct work_struct *work)
container_of(work, struct nv50_disp, supervisor);
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
struct nvkm_device *device = subdev->device;
+ struct nvkm_head *head;
u32 super = nvkm_rd32(device, 0x610030);
- int head;
nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super);
if (disp->super & 0x00000010) {
nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
- for (head = 0; head < disp->base.head.nr; head++) {
- if (!(super & (0x00000020 << head)))
+ list_for_each_entry(head, &disp->base.head, head) {
+ if (!(super & (0x00000020 << head->id)))
continue;
- if (!(super & (0x00000080 << head)))
+ if (!(super & (0x00000080 << head->id)))
continue;
- nv50_disp_intr_unk10_0(disp, head);
+ nv50_disp_intr_unk10_0(disp, head->id);
}
} else
if (disp->super & 0x00000020) {
- for (head = 0; head < disp->base.head.nr; head++) {
- if (!(super & (0x00000080 << head)))
+ list_for_each_entry(head, &disp->base.head, head) {
+ if (!(super & (0x00000080 << head->id)))
continue;
- nv50_disp_intr_unk20_0(disp, head);
+ nv50_disp_intr_unk20_0(disp, head->id);
}
- for (head = 0; head < disp->base.head.nr; head++) {
- if (!(super & (0x00000200 << head)))
+ list_for_each_entry(head, &disp->base.head, head) {
+ if (!(super & (0x00000200 << head->id)))
continue;
- nv50_disp_intr_unk20_1(disp, head);
+ nv50_disp_intr_unk20_1(disp, head->id);
}
- for (head = 0; head < disp->base.head.nr; head++) {
- if (!(super & (0x00000080 << head)))
+ list_for_each_entry(head, &disp->base.head, head) {
+ if (!(super & (0x00000080 << head->id)))
continue;
- nv50_disp_intr_unk20_2(disp, head);
+ nv50_disp_intr_unk20_2(disp, head->id);
}
} else
if (disp->super & 0x00000040) {
- for (head = 0; head < disp->base.head.nr; head++) {
- if (!(super & (0x00000080 << head)))
+ list_for_each_entry(head, &disp->base.head, head) {
+ if (!(super & (0x00000080 << head->id)))
continue;
- nv50_disp_intr_unk40_0(disp, head);
+ nv50_disp_intr_unk40_0(disp, head->id);
}
nv50_disp_update_sppll1(disp);
}
@@ -819,6 +826,7 @@ nv50_disp = {
.uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_super,
.root = &nv50_disp_root_oclass,
+ .head.new = nv50_head_new,
.head.vblank_init = nv50_disp_vblank_init,
.head.vblank_fini = nv50_disp_vblank_fini,
.head.scanoutpos = nv50_disp_root_scanoutpos,
OpenPOWER on IntegriCloud