[Nouveau] [PATCH v3 18/29] volt: add coefficients I found on my gpu

Karol Herbst nouveau at karolherbst.de
Thu Apr 7 21:24:08 UTC 2016


I am sure that those are a bit different on other GPUs, but while testing
the error range compared to nvidia was around 100%+-3%.

Without this change we are most of the time around 10% below nvidias voltage,
so this change causes no harm and improves the situation a lot already.

The remaining task for this is to figure out which of these constants are
chip specific and from where to get the chip specific factors

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.

Signed-off-by: Karol Herbst <nouveau at karolherbst.de>
---
 drm/nouveau/nvkm/subdev/volt/base.c | 53 ++++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 6 deletions(-)

diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c
index 552fecd..654b88e 100644
--- a/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drm/nouveau/nvkm/subdev/volt/base.c
@@ -110,13 +110,54 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp)
 
 	vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info);
 	if (vmap) {
-		if (info.link != 0xff) {
-			int ret = nvkm_volt_map(volt, info.link, temp);
-			if (ret < 0)
-				return ret;
-			info.min += ret;
+		switch (ver) {
+		case 0x10:
+			if (info.link != 0xff) {
+				int ret = nvkm_volt_map(volt, info.link, temp);
+				if (ret < 0)
+					return ret;
+				info.min += ret;
+			}
+			return info.min;
+		case 0x20: {
+			s32 result;
+			switch (info.mode) {
+			case 0x0:
+				result =  info.arg[0] / 10;
+				result += info.arg[1] * 168;
+				result += info.arg[2] * 28;
+				break;
+			case 0x1:
+				result =  (info.arg[0] / 1675) * 100;
+				result += info.arg[1]          * 100;
+				result += (info.arg[2] / 10)   * 153 * temp;
+				result += info.arg[3]          * 100 * temp;
+				result += info.arg[4]          * 41;
+				result += (info.arg[5] * (temp * temp)) / 15;
+				break;
+			case 0x3:
+				result = (info.min + info.max) / 2;
+				break;
+			case 0x2:
+			default:
+				result = info.min;
+				break;
+			}
+			result = min(max(result, (s32)info.min),
+				     (s32)info.max);
+
+			if (info.link != 0xff) {
+				int ret = nvkm_volt_map(volt, info.link, temp);
+				if (ret < 0)
+					return ret;
+				result += ret;
+			}
+
+			return result;
+		}
+		default:
+			return -ENODEV;
 		}
-		return info.min;
 	}
 
 	return id ? id * 10000 : -ENODEV;
-- 
2.8.1



More information about the Nouveau mailing list