]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/gpu/drm/nouveau/nouveau_temp.c
Merge branch 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ickle...
[linux-beck.git] / drivers / gpu / drm / nouveau / nouveau_temp.c
index 54e3d9222f799fff51ee0ddd9416b186da4177c1..7ecc4adc1e4575aca6ef2791752c25300ff7668b 100644 (file)
@@ -27,7 +27,7 @@
 #include "nouveau_drv.h"
 #include "nouveau_pm.h"
 
-void
+static void
 nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -113,8 +113,8 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
 
                switch (temp[0]) {
                case 0x01:
-                       value = (value&0x8f) == 0 ? (value >> 9) & 0x7f : 0;
-                       sensor->offset_constant = value;
+                       if ((value & 0x8f) == 0)
+                               sensor->offset_constant = (value >> 9) & 0x7f;
                        break;
 
                case 0x04:
@@ -154,8 +154,8 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
        nouveau_temp_safety_checks(dev);
 }
 
-static s16
-nouveau_nv40_sensor_setup(struct drm_device *dev)
+static int
+nv40_sensor_setup(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
@@ -182,40 +182,34 @@ nouveau_nv40_sensor_setup(struct drm_device *dev)
        return nv_rd32(dev, 0x0015b4) & 0x1fff;
 }
 
-s16
-nouveau_temp_get(struct drm_device *dev)
+int
+nv40_temp_get(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
        struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
+       int offset = sensor->offset_mult / sensor->offset_div;
+       int core_temp;
 
-       if (dev_priv->chipset >= 0x84) {
-               return nv_rd32(dev, 0x20400);
-       } else if (dev_priv->chipset >= 0x40) {
-               u32 offset = sensor->offset_mult / sensor->offset_div;
-               u32 core_temp;
-
-               if (dev_priv->chipset >= 0x50) {
-                       core_temp = nv_rd32(dev, 0x20008);
-               } else {
-                       core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff;
-                       /* Setup the sensor if the temperature is 0 */
-                       if (core_temp == 0)
-                               core_temp = nouveau_nv40_sensor_setup(dev);
-               }
-
-               core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
-               core_temp = core_temp + offset + sensor->offset_constant;
-
-               return core_temp;
+       if (dev_priv->card_type >= NV_50) {
+               core_temp = nv_rd32(dev, 0x20008);
        } else {
-               NV_ERROR(dev,
-                                "Temperature cannot be retrieved from an nv%x card\n",
-                                dev_priv->chipset);
-               return 0;
+               core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff;
+               /* Setup the sensor if the temperature is 0 */
+               if (core_temp == 0)
+                       core_temp = nv40_sensor_setup(dev);
        }
 
-       return 0;
+       core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
+       core_temp = core_temp + offset + sensor->offset_constant;
+
+       return core_temp;
+}
+
+int
+nv84_temp_get(struct drm_device *dev)
+{
+       return nv_rd32(dev, 0x20400);
 }
 
 void
@@ -241,6 +235,48 @@ nouveau_temp_safety_checks(struct drm_device *dev)
                temps->fan_boost = 40;
 }
 
+static bool
+probe_monitoring_device(struct nouveau_i2c_chan *i2c,
+                       struct i2c_board_info *info)
+{
+       char modalias[16] = "i2c:";
+       struct i2c_client *client;
+
+       strlcat(modalias, info->type, sizeof(modalias));
+       request_module(modalias);
+
+       client = i2c_new_device(&i2c->adapter, info);
+       if (!client)
+               return false;
+
+       if (!client->driver || client->driver->detect(client, info)) {
+               i2c_unregister_device(client);
+               return false;
+       }
+
+       return true;
+}
+
+static void
+nouveau_temp_probe_i2c(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct dcb_table *dcb = &dev_priv->vbios.dcb;
+       struct i2c_board_info info[] = {
+               { I2C_BOARD_INFO("w83l785ts", 0x2d) },
+               { I2C_BOARD_INFO("w83781d", 0x2d) },
+               { I2C_BOARD_INFO("f75375", 0x2e) },
+               { I2C_BOARD_INFO("adt7473", 0x2e) },
+               { I2C_BOARD_INFO("lm99", 0x4c) },
+               { }
+       };
+       int idx = (dcb->version >= 0x40 ?
+                  dcb->i2c_default_indices & 0xf : 2);
+
+       nouveau_i2c_identify(dev, "monitoring device", info,
+                            probe_monitoring_device, idx);
+}
+
 void
 nouveau_temp_init(struct drm_device *dev)
 {
@@ -259,11 +295,11 @@ nouveau_temp_init(struct drm_device *dev)
                        temp = ROMPTR(bios, P.data[16]);
                else
                        NV_WARN(dev, "unknown temp for BIT P %d\n", P.version);
-       } else {
-               NV_WARN(dev, "BMP entry unknown for temperature table.\n");
+
+               nouveau_temp_vbios_parse(dev, temp);
        }
 
-       nouveau_temp_vbios_parse(dev, temp);
+       nouveau_temp_probe_i2c(dev);
 }
 
 void