[Nouveau] [PATCH v2 16/22] volt: don't require perfect fit
Martin Peres
martin.peres at free.fr
Mon Mar 28 22:55:34 UTC 2016
On 21/03/16 18:16, Karol Herbst wrote:
> 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
This is indeed the goal.
>
> Signed-off-by: Karol Herbst <nouveau at karolherbst.de>
> ---
> drm/nouveau/nvkm/subdev/volt/base.c | 25 ++++++++++++++++++++++---
> 1 file changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c
> index e741383..58738e3 100644
> --- a/drm/nouveau/nvkm/subdev/volt/base.c
> +++ b/drm/nouveau/nvkm/subdev/volt/base.c
> @@ -51,18 +51,37 @@ 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, err, 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);
> + if (i == 0) {
> + best = 0;
> + err = volt->vid[i].uv - uv;
> + } else {
> + int new_err = volt->vid[i].uv - uv;
> + if (abs(new_err) < abs(err)
> + || (err < 0 && new_err >= 0)) {
> + best = i;
> + err = new_err;
> + }
> + }
> +
> + if (err == 0) {
> + ret = volt->func->vid_set(volt, volt->vid[best].vid);
> nvkm_debug(subdev, "set %duv: %d\n", uv, ret);
> break;
> }
> }
> +
> + if (best != -1) {
> + 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;
> }
The code is really weird though :o How about the following? It would
make it much more readable and actually do what your commit message says.
int best = -1;
u32 best_abs_err = -1;
for (i = 0; i < volt->vid_nr; i++) {
int abs_err = abs(volt->vid[i].uv - uv);
if (volt->vid[i].uv >= uv && abs_err < best_abs_err) {
best = i;
best_abs_err = abs_err;
if (abs_err == 0)
break;
}
}
if (best >= 0) {
ret = volt->func->vid_set(volt, volt->vid[best].vid);
nvkm_debug(subdev, "set %duv: %d\n", uv, ret);
} else {
/* return an error to tell that we cannot use the wanted clock since we cannot select the needed voltage! */
}
More information about the Nouveau
mailing list