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