浏览代码

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 <karolherbst@gmail.com>
Reviewed-by: Martin Peres <martin.peres@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Karol Herbst 9 年之前
父节点
当前提交
5e00e3263b
共有 1 个文件被更改,包括 17 次插入5 次删除
  1. 17 5
      drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c

+ 17 - 5
drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c

@@ -51,18 +51,30 @@ static int
 nvkm_volt_set(struct nvkm_volt *volt, u32 uv)
 nvkm_volt_set(struct nvkm_volt *volt, u32 uv)
 {
 {
 	struct nvkm_subdev *subdev = &volt->subdev;
 	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)
 	if (volt->func->volt_set)
 		return volt->func->volt_set(volt, uv);
 		return volt->func->volt_set(volt, uv);
 
 
 	for (i = 0; i < volt->vid_nr; i++) {
 	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;
 			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;
 	return ret;
 }
 }