summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-12-05 14:56:37 +1000
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 16:00:18 +1000
commit68197b4ba0a3c90190795b97248b840a3e506545 (patch)
treee9e5b0afea8c893950603d147481d5a2a48fc24f
parent9cbcd3374a1db6a2faeb660bb49feb9af25c84ec (diff)
drm/nouveau/therm: add interfaces to allow forcing off pwm fan control
Mostly to allow for the possibility of testing 'toggle' fan control easily. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Martin Peres <martin.peres@labri.fr>
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c18
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c31
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h1
5 files changed, 56 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 4822733ca88..b4d14490d09 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -96,6 +96,8 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent)
duty = divs - duty;
ret = priv->fan.pwm_set(therm, func.line, divs, duty);
+ if (ret == 0)
+ ret = priv->fan.pwm_ctrl(therm, func.line, true);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
index f2092af62ce..47a15ecbe00 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
@@ -80,6 +80,19 @@ nv40_temp_get(struct nouveau_therm *therm)
}
int
+nv40_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
+{
+ u32 mask = enable ? 0x80000000 : 0x0000000;
+ if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask);
+ else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask);
+ else {
+ nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+int
nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
{
if (line == 2) {
@@ -109,11 +122,11 @@ int
nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
{
if (line == 2) {
- nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs);
+ nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs);
} else
if (line == 9) {
nv_wr32(therm, 0x0015f8, divs);
- nv_wr32(therm, 0x0015f4, duty | 0x80000000);
+ nv_mask(therm, 0x0015f4, 0x7fffffff, duty);
} else {
nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
return -ENODEV;
@@ -136,6 +149,7 @@ nv40_therm_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ priv->base.fan.pwm_ctrl = nv40_fan_pwm_ctrl;
priv->base.fan.pwm_get = nv40_fan_pwm_get;
priv->base.fan.pwm_set = nv40_fan_pwm_set;
priv->base.base.temp_get = nv40_temp_get;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index b7e1ecf9340..6ebad82e4fe 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
@@ -55,6 +55,16 @@ pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx)
}
int
+nv50_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
+{
+ u32 data = enable ? 0x00000001 : 0x00000000;
+ int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
+ if (ret == 0)
+ nv_mask(therm, ctrl, 0x00010001 << line, data << line);
+ return ret;
+}
+
+int
nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
{
int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
@@ -77,7 +87,6 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
if (ret)
return ret;
- nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line);
nv_wr32(therm, 0x00e114 + (id * 8), divs);
nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000);
return 0;
@@ -129,6 +138,7 @@ nv50_therm_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ priv->base.fan.pwm_ctrl = nv50_fan_pwm_ctrl;
priv->base.fan.pwm_get = nv50_fan_pwm_get;
priv->base.fan.pwm_set = nv50_fan_pwm_set;
priv->base.fan.pwm_clock = nv50_fan_pwm_clock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
index f0336a09cf9..ec06e895b61 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -32,32 +32,52 @@ static int
pwm_info(struct nouveau_therm *therm, int line)
{
u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
- if (gpio & 0x00000040) {
+ switch (gpio & 0x000000c0) {
+ case 0x00000000: /* normal mode, possibly pwm forced off by us */
+ case 0x00000040: /* nvio special */
switch (gpio & 0x0000001f) {
case 0x19: return 1;
case 0x1c: return 0;
default:
break;
}
+ default:
+ break;
}
nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio);
- return -EINVAL;
+ return -ENODEV;
}
static int
-nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
+nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
{
+ u32 data = enable ? 0x00000040 : 0x00000000;
int indx = pwm_info(therm, line);
if (indx < 0)
return indx;
- *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
- *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
+ nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
return 0;
}
static int
+nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
+{
+ int indx = pwm_info(therm, line);
+ if (indx < 0)
+ return indx;
+
+ if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
+ *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
+ *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int
nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
{
int indx = pwm_info(therm, line);
@@ -111,6 +131,7 @@ nvd0_therm_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ priv->base.fan.pwm_ctrl = nvd0_fan_pwm_ctrl;
priv->base.fan.pwm_get = nvd0_fan_pwm_get;
priv->base.fan.pwm_set = nvd0_fan_pwm_set;
priv->base.fan.pwm_clock = nvd0_fan_pwm_clock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index bb940e9d4e8..a08ca85e43f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -47,6 +47,7 @@ struct nouveau_therm_priv {
struct dcb_gpio_func tach;
+ int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);
int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*);
int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
int (*pwm_clock)(struct nouveau_therm *);