diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index ca1a7d7..16c32bb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -806,31 +806,39 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, struct nvbios_outp *info) { struct nouveau_bios *bios = nouveau_bios(priv); - u16 mask, type, data; + u16 link1, link2 = 0, mask, type, data; if (outp < 4) { type = DCB_OUTPUT_ANALOG; - mask = 0; + link1 = 0; } else { outp -= 4; switch (ctrl & 0x00000f00) { - case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; - case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; - case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break; - case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break; - case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break; - case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; + case 0x00000000: type = DCB_OUTPUT_LVDS; link1 = 1; link2 = 2; break; + case 0x00000100: type = DCB_OUTPUT_TMDS; link1 = 1; break; + case 0x00000200: type = DCB_OUTPUT_TMDS; link1 = 2; break; + case 0x00000500: type = DCB_OUTPUT_TMDS; link1 = 1; link2 = 2; break; + case 0x00000800: type = DCB_OUTPUT_DP; link1 = 1; break; + case 0x00000900: type = DCB_OUTPUT_DP; link1 = 2; break; default: nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); return 0x0000; } } - mask = 0x00c0 & (mask << 6); + mask = 0x00c0 & (link1 << 6); mask |= 0x0001 << outp; mask |= 0x0100 << head; data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); + if (!data && link2) { + mask = 0x00c0 & (link2 << 6); + mask |= 0x0001 << outp; + mask |= 0x0100 << head; + + data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); + } + if (!data) return 0x0000; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 9e38ebf..ec6d4ca 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -576,35 +576,46 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, struct nvbios_outp *info) { struct nouveau_bios *bios = nouveau_bios(priv); - u16 mask, type, data; + u16 link1, link2 = 0, mask, type, data; if (outp < 4) { type = DCB_OUTPUT_ANALOG; - mask = 0; + link1 = 0; } else { outp -= 4; switch (ctrl & 0x00000f00) { - case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; - case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; - case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break; - case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break; - case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break; - case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; + case 0x00000000: type = DCB_OUTPUT_LVDS; link1 = 1; link2 = 2; break; + case 0x00000100: type = DCB_OUTPUT_TMDS; link1 = 1; break; + case 0x00000200: type = DCB_OUTPUT_TMDS; link1 = 2; break; + case 0x00000500: type = DCB_OUTPUT_TMDS; link1 = 1; link2 = 2; break; + case 0x00000800: type = DCB_OUTPUT_DP; link1 = 1; break; + case 0x00000900: type = DCB_OUTPUT_DP; link1 = 2; break; default: nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); return 0x0000; } - dcb->sorconf.link = mask; } - mask = 0x00c0 & (mask << 6); + mask = 0x00c0 & (link1 << 6); mask |= 0x0001 << outp; mask |= 0x0100 << head; data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); + if (!data && link2) { + link1 = link2; + mask = 0x00c0 & (link1 << 6); + mask |= 0x0001 << outp; + mask |= 0x0100 << head; + + data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); + } + if (!data) return 0x0000; + if (link1) + dcb->sorconf.link = link1; + return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); }