diff options
-rw-r--r-- | drivers/char/i8k.c | 76 |
1 files changed, 62 insertions, 14 deletions
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 09ebe06764e3..24cc4ed9a780 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #define I8K_SMM_SET_FAN 0x01a3 | 43 | #define I8K_SMM_SET_FAN 0x01a3 |
44 | #define I8K_SMM_GET_FAN 0x00a3 | 44 | #define I8K_SMM_GET_FAN 0x00a3 |
45 | #define I8K_SMM_GET_SPEED 0x02a3 | 45 | #define I8K_SMM_GET_SPEED 0x02a3 |
46 | #define I8K_SMM_GET_FAN_TYPE 0x03a3 | ||
46 | #define I8K_SMM_GET_NOM_SPEED 0x04a3 | 47 | #define I8K_SMM_GET_NOM_SPEED 0x04a3 |
47 | #define I8K_SMM_GET_TEMP 0x10a3 | 48 | #define I8K_SMM_GET_TEMP 0x10a3 |
48 | #define I8K_SMM_GET_TEMP_TYPE 0x11a3 | 49 | #define I8K_SMM_GET_TEMP_TYPE 0x11a3 |
@@ -279,6 +280,17 @@ static int i8k_get_fan_speed(int fan) | |||
279 | } | 280 | } |
280 | 281 | ||
281 | /* | 282 | /* |
283 | * Read the fan type. | ||
284 | */ | ||
285 | static int i8k_get_fan_type(int fan) | ||
286 | { | ||
287 | struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, }; | ||
288 | |||
289 | regs.ebx = fan & 0xff; | ||
290 | return i8k_smm(®s) ? : regs.eax & 0xff; | ||
291 | } | ||
292 | |||
293 | /* | ||
282 | * Read the fan nominal rpm for specific fan speed. | 294 | * Read the fan nominal rpm for specific fan speed. |
283 | */ | 295 | */ |
284 | static int i8k_get_fan_nominal_speed(int fan, int speed) | 296 | static int i8k_get_fan_nominal_speed(int fan, int speed) |
@@ -553,6 +565,37 @@ static ssize_t i8k_hwmon_show_temp(struct device *dev, | |||
553 | return sprintf(buf, "%d\n", temp * 1000); | 565 | return sprintf(buf, "%d\n", temp * 1000); |
554 | } | 566 | } |
555 | 567 | ||
568 | static ssize_t i8k_hwmon_show_fan_label(struct device *dev, | ||
569 | struct device_attribute *devattr, | ||
570 | char *buf) | ||
571 | { | ||
572 | static const char * const labels[] = { | ||
573 | "Processor Fan", | ||
574 | "Motherboard Fan", | ||
575 | "Video Fan", | ||
576 | "Power Supply Fan", | ||
577 | "Chipset Fan", | ||
578 | "Other Fan", | ||
579 | }; | ||
580 | int index = to_sensor_dev_attr(devattr)->index; | ||
581 | bool dock = false; | ||
582 | int type; | ||
583 | |||
584 | type = i8k_get_fan_type(index); | ||
585 | if (type < 0) | ||
586 | return type; | ||
587 | |||
588 | if (type & 0x10) { | ||
589 | dock = true; | ||
590 | type &= 0x0F; | ||
591 | } | ||
592 | |||
593 | if (type >= ARRAY_SIZE(labels)) | ||
594 | type = (ARRAY_SIZE(labels) - 1); | ||
595 | |||
596 | return sprintf(buf, "%s%s\n", (dock ? "Docking " : ""), labels[type]); | ||
597 | } | ||
598 | |||
556 | static ssize_t i8k_hwmon_show_fan(struct device *dev, | 599 | static ssize_t i8k_hwmon_show_fan(struct device *dev, |
557 | struct device_attribute *devattr, | 600 | struct device_attribute *devattr, |
558 | char *buf) | 601 | char *buf) |
@@ -611,14 +654,17 @@ static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, | |||
611 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3); | 654 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3); |
612 | static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, | 655 | static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, |
613 | 3); | 656 | 3); |
614 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, | 657 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0); |
615 | I8K_FAN_LEFT); | 658 | static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL, |
659 | 0); | ||
616 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, | 660 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, |
617 | i8k_hwmon_set_pwm, I8K_FAN_LEFT); | 661 | i8k_hwmon_set_pwm, 0); |
618 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL, | 662 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL, |
619 | I8K_FAN_RIGHT); | 663 | 1); |
664 | static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL, | ||
665 | 1); | ||
620 | static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, | 666 | static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, |
621 | i8k_hwmon_set_pwm, I8K_FAN_RIGHT); | 667 | i8k_hwmon_set_pwm, 1); |
622 | 668 | ||
623 | static struct attribute *i8k_attrs[] = { | 669 | static struct attribute *i8k_attrs[] = { |
624 | &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ | 670 | &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ |
@@ -630,9 +676,11 @@ static struct attribute *i8k_attrs[] = { | |||
630 | &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */ | 676 | &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */ |
631 | &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */ | 677 | &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */ |
632 | &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */ | 678 | &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */ |
633 | &sensor_dev_attr_pwm1.dev_attr.attr, /* 9 */ | 679 | &sensor_dev_attr_fan1_label.dev_attr.attr, /* 9 */ |
634 | &sensor_dev_attr_fan2_input.dev_attr.attr, /* 10 */ | 680 | &sensor_dev_attr_pwm1.dev_attr.attr, /* 10 */ |
635 | &sensor_dev_attr_pwm2.dev_attr.attr, /* 11 */ | 681 | &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */ |
682 | &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */ | ||
683 | &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */ | ||
636 | NULL | 684 | NULL |
637 | }; | 685 | }; |
638 | 686 | ||
@@ -651,10 +699,10 @@ static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, | |||
651 | if (index >= 6 && index <= 7 && | 699 | if (index >= 6 && index <= 7 && |
652 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) | 700 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) |
653 | return 0; | 701 | return 0; |
654 | if (index >= 8 && index <= 9 && | 702 | if (index >= 8 && index <= 10 && |
655 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1)) | 703 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1)) |
656 | return 0; | 704 | return 0; |
657 | if (index >= 10 && index <= 11 && | 705 | if (index >= 11 && index <= 13 && |
658 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) | 706 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) |
659 | return 0; | 707 | return 0; |
660 | 708 | ||
@@ -688,13 +736,13 @@ static int __init i8k_init_hwmon(void) | |||
688 | if (err >= 0) | 736 | if (err >= 0) |
689 | i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4; | 737 | i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4; |
690 | 738 | ||
691 | /* Left fan attributes, if left fan is present */ | 739 | /* First fan attributes, if fan type is OK */ |
692 | err = i8k_get_fan_status(I8K_FAN_LEFT); | 740 | err = i8k_get_fan_type(0); |
693 | if (err >= 0) | 741 | if (err >= 0) |
694 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1; | 742 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1; |
695 | 743 | ||
696 | /* Right fan attributes, if right fan is present */ | 744 | /* Second fan attributes, if fan type is OK */ |
697 | err = i8k_get_fan_status(I8K_FAN_RIGHT); | 745 | err = i8k_get_fan_type(1); |
698 | if (err >= 0) | 746 | if (err >= 0) |
699 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; | 747 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; |
700 | 748 | ||