int nouveau_volt_create(struct nouveau_device *device) { struct nouveau_volt *volt = &device->volt; struct nvbios_volt_entry ivid; struct nvbios_volt info; u8 ver, hdr, cnt, len; u16 data; int ret = -EUNKNOWN, i; volt->get = nouveau_volt_get; data = nvbios_volt_parse(device, &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(device, 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; } if (volt->vid_nr) { for (i = 0; i < volt->vid_nr; i++) { nv_debug(device, "VID %02x: %duv\n", volt->vid[i].vid, volt->vid[i].uv); } /*XXX: this is an assumption.. there probably exists boards * out there with i2c-connected voltage controllers too.. */ ret = nouveau_voltgpio_init(device); if (ret == 0) { volt->vid_get = nouveau_voltgpio_get; } } return ret; }
int nouveau_volt_create_(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, int length, void **pobject) { 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", "voltage", length, pobject); volt = *pobject; if (ret) return ret; volt->get = nouveau_volt_get; 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; } if (volt->vid_nr) { for (i = 0; i < volt->vid_nr; i++) { nv_debug(volt, "VID %02x: %duv\n", volt->vid[i].vid, volt->vid[i].uv); } /*XXX: this is an assumption.. there probably exists boards * out there with i2c-connected voltage controllers too.. */ ret = nouveau_voltgpio_init(volt); if (ret == 0) { volt->vid_get = nouveau_voltgpio_get; volt->vid_set = nouveau_voltgpio_set; } } return ret; }