diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_temp.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_temp.c | 331 |
1 files changed, 0 insertions, 331 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c deleted file mode 100644 index 1ad411dcc57a..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ /dev/null | |||
@@ -1,331 +0,0 @@ | |||
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 <drm/drmP.h> | ||
28 | |||
29 | #include "nouveau_drv.h" | ||
30 | #include "nouveau_pm.h" | ||
31 | |||
32 | static void | ||
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 | ||
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 | ||
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 | ||
238 | nv84_temp_get(struct drm_device *dev) | ||
239 | { | ||
240 | return nv_rd32(dev, 0x20400); | ||
241 | } | ||
242 | |||
243 | void | ||
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 | ||
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 | ||
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 | ||
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 | ||
328 | nouveau_temp_fini(struct drm_device *dev) | ||
329 | { | ||
330 | |||
331 | } | ||