diff options
author | Martin Peres <martin.peres@labri.fr> | 2012-09-01 20:55:58 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-10-02 23:13:14 -0400 |
commit | aa1b9b4836a8ab093ec06b0780553566a5430da7 (patch) | |
tree | 26c305c62178ad4f9bf9644b6b7766cb0af87b1f /drivers/gpu | |
parent | d46497dce7376e9d3e2e10c59d92e1c3b665b5dd (diff) |
drm/nouveau/therm: move thermal-related functions to the therm subdev
It looks scary because of the size, but I tried to keep the differences minimal.
Further patches will fix the actual "driver" code and add new features.
v2: change filenames, split to submodules
v3: add a missing include
v4: Ben Skeggs <bskeggs@redhat.com>
- fixed set_defaults() to allow min_duty < 30 (thermal table will
override this if it's actually necessary)
- fixed set_defaults() to not provide pwm_freq so nv4x (which only has
pwm_div) can actually work. the boards using pwm_freq will have a
thermal table entry to provide us the value.
- removed unused files
Signed-off-by: Martin Peres <martin.peres@labri.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
22 files changed, 1048 insertions, 542 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 1b05d114dee..15d17e88743 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -91,6 +91,12 @@ nouveau-y += core/subdev/mc/nvc0.o | |||
91 | nouveau-y += core/subdev/mxm/base.o | 91 | nouveau-y += core/subdev/mxm/base.o |
92 | nouveau-y += core/subdev/mxm/mxms.o | 92 | nouveau-y += core/subdev/mxm/mxms.o |
93 | nouveau-y += core/subdev/mxm/nv50.o | 93 | nouveau-y += core/subdev/mxm/nv50.o |
94 | nouveau-y += core/subdev/therm/base.o | ||
95 | nouveau-y += core/subdev/therm/fan.o | ||
96 | nouveau-y += core/subdev/therm/ic.o | ||
97 | nouveau-y += core/subdev/therm/nv40.o | ||
98 | nouveau-y += core/subdev/therm/nv50.o | ||
99 | nouveau-y += core/subdev/therm/temp.o | ||
94 | nouveau-y += core/subdev/timer/base.o | 100 | nouveau-y += core/subdev/timer/base.o |
95 | nouveau-y += core/subdev/timer/nv04.o | 101 | nouveau-y += core/subdev/timer/nv04.o |
96 | nouveau-y += core/subdev/vm/base.o | 102 | nouveau-y += core/subdev/vm/base.o |
@@ -173,7 +179,7 @@ nouveau-y += nv50_crtc.o nv50_dac.o nv50_sor.o nv50_cursor.o | |||
173 | nouveau-y += nv50_evo.o | 179 | nouveau-y += nv50_evo.o |
174 | 180 | ||
175 | # drm/pm | 181 | # drm/pm |
176 | nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o | 182 | nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o |
177 | nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o | 183 | nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o |
178 | nouveau-y += nouveau_mem.o | 184 | nouveau-y += nouveau_mem.o |
179 | 185 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index c32f96a2270..57899fc3b87 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h | |||
@@ -22,7 +22,6 @@ enum nv_subdev_type { | |||
22 | NVDEV_SUBDEV_VM, | 22 | NVDEV_SUBDEV_VM, |
23 | NVDEV_SUBDEV_BAR, | 23 | NVDEV_SUBDEV_BAR, |
24 | NVDEV_SUBDEV_VOLT, | 24 | NVDEV_SUBDEV_VOLT, |
25 | NVDEV_SUBDEV_FAN0, | ||
26 | NVDEV_SUBDEV_THERM, | 25 | NVDEV_SUBDEV_THERM, |
27 | NVDEV_ENGINE_DMAOBJ, | 26 | NVDEV_ENGINE_DMAOBJ, |
28 | NVDEV_ENGINE_FIFO, | 27 | NVDEV_ENGINE_FIFO, |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h new file mode 100644 index 00000000000..faee569fd45 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef __NOUVEAU_THERM_H__ | ||
2 | #define __NOUVEAU_THERM_H__ | ||
3 | |||
4 | #include <core/device.h> | ||
5 | #include <core/subdev.h> | ||
6 | |||
7 | enum nouveau_therm_fan_mode { | ||
8 | FAN_CONTROL_NONE = 0, | ||
9 | FAN_CONTROL_MANUAL = 1, | ||
10 | FAN_CONTROL_NR, | ||
11 | }; | ||
12 | |||
13 | enum nouveau_therm_attr_type { | ||
14 | NOUVEAU_THERM_ATTR_FAN_MIN_DUTY = 0, | ||
15 | NOUVEAU_THERM_ATTR_FAN_MAX_DUTY = 1, | ||
16 | NOUVEAU_THERM_ATTR_FAN_MODE = 2, | ||
17 | |||
18 | NOUVEAU_THERM_ATTR_THRS_FAN_BOOST = 10, | ||
19 | NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST = 11, | ||
20 | NOUVEAU_THERM_ATTR_THRS_DOWN_CLK = 12, | ||
21 | NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST = 13, | ||
22 | NOUVEAU_THERM_ATTR_THRS_CRITICAL = 14, | ||
23 | NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST = 15, | ||
24 | NOUVEAU_THERM_ATTR_THRS_SHUTDOWN = 16, | ||
25 | NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST = 17, | ||
26 | }; | ||
27 | |||
28 | struct nouveau_therm { | ||
29 | struct nouveau_subdev base; | ||
30 | |||
31 | int (*fan_get)(struct nouveau_therm *); | ||
32 | int (*fan_set)(struct nouveau_therm *, int); | ||
33 | int (*fan_sense)(struct nouveau_therm *); | ||
34 | |||
35 | int (*temp_get)(struct nouveau_therm *); | ||
36 | |||
37 | int (*attr_get)(struct nouveau_therm *, enum nouveau_therm_attr_type); | ||
38 | int (*attr_set)(struct nouveau_therm *, | ||
39 | enum nouveau_therm_attr_type, int); | ||
40 | }; | ||
41 | |||
42 | static inline struct nouveau_therm * | ||
43 | nouveau_therm(void *obj) | ||
44 | { | ||
45 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_THERM]; | ||
46 | } | ||
47 | |||
48 | #define nouveau_therm_create(p,e,o,d) \ | ||
49 | nouveau_subdev_create((p), (e), (o), 0, "THERM", "therm", d) | ||
50 | #define nouveau_therm_destroy(p) \ | ||
51 | nouveau_subdev_destroy(&(p)->base) | ||
52 | |||
53 | #define _nouveau_therm_dtor _nouveau_subdev_dtor | ||
54 | |||
55 | extern struct nouveau_oclass nv40_therm_oclass; | ||
56 | extern struct nouveau_oclass nv50_therm_oclass; | ||
57 | |||
58 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index cac67dc634b..7bf6f3760b9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c | |||
@@ -71,7 +71,6 @@ static const u64 disable_map[] = { | |||
71 | [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_DISABLE_CORE, | 71 | [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_DISABLE_CORE, |
72 | [NVDEV_SUBDEV_BAR] = NV_DEVICE_DISABLE_CORE, | 72 | [NVDEV_SUBDEV_BAR] = NV_DEVICE_DISABLE_CORE, |
73 | [NVDEV_SUBDEV_VOLT] = NV_DEVICE_DISABLE_CORE, | 73 | [NVDEV_SUBDEV_VOLT] = NV_DEVICE_DISABLE_CORE, |
74 | [NVDEV_SUBDEV_FAN0] = NV_DEVICE_DISABLE_CORE, | ||
75 | [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE, | 74 | [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE, |
76 | [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE, | 75 | [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE, |
77 | [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE, | 76 | [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index 1c8681f36f1..5fa58b7369b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <subdev/gpio.h> | 27 | #include <subdev/gpio.h> |
28 | #include <subdev/i2c.h> | 28 | #include <subdev/i2c.h> |
29 | #include <subdev/clock.h> | 29 | #include <subdev/clock.h> |
30 | #include <subdev/therm.h> | ||
30 | #include <subdev/devinit.h> | 31 | #include <subdev/devinit.h> |
31 | #include <subdev/mc.h> | 32 | #include <subdev/mc.h> |
32 | #include <subdev/timer.h> | 33 | #include <subdev/timer.h> |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index c6005c27382..320ccc4ae05 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <subdev/gpio.h> | 27 | #include <subdev/gpio.h> |
28 | #include <subdev/i2c.h> | 28 | #include <subdev/i2c.h> |
29 | #include <subdev/clock.h> | 29 | #include <subdev/clock.h> |
30 | #include <subdev/therm.h> | ||
30 | #include <subdev/devinit.h> | 31 | #include <subdev/devinit.h> |
31 | #include <subdev/mc.h> | 32 | #include <subdev/mc.h> |
32 | #include <subdev/timer.h> | 33 | #include <subdev/timer.h> |
@@ -51,6 +52,7 @@ nv40_identify(struct nouveau_device *device) | |||
51 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 52 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
52 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 53 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
53 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 54 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
55 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
54 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 56 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
55 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 57 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
56 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 58 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -70,6 +72,7 @@ nv40_identify(struct nouveau_device *device) | |||
70 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 72 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
71 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 73 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
72 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 74 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
75 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
73 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 76 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
74 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 77 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
75 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 78 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -89,6 +92,7 @@ nv40_identify(struct nouveau_device *device) | |||
89 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 92 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
90 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 93 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
91 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 94 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
95 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
92 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 96 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
93 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 97 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
94 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 98 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -108,6 +112,7 @@ nv40_identify(struct nouveau_device *device) | |||
108 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 112 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
109 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 113 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
110 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 114 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
115 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
111 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 116 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
112 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 117 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
113 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 118 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -127,6 +132,7 @@ nv40_identify(struct nouveau_device *device) | |||
127 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 132 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
128 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 133 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
129 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 134 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
135 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
130 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 136 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
131 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 137 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
132 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 138 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -146,6 +152,7 @@ nv40_identify(struct nouveau_device *device) | |||
146 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 152 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
147 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 153 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
148 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 154 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
155 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
149 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 156 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
150 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 157 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
151 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 158 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -165,6 +172,7 @@ nv40_identify(struct nouveau_device *device) | |||
165 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 172 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
166 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 173 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
167 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 174 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
175 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
168 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 176 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
169 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 177 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
170 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 178 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -184,6 +192,7 @@ nv40_identify(struct nouveau_device *device) | |||
184 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 192 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
185 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 193 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
186 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 194 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
195 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
187 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 196 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
188 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; | 197 | device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; |
189 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 198 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -203,6 +212,7 @@ nv40_identify(struct nouveau_device *device) | |||
203 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 212 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
204 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 213 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
205 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 214 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
215 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
206 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 216 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
207 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 217 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
208 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 218 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -222,6 +232,7 @@ nv40_identify(struct nouveau_device *device) | |||
222 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 232 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
223 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 233 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
224 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 234 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
235 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
225 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 236 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
226 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 237 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
227 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 238 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -241,6 +252,7 @@ nv40_identify(struct nouveau_device *device) | |||
241 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 252 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
242 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 253 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
243 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 254 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
255 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
244 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 256 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
245 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 257 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
246 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 258 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -260,6 +272,7 @@ nv40_identify(struct nouveau_device *device) | |||
260 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 272 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
261 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 273 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
262 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 274 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
275 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
263 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 276 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
264 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 277 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
265 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 278 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -279,6 +292,7 @@ nv40_identify(struct nouveau_device *device) | |||
279 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 292 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
280 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 293 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
281 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 294 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
295 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
282 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 296 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
283 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 297 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
284 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 298 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -298,6 +312,7 @@ nv40_identify(struct nouveau_device *device) | |||
298 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 312 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
299 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 313 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
300 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 314 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
315 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
301 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 316 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
302 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 317 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
303 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 318 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -317,6 +332,7 @@ nv40_identify(struct nouveau_device *device) | |||
317 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 332 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
318 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 333 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
319 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 334 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
335 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
320 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 336 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
321 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 337 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
322 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 338 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
@@ -336,6 +352,7 @@ nv40_identify(struct nouveau_device *device) | |||
336 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; | 352 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; |
337 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 353 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
338 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; | 354 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; |
355 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; | ||
339 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; | 356 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; |
340 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; | 357 | device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; |
341 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | 358 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 252e13c3c17..fec3bcc9a6f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <subdev/gpio.h> | 27 | #include <subdev/gpio.h> |
28 | #include <subdev/i2c.h> | 28 | #include <subdev/i2c.h> |
29 | #include <subdev/clock.h> | 29 | #include <subdev/clock.h> |
30 | #include <subdev/therm.h> | ||
30 | #include <subdev/mxm.h> | 31 | #include <subdev/mxm.h> |
31 | #include <subdev/devinit.h> | 32 | #include <subdev/devinit.h> |
32 | #include <subdev/mc.h> | 33 | #include <subdev/mc.h> |
@@ -58,6 +59,7 @@ nv50_identify(struct nouveau_device *device) | |||
58 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 59 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
59 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 60 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
60 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 61 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
62 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
61 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 63 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
62 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 64 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
63 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; | 65 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; |
@@ -79,6 +81,7 @@ nv50_identify(struct nouveau_device *device) | |||
79 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 81 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
80 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 82 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
81 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 83 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
84 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
82 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 85 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
83 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 86 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
84 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; | 87 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; |
@@ -103,6 +106,7 @@ nv50_identify(struct nouveau_device *device) | |||
103 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 106 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
104 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 107 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
105 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 108 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
109 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
106 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 110 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
107 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 111 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
108 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; | 112 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; |
@@ -127,6 +131,7 @@ nv50_identify(struct nouveau_device *device) | |||
127 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 131 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
128 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 132 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
129 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 133 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
134 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
130 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 135 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
131 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 136 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
132 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; | 137 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; |
@@ -151,6 +156,7 @@ nv50_identify(struct nouveau_device *device) | |||
151 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 156 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
152 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 157 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
153 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 158 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
159 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
154 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 160 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
155 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 161 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
156 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; | 162 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; |
@@ -175,6 +181,7 @@ nv50_identify(struct nouveau_device *device) | |||
175 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 181 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
176 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 182 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
177 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 183 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
184 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
178 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 185 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
179 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 186 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
180 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; | 187 | device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; |
@@ -199,6 +206,7 @@ nv50_identify(struct nouveau_device *device) | |||
199 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 206 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
200 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 207 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
201 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 208 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
209 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
202 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 210 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
203 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 211 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
204 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 212 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
@@ -223,6 +231,7 @@ nv50_identify(struct nouveau_device *device) | |||
223 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 231 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
224 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 232 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
225 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 233 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
234 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
226 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 235 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
227 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 236 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
228 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 237 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
@@ -247,6 +256,7 @@ nv50_identify(struct nouveau_device *device) | |||
247 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 256 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
248 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 257 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
249 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 258 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
259 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
250 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 260 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
251 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 261 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
252 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 262 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
@@ -271,6 +281,7 @@ nv50_identify(struct nouveau_device *device) | |||
271 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 281 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
272 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 282 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
273 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; | 283 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; |
284 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
274 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 285 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
275 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 286 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
276 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 287 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
@@ -295,6 +306,7 @@ nv50_identify(struct nouveau_device *device) | |||
295 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 306 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
296 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 307 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
297 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; | 308 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; |
309 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
298 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 310 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
299 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 311 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
300 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 312 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
@@ -320,6 +332,7 @@ nv50_identify(struct nouveau_device *device) | |||
320 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 332 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
321 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 333 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
322 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; | 334 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; |
335 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
323 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 336 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
324 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 337 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
325 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 338 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
@@ -344,6 +357,7 @@ nv50_identify(struct nouveau_device *device) | |||
344 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 357 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
345 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 358 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
346 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; | 359 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; |
360 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
347 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 361 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
348 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 362 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
349 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 363 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
@@ -368,6 +382,7 @@ nv50_identify(struct nouveau_device *device) | |||
368 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 382 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
369 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 383 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
370 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; | 384 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; |
385 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
371 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 386 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
372 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 387 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
373 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; | 388 | device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 8c14b3849fe..246bd081a01 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <subdev/gpio.h> | 27 | #include <subdev/gpio.h> |
28 | #include <subdev/i2c.h> | 28 | #include <subdev/i2c.h> |
29 | #include <subdev/clock.h> | 29 | #include <subdev/clock.h> |
30 | #include <subdev/therm.h> | ||
30 | #include <subdev/mxm.h> | 31 | #include <subdev/mxm.h> |
31 | #include <subdev/devinit.h> | 32 | #include <subdev/devinit.h> |
32 | #include <subdev/mc.h> | 33 | #include <subdev/mc.h> |
@@ -57,6 +58,7 @@ nvc0_identify(struct nouveau_device *device) | |||
57 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 58 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
58 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 59 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
59 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 60 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
61 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
60 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 62 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
61 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 63 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
62 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 64 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -83,6 +85,7 @@ nvc0_identify(struct nouveau_device *device) | |||
83 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 85 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
84 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 86 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
85 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 87 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
88 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
86 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 89 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
87 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 90 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
88 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 91 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -109,6 +112,7 @@ nvc0_identify(struct nouveau_device *device) | |||
109 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 112 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
110 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 113 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
111 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 114 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
115 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
112 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 116 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
113 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 117 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
114 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 118 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -135,6 +139,7 @@ nvc0_identify(struct nouveau_device *device) | |||
135 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 139 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
136 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 140 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
137 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 141 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
142 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
138 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 143 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
139 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 144 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
140 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 145 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -161,6 +166,7 @@ nvc0_identify(struct nouveau_device *device) | |||
161 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 166 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
162 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 167 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
163 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 168 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
169 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
164 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 170 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
165 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 171 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
166 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 172 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -187,6 +193,7 @@ nvc0_identify(struct nouveau_device *device) | |||
187 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 193 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
188 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 194 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
189 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 195 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
196 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
190 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 197 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
191 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 198 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
192 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 199 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -213,6 +220,7 @@ nvc0_identify(struct nouveau_device *device) | |||
213 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; | 220 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; |
214 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 221 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
215 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 222 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
223 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
216 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 224 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
217 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 225 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
218 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 226 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -239,6 +247,7 @@ nvc0_identify(struct nouveau_device *device) | |||
239 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; | 247 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; |
240 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 248 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
241 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 249 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
250 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
242 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 251 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
243 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 252 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
244 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 253 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 0d9d86b8124..4a280b7ab85 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <subdev/gpio.h> | 27 | #include <subdev/gpio.h> |
28 | #include <subdev/i2c.h> | 28 | #include <subdev/i2c.h> |
29 | #include <subdev/clock.h> | 29 | #include <subdev/clock.h> |
30 | #include <subdev/therm.h> | ||
30 | #include <subdev/mxm.h> | 31 | #include <subdev/mxm.h> |
31 | #include <subdev/devinit.h> | 32 | #include <subdev/devinit.h> |
32 | #include <subdev/mc.h> | 33 | #include <subdev/mc.h> |
@@ -55,6 +56,7 @@ nve0_identify(struct nouveau_device *device) | |||
55 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; | 56 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; |
56 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 57 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
57 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 58 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
59 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
58 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 60 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
59 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 61 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
60 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 62 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
@@ -79,6 +81,7 @@ nve0_identify(struct nouveau_device *device) | |||
79 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; | 81 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; |
80 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | 82 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; |
81 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | 83 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; |
84 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
82 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | 85 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; |
83 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | 86 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; |
84 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | 87 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c new file mode 100644 index 00000000000..6502dfb95dd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * Copyright 2012 The 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 <core/object.h> | ||
26 | #include <core/device.h> | ||
27 | |||
28 | #include <subdev/bios.h> | ||
29 | |||
30 | #include "priv.h" | ||
31 | |||
32 | int | ||
33 | nouveau_therm_attr_get(struct nouveau_therm *therm, | ||
34 | enum nouveau_therm_attr_type type) | ||
35 | { | ||
36 | struct nouveau_therm_priv *priv = (void *)therm; | ||
37 | |||
38 | switch (type) { | ||
39 | case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: | ||
40 | return priv->bios_fan.min_duty; | ||
41 | case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: | ||
42 | return priv->bios_fan.max_duty; | ||
43 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: | ||
44 | return priv->bios_sensor.thrs_fan_boost.temp; | ||
45 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: | ||
46 | return priv->bios_sensor.thrs_fan_boost.hysteresis; | ||
47 | case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: | ||
48 | return priv->bios_sensor.thrs_down_clock.temp; | ||
49 | case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: | ||
50 | return priv->bios_sensor.thrs_down_clock.hysteresis; | ||
51 | case NOUVEAU_THERM_ATTR_THRS_CRITICAL: | ||
52 | return priv->bios_sensor.thrs_critical.temp; | ||
53 | case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: | ||
54 | return priv->bios_sensor.thrs_critical.hysteresis; | ||
55 | case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: | ||
56 | return priv->bios_sensor.thrs_shutdown.temp; | ||
57 | case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: | ||
58 | return priv->bios_sensor.thrs_shutdown.hysteresis; | ||
59 | } | ||
60 | |||
61 | return -EINVAL; | ||
62 | } | ||
63 | |||
64 | int | ||
65 | nouveau_therm_attr_set(struct nouveau_therm *therm, | ||
66 | enum nouveau_therm_attr_type type, int value) | ||
67 | { | ||
68 | struct nouveau_therm_priv *priv = (void *)therm; | ||
69 | |||
70 | switch (type) { | ||
71 | case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: | ||
72 | if (value < 0) | ||
73 | value = 0; | ||
74 | if (value > priv->bios_fan.max_duty) | ||
75 | value = priv->bios_fan.max_duty; | ||
76 | priv->bios_fan.min_duty = value; | ||
77 | return 0; | ||
78 | case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: | ||
79 | if (value < 0) | ||
80 | value = 0; | ||
81 | if (value < priv->bios_fan.min_duty) | ||
82 | value = priv->bios_fan.min_duty; | ||
83 | priv->bios_fan.max_duty = value; | ||
84 | return 0; | ||
85 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: | ||
86 | priv->bios_sensor.thrs_fan_boost.temp = value; | ||
87 | return 0; | ||
88 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: | ||
89 | priv->bios_sensor.thrs_fan_boost.hysteresis = value; | ||
90 | return 0; | ||
91 | case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: | ||
92 | priv->bios_sensor.thrs_down_clock.temp = value; | ||
93 | return 0; | ||
94 | case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: | ||
95 | priv->bios_sensor.thrs_down_clock.hysteresis = value; | ||
96 | return 0; | ||
97 | case NOUVEAU_THERM_ATTR_THRS_CRITICAL: | ||
98 | priv->bios_sensor.thrs_critical.temp = value; | ||
99 | return 0; | ||
100 | case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: | ||
101 | priv->bios_sensor.thrs_critical.hysteresis = value; | ||
102 | return 0; | ||
103 | case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: | ||
104 | priv->bios_sensor.thrs_shutdown.temp = value; | ||
105 | return 0; | ||
106 | case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: | ||
107 | priv->bios_sensor.thrs_shutdown.hysteresis = value; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | return -EINVAL; | ||
112 | } | ||
113 | |||
114 | int | ||
115 | nouveau_therm_init(struct nouveau_object *object) | ||
116 | { | ||
117 | struct nouveau_therm *therm = (void *)object; | ||
118 | struct nouveau_therm_priv *priv = (void *)therm; | ||
119 | int ret; | ||
120 | |||
121 | ret = nouveau_subdev_init(&therm->base); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | if (priv->fan.percent >= 0) | ||
126 | therm->fan_set(therm, priv->fan.percent); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | int | ||
132 | nouveau_therm_fini(struct nouveau_object *object, bool suspend) | ||
133 | { | ||
134 | struct nouveau_therm *therm = (void *)object; | ||
135 | struct nouveau_therm_priv *priv = (void *)therm; | ||
136 | |||
137 | priv->fan.percent = therm->fan_get(therm); | ||
138 | |||
139 | return nouveau_subdev_fini(&therm->base, suspend); | ||
140 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c new file mode 100644 index 00000000000..9ad6e166dd7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Red Hat 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: Ben Skeggs | ||
23 | * Martin Peres | ||
24 | */ | ||
25 | |||
26 | #include "priv.h" | ||
27 | |||
28 | #include <core/object.h> | ||
29 | #include <core/device.h> | ||
30 | #include <subdev/gpio.h> | ||
31 | #include <subdev/timer.h> | ||
32 | |||
33 | int | ||
34 | nouveau_therm_fan_get(struct nouveau_therm *therm) | ||
35 | { | ||
36 | struct nouveau_therm_priv *priv = (void *)therm; | ||
37 | struct nouveau_gpio *gpio = nouveau_gpio(therm); | ||
38 | struct dcb_gpio_func func; | ||
39 | int card_type = nv_device(therm)->card_type; | ||
40 | u32 divs, duty; | ||
41 | int ret; | ||
42 | |||
43 | if (!priv->fan.pwm_get) | ||
44 | return -ENODEV; | ||
45 | |||
46 | ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); | ||
47 | if (ret == 0) { | ||
48 | ret = priv->fan.pwm_get(therm, func.line, &divs, &duty); | ||
49 | if (ret == 0 && divs) { | ||
50 | divs = max(divs, duty); | ||
51 | if (card_type <= NV_40 || (func.log[0] & 1)) | ||
52 | duty = divs - duty; | ||
53 | return (duty * 100) / divs; | ||
54 | } | ||
55 | |||
56 | return gpio->get(gpio, 0, func.func, func.line) * 100; | ||
57 | } | ||
58 | |||
59 | return -ENODEV; | ||
60 | } | ||
61 | |||
62 | int | ||
63 | nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) | ||
64 | { | ||
65 | struct nouveau_therm_priv *priv = (void *)therm; | ||
66 | struct nouveau_gpio *gpio = nouveau_gpio(therm); | ||
67 | struct dcb_gpio_func func; | ||
68 | int card_type = nv_device(therm)->card_type; | ||
69 | u32 divs, duty; | ||
70 | int ret; | ||
71 | |||
72 | if (!priv->fan.pwm_set) | ||
73 | return -ENODEV; | ||
74 | |||
75 | if (percent < priv->bios_fan.min_duty) | ||
76 | percent = priv->bios_fan.min_duty; | ||
77 | if (percent > priv->bios_fan.max_duty) | ||
78 | percent = priv->bios_fan.max_duty; | ||
79 | |||
80 | ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); | ||
81 | if (ret == 0) { | ||
82 | divs = priv->bios_perf_fan.pwm_divisor; | ||
83 | if (priv->bios_fan.pwm_freq) { | ||
84 | /*XXX: PNVIO clock more than likely... */ | ||
85 | divs = 135000 /priv->bios_fan.pwm_freq; | ||
86 | if (nv_device(therm)->chipset < 0xa3) | ||
87 | divs /= 4; | ||
88 | } | ||
89 | |||
90 | duty = ((divs * percent) + 99) / 100; | ||
91 | if (card_type <= NV_40 || (func.log[0] & 1)) | ||
92 | duty = divs - duty; | ||
93 | |||
94 | ret = priv->fan.pwm_set(therm, func.line, divs, duty); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | return -ENODEV; | ||
99 | } | ||
100 | |||
101 | int | ||
102 | nouveau_therm_fan_sense(struct nouveau_therm *therm) | ||
103 | { | ||
104 | struct nouveau_timer *ptimer = nouveau_timer(therm); | ||
105 | struct nouveau_gpio *gpio = nouveau_gpio(therm); | ||
106 | struct dcb_gpio_func func; | ||
107 | u32 cycles, cur, prev; | ||
108 | u64 start; | ||
109 | |||
110 | if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) | ||
111 | return -ENODEV; | ||
112 | |||
113 | /* Monitor the GPIO input 0x3b for 250ms. | ||
114 | * When the fan spins, it changes the value of GPIO FAN_SENSE. | ||
115 | * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. | ||
116 | */ | ||
117 | start = ptimer->read(ptimer); | ||
118 | prev = gpio->get(gpio, 0, func.func, func.line); | ||
119 | cycles = 0; | ||
120 | do { | ||
121 | cur = gpio->get(gpio, 0, func.func, func.line); | ||
122 | if (prev != cur) { | ||
123 | cycles++; | ||
124 | prev = cur; | ||
125 | } | ||
126 | |||
127 | usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ | ||
128 | } while (ptimer->read(ptimer) - start < 250000000); | ||
129 | |||
130 | /* interpolate to get rpm */ | ||
131 | return cycles / 4 * 4 * 60; | ||
132 | } | ||
133 | |||
134 | static void | ||
135 | nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) | ||
136 | { | ||
137 | struct nouveau_therm_priv *priv = (void *)therm; | ||
138 | |||
139 | priv->bios_fan.pwm_freq = 0; | ||
140 | priv->bios_fan.min_duty = 0; | ||
141 | priv->bios_fan.max_duty = 100; | ||
142 | } | ||
143 | |||
144 | |||
145 | static void | ||
146 | nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) | ||
147 | { | ||
148 | struct nouveau_therm_priv *priv = (void *)therm; | ||
149 | |||
150 | if (priv->bios_fan.min_duty > 100) | ||
151 | priv->bios_fan.min_duty = 100; | ||
152 | if (priv->bios_fan.max_duty > 100) | ||
153 | priv->bios_fan.max_duty = 100; | ||
154 | |||
155 | if (priv->bios_fan.min_duty > priv->bios_fan.max_duty) | ||
156 | priv->bios_fan.min_duty = priv->bios_fan.max_duty; | ||
157 | } | ||
158 | |||
159 | int | ||
160 | nouveau_therm_fan_ctor(struct nouveau_therm *therm) | ||
161 | { | ||
162 | struct nouveau_therm_priv *priv = (void *)therm; | ||
163 | struct nouveau_bios *bios = nouveau_bios(therm); | ||
164 | |||
165 | nouveau_therm_fan_set_defaults(therm); | ||
166 | nvbios_perf_fan_parse(bios, &priv->bios_perf_fan); | ||
167 | if (nvbios_therm_fan_parse(bios, &priv->bios_fan)) | ||
168 | nv_error(therm, "parsing the thermal table failed\n"); | ||
169 | nouveau_therm_fan_safety_checks(therm); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c new file mode 100644 index 00000000000..e512ff0aae6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c | |||
@@ -0,0 +1,116 @@ | |||
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 "priv.h" | ||
26 | |||
27 | #include <subdev/i2c.h> | ||
28 | #include <subdev/bios/extdev.h> | ||
29 | |||
30 | static bool | ||
31 | probe_monitoring_device(struct nouveau_i2c_port *i2c, | ||
32 | struct i2c_board_info *info) | ||
33 | { | ||
34 | struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c->i2c); | ||
35 | struct i2c_client *client; | ||
36 | |||
37 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); | ||
38 | |||
39 | client = i2c_new_device(&i2c->adapter, info); | ||
40 | if (!client) | ||
41 | return false; | ||
42 | |||
43 | if (!client->driver || client->driver->detect(client, info)) { | ||
44 | i2c_unregister_device(client); | ||
45 | return false; | ||
46 | } | ||
47 | |||
48 | nv_info(priv, | ||
49 | "Found an %s at address 0x%x (controlled by lm_sensors)\n", | ||
50 | info->type, info->addr); | ||
51 | priv->ic = client; | ||
52 | |||
53 | return true; | ||
54 | } | ||
55 | |||
56 | void | ||
57 | nouveau_therm_ic_ctor(struct nouveau_therm *therm) | ||
58 | { | ||
59 | struct nouveau_therm_priv *priv = (void *)therm; | ||
60 | struct nouveau_bios *bios = nouveau_bios(therm); | ||
61 | struct nouveau_i2c *i2c = nouveau_i2c(therm); | ||
62 | struct nvbios_extdev_func extdev_entry; | ||
63 | struct i2c_board_info info[] = { | ||
64 | { I2C_BOARD_INFO("w83l785ts", 0x2d) }, | ||
65 | { I2C_BOARD_INFO("w83781d", 0x2d) }, | ||
66 | { I2C_BOARD_INFO("adt7473", 0x2e) }, | ||
67 | { I2C_BOARD_INFO("adt7473", 0x2d) }, | ||
68 | { I2C_BOARD_INFO("adt7473", 0x2c) }, | ||
69 | { I2C_BOARD_INFO("f75375", 0x2e) }, | ||
70 | { I2C_BOARD_INFO("lm99", 0x4c) }, | ||
71 | { I2C_BOARD_INFO("lm90", 0x4c) }, | ||
72 | { I2C_BOARD_INFO("lm90", 0x4d) }, | ||
73 | { I2C_BOARD_INFO("adm1021", 0x18) }, | ||
74 | { I2C_BOARD_INFO("adm1021", 0x19) }, | ||
75 | { I2C_BOARD_INFO("adm1021", 0x1a) }, | ||
76 | { I2C_BOARD_INFO("adm1021", 0x29) }, | ||
77 | { I2C_BOARD_INFO("adm1021", 0x2a) }, | ||
78 | { I2C_BOARD_INFO("adm1021", 0x2b) }, | ||
79 | { I2C_BOARD_INFO("adm1021", 0x4c) }, | ||
80 | { I2C_BOARD_INFO("adm1021", 0x4d) }, | ||
81 | { I2C_BOARD_INFO("adm1021", 0x4e) }, | ||
82 | { I2C_BOARD_INFO("lm63", 0x18) }, | ||
83 | { I2C_BOARD_INFO("lm63", 0x4e) }, | ||
84 | { } | ||
85 | }; | ||
86 | |||
87 | if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { | ||
88 | struct i2c_board_info board[] = { | ||
89 | { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, | ||
90 | { } | ||
91 | }; | ||
92 | |||
93 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | ||
94 | board, probe_monitoring_device); | ||
95 | if (priv->ic) | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) { | ||
100 | struct i2c_board_info board[] = { | ||
101 | { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, | ||
102 | { } | ||
103 | }; | ||
104 | |||
105 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | ||
106 | board, probe_monitoring_device); | ||
107 | if (priv->ic) | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | /* The vbios doesn't provide the address of an exisiting monitoring | ||
112 | device. Let's try our static list. | ||
113 | */ | ||
114 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, | ||
115 | probe_monitoring_device); | ||
116 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c new file mode 100644 index 00000000000..9021b541da8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Red Hat 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: Ben Skeggs | ||
23 | * Martin Peres | ||
24 | */ | ||
25 | |||
26 | #include "priv.h" | ||
27 | |||
28 | static int | ||
29 | nv40_sensor_setup(struct nouveau_therm *therm) | ||
30 | { | ||
31 | struct nouveau_device *device = nv_device(therm); | ||
32 | |||
33 | /* enable ADC readout and disable the ALARM threshold */ | ||
34 | if (device->chipset >= 0x46) { | ||
35 | nv_mask(therm, 0x15b8, 0x80000000, 0); | ||
36 | nv_wr32(therm, 0x15b0, 0x80003fff); | ||
37 | return nv_rd32(therm, 0x15b4) & 0x3fff; | ||
38 | } else { | ||
39 | nv_wr32(therm, 0x15b0, 0xff); | ||
40 | return nv_rd32(therm, 0x15b4) & 0xff; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | static int | ||
45 | nv40_temp_get(struct nouveau_therm *therm) | ||
46 | { | ||
47 | struct nouveau_therm_priv *priv = (void *)therm; | ||
48 | struct nouveau_device *device = nv_device(therm); | ||
49 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; | ||
50 | int core_temp; | ||
51 | |||
52 | if (device->chipset >= 0x46) { | ||
53 | nv_wr32(therm, 0x15b0, 0x80003fff); | ||
54 | core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; | ||
55 | } else { | ||
56 | nv_wr32(therm, 0x15b0, 0xff); | ||
57 | core_temp = nv_rd32(therm, 0x15b4) & 0xff; | ||
58 | } | ||
59 | |||
60 | /* Setup the sensor if the temperature is 0 */ | ||
61 | if (core_temp == 0) | ||
62 | core_temp = nv40_sensor_setup(therm); | ||
63 | |||
64 | if (sensor->slope_div == 0) | ||
65 | sensor->slope_div = 1; | ||
66 | if (sensor->offset_den == 0) | ||
67 | sensor->offset_den = 1; | ||
68 | if (sensor->slope_mult < 1) | ||
69 | sensor->slope_mult = 1; | ||
70 | |||
71 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; | ||
72 | core_temp = core_temp + sensor->offset_num / sensor->offset_den; | ||
73 | core_temp = core_temp + sensor->offset_constant - 8; | ||
74 | |||
75 | return core_temp; | ||
76 | } | ||
77 | |||
78 | int | ||
79 | nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) | ||
80 | { | ||
81 | if (line == 2) { | ||
82 | u32 reg = nv_rd32(therm, 0x0010f0); | ||
83 | if (reg & 0x80000000) { | ||
84 | *duty = (reg & 0x7fff0000) >> 16; | ||
85 | *divs = (reg & 0x00007fff); | ||
86 | return 0; | ||
87 | } | ||
88 | } else | ||
89 | if (line == 9) { | ||
90 | u32 reg = nv_rd32(therm, 0x0015f4); | ||
91 | if (reg & 0x80000000) { | ||
92 | *divs = nv_rd32(therm, 0x0015f8); | ||
93 | *duty = (reg & 0x7fffffff); | ||
94 | return 0; | ||
95 | } | ||
96 | } else { | ||
97 | nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); | ||
98 | return -ENODEV; | ||
99 | } | ||
100 | |||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | int | ||
105 | nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) | ||
106 | { | ||
107 | if (line == 2) { | ||
108 | nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs); | ||
109 | } else | ||
110 | if (line == 9) { | ||
111 | nv_wr32(therm, 0x0015f8, divs); | ||
112 | nv_wr32(therm, 0x0015f4, duty | 0x80000000); | ||
113 | } else { | ||
114 | nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); | ||
115 | return -ENODEV; | ||
116 | } | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int | ||
122 | nv40_therm_ctor(struct nouveau_object *parent, | ||
123 | struct nouveau_object *engine, | ||
124 | struct nouveau_oclass *oclass, void *data, u32 size, | ||
125 | struct nouveau_object **pobject) | ||
126 | { | ||
127 | struct nouveau_therm_priv *priv; | ||
128 | struct nouveau_therm *therm; | ||
129 | int ret; | ||
130 | |||
131 | ret = nouveau_therm_create(parent, engine, oclass, &priv); | ||
132 | *pobject = nv_object(priv); | ||
133 | therm = (void *) priv; | ||
134 | if (ret) | ||
135 | return ret; | ||
136 | |||
137 | nouveau_therm_ic_ctor(therm); | ||
138 | nouveau_therm_sensor_ctor(therm); | ||
139 | nouveau_therm_fan_ctor(therm); | ||
140 | |||
141 | priv->fan.pwm_get = nv40_fan_pwm_get; | ||
142 | priv->fan.pwm_set = nv40_fan_pwm_set; | ||
143 | |||
144 | therm->temp_get = nv40_temp_get; | ||
145 | therm->fan_get = nouveau_therm_fan_get; | ||
146 | therm->fan_set = nouveau_therm_fan_set; | ||
147 | therm->fan_sense = nouveau_therm_fan_sense; | ||
148 | therm->attr_get = nouveau_therm_attr_get; | ||
149 | therm->attr_set = nouveau_therm_attr_set; | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | struct nouveau_oclass | ||
155 | nv40_therm_oclass = { | ||
156 | .handle = NV_SUBDEV(THERM, 0x40), | ||
157 | .ofuncs = &(struct nouveau_ofuncs) { | ||
158 | .ctor = nv40_therm_ctor, | ||
159 | .dtor = _nouveau_therm_dtor, | ||
160 | .init = nouveau_therm_init, | ||
161 | .fini = nouveau_therm_fini, | ||
162 | }, | ||
163 | }; \ No newline at end of file | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c new file mode 100644 index 00000000000..f7f51f35d18 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Red Hat 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: Ben Skeggs | ||
23 | * Martin Peres | ||
24 | */ | ||
25 | |||
26 | #include "priv.h" | ||
27 | |||
28 | static int | ||
29 | pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx) | ||
30 | { | ||
31 | if (*line == 0x04) { | ||
32 | *ctrl = 0x00e100; | ||
33 | *line = 4; | ||
34 | *indx = 0; | ||
35 | } else | ||
36 | if (*line == 0x09) { | ||
37 | *ctrl = 0x00e100; | ||
38 | *line = 9; | ||
39 | *indx = 1; | ||
40 | } else | ||
41 | if (*line == 0x10) { | ||
42 | *ctrl = 0x00e28c; | ||
43 | *line = 0; | ||
44 | *indx = 0; | ||
45 | } else { | ||
46 | nv_error(therm, "unknown pwm ctrl for gpio %d\n", *line); | ||
47 | return -ENODEV; | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int | ||
54 | nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) | ||
55 | { | ||
56 | int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); | ||
57 | if (ret) | ||
58 | return ret; | ||
59 | |||
60 | if (nv_rd32(therm, ctrl) & (1 << line)) { | ||
61 | *divs = nv_rd32(therm, 0x00e114 + (id * 8)); | ||
62 | *duty = nv_rd32(therm, 0x00e118 + (id * 8)); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | int | ||
70 | nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) | ||
71 | { | ||
72 | int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | |||
76 | nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line); | ||
77 | nv_wr32(therm, 0x00e114 + (id * 8), divs); | ||
78 | nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | int | ||
83 | nv50_temp_get(struct nouveau_therm *therm) | ||
84 | { | ||
85 | return nv_rd32(therm, 0x20400); | ||
86 | } | ||
87 | |||
88 | static int | ||
89 | nv50_therm_ctor(struct nouveau_object *parent, | ||
90 | struct nouveau_object *engine, | ||
91 | struct nouveau_oclass *oclass, void *data, u32 size, | ||
92 | struct nouveau_object **pobject) | ||
93 | { | ||
94 | struct nouveau_therm_priv *priv; | ||
95 | struct nouveau_therm *therm; | ||
96 | int ret; | ||
97 | |||
98 | ret = nouveau_therm_create(parent, engine, oclass, &priv); | ||
99 | *pobject = nv_object(priv); | ||
100 | therm = (void *) priv; | ||
101 | if (ret) | ||
102 | return ret; | ||
103 | |||
104 | nouveau_therm_ic_ctor(therm); | ||
105 | nouveau_therm_sensor_ctor(therm); | ||
106 | nouveau_therm_fan_ctor(therm); | ||
107 | |||
108 | priv->fan.pwm_get = nv50_fan_pwm_get; | ||
109 | priv->fan.pwm_set = nv50_fan_pwm_set; | ||
110 | |||
111 | therm->temp_get = nv50_temp_get; | ||
112 | therm->fan_get = nouveau_therm_fan_get; | ||
113 | therm->fan_set = nouveau_therm_fan_set; | ||
114 | therm->fan_sense = nouveau_therm_fan_sense; | ||
115 | therm->attr_get = nouveau_therm_attr_get; | ||
116 | therm->attr_set = nouveau_therm_attr_set; | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | struct nouveau_oclass | ||
122 | nv50_therm_oclass = { | ||
123 | .handle = NV_SUBDEV(THERM, 0x50), | ||
124 | .ofuncs = &(struct nouveau_ofuncs) { | ||
125 | .ctor = nv50_therm_ctor, | ||
126 | .dtor = _nouveau_therm_dtor, | ||
127 | .init = nouveau_therm_init, | ||
128 | .fini = nouveau_therm_fini, | ||
129 | }, | ||
130 | }; | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h new file mode 100644 index 00000000000..b7207b4524f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright 2012 The 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/therm.h> | ||
26 | |||
27 | #include <subdev/bios/extdev.h> | ||
28 | #include <subdev/bios/perf.h> | ||
29 | #include <subdev/bios/therm.h> | ||
30 | |||
31 | struct nouveau_therm_priv { | ||
32 | struct nouveau_therm base; | ||
33 | |||
34 | /* bios */ | ||
35 | struct nvbios_therm_sensor bios_sensor; | ||
36 | struct nvbios_therm_fan bios_fan; | ||
37 | struct nvbios_perf_fan bios_perf_fan; | ||
38 | |||
39 | /* fan priv */ | ||
40 | struct { | ||
41 | int percent; | ||
42 | |||
43 | int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); | ||
44 | int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); | ||
45 | } fan; | ||
46 | |||
47 | /* ic */ | ||
48 | struct i2c_client *ic; | ||
49 | }; | ||
50 | |||
51 | int nouveau_therm_init(struct nouveau_object *object); | ||
52 | int nouveau_therm_fini(struct nouveau_object *object, bool suspend); | ||
53 | int nouveau_therm_attr_get(struct nouveau_therm *therm, | ||
54 | enum nouveau_therm_attr_type type); | ||
55 | int nouveau_therm_attr_set(struct nouveau_therm *therm, | ||
56 | enum nouveau_therm_attr_type type, int value); | ||
57 | |||
58 | void nouveau_therm_ic_ctor(struct nouveau_therm *therm); | ||
59 | |||
60 | int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); | ||
61 | |||
62 | int nouveau_therm_fan_ctor(struct nouveau_therm *therm); | ||
63 | int nouveau_therm_fan_get(struct nouveau_therm *therm); | ||
64 | int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); | ||
65 | |||
66 | int nouveau_therm_fan_sense(struct nouveau_therm *therm); | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c new file mode 100644 index 00000000000..204282301fb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright 2012 The 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 "priv.h" | ||
26 | |||
27 | #include <core/object.h> | ||
28 | #include <core/device.h> | ||
29 | |||
30 | #include <subdev/bios.h> | ||
31 | |||
32 | static void | ||
33 | nouveau_therm_temp_set_defaults(struct nouveau_therm *therm) | ||
34 | { | ||
35 | struct nouveau_therm_priv *priv = (void *)therm; | ||
36 | |||
37 | priv->bios_sensor.slope_mult = 1; | ||
38 | priv->bios_sensor.slope_div = 1; | ||
39 | priv->bios_sensor.offset_num = 0; | ||
40 | priv->bios_sensor.offset_den = 1; | ||
41 | priv->bios_sensor.offset_constant = 0; | ||
42 | |||
43 | priv->bios_sensor.thrs_fan_boost.temp = 90; | ||
44 | priv->bios_sensor.thrs_fan_boost.hysteresis = 3; | ||
45 | |||
46 | priv->bios_sensor.thrs_down_clock.temp = 95; | ||
47 | priv->bios_sensor.thrs_down_clock.hysteresis = 3; | ||
48 | |||
49 | priv->bios_sensor.thrs_critical.temp = 105; | ||
50 | priv->bios_sensor.thrs_critical.hysteresis = 5; | ||
51 | |||
52 | priv->bios_sensor.thrs_shutdown.temp = 135; | ||
53 | priv->bios_sensor.thrs_shutdown.hysteresis = 5; /*not that it matters */ | ||
54 | } | ||
55 | |||
56 | |||
57 | static void | ||
58 | nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) | ||
59 | { | ||
60 | struct nouveau_therm_priv *priv = (void *)therm; | ||
61 | |||
62 | if (!priv->bios_sensor.slope_div) | ||
63 | priv->bios_sensor.slope_div = 1; | ||
64 | if (!priv->bios_sensor.offset_den) | ||
65 | priv->bios_sensor.offset_den = 1; | ||
66 | } | ||
67 | |||
68 | int | ||
69 | nouveau_therm_sensor_ctor(struct nouveau_therm *therm) | ||
70 | { | ||
71 | struct nouveau_therm_priv *priv = (void *)therm; | ||
72 | struct nouveau_bios *bios = nouveau_bios(therm); | ||
73 | |||
74 | nouveau_therm_temp_set_defaults(therm); | ||
75 | if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, | ||
76 | &priv->bios_sensor)) | ||
77 | nv_error(therm, "nvbios_therm_sensor_parse failed\n"); | ||
78 | nouveau_therm_temp_safety_checks(therm); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index b5c6a43511d..a11d2e4f8f6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c | |||
@@ -304,8 +304,6 @@ nouveau_perf_init(struct drm_device *dev) | |||
304 | } | 304 | } |
305 | 305 | ||
306 | perf = nouveau_perf_table(dev, &ver); | 306 | perf = nouveau_perf_table(dev, &ver); |
307 | if (ver >= 0x20 && ver < 0x40) | ||
308 | pm->fan.pwm_divisor = ROM16(perf[6]); | ||
309 | 307 | ||
310 | while ((perf = nouveau_perf_entry(dev, ++i, &ver, &hdr, &cnt, &len))) { | 308 | while ((perf = nouveau_perf_entry(dev, ++i, &ver, &hdr, &cnt, &len))) { |
311 | struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; | 309 | struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index bdd50953488..8317e82b86c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
@@ -34,9 +34,9 @@ | |||
34 | #include "nouveau_drm.h" | 34 | #include "nouveau_drm.h" |
35 | #include "nouveau_pm.h" | 35 | #include "nouveau_pm.h" |
36 | 36 | ||
37 | #include <subdev/bios/gpio.h> | ||
38 | #include <subdev/gpio.h> | 37 | #include <subdev/gpio.h> |
39 | #include <subdev/timer.h> | 38 | #include <subdev/timer.h> |
39 | #include <subdev/therm.h> | ||
40 | 40 | ||
41 | MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); | 41 | MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); |
42 | static char *nouveau_perflvl; | 42 | static char *nouveau_perflvl; |
@@ -47,86 +47,21 @@ static int nouveau_perflvl_wr; | |||
47 | module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); | 47 | module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); |
48 | 48 | ||
49 | static int | 49 | static int |
50 | nouveau_pwmfan_get(struct drm_device *dev) | ||
51 | { | ||
52 | struct nouveau_pm *pm = nouveau_pm(dev); | ||
53 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
54 | struct nouveau_device *device = nv_device(drm->device); | ||
55 | struct nouveau_gpio *gpio = nouveau_gpio(device); | ||
56 | struct dcb_gpio_func func; | ||
57 | u32 divs, duty; | ||
58 | int ret; | ||
59 | |||
60 | if (!pm->pwm_get) | ||
61 | return -ENODEV; | ||
62 | |||
63 | ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); | ||
64 | if (ret == 0) { | ||
65 | ret = pm->pwm_get(dev, func.line, &divs, &duty); | ||
66 | if (ret == 0 && divs) { | ||
67 | divs = max(divs, duty); | ||
68 | if (device->card_type <= NV_40 || (func.log[0] & 1)) | ||
69 | duty = divs - duty; | ||
70 | return (duty * 100) / divs; | ||
71 | } | ||
72 | |||
73 | return gpio->get(gpio, 0, func.func, func.line) * 100; | ||
74 | } | ||
75 | |||
76 | return -ENODEV; | ||
77 | } | ||
78 | |||
79 | static int | ||
80 | nouveau_pwmfan_set(struct drm_device *dev, int percent) | ||
81 | { | ||
82 | struct nouveau_pm *pm = nouveau_pm(dev); | ||
83 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
84 | struct nouveau_device *device = nv_device(drm->device); | ||
85 | struct nouveau_gpio *gpio = nouveau_gpio(device); | ||
86 | struct dcb_gpio_func func; | ||
87 | u32 divs, duty; | ||
88 | int ret; | ||
89 | |||
90 | if (!pm->pwm_set) | ||
91 | return -ENODEV; | ||
92 | |||
93 | ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); | ||
94 | if (ret == 0) { | ||
95 | divs = pm->fan.pwm_divisor; | ||
96 | if (pm->fan.pwm_freq) { | ||
97 | /*XXX: PNVIO clock more than likely... */ | ||
98 | divs = 135000 / pm->fan.pwm_freq; | ||
99 | if (nv_device(drm->device)->chipset < 0xa3) | ||
100 | divs /= 4; | ||
101 | } | ||
102 | |||
103 | duty = ((divs * percent) + 99) / 100; | ||
104 | if (device->card_type <= NV_40 || (func.log[0] & 1)) | ||
105 | duty = divs - duty; | ||
106 | |||
107 | ret = pm->pwm_set(dev, func.line, divs, duty); | ||
108 | if (!ret) | ||
109 | pm->fan.percent = percent; | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | return -ENODEV; | ||
114 | } | ||
115 | |||
116 | static int | ||
117 | nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, | 50 | nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, |
118 | struct nouveau_pm_level *a, struct nouveau_pm_level *b) | 51 | struct nouveau_pm_level *a, struct nouveau_pm_level *b) |
119 | { | 52 | { |
120 | struct nouveau_drm *drm = nouveau_drm(dev); | 53 | struct nouveau_drm *drm = nouveau_drm(dev); |
121 | struct nouveau_pm *pm = nouveau_pm(dev); | 54 | struct nouveau_pm *pm = nouveau_pm(dev); |
55 | struct nouveau_therm *therm = nouveau_therm(drm); | ||
122 | int ret; | 56 | int ret; |
123 | 57 | ||
124 | /*XXX: not on all boards, we should control based on temperature | 58 | /*XXX: not on all boards, we should control based on temperature |
125 | * on recent boards.. or maybe on some other factor we don't | 59 | * on recent boards.. or maybe on some other factor we don't |
126 | * know about? | 60 | * know about? |
127 | */ | 61 | */ |
128 | if (a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { | 62 | if (therm && therm->fan_set && |
129 | ret = nouveau_pwmfan_set(dev, perflvl->fanspeed); | 63 | a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { |
64 | ret = therm->fan_set(therm, perflvl->fanspeed); | ||
130 | if (ret && ret != -ENODEV) { | 65 | if (ret && ret != -ENODEV) { |
131 | NV_ERROR(drm, "fanspeed set failed: %d\n", ret); | 66 | NV_ERROR(drm, "fanspeed set failed: %d\n", ret); |
132 | return ret; | 67 | return ret; |
@@ -291,7 +226,9 @@ const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = { | |||
291 | static int | 226 | static int |
292 | nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | 227 | nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) |
293 | { | 228 | { |
229 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
294 | struct nouveau_pm *pm = nouveau_pm(dev); | 230 | struct nouveau_pm *pm = nouveau_pm(dev); |
231 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
295 | int ret; | 232 | int ret; |
296 | 233 | ||
297 | memset(perflvl, 0, sizeof(*perflvl)); | 234 | memset(perflvl, 0, sizeof(*perflvl)); |
@@ -310,9 +247,11 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | |||
310 | } | 247 | } |
311 | } | 248 | } |
312 | 249 | ||
313 | ret = nouveau_pwmfan_get(dev); | 250 | if (therm && therm->fan_get) { |
314 | if (ret > 0) | 251 | ret = therm->fan_get(therm); |
315 | perflvl->fanspeed = ret; | 252 | if (ret >= 0) |
253 | perflvl->fanspeed = ret; | ||
254 | } | ||
316 | 255 | ||
317 | nouveau_mem_timing_read(dev, &perflvl->timing); | 256 | nouveau_mem_timing_read(dev, &perflvl->timing); |
318 | return 0; | 257 | return 0; |
@@ -462,9 +401,10 @@ static ssize_t | |||
462 | nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) | 401 | nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) |
463 | { | 402 | { |
464 | struct drm_device *dev = dev_get_drvdata(d); | 403 | struct drm_device *dev = dev_get_drvdata(d); |
465 | struct nouveau_pm *pm = nouveau_pm(dev); | 404 | struct nouveau_drm *drm = nouveau_drm(dev); |
405 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
466 | 406 | ||
467 | return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000); | 407 | return snprintf(buf, PAGE_SIZE, "%d\n", therm->temp_get(therm) * 1000); |
468 | } | 408 | } |
469 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, | 409 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, |
470 | NULL, 0); | 410 | NULL, 0); |
@@ -473,26 +413,25 @@ static ssize_t | |||
473 | nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) | 413 | nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) |
474 | { | 414 | { |
475 | struct drm_device *dev = dev_get_drvdata(d); | 415 | struct drm_device *dev = dev_get_drvdata(d); |
476 | struct nouveau_pm *pm = nouveau_pm(dev); | 416 | struct nouveau_drm *drm = nouveau_drm(dev); |
477 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 417 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
478 | 418 | ||
479 | return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000); | 419 | return snprintf(buf, PAGE_SIZE, "%d\n", |
420 | therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK) * 1000); | ||
480 | } | 421 | } |
481 | static ssize_t | 422 | static ssize_t |
482 | nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a, | 423 | nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a, |
483 | const char *buf, size_t count) | 424 | const char *buf, size_t count) |
484 | { | 425 | { |
485 | struct drm_device *dev = dev_get_drvdata(d); | 426 | struct drm_device *dev = dev_get_drvdata(d); |
486 | struct nouveau_pm *pm = nouveau_pm(dev); | 427 | struct nouveau_drm *drm = nouveau_drm(dev); |
487 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 428 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
488 | long value; | 429 | long value; |
489 | 430 | ||
490 | if (kstrtol(buf, 10, &value) == -EINVAL) | 431 | if (kstrtol(buf, 10, &value) == -EINVAL) |
491 | return count; | 432 | return count; |
492 | 433 | ||
493 | temp->down_clock = value/1000; | 434 | therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK, value / 1000); |
494 | |||
495 | nouveau_temp_safety_checks(dev); | ||
496 | 435 | ||
497 | return count; | 436 | return count; |
498 | } | 437 | } |
@@ -505,10 +444,11 @@ nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a, | |||
505 | char *buf) | 444 | char *buf) |
506 | { | 445 | { |
507 | struct drm_device *dev = dev_get_drvdata(d); | 446 | struct drm_device *dev = dev_get_drvdata(d); |
508 | struct nouveau_pm *pm = nouveau_pm(dev); | 447 | struct nouveau_drm *drm = nouveau_drm(dev); |
509 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 448 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
510 | 449 | ||
511 | return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000); | 450 | return snprintf(buf, PAGE_SIZE, "%d\n", |
451 | therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL) * 1000); | ||
512 | } | 452 | } |
513 | static ssize_t | 453 | static ssize_t |
514 | nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a, | 454 | nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a, |
@@ -516,16 +456,14 @@ nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a, | |||
516 | size_t count) | 456 | size_t count) |
517 | { | 457 | { |
518 | struct drm_device *dev = dev_get_drvdata(d); | 458 | struct drm_device *dev = dev_get_drvdata(d); |
519 | struct nouveau_pm *pm = nouveau_pm(dev); | 459 | struct nouveau_drm *drm = nouveau_drm(dev); |
520 | struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 460 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
521 | long value; | 461 | long value; |
522 | 462 | ||
523 | if (kstrtol(buf, 10, &value) == -EINVAL) | 463 | if (kstrtol(buf, 10, &value) == -EINVAL) |
524 | return count; | 464 | return count; |
525 | 465 | ||
526 | temp->critical = value/1000; | 466 | therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL, value / 1000); |
527 | |||
528 | nouveau_temp_safety_checks(dev); | ||
529 | 467 | ||
530 | return count; | 468 | return count; |
531 | } | 469 | } |
@@ -558,34 +496,9 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, | |||
558 | { | 496 | { |
559 | struct drm_device *dev = dev_get_drvdata(d); | 497 | struct drm_device *dev = dev_get_drvdata(d); |
560 | struct nouveau_drm *drm = nouveau_drm(dev); | 498 | struct nouveau_drm *drm = nouveau_drm(dev); |
561 | struct nouveau_timer *ptimer = nouveau_timer(drm->device); | 499 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
562 | struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||
563 | struct dcb_gpio_func func; | ||
564 | u32 cycles, cur, prev; | ||
565 | u64 start; | ||
566 | |||
567 | if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) | ||
568 | return -ENODEV; | ||
569 | |||
570 | /* Monitor the GPIO input 0x3b for 250ms. | ||
571 | * When the fan spins, it changes the value of GPIO FAN_SENSE. | ||
572 | * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. | ||
573 | */ | ||
574 | start = ptimer->read(ptimer); | ||
575 | prev = gpio->get(gpio, 0, func.func, func.line); | ||
576 | cycles = 0; | ||
577 | do { | ||
578 | cur = gpio->get(gpio, 0, func.func, func.line); | ||
579 | if (prev != cur) { | ||
580 | cycles++; | ||
581 | prev = cur; | ||
582 | } | ||
583 | 500 | ||
584 | usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ | 501 | return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm)); |
585 | } while (ptimer->read(ptimer) - start < 250000000); | ||
586 | |||
587 | /* interpolate to get rpm */ | ||
588 | return sprintf(buf, "%i\n", cycles / 4 * 4 * 60); | ||
589 | } | 502 | } |
590 | static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, | 503 | static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, |
591 | NULL, 0); | 504 | NULL, 0); |
@@ -594,9 +507,11 @@ static ssize_t | |||
594 | nouveau_hwmon_get_pwm0(struct device *d, struct device_attribute *a, char *buf) | 507 | nouveau_hwmon_get_pwm0(struct device *d, struct device_attribute *a, char *buf) |
595 | { | 508 | { |
596 | struct drm_device *dev = dev_get_drvdata(d); | 509 | struct drm_device *dev = dev_get_drvdata(d); |
510 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
511 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
597 | int ret; | 512 | int ret; |
598 | 513 | ||
599 | ret = nouveau_pwmfan_get(dev); | 514 | ret = therm->fan_get(therm); |
600 | if (ret < 0) | 515 | if (ret < 0) |
601 | return ret; | 516 | return ret; |
602 | 517 | ||
@@ -608,7 +523,8 @@ nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a, | |||
608 | const char *buf, size_t count) | 523 | const char *buf, size_t count) |
609 | { | 524 | { |
610 | struct drm_device *dev = dev_get_drvdata(d); | 525 | struct drm_device *dev = dev_get_drvdata(d); |
611 | struct nouveau_pm *pm = nouveau_pm(dev); | 526 | struct nouveau_drm *drm = nouveau_drm(dev); |
527 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
612 | int ret = -ENODEV; | 528 | int ret = -ENODEV; |
613 | long value; | 529 | long value; |
614 | 530 | ||
@@ -618,12 +534,7 @@ nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a, | |||
618 | if (kstrtol(buf, 10, &value) == -EINVAL) | 534 | if (kstrtol(buf, 10, &value) == -EINVAL) |
619 | return -EINVAL; | 535 | return -EINVAL; |
620 | 536 | ||
621 | if (value < pm->fan.min_duty) | 537 | ret = therm->fan_set(therm, value); |
622 | value = pm->fan.min_duty; | ||
623 | if (value > pm->fan.max_duty) | ||
624 | value = pm->fan.max_duty; | ||
625 | |||
626 | ret = nouveau_pwmfan_set(dev, value); | ||
627 | if (ret) | 538 | if (ret) |
628 | return ret; | 539 | return ret; |
629 | 540 | ||
@@ -639,9 +550,15 @@ nouveau_hwmon_get_pwm0_min(struct device *d, | |||
639 | struct device_attribute *a, char *buf) | 550 | struct device_attribute *a, char *buf) |
640 | { | 551 | { |
641 | struct drm_device *dev = dev_get_drvdata(d); | 552 | struct drm_device *dev = dev_get_drvdata(d); |
642 | struct nouveau_pm *pm = nouveau_pm(dev); | 553 | struct nouveau_drm *drm = nouveau_drm(dev); |
554 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
555 | int ret; | ||
556 | |||
557 | ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MIN_DUTY); | ||
558 | if (ret < 0) | ||
559 | return ret; | ||
643 | 560 | ||
644 | return sprintf(buf, "%i\n", pm->fan.min_duty); | 561 | return sprintf(buf, "%i\n", ret); |
645 | } | 562 | } |
646 | 563 | ||
647 | static ssize_t | 564 | static ssize_t |
@@ -649,22 +566,17 @@ nouveau_hwmon_set_pwm0_min(struct device *d, struct device_attribute *a, | |||
649 | const char *buf, size_t count) | 566 | const char *buf, size_t count) |
650 | { | 567 | { |
651 | struct drm_device *dev = dev_get_drvdata(d); | 568 | struct drm_device *dev = dev_get_drvdata(d); |
652 | struct nouveau_pm *pm = nouveau_pm(dev); | 569 | struct nouveau_drm *drm = nouveau_drm(dev); |
570 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
653 | long value; | 571 | long value; |
572 | int ret; | ||
654 | 573 | ||
655 | if (kstrtol(buf, 10, &value) == -EINVAL) | 574 | if (kstrtol(buf, 10, &value) == -EINVAL) |
656 | return -EINVAL; | 575 | return -EINVAL; |
657 | 576 | ||
658 | if (value < 0) | 577 | ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MIN_DUTY, value); |
659 | value = 0; | 578 | if (ret < 0) |
660 | 579 | return ret; | |
661 | if (pm->fan.max_duty - value < 10) | ||
662 | value = pm->fan.max_duty - 10; | ||
663 | |||
664 | if (value < 10) | ||
665 | pm->fan.min_duty = 10; | ||
666 | else | ||
667 | pm->fan.min_duty = value; | ||
668 | 580 | ||
669 | return count; | 581 | return count; |
670 | } | 582 | } |
@@ -678,9 +590,15 @@ nouveau_hwmon_get_pwm0_max(struct device *d, | |||
678 | struct device_attribute *a, char *buf) | 590 | struct device_attribute *a, char *buf) |
679 | { | 591 | { |
680 | struct drm_device *dev = dev_get_drvdata(d); | 592 | struct drm_device *dev = dev_get_drvdata(d); |
681 | struct nouveau_pm *pm = nouveau_pm(dev); | 593 | struct nouveau_drm *drm = nouveau_drm(dev); |
594 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
595 | int ret; | ||
682 | 596 | ||
683 | return sprintf(buf, "%i\n", pm->fan.max_duty); | 597 | ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MAX_DUTY); |
598 | if (ret < 0) | ||
599 | return ret; | ||
600 | |||
601 | return sprintf(buf, "%i\n", ret); | ||
684 | } | 602 | } |
685 | 603 | ||
686 | static ssize_t | 604 | static ssize_t |
@@ -688,22 +606,17 @@ nouveau_hwmon_set_pwm0_max(struct device *d, struct device_attribute *a, | |||
688 | const char *buf, size_t count) | 606 | const char *buf, size_t count) |
689 | { | 607 | { |
690 | struct drm_device *dev = dev_get_drvdata(d); | 608 | struct drm_device *dev = dev_get_drvdata(d); |
691 | struct nouveau_pm *pm = nouveau_pm(dev); | 609 | struct nouveau_drm *drm = nouveau_drm(dev); |
610 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
692 | long value; | 611 | long value; |
612 | int ret; | ||
693 | 613 | ||
694 | if (kstrtol(buf, 10, &value) == -EINVAL) | 614 | if (kstrtol(buf, 10, &value) == -EINVAL) |
695 | return -EINVAL; | 615 | return -EINVAL; |
696 | 616 | ||
697 | if (value < 0) | 617 | ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MAX_DUTY, value); |
698 | value = 0; | 618 | if (ret < 0) |
699 | 619 | return ret; | |
700 | if (value - pm->fan.min_duty < 10) | ||
701 | value = pm->fan.min_duty + 10; | ||
702 | |||
703 | if (value > 100) | ||
704 | pm->fan.max_duty = 100; | ||
705 | else | ||
706 | pm->fan.max_duty = value; | ||
707 | 620 | ||
708 | return count; | 621 | return count; |
709 | } | 622 | } |
@@ -747,14 +660,14 @@ nouveau_hwmon_init(struct drm_device *dev) | |||
747 | { | 660 | { |
748 | struct nouveau_pm *pm = nouveau_pm(dev); | 661 | struct nouveau_pm *pm = nouveau_pm(dev); |
749 | struct nouveau_drm *drm = nouveau_drm(dev); | 662 | struct nouveau_drm *drm = nouveau_drm(dev); |
750 | struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | 663 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
751 | struct dcb_gpio_func func; | ||
752 | 664 | ||
753 | #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) | 665 | #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) |
754 | struct device *hwmon_dev; | 666 | struct device *hwmon_dev; |
755 | int ret = 0; | 667 | int ret = 0; |
756 | 668 | ||
757 | if (!pm->temp_get) | 669 | if (!therm || !therm->temp_get || !therm->attr_get || |
670 | !therm->attr_set || therm->temp_get(therm) < 0) | ||
758 | return -ENODEV; | 671 | return -ENODEV; |
759 | 672 | ||
760 | hwmon_dev = hwmon_device_register(&dev->pdev->dev); | 673 | hwmon_dev = hwmon_device_register(&dev->pdev->dev); |
@@ -776,7 +689,7 @@ nouveau_hwmon_init(struct drm_device *dev) | |||
776 | /*XXX: incorrect, need better detection for this, some boards have | 689 | /*XXX: incorrect, need better detection for this, some boards have |
777 | * the gpio entries for pwm fan control even when there's no | 690 | * the gpio entries for pwm fan control even when there's no |
778 | * actual fan connected to it... therm table? */ | 691 | * actual fan connected to it... therm table? */ |
779 | if (nouveau_pwmfan_get(dev) >= 0) { | 692 | if (therm->fan_get && therm->fan_get(therm) >= 0) { |
780 | ret = sysfs_create_group(&dev->pdev->dev.kobj, | 693 | ret = sysfs_create_group(&dev->pdev->dev.kobj, |
781 | &hwmon_pwm_fan_attrgroup); | 694 | &hwmon_pwm_fan_attrgroup); |
782 | if (ret) | 695 | if (ret) |
@@ -784,7 +697,7 @@ nouveau_hwmon_init(struct drm_device *dev) | |||
784 | } | 697 | } |
785 | 698 | ||
786 | /* if the card can read the fan rpm */ | 699 | /* if the card can read the fan rpm */ |
787 | if (!gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) { | 700 | if (therm->fan_sense(therm) >= 0) { |
788 | ret = sysfs_create_group(&dev->pdev->dev.kobj, | 701 | ret = sysfs_create_group(&dev->pdev->dev.kobj, |
789 | &hwmon_fan_rpm_attrgroup); | 702 | &hwmon_fan_rpm_attrgroup); |
790 | if (ret) | 703 | if (ret) |
@@ -873,9 +786,6 @@ nouveau_pm_init(struct drm_device *dev) | |||
873 | pm->clocks_set = nv40_pm_clocks_set; | 786 | pm->clocks_set = nv40_pm_clocks_set; |
874 | pm->voltage_get = nouveau_voltage_gpio_get; | 787 | pm->voltage_get = nouveau_voltage_gpio_get; |
875 | pm->voltage_set = nouveau_voltage_gpio_set; | 788 | pm->voltage_set = nouveau_voltage_gpio_set; |
876 | pm->temp_get = nv40_temp_get; | ||
877 | pm->pwm_get = nv40_pm_pwm_get; | ||
878 | pm->pwm_set = nv40_pm_pwm_set; | ||
879 | } else | 789 | } else |
880 | if (device->card_type < NV_C0) { | 790 | if (device->card_type < NV_C0) { |
881 | if (device->chipset < 0xa3 || | 791 | if (device->chipset < 0xa3 || |
@@ -891,9 +801,6 @@ nouveau_pm_init(struct drm_device *dev) | |||
891 | } | 801 | } |
892 | pm->voltage_get = nouveau_voltage_gpio_get; | 802 | pm->voltage_get = nouveau_voltage_gpio_get; |
893 | pm->voltage_set = nouveau_voltage_gpio_set; | 803 | pm->voltage_set = nouveau_voltage_gpio_set; |
894 | pm->temp_get = nv84_temp_get; | ||
895 | pm->pwm_get = nv50_pm_pwm_get; | ||
896 | pm->pwm_set = nv50_pm_pwm_set; | ||
897 | } else | 804 | } else |
898 | if (device->card_type < NV_E0) { | 805 | if (device->card_type < NV_E0) { |
899 | pm->clocks_get = nvc0_pm_clocks_get; | 806 | pm->clocks_get = nvc0_pm_clocks_get; |
@@ -901,17 +808,11 @@ nouveau_pm_init(struct drm_device *dev) | |||
901 | pm->clocks_set = nvc0_pm_clocks_set; | 808 | pm->clocks_set = nvc0_pm_clocks_set; |
902 | pm->voltage_get = nouveau_voltage_gpio_get; | 809 | pm->voltage_get = nouveau_voltage_gpio_get; |
903 | pm->voltage_set = nouveau_voltage_gpio_set; | 810 | pm->voltage_set = nouveau_voltage_gpio_set; |
904 | pm->temp_get = nv84_temp_get; | ||
905 | if (device->card_type < NV_D0) { | ||
906 | pm->pwm_get = nv50_pm_pwm_get; | ||
907 | pm->pwm_set = nv50_pm_pwm_set; | ||
908 | } | ||
909 | } | 811 | } |
910 | 812 | ||
911 | 813 | ||
912 | /* parse aux tables from vbios */ | 814 | /* parse aux tables from vbios */ |
913 | nouveau_volt_init(dev); | 815 | nouveau_volt_init(dev); |
914 | nouveau_temp_init(dev); | ||
915 | 816 | ||
916 | INIT_LIST_HEAD(&pm->profiles); | 817 | INIT_LIST_HEAD(&pm->profiles); |
917 | 818 | ||
@@ -950,9 +851,6 @@ nouveau_pm_init(struct drm_device *dev) | |||
950 | if (nouveau_perflvl != NULL) | 851 | if (nouveau_perflvl != NULL) |
951 | nouveau_pm_profile_set(dev, nouveau_perflvl); | 852 | nouveau_pm_profile_set(dev, nouveau_perflvl); |
952 | 853 | ||
953 | /* determine the current fan speed */ | ||
954 | pm->fan.percent = nouveau_pwmfan_get(dev); | ||
955 | |||
956 | nouveau_sysfs_init(dev); | 854 | nouveau_sysfs_init(dev); |
957 | nouveau_hwmon_init(dev); | 855 | nouveau_hwmon_init(dev); |
958 | #if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY) | 856 | #if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY) |
@@ -977,7 +875,6 @@ nouveau_pm_fini(struct drm_device *dev) | |||
977 | if (pm->cur != &pm->boot) | 875 | if (pm->cur != &pm->boot) |
978 | nouveau_pm_perflvl_set(dev, &pm->boot); | 876 | nouveau_pm_perflvl_set(dev, &pm->boot); |
979 | 877 | ||
980 | nouveau_temp_fini(dev); | ||
981 | nouveau_perf_fini(dev); | 878 | nouveau_perf_fini(dev); |
982 | nouveau_volt_fini(dev); | 879 | nouveau_volt_fini(dev); |
983 | 880 | ||
@@ -1003,5 +900,4 @@ nouveau_pm_resume(struct drm_device *dev) | |||
1003 | perflvl = pm->cur; | 900 | perflvl = pm->cur; |
1004 | pm->cur = &pm->boot; | 901 | pm->cur = &pm->boot; |
1005 | nouveau_pm_perflvl_set(dev, perflvl); | 902 | nouveau_pm_perflvl_set(dev, perflvl); |
1006 | nouveau_pwmfan_set(dev, pm->fan.percent); | ||
1007 | } | 903 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h index 2e39ccbd5d4..73b789c230a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h | |||
@@ -150,14 +150,6 @@ struct nouveau_pm_threshold_temp { | |||
150 | s16 down_clock; | 150 | s16 down_clock; |
151 | }; | 151 | }; |
152 | 152 | ||
153 | struct nouveau_pm_fan { | ||
154 | u32 percent; | ||
155 | u32 min_duty; | ||
156 | u32 max_duty; | ||
157 | u32 pwm_freq; | ||
158 | u32 pwm_divisor; | ||
159 | }; | ||
160 | |||
161 | struct nouveau_pm { | 153 | struct nouveau_pm { |
162 | struct drm_device *dev; | 154 | struct drm_device *dev; |
163 | 155 | ||
@@ -166,7 +158,6 @@ struct nouveau_pm { | |||
166 | int nr_perflvl; | 158 | int nr_perflvl; |
167 | struct nouveau_pm_temp_sensor_constants sensor_constants; | 159 | struct nouveau_pm_temp_sensor_constants sensor_constants; |
168 | struct nouveau_pm_threshold_temp threshold_temp; | 160 | struct nouveau_pm_threshold_temp threshold_temp; |
169 | struct nouveau_pm_fan fan; | ||
170 | 161 | ||
171 | struct nouveau_pm_profile *profile_ac; | 162 | struct nouveau_pm_profile *profile_ac; |
172 | struct nouveau_pm_profile *profile_dc; | 163 | struct nouveau_pm_profile *profile_dc; |
@@ -185,9 +176,6 @@ struct nouveau_pm { | |||
185 | 176 | ||
186 | int (*voltage_get)(struct drm_device *); | 177 | int (*voltage_get)(struct drm_device *); |
187 | int (*voltage_set)(struct drm_device *, int voltage); | 178 | int (*voltage_set)(struct drm_device *, int voltage); |
188 | int (*pwm_get)(struct drm_device *, int line, u32*, u32*); | ||
189 | int (*pwm_set)(struct drm_device *, int line, u32, u32); | ||
190 | int (*temp_get)(struct drm_device *); | ||
191 | }; | 179 | }; |
192 | 180 | ||
193 | static inline struct nouveau_pm * | 181 | static inline struct nouveau_pm * |
@@ -270,13 +258,6 @@ int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); | |||
270 | void *nvc0_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); | 258 | void *nvc0_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); |
271 | int nvc0_pm_clocks_set(struct drm_device *, void *); | 259 | int nvc0_pm_clocks_set(struct drm_device *, void *); |
272 | 260 | ||
273 | /* nouveau_temp.c */ | ||
274 | void nouveau_temp_init(struct drm_device *dev); | ||
275 | void nouveau_temp_fini(struct drm_device *dev); | ||
276 | void nouveau_temp_safety_checks(struct drm_device *dev); | ||
277 | int nv40_temp_get(struct drm_device *dev); | ||
278 | int nv84_temp_get(struct drm_device *dev); | ||
279 | |||
280 | /* nouveau_mem.c */ | 261 | /* nouveau_mem.c */ |
281 | int nouveau_mem_timing_calc(struct drm_device *, u32 freq, | 262 | int nouveau_mem_timing_calc(struct drm_device *, u32 freq, |
282 | struct nouveau_pm_memtiming *); | 263 | struct nouveau_pm_memtiming *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c deleted file mode 100644 index 6d2b957ca01..00000000000 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ /dev/null | |||
@@ -1,237 +0,0 @@ | |||
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_drm.h" | ||
30 | #include "nouveau_pm.h" | ||
31 | |||
32 | #include <subdev/i2c.h> | ||
33 | #include <subdev/bios/therm.h> | ||
34 | #include <subdev/bios/extdev.h> | ||
35 | |||
36 | static int | ||
37 | nv40_sensor_setup(struct drm_device *dev) | ||
38 | { | ||
39 | struct nouveau_device *device = nouveau_dev(dev); | ||
40 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
41 | |||
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; | ||
47 | } else { | ||
48 | nv_wr32(device, 0x15b0, 0xff); | ||
49 | return nv_rd32(device, 0x15b4) & 0xff; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | int | ||
54 | nv40_temp_get(struct drm_device *dev) | ||
55 | { | ||
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; | ||
60 | int core_temp; | ||
61 | |||
62 | if (nv_device(drm->device)->chipset >= 0x46) { | ||
63 | nv_wr32(device, 0x15b0, 0x80003fff); | ||
64 | core_temp = nv_rd32(device, 0x15b4) & 0x3fff; | ||
65 | } else { | ||
66 | nv_wr32(device, 0x15b0, 0xff); | ||
67 | core_temp = nv_rd32(device, 0x15b4) & 0xff; | ||
68 | } | ||
69 | |||
70 | /* Setup the sensor if the temperature is 0 */ | ||
71 | if (core_temp == 0) | ||
72 | core_temp = nv40_sensor_setup(dev); | ||
73 | |||
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; | ||
80 | |||
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; | ||
84 | |||
85 | return core_temp; | ||
86 | } | ||
87 | |||
88 | int | ||
89 | nv84_temp_get(struct drm_device *dev) | ||
90 | { | ||
91 | struct nouveau_device *device = nouveau_dev(dev); | ||
92 | return nv_rd32(device, 0x20400); | ||
93 | } | ||
94 | |||
95 | void | ||
96 | nouveau_temp_safety_checks(struct drm_device *dev) | ||
97 | { | ||
98 | struct nouveau_pm *pm = nouveau_pm(dev); | ||
99 | struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | ||
100 | |||
101 | if (temps->critical > 120) | ||
102 | temps->critical = 120; | ||
103 | else if (temps->critical < 80) | ||
104 | temps->critical = 80; | ||
105 | |||
106 | if (temps->down_clock > 110) | ||
107 | temps->down_clock = 110; | ||
108 | else if (temps->down_clock < 60) | ||
109 | temps->down_clock = 60; | ||
110 | } | ||
111 | |||
112 | static bool | ||
113 | probe_monitoring_device(struct nouveau_i2c_port *i2c, | ||
114 | struct i2c_board_info *info) | ||
115 | { | ||
116 | struct i2c_client *client; | ||
117 | |||
118 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); | ||
119 | |||
120 | client = i2c_new_device(&i2c->adapter, info); | ||
121 | if (!client) | ||
122 | return false; | ||
123 | |||
124 | if (!client->driver || client->driver->detect(client, info)) { | ||
125 | i2c_unregister_device(client); | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | return true; | ||
130 | } | ||
131 | |||
132 | static void | ||
133 | nouveau_temp_probe_i2c(struct drm_device *dev) | ||
134 | { | ||
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) }, | ||
160 | { } | ||
161 | }; | ||
162 | |||
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) }, | ||
166 | { } | ||
167 | }; | ||
168 | |||
169 | if (i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | ||
170 | board, probe_monitoring_device)) | ||
171 | return; | ||
172 | } | ||
173 | |||
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) }, | ||
177 | { } | ||
178 | }; | ||
179 | |||
180 | if (i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | ||
181 | board, probe_monitoring_device)) | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | /* The vbios doesn't provide the address of an exisiting monitoring | ||
186 | device. Let's try our static list. | ||
187 | */ | ||
188 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, | ||
189 | probe_monitoring_device); | ||
190 | } | ||
191 | |||
192 | void | ||
193 | nouveau_temp_init(struct drm_device *dev) | ||
194 | { | ||
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; | ||
203 | |||
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; | ||
210 | |||
211 | if (!nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, | ||
212 | &bios_sensor)) { | ||
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; | ||
218 | |||
219 | temps->down_clock = bios_sensor.thrs_down_clock.temp; | ||
220 | temps->critical = bios_sensor.thrs_critical.temp; | ||
221 | } | ||
222 | |||
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; | ||
227 | } | ||
228 | |||
229 | nouveau_temp_safety_checks(dev); | ||
230 | nouveau_temp_probe_i2c(dev); | ||
231 | } | ||
232 | |||
233 | void | ||
234 | nouveau_temp_fini(struct drm_device *dev) | ||
235 | { | ||
236 | |||
237 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index 23f200630d8..e9b81a97c48 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c | |||
@@ -351,52 +351,3 @@ resume: | |||
351 | kfree(info); | 351 | kfree(info); |
352 | return ret; | 352 | return ret; |
353 | } | 353 | } |
354 | |||
355 | int | ||
356 | nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | ||
357 | { | ||
358 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
359 | struct nouveau_device *device = nouveau_dev(dev); | ||
360 | |||
361 | if (line == 2) { | ||
362 | u32 reg = nv_rd32(device, 0x0010f0); | ||
363 | if (reg & 0x80000000) { | ||
364 | *duty = (reg & 0x7fff0000) >> 16; | ||
365 | *divs = (reg & 0x00007fff); | ||
366 | return 0; | ||
367 | } | ||
368 | } else | ||
369 | if (line == 9) { | ||
370 | u32 reg = nv_rd32(device, 0x0015f4); | ||
371 | if (reg & 0x80000000) { | ||
372 | *divs = nv_rd32(device, 0x0015f8); | ||
373 | *duty = (reg & 0x7fffffff); | ||
374 | return 0; | ||
375 | } | ||
376 | } else { | ||
377 | NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", line); | ||
378 | return -ENODEV; | ||
379 | } | ||
380 | |||
381 | return -EINVAL; | ||
382 | } | ||
383 | |||
384 | int | ||
385 | nv40_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) | ||
386 | { | ||
387 | struct nouveau_device *device = nouveau_dev(dev); | ||
388 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
389 | |||
390 | if (line == 2) { | ||
391 | nv_wr32(device, 0x0010f0, 0x80000000 | (duty << 16) | divs); | ||
392 | } else | ||
393 | if (line == 9) { | ||
394 | nv_wr32(device, 0x0015f8, divs); | ||
395 | nv_wr32(device, 0x0015f4, duty | 0x80000000); | ||
396 | } else { | ||
397 | NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", line); | ||
398 | return -ENODEV; | ||
399 | } | ||
400 | |||
401 | return 0; | ||
402 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 0036c8c966d..7724eae5db9 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c | |||
@@ -853,61 +853,3 @@ resume: | |||
853 | kfree(info); | 853 | kfree(info); |
854 | return ret; | 854 | return ret; |
855 | } | 855 | } |
856 | |||
857 | static int | ||
858 | pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) | ||
859 | { | ||
860 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
861 | |||
862 | if (*line == 0x04) { | ||
863 | *ctrl = 0x00e100; | ||
864 | *line = 4; | ||
865 | *indx = 0; | ||
866 | } else | ||
867 | if (*line == 0x09) { | ||
868 | *ctrl = 0x00e100; | ||
869 | *line = 9; | ||
870 | *indx = 1; | ||
871 | } else | ||
872 | if (*line == 0x10) { | ||
873 | *ctrl = 0x00e28c; | ||
874 | *line = 0; | ||
875 | *indx = 0; | ||
876 | } else { | ||
877 | NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", *line); | ||
878 | return -ENODEV; | ||
879 | } | ||
880 | |||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | int | ||
885 | nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | ||
886 | { | ||
887 | struct nouveau_device *device = nouveau_dev(dev); | ||
888 | int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); | ||
889 | if (ret) | ||
890 | return ret; | ||
891 | |||
892 | if (nv_rd32(device, ctrl) & (1 << line)) { | ||
893 | *divs = nv_rd32(device, 0x00e114 + (id * 8)); | ||
894 | *duty = nv_rd32(device, 0x00e118 + (id * 8)); | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | return -EINVAL; | ||
899 | } | ||
900 | |||
901 | int | ||
902 | nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) | ||
903 | { | ||
904 | struct nouveau_device *device = nouveau_dev(dev); | ||
905 | int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); | ||
906 | if (ret) | ||
907 | return ret; | ||
908 | |||
909 | nv_mask(device, ctrl, 0x00010001 << line, 0x00000001 << line); | ||
910 | nv_wr32(device, 0x00e114 + (id * 8), divs); | ||
911 | nv_wr32(device, 0x00e118 + (id * 8), duty | 0x80000000); | ||
912 | return 0; | ||
913 | } | ||