drm/nvc0-: Fix voltage obtained from vbios.
Subsystems (3)
PATCH 1/1 drm/nvc0-: Fix voltage obtained from vbios.
Coefficients are based on the formula:
uV = 0.1 * arg[0] + 150.5 * arg[1] + 22.65025 * arg[2]
It seems to be rounded downwards. I have no idea why the voltage isn't specified in the bios directly.
Signed-off-by Maarten Lankhorst <[email protected]>
----
drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c +15 -4
@@ -87,14 +87,25 @@ nvbios_vmap_entry_parse(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len,u16 vmap =nvbios_vmap_entry (bios, idx, ver, len);memset (info,0x00 ,sizeof (*info));switch (!!vmap * *ver) { -case 0x10 : +case 0x10 : { +s32 accum, b, c; + info->link =0xff ; info->min =nv_ro32 (bios, vmap +0x00 ); info->max =nv_ro32 (bios, vmap +0x04 ); - info->arg[0 ] =nv_ro32 (bios, vmap +0x08 ); - info->arg[1 ] =nv_ro32 (bios, vmap +0x0c ); - info->arg[2 ] =nv_ro32 (bios, vmap +0x10 ); + + accum =nv_ro32 (bios, vmap +0x08 ); + b =nv_ro32 (bios, vmap +0x0c ); + c =nv_ro32 (bios, vmap +0x10 ); + + accum += b *1505 ; + accum += (c *453 /2 ) + c /400 ; + accum /=10 ; + +if (accum > info->min) + info->min =min ((u32 )accum, info->max);break ; + }case 0x20 : info->unk0 =nv_ro08 (bios, vmap +0x00 ); info->link =nv_ro08 (bios, vmap +0x01 );
drivers/gpu/drm/nouveau/core/subdev/volt/base.c +15 -4
@@ -50,12 +50,23 @@ nouveau_volt_set(struct nouveau_volt *volt, u32 uv) {if (volt->vid_set) {int i, ret = -EINVAL ; +u32 best_uv =INT_MAX , best_vid =0 ; +for (i =0 ; i < volt->vid_nr; i++) { -if (volt->vid[i].uv == uv) { - ret = volt->vid_set (volt, volt->vid[i].vid); -nv_debug (volt,"set %duv: %d\n" , uv, ret); +s32 delta = volt->vid[i].uv - uv; + +if (delta <0 || best_uv < volt->vid[i].uv) +continue ; + + best_uv = volt->vid[i].uv; + best_vid = volt->vid[i].vid; +if (!delta)break ; - } + } + +if (best_uv <INT_MAX ) { + ret = volt->vid_set (volt, best_vid); +nv_debug (volt,"set %duv from %duv: %d\n" , best_uv, uv, ret); }return ret; }