1/* 2 * Copyright 2010 PathScale inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Martin Peres 23 */ 24 25#include <linux/module.h> 26 27#include "drmP.h" 28 29#include "nouveau_drv.h" 30#include "nouveau_pm.h" 31 32static void 33nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) 34{ 35 struct drm_nouveau_private *dev_priv = dev->dev_private; 36 struct nouveau_pm_engine *pm = &dev_priv->engine.pm; 37 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; 38 struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; 39 int i, headerlen, recordlen, entries; 40 41 if (!temp) { 42 NV_DEBUG(dev, "temperature table pointer invalid\n"); 43 return; 44 } 45 46 /* Set the default sensor's contants */ 47 sensor->offset_constant = 0; 48 sensor->offset_mult = 0; 49 sensor->offset_div = 1; 50 sensor->slope_mult = 1; 51 sensor->slope_div = 1; 52 53 /* Set the default temperature thresholds */ 54 temps->critical = 110; 55 temps->down_clock = 100; 56 temps->fan_boost = 90; 57 58 /* Set the default range for the pwm fan */ 59 pm->fan.min_duty = 30; 60 pm->fan.max_duty = 100; 61 62 /* Set the known default values to setup the temperature sensor */ 63 if (dev_priv->card_type >= NV_40) { 64 switch (dev_priv->chipset) { 65 case 0x43: 66 sensor->offset_mult = 32060; 67 sensor->offset_div = 1000; 68 sensor->slope_mult = 792; 69 sensor->slope_div = 1000; 70 break; 71 72 case 0x44: 73 case 0x47: 74 case 0x4a: 75 sensor->offset_mult = 27839; 76 sensor->offset_div = 1000; 77 sensor->slope_mult = 780; 78 sensor->slope_div = 1000; 79 break; 80 81 case 0x46: 82 sensor->offset_mult = -24775; 83 sensor->offset_div = 100; 84 sensor->slope_mult = 467; 85 sensor->slope_div = 10000; 86 break; 87 88 case 0x49: 89 sensor->offset_mult = -25051; 90 sensor->offset_div = 100; 91 sensor->slope_mult = 458; 92 sensor->slope_div = 10000; 93 break; 94 95 case 0x4b: 96 sensor->offset_mult = -24088; 97 sensor->offset_div = 100; 98 sensor->slope_mult = 442; 99 sensor->slope_div = 10000; 100 break; 101 102 case 0x50: 103 sensor->offset_mult = -22749; 104 sensor->offset_div = 100; 105 sensor->slope_mult = 431; 106 sensor->slope_div = 10000; 107 break; 108 109 case 0x67: 110 sensor->offset_mult = -26149; 111 sensor->offset_div = 100; 112 sensor->slope_mult = 484; 113 sensor->slope_div = 10000; 114 break; 115 } 116 } 117 118 headerlen = temp[1]; 119 recordlen = temp[2]; 120 entries = temp[3]; 121 temp = temp + headerlen; 122 123 /* Read the entries from the table */ 124 for (i = 0; i < entries; i++) { 125 s16 value = ROM16(temp[1]); 126 127 switch (temp[0]) { 128 case 0x01: 129 if ((value & 0x8f) == 0) 130 sensor->offset_constant = (value >> 9) & 0x7f; 131 break; 132 133 case 0x04: 134 if ((value & 0xf00f) == 0xa000) /* core */ 135 temps->critical = (value&0x0ff0) >> 4; 136 break; 137 138 case 0x07: 139 if ((value & 0xf00f) == 0xa000) /* core */ 140 temps->down_clock = (value&0x0ff0) >> 4; 141 break; 142 143 case 0x08: 144 if ((value & 0xf00f) == 0xa000) /* core */ 145 temps->fan_boost = (value&0x0ff0) >> 4; 146 break; 147 148 case 0x10: 149 sensor->offset_mult = value; 150 break; 151 152 case 0x11: 153 sensor->offset_div = value; 154 break; 155 156 case 0x12: 157 sensor->slope_mult = value; 158 break; 159 160 case 0x13: 161 sensor->slope_div = value; 162 break; 163 case 0x22: 164 pm->fan.min_duty = value & 0xff; 165 pm->fan.max_duty = (value & 0xff00) >> 8; 166 break; 167 case 0x26: 168 pm->fan.pwm_freq = value; 169 break; 170 } 171 temp += recordlen; 172 } 173 174 nouveau_temp_safety_checks(dev); 175 176 /* check the fan min/max settings */ 177 if (pm->fan.min_duty < 10) 178 pm->fan.min_duty = 10; 179 if (pm->fan.max_duty > 100) 180 pm->fan.max_duty = 100; 181 if (pm->fan.max_duty < pm->fan.min_duty) 182 pm->fan.max_duty = pm->fan.min_duty; 183} 184 185static int 186nv40_sensor_setup(struct drm_device *dev) 187{ 188 struct drm_nouveau_private *dev_priv = dev->dev_private; 189 struct nouveau_pm_engine *pm = &dev_priv->engine.pm; 190 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; 191 s32 offset = sensor->offset_mult / sensor->offset_div; 192 s32 sensor_calibration; 193 194 /* set up the sensors */ 195 sensor_calibration = 120 - offset - sensor->offset_constant; 196 sensor_calibration = sensor_calibration * sensor->slope_div / 197 sensor->slope_mult; 198 199 if (dev_priv->chipset >= 0x46) 200 sensor_calibration |= 0x80000000; 201 else 202 sensor_calibration |= 0x10000000; 203 204 nv_wr32(dev, 0x0015b0, sensor_calibration); 205 206 /* Wait for the sensor to update */ 207 msleep(5); 208 209 /* read */ 210 return nv_rd32(dev, 0x0015b4) & 0x1fff; 211} 212 213int 214nv40_temp_get(struct drm_device *dev) 215{ 216 struct drm_nouveau_private *dev_priv = dev->dev_private; 217 struct nouveau_pm_engine *pm = &dev_priv->engine.pm; 218 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; 219 int offset = sensor->offset_mult / sensor->offset_div; 220 int core_temp; 221 222 if (dev_priv->card_type >= NV_50) { 223 core_temp = nv_rd32(dev, 0x20008); 224 } else { 225 core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; 226 /* Setup the sensor if the temperature is 0 */ 227 if (core_temp == 0) 228 core_temp = nv40_sensor_setup(dev); 229 } 230 231 core_temp = core_temp * sensor->slope_mult / sensor->slope_div; 232 core_temp = core_temp + offset + sensor->offset_constant; 233 234 return core_temp; 235} 236 237int 238nv84_temp_get(struct drm_device *dev) 239{ 240 return nv_rd32(dev, 0x20400); 241} 242 243void 244nouveau_temp_safety_checks(struct drm_device *dev) 245{ 246 struct drm_nouveau_private *dev_priv = dev->dev_private; 247 struct nouveau_pm_engine *pm = &dev_priv->engine.pm; 248 struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; 249 250 if (temps->critical > 120) 251 temps->critical = 120; 252 else if (temps->critical < 80) 253 temps->critical = 80; 254 255 if (temps->down_clock > 110) 256 temps->down_clock = 110; 257 else if (temps->down_clock < 60) 258 temps->down_clock = 60; 259 260 if (temps->fan_boost > 100) 261 temps->fan_boost = 100; 262 else if (temps->fan_boost < 40) 263 temps->fan_boost = 40; 264} 265 266static bool 267probe_monitoring_device(struct nouveau_i2c_chan *i2c, 268 struct i2c_board_info *info) 269{ 270 struct i2c_client *client; 271 272 request_module("%s%s", I2C_MODULE_PREFIX, info->type); 273 274 client = i2c_new_device(&i2c->adapter, info); 275 if (!client) 276 return false; 277 278 if (!client->driver || client->driver->detect(client, info)) { 279 i2c_unregister_device(client); 280 return false; 281 } 282 283 return true; 284} 285 286static void 287nouveau_temp_probe_i2c(struct drm_device *dev) 288{ 289 struct i2c_board_info info[] = { 290 { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 291 { I2C_BOARD_INFO("w83781d", 0x2d) }, 292 { I2C_BOARD_INFO("adt7473", 0x2e) }, 293 { I2C_BOARD_INFO("f75375", 0x2e) }, 294 { I2C_BOARD_INFO("lm99", 0x4c) }, 295 { } 296 }; 297 298 nouveau_i2c_identify(dev, "monitoring device", info, 299 probe_monitoring_device, NV_I2C_DEFAULT(0)); 300} 301 302void 303nouveau_temp_init(struct drm_device *dev) 304{ 305 struct drm_nouveau_private *dev_priv = dev->dev_private; 306 struct nvbios *bios = &dev_priv->vbios; 307 struct bit_entry P; 308 u8 *temp = NULL; 309 310 if (bios->type == NVBIOS_BIT) { 311 if (bit_table(dev, 'P', &P)) 312 return; 313 314 if (P.version == 1) 315 temp = ROMPTR(dev, P.data[12]); 316 else if (P.version == 2) 317 temp = ROMPTR(dev, P.data[16]); 318 else 319 NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); 320 321 nouveau_temp_vbios_parse(dev, temp); 322 } 323 324 nouveau_temp_probe_i2c(dev); 325} 326 327void 328nouveau_temp_fini(struct drm_device *dev) 329{ 330 331} 332