drm/nouveau/volt: Properly detect entry based voltage tables
authorKarol Herbst <karolherbst@gmail.com>
Tue, 12 Jul 2016 19:36:08 +0000 (21:36 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 12 Oct 2016 07:29:19 +0000 (17:29 +1000)
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.
v5: Reverse flag name.

Signed-off-by: Karol Herbst <karolherbst@gmail.com>
Reviewed-by: Martin Peres <martin.peres@free.fr>
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c

index b0df610cec2b5ba3a28966092ec53726ef9e00d9..23f3d1b93ebbbe3852d8c0a530a43e858772de43 100644 (file)
@@ -13,8 +13,9 @@ struct nvbios_volt {
        u32 base;
 
        /* GPIO mode */
-       u8  vidmask;
-       s16 step;
+       bool ranged;
+       u8   vidmask;
+       s16  step;
 
        /* PWM mode */
        u32 pwm_freq;
index 81a47b22617a401b1f2e945897a57ed62b2a4e4d..4504822ace51cb9a6dc07098b797269fa096f2c5 100644 (file)
@@ -75,20 +75,24 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
        case 0x12:
                info->type    = NVBIOS_VOLT_GPIO;
                info->vidmask = nvbios_rd08(bios, volt + 0x04);
+               info->ranged  = false;
                break;
        case 0x20:
                info->type    = NVBIOS_VOLT_GPIO;
                info->vidmask = nvbios_rd08(bios, volt + 0x05);
+               info->ranged  = false;
                break;
        case 0x30:
                info->type    = NVBIOS_VOLT_GPIO;
                info->vidmask = nvbios_rd08(bios, volt + 0x04);
+               info->ranged  = false;
                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->ranged  = true; /* XXX: find the flag byte */
                /*XXX*/
                info->min     = 0;
                info->max     = info->base;
@@ -104,9 +108,11 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
                        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->ranged  =
+                               !!(nvbios_rd08(bios, volt + 0x4) & 0x2);
                }
                break;
        }
index 1c3d23b0e84ad063c0c11310828327e232ac03bd..53a1cba6ad8d4c49bba0fa4118879a0bafcef447 100644 (file)
@@ -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.ranged) {
+               nvkm_debug(subdev, "found ranged based VIDs\n");
                volt->min_uv = info.min;
                volt->max_uv = info.max;
                for (i = 0; i < info.vidmask + 1; i++) {
@@ -132,7 +134,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.ranged) {
+               nvkm_debug(subdev, "found entry based VIDs\n");
                volt->min_uv = 0xffffffff;
                volt->max_uv = 0;
                for (i = 0; i < cnt; i++) {