diff options
author | Mark van Doesburg <mark.vandoesburg@hetnet.nl> | 2009-01-07 10:37:27 -0500 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-01-07 10:37:27 -0500 |
commit | 9ab796ebe185257013f0ac505ecbe7abf068a608 (patch) | |
tree | dd9d6ef57ab173538fb7fe3d889fa2f4b4cf7706 | |
parent | 77a4a3e2a36aea5896f86653f6b77168d578c962 (diff) |
hwmon: (f71882fg) Add PWM support
Add PWM (fan speed control) support to the f71882fg driver. Both
manual control and automatic (temperature-based) modes are supported.
Additionally, each mode has a PWM-based and an RPM-based variant. By
default we use the mode set by the BIOS.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Cc: Mark van Doesburg <mark.vandoesburg@hetnet.nl>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r-- | drivers/hwmon/f71882fg.c | 656 |
1 files changed, 655 insertions, 1 deletions
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index c6fa8578bdeb..c04108735f3f 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c | |||
@@ -57,6 +57,8 @@ | |||
57 | #define F71882FG_REG_IN1_HIGH 0x32 | 57 | #define F71882FG_REG_IN1_HIGH 0x32 |
58 | 58 | ||
59 | #define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) | 59 | #define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) |
60 | #define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr))) | ||
61 | #define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr))) | ||
60 | #define F71882FG_REG_FAN_STATUS 0x92 | 62 | #define F71882FG_REG_FAN_STATUS 0x92 |
61 | #define F71882FG_REG_FAN_BEEP 0x93 | 63 | #define F71882FG_REG_FAN_BEEP 0x93 |
62 | 64 | ||
@@ -70,6 +72,17 @@ | |||
70 | #define F71882FG_REG_TEMP_TYPE 0x6B | 72 | #define F71882FG_REG_TEMP_TYPE 0x6B |
71 | #define F71882FG_REG_TEMP_DIODE_OPEN 0x6F | 73 | #define F71882FG_REG_TEMP_DIODE_OPEN 0x6F |
72 | 74 | ||
75 | #define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr))) | ||
76 | #define F71882FG_REG_PWM_TYPE 0x94 | ||
77 | #define F71882FG_REG_PWM_ENABLE 0x96 | ||
78 | |||
79 | #define F71882FG_REG_FAN_HYST0 0x98 | ||
80 | #define F71882FG_REG_FAN_HYST1 0x99 | ||
81 | |||
82 | #define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm))) | ||
83 | #define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm))) | ||
84 | #define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr)) | ||
85 | |||
73 | #define F71882FG_REG_START 0x01 | 86 | #define F71882FG_REG_START 0x01 |
74 | 87 | ||
75 | #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ | 88 | #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ |
@@ -78,6 +91,12 @@ static unsigned short force_id; | |||
78 | module_param(force_id, ushort, 0); | 91 | module_param(force_id, ushort, 0); |
79 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | 92 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); |
80 | 93 | ||
94 | static int fan_mode[4] = { 0, 0, 0, 0 }; | ||
95 | module_param_array(fan_mode, int, NULL, 0644); | ||
96 | MODULE_PARM_DESC(fan_mode, "List of fan control modes (f71882fg only) " | ||
97 | "(0=don't change, 1=pwm, 2=rpm)\n" | ||
98 | "Note: this needs a write to pwm#_enable to take effect"); | ||
99 | |||
81 | static struct platform_device *f71882fg_pdev; | 100 | static struct platform_device *f71882fg_pdev; |
82 | 101 | ||
83 | /* Super-I/O Function prototypes */ | 102 | /* Super-I/O Function prototypes */ |
@@ -102,6 +121,8 @@ struct f71882fg_data { | |||
102 | u8 in_status; | 121 | u8 in_status; |
103 | u8 in_beep; | 122 | u8 in_beep; |
104 | u16 fan[4]; | 123 | u16 fan[4]; |
124 | u16 fan_target[4]; | ||
125 | u16 fan_full_speed[4]; | ||
105 | u8 fan_status; | 126 | u8 fan_status; |
106 | u8 fan_beep; | 127 | u8 fan_beep; |
107 | u8 temp[3]; | 128 | u8 temp[3]; |
@@ -112,6 +133,12 @@ struct f71882fg_data { | |||
112 | u8 temp_status; | 133 | u8 temp_status; |
113 | u8 temp_beep; | 134 | u8 temp_beep; |
114 | u8 temp_diode_open; | 135 | u8 temp_diode_open; |
136 | u8 pwm[4]; | ||
137 | u8 pwm_enable; | ||
138 | u8 pwm_auto_point_hyst[2]; | ||
139 | u8 pwm_auto_point_mapping[4]; | ||
140 | u8 pwm_auto_point_pwm[4][5]; | ||
141 | u8 pwm_auto_point_temp[4][4]; | ||
115 | }; | 142 | }; |
116 | 143 | ||
117 | /* Sysfs in */ | 144 | /* Sysfs in */ |
@@ -130,6 +157,10 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute | |||
130 | /* Sysfs Fan */ | 157 | /* Sysfs Fan */ |
131 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | 158 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, |
132 | char *buf); | 159 | char *buf); |
160 | static ssize_t show_fan_full_speed(struct device *dev, | ||
161 | struct device_attribute *devattr, char *buf); | ||
162 | static ssize_t store_fan_full_speed(struct device *dev, | ||
163 | struct device_attribute *devattr, const char *buf, size_t count); | ||
133 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute | 164 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute |
134 | *devattr, char *buf); | 165 | *devattr, char *buf); |
135 | static ssize_t store_fan_beep(struct device *dev, struct device_attribute | 166 | static ssize_t store_fan_beep(struct device *dev, struct device_attribute |
@@ -163,6 +194,35 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute | |||
163 | *devattr, char *buf); | 194 | *devattr, char *buf); |
164 | static ssize_t show_temp_fault(struct device *dev, struct device_attribute | 195 | static ssize_t show_temp_fault(struct device *dev, struct device_attribute |
165 | *devattr, char *buf); | 196 | *devattr, char *buf); |
197 | /* PWM and Auto point control */ | ||
198 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, | ||
199 | char *buf); | ||
200 | static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr, | ||
201 | const char *buf, size_t count); | ||
202 | static ssize_t show_pwm_enable(struct device *dev, | ||
203 | struct device_attribute *devattr, char *buf); | ||
204 | static ssize_t store_pwm_enable(struct device *dev, | ||
205 | struct device_attribute *devattr, const char *buf, size_t count); | ||
206 | static ssize_t show_pwm_interpolate(struct device *dev, | ||
207 | struct device_attribute *devattr, char *buf); | ||
208 | static ssize_t store_pwm_interpolate(struct device *dev, | ||
209 | struct device_attribute *devattr, const char *buf, size_t count); | ||
210 | static ssize_t show_pwm_auto_point_channel(struct device *dev, | ||
211 | struct device_attribute *devattr, char *buf); | ||
212 | static ssize_t store_pwm_auto_point_channel(struct device *dev, | ||
213 | struct device_attribute *devattr, const char *buf, size_t count); | ||
214 | static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, | ||
215 | struct device_attribute *devattr, char *buf); | ||
216 | static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, | ||
217 | struct device_attribute *devattr, const char *buf, size_t count); | ||
218 | static ssize_t show_pwm_auto_point_pwm(struct device *dev, | ||
219 | struct device_attribute *devattr, char *buf); | ||
220 | static ssize_t store_pwm_auto_point_pwm(struct device *dev, | ||
221 | struct device_attribute *devattr, const char *buf, size_t count); | ||
222 | static ssize_t show_pwm_auto_point_temp(struct device *dev, | ||
223 | struct device_attribute *devattr, char *buf); | ||
224 | static ssize_t store_pwm_auto_point_temp(struct device *dev, | ||
225 | struct device_attribute *devattr, const char *buf, size_t count); | ||
166 | /* Sysfs misc */ | 226 | /* Sysfs misc */ |
167 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, | 227 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, |
168 | char *buf); | 228 | char *buf); |
@@ -249,21 +309,217 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { | |||
249 | 309 | ||
250 | static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { | 310 | static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { |
251 | SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), | 311 | SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), |
312 | SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, | ||
313 | show_fan_full_speed, | ||
314 | store_fan_full_speed, 0, 0), | ||
252 | SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 315 | SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
253 | store_fan_beep, 0, 0), | 316 | store_fan_beep, 0, 0), |
254 | SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), | 317 | SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), |
255 | SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), | 318 | SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), |
319 | SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, | ||
320 | show_fan_full_speed, | ||
321 | store_fan_full_speed, 0, 1), | ||
256 | SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 322 | SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
257 | store_fan_beep, 0, 1), | 323 | store_fan_beep, 0, 1), |
258 | SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), | 324 | SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), |
259 | SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), | 325 | SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), |
326 | SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, | ||
327 | show_fan_full_speed, | ||
328 | store_fan_full_speed, 0, 2), | ||
260 | SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 329 | SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
261 | store_fan_beep, 0, 2), | 330 | store_fan_beep, 0, 2), |
262 | SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), | 331 | SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), |
263 | SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), | 332 | SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), |
333 | SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, | ||
334 | show_fan_full_speed, | ||
335 | store_fan_full_speed, 0, 3), | ||
264 | SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 336 | SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
265 | store_fan_beep, 0, 3), | 337 | store_fan_beep, 0, 3), |
266 | SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), | 338 | SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), |
339 | |||
340 | SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), | ||
341 | SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
342 | store_pwm_enable, 0, 0), | ||
343 | SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR, | ||
344 | show_pwm_interpolate, store_pwm_interpolate, 0, 0), | ||
345 | SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
346 | show_pwm_auto_point_channel, | ||
347 | store_pwm_auto_point_channel, 0, 0), | ||
348 | SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
349 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
350 | 0, 0), | ||
351 | SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
352 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
353 | 1, 0), | ||
354 | SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
355 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
356 | 2, 0), | ||
357 | SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
358 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
359 | 3, 0), | ||
360 | SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
361 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
362 | 4, 0), | ||
363 | SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
364 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
365 | 0, 0), | ||
366 | SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
367 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
368 | 1, 0), | ||
369 | SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
370 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
371 | 2, 0), | ||
372 | SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
373 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
374 | 3, 0), | ||
375 | SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
376 | show_pwm_auto_point_temp_hyst, | ||
377 | store_pwm_auto_point_temp_hyst, | ||
378 | 0, 0), | ||
379 | SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, | ||
380 | show_pwm_auto_point_temp_hyst, NULL, 1, 0), | ||
381 | SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO, | ||
382 | show_pwm_auto_point_temp_hyst, NULL, 2, 0), | ||
383 | SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO, | ||
384 | show_pwm_auto_point_temp_hyst, NULL, 3, 0), | ||
385 | |||
386 | SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1), | ||
387 | SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
388 | store_pwm_enable, 0, 1), | ||
389 | SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR, | ||
390 | show_pwm_interpolate, store_pwm_interpolate, 0, 1), | ||
391 | SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
392 | show_pwm_auto_point_channel, | ||
393 | store_pwm_auto_point_channel, 0, 1), | ||
394 | SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
395 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
396 | 0, 1), | ||
397 | SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
398 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
399 | 1, 1), | ||
400 | SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
401 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
402 | 2, 1), | ||
403 | SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
404 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
405 | 3, 1), | ||
406 | SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
407 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
408 | 4, 1), | ||
409 | SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
410 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
411 | 0, 1), | ||
412 | SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
413 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
414 | 1, 1), | ||
415 | SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
416 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
417 | 2, 1), | ||
418 | SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
419 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
420 | 3, 1), | ||
421 | SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
422 | show_pwm_auto_point_temp_hyst, | ||
423 | store_pwm_auto_point_temp_hyst, | ||
424 | 0, 1), | ||
425 | SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, | ||
426 | show_pwm_auto_point_temp_hyst, NULL, 1, 1), | ||
427 | SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO, | ||
428 | show_pwm_auto_point_temp_hyst, NULL, 2, 1), | ||
429 | SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, | ||
430 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), | ||
431 | |||
432 | SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), | ||
433 | SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
434 | store_pwm_enable, 0, 2), | ||
435 | SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, | ||
436 | show_pwm_interpolate, store_pwm_interpolate, 0, 2), | ||
437 | SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
438 | show_pwm_auto_point_channel, | ||
439 | store_pwm_auto_point_channel, 0, 2), | ||
440 | SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
441 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
442 | 0, 2), | ||
443 | SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
444 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
445 | 1, 2), | ||
446 | SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
447 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
448 | 2, 2), | ||
449 | SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
450 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
451 | 3, 2), | ||
452 | SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
453 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
454 | 4, 2), | ||
455 | SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
456 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
457 | 0, 2), | ||
458 | SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
459 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
460 | 1, 2), | ||
461 | SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
462 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
463 | 2, 2), | ||
464 | SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
465 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
466 | 3, 2), | ||
467 | SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
468 | show_pwm_auto_point_temp_hyst, | ||
469 | store_pwm_auto_point_temp_hyst, | ||
470 | 0, 2), | ||
471 | SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, | ||
472 | show_pwm_auto_point_temp_hyst, NULL, 1, 2), | ||
473 | SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO, | ||
474 | show_pwm_auto_point_temp_hyst, NULL, 2, 2), | ||
475 | SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO, | ||
476 | show_pwm_auto_point_temp_hyst, NULL, 3, 2), | ||
477 | |||
478 | SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3), | ||
479 | SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
480 | store_pwm_enable, 0, 3), | ||
481 | SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR, | ||
482 | show_pwm_interpolate, store_pwm_interpolate, 0, 3), | ||
483 | SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
484 | show_pwm_auto_point_channel, | ||
485 | store_pwm_auto_point_channel, 0, 3), | ||
486 | SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
487 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
488 | 0, 3), | ||
489 | SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
490 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
491 | 1, 3), | ||
492 | SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
493 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
494 | 2, 3), | ||
495 | SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
496 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
497 | 3, 3), | ||
498 | SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
499 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
500 | 4, 3), | ||
501 | SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
502 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
503 | 0, 3), | ||
504 | SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
505 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
506 | 1, 3), | ||
507 | SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
508 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
509 | 2, 3), | ||
510 | SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
511 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
512 | 3, 3), | ||
513 | SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
514 | show_pwm_auto_point_temp_hyst, | ||
515 | store_pwm_auto_point_temp_hyst, | ||
516 | 0, 3), | ||
517 | SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO, | ||
518 | show_pwm_auto_point_temp_hyst, NULL, 1, 3), | ||
519 | SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO, | ||
520 | show_pwm_auto_point_temp_hyst, NULL, 2, 3), | ||
521 | SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO, | ||
522 | show_pwm_auto_point_temp_hyst, NULL, 3, 3), | ||
267 | }; | 523 | }; |
268 | 524 | ||
269 | 525 | ||
@@ -307,6 +563,11 @@ static inline u16 fan_from_reg(u16 reg) | |||
307 | return reg ? (1500000 / reg) : 0; | 563 | return reg ? (1500000 / reg) : 0; |
308 | } | 564 | } |
309 | 565 | ||
566 | static inline u16 fan_to_reg(u16 fan) | ||
567 | { | ||
568 | return fan ? (1500000 / fan) : 0; | ||
569 | } | ||
570 | |||
310 | static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) | 571 | static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) |
311 | { | 572 | { |
312 | u8 val; | 573 | u8 val; |
@@ -335,6 +596,14 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) | |||
335 | outb(val, data->addr + DATA_REG_OFFSET); | 596 | outb(val, data->addr + DATA_REG_OFFSET); |
336 | } | 597 | } |
337 | 598 | ||
599 | static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) | ||
600 | { | ||
601 | outb(reg++, data->addr + ADDR_REG_OFFSET); | ||
602 | outb(val >> 8, data->addr + DATA_REG_OFFSET); | ||
603 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
604 | outb(val & 255, data->addr + DATA_REG_OFFSET); | ||
605 | } | ||
606 | |||
338 | static struct f71882fg_data *f71882fg_update_device(struct device *dev) | 607 | static struct f71882fg_data *f71882fg_update_device(struct device *dev) |
339 | { | 608 | { |
340 | struct f71882fg_data *data = dev_get_drvdata(dev); | 609 | struct f71882fg_data *data = dev_get_drvdata(dev); |
@@ -381,6 +650,32 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
381 | 650 | ||
382 | data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); | 651 | data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); |
383 | 652 | ||
653 | data->pwm_enable = f71882fg_read8(data, | ||
654 | F71882FG_REG_PWM_ENABLE); | ||
655 | data->pwm_auto_point_hyst[0] = f71882fg_read8(data, | ||
656 | F71882FG_REG_FAN_HYST0); | ||
657 | data->pwm_auto_point_hyst[1] = f71882fg_read8(data, | ||
658 | F71882FG_REG_FAN_HYST1); | ||
659 | for (nr = 0; nr < 4; nr++) { | ||
660 | int point; | ||
661 | |||
662 | data->pwm_auto_point_mapping[nr] = | ||
663 | f71882fg_read8(data, | ||
664 | F71882FG_REG_POINT_MAPPING(nr)); | ||
665 | |||
666 | for (point = 0; point < 5; point++) { | ||
667 | data->pwm_auto_point_pwm[nr][point] = | ||
668 | f71882fg_read8(data, | ||
669 | F71882FG_REG_POINT_PWM | ||
670 | (nr, point)); | ||
671 | } | ||
672 | for (point = 0; point < 4; point++) { | ||
673 | data->pwm_auto_point_temp[nr][point] = | ||
674 | f71882fg_read8(data, | ||
675 | F71882FG_REG_POINT_TEMP | ||
676 | (nr, point)); | ||
677 | } | ||
678 | } | ||
384 | data->last_limits = jiffies; | 679 | data->last_limits = jiffies; |
385 | } | 680 | } |
386 | 681 | ||
@@ -396,9 +691,17 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
396 | 691 | ||
397 | data->fan_status = f71882fg_read8(data, | 692 | data->fan_status = f71882fg_read8(data, |
398 | F71882FG_REG_FAN_STATUS); | 693 | F71882FG_REG_FAN_STATUS); |
399 | for (nr = 0; nr < 4; nr++) | 694 | for (nr = 0; nr < 4; nr++) { |
400 | data->fan[nr] = f71882fg_read16(data, | 695 | data->fan[nr] = f71882fg_read16(data, |
401 | F71882FG_REG_FAN(nr)); | 696 | F71882FG_REG_FAN(nr)); |
697 | data->fan_target[nr] = | ||
698 | f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr)); | ||
699 | data->fan_full_speed[nr] = | ||
700 | f71882fg_read16(data, | ||
701 | F71882FG_REG_FAN_FULL_SPEED(nr)); | ||
702 | data->pwm[nr] = | ||
703 | f71882fg_read8(data, F71882FG_REG_PWM(nr)); | ||
704 | } | ||
402 | 705 | ||
403 | data->in_status = f71882fg_read8(data, | 706 | data->in_status = f71882fg_read8(data, |
404 | F71882FG_REG_IN_STATUS); | 707 | F71882FG_REG_IN_STATUS); |
@@ -429,6 +732,40 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | |||
429 | return sprintf(buf, "%d\n", speed); | 732 | return sprintf(buf, "%d\n", speed); |
430 | } | 733 | } |
431 | 734 | ||
735 | static ssize_t show_fan_full_speed(struct device *dev, | ||
736 | struct device_attribute *devattr, char *buf) | ||
737 | { | ||
738 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
739 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
740 | int speed = fan_from_reg(data->fan_full_speed[nr]); | ||
741 | return sprintf(buf, "%d\n", speed); | ||
742 | } | ||
743 | |||
744 | static ssize_t store_fan_full_speed(struct device *dev, | ||
745 | struct device_attribute *devattr, | ||
746 | const char *buf, size_t count) | ||
747 | { | ||
748 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
749 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
750 | long val = simple_strtol(buf, NULL, 10); | ||
751 | |||
752 | val = SENSORS_LIMIT(val, 23, 1500000); | ||
753 | val = fan_to_reg(val); | ||
754 | |||
755 | mutex_lock(&data->update_lock); | ||
756 | if (data->pwm_enable & (1 << (2 * nr))) | ||
757 | /* PWM mode */ | ||
758 | count = -EINVAL; | ||
759 | else { | ||
760 | /* RPM mode */ | ||
761 | f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val); | ||
762 | data->fan_full_speed[nr] = val; | ||
763 | } | ||
764 | mutex_unlock(&data->update_lock); | ||
765 | |||
766 | return count; | ||
767 | } | ||
768 | |||
432 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute | 769 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute |
433 | *devattr, char *buf) | 770 | *devattr, char *buf) |
434 | { | 771 | { |
@@ -736,6 +1073,323 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute | |||
736 | return sprintf(buf, "0\n"); | 1073 | return sprintf(buf, "0\n"); |
737 | } | 1074 | } |
738 | 1075 | ||
1076 | static ssize_t show_pwm(struct device *dev, | ||
1077 | struct device_attribute *devattr, char *buf) | ||
1078 | { | ||
1079 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1080 | int val, nr = to_sensor_dev_attr_2(devattr)->index; | ||
1081 | if (data->pwm_enable & (1 << (2 * nr))) | ||
1082 | /* PWM mode */ | ||
1083 | val = data->pwm[nr]; | ||
1084 | else { | ||
1085 | /* RPM mode */ | ||
1086 | mutex_lock(&data->update_lock); | ||
1087 | val = 255 * fan_from_reg(data->fan_target[nr]) | ||
1088 | / fan_from_reg(data->fan_full_speed[nr]); | ||
1089 | mutex_unlock(&data->update_lock); | ||
1090 | } | ||
1091 | return sprintf(buf, "%d\n", val); | ||
1092 | } | ||
1093 | |||
1094 | static ssize_t store_pwm(struct device *dev, | ||
1095 | struct device_attribute *devattr, const char *buf, | ||
1096 | size_t count) | ||
1097 | { | ||
1098 | /* struct f71882fg_data *data = dev_get_drvdata(dev); */ | ||
1099 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1100 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1101 | long val = simple_strtol(buf, NULL, 10); | ||
1102 | val = SENSORS_LIMIT(val, 0, 255); | ||
1103 | |||
1104 | mutex_lock(&data->update_lock); | ||
1105 | if (data->pwm_enable & (1 << (2 * nr))) { | ||
1106 | /* PWM mode */ | ||
1107 | f71882fg_write8(data, F71882FG_REG_PWM(nr), val); | ||
1108 | data->pwm[nr] = val; | ||
1109 | } else { | ||
1110 | /* RPM mode */ | ||
1111 | int target = val * fan_from_reg(data->fan_full_speed[nr]) / 255; | ||
1112 | f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), | ||
1113 | fan_to_reg(target)); | ||
1114 | data->fan_target[nr] = fan_to_reg(target); | ||
1115 | } | ||
1116 | mutex_unlock(&data->update_lock); | ||
1117 | |||
1118 | return count; | ||
1119 | } | ||
1120 | |||
1121 | static ssize_t show_pwm_enable(struct device *dev, | ||
1122 | struct device_attribute *devattr, char *buf) | ||
1123 | { | ||
1124 | int result; | ||
1125 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1126 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1127 | |||
1128 | if (data->pwm_enable & (2 << (2 * nr))) | ||
1129 | result = 1; | ||
1130 | else | ||
1131 | result = 2; | ||
1132 | |||
1133 | return sprintf(buf, "%d\n", result); | ||
1134 | } | ||
1135 | |||
1136 | static ssize_t store_pwm_enable(struct device *dev, struct device_attribute | ||
1137 | *devattr, const char *buf, size_t count) | ||
1138 | { | ||
1139 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1140 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1141 | long val = simple_strtol(buf, NULL, 10); | ||
1142 | if (val < 1 || val > 2) | ||
1143 | return -EINVAL; | ||
1144 | |||
1145 | mutex_lock(&data->update_lock); | ||
1146 | switch (val) { | ||
1147 | case 1: | ||
1148 | data->pwm_enable |= 2 << (2 * nr); | ||
1149 | break; /* Manual */ | ||
1150 | case 2: | ||
1151 | data->pwm_enable &= ~(2 << (2 * nr)); | ||
1152 | break; /* Temperature ctrl */ | ||
1153 | } | ||
1154 | switch (fan_mode[nr]) { | ||
1155 | case 1: | ||
1156 | data->pwm_enable |= 1 << (2 * nr); | ||
1157 | break; /* Duty cycle mode */ | ||
1158 | case 2: | ||
1159 | data->pwm_enable &= ~(1 << (2 * nr)); | ||
1160 | break; /* RPM mode */ | ||
1161 | } | ||
1162 | f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); | ||
1163 | mutex_unlock(&data->update_lock); | ||
1164 | |||
1165 | return count; | ||
1166 | } | ||
1167 | |||
1168 | static ssize_t show_pwm_auto_point_pwm(struct device *dev, | ||
1169 | struct device_attribute *devattr, | ||
1170 | char *buf) | ||
1171 | { | ||
1172 | int result; | ||
1173 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1174 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1175 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1176 | |||
1177 | if (data->pwm_enable & (1 << (2 * pwm))) { | ||
1178 | /* PWM mode */ | ||
1179 | result = data->pwm_auto_point_pwm[pwm][point]; | ||
1180 | } else { | ||
1181 | /* RPM mode */ | ||
1182 | result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]); | ||
1183 | } | ||
1184 | |||
1185 | return sprintf(buf, "%d\n", result); | ||
1186 | } | ||
1187 | |||
1188 | static ssize_t store_pwm_auto_point_pwm(struct device *dev, | ||
1189 | struct device_attribute *devattr, | ||
1190 | const char *buf, size_t count) | ||
1191 | { | ||
1192 | /* struct f71882fg_data *data = dev_get_drvdata(dev); */ | ||
1193 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1194 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1195 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1196 | int val = simple_strtoul(buf, NULL, 10); | ||
1197 | val = SENSORS_LIMIT(val, 0, 255); | ||
1198 | |||
1199 | mutex_lock(&data->update_lock); | ||
1200 | if (data->pwm_enable & (1 << (2 * pwm))) { | ||
1201 | /* PWM mode */ | ||
1202 | } else { | ||
1203 | /* RPM mode */ | ||
1204 | if (val < 29) /* Prevent negative numbers */ | ||
1205 | val = 255; | ||
1206 | else | ||
1207 | val = (255 - val) * 32 / val; | ||
1208 | } | ||
1209 | f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val); | ||
1210 | data->pwm_auto_point_pwm[pwm][point] = val; | ||
1211 | mutex_unlock(&data->update_lock); | ||
1212 | |||
1213 | return count; | ||
1214 | } | ||
1215 | |||
1216 | static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, | ||
1217 | struct device_attribute *devattr, | ||
1218 | char *buf) | ||
1219 | { | ||
1220 | int result = 0; | ||
1221 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1222 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1223 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1224 | |||
1225 | mutex_lock(&data->update_lock); | ||
1226 | switch (nr) { | ||
1227 | case 0: | ||
1228 | result = data->pwm_auto_point_hyst[0] & 0x0f; | ||
1229 | break; | ||
1230 | case 1: | ||
1231 | result = data->pwm_auto_point_hyst[0] >> 4; | ||
1232 | break; | ||
1233 | case 2: | ||
1234 | result = data->pwm_auto_point_hyst[1] & 0x0f; | ||
1235 | break; | ||
1236 | case 3: | ||
1237 | result = data->pwm_auto_point_hyst[1] >> 4; | ||
1238 | break; | ||
1239 | } | ||
1240 | result = 1000 * (data->pwm_auto_point_temp[nr][point] - result); | ||
1241 | mutex_unlock(&data->update_lock); | ||
1242 | |||
1243 | return sprintf(buf, "%d\n", result); | ||
1244 | } | ||
1245 | |||
1246 | static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, | ||
1247 | struct device_attribute *devattr, | ||
1248 | const char *buf, size_t count) | ||
1249 | { | ||
1250 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1251 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1252 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1253 | long val = simple_strtol(buf, NULL, 10) / 1000; | ||
1254 | |||
1255 | mutex_lock(&data->update_lock); | ||
1256 | val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15, | ||
1257 | data->pwm_auto_point_temp[nr][point]); | ||
1258 | val = data->pwm_auto_point_temp[nr][point] - val; | ||
1259 | |||
1260 | switch (nr) { | ||
1261 | case 0: | ||
1262 | val = (data->pwm_auto_point_hyst[0] & 0xf0) | val; | ||
1263 | break; | ||
1264 | case 1: | ||
1265 | val = (data->pwm_auto_point_hyst[0] & 0x0f) | (val << 4); | ||
1266 | break; | ||
1267 | case 2: | ||
1268 | val = (data->pwm_auto_point_hyst[1] & 0xf0) | val; | ||
1269 | break; | ||
1270 | case 3: | ||
1271 | val = (data->pwm_auto_point_hyst[1] & 0x0f) | (val << 4); | ||
1272 | break; | ||
1273 | } | ||
1274 | if (nr == 0 || nr == 1) { | ||
1275 | f71882fg_write8(data, F71882FG_REG_FAN_HYST0, val); | ||
1276 | data->pwm_auto_point_hyst[0] = val; | ||
1277 | } else { | ||
1278 | f71882fg_write8(data, F71882FG_REG_FAN_HYST1, val); | ||
1279 | data->pwm_auto_point_hyst[1] = val; | ||
1280 | } | ||
1281 | mutex_unlock(&data->update_lock); | ||
1282 | |||
1283 | return count; | ||
1284 | } | ||
1285 | |||
1286 | static ssize_t show_pwm_interpolate(struct device *dev, | ||
1287 | struct device_attribute *devattr, char *buf) | ||
1288 | { | ||
1289 | int result; | ||
1290 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1291 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1292 | |||
1293 | result = (data->pwm_auto_point_mapping[nr] >> 4) & 1; | ||
1294 | |||
1295 | return sprintf(buf, "%d\n", result); | ||
1296 | } | ||
1297 | |||
1298 | static ssize_t store_pwm_interpolate(struct device *dev, | ||
1299 | struct device_attribute *devattr, | ||
1300 | const char *buf, size_t count) | ||
1301 | { | ||
1302 | /* struct f71882fg_data *data = dev_get_drvdata(dev); */ | ||
1303 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1304 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1305 | int val = simple_strtoul(buf, NULL, 10); | ||
1306 | mutex_lock(&data->update_lock); | ||
1307 | if (val) | ||
1308 | val = data->pwm_auto_point_mapping[nr] | (1 << 4); | ||
1309 | else | ||
1310 | val = data->pwm_auto_point_mapping[nr] & (~(1 << 4)); | ||
1311 | f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); | ||
1312 | data->pwm_auto_point_mapping[nr] = val; | ||
1313 | mutex_unlock(&data->update_lock); | ||
1314 | |||
1315 | return count; | ||
1316 | } | ||
1317 | |||
1318 | static ssize_t show_pwm_auto_point_channel(struct device *dev, | ||
1319 | struct device_attribute *devattr, | ||
1320 | char *buf) | ||
1321 | { | ||
1322 | int result; | ||
1323 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1324 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1325 | |||
1326 | result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - 1); | ||
1327 | |||
1328 | return sprintf(buf, "%d\n", result); | ||
1329 | } | ||
1330 | |||
1331 | static ssize_t store_pwm_auto_point_channel(struct device *dev, | ||
1332 | struct device_attribute *devattr, | ||
1333 | const char *buf, size_t count) | ||
1334 | { | ||
1335 | /* struct f71882fg_data *data = dev_get_drvdata(dev); */ | ||
1336 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1337 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1338 | long val = simple_strtol(buf, NULL, 10); | ||
1339 | switch (val) { | ||
1340 | case 1: | ||
1341 | val = 1; | ||
1342 | break; | ||
1343 | case 2: | ||
1344 | val = 2; | ||
1345 | break; | ||
1346 | case 4: | ||
1347 | val = 3; | ||
1348 | break; | ||
1349 | default: | ||
1350 | return -EINVAL; | ||
1351 | } | ||
1352 | mutex_lock(&data->update_lock); | ||
1353 | val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val; | ||
1354 | f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); | ||
1355 | data->pwm_auto_point_mapping[nr] = val; | ||
1356 | mutex_unlock(&data->update_lock); | ||
1357 | |||
1358 | return count; | ||
1359 | } | ||
1360 | |||
1361 | static ssize_t show_pwm_auto_point_temp(struct device *dev, | ||
1362 | struct device_attribute *devattr, | ||
1363 | char *buf) | ||
1364 | { | ||
1365 | int result; | ||
1366 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1367 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1368 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1369 | |||
1370 | result = data->pwm_auto_point_temp[pwm][point]; | ||
1371 | return sprintf(buf, "%d\n", 1000 * result); | ||
1372 | } | ||
1373 | |||
1374 | static ssize_t store_pwm_auto_point_temp(struct device *dev, | ||
1375 | struct device_attribute *devattr, | ||
1376 | const char *buf, size_t count) | ||
1377 | { | ||
1378 | /* struct f71882fg_data *data = dev_get_drvdata(dev); */ | ||
1379 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1380 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1381 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1382 | long val = simple_strtol(buf, NULL, 10) / 1000; | ||
1383 | val = SENSORS_LIMIT(val, 0, 255); | ||
1384 | |||
1385 | mutex_lock(&data->update_lock); | ||
1386 | f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val); | ||
1387 | data->pwm_auto_point_temp[pwm][point] = val; | ||
1388 | mutex_unlock(&data->update_lock); | ||
1389 | |||
1390 | return count; | ||
1391 | } | ||
1392 | |||
739 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, | 1393 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, |
740 | char *buf) | 1394 | char *buf) |
741 | { | 1395 | { |