aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@labri.fr>2012-09-04 07:52:00 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-10-02 23:13:15 -0400
commit2f951a5db5b55f65eb02d9a90aa7cecafde9f8b8 (patch)
tree9aeaca54de7a14598a3b2be04cb13ab891863dfd /drivers/gpu
parentc9cbf135065c0a674d43451127a10e48a53f9054 (diff)
drm/nouveau/therm: add support for fan-control modes
For now, only 2 control modes are available: - NONE: The fan is never touched (default) - MANUAL: The fan is set to the user-defined fan speed (pwm1) This patch introduces a distinction between ptherm internal fan management and external fan management. The latter is bound to respect the fan mode while the first can still select the speed it wants unless the NONE mode is selected. This is important for automatic fan management. Signed-off-by: Martin Peres <martin.peres@labri.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c52
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.c40
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
141static void 144int
145nouveau_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
172int
173nouveau_therm_fan_user_get(struct nouveau_therm *therm)
174{
175 return nouveau_therm_fan_get(therm);
176}
177
178int
179nouveau_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
189void
142nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) 190nouveau_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);
63int nouveau_therm_fan_ctor(struct nouveau_therm *therm); 64int nouveau_therm_fan_ctor(struct nouveau_therm *therm);
64int nouveau_therm_fan_get(struct nouveau_therm *therm); 65int nouveau_therm_fan_get(struct nouveau_therm *therm);
65int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); 66int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent);
67int nouveau_therm_fan_user_get(struct nouveau_therm *therm);
68int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent);
69int nouveau_therm_fan_set_mode(struct nouveau_therm *therm,
70 enum nouveau_therm_fan_mode mode);
71
66 72
67int nouveau_therm_fan_sense(struct nouveau_therm *therm); 73int 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,
503static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, 503static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input,
504 NULL, 0); 504 NULL, 0);
505 505
506 static ssize_t
507nouveau_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
522static ssize_t
523nouveau_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}
541static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
542 nouveau_hwmon_get_pwm1_enable,
543 nouveau_hwmon_set_pwm1_enable, 0);
544
506static ssize_t 545static ssize_t
507nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf) 546nouveau_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};
640static struct attribute *hwmon_pwm_fan_attributes[] = { 679static 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,