Exemple #1
0
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;
}
Exemple #2
0
int
gk104_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
{
	const struct nvkm_volt_func *volt_func = &gk104_volt_gpio;
	struct dcb_gpio_func gpio;
	struct nvbios_volt bios;
	struct gk104_volt *volt;
	u8 ver, hdr, cnt, len;
	const char *mode;

	if (!nvbios_volt_parse(device->bios, &ver, &hdr, &cnt, &len, &bios))
		return 0;

	if (!nvkm_gpio_find(device->gpio, 0, DCB_GPIO_VID_PWM, 0xff, &gpio) &&
	    bios.type == NVBIOS_VOLT_PWM) {
		volt_func = &gk104_volt_pwm;
	}

	if (!(volt = kzalloc(sizeof(*volt), GFP_KERNEL)))
		return -ENOMEM;
	nvkm_volt_ctor(volt_func, device, index, &volt->base);
	*pvolt = &volt->base;
	volt->bios = bios;

	/* now that we have a subdev, we can show an error if we found through
	 * the voltage table that we were supposed to use the PWN mode but we
	 * did not find the right GPIO for it.
	 */
	if (bios.type == NVBIOS_VOLT_PWM && volt_func != &gk104_volt_pwm) {
		nvkm_error(&volt->base.subdev,
			   "Type mismatch between the voltage table type and "
			   "the GPIO table. Fallback to GPIO mode.\n");
	}

	if (volt_func == &gk104_volt_gpio) {
		nvkm_voltgpio_init(&volt->base);
		mode = "GPIO";
	} else
		mode = "PWM";

	nvkm_debug(&volt->base.subdev, "Using %s mode\n", mode);

	return 0;
}
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;
}