summaryrefslogtreecommitdiff
path: root/drm/nouveau/nvkm/subdev
diff options
context:
space:
mode:
authorKarol Herbst <karolherbst@gmail.com>2016-07-12 21:36:08 +0200
committerBen Skeggs <bskeggs@redhat.com>2016-11-04 17:17:04 +1000
commitc0f6b0e7ec26e76c7a470e7be3ba045212fa0a62 (patch)
treed63d90b11fbfc31b50a0ff21b32274e92d9de2af /drm/nouveau/nvkm/subdev
parente087c9a718e41111b0764b04cc21c78a83490f77 (diff)
downloadnouveau-c0f6b0e7ec26e76c7a470e7be3ba045212fa0a62.tar.gz
volt: Don't require perfect fit
If we calculate the voltage in the table right, we get all kinds of values, which never fit the hardware steps, so we use the closest higher value the hardware can do. v3: Simplify the implementation. v5: Initialize best_err with volt->max_uv. Signed-off-by: Karol Herbst <karolherbst@gmail.com> Reviewed-by: Martin Peres <martin.peres@free.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drm/nouveau/nvkm/subdev')
-rw-r--r--drm/nouveau/nvkm/subdev/volt/base.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c
index 5e07bd3aa..ec59d58be 100644
--- a/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drm/nouveau/nvkm/subdev/volt/base.c
@@ -51,18 +51,30 @@ static int
nvkm_volt_set(struct nvkm_volt *volt, u32 uv)
{
struct nvkm_subdev *subdev = &volt->subdev;
- int i, ret = -EINVAL;
+ int i, ret = -EINVAL, best_err = volt->max_uv, best = -1;
if (volt->func->volt_set)
return volt->func->volt_set(volt, uv);
for (i = 0; i < volt->vid_nr; i++) {
- if (volt->vid[i].uv == uv) {
- ret = volt->func->vid_set(volt, volt->vid[i].vid);
- nvkm_debug(subdev, "set %duv: %d\n", uv, ret);
+ int err = volt->vid[i].uv - uv;
+ if (err < 0 || err > best_err)
+ continue;
+
+ best_err = err;
+ best = i;
+ if (best_err == 0)
break;
- }
}
+
+ if (best == -1) {
+ nvkm_error(subdev, "couldn't set %iuv\n", uv);
+ return ret;
+ }
+
+ ret = volt->func->vid_set(volt, volt->vid[best].vid);
+ nvkm_debug(subdev, "set req %duv to %duv: %d\n", uv,
+ volt->vid[best].uv, ret);
return ret;
}