diff options
author | Pali Rohár <pali.rohar@gmail.com> | 2015-01-12 08:31:57 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-01-25 12:17:58 -0500 |
commit | 5114b474cbb464e7a5da4ba5cdc551e798395151 (patch) | |
tree | f12643266d1524827ccad32a72390e9ae867b249 /drivers/char/i8k.c | |
parent | d9b1652947c695d247b5e4603a16213ec55661ed (diff) |
i8k: Add support for temperature sensor labels
This patch adds labels for temperature sensors if SMM function with EAX register
0x11a3 reports it. This information was taken from DOS binary NBSVC.MDM.
Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Pali Rohár <pali.rohar@gmail.com>
Tested-by: Steven Honeyman <stevenhoneyman@gmail.com>
Tested-by: Gabriele Mazzotta <gabriele.mzt@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/char/i8k.c')
-rw-r--r-- | drivers/char/i8k.c | 74 |
1 files changed, 61 insertions, 13 deletions
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index e34a019eb930..663868b2adc4 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #define I8K_SMM_GET_FAN 0x00a3 | 42 | #define I8K_SMM_GET_FAN 0x00a3 |
43 | #define I8K_SMM_GET_SPEED 0x02a3 | 43 | #define I8K_SMM_GET_SPEED 0x02a3 |
44 | #define I8K_SMM_GET_TEMP 0x10a3 | 44 | #define I8K_SMM_GET_TEMP 0x10a3 |
45 | #define I8K_SMM_GET_TEMP_TYPE 0x11a3 | ||
45 | #define I8K_SMM_GET_DELL_SIG1 0xfea3 | 46 | #define I8K_SMM_GET_DELL_SIG1 0xfea3 |
46 | #define I8K_SMM_GET_DELL_SIG2 0xffa3 | 47 | #define I8K_SMM_GET_DELL_SIG2 0xffa3 |
47 | 48 | ||
@@ -288,6 +289,14 @@ static int i8k_set_fan(int fan, int speed) | |||
288 | return i8k_smm(®s) ? : i8k_get_fan_status(fan); | 289 | return i8k_smm(®s) ? : i8k_get_fan_status(fan); |
289 | } | 290 | } |
290 | 291 | ||
292 | static int i8k_get_temp_type(int sensor) | ||
293 | { | ||
294 | struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP_TYPE, }; | ||
295 | |||
296 | regs.ebx = sensor & 0xff; | ||
297 | return i8k_smm(®s) ? : regs.eax & 0xff; | ||
298 | } | ||
299 | |||
291 | /* | 300 | /* |
292 | * Read the cpu temperature. | 301 | * Read the cpu temperature. |
293 | */ | 302 | */ |
@@ -493,6 +502,29 @@ static int i8k_open_fs(struct inode *inode, struct file *file) | |||
493 | * Hwmon interface | 502 | * Hwmon interface |
494 | */ | 503 | */ |
495 | 504 | ||
505 | static ssize_t i8k_hwmon_show_temp_label(struct device *dev, | ||
506 | struct device_attribute *devattr, | ||
507 | char *buf) | ||
508 | { | ||
509 | static const char * const labels[] = { | ||
510 | "CPU", | ||
511 | "GPU", | ||
512 | "SODIMM", | ||
513 | "Other", | ||
514 | "Ambient", | ||
515 | "Other", | ||
516 | }; | ||
517 | int index = to_sensor_dev_attr(devattr)->index; | ||
518 | int type; | ||
519 | |||
520 | type = i8k_get_temp_type(index); | ||
521 | if (type < 0) | ||
522 | return type; | ||
523 | if (type >= ARRAY_SIZE(labels)) | ||
524 | type = ARRAY_SIZE(labels) - 1; | ||
525 | return sprintf(buf, "%s\n", labels[type]); | ||
526 | } | ||
527 | |||
496 | static ssize_t i8k_hwmon_show_temp(struct device *dev, | 528 | static ssize_t i8k_hwmon_show_temp(struct device *dev, |
497 | struct device_attribute *devattr, | 529 | struct device_attribute *devattr, |
498 | char *buf) | 530 | char *buf) |
@@ -555,9 +587,17 @@ static ssize_t i8k_hwmon_set_pwm(struct device *dev, | |||
555 | } | 587 | } |
556 | 588 | ||
557 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0); | 589 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0); |
590 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, | ||
591 | 0); | ||
558 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1); | 592 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1); |
593 | static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, | ||
594 | 1); | ||
559 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2); | 595 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2); |
596 | static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, | ||
597 | 2); | ||
560 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3); | 598 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3); |
599 | static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, | ||
600 | 3); | ||
561 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, | 601 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, |
562 | I8K_FAN_LEFT); | 602 | I8K_FAN_LEFT); |
563 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, | 603 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, |
@@ -569,31 +609,39 @@ static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, | |||
569 | 609 | ||
570 | static struct attribute *i8k_attrs[] = { | 610 | static struct attribute *i8k_attrs[] = { |
571 | &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ | 611 | &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ |
572 | &sensor_dev_attr_temp2_input.dev_attr.attr, /* 1 */ | 612 | &sensor_dev_attr_temp1_label.dev_attr.attr, /* 1 */ |
573 | &sensor_dev_attr_temp3_input.dev_attr.attr, /* 2 */ | 613 | &sensor_dev_attr_temp2_input.dev_attr.attr, /* 2 */ |
574 | &sensor_dev_attr_temp4_input.dev_attr.attr, /* 3 */ | 614 | &sensor_dev_attr_temp2_label.dev_attr.attr, /* 3 */ |
575 | &sensor_dev_attr_fan1_input.dev_attr.attr, /* 4 */ | 615 | &sensor_dev_attr_temp3_input.dev_attr.attr, /* 4 */ |
576 | &sensor_dev_attr_pwm1.dev_attr.attr, /* 5 */ | 616 | &sensor_dev_attr_temp3_label.dev_attr.attr, /* 5 */ |
577 | &sensor_dev_attr_fan2_input.dev_attr.attr, /* 6 */ | 617 | &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */ |
578 | &sensor_dev_attr_pwm2.dev_attr.attr, /* 7 */ | 618 | &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */ |
619 | &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */ | ||
620 | &sensor_dev_attr_pwm1.dev_attr.attr, /* 9 */ | ||
621 | &sensor_dev_attr_fan2_input.dev_attr.attr, /* 10 */ | ||
622 | &sensor_dev_attr_pwm2.dev_attr.attr, /* 11 */ | ||
579 | NULL | 623 | NULL |
580 | }; | 624 | }; |
581 | 625 | ||
582 | static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, | 626 | static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, |
583 | int index) | 627 | int index) |
584 | { | 628 | { |
585 | if (index == 0 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) | 629 | if (index >= 0 && index <= 1 && |
630 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) | ||
586 | return 0; | 631 | return 0; |
587 | if (index == 1 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2)) | 632 | if (index >= 2 && index <= 3 && |
633 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2)) | ||
588 | return 0; | 634 | return 0; |
589 | if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3)) | 635 | if (index >= 4 && index <= 5 && |
636 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3)) | ||
590 | return 0; | 637 | return 0; |
591 | if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) | 638 | if (index >= 6 && index <= 7 && |
639 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) | ||
592 | return 0; | 640 | return 0; |
593 | if (index >= 4 && index <= 5 && | 641 | if (index >= 8 && index <= 9 && |
594 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1)) | 642 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1)) |
595 | return 0; | 643 | return 0; |
596 | if (index >= 6 && index <= 7 && | 644 | if (index >= 10 && index <= 11 && |
597 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) | 645 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) |
598 | return 0; | 646 | return 0; |
599 | 647 | ||