pandora: defconfig: update
[pandora-kernel.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_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 known default values to setup the temperature sensor */
59         if (dev_priv->card_type >= NV_40) {
60                 switch (dev_priv->chipset) {
61                 case 0x43:
62                         sensor->offset_mult = 32060;
63                         sensor->offset_div = 1000;
64                         sensor->slope_mult = 792;
65                         sensor->slope_div = 1000;
66                         break;
67
68                 case 0x44:
69                 case 0x47:
70                 case 0x4a:
71                         sensor->offset_mult = 27839;
72                         sensor->offset_div = 1000;
73                         sensor->slope_mult = 780;
74                         sensor->slope_div = 1000;
75                         break;
76
77                 case 0x46:
78                         sensor->offset_mult = -24775;
79                         sensor->offset_div = 100;
80                         sensor->slope_mult = 467;
81                         sensor->slope_div = 10000;
82                         break;
83
84                 case 0x49:
85                         sensor->offset_mult = -25051;
86                         sensor->offset_div = 100;
87                         sensor->slope_mult = 458;
88                         sensor->slope_div = 10000;
89                         break;
90
91                 case 0x4b:
92                         sensor->offset_mult = -24088;
93                         sensor->offset_div = 100;
94                         sensor->slope_mult = 442;
95                         sensor->slope_div = 10000;
96                         break;
97
98                 case 0x50:
99                         sensor->offset_mult = -22749;
100                         sensor->offset_div = 100;
101                         sensor->slope_mult = 431;
102                         sensor->slope_div = 10000;
103                         break;
104
105                 case 0x67:
106                         sensor->offset_mult = -26149;
107                         sensor->offset_div = 100;
108                         sensor->slope_mult = 484;
109                         sensor->slope_div = 10000;
110                         break;
111                 }
112         }
113
114         headerlen = temp[1];
115         recordlen = temp[2];
116         entries = temp[3];
117         temp = temp + headerlen;
118
119         /* Read the entries from the table */
120         for (i = 0; i < entries; i++) {
121                 s16 value = ROM16(temp[1]);
122
123                 switch (temp[0]) {
124                 case 0x01:
125                         if ((value & 0x8f) == 0)
126                                 sensor->offset_constant = (value >> 9) & 0x7f;
127                         break;
128
129                 case 0x04:
130                         if ((value & 0xf00f) == 0xa000) /* core */
131                                 temps->critical = (value&0x0ff0) >> 4;
132                         break;
133
134                 case 0x07:
135                         if ((value & 0xf00f) == 0xa000) /* core */
136                                 temps->down_clock = (value&0x0ff0) >> 4;
137                         break;
138
139                 case 0x08:
140                         if ((value & 0xf00f) == 0xa000) /* core */
141                                 temps->fan_boost = (value&0x0ff0) >> 4;
142                         break;
143
144                 case 0x10:
145                         sensor->offset_mult = value;
146                         break;
147
148                 case 0x11:
149                         sensor->offset_div = value;
150                         break;
151
152                 case 0x12:
153                         sensor->slope_mult = value;
154                         break;
155
156                 case 0x13:
157                         sensor->slope_div = value;
158                         break;
159                 }
160                 temp += recordlen;
161         }
162
163         nouveau_temp_safety_checks(dev);
164 }
165
166 static int
167 nv40_sensor_setup(struct drm_device *dev)
168 {
169         struct drm_nouveau_private *dev_priv = dev->dev_private;
170         struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
171         struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
172         s32 offset = sensor->offset_mult / sensor->offset_div;
173         s32 sensor_calibration;
174
175         /* set up the sensors */
176         sensor_calibration = 120 - offset - sensor->offset_constant;
177         sensor_calibration = sensor_calibration * sensor->slope_div /
178                                 sensor->slope_mult;
179
180         if (dev_priv->chipset >= 0x46)
181                 sensor_calibration |= 0x80000000;
182         else
183                 sensor_calibration |= 0x10000000;
184
185         nv_wr32(dev, 0x0015b0, sensor_calibration);
186
187         /* Wait for the sensor to update */
188         msleep(5);
189
190         /* read */
191         return nv_rd32(dev, 0x0015b4) & 0x1fff;
192 }
193
194 int
195 nv40_temp_get(struct drm_device *dev)
196 {
197         struct drm_nouveau_private *dev_priv = dev->dev_private;
198         struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
199         struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
200         int offset = sensor->offset_mult / sensor->offset_div;
201         int core_temp;
202
203         if (dev_priv->card_type >= NV_50) {
204                 core_temp = nv_rd32(dev, 0x20008);
205         } else {
206                 core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff;
207                 /* Setup the sensor if the temperature is 0 */
208                 if (core_temp == 0)
209                         core_temp = nv40_sensor_setup(dev);
210         }
211
212         core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
213         core_temp = core_temp + offset + sensor->offset_constant;
214
215         return core_temp;
216 }
217
218 int
219 nv84_temp_get(struct drm_device *dev)
220 {
221         return nv_rd32(dev, 0x20400);
222 }
223
224 void
225 nouveau_temp_safety_checks(struct drm_device *dev)
226 {
227         struct drm_nouveau_private *dev_priv = dev->dev_private;
228         struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
229         struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp;
230
231         if (temps->critical > 120)
232                 temps->critical = 120;
233         else if (temps->critical < 80)
234                 temps->critical = 80;
235
236         if (temps->down_clock > 110)
237                 temps->down_clock = 110;
238         else if (temps->down_clock < 60)
239                 temps->down_clock = 60;
240
241         if (temps->fan_boost > 100)
242                 temps->fan_boost = 100;
243         else if (temps->fan_boost < 40)
244                 temps->fan_boost = 40;
245 }
246
247 static bool
248 probe_monitoring_device(struct nouveau_i2c_chan *i2c,
249                         struct i2c_board_info *info)
250 {
251         struct i2c_client *client;
252
253         request_module("%s%s", I2C_MODULE_PREFIX, info->type);
254
255         client = i2c_new_device(&i2c->adapter, info);
256         if (!client)
257                 return false;
258
259         if (!client->driver || client->driver->detect(client, info)) {
260                 i2c_unregister_device(client);
261                 return false;
262         }
263
264         return true;
265 }
266
267 static void
268 nouveau_temp_probe_i2c(struct drm_device *dev)
269 {
270         struct drm_nouveau_private *dev_priv = dev->dev_private;
271         struct dcb_table *dcb = &dev_priv->vbios.dcb;
272         struct i2c_board_info info[] = {
273                 { I2C_BOARD_INFO("w83l785ts", 0x2d) },
274                 { I2C_BOARD_INFO("w83781d", 0x2d) },
275                 { I2C_BOARD_INFO("adt7473", 0x2e) },
276                 { I2C_BOARD_INFO("f75375", 0x2e) },
277                 { I2C_BOARD_INFO("lm99", 0x4c) },
278                 { }
279         };
280         int idx = (dcb->version >= 0x40 ?
281                    dcb->i2c_default_indices & 0xf : 2);
282
283         nouveau_i2c_identify(dev, "monitoring device", info,
284                              probe_monitoring_device, idx);
285 }
286
287 void
288 nouveau_temp_init(struct drm_device *dev)
289 {
290         struct drm_nouveau_private *dev_priv = dev->dev_private;
291         struct nvbios *bios = &dev_priv->vbios;
292         struct bit_entry P;
293         u8 *temp = NULL;
294
295         if (bios->type == NVBIOS_BIT) {
296                 if (bit_table(dev, 'P', &P))
297                         return;
298
299                 if (P.version == 1)
300                         temp = ROMPTR(bios, P.data[12]);
301                 else if (P.version == 2)
302                         temp = ROMPTR(bios, P.data[16]);
303                 else
304                         NV_WARN(dev, "unknown temp for BIT P %d\n", P.version);
305
306                 nouveau_temp_vbios_parse(dev, temp);
307         }
308
309         nouveau_temp_probe_i2c(dev);
310 }
311
312 void
313 nouveau_temp_fini(struct drm_device *dev)
314 {
315
316 }