mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-04 04:44:37 +08:00
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: Karol Herbst <karolherbst@gmail.com> Reviewed-by: Martin Peres <martin.peres@free.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
08de5743db
commit
114653c759
@ -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);
|
vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info);
|
||||||
if (vmap) {
|
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) {
|
if (info.link != 0xff) {
|
||||||
int ret = nvkm_volt_map(volt, info.link, temp);
|
int ret = nvkm_volt_map(volt, info.link, temp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
info.min += ret;
|
result += ret;
|
||||||
}
|
}
|
||||||
return info.min;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return id ? id * 10000 : -ENODEV;
|
return id ? id * 10000 : -ENODEV;
|
||||||
|
Loading…
Reference in New Issue
Block a user