]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/nouveau_temp.c
drm/nouveau: port remainder of drm code, and rip out compat layer
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nouveau_temp.c
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_drm.h"
30 #include "nouveau_pm.h"
31
32 #include <subdev/i2c.h>
33
34 static void
35 nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
36 {
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;
42
43         if (!temp) {
44                 NV_DEBUG(drm, "temperature table pointer invalid\n");
45                 return;
46         }
47
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;
54
55         /* Set the default temperature thresholds */
56         temps->critical = 110;
57         temps->down_clock = 100;
58         temps->fan_boost = 90;
59
60         /* Set the default range for the pwm fan */
61         pm->fan.min_duty = 30;
62         pm->fan.max_duty = 100;
63
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) {
67                 case 0x43:
68                         sensor->offset_mult = 32060;
69                         sensor->offset_div = 1000;
70                         sensor->slope_mult = 792;
71                         sensor->slope_div = 1000;
72                         break;
73
74                 case 0x44:
75                 case 0x47:
76                 case 0x4a:
77                         sensor->offset_mult = 27839;
78                         sensor->offset_div = 1000;
79                         sensor->slope_mult = 780;
80                         sensor->slope_div = 1000;
81                         break;
82
83                 case 0x46:
84                         sensor->offset_mult = -24775;
85                         sensor->offset_div = 100;
86                         sensor->slope_mult = 467;
87                         sensor->slope_div = 10000;
88                         break;
89
90                 case 0x49:
91                         sensor->offset_mult = -25051;
92                         sensor->offset_div = 100;
93                         sensor->slope_mult = 458;
94                         sensor->slope_div = 10000;
95                         break;
96
97                 case 0x4b:
98                         sensor->offset_mult = -24088;
99                         sensor->offset_div = 100;
100                         sensor->slope_mult = 442;
101                         sensor->slope_div = 10000;
102                         break;
103
104                 case 0x50:
105                         sensor->offset_mult = -22749;
106                         sensor->offset_div = 100;
107                         sensor->slope_mult = 431;
108                         sensor->slope_div = 10000;
109                         break;
110
111                 case 0x67:
112                         sensor->offset_mult = -26149;
113                         sensor->offset_div = 100;
114                         sensor->slope_mult = 484;
115                         sensor->slope_div = 10000;
116                         break;
117                 }
118         }
119
120         headerlen = temp[1];
121         recordlen = temp[2];
122         entries = temp[3];
123         temp = temp + headerlen;
124
125         /* Read the entries from the table */
126         for (i = 0; i < entries; i++) {
127                 s16 value = ROM16(temp[1]);
128
129                 switch (temp[0]) {
130                 case 0x01:
131                         if ((value & 0x8f) == 0)
132                                 sensor->offset_constant = (value >> 9) & 0x7f;
133                         break;
134
135                 case 0x04:
136                         if ((value & 0xf00f) == 0xa000) /* core */
137                                 temps->critical = (value&0x0ff0) >> 4;
138                         break;
139
140                 case 0x07:
141                         if ((value & 0xf00f) == 0xa000) /* core */
142                                 temps->down_clock = (value&0x0ff0) >> 4;
143                         break;
144
145                 case 0x08:
146                         if ((value & 0xf00f) == 0xa000) /* core */
147                                 temps->fan_boost = (value&0x0ff0) >> 4;
148                         break;
149
150                 case 0x10:
151                         sensor->offset_mult = value;
152                         break;
153
154                 case 0x11:
155                         sensor->offset_div = value;
156                         break;
157
158                 case 0x12:
159                         sensor->slope_mult = value;
160                         break;
161
162                 case 0x13:
163                         sensor->slope_div = value;
164                         break;
165                 case 0x22:
166                         pm->fan.min_duty = value & 0xff;
167                         pm->fan.max_duty = (value & 0xff00) >> 8;
168                         break;
169                 case 0x26:
170                         pm->fan.pwm_freq = value;
171                         break;
172                 }
173                 temp += recordlen;
174         }
175
176         nouveau_temp_safety_checks(dev);
177
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;
185 }
186
187 static int
188 nv40_sensor_setup(struct drm_device *dev)
189 {
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;
196
197         /* set up the sensors */
198         sensor_calibration = 120 - offset - sensor->offset_constant;
199         sensor_calibration = sensor_calibration * sensor->slope_div /
200                                 sensor->slope_mult;
201
202         if (nv_device(drm->device)->chipset >= 0x46)
203                 sensor_calibration |= 0x80000000;
204         else
205                 sensor_calibration |= 0x10000000;
206
207         nv_wr32(device, 0x0015b0, sensor_calibration);
208
209         /* Wait for the sensor to update */
210         msleep(5);
211
212         /* read */
213         return nv_rd32(device, 0x0015b4) & 0x1fff;
214 }
215
216 int
217 nv40_temp_get(struct drm_device *dev)
218 {
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;
224         int core_temp;
225
226         if (nv_device(drm->device)->card_type >= NV_50) {
227                 core_temp = nv_rd32(device, 0x20008);
228         } else {
229                 core_temp = nv_rd32(device, 0x0015b4) & 0x1fff;
230                 /* Setup the sensor if the temperature is 0 */
231                 if (core_temp == 0)
232                         core_temp = nv40_sensor_setup(dev);
233         }
234
235         core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
236         core_temp = core_temp + offset + sensor->offset_constant;
237
238         return core_temp;
239 }
240
241 int
242 nv84_temp_get(struct drm_device *dev)
243 {
244         struct nouveau_device *device = nouveau_dev(dev);
245         return nv_rd32(device, 0x20400);
246 }
247
248 void
249 nouveau_temp_safety_checks(struct drm_device *dev)
250 {
251         struct nouveau_pm *pm = nouveau_pm(dev);
252         struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp;
253
254         if (temps->critical > 120)
255                 temps->critical = 120;
256         else if (temps->critical < 80)
257                 temps->critical = 80;
258
259         if (temps->down_clock > 110)
260                 temps->down_clock = 110;
261         else if (temps->down_clock < 60)
262                 temps->down_clock = 60;
263
264         if (temps->fan_boost > 100)
265                 temps->fan_boost = 100;
266         else if (temps->fan_boost < 40)
267                 temps->fan_boost = 40;
268 }
269
270 static bool
271 probe_monitoring_device(struct nouveau_i2c_port *i2c,
272                         struct i2c_board_info *info)
273 {
274         struct i2c_client *client;
275
276         request_module("%s%s", I2C_MODULE_PREFIX, info->type);
277
278         client = i2c_new_device(&i2c->adapter, info);
279         if (!client)
280                 return false;
281
282         if (!client->driver || client->driver->detect(client, info)) {
283                 i2c_unregister_device(client);
284                 return false;
285         }
286
287         return true;
288 }
289
290 static void
291 nouveau_temp_probe_i2c(struct drm_device *dev)
292 {
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) },
301                 { }
302         };
303
304         i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info,
305                       probe_monitoring_device);
306 }
307
308 void
309 nouveau_temp_init(struct drm_device *dev)
310 {
311         struct nouveau_drm *drm = nouveau_drm(dev);
312         struct nvbios *bios = &drm->vbios;
313         struct bit_entry P;
314         u8 *temp = NULL;
315
316         if (bios->type == NVBIOS_BIT) {
317                 if (bit_table(dev, 'P', &P))
318                         return;
319
320                 if (P.version == 1)
321                         temp = ROMPTR(dev, P.data[12]);
322                 else if (P.version == 2)
323                         temp = ROMPTR(dev, P.data[16]);
324                 else
325                         NV_WARN(drm, "unknown temp for BIT P %d\n", P.version);
326
327                 nouveau_temp_vbios_parse(dev, temp);
328         }
329
330         nouveau_temp_probe_i2c(dev);
331 }
332
333 void
334 nouveau_temp_fini(struct drm_device *dev)
335 {
336
337 }