[Nouveau] [PATCH v2 2/3] drm/nouveau/disp: quirk for SOR crossbar routing

Danilo Krummrich danilokrummrich at dk-develop.de
Mon Feb 5 15:16:36 UTC 2018


With DCB 4.1 implemented by VBIOS since GM20x GPUs, SOR crossbar
routing should be possible, such that any SOR sublink can drive
any macro link.

Unfortunately, there's at least one card where some SOR sublinks
being connected to a particular macro link are causing failures.

To work around this issue, supply a quirk for such cards which
prevents a dynamic mapping of SOR sublink and macro link and
instead relies on identity mapping.

Signed-off-by: Danilo Krummrich <danilokrummrich at dk-develop.de>
---
v2: checking actual pad macro and link instead of outp index
---
 drivers/gpu/drm/nouveau/include/nvkm/core/device.h |  1 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c    | 19 +++++++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
index 560265b15ec2..d384cb03ad85 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
@@ -184,6 +184,7 @@ struct nvkm_device_func {
 struct nvkm_device_quirk {
 	u8 tv_pin_mask;
 	u8 tv_gpio;
+	u8 outp_links_skip;
 };
 
 struct nvkm_device_chip {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
index be9e7f8c3b23..a574746ddd82 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
@@ -99,6 +99,18 @@ nvkm_outp_release(struct nvkm_outp *outp, u8 user)
 	}
 }
 
+static inline bool
+nvkm_outp_ior_route_quirk(struct nvkm_outp *outp)
+{
+	struct nvkm_device *dev = outp->disp->engine.subdev.device;
+
+	int macro_link = __ffs(outp->info.or) * 2 + outp->info.sorconf.link;
+	if (unlikely(dev->quirk))
+		return !(dev->quirk->outp_links_skip & BIT(macro_link));
+
+	return true;
+}
+
 static inline int
 nvkm_outp_acquire_ior(struct nvkm_outp *outp, u8 user, struct nvkm_ior *ior)
 {
@@ -115,6 +127,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user)
 	struct nvkm_ior *ior = outp->ior;
 	enum nvkm_ior_proto proto;
 	enum nvkm_ior_type type;
+	bool route_crossbar = nvkm_outp_ior_route_quirk(outp);
 
 	OUTP_TRACE(outp, "acquire %02x |= %02x %p", outp->acquired, user, ior);
 	if (ior) {
@@ -138,7 +151,8 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user)
 	/* Failing that, a completely unused OR is the next best thing. */
 	list_for_each_entry(ior, &outp->disp->ior, head) {
 		if (!ior->asy.outp && ior->type == type && !ior->arm.outp &&
-		    (ior->func->route.set || ior->id == __ffs(outp->info.or)))
+		    ((ior->func->route.set && route_crossbar) ||
+		     ior->id == __ffs(outp->info.or)))
 			return nvkm_outp_acquire_ior(outp, user, ior);
 	}
 
@@ -147,7 +161,8 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user)
 	 */
 	list_for_each_entry(ior, &outp->disp->ior, head) {
 		if (!ior->asy.outp && ior->type == type &&
-		    (ior->func->route.set || ior->id == __ffs(outp->info.or)))
+		    ((ior->func->route.set && route_crossbar) ||
+		     ior->id == __ffs(outp->info.or)))
 			return nvkm_outp_acquire_ior(outp, user, ior);
 	}
 
-- 
2.14.1



More information about the Nouveau mailing list