diff options
Diffstat (limited to 'drivers/hwmon/applesmc.c')
-rw-r--r-- | drivers/hwmon/applesmc.c | 133 |
1 files changed, 67 insertions, 66 deletions
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 2cde9ecf7731..4d937a18fadb 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #define APPLESMC_MAX_DATA_LENGTH 32 | 54 | #define APPLESMC_MAX_DATA_LENGTH 32 |
55 | 55 | ||
56 | /* wait up to 32 ms for a status change. */ | 56 | /* wait up to 32 ms for a status change. */ |
57 | #define APPLESMC_MIN_WAIT 0x0040 | 57 | #define APPLESMC_MIN_WAIT 0x0010 |
58 | #define APPLESMC_MAX_WAIT 0x8000 | 58 | #define APPLESMC_MAX_WAIT 0x8000 |
59 | 59 | ||
60 | #define APPLESMC_STATUS_MASK 0x0f | 60 | #define APPLESMC_STATUS_MASK 0x0f |
@@ -80,6 +80,8 @@ | |||
80 | #define FANS_MANUAL "FS! " /* r-w ui16 */ | 80 | #define FANS_MANUAL "FS! " /* r-w ui16 */ |
81 | #define FAN_ID_FMT "F%dID" /* r-o char[16] */ | 81 | #define FAN_ID_FMT "F%dID" /* r-o char[16] */ |
82 | 82 | ||
83 | #define TEMP_SENSOR_TYPE "sp78" | ||
84 | |||
83 | /* List of keys used to read/write fan speeds */ | 85 | /* List of keys used to read/write fan speeds */ |
84 | static const char *const fan_speed_fmt[] = { | 86 | static const char *const fan_speed_fmt[] = { |
85 | "F%dAc", /* actual speed */ | 87 | "F%dAc", /* actual speed */ |
@@ -96,10 +98,6 @@ static const char *const fan_speed_fmt[] = { | |||
96 | #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ | 98 | #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ |
97 | #define APPLESMC_INPUT_FLAT 4 | 99 | #define APPLESMC_INPUT_FLAT 4 |
98 | 100 | ||
99 | #define SENSOR_X 0 | ||
100 | #define SENSOR_Y 1 | ||
101 | #define SENSOR_Z 2 | ||
102 | |||
103 | #define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff) | 101 | #define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff) |
104 | #define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16) | 102 | #define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16) |
105 | 103 | ||
@@ -135,11 +133,13 @@ static struct applesmc_registers { | |||
135 | unsigned int temp_count; /* number of temperature registers */ | 133 | unsigned int temp_count; /* number of temperature registers */ |
136 | unsigned int temp_begin; /* temperature lower index bound */ | 134 | unsigned int temp_begin; /* temperature lower index bound */ |
137 | unsigned int temp_end; /* temperature upper index bound */ | 135 | unsigned int temp_end; /* temperature upper index bound */ |
136 | unsigned int index_count; /* size of temperature index array */ | ||
138 | int num_light_sensors; /* number of light sensors */ | 137 | int num_light_sensors; /* number of light sensors */ |
139 | bool has_accelerometer; /* has motion sensor */ | 138 | bool has_accelerometer; /* has motion sensor */ |
140 | bool has_key_backlight; /* has keyboard backlight */ | 139 | bool has_key_backlight; /* has keyboard backlight */ |
141 | bool init_complete; /* true when fully initialized */ | 140 | bool init_complete; /* true when fully initialized */ |
142 | struct applesmc_entry *cache; /* cached key entries */ | 141 | struct applesmc_entry *cache; /* cached key entries */ |
142 | const char **index; /* temperature key index */ | ||
143 | } smcreg = { | 143 | } smcreg = { |
144 | .mutex = __MUTEX_INITIALIZER(smcreg.mutex), | 144 | .mutex = __MUTEX_INITIALIZER(smcreg.mutex), |
145 | }; | 145 | }; |
@@ -432,30 +432,19 @@ static int applesmc_has_key(const char *key, bool *value) | |||
432 | } | 432 | } |
433 | 433 | ||
434 | /* | 434 | /* |
435 | * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). | 435 | * applesmc_read_s16 - Read 16-bit signed big endian register |
436 | */ | 436 | */ |
437 | static int applesmc_read_motion_sensor(int index, s16 *value) | 437 | static int applesmc_read_s16(const char *key, s16 *value) |
438 | { | 438 | { |
439 | u8 buffer[2]; | 439 | u8 buffer[2]; |
440 | int ret; | 440 | int ret; |
441 | 441 | ||
442 | switch (index) { | 442 | ret = applesmc_read_key(key, buffer, 2); |
443 | case SENSOR_X: | 443 | if (ret) |
444 | ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2); | 444 | return ret; |
445 | break; | ||
446 | case SENSOR_Y: | ||
447 | ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2); | ||
448 | break; | ||
449 | case SENSOR_Z: | ||
450 | ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2); | ||
451 | break; | ||
452 | default: | ||
453 | ret = -EINVAL; | ||
454 | } | ||
455 | 445 | ||
456 | *value = ((s16)buffer[0] << 8) | buffer[1]; | 446 | *value = ((s16)buffer[0] << 8) | buffer[1]; |
457 | 447 | return 0; | |
458 | return ret; | ||
459 | } | 448 | } |
460 | 449 | ||
461 | /* | 450 | /* |
@@ -482,6 +471,30 @@ static void applesmc_device_init(void) | |||
482 | pr_warn("failed to init the device\n"); | 471 | pr_warn("failed to init the device\n"); |
483 | } | 472 | } |
484 | 473 | ||
474 | static int applesmc_init_index(struct applesmc_registers *s) | ||
475 | { | ||
476 | const struct applesmc_entry *entry; | ||
477 | unsigned int i; | ||
478 | |||
479 | if (s->index) | ||
480 | return 0; | ||
481 | |||
482 | s->index = kcalloc(s->temp_count, sizeof(s->index[0]), GFP_KERNEL); | ||
483 | if (!s->index) | ||
484 | return -ENOMEM; | ||
485 | |||
486 | for (i = s->temp_begin; i < s->temp_end; i++) { | ||
487 | entry = applesmc_get_entry_by_index(i); | ||
488 | if (IS_ERR(entry)) | ||
489 | continue; | ||
490 | if (strcmp(entry->type, TEMP_SENSOR_TYPE)) | ||
491 | continue; | ||
492 | s->index[s->index_count++] = entry->key; | ||
493 | } | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
485 | /* | 498 | /* |
486 | * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. | 499 | * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. |
487 | */ | 500 | */ |
@@ -517,6 +530,10 @@ static int applesmc_init_smcreg_try(void) | |||
517 | return ret; | 530 | return ret; |
518 | s->temp_count = s->temp_end - s->temp_begin; | 531 | s->temp_count = s->temp_end - s->temp_begin; |
519 | 532 | ||
533 | ret = applesmc_init_index(s); | ||
534 | if (ret) | ||
535 | return ret; | ||
536 | |||
520 | ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); | 537 | ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); |
521 | if (ret) | 538 | if (ret) |
522 | return ret; | 539 | return ret; |
@@ -533,8 +550,8 @@ static int applesmc_init_smcreg_try(void) | |||
533 | s->num_light_sensors = left_light_sensor + right_light_sensor; | 550 | s->num_light_sensors = left_light_sensor + right_light_sensor; |
534 | s->init_complete = true; | 551 | s->init_complete = true; |
535 | 552 | ||
536 | pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n", | 553 | pr_info("key=%d fan=%d temp=%d index=%d acc=%d lux=%d kbd=%d\n", |
537 | s->key_count, s->fan_count, s->temp_count, | 554 | s->key_count, s->fan_count, s->temp_count, s->index_count, |
538 | s->has_accelerometer, | 555 | s->has_accelerometer, |
539 | s->num_light_sensors, | 556 | s->num_light_sensors, |
540 | s->has_key_backlight); | 557 | s->has_key_backlight); |
@@ -542,6 +559,15 @@ static int applesmc_init_smcreg_try(void) | |||
542 | return 0; | 559 | return 0; |
543 | } | 560 | } |
544 | 561 | ||
562 | static void applesmc_destroy_smcreg(void) | ||
563 | { | ||
564 | kfree(smcreg.index); | ||
565 | smcreg.index = NULL; | ||
566 | kfree(smcreg.cache); | ||
567 | smcreg.cache = NULL; | ||
568 | smcreg.init_complete = false; | ||
569 | } | ||
570 | |||
545 | /* | 571 | /* |
546 | * applesmc_init_smcreg - Initialize register cache. | 572 | * applesmc_init_smcreg - Initialize register cache. |
547 | * | 573 | * |
@@ -562,19 +588,11 @@ static int applesmc_init_smcreg(void) | |||
562 | msleep(INIT_WAIT_MSECS); | 588 | msleep(INIT_WAIT_MSECS); |
563 | } | 589 | } |
564 | 590 | ||
565 | kfree(smcreg.cache); | 591 | applesmc_destroy_smcreg(); |
566 | smcreg.cache = NULL; | ||
567 | 592 | ||
568 | return ret; | 593 | return ret; |
569 | } | 594 | } |
570 | 595 | ||
571 | static void applesmc_destroy_smcreg(void) | ||
572 | { | ||
573 | kfree(smcreg.cache); | ||
574 | smcreg.cache = NULL; | ||
575 | smcreg.init_complete = false; | ||
576 | } | ||
577 | |||
578 | /* Device model stuff */ | 596 | /* Device model stuff */ |
579 | static int applesmc_probe(struct platform_device *dev) | 597 | static int applesmc_probe(struct platform_device *dev) |
580 | { | 598 | { |
@@ -624,8 +642,8 @@ static struct platform_driver applesmc_driver = { | |||
624 | */ | 642 | */ |
625 | static void applesmc_calibrate(void) | 643 | static void applesmc_calibrate(void) |
626 | { | 644 | { |
627 | applesmc_read_motion_sensor(SENSOR_X, &rest_x); | 645 | applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x); |
628 | applesmc_read_motion_sensor(SENSOR_Y, &rest_y); | 646 | applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y); |
629 | rest_x = -rest_x; | 647 | rest_x = -rest_x; |
630 | } | 648 | } |
631 | 649 | ||
@@ -634,9 +652,9 @@ static void applesmc_idev_poll(struct input_polled_dev *dev) | |||
634 | struct input_dev *idev = dev->input; | 652 | struct input_dev *idev = dev->input; |
635 | s16 x, y; | 653 | s16 x, y; |
636 | 654 | ||
637 | if (applesmc_read_motion_sensor(SENSOR_X, &x)) | 655 | if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x)) |
638 | return; | 656 | return; |
639 | if (applesmc_read_motion_sensor(SENSOR_Y, &y)) | 657 | if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y)) |
640 | return; | 658 | return; |
641 | 659 | ||
642 | x = -x; | 660 | x = -x; |
@@ -659,13 +677,13 @@ static ssize_t applesmc_position_show(struct device *dev, | |||
659 | int ret; | 677 | int ret; |
660 | s16 x, y, z; | 678 | s16 x, y, z; |
661 | 679 | ||
662 | ret = applesmc_read_motion_sensor(SENSOR_X, &x); | 680 | ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x); |
663 | if (ret) | 681 | if (ret) |
664 | goto out; | 682 | goto out; |
665 | ret = applesmc_read_motion_sensor(SENSOR_Y, &y); | 683 | ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y); |
666 | if (ret) | 684 | if (ret) |
667 | goto out; | 685 | goto out; |
668 | ret = applesmc_read_motion_sensor(SENSOR_Z, &z); | 686 | ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z); |
669 | if (ret) | 687 | if (ret) |
670 | goto out; | 688 | goto out; |
671 | 689 | ||
@@ -718,44 +736,27 @@ out: | |||
718 | static ssize_t applesmc_show_sensor_label(struct device *dev, | 736 | static ssize_t applesmc_show_sensor_label(struct device *dev, |
719 | struct device_attribute *devattr, char *sysfsbuf) | 737 | struct device_attribute *devattr, char *sysfsbuf) |
720 | { | 738 | { |
721 | int index = smcreg.temp_begin + to_index(devattr); | 739 | const char *key = smcreg.index[to_index(devattr)]; |
722 | const struct applesmc_entry *entry; | ||
723 | 740 | ||
724 | entry = applesmc_get_entry_by_index(index); | 741 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key); |
725 | if (IS_ERR(entry)) | ||
726 | return PTR_ERR(entry); | ||
727 | |||
728 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); | ||
729 | } | 742 | } |
730 | 743 | ||
731 | /* Displays degree Celsius * 1000 */ | 744 | /* Displays degree Celsius * 1000 */ |
732 | static ssize_t applesmc_show_temperature(struct device *dev, | 745 | static ssize_t applesmc_show_temperature(struct device *dev, |
733 | struct device_attribute *devattr, char *sysfsbuf) | 746 | struct device_attribute *devattr, char *sysfsbuf) |
734 | { | 747 | { |
735 | int index = smcreg.temp_begin + to_index(devattr); | 748 | const char *key = smcreg.index[to_index(devattr)]; |
736 | const struct applesmc_entry *entry; | ||
737 | int ret; | 749 | int ret; |
738 | u8 buffer[2]; | 750 | s16 value; |
739 | unsigned int temp; | 751 | int temp; |
740 | |||
741 | entry = applesmc_get_entry_by_index(index); | ||
742 | if (IS_ERR(entry)) | ||
743 | return PTR_ERR(entry); | ||
744 | if (entry->len > 2) | ||
745 | return -EINVAL; | ||
746 | 752 | ||
747 | ret = applesmc_read_entry(entry, buffer, entry->len); | 753 | ret = applesmc_read_s16(key, &value); |
748 | if (ret) | 754 | if (ret) |
749 | return ret; | 755 | return ret; |
750 | 756 | ||
751 | if (entry->len == 2) { | 757 | temp = 250 * (value >> 6); |
752 | temp = buffer[0] * 1000; | ||
753 | temp += (buffer[1] >> 6) * 250; | ||
754 | } else { | ||
755 | temp = buffer[0] * 4000; | ||
756 | } | ||
757 | 758 | ||
758 | return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp); | 759 | return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", temp); |
759 | } | 760 | } |
760 | 761 | ||
761 | static ssize_t applesmc_show_fan_speed(struct device *dev, | 762 | static ssize_t applesmc_show_fan_speed(struct device *dev, |
@@ -1265,7 +1266,7 @@ static int __init applesmc_init(void) | |||
1265 | if (ret) | 1266 | if (ret) |
1266 | goto out_info; | 1267 | goto out_info; |
1267 | 1268 | ||
1268 | ret = applesmc_create_nodes(temp_group, smcreg.temp_count); | 1269 | ret = applesmc_create_nodes(temp_group, smcreg.index_count); |
1269 | if (ret) | 1270 | if (ret) |
1270 | goto out_fans; | 1271 | goto out_fans; |
1271 | 1272 | ||