From 7bddeba9663962a5bd507e636c84361852314f04 Mon Sep 17 00:00:00 2001 From: Martin Peres Date: Wed, 9 Sep 2015 04:05:50 +0300 Subject: [PATCH] drm/nouveau/bios/volt: add support for pwm-based volt management Signed-off-by: Martin Peres Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/subdev/bios/volt.h | 15 ++++++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c | 17 +++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h index eb2de4b85bbd..b0df610cec2b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h @@ -1,11 +1,24 @@ #ifndef __NVBIOS_VOLT_H__ #define __NVBIOS_VOLT_H__ + +enum nvbios_volt_type { + NVBIOS_VOLT_GPIO = 0, + NVBIOS_VOLT_PWM, +}; + struct nvbios_volt { - u8 vidmask; + enum nvbios_volt_type type; u32 min; u32 max; u32 base; + + /* GPIO mode */ + u8 vidmask; s16 step; + + /* PWM mode */ + u32 pwm_freq; + u32 pwm_range; }; u16 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c index 615804c3887b..6e0a33648be9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c @@ -73,15 +73,19 @@ 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); break; case 0x20: + info->type = NVBIOS_VOLT_GPIO; info->vidmask = nvbios_rd08(bios, volt + 0x05); break; case 0x30: + info->type = NVBIOS_VOLT_GPIO; info->vidmask = nvbios_rd08(bios, volt + 0x04); 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); @@ -90,11 +94,20 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, info->max = info->base; break; case 0x50: - info->vidmask = nvbios_rd08(bios, volt + 0x06); info->min = nvbios_rd32(bios, volt + 0x0a); info->max = nvbios_rd32(bios, volt + 0x0e); info->base = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff; - info->step = nvbios_rd16(bios, volt + 0x16); + + /* 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); + } else { + info->type = NVBIOS_VOLT_GPIO; + info->vidmask = nvbios_rd08(bios, volt + 0x06); + info->step = nvbios_rd16(bios, volt + 0x16); + } break; } return volt; -- 2.20.1