Loading drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +5 −25 Original line number Diff line number Diff line Loading @@ -576,8 +576,7 @@ 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 data, idx = 0; u16 mask, type; u16 mask, type, data; if (outp < 4) { type = DCB_OUTPUT_ANALOG; Loading @@ -602,32 +601,13 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, mask |= 0x0001 << outp; mask |= 0x0100 << head; /* this is a tad special, but for the moment its needed to get * all the dcb data required by the vbios scripts.. will be cleaned * up later as more bits are moved to the core.. */ while ((data = dcb_outp(bios, idx++, ver, hdr))) { u32 conn = nv_ro32(bios, data + 0); u32 conf = nv_ro32(bios, data + 4); if ((conn & 0x00300000) || (conn & 0x0000000f) != type || (conn & 0x0f000000) != (0x01000000 << outp)) continue; if ( (mask & 0x00c0) && (mask & 0x00c0) != ((mask & 0x00c0) & ((conf & 0x00000030) << 2))) continue; dcb->type = type; dcb->or = 1 << outp; dcb->connector = (conn & 0x0000f000) >> 12; 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); } return 0x0000; } static bool exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id) { Loading drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +4 −23 Original line number Diff line number Diff line Loading @@ -53,37 +53,18 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) 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 = { .type = type, .or = (1 << or), .sorconf.link = (1 << link), }; u8 ver, hdr, idx = 0; struct dcb_output outp; u8 ver, hdr; u32 data; int ret = -EINVAL; if (size < sizeof(u32)) return -EINVAL; data = *(u32 *)args; while (type && (data = dcb_outp(bios, idx++, &ver, &hdr))) { u32 conn = nv_ro32(bios, data + 0); u32 conf = nv_ro32(bios, data + 4); if ((conn & 0x00300000) || (conn & 0x0000000f) != type || (conn & 0x0f000000) != (0x01000000 << or)) continue; if ( (mask & 0x00c0) && (mask & 0x00c0) != ((mask & 0x00c0) & ((conf & 0x00000030) << 2))) continue; outp.connector = (conn & 0x0000f000) >> 12; } if (data == 0x0000) if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp)) return -ENODEV; data = *(u32 *)args; switch (mthd & ~0x3f) { case NV50_DISP_SOR_PWR: ret = priv->sor.power(priv, or, data); Loading drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h +5 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ struct dcb_output { uint8_t bus; uint8_t location; uint8_t or; uint8_t link; bool duallink_possible; union { struct sor_conf { Loading Loading @@ -55,6 +56,10 @@ struct dcb_output { u16 dcb_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); u16 dcb_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); u16 dcb_outp_parse(struct nouveau_bios *, u8 idx, u8 *, u8 *, struct dcb_output *); u16 dcb_outp_match(struct nouveau_bios *, u16 type, u16 mask, u8 *, u8 *, struct dcb_output *); int dcb_outp_foreach(struct nouveau_bios *, void *data, int (*exec) (struct nouveau_bios *, void *, int index, u16 entry)); Loading drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +63 −0 Original line number Diff line number Diff line Loading @@ -107,6 +107,69 @@ dcb_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) return 0x0000; } u16 dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, struct dcb_output *outp) { u16 dcb = dcb_outp(bios, idx, ver, len); if (dcb) { if (*ver >= 0x20) { u32 conn = nv_ro32(bios, dcb + 0x00); outp->or = (conn & 0x0f000000) >> 24; outp->location = (conn & 0x00300000) >> 20; outp->bus = (conn & 0x000f0000) >> 16; outp->connector = (conn & 0x0000f000) >> 12; outp->heads = (conn & 0x00000f00) >> 8; outp->i2c_index = (conn & 0x000000f0) >> 4; outp->type = (conn & 0x0000000f); outp->link = 0; } else { dcb = 0x0000; } if (*ver >= 0x40) { u32 conf = nv_ro32(bios, dcb + 0x04); switch (outp->type) { case DCB_OUTPUT_TMDS: case DCB_OUTPUT_LVDS: case DCB_OUTPUT_DP: outp->link = (conf & 0x00000030) >> 4; outp->sorconf.link = outp->link; /*XXX*/ break; default: break; } } } return dcb; } static inline u16 dcb_outp_hasht(struct dcb_output *outp) { return outp->type; } static inline u16 dcb_outp_hashm(struct dcb_output *outp) { return (outp->heads << 8) | (outp->link << 6) | outp->or; } u16 dcb_outp_match(struct nouveau_bios *bios, u16 type, u16 mask, u8 *ver, u8 *len, struct dcb_output *outp) { u16 dcb, idx = 0; while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) { if (dcb_outp_hasht(outp) == type) { if ((dcb_outp_hashm(outp) & mask) == mask) break; } } return dcb; } int dcb_outp_foreach(struct nouveau_bios *bios, void *data, int (*exec)(struct nouveau_bios *, void *, int, u16)) Loading Loading
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +5 −25 Original line number Diff line number Diff line Loading @@ -576,8 +576,7 @@ 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 data, idx = 0; u16 mask, type; u16 mask, type, data; if (outp < 4) { type = DCB_OUTPUT_ANALOG; Loading @@ -602,32 +601,13 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, mask |= 0x0001 << outp; mask |= 0x0100 << head; /* this is a tad special, but for the moment its needed to get * all the dcb data required by the vbios scripts.. will be cleaned * up later as more bits are moved to the core.. */ while ((data = dcb_outp(bios, idx++, ver, hdr))) { u32 conn = nv_ro32(bios, data + 0); u32 conf = nv_ro32(bios, data + 4); if ((conn & 0x00300000) || (conn & 0x0000000f) != type || (conn & 0x0f000000) != (0x01000000 << outp)) continue; if ( (mask & 0x00c0) && (mask & 0x00c0) != ((mask & 0x00c0) & ((conf & 0x00000030) << 2))) continue; dcb->type = type; dcb->or = 1 << outp; dcb->connector = (conn & 0x0000f000) >> 12; 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); } return 0x0000; } static bool exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id) { Loading
drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +4 −23 Original line number Diff line number Diff line Loading @@ -53,37 +53,18 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) 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 = { .type = type, .or = (1 << or), .sorconf.link = (1 << link), }; u8 ver, hdr, idx = 0; struct dcb_output outp; u8 ver, hdr; u32 data; int ret = -EINVAL; if (size < sizeof(u32)) return -EINVAL; data = *(u32 *)args; while (type && (data = dcb_outp(bios, idx++, &ver, &hdr))) { u32 conn = nv_ro32(bios, data + 0); u32 conf = nv_ro32(bios, data + 4); if ((conn & 0x00300000) || (conn & 0x0000000f) != type || (conn & 0x0f000000) != (0x01000000 << or)) continue; if ( (mask & 0x00c0) && (mask & 0x00c0) != ((mask & 0x00c0) & ((conf & 0x00000030) << 2))) continue; outp.connector = (conn & 0x0000f000) >> 12; } if (data == 0x0000) if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp)) return -ENODEV; data = *(u32 *)args; switch (mthd & ~0x3f) { case NV50_DISP_SOR_PWR: ret = priv->sor.power(priv, or, data); Loading
drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h +5 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ struct dcb_output { uint8_t bus; uint8_t location; uint8_t or; uint8_t link; bool duallink_possible; union { struct sor_conf { Loading Loading @@ -55,6 +56,10 @@ struct dcb_output { u16 dcb_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); u16 dcb_outp(struct nouveau_bios *, u8 idx, u8 *ver, u8 *len); u16 dcb_outp_parse(struct nouveau_bios *, u8 idx, u8 *, u8 *, struct dcb_output *); u16 dcb_outp_match(struct nouveau_bios *, u16 type, u16 mask, u8 *, u8 *, struct dcb_output *); int dcb_outp_foreach(struct nouveau_bios *, void *data, int (*exec) (struct nouveau_bios *, void *, int index, u16 entry)); Loading
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +63 −0 Original line number Diff line number Diff line Loading @@ -107,6 +107,69 @@ dcb_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) return 0x0000; } u16 dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, struct dcb_output *outp) { u16 dcb = dcb_outp(bios, idx, ver, len); if (dcb) { if (*ver >= 0x20) { u32 conn = nv_ro32(bios, dcb + 0x00); outp->or = (conn & 0x0f000000) >> 24; outp->location = (conn & 0x00300000) >> 20; outp->bus = (conn & 0x000f0000) >> 16; outp->connector = (conn & 0x0000f000) >> 12; outp->heads = (conn & 0x00000f00) >> 8; outp->i2c_index = (conn & 0x000000f0) >> 4; outp->type = (conn & 0x0000000f); outp->link = 0; } else { dcb = 0x0000; } if (*ver >= 0x40) { u32 conf = nv_ro32(bios, dcb + 0x04); switch (outp->type) { case DCB_OUTPUT_TMDS: case DCB_OUTPUT_LVDS: case DCB_OUTPUT_DP: outp->link = (conf & 0x00000030) >> 4; outp->sorconf.link = outp->link; /*XXX*/ break; default: break; } } } return dcb; } static inline u16 dcb_outp_hasht(struct dcb_output *outp) { return outp->type; } static inline u16 dcb_outp_hashm(struct dcb_output *outp) { return (outp->heads << 8) | (outp->link << 6) | outp->or; } u16 dcb_outp_match(struct nouveau_bios *bios, u16 type, u16 mask, u8 *ver, u8 *len, struct dcb_output *outp) { u16 dcb, idx = 0; while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) { if (dcb_outp_hasht(outp) == type) { if ((dcb_outp_hashm(outp) & mask) == mask) break; } } return dcb; } int dcb_outp_foreach(struct nouveau_bios *bios, void *data, int (*exec)(struct nouveau_bios *, void *, int, u16)) Loading