From: Martin Peres <martin.peres@free.fr>
Date: Wed, 9 Sep 2015 01:05:50 +0000 (+0300)
Subject: drm/nouveau/bios/volt: add support for pwm-based volt management
X-Git-Tag: firefly_0821_release~176^2~493^2^2~46
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=7bddeba9663962a5bd507e636c84361852314f04;p=firefly-linux-kernel-4.4.55.git

drm/nouveau/bios/volt: add support for pwm-based volt management

Signed-off-by: Martin Peres <martin.peres@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
---

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;