[19/19] volt: add coefficients I found on my gpu

Submitted by Karol Herbst on March 17, 2016, 11:03 p.m.

Details

Message ID 1458255836-3878-20-git-send-email-nouveau@karolherbst.de
State New
Headers show
Series "Volting/Clocking improvements for Fermi and newer" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Karol Herbst March 17, 2016, 11:03 p.m.
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

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

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c
index 58738e3..2b3f460 100644
--- a/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drm/nouveau/nvkm/subdev/volt/base.c
@@ -117,13 +117,55 @@  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;
+			u16 temp = 40;
+			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;