summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@labri.fr>2012-09-04 13:52:00 +0200
committerBen Skeggs <bskeggs@redhat.com>2012-10-03 13:13:15 +1000
commit2f951a5db5b55f65eb02d9a90aa7cecafde9f8b8 (patch)
tree9aeaca54de7a14598a3b2be04cb13ab891863dfd /drivers/gpu/drm/nouveau/core
parentc9cbf135065c0a674d43451127a10e48a53f9054 (diff)
downloadop-kernel-dev-2f951a5db5b55f65eb02d9a90aa7cecafde9f8b8.zip
op-kernel-dev-2f951a5db5b55f65eb02d9a90aa7cecafde9f8b8.tar.gz
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/drm/nouveau/core')
-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
5 files changed, 65 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 6502dfb..1674c74 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,
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:
@@ -82,6 +84,8 @@ nouveau_therm_attr_set(struct nouveau_therm *therm,
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;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 409b95d..b292379 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)
u32 divs, duty;
int ret;
+ if (priv->fan.mode == FAN_CONTROL_NONE)
+ return -EINVAL;
+
if (!priv->fan.pwm_set)
return -ENODEV;
@@ -138,7 +141,52 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm)
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;
@@ -180,5 +228,7 @@ nouveau_therm_fan_ctor(struct nouveau_therm *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;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
index 9021b54..fcf2cfe 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,
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;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index de7dc20..f87a7a3 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,
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;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index c53eb53..1c3cd6a 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 {
/* fan priv */
struct {
+ enum nouveau_therm_fan_mode mode;
int percent;
int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*);
@@ -63,5 +64,10 @@ int nouveau_therm_sensor_ctor(struct nouveau_therm *therm);
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);
OpenPOWER on IntegriCloud