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 
32 static void
nouveau_temp_vbios_parse(struct drm_device * dev,u8 * temp)33 nouveau_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 
185 static int
nv40_sensor_setup(struct drm_device * dev)186 nv40_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 
213 int
nv40_temp_get(struct drm_device * dev)214 nv40_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 
237 int
nv84_temp_get(struct drm_device * dev)238 nv84_temp_get(struct drm_device *dev)
239 {
240 	return nv_rd32(dev, 0x20400);
241 }
242 
243 void
nouveau_temp_safety_checks(struct drm_device * dev)244 nouveau_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 
266 static bool
probe_monitoring_device(struct nouveau_i2c_chan * i2c,struct i2c_board_info * info)267 probe_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 
286 static void
nouveau_temp_probe_i2c(struct drm_device * dev)287 nouveau_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 
302 void
nouveau_temp_init(struct drm_device * dev)303 nouveau_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 
327 void
nouveau_temp_fini(struct drm_device * dev)328 nouveau_temp_fini(struct drm_device *dev)
329 {
330 
331 }
332