These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / subdev / volt / base.c
index 39f1580..50b5649 100644 (file)
  *
  * Authors: Ben Skeggs
  */
-#include <subdev/volt.h>
+#include "priv.h"
+
 #include <subdev/bios.h>
 #include <subdev/bios/vmap.h>
 #include <subdev/bios/volt.h>
 
-static int
+int
 nvkm_volt_get(struct nvkm_volt *volt)
 {
-       if (volt->vid_get) {
-               int ret = volt->vid_get(volt), i;
-               if (ret >= 0) {
-                       for (i = 0; i < volt->vid_nr; i++) {
-                               if (volt->vid[i].vid == ret)
-                                       return volt->vid[i].uv;
-                       }
-                       ret = -EINVAL;
+       int ret, i;
+
+       if (volt->func->volt_get)
+               return volt->func->volt_get(volt);
+
+       ret = volt->func->vid_get(volt);
+       if (ret >= 0) {
+               for (i = 0; i < volt->vid_nr; i++) {
+                       if (volt->vid[i].vid == ret)
+                               return volt->vid[i].uv;
                }
-               return ret;
+               ret = -EINVAL;
        }
-       return -ENODEV;
+       return ret;
 }
 
 static int
 nvkm_volt_set(struct nvkm_volt *volt, u32 uv)
 {
-       if (volt->vid_set) {
-               int i, ret = -EINVAL;
-               for (i = 0; i < volt->vid_nr; i++) {
-                       if (volt->vid[i].uv == uv) {
-                               ret = volt->vid_set(volt, volt->vid[i].vid);
-                               nv_debug(volt, "set %duv: %d\n", uv, ret);
-                               break;
-                       }
+       struct nvkm_subdev *subdev = &volt->subdev;
+       int i, ret = -EINVAL;
+
+       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);
+                       break;
                }
-               return ret;
        }
-       return -ENODEV;
+       return ret;
 }
 
 static int
 nvkm_volt_map(struct nvkm_volt *volt, u8 id)
 {
-       struct nvkm_bios *bios = nvkm_bios(volt);
+       struct nvkm_bios *bios = volt->subdev.device->bios;
        struct nvbios_vmap_entry info;
        u8  ver, len;
        u16 vmap;
@@ -82,10 +87,15 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id)
        return id ? id * 10000 : -ENODEV;
 }
 
-static int
+int
 nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition)
 {
-       int ret = nvkm_volt_map(volt, id);
+       int ret;
+
+       if (volt->func->set_id)
+               return volt->func->set_id(volt, id, condition);
+
+       ret = nvkm_volt_map(volt, id);
        if (ret >= 0) {
                int prev = nvkm_volt_get(volt);
                if (!condition || prev < 0 ||
@@ -134,51 +144,41 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
        }
 }
 
-int
-_nvkm_volt_init(struct nvkm_object *object)
+static int
+nvkm_volt_init(struct nvkm_subdev *subdev)
 {
-       struct nvkm_volt *volt = (void *)object;
-       int ret;
-
-       ret = nvkm_subdev_init(&volt->base);
-       if (ret)
-               return ret;
-
-       ret = volt->get(volt);
+       struct nvkm_volt *volt = nvkm_volt(subdev);
+       int ret = nvkm_volt_get(volt);
        if (ret < 0) {
                if (ret != -ENODEV)
-                       nv_debug(volt, "current voltage unknown\n");
+                       nvkm_debug(subdev, "current voltage unknown\n");
                return 0;
        }
-
-       nv_info(volt, "GPU voltage: %duv\n", ret);
+       nvkm_debug(subdev, "current voltage: %duv\n", ret);
        return 0;
 }
 
-void
-_nvkm_volt_dtor(struct nvkm_object *object)
+static void *
+nvkm_volt_dtor(struct nvkm_subdev *subdev)
 {
-       struct nvkm_volt *volt = (void *)object;
-       nvkm_subdev_destroy(&volt->base);
+       return nvkm_volt(subdev);
 }
 
-int
-nvkm_volt_create_(struct nvkm_object *parent, struct nvkm_object *engine,
-                 struct nvkm_oclass *oclass, int length, void **pobject)
-{
-       struct nvkm_bios *bios = nvkm_bios(parent);
-       struct nvkm_volt *volt;
-       int ret, i;
+static const struct nvkm_subdev_func
+nvkm_volt = {
+       .dtor = nvkm_volt_dtor,
+       .init = nvkm_volt_init,
+};
 
-       ret = nvkm_subdev_create_(parent, engine, oclass, 0, "VOLT",
-                                 "voltage", length, pobject);
-       volt = *pobject;
-       if (ret)
-               return ret;
+void
+nvkm_volt_ctor(const struct nvkm_volt_func *func, struct nvkm_device *device,
+              int index, struct nvkm_volt *volt)
+{
+       struct nvkm_bios *bios = device->bios;
+       int i;
 
-       volt->get = nvkm_volt_get;
-       volt->set = nvkm_volt_set;
-       volt->set_id = nvkm_volt_set_id;
+       nvkm_subdev_ctor(&nvkm_volt, device, index, 0, &volt->subdev);
+       volt->func = func;
 
        /* Assuming the non-bios device should build the voltage table later */
        if (bios)
@@ -186,19 +186,18 @@ nvkm_volt_create_(struct nvkm_object *parent, struct nvkm_object *engine,
 
        if (volt->vid_nr) {
                for (i = 0; i < volt->vid_nr; i++) {
-                       nv_debug(volt, "VID %02x: %duv\n",
-                                volt->vid[i].vid, volt->vid[i].uv);
-               }
-
-               /*XXX: this is an assumption.. there probably exists boards
-                * out there with i2c-connected voltage controllers too..
-                */
-               ret = nvkm_voltgpio_init(volt);
-               if (ret == 0) {
-                       volt->vid_get = nvkm_voltgpio_get;
-                       volt->vid_set = nvkm_voltgpio_set;
+                       nvkm_debug(&volt->subdev, "VID %02x: %duv\n",
+                                  volt->vid[i].vid, volt->vid[i].uv);
                }
        }
+}
 
-       return ret;
+int
+nvkm_volt_new_(const struct nvkm_volt_func *func, struct nvkm_device *device,
+              int index, struct nvkm_volt **pvolt)
+{
+       if (!(*pvolt = kzalloc(sizeof(**pvolt), GFP_KERNEL)))
+               return -ENOMEM;
+       nvkm_volt_ctor(func, device, index, *pvolt);
+       return 0;
 }