[v2,2/2] volt: properly detect entry based voltage tables

Submitted by Karol Herbst on March 16, 2016, 6:17 p.m.

Details

Message ID 1458152267-7426-1-git-send-email-nouveau@karolherbst.de
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Karol Herbst March 16, 2016, 6:17 p.m.
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 of the table

Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
---
 drm/nouveau/include/nvkm/subdev/bios/volt.h |  5 +--
 drm/nouveau/nvkm/subdev/bios/volt.c         | 47 ++++++++++++++++-------------
 drm/nouveau/nvkm/subdev/volt/base.c         |  7 +++--
 3 files changed, 34 insertions(+), 25 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/include/nvkm/subdev/bios/volt.h b/drm/nouveau/include/nvkm/subdev/bios/volt.h
index b0df610..0d91c24 100644
--- a/drm/nouveau/include/nvkm/subdev/bios/volt.h
+++ b/drm/nouveau/include/nvkm/subdev/bios/volt.h
@@ -13,8 +13,9 @@  struct nvbios_volt {
 	u32 base;
 
 	/* GPIO mode */
-	u8  vidmask;
-	s16 step;
+	bool entry_based;
+	u8   vidmask;
+	s16  step;
 
 	/* PWM mode */
 	u32 pwm_freq;
diff --git a/drm/nouveau/nvkm/subdev/bios/volt.c b/drm/nouveau/nvkm/subdev/bios/volt.c
index 81a47b2..77e7b75 100644
--- a/drm/nouveau/nvkm/subdev/bios/volt.c
+++ b/drm/nouveau/nvkm/subdev/bios/volt.c
@@ -73,40 +73,45 @@  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);
+		info->type        = NVBIOS_VOLT_GPIO;
+		info->vidmask     = nvbios_rd08(bios, volt + 0x04);
+		info->entry_based = true;
 		break;
 	case 0x20:
-		info->type    = NVBIOS_VOLT_GPIO;
-		info->vidmask = nvbios_rd08(bios, volt + 0x05);
+		info->type        = NVBIOS_VOLT_GPIO;
+		info->vidmask     = nvbios_rd08(bios, volt + 0x05);
+		info->entry_based = true;
 		break;
 	case 0x30:
-		info->type    = NVBIOS_VOLT_GPIO;
-		info->vidmask = nvbios_rd08(bios, volt + 0x04);
+		info->type        = NVBIOS_VOLT_GPIO;
+		info->vidmask     = nvbios_rd08(bios, volt + 0x04);
+		info->entry_based = true;
 		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->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->entry_based = false; /* XXX: check for it */
 		/*XXX*/
-		info->min     = 0;
-		info->max     = info->base;
+		info->min         = 0;
+		info->max         = info->base;
 		break;
 	case 0x50:
-		info->min     = nvbios_rd32(bios, volt + 0x0a);
-		info->max     = nvbios_rd32(bios, volt + 0x0e);
-		info->base    = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
+		info->min         = nvbios_rd32(bios, volt + 0x0a);
+		info->max         = nvbios_rd32(bios, volt + 0x0e);
+		info->base        = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
 
 		/* 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);
+			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);
+			info->type        = NVBIOS_VOLT_GPIO;
+			info->vidmask     = nvbios_rd08(bios, volt + 0x06);
+			info->step        = nvbios_rd16(bios, volt + 0x16);
+			info->entry_based = !(nvbios_rd08(bios, volt + 0x4) & 0x2);
 		}
 		break;
 	}
diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c
index 50b5649..4653f3f 100644
--- a/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drm/nouveau/nvkm/subdev/volt/base.c
@@ -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.entry_based) {
+		nvkm_debug(subdev, "found header based VIDs\n");
 		for (i = 0; i < info.vidmask + 1; i++) {
 			if (info.base >= info.min &&
 				info.base <= info.max) {
@@ -130,7 +132,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.entry_based) {
+		nvkm_debug(subdev, "found entry based VIDs\n");
 		for (i = 0; i < cnt; i++) {
 			data = nvbios_volt_entry_parse(bios, i, &ver, &hdr,
 						       &ivid);

Comments

On 16/03/16 20:17, Karol Herbst wrote:
> 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 of the table
>
> Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
> ---
>   drm/nouveau/include/nvkm/subdev/bios/volt.h |  5 +--
>   drm/nouveau/nvkm/subdev/bios/volt.c         | 47 ++++++++++++++++-------------
>   drm/nouveau/nvkm/subdev/volt/base.c         |  7 +++--
>   3 files changed, 34 insertions(+), 25 deletions(-)
>
> diff --git a/drm/nouveau/include/nvkm/subdev/bios/volt.h b/drm/nouveau/include/nvkm/subdev/bios/volt.h
> index b0df610..0d91c24 100644
> --- a/drm/nouveau/include/nvkm/subdev/bios/volt.h
> +++ b/drm/nouveau/include/nvkm/subdev/bios/volt.h
> @@ -13,8 +13,9 @@ struct nvbios_volt {
>   	u32 base;
>   
>   	/* GPIO mode */
> -	u8  vidmask;
> -	s16 step;
> +	bool entry_based;
> +	u8   vidmask;
> +	s16  step;
>   
>   	/* PWM mode */
>   	u32 pwm_freq;
> diff --git a/drm/nouveau/nvkm/subdev/bios/volt.c b/drm/nouveau/nvkm/subdev/bios/volt.c
> index 81a47b2..77e7b75 100644
> --- a/drm/nouveau/nvkm/subdev/bios/volt.c
> +++ b/drm/nouveau/nvkm/subdev/bios/volt.c
> @@ -73,40 +73,45 @@ 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);
> +		info->type        = NVBIOS_VOLT_GPIO;
> +		info->vidmask     = nvbios_rd08(bios, volt + 0x04);
> +		info->entry_based = true;
>   		break;
>   	case 0x20:
> -		info->type    = NVBIOS_VOLT_GPIO;
> -		info->vidmask = nvbios_rd08(bios, volt + 0x05);
> +		info->type        = NVBIOS_VOLT_GPIO;
> +		info->vidmask     = nvbios_rd08(bios, volt + 0x05);
> +		info->entry_based = true;
>   		break;
>   	case 0x30:
> -		info->type    = NVBIOS_VOLT_GPIO;
> -		info->vidmask = nvbios_rd08(bios, volt + 0x04);
> +		info->type        = NVBIOS_VOLT_GPIO;
> +		info->vidmask     = nvbios_rd08(bios, volt + 0x04);
> +		info->entry_based = true;
>   		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->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->entry_based = false; /* XXX: check for it */
/* Overridden when parsing the flag byte */
>   		/*XXX*/
> -		info->min     = 0;
> -		info->max     = info->base;
> +		info->min         = 0;
> +		info->max         = info->base;
>   		break;
>   	case 0x50:
> -		info->min     = nvbios_rd32(bios, volt + 0x0a);
> -		info->max     = nvbios_rd32(bios, volt + 0x0e);
> -		info->base    = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
> +		info->min         = nvbios_rd32(bios, volt + 0x0a);
> +		info->max         = nvbios_rd32(bios, volt + 0x0e);
> +		info->base        = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff;
>   
>   		/* 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);
> +			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);
> +			info->type        = NVBIOS_VOLT_GPIO;
> +			info->vidmask     = nvbios_rd08(bios, volt + 0x06);
> +			info->step        = nvbios_rd16(bios, volt + 0x16);
> +			info->entry_based = !(nvbios_rd08(bios, volt + 0x4) & 0x2);
>   		}
>   		break;
>   	}
> diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c
> index 50b5649..4653f3f 100644
> --- a/drm/nouveau/nvkm/subdev/volt/base.c
> +++ b/drm/nouveau/nvkm/subdev/volt/base.c
> @@ -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.entry_based) {
> +		nvkm_debug(subdev, "found header based VIDs\n");
>   		for (i = 0; i < info.vidmask + 1; i++) {
>   			if (info.base >= info.min &&
>   				info.base <= info.max) {
> @@ -130,7 +132,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.entry_based) {
> +		nvkm_debug(subdev, "found entry based VIDs\n");
>   		for (i = 0; i < cnt; i++) {
>   			data = nvbios_volt_entry_parse(bios, i, &ver, &hdr,
>   						       &ivid);

Both patches are:

Reviewed-by: Martin Peres <martin.peres@free.fr>