return priv->bios_fan.min_duty;
case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY:
return priv->bios_fan.max_duty;
+ case NOUVEAU_THERM_ATTR_FAN_MODE:
+ return priv->fan.mode;
case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST:
return priv->bios_sensor.thrs_fan_boost.temp;
case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST:
value = priv->bios_fan.min_duty;
priv->bios_fan.max_duty = value;
return 0;
+ case NOUVEAU_THERM_ATTR_FAN_MODE:
+ return nouveau_therm_fan_set_mode(therm, value);
case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST:
priv->bios_sensor.thrs_fan_boost.temp = value;
return 0;
u32 divs, duty;
int ret;
+ if (priv->fan.mode == FAN_CONTROL_NONE)
+ return -EINVAL;
+
if (!priv->fan.pwm_set)
return -ENODEV;
return 0;
}
-static void
+int
+nouveau_therm_fan_set_mode(struct nouveau_therm *therm,
+ enum nouveau_therm_fan_mode mode)
+{
+ struct nouveau_therm_priv *priv = (void *)therm;
+
+ if (priv->fan.mode == mode)
+ return 0;
+
+ if (mode < FAN_CONTROL_NONE || mode >= FAN_CONTROL_NR)
+ return -EINVAL;
+
+ switch (mode)
+ {
+ case FAN_CONTROL_NONE:
+ nv_info(therm, "switch fan to no-control mode\n");
+ break;
+ case FAN_CONTROL_MANUAL:
+ nv_info(therm, "switch fan to manual mode\n");
+ break;
+ case FAN_CONTROL_NR:
+ break;
+ }
+
+ priv->fan.mode = mode;
+ return 0;
+}
+
+int
+nouveau_therm_fan_user_get(struct nouveau_therm *therm)
+{
+ return nouveau_therm_fan_get(therm);
+}
+
+int
+nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent)
+{
+ struct nouveau_therm_priv *priv = (void *)therm;
+
+ if (priv->fan.mode != FAN_CONTROL_MANUAL)
+ return -EINVAL;
+
+ return nouveau_therm_fan_set(therm, percent);
+}
+
+void
nouveau_therm_fan_set_defaults(struct nouveau_therm *therm)
{
struct nouveau_therm_priv *priv = (void *)therm;
nv_error(therm, "parsing the thermal table failed\n");
nouveau_therm_fan_safety_checks(therm);
+ nouveau_therm_fan_set_mode(therm, FAN_CONTROL_NONE);
+
return 0;
}
priv->fan.pwm_set = nv40_fan_pwm_set;
therm->temp_get = nv40_temp_get;
- therm->fan_get = nouveau_therm_fan_get;
- therm->fan_set = nouveau_therm_fan_set;
+ therm->fan_get = nouveau_therm_fan_user_get;
+ therm->fan_set = nouveau_therm_fan_user_set;
therm->fan_sense = nouveau_therm_fan_sense;
therm->attr_get = nouveau_therm_attr_get;
therm->attr_set = nouveau_therm_attr_set;
priv->fan.pwm_clock = nv50_fan_pwm_clock;
therm->temp_get = nv50_temp_get;
- therm->fan_get = nouveau_therm_fan_get;
- therm->fan_set = nouveau_therm_fan_set;
+ therm->fan_get = nouveau_therm_fan_user_get;
+ therm->fan_set = nouveau_therm_fan_user_set;
therm->fan_sense = nouveau_therm_fan_sense;
therm->attr_get = nouveau_therm_attr_get;
therm->attr_set = nouveau_therm_attr_set;
/* fan priv */
struct {
+ enum nouveau_therm_fan_mode mode;
int percent;
int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*);
int nouveau_therm_fan_ctor(struct nouveau_therm *therm);
int nouveau_therm_fan_get(struct nouveau_therm *therm);
int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent);
+int nouveau_therm_fan_user_get(struct nouveau_therm *therm);
+int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent);
+int nouveau_therm_fan_set_mode(struct nouveau_therm *therm,
+ enum nouveau_therm_fan_mode mode);
+
int nouveau_therm_fan_sense(struct nouveau_therm *therm);
static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input,
NULL, 0);
+ static ssize_t
+nouveau_hwmon_get_pwm1_enable(struct device *d,
+ struct device_attribute *a, char *buf)
+{
+ struct drm_device *dev = dev_get_drvdata(d);
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_therm *therm = nouveau_therm(drm->device);
+ int ret;
+
+ ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MODE);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%i\n", ret);
+}
+
+static ssize_t
+nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,
+ const char *buf, size_t count)
+{
+ struct drm_device *dev = dev_get_drvdata(d);
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_therm *therm = nouveau_therm(drm->device);
+ long value;
+ int ret;
+
+ if (strict_strtol(buf, 10, &value) == -EINVAL)
+ return -EINVAL;
+
+ ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MODE, value);
+ if (ret)
+ return ret;
+ else
+ return count;
+}
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+ nouveau_hwmon_get_pwm1_enable,
+ nouveau_hwmon_set_pwm1_enable, 0);
+
static ssize_t
nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf)
{
NULL
};
static struct attribute *hwmon_pwm_fan_attributes[] = {
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
&sensor_dev_attr_pwm1.dev_attr.attr,
&sensor_dev_attr_pwm1_min.dev_attr.attr,
&sensor_dev_attr_pwm1_max.dev_attr.attr,