[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