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