2 * Copyright 2010 PathScale inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 * Authors: Martin Peres
25 #include <linux/module.h>
29 #include "nouveau_drm.h"
30 #include "nouveau_pm.h"
32 #include <subdev/i2c.h>
35 nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
37 struct nouveau_drm *drm = nouveau_drm(dev);
38 struct nouveau_pm *pm = nouveau_pm(dev);
39 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
40 struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp;
41 int i, headerlen, recordlen, entries;
44 NV_DEBUG(drm, "temperature table pointer invalid\n");
48 /* Set the default sensor's contants */
49 sensor->offset_constant = 0;
50 sensor->offset_mult = 0;
51 sensor->offset_div = 1;
52 sensor->slope_mult = 1;
53 sensor->slope_div = 1;
55 /* Set the default temperature thresholds */
56 temps->critical = 110;
57 temps->down_clock = 100;
58 temps->fan_boost = 90;
60 /* Set the default range for the pwm fan */
61 pm->fan.min_duty = 30;
62 pm->fan.max_duty = 100;
64 /* Set the known default values to setup the temperature sensor */
65 if (nv_device(drm->device)->card_type >= NV_40) {
66 switch (nv_device(drm->device)->chipset) {
68 sensor->offset_mult = 32060;
69 sensor->offset_div = 1000;
70 sensor->slope_mult = 792;
71 sensor->slope_div = 1000;
77 sensor->offset_mult = 27839;
78 sensor->offset_div = 1000;
79 sensor->slope_mult = 780;
80 sensor->slope_div = 1000;
84 sensor->offset_mult = -24775;
85 sensor->offset_div = 100;
86 sensor->slope_mult = 467;
87 sensor->slope_div = 10000;
91 sensor->offset_mult = -25051;
92 sensor->offset_div = 100;
93 sensor->slope_mult = 458;
94 sensor->slope_div = 10000;
98 sensor->offset_mult = -24088;
99 sensor->offset_div = 100;
100 sensor->slope_mult = 442;
101 sensor->slope_div = 10000;
105 sensor->offset_mult = -22749;
106 sensor->offset_div = 100;
107 sensor->slope_mult = 431;
108 sensor->slope_div = 10000;
112 sensor->offset_mult = -26149;
113 sensor->offset_div = 100;
114 sensor->slope_mult = 484;
115 sensor->slope_div = 10000;
123 temp = temp + headerlen;
125 /* Read the entries from the table */
126 for (i = 0; i < entries; i++) {
127 s16 value = ROM16(temp[1]);
131 if ((value & 0x8f) == 0)
132 sensor->offset_constant = (value >> 9) & 0x7f;
136 if ((value & 0xf00f) == 0xa000) /* core */
137 temps->critical = (value&0x0ff0) >> 4;
141 if ((value & 0xf00f) == 0xa000) /* core */
142 temps->down_clock = (value&0x0ff0) >> 4;
146 if ((value & 0xf00f) == 0xa000) /* core */
147 temps->fan_boost = (value&0x0ff0) >> 4;
151 sensor->offset_mult = value;
155 sensor->offset_div = value;
159 sensor->slope_mult = value;
163 sensor->slope_div = value;
166 pm->fan.min_duty = value & 0xff;
167 pm->fan.max_duty = (value & 0xff00) >> 8;
170 pm->fan.pwm_freq = value;
176 nouveau_temp_safety_checks(dev);
178 /* check the fan min/max settings */
179 if (pm->fan.min_duty < 10)
180 pm->fan.min_duty = 10;
181 if (pm->fan.max_duty > 100)
182 pm->fan.max_duty = 100;
183 if (pm->fan.max_duty < pm->fan.min_duty)
184 pm->fan.max_duty = pm->fan.min_duty;
188 nv40_sensor_setup(struct drm_device *dev)
190 struct nouveau_device *device = nouveau_dev(dev);
191 struct nouveau_drm *drm = nouveau_drm(dev);
192 struct nouveau_pm *pm = nouveau_pm(dev);
193 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
194 s32 offset = sensor->offset_mult / sensor->offset_div;
195 s32 sensor_calibration;
197 /* set up the sensors */
198 sensor_calibration = 120 - offset - sensor->offset_constant;
199 sensor_calibration = sensor_calibration * sensor->slope_div /
202 if (nv_device(drm->device)->chipset >= 0x46)
203 sensor_calibration |= 0x80000000;
205 sensor_calibration |= 0x10000000;
207 nv_wr32(device, 0x0015b0, sensor_calibration);
209 /* Wait for the sensor to update */
213 return nv_rd32(device, 0x0015b4) & 0x1fff;
217 nv40_temp_get(struct drm_device *dev)
219 struct nouveau_device *device = nouveau_dev(dev);
220 struct nouveau_drm *drm = nouveau_drm(dev);
221 struct nouveau_pm *pm = nouveau_pm(dev);
222 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
223 int offset = sensor->offset_mult / sensor->offset_div;
226 if (nv_device(drm->device)->card_type >= NV_50) {
227 core_temp = nv_rd32(device, 0x20008);
229 core_temp = nv_rd32(device, 0x0015b4) & 0x1fff;
230 /* Setup the sensor if the temperature is 0 */
232 core_temp = nv40_sensor_setup(dev);
235 core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
236 core_temp = core_temp + offset + sensor->offset_constant;
242 nv84_temp_get(struct drm_device *dev)
244 struct nouveau_device *device = nouveau_dev(dev);
245 return nv_rd32(device, 0x20400);
249 nouveau_temp_safety_checks(struct drm_device *dev)
251 struct nouveau_pm *pm = nouveau_pm(dev);
252 struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp;
254 if (temps->critical > 120)
255 temps->critical = 120;
256 else if (temps->critical < 80)
257 temps->critical = 80;
259 if (temps->down_clock > 110)
260 temps->down_clock = 110;
261 else if (temps->down_clock < 60)
262 temps->down_clock = 60;
264 if (temps->fan_boost > 100)
265 temps->fan_boost = 100;
266 else if (temps->fan_boost < 40)
267 temps->fan_boost = 40;
271 probe_monitoring_device(struct nouveau_i2c_port *i2c,
272 struct i2c_board_info *info)
274 struct i2c_client *client;
276 request_module("%s%s", I2C_MODULE_PREFIX, info->type);
278 client = i2c_new_device(&i2c->adapter, info);
282 if (!client->driver || client->driver->detect(client, info)) {
283 i2c_unregister_device(client);
291 nouveau_temp_probe_i2c(struct drm_device *dev)
293 struct nouveau_device *device = nouveau_dev(dev);
294 struct nouveau_i2c *i2c = nouveau_i2c(device);
295 struct i2c_board_info info[] = {
296 { I2C_BOARD_INFO("w83l785ts", 0x2d) },
297 { I2C_BOARD_INFO("w83781d", 0x2d) },
298 { I2C_BOARD_INFO("adt7473", 0x2e) },
299 { I2C_BOARD_INFO("f75375", 0x2e) },
300 { I2C_BOARD_INFO("lm99", 0x4c) },
304 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info,
305 probe_monitoring_device);
309 nouveau_temp_init(struct drm_device *dev)
311 struct nouveau_drm *drm = nouveau_drm(dev);
312 struct nvbios *bios = &drm->vbios;
316 if (bios->type == NVBIOS_BIT) {
317 if (bit_table(dev, 'P', &P))
321 temp = ROMPTR(dev, P.data[12]);
322 else if (P.version == 2)
323 temp = ROMPTR(dev, P.data[16]);
325 NV_WARN(drm, "unknown temp for BIT P %d\n", P.version);
327 nouveau_temp_vbios_parse(dev, temp);
330 nouveau_temp_probe_i2c(dev);
334 nouveau_temp_fini(struct drm_device *dev)