Esempio n. 1
0
int
nouveau_therm_fan_ctor(struct nouveau_therm *therm)
{
	struct nouveau_therm_priv *priv = (void *)therm;
	struct nouveau_gpio *gpio = nouveau_gpio(therm);
	struct nouveau_bios *bios = nouveau_bios(therm);
	struct dcb_gpio_func func;
	int ret;

	/* attempt to locate a drivable fan, and determine control method */
	ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
	if (ret == 0) {
		/* FIXME: is this really the place to perform such checks ? */
		if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
			nv_debug(therm, "GPIO_FAN is in input mode\n");
			ret = -EINVAL;
		} else {
			ret = nouveau_fanpwm_create(therm, &func);
			if (ret != 0)
				ret = nouveau_fantog_create(therm, &func);
		}
	}

	/* no controllable fan found, create a dummy fan module */
	if (ret != 0) {
		ret = nouveau_fannil_create(therm);
		if (ret)
			return ret;
	}

	nv_info(therm, "FAN control: %s\n", priv->fan->type);

	/* read the current speed, it is useful when resuming */
	priv->fan->percent = nouveau_therm_fan_get(therm);

	/* attempt to detect a tachometer connection */
	ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach);
	if (ret)
		priv->fan->tach.func = DCB_GPIO_UNUSED;

	/* initialise fan bump/slow update handling */
	priv->fan->parent = therm;
	nouveau_alarm_init(&priv->fan->alarm, nouveau_fan_alarm);
	spin_lock_init(&priv->fan->lock);

	/* other random init... */
	nouveau_therm_fan_set_defaults(therm);
	nvbios_perf_fan_parse(bios, &priv->fan->perf);
	if (!nvbios_fan_parse(bios, &priv->fan->bios)) {
		nv_debug(therm, "parsing the fan table failed\n");
		if (nvbios_therm_fan_parse(bios, &priv->fan->bios))
			nv_error(therm, "parsing both fan tables failed\n");
	}
	nouveau_therm_fan_safety_checks(therm);
	return 0;
}
static void
nouveau_therm_update(struct nouveau_therm *therm, int mode)
{
	struct nouveau_timer *ptimer = nouveau_timer(therm);
	struct nouveau_therm_priv *priv = (void *)therm;
	unsigned long flags;
	bool immd = true;
	bool poll = true;
	int duty = -1;

	spin_lock_irqsave(&priv->lock, flags);
	if (mode < 0)
		mode = priv->mode;
	priv->mode = mode;

	switch (mode) {
	case NOUVEAU_THERM_CTRL_MANUAL:
		ptimer->alarm_cancel(ptimer, &priv->alarm);
		duty = nouveau_therm_fan_get(therm);
		if (duty < 0)
			duty = 100;
		poll = false;
		break;
	case NOUVEAU_THERM_CTRL_AUTO:
		switch(priv->fan->bios.fan_mode) {
		case NVBIOS_THERM_FAN_TRIP:
			duty = nouveau_therm_update_trip(therm);
			break;
		case NVBIOS_THERM_FAN_LINEAR:
			duty = nouveau_therm_update_linear(therm);
			break;
		case NVBIOS_THERM_FAN_OTHER:
			if (priv->cstate)
				duty = priv->cstate;
			poll = false;
			break;
		}
		immd = false;
		break;
	case NOUVEAU_THERM_CTRL_NONE:
	default:
		ptimer->alarm_cancel(ptimer, &priv->alarm);
		poll = false;
	}

	if (list_empty(&priv->alarm.head) && poll)
		ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
	spin_unlock_irqrestore(&priv->lock, flags);

	if (duty >= 0) {
		nv_debug(therm, "FAN target request: %d%%\n", duty);
		nouveau_therm_fan_set(therm, immd, duty);
	}
}
Esempio n. 3
0
static void
nouveau_therm_update(struct nouveau_therm *therm, int mode)
{
    struct nouveau_timer *ptimer = nouveau_timer(therm);
    struct nouveau_therm_priv *priv = (void *)therm;
    unsigned long flags;
    int duty;

    spin_lock_irqsave(&priv->lock, flags);
    nv_debug(therm, "FAN speed check\n");
    if (mode < 0)
        mode = priv->mode;
    priv->mode = mode;

    switch (mode) {
    case NOUVEAU_THERM_CTRL_MANUAL:
        ptimer->alarm_cancel(ptimer, &priv->alarm);
        duty = nouveau_therm_fan_get(therm);
        if (duty < 0)
            duty = 100;
        break;
    case NOUVEAU_THERM_CTRL_AUTO:
        if (priv->fan->bios.nr_fan_trip)
            duty = nouveau_therm_update_trip(therm);
        else
            duty = nouveau_therm_update_linear(therm);
        break;
    case NOUVEAU_THERM_CTRL_NONE:
    default:
        ptimer->alarm_cancel(ptimer, &priv->alarm);
        goto done;
    }

    nv_debug(therm, "FAN target request: %d%%\n", duty);
    nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty);

done:
    if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO))
        ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm);
    else if (!list_empty(&priv->alarm.head))
        nv_debug(therm, "therm fan alarm list is not empty\n");
    spin_unlock_irqrestore(&priv->lock, flags);
}
Esempio n. 4
0
int
nouveau_therm_fan_user_get(struct nouveau_therm *therm)
{
	return nouveau_therm_fan_get(therm);
}