diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/bios/therm.c | 177 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_pm.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_pm.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_temp.c | 257 |
6 files changed, 282 insertions, 205 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 1c506c5a9a48..b6a6fa7fbcd4 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -35,6 +35,7 @@ nouveau-y += core/subdev/bios/i2c.o | |||
35 | nouveau-y += core/subdev/bios/init.o | 35 | nouveau-y += core/subdev/bios/init.o |
36 | nouveau-y += core/subdev/bios/mxm.o | 36 | nouveau-y += core/subdev/bios/mxm.o |
37 | nouveau-y += core/subdev/bios/pll.o | 37 | nouveau-y += core/subdev/bios/pll.o |
38 | nouveau-y += core/subdev/bios/therm.o | ||
38 | nouveau-y += core/subdev/clock/nv04.o | 39 | nouveau-y += core/subdev/clock/nv04.o |
39 | nouveau-y += core/subdev/clock/nv40.o | 40 | nouveau-y += core/subdev/clock/nv40.o |
40 | nouveau-y += core/subdev/clock/nv50.o | 41 | nouveau-y += core/subdev/clock/nv50.o |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h new file mode 100644 index 000000000000..a2c4296fc5f6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef __NVBIOS_THERM_H__ | ||
2 | #define __NVBIOS_THERM_H__ | ||
3 | |||
4 | struct nouveau_bios; | ||
5 | |||
6 | struct nvbios_therm_threshold { | ||
7 | u8 temp; | ||
8 | u8 hysteresis; | ||
9 | }; | ||
10 | |||
11 | struct nvbios_therm_sensor { | ||
12 | /* diode */ | ||
13 | s16 slope_mult; | ||
14 | s16 slope_div; | ||
15 | s16 offset_num; | ||
16 | s16 offset_den; | ||
17 | s8 offset_constant; | ||
18 | |||
19 | /* thresholds */ | ||
20 | struct nvbios_therm_threshold thrs_fan_boost; | ||
21 | struct nvbios_therm_threshold thrs_down_clock; | ||
22 | struct nvbios_therm_threshold thrs_critical; | ||
23 | struct nvbios_therm_threshold thrs_shutdown; | ||
24 | }; | ||
25 | |||
26 | struct nvbios_therm_fan { | ||
27 | u16 pwm_freq; | ||
28 | |||
29 | u8 min_duty; | ||
30 | u8 max_duty; | ||
31 | }; | ||
32 | |||
33 | enum nvbios_therm_domain { | ||
34 | NVBIOS_THERM_DOMAIN_CORE, | ||
35 | NVBIOS_THERM_DOMAIN_AMBIENT, | ||
36 | }; | ||
37 | |||
38 | int | ||
39 | nvbios_therm_sensor_parse(struct nouveau_bios *, enum nvbios_therm_domain, | ||
40 | struct nvbios_therm_sensor *); | ||
41 | |||
42 | int | ||
43 | nvbios_therm_fan_parse(struct nouveau_bios *, struct nvbios_therm_fan *); | ||
44 | |||
45 | |||
46 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c new file mode 100644 index 000000000000..862a08a2ae27 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Nouveau Community | ||
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 <subdev/bios.h> | ||
26 | #include <subdev/bios/bit.h> | ||
27 | #include <subdev/bios/therm.h> | ||
28 | |||
29 | static u16 | ||
30 | therm_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) | ||
31 | { | ||
32 | struct bit_entry bit_P; | ||
33 | u16 therm = 0; | ||
34 | |||
35 | if (!bit_entry(bios, 'P', &bit_P)) { | ||
36 | if (bit_P.version == 1) | ||
37 | therm = nv_ro16(bios, bit_P.offset + 12); | ||
38 | else if (bit_P.version == 2) | ||
39 | therm = nv_ro16(bios, bit_P.offset + 16); | ||
40 | else | ||
41 | nv_error(bios, | ||
42 | "unknown offset for thermal in BIT P %d\n", | ||
43 | bit_P.version); | ||
44 | } | ||
45 | |||
46 | /* exit now if we haven't found the thermal table */ | ||
47 | if (!therm) | ||
48 | return 0x0000; | ||
49 | |||
50 | *ver = nv_ro08(bios, therm + 0); | ||
51 | *hdr = nv_ro08(bios, therm + 1); | ||
52 | *len = nv_ro08(bios, therm + 2); | ||
53 | *cnt = nv_ro08(bios, therm + 3); | ||
54 | |||
55 | return therm + nv_ro08(bios, therm + 1); | ||
56 | } | ||
57 | |||
58 | u16 | ||
59 | nvbios_therm_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) | ||
60 | { | ||
61 | u8 hdr, cnt; | ||
62 | u16 therm = therm_table(bios, ver, &hdr, len, &cnt); | ||
63 | if (therm && idx < cnt) | ||
64 | return therm + idx * *len; | ||
65 | return 0x0000; | ||
66 | } | ||
67 | |||
68 | int | ||
69 | nvbios_therm_sensor_parse(struct nouveau_bios *bios, | ||
70 | enum nvbios_therm_domain domain, | ||
71 | struct nvbios_therm_sensor *sensor) | ||
72 | { | ||
73 | s8 thrs_section, sensor_section, offset; | ||
74 | u8 ver, len, i; | ||
75 | u16 entry; | ||
76 | |||
77 | /* we only support the core domain for now */ | ||
78 | if (domain != NVBIOS_THERM_DOMAIN_CORE) | ||
79 | return -EINVAL; | ||
80 | |||
81 | /* Read the entries from the table */ | ||
82 | thrs_section = 0; | ||
83 | sensor_section = -1; | ||
84 | i = 0; | ||
85 | while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { | ||
86 | s16 value = nv_ro16(bios, entry + 1); | ||
87 | |||
88 | switch (nv_ro08(bios, entry + 0)) { | ||
89 | case 0x0: | ||
90 | thrs_section = value; | ||
91 | if (value > 0) | ||
92 | return 0; /* we do not try to support ambient */ | ||
93 | break; | ||
94 | case 0x01: | ||
95 | sensor_section++; | ||
96 | if (sensor_section == 0) { | ||
97 | offset = ((s8) nv_ro08(bios, entry + 2)) / 2; | ||
98 | sensor->offset_constant = offset; | ||
99 | } | ||
100 | break; | ||
101 | |||
102 | case 0x04: | ||
103 | if (thrs_section == 0) { | ||
104 | sensor->thrs_critical.temp = (value & 0xff0) >> 4; | ||
105 | sensor->thrs_critical.hysteresis = value & 0xf; | ||
106 | } | ||
107 | break; | ||
108 | |||
109 | case 0x07: | ||
110 | if (thrs_section == 0) { | ||
111 | sensor->thrs_down_clock.temp = (value & 0xff0) >> 4; | ||
112 | sensor->thrs_down_clock.hysteresis = value & 0xf; | ||
113 | } | ||
114 | break; | ||
115 | |||
116 | case 0x08: | ||
117 | if (thrs_section == 0) { | ||
118 | sensor->thrs_fan_boost.temp = (value & 0xff0) >> 4; | ||
119 | sensor->thrs_fan_boost.hysteresis = value & 0xf; | ||
120 | } | ||
121 | break; | ||
122 | |||
123 | case 0x10: | ||
124 | if (sensor_section == 0) | ||
125 | sensor->offset_num = value; | ||
126 | break; | ||
127 | |||
128 | case 0x11: | ||
129 | if (sensor_section == 0) | ||
130 | sensor->offset_den = value; | ||
131 | break; | ||
132 | |||
133 | case 0x12: | ||
134 | if (sensor_section == 0) | ||
135 | sensor->slope_mult = value; | ||
136 | break; | ||
137 | |||
138 | case 0x13: | ||
139 | if (sensor_section == 0) | ||
140 | sensor->slope_div = value; | ||
141 | break; | ||
142 | case 0x32: | ||
143 | if (thrs_section == 0) { | ||
144 | sensor->thrs_shutdown.temp = (value & 0xff0) >> 4; | ||
145 | sensor->thrs_shutdown.hysteresis = value & 0xf; | ||
146 | } | ||
147 | break; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | int | ||
155 | nvbios_therm_fan_parse(struct nouveau_bios *bios, | ||
156 | struct nvbios_therm_fan *fan) | ||
157 | { | ||
158 | u8 ver, len, i; | ||
159 | u16 entry; | ||
160 | |||
161 | i = 0; | ||
162 | while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { | ||
163 | s16 value = nv_ro16(bios, entry + 1); | ||
164 | |||
165 | switch (nv_ro08(bios, entry + 0)) { | ||
166 | case 0x22: | ||
167 | fan->min_duty = value & 0xff; | ||
168 | fan->max_duty = (value & 0xff00) >> 8; | ||
169 | break; | ||
170 | case 0x26: | ||
171 | fan->pwm_freq = value; | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index d2f2de67f688..bdd50953488c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
@@ -891,10 +891,7 @@ nouveau_pm_init(struct drm_device *dev) | |||
891 | } | 891 | } |
892 | pm->voltage_get = nouveau_voltage_gpio_get; | 892 | pm->voltage_get = nouveau_voltage_gpio_get; |
893 | pm->voltage_set = nouveau_voltage_gpio_set; | 893 | pm->voltage_set = nouveau_voltage_gpio_set; |
894 | if (device->chipset == 0x50) | 894 | pm->temp_get = nv84_temp_get; |
895 | pm->temp_get = nv40_temp_get; | ||
896 | else | ||
897 | pm->temp_get = nv84_temp_get; | ||
898 | pm->pwm_get = nv50_pm_pwm_get; | 895 | pm->pwm_get = nv50_pm_pwm_get; |
899 | pm->pwm_set = nv50_pm_pwm_set; | 896 | pm->pwm_set = nv50_pm_pwm_set; |
900 | } else | 897 | } else |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h index e2ec9c0ed567..2e39ccbd5d46 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h | |||
@@ -148,7 +148,6 @@ struct nouveau_pm_temp_sensor_constants { | |||
148 | struct nouveau_pm_threshold_temp { | 148 | struct nouveau_pm_threshold_temp { |
149 | s16 critical; | 149 | s16 critical; |
150 | s16 down_clock; | 150 | s16 down_clock; |
151 | s16 fan_boost; | ||
152 | }; | 151 | }; |
153 | 152 | ||
154 | struct nouveau_pm_fan { | 153 | struct nouveau_pm_fan { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 7ae25e47be9f..5465abf87f18 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c | |||
@@ -30,187 +30,23 @@ | |||
30 | #include "nouveau_pm.h" | 30 | #include "nouveau_pm.h" |
31 | 31 | ||
32 | #include <subdev/i2c.h> | 32 | #include <subdev/i2c.h> |
33 | 33 | #include <subdev/bios/therm.h> | |
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 | 34 | ||
187 | static int | 35 | static int |
188 | nv40_sensor_setup(struct drm_device *dev) | 36 | nv40_sensor_setup(struct drm_device *dev) |
189 | { | 37 | { |
190 | struct nouveau_device *device = nouveau_dev(dev); | 38 | struct nouveau_device *device = nouveau_dev(dev); |
191 | struct nouveau_drm *drm = nouveau_drm(dev); | 39 | 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 | 40 | ||
202 | if (nv_device(drm->device)->chipset >= 0x46) | 41 | /* enable ADC readout and disable the ALARM threshold */ |
203 | sensor_calibration |= 0x80000000; | 42 | if (nv_device(drm->device)->chipset >= 0x46) { |
204 | else | 43 | nv_mask(device, 0x15b8, 0x80000000, 0); |
205 | sensor_calibration |= 0x10000000; | 44 | nv_wr32(device, 0x15b0, 0x80003fff); |
206 | 45 | return nv_rd32(device, 0x15b4) & 0x3fff; | |
207 | nv_wr32(device, 0x0015b0, sensor_calibration); | 46 | } else { |
208 | 47 | nv_wr32(device, 0x15b0, 0xff); | |
209 | /* Wait for the sensor to update */ | 48 | return nv_rd32(device, 0x15b4) & 0xff; |
210 | msleep(5); | 49 | } |
211 | |||
212 | /* read */ | ||
213 | return nv_rd32(device, 0x0015b4) & 0x1fff; | ||
214 | } | 50 | } |
215 | 51 | ||
216 | int | 52 | int |
@@ -220,20 +56,30 @@ nv40_temp_get(struct drm_device *dev) | |||
220 | struct nouveau_drm *drm = nouveau_drm(dev); | 56 | struct nouveau_drm *drm = nouveau_drm(dev); |
221 | struct nouveau_pm *pm = nouveau_pm(dev); | 57 | struct nouveau_pm *pm = nouveau_pm(dev); |
222 | struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | 58 | struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; |
223 | int offset = sensor->offset_mult / sensor->offset_div; | ||
224 | int core_temp; | 59 | int core_temp; |
225 | 60 | ||
226 | if (nv_device(drm->device)->card_type >= NV_50) { | 61 | if (nv_device(drm->device)->chipset >= 0x46) { |
227 | core_temp = nv_rd32(device, 0x20008); | 62 | nv_wr32(device, 0x15b0, 0x80003fff); |
63 | core_temp = nv_rd32(device, 0x15b4) & 0x3fff; | ||
228 | } else { | 64 | } else { |
229 | core_temp = nv_rd32(device, 0x0015b4) & 0x1fff; | 65 | nv_wr32(device, 0x15b0, 0xff); |
230 | /* Setup the sensor if the temperature is 0 */ | 66 | core_temp = nv_rd32(device, 0x15b4) & 0xff; |
231 | if (core_temp == 0) | ||
232 | core_temp = nv40_sensor_setup(dev); | ||
233 | } | 67 | } |
234 | 68 | ||
69 | /* Setup the sensor if the temperature is 0 */ | ||
70 | if (core_temp == 0) | ||
71 | core_temp = nv40_sensor_setup(dev); | ||
72 | |||
73 | if (sensor->slope_div == 0) | ||
74 | sensor->slope_div = 1; | ||
75 | if (sensor->offset_div == 0) | ||
76 | sensor->offset_div = 1; | ||
77 | if (sensor->slope_mult < 1) | ||
78 | sensor->slope_mult = 1; | ||
79 | |||
235 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; | 80 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; |
236 | core_temp = core_temp + offset + sensor->offset_constant; | 81 | core_temp = core_temp + sensor->offset_mult / sensor->offset_div; |
82 | core_temp = core_temp + sensor->offset_constant - 8; | ||
237 | 83 | ||
238 | return core_temp; | 84 | return core_temp; |
239 | } | 85 | } |
@@ -260,11 +106,6 @@ nouveau_temp_safety_checks(struct drm_device *dev) | |||
260 | temps->down_clock = 110; | 106 | temps->down_clock = 110; |
261 | else if (temps->down_clock < 60) | 107 | else if (temps->down_clock < 60) |
262 | temps->down_clock = 60; | 108 | 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 | } | 109 | } |
269 | 110 | ||
270 | static bool | 111 | static bool |
@@ -309,24 +150,40 @@ void | |||
309 | nouveau_temp_init(struct drm_device *dev) | 150 | nouveau_temp_init(struct drm_device *dev) |
310 | { | 151 | { |
311 | struct nouveau_drm *drm = nouveau_drm(dev); | 152 | struct nouveau_drm *drm = nouveau_drm(dev); |
312 | struct nvbios *bios = &drm->vbios; | 153 | struct nouveau_device *device = nv_device(drm->device); |
313 | struct bit_entry P; | 154 | struct nouveau_bios *bios = nouveau_bios(device); |
314 | u8 *temp = NULL; | 155 | struct nouveau_pm *pm = nouveau_pm(dev); |
156 | struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | ||
157 | struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | ||
158 | struct nvbios_therm_sensor bios_sensor; | ||
159 | struct nvbios_therm_fan bios_fan; | ||
315 | 160 | ||
316 | if (bios->type == NVBIOS_BIT) { | 161 | /* store some safe defaults */ |
317 | if (bit_table(dev, 'P', &P)) | 162 | sensor->offset_constant = 0; |
318 | return; | 163 | sensor->offset_mult = 0; |
164 | sensor->offset_div = 1; | ||
165 | sensor->slope_mult = 1; | ||
166 | sensor->slope_div = 1; | ||
319 | 167 | ||
320 | if (P.version == 1) | 168 | if (!nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, |
321 | temp = ROMPTR(dev, P.data[12]); | 169 | &bios_sensor)) { |
322 | else if (P.version == 2) | 170 | sensor->slope_mult = bios_sensor.slope_mult; |
323 | temp = ROMPTR(dev, P.data[16]); | 171 | sensor->slope_div = bios_sensor.slope_div; |
324 | else | 172 | sensor->offset_mult = bios_sensor.offset_num; |
325 | NV_WARN(drm, "unknown temp for BIT P %d\n", P.version); | 173 | sensor->offset_div = bios_sensor.offset_den; |
174 | sensor->offset_constant = bios_sensor.offset_constant; | ||
326 | 175 | ||
327 | nouveau_temp_vbios_parse(dev, temp); | 176 | temps->down_clock = bios_sensor.thrs_down_clock.temp; |
177 | temps->critical = bios_sensor.thrs_critical.temp; | ||
328 | } | 178 | } |
329 | 179 | ||
180 | if (nvbios_therm_fan_parse(bios, &bios_fan)) { | ||
181 | pm->fan.min_duty = bios_fan.min_duty; | ||
182 | pm->fan.max_duty = bios_fan.max_duty; | ||
183 | pm->fan.pwm_freq = bios_fan.pwm_freq; | ||
184 | } | ||
185 | |||
186 | nouveau_temp_safety_checks(dev); | ||
330 | nouveau_temp_probe_i2c(dev); | 187 | nouveau_temp_probe_i2c(dev); |
331 | } | 188 | } |
332 | 189 | ||