2 * Copyright 2010 PathScale inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 * Authors: Martin Peres
25 #include <linux/module.h>
29 #include "nouveau_drm.h"
30 #include "nouveau_pm.h"
32 #include <subdev/i2c.h>
33 #include <subdev/bios/therm.h>
34 #include <subdev/bios/extdev.h>
37 nv40_sensor_setup(struct drm_device *dev)
39 struct nouveau_device *device = nouveau_dev(dev);
40 struct nouveau_drm *drm = nouveau_drm(dev);
42 /* enable ADC readout and disable the ALARM threshold */
43 if (nv_device(drm->device)->chipset >= 0x46) {
44 nv_mask(device, 0x15b8, 0x80000000, 0);
45 nv_wr32(device, 0x15b0, 0x80003fff);
46 return nv_rd32(device, 0x15b4) & 0x3fff;
48 nv_wr32(device, 0x15b0, 0xff);
49 return nv_rd32(device, 0x15b4) & 0xff;
54 nv40_temp_get(struct drm_device *dev)
56 struct nouveau_device *device = nouveau_dev(dev);
57 struct nouveau_drm *drm = nouveau_drm(dev);
58 struct nouveau_pm *pm = nouveau_pm(dev);
59 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
62 if (nv_device(drm->device)->chipset >= 0x46) {
63 nv_wr32(device, 0x15b0, 0x80003fff);
64 core_temp = nv_rd32(device, 0x15b4) & 0x3fff;
66 nv_wr32(device, 0x15b0, 0xff);
67 core_temp = nv_rd32(device, 0x15b4) & 0xff;
70 /* Setup the sensor if the temperature is 0 */
72 core_temp = nv40_sensor_setup(dev);
74 if (sensor->slope_div == 0)
75 sensor->slope_div = 1;
76 if (sensor->offset_div == 0)
77 sensor->offset_div = 1;
78 if (sensor->slope_mult < 1)
79 sensor->slope_mult = 1;
81 core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
82 core_temp = core_temp + sensor->offset_mult / sensor->offset_div;
83 core_temp = core_temp + sensor->offset_constant - 8;
89 nv84_temp_get(struct drm_device *dev)
91 struct nouveau_device *device = nouveau_dev(dev);
92 return nv_rd32(device, 0x20400);
96 nouveau_temp_safety_checks(struct drm_device *dev)
98 struct nouveau_pm *pm = nouveau_pm(dev);
99 struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp;
101 if (temps->critical > 120)
102 temps->critical = 120;
103 else if (temps->critical < 80)
104 temps->critical = 80;
106 if (temps->down_clock > 110)
107 temps->down_clock = 110;
108 else if (temps->down_clock < 60)
109 temps->down_clock = 60;
113 probe_monitoring_device(struct nouveau_i2c_port *i2c,
114 struct i2c_board_info *info)
116 struct i2c_client *client;
118 request_module("%s%s", I2C_MODULE_PREFIX, info->type);
120 client = i2c_new_device(&i2c->adapter, info);
124 if (!client->driver || client->driver->detect(client, info)) {
125 i2c_unregister_device(client);
133 nouveau_temp_probe_i2c(struct drm_device *dev)
135 struct nouveau_device *device = nouveau_dev(dev);
136 struct nouveau_bios *bios = nouveau_bios(device);
137 struct nouveau_i2c *i2c = nouveau_i2c(device);
138 struct nvbios_extdev_func extdev_entry;
139 struct i2c_board_info info[] = {
140 { I2C_BOARD_INFO("w83l785ts", 0x2d) },
141 { I2C_BOARD_INFO("w83781d", 0x2d) },
142 { I2C_BOARD_INFO("adt7473", 0x2e) },
143 { I2C_BOARD_INFO("adt7473", 0x2d) },
144 { I2C_BOARD_INFO("adt7473", 0x2c) },
145 { I2C_BOARD_INFO("f75375", 0x2e) },
146 { I2C_BOARD_INFO("lm99", 0x4c) },
147 { I2C_BOARD_INFO("lm90", 0x4c) },
148 { I2C_BOARD_INFO("lm90", 0x4d) },
149 { I2C_BOARD_INFO("adm1021", 0x18) },
150 { I2C_BOARD_INFO("adm1021", 0x19) },
151 { I2C_BOARD_INFO("adm1021", 0x1a) },
152 { I2C_BOARD_INFO("adm1021", 0x29) },
153 { I2C_BOARD_INFO("adm1021", 0x2a) },
154 { I2C_BOARD_INFO("adm1021", 0x2b) },
155 { I2C_BOARD_INFO("adm1021", 0x4c) },
156 { I2C_BOARD_INFO("adm1021", 0x4d) },
157 { I2C_BOARD_INFO("adm1021", 0x4e) },
158 { I2C_BOARD_INFO("lm63", 0x18) },
159 { I2C_BOARD_INFO("lm63", 0x4e) },
163 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) {
164 struct i2c_board_info board[] = {
165 { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) },
169 if (i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
170 board, probe_monitoring_device))
174 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) {
175 struct i2c_board_info board[] = {
176 { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) },
180 if (i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
181 board, probe_monitoring_device))
185 /* The vbios doesn't provide the address of an exisiting monitoring
186 device. Let's try our static list.
188 i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info,
189 probe_monitoring_device);
193 nouveau_temp_init(struct drm_device *dev)
195 struct nouveau_drm *drm = nouveau_drm(dev);
196 struct nouveau_device *device = nv_device(drm->device);
197 struct nouveau_bios *bios = nouveau_bios(device);
198 struct nouveau_pm *pm = nouveau_pm(dev);
199 struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
200 struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp;
201 struct nvbios_therm_sensor bios_sensor;
202 struct nvbios_therm_fan bios_fan;
204 /* store some safe defaults */
205 sensor->offset_constant = 0;
206 sensor->offset_mult = 0;
207 sensor->offset_div = 1;
208 sensor->slope_mult = 1;
209 sensor->slope_div = 1;
211 if (!nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE,
213 sensor->slope_mult = bios_sensor.slope_mult;
214 sensor->slope_div = bios_sensor.slope_div;
215 sensor->offset_mult = bios_sensor.offset_num;
216 sensor->offset_div = bios_sensor.offset_den;
217 sensor->offset_constant = bios_sensor.offset_constant;
219 temps->down_clock = bios_sensor.thrs_down_clock.temp;
220 temps->critical = bios_sensor.thrs_critical.temp;
223 if (nvbios_therm_fan_parse(bios, &bios_fan)) {
224 pm->fan.min_duty = bios_fan.min_duty;
225 pm->fan.max_duty = bios_fan.max_duty;
226 pm->fan.pwm_freq = bios_fan.pwm_freq;
229 nouveau_temp_safety_checks(dev);
230 nouveau_temp_probe_i2c(dev);
234 nouveau_temp_fini(struct drm_device *dev)