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 | |
| 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>
22 files changed, 1048 insertions, 542 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 1b05d114deea..15d17e887434 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 c32f96a22704..57899fc3b877 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 000000000000..faee569fd458 --- /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 cac67dc634b7..7bf6f3760b99 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 1c8681f36f1e..5fa58b7369b5 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 c6005c27382e..320ccc4ae05c 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 252e13c3c17a..fec3bcc9a6fc 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 8c14b3849fe3..246bd081a01c 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 0d9d86b8124c..4a280b7ab853 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 000000000000..6502dfb95dd6 --- /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 000000000000..9ad6e166dd75 --- /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 000000000000..e512ff0aae60 --- /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 000000000000..9021b541da8d --- /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 000000000000..f7f51f35d18b --- /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 000000000000..b7207b4524f6 --- /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 000000000000..204282301fb1 --- /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 b5c6a43511d9..a11d2e4f8f6e 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 bdd50953488c..8317e82b86ce 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 2e39ccbd5d46..73b789c230a9 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 6d2b957ca016..000000000000 --- 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 23f200630d8b..e9b81a97c481 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 0036c8c966de..7724eae5db98 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 | } | ||
