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

Commit 114653c7 authored by Karol Herbst's avatar Karol Herbst Committed by Ben Skeggs
Browse files

drm/nouveau/volt: Make use of cvb coefficients



I'm quite sure that those coefficients are real close, because while
testing the biggest error compared to nvidia was around -1.5% (biggest
error with right coefficients is 12.5mV / 600mV = 2%).

These coefficients were REed by modifing the voltage map entries and by
calculating the set voltage back until I was able to forecast which voltage
nvidia sets for a given voltage map entry.

With these formulars I am able to precisely predict at which exact
temperature Nvidia down- or upvolts due to a changed therm reading.

That's why I am quite sure these are right, or at least really really
close.

v4: Use better coefficients and speedo.
v5: Add error message when speedo is missing.

Signed-off-by: default avatarKarol Herbst <karolherbst@gmail.com>
Reviewed-by: default avatarMartin Peres <martin.peres@free.fr>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 08de5743
Loading
Loading
Loading
Loading
+36 −2
Original line number Diff line number Diff line
@@ -110,13 +110,47 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp)

	vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info);
	if (vmap) {
		s64 result;

		if (volt->speedo < 0)
			return volt->speedo;

		if (ver == 0x10 || (ver == 0x20 && info.mode == 0)) {
			result  =  (s64)info.arg[0] / 10;
			result += ((s64)info.arg[1] * volt->speedo) / 10;
			result += ((s64)info.arg[2] * volt->speedo * volt->speedo) / 100000;
		} else if (ver == 0x20) {
			switch (info.mode) {
			/* 0x0 handled above! */
			case 0x1:
				result =  ((s64)info.arg[0] * 15625) >> 18;
				result += ((s64)info.arg[1] * volt->speedo * 15625) >> 18;
				result += ((s64)info.arg[2] * temp * 15625) >> 10;
				result += ((s64)info.arg[3] * volt->speedo * temp * 15625) >> 18;
				result += ((s64)info.arg[4] * volt->speedo * volt->speedo * 15625) >> 30;
				result += ((s64)info.arg[5] * temp * temp * 15625) >> 18;
				break;
			case 0x3:
				result = (info.min + info.max) / 2;
				break;
			case 0x2:
			default:
				result = info.min;
				break;
			}
		} else {
			return -ENODEV;
		}

		result = min(max(result, (s64)info.min), (s64)info.max);

		if (info.link != 0xff) {
			int ret = nvkm_volt_map(volt, info.link, temp);
			if (ret < 0)
				return ret;
			info.min += ret;
			result += ret;
		}
		return info.min;
		return result;
	}

	return id ? id * 10000 : -ENODEV;