Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc9139d2 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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: default avatarBen Skeggs <bskeggs@redhat.com>
Cc: stable@vger.kernel.org
parent 92181d47
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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 *);

struct nvbios_ocfg {
	u16 match;
	u8  proto;
	u8  flags;
	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);
u16 nvbios_ocfg_parse(struct nvkm_bios *, u16 outp, u8 idx,
		      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 *);
u16 nvbios_oclk_match(struct nvkm_bios *, u16 cmp, u32 khz);
#endif
+5 −8
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
	mask |= 0x0001 << or;
	mask |= 0x0100 << head;


	list_for_each_entry(outp, &disp->base.outp, head) {
		if ((outp->info.hasht & 0xff) == type &&
		    (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)
		return NULL;

	*conf = (ctrl & 0x00000f00) >> 8;
	switch (outp->info.type) {
	case DCB_OUTPUT_TMDS:
		*conf = (ctrl & 0x00000f00) >> 8;
		if (*conf == 5)
			*conf |= 0x0100;
		break;
	case DCB_OUTPUT_LVDS:
		*conf = disp->sor.lvdsconf;
		break;
	case DCB_OUTPUT_DP:
		*conf = (ctrl & 0x00000f00) >> 8;
		*conf |= disp->sor.lvdsconf;
		break;
	case DCB_OUTPUT_ANALOG:
	default:
		*conf = 0x00ff;
		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) {
		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
		if (data) {
+4 −8
Original line number Diff line number Diff line
@@ -387,22 +387,17 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
	if (!outp)
		return NULL;

	*conf = (ctrl & 0x00000f00) >> 8;
	if (outp->info.location == 0) {
		switch (outp->info.type) {
		case DCB_OUTPUT_TMDS:
			*conf = (ctrl & 0x00000f00) >> 8;
			if (*conf == 5)
				*conf |= 0x0100;
			break;
		case DCB_OUTPUT_LVDS:
			*conf = disp->sor.lvdsconf;
			break;
		case DCB_OUTPUT_DP:
			*conf = (ctrl & 0x00000f00) >> 8;
			*conf |= disp->sor.lvdsconf;
			break;
		case DCB_OUTPUT_ANALOG:
		default:
			*conf = 0x00ff;
			break;
		}
	} else {
@@ -410,7 +405,8 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
		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) {
		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
		if (data) {
+5 −3
Original line number Diff line number Diff line
@@ -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);
	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[1] = nvbios_rd16(bios, data + 0x04);
	}
@@ -149,12 +150,13 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
}

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)
{
	u16 data, idx = 0;
	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;
	}
	return data;