Blob Blame History Raw
From: Ben Skeggs <bskeggs@redhat.com>
Date: Tue, 8 May 2018 20:39:46 +1000
Subject: drm/nouveau/disp/nv50-: fetch mask of available heads during oneinit
Git-commit: f7b2ece37fce822692d3d6e616e0d0f3df9d4f49
Patch-mainline: v4.18-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c       |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c       |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c     |   12 ++----------
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h      |    4 ++++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c |   11 ++++++++---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c  |    7 +++++++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c     |    4 ++--
 drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c      |   13 ++++++++-----
 drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h      |    6 +++---
 18 files changed, 56 insertions(+), 45 deletions(-)

--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
@@ -32,7 +32,7 @@ g84_disp = {
 	.uevent = &nv50_disp_chan_uevent,
 	.super = nv50_disp_super,
 	.root = &g84_disp_root_oclass,
-	.head.new = nv50_head_new,
+	.head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
 	.dac = { .nr = 3, .new = nv50_dac_new },
 	.sor = { .nr = 2, .new = g84_sor_new },
 	.pior = { .nr = 3, .new = nv50_pior_new },
@@ -41,5 +41,5 @@ g84_disp = {
 int
 g84_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return nv50_disp_new_(&g84_disp, device, index, 2, pdisp);
+	return nv50_disp_new_(&g84_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
@@ -32,7 +32,7 @@ g94_disp = {
 	.uevent = &nv50_disp_chan_uevent,
 	.super = nv50_disp_super,
 	.root = &g94_disp_root_oclass,
-	.head.new = nv50_head_new,
+	.head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
 	.dac = { .nr = 3, .new = nv50_dac_new },
 	.sor = { .nr = 4, .new = g94_sor_new },
 	.pior = { .nr = 3, .new = nv50_pior_new },
@@ -41,5 +41,5 @@ g94_disp = {
 int
 g94_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return nv50_disp_new_(&g94_disp, device, index, 2, pdisp);
+	return nv50_disp_new_(&g94_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -164,14 +164,6 @@ gf119_disp_intr(struct nv50_disp *disp)
 	}
 }
 
-int
-gf119_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
-		int index, struct nvkm_disp **pdisp)
-{
-	u32 heads = nvkm_rd32(device, 0x022448);
-	return nv50_disp_new_(func, device, index, heads, pdisp);
-}
-
 static const struct nv50_disp_func
 gf119_disp = {
 	.intr = gf119_disp_intr,
@@ -179,7 +171,7 @@ gf119_disp = {
 	.uevent = &gf119_disp_chan_uevent,
 	.super = gf119_disp_super,
 	.root = &gf119_disp_root_oclass,
-	.head.new = gf119_head_new,
+	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
 	.dac = { .nr = 3, .new = gf119_dac_new },
 	.sor = { .nr = 4, .new = gf119_sor_new },
 };
@@ -187,5 +179,5 @@ gf119_disp = {
 int
 gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return gf119_disp_new_(&gf119_disp, device, index, pdisp);
+	return nv50_disp_new_(&gf119_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
@@ -33,7 +33,7 @@ gk104_disp = {
 	.uevent = &gf119_disp_chan_uevent,
 	.super = gf119_disp_super,
 	.root = &gk104_disp_root_oclass,
-	.head.new = gf119_head_new,
+	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
 	.dac = { .nr = 3, .new = gf119_dac_new },
 	.sor = { .nr = 4, .new = gk104_sor_new },
 };
@@ -41,5 +41,5 @@ gk104_disp = {
 int
 gk104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return gf119_disp_new_(&gk104_disp, device, index, pdisp);
+	return nv50_disp_new_(&gk104_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c
@@ -33,7 +33,7 @@ gk110_disp = {
 	.uevent = &gf119_disp_chan_uevent,
 	.super = gf119_disp_super,
 	.root = &gk110_disp_root_oclass,
-	.head.new = gf119_head_new,
+	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
 	.dac = { .nr = 3, .new = gf119_dac_new },
 	.sor = { .nr = 4, .new = gk104_sor_new },
 };
@@ -41,5 +41,5 @@ gk110_disp = {
 int
 gk110_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return gf119_disp_new_(&gk110_disp, device, index, pdisp);
+	return nv50_disp_new_(&gk110_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
@@ -33,7 +33,7 @@ gm107_disp = {
 	.uevent = &gf119_disp_chan_uevent,
 	.super = gf119_disp_super,
 	.root = &gm107_disp_root_oclass,
-	.head.new = gf119_head_new,
+	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
 	.dac = { .nr = 3, .new = gf119_dac_new },
 	.sor = { .nr = 4, .new = gm107_sor_new },
 };
@@ -41,5 +41,5 @@ gm107_disp = {
 int
 gm107_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return gf119_disp_new_(&gm107_disp, device, index, pdisp);
+	return nv50_disp_new_(&gm107_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
@@ -33,7 +33,7 @@ gm200_disp = {
 	.uevent = &gf119_disp_chan_uevent,
 	.super = gf119_disp_super,
 	.root = &gm200_disp_root_oclass,
-	.head.new = gf119_head_new,
+	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
 	.dac = { .nr = 3, .new = gf119_dac_new },
 	.sor = { .nr = 4, .new = gm200_sor_new },
 };
@@ -41,5 +41,5 @@ gm200_disp = {
 int
 gm200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return gf119_disp_new_(&gm200_disp, device, index, pdisp);
+	return nv50_disp_new_(&gm200_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
@@ -33,12 +33,12 @@ gp100_disp = {
 	.uevent = &gf119_disp_chan_uevent,
 	.super = gf119_disp_super,
 	.root = &gp100_disp_root_oclass,
-	.head.new = gf119_head_new,
+	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
 	.sor = { .nr = 4, .new = gm200_sor_new },
 };
 
 int
 gp100_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return gf119_disp_new_(&gp100_disp, device, index, pdisp);
+	return nv50_disp_new_(&gp100_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
@@ -59,12 +59,12 @@ gp102_disp = {
 	.uevent = &gf119_disp_chan_uevent,
 	.super = gf119_disp_super,
 	.root = &gp102_disp_root_oclass,
-	.head.new = gf119_head_new,
+	.head = { .cnt = gf119_head_cnt, .new = gf119_head_new },
 	.sor = { .nr = 4, .new = gm200_sor_new },
 };
 
 int
 gp102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return gf119_disp_new_(&gp102_disp, device, index, pdisp);
+	return nv50_disp_new_(&gp102_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c
@@ -32,7 +32,7 @@ gt200_disp = {
 	.uevent = &nv50_disp_chan_uevent,
 	.super = nv50_disp_super,
 	.root = &gt200_disp_root_oclass,
-	.head.new = nv50_head_new,
+	.head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
 	.dac = { .nr = 3, .new = nv50_dac_new },
 	.sor = { .nr = 2, .new = g84_sor_new },
 	.pior = { .nr = 3, .new = nv50_pior_new },
@@ -41,5 +41,5 @@ gt200_disp = {
 int
 gt200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return nv50_disp_new_(&gt200_disp, device, index, 2, pdisp);
+	return nv50_disp_new_(&gt200_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
@@ -32,7 +32,7 @@ gt215_disp = {
 	.uevent = &nv50_disp_chan_uevent,
 	.super = nv50_disp_super,
 	.root = &gt215_disp_root_oclass,
-	.head.new = nv50_head_new,
+	.head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
 	.dac = { .nr = 3, .new = nv50_dac_new },
 	.sor = { .nr = 4, .new = gt215_sor_new },
 	.pior = { .nr = 3, .new = nv50_pior_new },
@@ -41,5 +41,5 @@ gt215_disp = {
 int
 gt215_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return nv50_disp_new_(&gt215_disp, device, index, 2, pdisp);
+	return nv50_disp_new_(&gt215_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
@@ -51,6 +51,10 @@ void nv50_head_rgpos(struct nvkm_head *,
 #define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a)
 
 int nv04_head_new(struct nvkm_disp *, int id);
+
+int nv50_head_cnt(struct nvkm_disp *, unsigned long *);
 int nv50_head_new(struct nvkm_disp *, int id);
+
+int gf119_head_cnt(struct nvkm_disp *, unsigned long *);
 int gf119_head_new(struct nvkm_disp *, int id);
 #endif
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c
@@ -92,8 +92,13 @@ gf119_head = {
 int
 gf119_head_new(struct nvkm_disp *disp, int id)
 {
-	struct nvkm_device *device = disp->engine.subdev.device;
-	if (!(nvkm_rd32(device, 0x612004) & (0x00000001 << id)))
-		return 0;
 	return nvkm_head_new_(&gf119_head, disp, id);
 }
+
+int
+gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask)
+{
+	struct nvkm_device *device = disp->engine.subdev.device;
+	*pmask = nvkm_rd32(device, 0x612004) & 0x0000000f;
+	return nvkm_rd32(device, 0x022448);
+}
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c
@@ -90,3 +90,10 @@ nv50_head_new(struct nvkm_disp *disp, in
 {
 	return nvkm_head_new_(&nv50_head, disp, id);
 }
+
+int
+nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask)
+{
+	*pmask = 3;
+	return 2;
+}
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
@@ -30,7 +30,7 @@ mcp77_disp = {
 	.uevent = &nv50_disp_chan_uevent,
 	.super = nv50_disp_super,
 	.root = &g94_disp_root_oclass,
-	.head.new = nv50_head_new,
+	.head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
 	.dac = { .nr = 3, .new = nv50_dac_new },
 	.sor = { .nr = 4, .new = mcp77_sor_new },
 	.pior = { .nr = 3, .new = nv50_pior_new },
@@ -39,5 +39,5 @@ mcp77_disp = {
 int
 mcp77_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return nv50_disp_new_(&mcp77_disp, device, index, 2, pdisp);
+	return nv50_disp_new_(&mcp77_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
@@ -30,7 +30,7 @@ mcp89_disp = {
 	.uevent = &nv50_disp_chan_uevent,
 	.super = nv50_disp_super,
 	.root = &gt215_disp_root_oclass,
-	.head.new = nv50_head_new,
+	.head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
 	.dac = { .nr = 3, .new = nv50_dac_new },
 	.sor = { .nr = 4, .new = mcp89_sor_new },
 	.pior = { .nr = 3, .new = nv50_pior_new },
@@ -39,5 +39,5 @@ mcp89_disp = {
 int
 mcp89_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return nv50_disp_new_(&mcp89_disp, device, index, 2, pdisp);
+	return nv50_disp_new_(&mcp89_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -64,9 +64,13 @@ nv50_disp_oneinit_(struct nvkm_disp *bas
 {
 	struct nv50_disp *disp = nv50_disp(base);
 	const struct nv50_disp_func *func = disp->func;
+	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	int ret, i;
 
-	for (i = 0; func->head.new && i < disp->head.nr; i++) {
+	disp->head.nr = func->head.cnt(&disp->base, &disp->head.mask);
+	nvkm_debug(subdev, "  Head(s): %d (%02lx)\n",
+		   disp->head.nr, disp->head.mask);
+	for_each_set_bit(i, &disp->head.mask, disp->head.nr) {
 		ret = func->head.new(&disp->base, i);
 		if (ret)
 			return ret;
@@ -103,7 +107,7 @@ nv50_disp_ = {
 
 int
 nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
-	       int index, int heads, struct nvkm_disp **pdisp)
+	       int index, struct nvkm_disp **pdisp)
 {
 	struct nv50_disp *disp;
 	int ret;
@@ -122,7 +126,6 @@ nv50_disp_new_(const struct nv50_disp_fu
 		return -ENOMEM;
 
 	INIT_WORK(&disp->supervisor, func->super);
-	disp->head.nr = heads;
 
 	return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan),
 			       &disp->uevent);
@@ -633,7 +636,7 @@ nv50_disp = {
 	.uevent = &nv50_disp_chan_uevent,
 	.super = nv50_disp_super,
 	.root = &nv50_disp_root_oclass,
-	.head.new = nv50_head_new,
+	.head = { .cnt = nv50_head_cnt, .new = nv50_head_new },
 	.dac = { .nr = 3, .new = nv50_dac_new },
 	.sor = { .nr = 2, .new = nv50_sor_new },
 	.pior = { .nr = 3, .new = nv50_pior_new },
@@ -642,5 +645,5 @@ nv50_disp = {
 int
 nv50_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
 {
-	return nv50_disp_new_(&nv50_disp, device, index, 2, pdisp);
+	return nv50_disp_new_(&nv50_disp, device, index, pdisp);
 }
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
@@ -15,6 +15,7 @@ struct nv50_disp {
 	struct nvkm_event uevent;
 
 	struct {
+		unsigned long mask;
 		int nr;
 	} head;
 
@@ -37,9 +38,7 @@ void nv50_disp_super_2_2(struct nv50_dis
 void nv50_disp_super_3_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 **);
-int gf119_disp_new_(const struct nv50_disp_func *, struct nvkm_device *,
-		    int index, struct nvkm_disp **);
+		   int index, struct nvkm_disp **);
 
 struct nv50_disp_func {
 	void (*intr)(struct nv50_disp *);
@@ -51,6 +50,7 @@ struct nv50_disp_func {
 	const struct nvkm_disp_oclass *root;
 
 	struct {
+		int (*cnt)(struct nvkm_disp *, unsigned long *mask);
 		int (*new)(struct nvkm_disp *, int id);
 	} head;