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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxx>
---
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

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux