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