On 16/03/16 20:17, Karol Herbst wrote:
there is a field in the voltage table which tells us if the VIDs are taken from
the entries or calculated through the header

v2: don't break older versions of the table

Signed-off-by: Karol Herbst <nouv...@karolherbst.de>
---
  drm/nouveau/include/nvkm/subdev/bios/volt.h |  5 +--
  drm/nouveau/nvkm/subdev/bios/volt.c         | 47 ++++++++++++++++-------------
  drm/nouveau/nvkm/subdev/volt/base.c         |  7 +++--
  3 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/drm/nouveau/include/nvkm/subdev/bios/volt.h 
b/drm/nouveau/include/nvkm/subdev/bios/volt.h
index b0df610..0d91c24 100644
--- a/drm/nouveau/include/nvkm/subdev/bios/volt.h
+++ b/drm/nouveau/include/nvkm/subdev/bios/volt.h
@@ -13,8 +13,9 @@ struct nvbios_volt {
        u32 base;
/* GPIO mode */
-       u8  vidmask;
-       s16 step;
+       bool entry_based;
+       u8   vidmask;
+       s16  step;
/* PWM mode */
        u32 pwm_freq;
diff --git a/drm/nouveau/nvkm/subdev/bios/volt.c 
b/drm/nouveau/nvkm/subdev/bios/volt.c
index 81a47b2..77e7b75 100644
--- a/drm/nouveau/nvkm/subdev/bios/volt.c
+++ b/drm/nouveau/nvkm/subdev/bios/volt.c
@@ -73,40 +73,45 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, 
u8 *cnt, u8 *len,
        memset(info, 0x00, sizeof(*info));
        switch (!!volt * *ver) {
        case 0x12:
-               info->type    = NVBIOS_VOLT_GPIO;
-               info->vidmask = nvbios_rd08(bios, volt + 0x04);
+               info->type        = NVBIOS_VOLT_GPIO;
+               info->vidmask     = nvbios_rd08(bios, volt + 0x04);
+               info->entry_based = true;
                break;
        case 0x20:
-               info->type    = NVBIOS_VOLT_GPIO;
-               info->vidmask = nvbios_rd08(bios, volt + 0x05);
+               info->type        = NVBIOS_VOLT_GPIO;
+               info->vidmask     = nvbios_rd08(bios, volt + 0x05);
+               info->entry_based = true;
                break;
        case 0x30:
-               info->type    = NVBIOS_VOLT_GPIO;
-               info->vidmask = nvbios_rd08(bios, volt + 0x04);
+               info->type        = NVBIOS_VOLT_GPIO;
+               info->vidmask     = nvbios_rd08(bios, volt + 0x04);
+               info->entry_based = true;
                break;
        case 0x40:
-               info->type    = NVBIOS_VOLT_GPIO;
-               info->base    = nvbios_rd32(bios, volt + 0x04);
-               info->step    = nvbios_rd16(bios, volt + 0x08);
-               info->vidmask = nvbios_rd08(bios, volt + 0x0b);
+               info->type        = NVBIOS_VOLT_GPIO;
+               info->base        = nvbios_rd32(bios, volt + 0x04);
+               info->step        = nvbios_rd16(bios, volt + 0x08);
+               info->vidmask     = nvbios_rd08(bios, volt + 0x0b);
+               info->entry_based = false; /* XXX: check for it */
/* Overridden when parsing the flag byte */
                /*XXX*/
-               info->min     = 0;
-               info->max     = info->base;
+               info->min         = 0;
+               info->max         = info->base;
                break;
        case 0x50:
-               info->min     = nvbios_rd32(bios, volt + 0x0a);
-               info->max     = nvbios_rd32(bios, volt + 0x0e);
-               info->base    = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
+               info->min         = nvbios_rd32(bios, volt + 0x0a);
+               info->max         = nvbios_rd32(bios, volt + 0x0e);
+               info->base        = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
/* offset 4 seems to be a flag byte */
                if (nvbios_rd32(bios, volt + 0x4) & 1) {
-                       info->type      = NVBIOS_VOLT_PWM;
-                       info->pwm_freq  = nvbios_rd32(bios, volt + 0x5) / 1000;
-                       info->pwm_range = nvbios_rd32(bios, volt + 0x16);
+                       info->type        = NVBIOS_VOLT_PWM;
+                       info->pwm_freq    = nvbios_rd32(bios, volt + 0x5) / 
1000;
+                       info->pwm_range   = nvbios_rd32(bios, volt + 0x16);
                } else {
-                       info->type      = NVBIOS_VOLT_GPIO;
-                       info->vidmask   = nvbios_rd08(bios, volt + 0x06);
-                       info->step      = nvbios_rd16(bios, volt + 0x16);
+                       info->type        = NVBIOS_VOLT_GPIO;
+                       info->vidmask     = nvbios_rd08(bios, volt + 0x06);
+                       info->step        = nvbios_rd16(bios, volt + 0x16);
+                       info->entry_based = !(nvbios_rd08(bios, volt + 0x4) & 
0x2);
                }
                break;
        }
diff --git a/drm/nouveau/nvkm/subdev/volt/base.c 
b/drm/nouveau/nvkm/subdev/volt/base.c
index 50b5649..4653f3f 100644
--- a/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drm/nouveau/nvkm/subdev/volt/base.c
@@ -112,6 +112,7 @@ nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int 
condition)
  static void
  nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
  {
+       struct nvkm_subdev *subdev = &bios->subdev;
        struct nvbios_volt_entry ivid;
        struct nvbios_volt info;
        u8  ver, hdr, cnt, len;
@@ -119,7 +120,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct 
nvkm_volt *volt)
        int i;
data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info);
-       if (data && info.vidmask && info.base && info.step) {
+       if (data && info.vidmask && info.base && info.step && 
!info.entry_based) {
+               nvkm_debug(subdev, "found header based VIDs\n");
                for (i = 0; i < info.vidmask + 1; i++) {
                        if (info.base >= info.min &&
                                info.base <= info.max) {
@@ -130,7 +132,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct 
nvkm_volt *volt)
                        info.base += info.step;
                }
                volt->vid_mask = info.vidmask;
-       } else if (data && info.vidmask) {
+       } else if (data && info.vidmask && info.entry_based) {
+               nvkm_debug(subdev, "found entry based VIDs\n");
                for (i = 0; i < cnt; i++) {
                        data = nvbios_volt_entry_parse(bios, i, &ver, &hdr,
                                                       &ivid);

Both patches are:

Reviewed-by: Martin Peres <martin.pe...@free.fr>
_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to