static u16 exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *info) { struct nouveau_bios *bios = nouveau_bios(priv); u16 mask, type, data; if (outp < 4) { type = DCB_OUTPUT_ANALOG; mask = 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; default: nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); return 0x0000; } dcb->sorconf.link = mask; } mask = 0x00c0 & (mask << 6); mask |= 0x0001 << outp; mask |= 0x0100 << head; data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); if (!data) return 0x0000; return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); }
static u16 exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *info) { struct nouveau_bios *bios = nouveau_bios(priv); u16 mask, type, data; if (outp < 4) { type = DCB_OUTPUT_ANALOG; mask = 0; } else if (outp < 8) { 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; default: nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); return 0x0000; } outp -= 4; } else { outp = outp - 8; type = 0x0010; mask = 0; switch (ctrl & 0x00000f00) { case 0x00000000: type |= priv->pior.type[outp]; break; default: nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl); return 0x0000; } } mask = 0x00c0 & (mask << 6); mask |= 0x0001 << outp; mask |= 0x0100 << head; data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); if (!data) return 0x0000; /* off-chip encoders require matching the exact encoder type */ if (dcb->location != 0) type |= dcb->extdev << 8; return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); }
int nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) { struct nv50_disp_priv *priv = (void *)object->engine; struct nouveau_bios *bios = nouveau_bios(priv); const u16 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12; const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2; const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or); struct dcb_output outp; u8 ver, hdr; u32 data; int ret = -EINVAL; if (size < sizeof(u32)) return -EINVAL; data = *(u32 *)args; if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp)) return -ENODEV; switch (mthd & ~0x3f) { case NV50_DISP_SOR_PWR: ret = priv->sor.power(priv, or, data); break; case NVA3_DISP_SOR_HDA_ELD: ret = priv->sor.hda_eld(priv, or, args, size); break; case NV84_DISP_SOR_HDMI_PWR: ret = priv->sor.hdmi(priv, head, or, data); break; case NV50_DISP_SOR_LVDS_SCRIPT: priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; ret = 0; break; default: BUG_ON(1); } return ret; }