Commit 17f486de authored by Karol Herbst's avatar Karol Herbst Committed by Ben Skeggs

drm/nouveau/volt: Properly detect entry based voltage tables

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: default avatarKarol Herbst <karolherbst@gmail.com>
Reviewed-by: default avatarMartin Peres <martin.peres@free.fr>
Tested-by: default avatarPierre Moreau <pierre.morrow@free.fr>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 32dd7f23
...@@ -13,8 +13,9 @@ struct nvbios_volt { ...@@ -13,8 +13,9 @@ struct nvbios_volt {
u32 base; u32 base;
/* GPIO mode */ /* GPIO mode */
u8 vidmask; bool ranged;
s16 step; u8 vidmask;
s16 step;
/* PWM mode */ /* PWM mode */
u32 pwm_freq; u32 pwm_freq;
......
...@@ -75,20 +75,24 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, ...@@ -75,20 +75,24 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
case 0x12: case 0x12:
info->type = NVBIOS_VOLT_GPIO; info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04); info->vidmask = nvbios_rd08(bios, volt + 0x04);
info->ranged = false;
break; break;
case 0x20: case 0x20:
info->type = NVBIOS_VOLT_GPIO; info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x05); info->vidmask = nvbios_rd08(bios, volt + 0x05);
info->ranged = false;
break; break;
case 0x30: case 0x30:
info->type = NVBIOS_VOLT_GPIO; info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04); info->vidmask = nvbios_rd08(bios, volt + 0x04);
info->ranged = false;
break; break;
case 0x40: case 0x40:
info->type = NVBIOS_VOLT_GPIO; info->type = NVBIOS_VOLT_GPIO;
info->base = nvbios_rd32(bios, volt + 0x04); info->base = nvbios_rd32(bios, volt + 0x04);
info->step = nvbios_rd16(bios, volt + 0x08); info->step = nvbios_rd16(bios, volt + 0x08);
info->vidmask = nvbios_rd08(bios, volt + 0x0b); info->vidmask = nvbios_rd08(bios, volt + 0x0b);
info->ranged = true; /* XXX: find the flag byte */
/*XXX*/ /*XXX*/
info->min = 0; info->min = 0;
info->max = info->base; info->max = info->base;
...@@ -104,9 +108,11 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, ...@@ -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_freq = nvbios_rd32(bios, volt + 0x5) / 1000;
info->pwm_range = nvbios_rd32(bios, volt + 0x16); info->pwm_range = nvbios_rd32(bios, volt + 0x16);
} else { } else {
info->type = NVBIOS_VOLT_GPIO; info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x06); info->vidmask = nvbios_rd08(bios, volt + 0x06);
info->step = nvbios_rd16(bios, volt + 0x16); info->step = nvbios_rd16(bios, volt + 0x16);
info->ranged =
!!(nvbios_rd08(bios, volt + 0x4) & 0x2);
} }
break; break;
} }
......
...@@ -112,6 +112,7 @@ nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition) ...@@ -112,6 +112,7 @@ nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition)
static void static void
nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) 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_entry ivid;
struct nvbios_volt info; struct nvbios_volt info;
u8 ver, hdr, cnt, len; u8 ver, hdr, cnt, len;
...@@ -119,7 +120,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) ...@@ -119,7 +120,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
int i; int i;
data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info); 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->min_uv = info.min;
volt->max_uv = info.max; volt->max_uv = info.max;
for (i = 0; i < info.vidmask + 1; i++) { for (i = 0; i < info.vidmask + 1; i++) {
...@@ -132,7 +134,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt) ...@@ -132,7 +134,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
info.base += info.step; info.base += info.step;
} }
volt->vid_mask = info.vidmask; 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->min_uv = 0xffffffff;
volt->max_uv = 0; volt->max_uv = 0;
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment