drm/nvd0/therm: add support for hardware fan tachometer
authorBen Skeggs <bskeggs@redhat.com>
Tue, 4 Dec 2012 02:10:19 +0000 (12:10 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 20 Feb 2013 06:00:17 +0000 (16:00 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
drivers/gpu/drm/nouveau/core/subdev/therm/priv.h

index f4738082f3585bb96435b95d67263e785ba4e709..9a8daf4b36d5ac14cb3f326a2f114d9f971a174a 100644 (file)
@@ -30,7 +30,7 @@ struct nva3_therm_priv {
        struct nouveau_therm_priv base;
 };
 
-static int
+int
 nva3_therm_fan_sense(struct nouveau_therm *therm)
 {
        u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff;
index b001cd39b5a75a1bfa8b5a9af2cb28f2555ea1fe..f0336a09cf9e046352bef99a3974107633b87852 100644 (file)
@@ -75,6 +75,28 @@ nvd0_fan_pwm_clock(struct nouveau_therm *therm)
        return (nv_device(therm)->crystal * 1000) / 20;
 }
 
+static int
+nvd0_therm_init(struct nouveau_object *object)
+{
+       struct nvd0_therm_priv *priv = (void *)object;
+       int ret;
+
+       ret = nouveau_therm_init(&priv->base.base);
+       if (ret)
+               return ret;
+
+       /* enable fan tach, count revolutions per-second */
+       nv_mask(priv, 0x00e720, 0x00000003, 0x00000002);
+       if (priv->base.fan.tach.func != DCB_GPIO_UNUSED) {
+               nv_mask(priv, 0x00d79c, 0x000000ff, priv->base.fan.tach.line);
+               nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000);
+               nv_mask(priv, 0x00e720, 0x00000001, 0x00000001);
+       }
+       nv_mask(priv, 0x00e720, 0x00000002, 0x00000000);
+
+       return 0;
+}
+
 static int
 nvd0_therm_ctor(struct nouveau_object *parent,
                struct nouveau_object *engine,
@@ -93,6 +115,7 @@ nvd0_therm_ctor(struct nouveau_object *parent,
        priv->base.fan.pwm_set = nvd0_fan_pwm_set;
        priv->base.fan.pwm_clock = nvd0_fan_pwm_clock;
        priv->base.base.temp_get = nv50_temp_get;
+       priv->base.base.fan_sense = nva3_therm_fan_sense;
        return 0;
 }
 
@@ -102,7 +125,7 @@ nvd0_therm_oclass = {
        .ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvd0_therm_ctor,
                .dtor = _nouveau_therm_dtor,
-               .init = _nouveau_therm_init,
+               .init = nvd0_therm_init,
                .fini = _nouveau_therm_fini,
        },
 };
index 33fbc596ee4f802e09ffe6555130c823500f5e31..bb940e9d4e8fd40e4b7a46317eaebe244f07c4e2 100644 (file)
@@ -80,4 +80,6 @@ int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
 int nv50_fan_pwm_clock(struct nouveau_therm *);
 int nv50_temp_get(struct nouveau_therm *therm);
 
+int nva3_therm_fan_sense(struct nouveau_therm *);
+
 #endif