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 <[email protected]> --- 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 _______________________________________________ Nouveau mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/nouveau
