#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;
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:
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;
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
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)
{
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