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: 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>
This commit is contained in:
@@ -13,6 +13,7 @@ struct nvbios_volt {
|
|||||||
u32 base;
|
u32 base;
|
||||||
|
|
||||||
/* GPIO mode */
|
/* GPIO mode */
|
||||||
|
bool ranged;
|
||||||
u8 vidmask;
|
u8 vidmask;
|
||||||
s16 step;
|
s16 step;
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
@@ -107,6 +111,8 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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++) {
|
||||||
|
Reference in New Issue
Block a user