summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c71
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h2
3 files changed, 70 insertions, 12 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
index 7a8dff7b8c95..e8bfb6ee89ae 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -177,12 +177,6 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
}
static void
-gf119_disp_intr_unk1_0(struct nv50_disp *disp, int head)
-{
- exec_script(disp, head, 1);
-}
-
-static void
gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
{
struct nvkm_subdev *subdev = &disp->base.engine.subdev;
@@ -363,8 +357,7 @@ gf119_disp_super(struct work_struct *work)
list_for_each_entry(head, &disp->base.head, head) {
if (!(mask[head->id] & 0x00001000))
continue;
- nvkm_debug(subdev, "supervisor 1.0 - head %d\n", head->id);
- gf119_disp_intr_unk1_0(disp, head->id);
+ nv50_disp_super_1_0(disp, head);
}
} else
if (disp->super & 0x00000002) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index c018dbdb121d..96d281568765 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -114,6 +114,60 @@ nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent);
}
+static u32
+nv50_disp_super_iedt(struct nvkm_head *head, struct nvkm_outp *outp,
+ u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+ struct nvbios_outp *iedt)
+{
+ struct nvkm_bios *bios = head->disp->engine.subdev.device->bios;
+ const u8 l = ffs(outp->info.link);
+ const u16 t = outp->info.hasht;
+ const u16 m = (0x0100 << head->id) | (l << 6) | outp->info.or;
+ u32 data = nvbios_outp_match(bios, t, m, ver, hdr, cnt, len, iedt);
+ if (!data)
+ OUTP_DBG(outp, "missing IEDT for %04x:%04x", t, m);
+ return data;
+}
+
+static void
+nv50_disp_super_ied_off(struct nvkm_head *head, struct nvkm_ior *ior, int id)
+{
+ struct nvkm_outp *outp = ior->arm.outp;
+ struct nvbios_outp iedt;
+ u8 ver, hdr, cnt, len;
+ u32 data;
+
+ if (!outp) {
+ IOR_DBG(ior, "nothing attached");
+ return;
+ }
+
+ data = nv50_disp_super_iedt(head, outp, &ver, &hdr, &cnt, &len, &iedt);
+ if (!data)
+ return;
+
+ nvbios_init(&head->disp->engine.subdev, iedt.script[id],
+ init.outp = &outp->info;
+ init.or = ior->id;
+ init.link = ior->arm.link;
+ init.head = head->id;
+ );
+}
+
+static struct nvkm_ior *
+nv50_disp_super_ior_arm(struct nvkm_head *head)
+{
+ struct nvkm_ior *ior;
+ list_for_each_entry(ior, &head->disp->ior, head) {
+ if (ior->arm.head & (1 << head->id)) {
+ HEAD_DBG(head, "on %s", ior->name);
+ return ior;
+ }
+ }
+ HEAD_DBG(head, "nothing attached");
+ return NULL;
+}
+
static struct nvkm_output *
exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
@@ -582,10 +636,19 @@ nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
}
}
-static void
-nv50_disp_intr_unk10_0(struct nv50_disp *disp, int head)
+void
+nv50_disp_super_1_0(struct nv50_disp *disp, struct nvkm_head *head)
{
- exec_script(disp, head, 1);
+ struct nvkm_ior *ior;
+
+ /* Determine which OR, if any, we're detaching from the head. */
+ HEAD_DBG(head, "supervisor 1.0");
+ ior = nv50_disp_super_ior_arm(head);
+ if (!ior)
+ return;
+
+ /* Execute OffInt1 IED script. */
+ nv50_disp_super_ied_off(head, ior, 1);
}
void
@@ -625,7 +688,7 @@ nv50_disp_super(struct work_struct *work)
continue;
if (!(super & (0x00000080 << head->id)))
continue;
- nv50_disp_intr_unk10_0(disp, head->id);
+ nv50_disp_super_1_0(disp, head);
}
} else
if (disp->super & 0x00000020) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
index 65d445687038..921ed0fa87f3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
@@ -3,6 +3,7 @@
#define nv50_disp(p) container_of((p), struct nv50_disp, base)
#include "priv.h"
#include "dp.h"
+struct nvkm_head;
struct nv50_disp {
const struct nv50_disp_func *func;
@@ -26,6 +27,7 @@ struct nv50_disp {
};
void nv50_disp_super_1(struct nv50_disp *);
+void nv50_disp_super_1_0(struct nv50_disp *, struct nvkm_head *);
int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *,
int index, int heads, struct nvkm_disp **);