diff options
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/base.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | 52 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_pm.c | 40 |
6 files changed, 105 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index 6502dfb95dd6..1674c74a76c8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c | |||
| @@ -40,6 +40,8 @@ nouveau_therm_attr_get(struct nouveau_therm *therm, | |||
| 40 | return priv->bios_fan.min_duty; | 40 | return priv->bios_fan.min_duty; |
| 41 | case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: | 41 | case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: |
| 42 | return priv->bios_fan.max_duty; | 42 | return priv->bios_fan.max_duty; |
| 43 | case NOUVEAU_THERM_ATTR_FAN_MODE: | ||
| 44 | return priv->fan.mode; | ||
| 43 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: | 45 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: |
| 44 | return priv->bios_sensor.thrs_fan_boost.temp; | 46 | return priv->bios_sensor.thrs_fan_boost.temp; |
| 45 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: | 47 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: |
| @@ -82,6 +84,8 @@ nouveau_therm_attr_set(struct nouveau_therm *therm, | |||
| 82 | value = priv->bios_fan.min_duty; | 84 | value = priv->bios_fan.min_duty; |
| 83 | priv->bios_fan.max_duty = value; | 85 | priv->bios_fan.max_duty = value; |
| 84 | return 0; | 86 | return 0; |
| 87 | case NOUVEAU_THERM_ATTR_FAN_MODE: | ||
| 88 | return nouveau_therm_fan_set_mode(therm, value); | ||
| 85 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: | 89 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: |
| 86 | priv->bios_sensor.thrs_fan_boost.temp = value; | 90 | priv->bios_sensor.thrs_fan_boost.temp = value; |
| 87 | return 0; | 91 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index 409b95d5b679..b29237970fa0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | |||
| @@ -69,6 +69,9 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) | |||
| 69 | u32 divs, duty; | 69 | u32 divs, duty; |
| 70 | int ret; | 70 | int ret; |
| 71 | 71 | ||
| 72 | if (priv->fan.mode == FAN_CONTROL_NONE) | ||
| 73 | return -EINVAL; | ||
| 74 | |||
| 72 | if (!priv->fan.pwm_set) | 75 | if (!priv->fan.pwm_set) |
| 73 | return -ENODEV; | 76 | return -ENODEV; |
| 74 | 77 | ||
| @@ -138,7 +141,52 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm) | |||
| 138 | return 0; | 141 | return 0; |
| 139 | } | 142 | } |
| 140 | 143 | ||
| 141 | static void | 144 | int |
| 145 | nouveau_therm_fan_set_mode(struct nouveau_therm *therm, | ||
| 146 | enum nouveau_therm_fan_mode mode) | ||
| 147 | { | ||
| 148 | struct nouveau_therm_priv *priv = (void *)therm; | ||
| 149 | |||
| 150 | if (priv->fan.mode == mode) | ||
| 151 | return 0; | ||
| 152 | |||
| 153 | if (mode < FAN_CONTROL_NONE || mode >= FAN_CONTROL_NR) | ||
| 154 | return -EINVAL; | ||
| 155 | |||
| 156 | switch (mode) | ||
| 157 | { | ||
| 158 | case FAN_CONTROL_NONE: | ||
| 159 | nv_info(therm, "switch fan to no-control mode\n"); | ||
| 160 | break; | ||
| 161 | case FAN_CONTROL_MANUAL: | ||
| 162 | nv_info(therm, "switch fan to manual mode\n"); | ||
| 163 | break; | ||
| 164 | case FAN_CONTROL_NR: | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | |||
| 168 | priv->fan.mode = mode; | ||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | int | ||
| 173 | nouveau_therm_fan_user_get(struct nouveau_therm *therm) | ||
| 174 | { | ||
| 175 | return nouveau_therm_fan_get(therm); | ||
| 176 | } | ||
| 177 | |||
| 178 | int | ||
| 179 | nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent) | ||
| 180 | { | ||
| 181 | struct nouveau_therm_priv *priv = (void *)therm; | ||
| 182 | |||
| 183 | if (priv->fan.mode != FAN_CONTROL_MANUAL) | ||
| 184 | return -EINVAL; | ||
| 185 | |||
| 186 | return nouveau_therm_fan_set(therm, percent); | ||
| 187 | } | ||
| 188 | |||
| 189 | void | ||
| 142 | nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) | 190 | nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) |
| 143 | { | 191 | { |
| 144 | struct nouveau_therm_priv *priv = (void *)therm; | 192 | struct nouveau_therm_priv *priv = (void *)therm; |
| @@ -180,5 +228,7 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm) | |||
| 180 | nv_error(therm, "parsing the thermal table failed\n"); | 228 | nv_error(therm, "parsing the thermal table failed\n"); |
| 181 | nouveau_therm_fan_safety_checks(therm); | 229 | nouveau_therm_fan_safety_checks(therm); |
| 182 | 230 | ||
| 231 | nouveau_therm_fan_set_mode(therm, FAN_CONTROL_NONE); | ||
| 232 | |||
| 183 | return 0; | 233 | return 0; |
| 184 | } | 234 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c index 9021b541da8d..fcf2cfe731d6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | |||
| @@ -142,8 +142,8 @@ nv40_therm_ctor(struct nouveau_object *parent, | |||
| 142 | priv->fan.pwm_set = nv40_fan_pwm_set; | 142 | priv->fan.pwm_set = nv40_fan_pwm_set; |
| 143 | 143 | ||
| 144 | therm->temp_get = nv40_temp_get; | 144 | therm->temp_get = nv40_temp_get; |
| 145 | therm->fan_get = nouveau_therm_fan_get; | 145 | therm->fan_get = nouveau_therm_fan_user_get; |
| 146 | therm->fan_set = nouveau_therm_fan_set; | 146 | therm->fan_set = nouveau_therm_fan_user_set; |
| 147 | therm->fan_sense = nouveau_therm_fan_sense; | 147 | therm->fan_sense = nouveau_therm_fan_sense; |
| 148 | therm->attr_get = nouveau_therm_attr_get; | 148 | therm->attr_get = nouveau_therm_attr_get; |
| 149 | therm->attr_set = nouveau_therm_attr_set; | 149 | therm->attr_set = nouveau_therm_attr_set; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c index de7dc20ed436..f87a7a3eb4e7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | |||
| @@ -136,8 +136,8 @@ nv50_therm_ctor(struct nouveau_object *parent, | |||
| 136 | priv->fan.pwm_clock = nv50_fan_pwm_clock; | 136 | priv->fan.pwm_clock = nv50_fan_pwm_clock; |
| 137 | 137 | ||
| 138 | therm->temp_get = nv50_temp_get; | 138 | therm->temp_get = nv50_temp_get; |
| 139 | therm->fan_get = nouveau_therm_fan_get; | 139 | therm->fan_get = nouveau_therm_fan_user_get; |
| 140 | therm->fan_set = nouveau_therm_fan_set; | 140 | therm->fan_set = nouveau_therm_fan_user_set; |
| 141 | therm->fan_sense = nouveau_therm_fan_sense; | 141 | therm->fan_sense = nouveau_therm_fan_sense; |
| 142 | therm->attr_get = nouveau_therm_attr_get; | 142 | therm->attr_get = nouveau_therm_attr_get; |
| 143 | therm->attr_set = nouveau_therm_attr_set; | 143 | therm->attr_set = nouveau_therm_attr_set; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index c53eb5396972..1c3cd6abc36e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | |||
| @@ -38,6 +38,7 @@ struct nouveau_therm_priv { | |||
| 38 | 38 | ||
| 39 | /* fan priv */ | 39 | /* fan priv */ |
| 40 | struct { | 40 | struct { |
| 41 | enum nouveau_therm_fan_mode mode; | ||
| 41 | int percent; | 42 | int percent; |
| 42 | 43 | ||
| 43 | int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); | 44 | int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); |
| @@ -63,5 +64,10 @@ int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); | |||
| 63 | int nouveau_therm_fan_ctor(struct nouveau_therm *therm); | 64 | int nouveau_therm_fan_ctor(struct nouveau_therm *therm); |
| 64 | int nouveau_therm_fan_get(struct nouveau_therm *therm); | 65 | int nouveau_therm_fan_get(struct nouveau_therm *therm); |
| 65 | int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); | 66 | int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); |
| 67 | int nouveau_therm_fan_user_get(struct nouveau_therm *therm); | ||
| 68 | int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent); | ||
| 69 | int nouveau_therm_fan_set_mode(struct nouveau_therm *therm, | ||
| 70 | enum nouveau_therm_fan_mode mode); | ||
| 71 | |||
| 66 | 72 | ||
| 67 | int nouveau_therm_fan_sense(struct nouveau_therm *therm); | 73 | int nouveau_therm_fan_sense(struct nouveau_therm *therm); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 0dca191ee173..b9d5335df742 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
| @@ -503,6 +503,45 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, | |||
| 503 | static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, | 503 | static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, |
| 504 | NULL, 0); | 504 | NULL, 0); |
| 505 | 505 | ||
| 506 | static ssize_t | ||
| 507 | nouveau_hwmon_get_pwm1_enable(struct device *d, | ||
| 508 | struct device_attribute *a, char *buf) | ||
| 509 | { | ||
| 510 | struct drm_device *dev = dev_get_drvdata(d); | ||
| 511 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
| 512 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
| 513 | int ret; | ||
| 514 | |||
| 515 | ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MODE); | ||
| 516 | if (ret < 0) | ||
| 517 | return ret; | ||
| 518 | |||
| 519 | return sprintf(buf, "%i\n", ret); | ||
| 520 | } | ||
| 521 | |||
| 522 | static ssize_t | ||
| 523 | nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a, | ||
| 524 | const char *buf, size_t count) | ||
| 525 | { | ||
| 526 | struct drm_device *dev = dev_get_drvdata(d); | ||
| 527 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
| 528 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
| 529 | long value; | ||
| 530 | int ret; | ||
| 531 | |||
| 532 | if (strict_strtol(buf, 10, &value) == -EINVAL) | ||
| 533 | return -EINVAL; | ||
| 534 | |||
| 535 | ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MODE, value); | ||
| 536 | if (ret) | ||
| 537 | return ret; | ||
| 538 | else | ||
| 539 | return count; | ||
| 540 | } | ||
| 541 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, | ||
| 542 | nouveau_hwmon_get_pwm1_enable, | ||
| 543 | nouveau_hwmon_set_pwm1_enable, 0); | ||
| 544 | |||
| 506 | static ssize_t | 545 | static ssize_t |
| 507 | nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf) | 546 | nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf) |
| 508 | { | 547 | { |
| @@ -638,6 +677,7 @@ static struct attribute *hwmon_fan_rpm_attributes[] = { | |||
| 638 | NULL | 677 | NULL |
| 639 | }; | 678 | }; |
| 640 | static struct attribute *hwmon_pwm_fan_attributes[] = { | 679 | static struct attribute *hwmon_pwm_fan_attributes[] = { |
| 680 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
| 641 | &sensor_dev_attr_pwm1.dev_attr.attr, | 681 | &sensor_dev_attr_pwm1.dev_attr.attr, |
| 642 | &sensor_dev_attr_pwm1_min.dev_attr.attr, | 682 | &sensor_dev_attr_pwm1_min.dev_attr.attr, |
| 643 | &sensor_dev_attr_pwm1_max.dev_attr.attr, | 683 | &sensor_dev_attr_pwm1_max.dev_attr.attr, |
