diff options
author | Karol Herbst <[email protected]> | 2016-07-12 21:36:08 +0200 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2016-10-12 17:29:25 +1000 |
commit | 5e00e3263ba68bd32337063a43aa8467b27acd1d (patch) | |
tree | 57970a8bff5bebf7c47ac331d7906336c48ba455 | |
parent | 4b9ce6e7b68683ac3874f9ebb243eb6f29c46812 (diff) |
drm/nouveau/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 <[email protected]>
Reviewed-by: Martin Peres <[email protected]>
Signed-off-by: Ben Skeggs <[email protected]>
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 5e07bd3aaccc..ec59d58becdc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/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; } |