drm/nouveau/therm: don't try pwm/toggle control if GPIO_FAN is input
authorBen Skeggs <bskeggs@redhat.com>
Fri, 7 Dec 2012 01:37:28 +0000 (11:37 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 20 Feb 2013 06:00:29 +0000 (16:00 +1000)
My GTX660 has the GPIO_FAN function, but it's configured in input-mode;
presumably to monitor the frequency set by an I2C fan controller?

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
drivers/gpu/drm/nouveau/core/subdev/therm/fan.c

index cb060576c20ef6e13d465276200a9bbb31e676f0..96d3364f6db30bca72ac8c9b9947c5230b3eb678 100644 (file)
@@ -10,6 +10,13 @@ enum dcb_gpio_func_name {
        DCB_GPIO_UNUSED = 0xff
 };
 
+#define DCB_GPIO_LOG_DIR     0x02
+#define DCB_GPIO_LOG_DIR_OUT 0x00
+#define DCB_GPIO_LOG_DIR_IN  0x02
+#define DCB_GPIO_LOG_VAL     0x01
+#define DCB_GPIO_LOG_VAL_LO  0x00
+#define DCB_GPIO_LOG_VAL_HI  0x01
+
 struct dcb_gpio_func {
        u8 func;
        u8 line;
index edc1664ee54f1dcb8885e3469eaf291aaedbf800..ddb23dc8a8393b3cf98fe71fff307023be97f696 100644 (file)
@@ -214,14 +214,23 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm)
 
        /* attempt to locate a drivable fan, and determine control method */
        ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
-       if (ret == 0)
-               ret = nouveau_fanpwm_create(therm, &func);
-       if (ret != 0)
-               ret = nouveau_fantog_create(therm, &func);
-       if (ret != 0)
+       if (ret == 0) {
+               if (func.log[0] & DCB_GPIO_LOG_DIR_IN) {
+                       nv_debug(therm, "GPIO_FAN is in input mode\n");
+                       ret = -EINVAL;
+               } else {
+                       ret = nouveau_fanpwm_create(therm, &func);
+                       if (ret != 0)
+                               ret = nouveau_fantog_create(therm, &func);
+               }
+       }
+
+       /* no controllable fan found, create a dummy fan module */
+       if (ret != 0) {
                ret = nouveau_fannil_create(therm);
-       if (ret)
-               return ret;
+               if (ret)
+                       return ret;
+       }
 
        nv_info(therm, "FAN control: %s\n", priv->fan->type);