drm/nouveau/bios/disp: fix handling of "match any protocol" entries
As it turns out, a value of 0xff means "any protocol" and not "VGA". Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
92181d47ee
commit
bc9139d23f
@ -25,7 +25,8 @@ u16 nvbios_outp_match(struct nvkm_bios *, u16 type, u16 mask,
|
|||||||
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *);
|
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *);
|
||||||
|
|
||||||
struct nvbios_ocfg {
|
struct nvbios_ocfg {
|
||||||
u16 match;
|
u8 proto;
|
||||||
|
u8 flags;
|
||||||
u16 clkcmp[2];
|
u16 clkcmp[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ u16 nvbios_ocfg_entry(struct nvkm_bios *, u16 outp, u8 idx,
|
|||||||
u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
|
u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
|
||||||
u16 nvbios_ocfg_parse(struct nvkm_bios *, u16 outp, u8 idx,
|
u16 nvbios_ocfg_parse(struct nvkm_bios *, u16 outp, u8 idx,
|
||||||
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
|
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
|
||||||
u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u16 type,
|
u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u8 proto, u8 flags,
|
||||||
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
|
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
|
||||||
u16 nvbios_oclk_match(struct nvkm_bios *, u16 cmp, u32 khz);
|
u16 nvbios_oclk_match(struct nvkm_bios *, u16 cmp, u32 khz);
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,6 +76,7 @@ exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
|
|||||||
mask |= 0x0001 << or;
|
mask |= 0x0001 << or;
|
||||||
mask |= 0x0100 << head;
|
mask |= 0x0100 << head;
|
||||||
|
|
||||||
|
|
||||||
list_for_each_entry(outp, &disp->base.outp, head) {
|
list_for_each_entry(outp, &disp->base.outp, head) {
|
||||||
if ((outp->info.hasht & 0xff) == type &&
|
if ((outp->info.hasht & 0xff) == type &&
|
||||||
(outp->info.hashm & mask) == mask) {
|
(outp->info.hashm & mask) == mask) {
|
||||||
@ -155,25 +156,21 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
|
|||||||
if (!outp)
|
if (!outp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
*conf = (ctrl & 0x00000f00) >> 8;
|
||||||
switch (outp->info.type) {
|
switch (outp->info.type) {
|
||||||
case DCB_OUTPUT_TMDS:
|
case DCB_OUTPUT_TMDS:
|
||||||
*conf = (ctrl & 0x00000f00) >> 8;
|
|
||||||
if (*conf == 5)
|
if (*conf == 5)
|
||||||
*conf |= 0x0100;
|
*conf |= 0x0100;
|
||||||
break;
|
break;
|
||||||
case DCB_OUTPUT_LVDS:
|
case DCB_OUTPUT_LVDS:
|
||||||
*conf = disp->sor.lvdsconf;
|
*conf |= disp->sor.lvdsconf;
|
||||||
break;
|
break;
|
||||||
case DCB_OUTPUT_DP:
|
|
||||||
*conf = (ctrl & 0x00000f00) >> 8;
|
|
||||||
break;
|
|
||||||
case DCB_OUTPUT_ANALOG:
|
|
||||||
default:
|
default:
|
||||||
*conf = 0x00ff;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
|
data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
|
||||||
|
&ver, &hdr, &cnt, &len, &info2);
|
||||||
if (data && id < 0xff) {
|
if (data && id < 0xff) {
|
||||||
data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
|
data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -387,22 +387,17 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
|
|||||||
if (!outp)
|
if (!outp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
*conf = (ctrl & 0x00000f00) >> 8;
|
||||||
if (outp->info.location == 0) {
|
if (outp->info.location == 0) {
|
||||||
switch (outp->info.type) {
|
switch (outp->info.type) {
|
||||||
case DCB_OUTPUT_TMDS:
|
case DCB_OUTPUT_TMDS:
|
||||||
*conf = (ctrl & 0x00000f00) >> 8;
|
|
||||||
if (*conf == 5)
|
if (*conf == 5)
|
||||||
*conf |= 0x0100;
|
*conf |= 0x0100;
|
||||||
break;
|
break;
|
||||||
case DCB_OUTPUT_LVDS:
|
case DCB_OUTPUT_LVDS:
|
||||||
*conf = disp->sor.lvdsconf;
|
*conf |= disp->sor.lvdsconf;
|
||||||
break;
|
break;
|
||||||
case DCB_OUTPUT_DP:
|
|
||||||
*conf = (ctrl & 0x00000f00) >> 8;
|
|
||||||
break;
|
|
||||||
case DCB_OUTPUT_ANALOG:
|
|
||||||
default:
|
default:
|
||||||
*conf = 0x00ff;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -410,7 +405,8 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
|
|||||||
pclk = pclk / 2;
|
pclk = pclk / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
|
data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
|
||||||
|
&ver, &hdr, &cnt, &len, &info2);
|
||||||
if (data && id < 0xff) {
|
if (data && id < 0xff) {
|
||||||
data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
|
data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -141,7 +141,8 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
|
|||||||
{
|
{
|
||||||
u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len);
|
u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len);
|
||||||
if (data) {
|
if (data) {
|
||||||
info->match = nvbios_rd16(bios, data + 0x00);
|
info->proto = nvbios_rd08(bios, data + 0x00);
|
||||||
|
info->flags = nvbios_rd16(bios, data + 0x01);
|
||||||
info->clkcmp[0] = nvbios_rd16(bios, data + 0x02);
|
info->clkcmp[0] = nvbios_rd16(bios, data + 0x02);
|
||||||
info->clkcmp[1] = nvbios_rd16(bios, data + 0x04);
|
info->clkcmp[1] = nvbios_rd16(bios, data + 0x04);
|
||||||
}
|
}
|
||||||
@ -149,12 +150,13 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
u16
|
u16
|
||||||
nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u16 type,
|
nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u8 proto, u8 flags,
|
||||||
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *info)
|
u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *info)
|
||||||
{
|
{
|
||||||
u16 data, idx = 0;
|
u16 data, idx = 0;
|
||||||
while ((data = nvbios_ocfg_parse(bios, outp, idx++, ver, hdr, cnt, len, info))) {
|
while ((data = nvbios_ocfg_parse(bios, outp, idx++, ver, hdr, cnt, len, info))) {
|
||||||
if (info->match == type)
|
if ((info->proto == proto || info->proto == 0xff) &&
|
||||||
|
(info->flags == flags))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user