drm/nouveau/volt: allow non-bios voltage scaling

Move the vbios parsing out of init() and call it conditionally if the
platform has a vbios. Non-vbios platforms can use the ctor() to init the
data structures.

Signed-off-by: Vince Hsu <vinceh@nvidia.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Martin Peres <martin.peres@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Vince Hsu 2014-12-02 12:50:33 +08:00 committed by Ben Skeggs
parent c6f37e0ce6
commit 08c7f248be
1 changed files with 38 additions and 29 deletions

View File

@ -101,6 +101,41 @@ nouveau_volt_set_id(struct nouveau_volt *volt, u8 id, int condition)
return ret;
}
static void nouveau_volt_parse_bios(struct nouveau_bios *bios,
struct nouveau_volt *volt)
{
struct nvbios_volt_entry ivid;
struct nvbios_volt info;
u8 ver, hdr, cnt, len;
u16 data;
int i;
data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info);
if (data && info.vidmask && info.base && info.step) {
for (i = 0; i < info.vidmask + 1; i++) {
if (info.base >= info.min &&
info.base <= info.max) {
volt->vid[volt->vid_nr].uv = info.base;
volt->vid[volt->vid_nr].vid = i;
volt->vid_nr++;
}
info.base += info.step;
}
volt->vid_mask = info.vidmask;
} else if (data && info.vidmask) {
for (i = 0; i < cnt; i++) {
data = nvbios_volt_entry_parse(bios, i, &ver, &hdr,
&ivid);
if (data) {
volt->vid[volt->vid_nr].uv = ivid.voltage;
volt->vid[volt->vid_nr].vid = ivid.vid;
volt->vid_nr++;
}
}
volt->vid_mask = info.vidmask;
}
}
int
_nouveau_volt_init(struct nouveau_object *object)
{
@ -136,10 +171,6 @@ nouveau_volt_create_(struct nouveau_object *parent,
{
struct nouveau_bios *bios = nouveau_bios(parent);
struct nouveau_volt *volt;
struct nvbios_volt_entry ivid;
struct nvbios_volt info;
u8 ver, hdr, cnt, len;
u16 data;
int ret, i;
ret = nouveau_subdev_create_(parent, engine, oclass, 0, "VOLT",
@ -152,31 +183,9 @@ nouveau_volt_create_(struct nouveau_object *parent,
volt->set = nouveau_volt_set;
volt->set_id = nouveau_volt_set_id;
data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info);
if (data && info.vidmask && info.base && info.step) {
for (i = 0; i < info.vidmask + 1; i++) {
if (info.base >= info.min &&
info.base <= info.max) {
volt->vid[volt->vid_nr].uv = info.base;
volt->vid[volt->vid_nr].vid = i;
volt->vid_nr++;
}
info.base += info.step;
}
volt->vid_mask = info.vidmask;
} else
if (data && info.vidmask) {
for (i = 0; i < cnt; i++) {
data = nvbios_volt_entry_parse(bios, i, &ver, &hdr,
&ivid);
if (data) {
volt->vid[volt->vid_nr].uv = ivid.voltage;
volt->vid[volt->vid_nr].vid = ivid.vid;
volt->vid_nr++;
}
}
volt->vid_mask = info.vidmask;
}
/* Assuming the non-bios device should build the voltage table later */
if (bios)
nouveau_volt_parse_bios(bios, volt);
if (volt->vid_nr) {
for (i = 0; i < volt->vid_nr; i++) {