aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/thinkpad_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
-rw-r--r--drivers/misc/thinkpad_acpi.c602
1 files changed, 526 insertions, 76 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 95c0b96e83f2..f15a58f7403f 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -21,8 +21,8 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define IBM_VERSION "0.14" 24#define IBM_VERSION "0.15"
25#define TPACPI_SYSFS_VERSION 0x000100 25#define TPACPI_SYSFS_VERSION 0x010000
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -92,6 +92,29 @@ MODULE_LICENSE("GPL");
92/* Please remove this in year 2009 */ 92/* Please remove this in year 2009 */
93MODULE_ALIAS("ibm_acpi"); 93MODULE_ALIAS("ibm_acpi");
94 94
95/*
96 * DMI matching for module autoloading
97 *
98 * See http://thinkwiki.org/wiki/List_of_DMI_IDs
99 * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
100 *
101 * Only models listed in thinkwiki will be supported, so add yours
102 * if it is not there yet.
103 */
104#define IBM_BIOS_MODULE_ALIAS(__type) \
105 MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW")
106
107/* Non-ancient thinkpads */
108MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
109MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
110
111/* Ancient thinkpad BIOSes have to be identified by
112 * BIOS type or model number, and there are far less
113 * BIOS types than model numbers... */
114IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]");
115IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]");
116IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
117
95#define __unused __attribute__ ((unused)) 118#define __unused __attribute__ ((unused))
96 119
97/**************************************************************************** 120/****************************************************************************
@@ -106,7 +129,7 @@ MODULE_ALIAS("ibm_acpi");
106 * ACPI basic handles 129 * ACPI basic handles
107 */ 130 */
108 131
109static acpi_handle root_handle = NULL; 132static acpi_handle root_handle;
110 133
111#define IBM_HANDLE(object, parent, paths...) \ 134#define IBM_HANDLE(object, parent, paths...) \
112 static acpi_handle object##_handle; \ 135 static acpi_handle object##_handle; \
@@ -487,19 +510,36 @@ static char *next_cmd(char **cmds)
487/**************************************************************************** 510/****************************************************************************
488 **************************************************************************** 511 ****************************************************************************
489 * 512 *
490 * Device model: hwmon and platform 513 * Device model: input, hwmon and platform
491 * 514 *
492 **************************************************************************** 515 ****************************************************************************
493 ****************************************************************************/ 516 ****************************************************************************/
494 517
495static struct platform_device *tpacpi_pdev = NULL; 518static struct platform_device *tpacpi_pdev;
496static struct class_device *tpacpi_hwmon = NULL; 519static struct class_device *tpacpi_hwmon;
520static struct input_dev *tpacpi_inputdev;
521
522
523static int tpacpi_resume_handler(struct platform_device *pdev)
524{
525 struct ibm_struct *ibm, *itmp;
526
527 list_for_each_entry_safe(ibm, itmp,
528 &tpacpi_all_drivers,
529 all_drivers) {
530 if (ibm->resume)
531 (ibm->resume)();
532 }
533
534 return 0;
535}
497 536
498static struct platform_driver tpacpi_pdriver = { 537static struct platform_driver tpacpi_pdriver = {
499 .driver = { 538 .driver = {
500 .name = IBM_DRVR_NAME, 539 .name = IBM_DRVR_NAME,
501 .owner = THIS_MODULE, 540 .owner = THIS_MODULE,
502 }, 541 },
542 .resume = tpacpi_resume_handler,
503}; 543};
504 544
505 545
@@ -677,9 +717,19 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
677 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); 717 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
678 printk(IBM_INFO "%s\n", IBM_URL); 718 printk(IBM_INFO "%s\n", IBM_URL);
679 719
680 if (ibm_thinkpad_ec_found) 720 printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n",
681 printk(IBM_INFO "ThinkPad EC firmware %s\n", 721 (thinkpad_id.bios_version_str) ?
682 ibm_thinkpad_ec_found); 722 thinkpad_id.bios_version_str : "unknown",
723 (thinkpad_id.ec_version_str) ?
724 thinkpad_id.ec_version_str : "unknown");
725
726 if (thinkpad_id.vendor && thinkpad_id.model_str)
727 printk(IBM_INFO "%s %s\n",
728 (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ?
729 "IBM" : ((thinkpad_id.vendor ==
730 PCI_VENDOR_ID_LENOVO) ?
731 "Lenovo" : "Unknown vendor"),
732 thinkpad_id.model_str);
683 733
684 return 0; 734 return 0;
685} 735}
@@ -704,16 +754,28 @@ static struct ibm_struct thinkpad_acpi_driver_data = {
704 */ 754 */
705 755
706static int hotkey_orig_status; 756static int hotkey_orig_status;
707static int hotkey_orig_mask; 757static u32 hotkey_orig_mask;
758static u32 hotkey_all_mask;
759static u32 hotkey_reserved_mask;
760
761static u16 *hotkey_keycode_map;
708 762
709static struct attribute_set *hotkey_dev_attributes = NULL; 763static struct attribute_set *hotkey_dev_attributes;
764
765static int hotkey_get_wlsw(int *status)
766{
767 if (!acpi_evalf(hkey_handle, status, "WLSW", "d"))
768 return -EIO;
769 return 0;
770}
710 771
711/* sysfs hotkey enable ------------------------------------------------- */ 772/* sysfs hotkey enable ------------------------------------------------- */
712static ssize_t hotkey_enable_show(struct device *dev, 773static ssize_t hotkey_enable_show(struct device *dev,
713 struct device_attribute *attr, 774 struct device_attribute *attr,
714 char *buf) 775 char *buf)
715{ 776{
716 int res, status, mask; 777 int res, status;
778 u32 mask;
717 779
718 res = hotkey_get(&status, &mask); 780 res = hotkey_get(&status, &mask);
719 if (res) 781 if (res)
@@ -727,7 +789,8 @@ static ssize_t hotkey_enable_store(struct device *dev,
727 const char *buf, size_t count) 789 const char *buf, size_t count)
728{ 790{
729 unsigned long t; 791 unsigned long t;
730 int res, status, mask; 792 int res, status;
793 u32 mask;
731 794
732 if (parse_strtoul(buf, 1, &t)) 795 if (parse_strtoul(buf, 1, &t))
733 return -EINVAL; 796 return -EINVAL;
@@ -748,13 +811,14 @@ static ssize_t hotkey_mask_show(struct device *dev,
748 struct device_attribute *attr, 811 struct device_attribute *attr,
749 char *buf) 812 char *buf)
750{ 813{
751 int res, status, mask; 814 int res, status;
815 u32 mask;
752 816
753 res = hotkey_get(&status, &mask); 817 res = hotkey_get(&status, &mask);
754 if (res) 818 if (res)
755 return res; 819 return res;
756 820
757 return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask); 821 return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask);
758} 822}
759 823
760static ssize_t hotkey_mask_store(struct device *dev, 824static ssize_t hotkey_mask_store(struct device *dev,
@@ -762,9 +826,10 @@ static ssize_t hotkey_mask_store(struct device *dev,
762 const char *buf, size_t count) 826 const char *buf, size_t count)
763{ 827{
764 unsigned long t; 828 unsigned long t;
765 int res, status, mask; 829 int res, status;
830 u32 mask;
766 831
767 if (parse_strtoul(buf, 0xffff, &t)) 832 if (parse_strtoul(buf, 0xffffffffUL, &t))
768 return -EINVAL; 833 return -EINVAL;
769 834
770 res = hotkey_get(&status, &mask); 835 res = hotkey_get(&status, &mask);
@@ -794,26 +859,123 @@ static ssize_t hotkey_bios_mask_show(struct device *dev,
794 struct device_attribute *attr, 859 struct device_attribute *attr,
795 char *buf) 860 char *buf)
796{ 861{
797 return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask); 862 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);
798} 863}
799 864
800static struct device_attribute dev_attr_hotkey_bios_mask = 865static struct device_attribute dev_attr_hotkey_bios_mask =
801 __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); 866 __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
802 867
868/* sysfs hotkey all_mask ----------------------------------------------- */
869static ssize_t hotkey_all_mask_show(struct device *dev,
870 struct device_attribute *attr,
871 char *buf)
872{
873 return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask);
874}
875
876static struct device_attribute dev_attr_hotkey_all_mask =
877 __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL);
878
879/* sysfs hotkey recommended_mask --------------------------------------- */
880static ssize_t hotkey_recommended_mask_show(struct device *dev,
881 struct device_attribute *attr,
882 char *buf)
883{
884 return snprintf(buf, PAGE_SIZE, "0x%08x\n",
885 hotkey_all_mask & ~hotkey_reserved_mask);
886}
887
888static struct device_attribute dev_attr_hotkey_recommended_mask =
889 __ATTR(hotkey_recommended_mask, S_IRUGO,
890 hotkey_recommended_mask_show, NULL);
891
892/* sysfs hotkey radio_sw ----------------------------------------------- */
893static ssize_t hotkey_radio_sw_show(struct device *dev,
894 struct device_attribute *attr,
895 char *buf)
896{
897 int res, s;
898 res = hotkey_get_wlsw(&s);
899 if (res < 0)
900 return res;
901
902 return snprintf(buf, PAGE_SIZE, "%d\n", !!s);
903}
904
905static struct device_attribute dev_attr_hotkey_radio_sw =
906 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
907
803/* --------------------------------------------------------------------- */ 908/* --------------------------------------------------------------------- */
804 909
805static struct attribute *hotkey_mask_attributes[] = { 910static struct attribute *hotkey_mask_attributes[] = {
806 &dev_attr_hotkey_mask.attr, 911 &dev_attr_hotkey_mask.attr,
807 &dev_attr_hotkey_bios_enabled.attr, 912 &dev_attr_hotkey_bios_enabled.attr,
808 &dev_attr_hotkey_bios_mask.attr, 913 &dev_attr_hotkey_bios_mask.attr,
914 &dev_attr_hotkey_all_mask.attr,
915 &dev_attr_hotkey_recommended_mask.attr,
809}; 916};
810 917
811static int __init hotkey_init(struct ibm_init_struct *iibm) 918static int __init hotkey_init(struct ibm_init_struct *iibm)
812{ 919{
813 int res; 920
921 static u16 ibm_keycode_map[] __initdata = {
922 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
923 KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP,
924 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
925 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
926 /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
927 KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
928 KEY_UNKNOWN, /* 0x0D: FN+INSERT */
929 KEY_UNKNOWN, /* 0x0E: FN+DELETE */
930 KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
931 /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
932 KEY_RESERVED, /* 0x10: FN+END (brightness down) */
933 KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
934 KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
935 KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
936 KEY_RESERVED, /* 0x14: VOLUME UP */
937 KEY_RESERVED, /* 0x15: VOLUME DOWN */
938 KEY_RESERVED, /* 0x16: MUTE */
939 KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
940 /* (assignments unknown, please report if found) */
941 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
942 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
943 };
944 static u16 lenovo_keycode_map[] __initdata = {
945 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
946 KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP,
947 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
948 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
949 /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
950 KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
951 KEY_UNKNOWN, /* 0x0D: FN+INSERT */
952 KEY_UNKNOWN, /* 0x0E: FN+DELETE */
953 KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
954 /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
955 KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
956 KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
957 KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
958 KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
959 KEY_RESERVED, /* 0x14: VOLUME UP */
960 KEY_RESERVED, /* 0x15: VOLUME DOWN */
961 KEY_RESERVED, /* 0x16: MUTE */
962 KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
963 /* (assignments unknown, please report if found) */
964 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
965 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
966 };
967
968#define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map)
969#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map)
970#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0])
971
972 int res, i;
973 int status;
814 974
815 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 975 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
816 976
977 BUG_ON(!tpacpi_inputdev);
978
817 IBM_ACPIHANDLE_INIT(hkey); 979 IBM_ACPIHANDLE_INIT(hkey);
818 mutex_init(&hotkey_mutex); 980 mutex_init(&hotkey_mutex);
819 981
@@ -824,7 +986,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
824 str_supported(tp_features.hotkey)); 986 str_supported(tp_features.hotkey));
825 987
826 if (tp_features.hotkey) { 988 if (tp_features.hotkey) {
827 hotkey_dev_attributes = create_attr_set(4, NULL); 989 hotkey_dev_attributes = create_attr_set(7, NULL);
828 if (!hotkey_dev_attributes) 990 if (!hotkey_dev_attributes)
829 return -ENOMEM; 991 return -ENOMEM;
830 res = add_to_attr_set(hotkey_dev_attributes, 992 res = add_to_attr_set(hotkey_dev_attributes,
@@ -840,19 +1002,92 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
840 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", 1002 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
841 str_supported(tp_features.hotkey_mask)); 1003 str_supported(tp_features.hotkey_mask));
842 1004
1005 if (tp_features.hotkey_mask) {
1006 /* MHKA available in A31, R40, R40e, T4x, X31, and later */
1007 if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
1008 "MHKA", "qd"))
1009 hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */
1010 }
1011
843 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); 1012 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
844 if (!res && tp_features.hotkey_mask) { 1013 if (!res && tp_features.hotkey_mask) {
845 res = add_many_to_attr_set(hotkey_dev_attributes, 1014 res = add_many_to_attr_set(hotkey_dev_attributes,
846 hotkey_mask_attributes, 1015 hotkey_mask_attributes,
847 ARRAY_SIZE(hotkey_mask_attributes)); 1016 ARRAY_SIZE(hotkey_mask_attributes));
848 } 1017 }
1018
1019 /* Not all thinkpads have a hardware radio switch */
1020 if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
1021 tp_features.hotkey_wlsw = 1;
1022 printk(IBM_INFO
1023 "radio switch found; radios are %s\n",
1024 enabled(status, 0));
1025 res = add_to_attr_set(hotkey_dev_attributes,
1026 &dev_attr_hotkey_radio_sw.attr);
1027 }
1028
849 if (!res) 1029 if (!res)
850 res = register_attr_set_with_sysfs( 1030 res = register_attr_set_with_sysfs(
851 hotkey_dev_attributes, 1031 hotkey_dev_attributes,
852 &tpacpi_pdev->dev.kobj); 1032 &tpacpi_pdev->dev.kobj);
1033 if (res)
1034 return res;
1035
1036 /* Set up key map */
1037
1038 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
1039 GFP_KERNEL);
1040 if (!hotkey_keycode_map) {
1041 printk(IBM_ERR "failed to allocate memory for key map\n");
1042 return -ENOMEM;
1043 }
1044
1045 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
1046 dbg_printk(TPACPI_DBG_INIT,
1047 "using Lenovo default hot key map\n");
1048 memcpy(hotkey_keycode_map, &lenovo_keycode_map,
1049 TPACPI_HOTKEY_MAP_SIZE);
1050 } else {
1051 dbg_printk(TPACPI_DBG_INIT,
1052 "using IBM default hot key map\n");
1053 memcpy(hotkey_keycode_map, &ibm_keycode_map,
1054 TPACPI_HOTKEY_MAP_SIZE);
1055 }
853 1056
1057#ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED
1058 for (i = 0; i < 12; i++)
1059 hotkey_keycode_map[i] = KEY_UNKNOWN;
1060#endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */
1061
1062 set_bit(EV_KEY, tpacpi_inputdev->evbit);
1063 set_bit(EV_MSC, tpacpi_inputdev->evbit);
1064 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
1065 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
1066 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
1067 tpacpi_inputdev->keycode = hotkey_keycode_map;
1068 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
1069 if (hotkey_keycode_map[i] != KEY_RESERVED) {
1070 set_bit(hotkey_keycode_map[i],
1071 tpacpi_inputdev->keybit);
1072 } else {
1073 if (i < sizeof(hotkey_reserved_mask)*8)
1074 hotkey_reserved_mask |= 1 << i;
1075 }
1076 }
1077
1078 if (tp_features.hotkey_wlsw) {
1079 set_bit(EV_SW, tpacpi_inputdev->evbit);
1080 set_bit(SW_RADIO, tpacpi_inputdev->swbit);
1081 }
1082
1083#ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED
1084 dbg_printk(TPACPI_DBG_INIT,
1085 "enabling hot key handling\n");
1086 res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
1087 | hotkey_orig_mask);
854 if (res) 1088 if (res)
855 return res; 1089 return res;
1090#endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */
856 } 1091 }
857 1092
858 return (tp_features.hotkey)? 0 : 1; 1093 return (tp_features.hotkey)? 0 : 1;
@@ -875,22 +1110,101 @@ static void hotkey_exit(void)
875 } 1110 }
876} 1111}
877 1112
1113static void tpacpi_input_send_key(unsigned int scancode,
1114 unsigned int keycode)
1115{
1116 if (keycode != KEY_RESERVED) {
1117 input_report_key(tpacpi_inputdev, keycode, 1);
1118 if (keycode == KEY_UNKNOWN)
1119 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1120 scancode);
1121 input_sync(tpacpi_inputdev);
1122
1123 input_report_key(tpacpi_inputdev, keycode, 0);
1124 if (keycode == KEY_UNKNOWN)
1125 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1126 scancode);
1127 input_sync(tpacpi_inputdev);
1128 }
1129}
1130
1131static void tpacpi_input_send_radiosw(void)
1132{
1133 int wlsw;
1134
1135 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw))
1136 input_report_switch(tpacpi_inputdev,
1137 SW_RADIO, !!wlsw);
1138}
1139
878static void hotkey_notify(struct ibm_struct *ibm, u32 event) 1140static void hotkey_notify(struct ibm_struct *ibm, u32 event)
879{ 1141{
880 int hkey; 1142 u32 hkey;
1143 unsigned int keycode, scancode;
1144 int sendacpi = 1;
1145
1146 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
1147 if (tpacpi_inputdev->users > 0) {
1148 switch (hkey >> 12) {
1149 case 1:
1150 /* 0x1000-0x1FFF: key presses */
1151 scancode = hkey & 0xfff;
1152 if (scancode > 0 && scancode < 0x21) {
1153 scancode--;
1154 keycode = hotkey_keycode_map[scancode];
1155 tpacpi_input_send_key(scancode, keycode);
1156 sendacpi = (keycode == KEY_RESERVED
1157 || keycode == KEY_UNKNOWN);
1158 } else {
1159 printk(IBM_ERR
1160 "hotkey 0x%04x out of range for keyboard map\n",
1161 hkey);
1162 }
1163 break;
1164 case 5:
1165 /* 0x5000-0x5FFF: LID */
1166 /* we don't handle it through this path, just
1167 * eat up known LID events */
1168 if (hkey != 0x5001 && hkey != 0x5002) {
1169 printk(IBM_ERR
1170 "unknown LID-related hotkey event: 0x%04x\n",
1171 hkey);
1172 }
1173 break;
1174 case 7:
1175 /* 0x7000-0x7FFF: misc */
1176 if (tp_features.hotkey_wlsw && hkey == 0x7000) {
1177 tpacpi_input_send_radiosw();
1178 sendacpi = 0;
1179 break;
1180 }
1181 /* fallthrough to default */
1182 default:
1183 /* case 2: dock-related */
1184 /* 0x2305 - T43 waking up due to bay lever eject while aslept */
1185 /* case 3: ultra-bay related. maybe bay in dock? */
1186 /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */
1187 printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey);
1188 }
1189 }
881 1190
882 if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) 1191 if (sendacpi)
883 acpi_bus_generate_event(ibm->acpi->device, event, hkey); 1192 acpi_bus_generate_event(ibm->acpi->device, event, hkey);
884 else { 1193 } else {
885 printk(IBM_ERR "unknown hotkey event %d\n", event); 1194 printk(IBM_ERR "unknown hotkey notification event %d\n", event);
886 acpi_bus_generate_event(ibm->acpi->device, event, 0); 1195 acpi_bus_generate_event(ibm->acpi->device, event, 0);
887 } 1196 }
888} 1197}
889 1198
1199static void hotkey_resume(void)
1200{
1201 tpacpi_input_send_radiosw();
1202}
1203
890/* 1204/*
891 * Call with hotkey_mutex held 1205 * Call with hotkey_mutex held
892 */ 1206 */
893static int hotkey_get(int *status, int *mask) 1207static int hotkey_get(int *status, u32 *mask)
894{ 1208{
895 if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) 1209 if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
896 return -EIO; 1210 return -EIO;
@@ -905,7 +1219,7 @@ static int hotkey_get(int *status, int *mask)
905/* 1219/*
906 * Call with hotkey_mutex held 1220 * Call with hotkey_mutex held
907 */ 1221 */
908static int hotkey_set(int status, int mask) 1222static int hotkey_set(int status, u32 mask)
909{ 1223{
910 int i; 1224 int i;
911 1225
@@ -926,7 +1240,8 @@ static int hotkey_set(int status, int mask)
926/* procfs -------------------------------------------------------------- */ 1240/* procfs -------------------------------------------------------------- */
927static int hotkey_read(char *p) 1241static int hotkey_read(char *p)
928{ 1242{
929 int res, status, mask; 1243 int res, status;
1244 u32 mask;
930 int len = 0; 1245 int len = 0;
931 1246
932 if (!tp_features.hotkey) { 1247 if (!tp_features.hotkey) {
@@ -944,7 +1259,7 @@ static int hotkey_read(char *p)
944 1259
945 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); 1260 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
946 if (tp_features.hotkey_mask) { 1261 if (tp_features.hotkey_mask) {
947 len += sprintf(p + len, "mask:\t\t0x%04x\n", mask); 1262 len += sprintf(p + len, "mask:\t\t0x%08x\n", mask);
948 len += sprintf(p + len, 1263 len += sprintf(p + len,
949 "commands:\tenable, disable, reset, <mask>\n"); 1264 "commands:\tenable, disable, reset, <mask>\n");
950 } else { 1265 } else {
@@ -957,7 +1272,8 @@ static int hotkey_read(char *p)
957 1272
958static int hotkey_write(char *buf) 1273static int hotkey_write(char *buf)
959{ 1274{
960 int res, status, mask; 1275 int res, status;
1276 u32 mask;
961 char *cmd; 1277 char *cmd;
962 int do_cmd = 0; 1278 int do_cmd = 0;
963 1279
@@ -1012,6 +1328,7 @@ static struct ibm_struct hotkey_driver_data = {
1012 .read = hotkey_read, 1328 .read = hotkey_read,
1013 .write = hotkey_write, 1329 .write = hotkey_write,
1014 .exit = hotkey_exit, 1330 .exit = hotkey_exit,
1331 .resume = hotkey_resume,
1015 .acpi = &ibm_hotkey_acpidriver, 1332 .acpi = &ibm_hotkey_acpidriver,
1016}; 1333};
1017 1334
@@ -1770,7 +2087,10 @@ static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
1770 .type = ACPI_SYSTEM_NOTIFY, 2087 .type = ACPI_SYSTEM_NOTIFY,
1771 }, 2088 },
1772 { 2089 {
1773 .hid = IBM_PCI_HID, 2090 /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING.
2091 * We just use it to get notifications of dock hotplug
2092 * in very old thinkpads */
2093 .hid = PCI_ROOT_HID_STRING,
1774 .notify = dock_notify, 2094 .notify = dock_notify,
1775 .handle = &pci_handle, 2095 .handle = &pci_handle,
1776 .type = ACPI_SYSTEM_NOTIFY, 2096 .type = ACPI_SYSTEM_NOTIFY,
@@ -1829,7 +2149,7 @@ static int __init dock_init2(struct ibm_init_struct *iibm)
1829static void dock_notify(struct ibm_struct *ibm, u32 event) 2149static void dock_notify(struct ibm_struct *ibm, u32 event)
1830{ 2150{
1831 int docked = dock_docked(); 2151 int docked = dock_docked();
1832 int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, IBM_PCI_HID); 2152 int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, PCI_ROOT_HID_STRING);
1833 2153
1834 if (event == 1 && !pci) /* 570 */ 2154 if (event == 1 && !pci) /* 570 */
1835 acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ 2155 acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */
@@ -2389,7 +2709,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
2389 2709
2390 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); 2710 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
2391 2711
2392 if (ibm_thinkpad_ec_found && experimental) { 2712 if (thinkpad_id.ec_model) {
2393 /* 2713 /*
2394 * Direct EC access mode: sensors at registers 2714 * Direct EC access mode: sensors at registers
2395 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for 2715 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
@@ -2533,6 +2853,8 @@ static int thermal_get_sensor(int idx, s32 *value)
2533 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); 2853 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx);
2534 if (!acpi_evalf(ec_handle, &t, tmpi, "d")) 2854 if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
2535 return -EIO; 2855 return -EIO;
2856 if (t > 127 || t < -127)
2857 t = TP_EC_THERMAL_TMP_NA;
2536 *value = t * 1000; 2858 *value = t * 1000;
2537 return 0; 2859 return 0;
2538 } 2860 }
@@ -2671,22 +2993,39 @@ static struct ibm_struct ecdump_driver_data = {
2671 * Backlight/brightness subdriver 2993 * Backlight/brightness subdriver
2672 */ 2994 */
2673 2995
2674static struct backlight_device *ibm_backlight_device = NULL; 2996static struct backlight_device *ibm_backlight_device;
2675 2997
2676static struct backlight_ops ibm_backlight_data = { 2998static struct backlight_ops ibm_backlight_data = {
2677 .get_brightness = brightness_get, 2999 .get_brightness = brightness_get,
2678 .update_status = brightness_update_status, 3000 .update_status = brightness_update_status,
2679}; 3001};
2680 3002
3003static struct mutex brightness_mutex;
3004
2681static int __init brightness_init(struct ibm_init_struct *iibm) 3005static int __init brightness_init(struct ibm_init_struct *iibm)
2682{ 3006{
2683 int b; 3007 int b;
2684 3008
2685 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); 3009 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
2686 3010
3011 mutex_init(&brightness_mutex);
3012
3013 if (!brightness_mode) {
3014 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO)
3015 brightness_mode = 2;
3016 else
3017 brightness_mode = 3;
3018
3019 dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n",
3020 brightness_mode);
3021 }
3022
3023 if (brightness_mode > 3)
3024 return -EINVAL;
3025
2687 b = brightness_get(NULL); 3026 b = brightness_get(NULL);
2688 if (b < 0) 3027 if (b < 0)
2689 return b; 3028 return 1;
2690 3029
2691 ibm_backlight_device = backlight_device_register( 3030 ibm_backlight_device = backlight_device_register(
2692 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, 3031 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
@@ -2722,34 +3061,79 @@ static int brightness_update_status(struct backlight_device *bd)
2722 bd->props.brightness : 0); 3061 bd->props.brightness : 0);
2723} 3062}
2724 3063
3064/*
3065 * ThinkPads can read brightness from two places: EC 0x31, or
3066 * CMOS NVRAM byte 0x5E, bits 0-3.
3067 */
2725static int brightness_get(struct backlight_device *bd) 3068static int brightness_get(struct backlight_device *bd)
2726{ 3069{
2727 u8 level; 3070 u8 lec = 0, lcmos = 0, level = 0;
2728 if (!acpi_ec_read(brightness_offset, &level))
2729 return -EIO;
2730 3071
2731 level &= 0x7; 3072 if (brightness_mode & 1) {
3073 if (!acpi_ec_read(brightness_offset, &lec))
3074 return -EIO;
3075 lec &= 7;
3076 level = lec;
3077 };
3078 if (brightness_mode & 2) {
3079 lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
3080 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
3081 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
3082 level = lcmos;
3083 }
3084
3085 if (brightness_mode == 3 && lec != lcmos) {
3086 printk(IBM_ERR
3087 "CMOS NVRAM (%u) and EC (%u) do not agree "
3088 "on display brightness level\n",
3089 (unsigned int) lcmos,
3090 (unsigned int) lec);
3091 return -EIO;
3092 }
2732 3093
2733 return level; 3094 return level;
2734} 3095}
2735 3096
2736static int brightness_set(int value) 3097static int brightness_set(int value)
2737{ 3098{
2738 int cmos_cmd, inc, i; 3099 int cmos_cmd, inc, i, res;
2739 int current_value = brightness_get(NULL); 3100 int current_value;
3101
3102 if (value > 7)
3103 return -EINVAL;
2740 3104
2741 value &= 7; 3105 res = mutex_lock_interruptible(&brightness_mutex);
3106 if (res < 0)
3107 return res;
3108
3109 current_value = brightness_get(NULL);
3110 if (current_value < 0) {
3111 res = current_value;
3112 goto errout;
3113 }
2742 3114
2743 cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; 3115 cmos_cmd = value > current_value ?
3116 TP_CMOS_BRIGHTNESS_UP :
3117 TP_CMOS_BRIGHTNESS_DOWN;
2744 inc = value > current_value ? 1 : -1; 3118 inc = value > current_value ? 1 : -1;
3119
3120 res = 0;
2745 for (i = current_value; i != value; i += inc) { 3121 for (i = current_value; i != value; i += inc) {
2746 if (issue_thinkpad_cmos_command(cmos_cmd)) 3122 if ((brightness_mode & 2) &&
2747 return -EIO; 3123 issue_thinkpad_cmos_command(cmos_cmd)) {
2748 if (!acpi_ec_write(brightness_offset, i + inc)) 3124 res = -EIO;
2749 return -EIO; 3125 goto errout;
3126 }
3127 if ((brightness_mode & 1) &&
3128 !acpi_ec_write(brightness_offset, i + inc)) {
3129 res = -EIO;
3130 goto errout;;
3131 }
2750 } 3132 }
2751 3133
2752 return 0; 3134errout:
3135 mutex_unlock(&brightness_mutex);
3136 return res;
2753} 3137}
2754 3138
2755static int brightness_read(char *p) 3139static int brightness_read(char *p)
@@ -3273,20 +3657,19 @@ static int __init fan_init(struct ibm_init_struct *iibm)
3273 * Enable for TP-1Y (T43), TP-78 (R51e), 3657 * Enable for TP-1Y (T43), TP-78 (R51e),
3274 * TP-76 (R52), TP-70 (T43, R52), which are known 3658 * TP-76 (R52), TP-70 (T43, R52), which are known
3275 * to be buggy. */ 3659 * to be buggy. */
3276 if (fan_control_initial_status == 0x07 && 3660 if (fan_control_initial_status == 0x07) {
3277 ibm_thinkpad_ec_found && 3661 switch (thinkpad_id.ec_model) {
3278 ((ibm_thinkpad_ec_found[0] == '1' && 3662 case 0x5931: /* TP-1Y */
3279 ibm_thinkpad_ec_found[1] == 'Y') || 3663 case 0x3837: /* TP-78 */
3280 (ibm_thinkpad_ec_found[0] == '7' && 3664 case 0x3637: /* TP-76 */
3281 (ibm_thinkpad_ec_found[1] == '6' || 3665 case 0x3037: /* TP-70 */
3282 ibm_thinkpad_ec_found[1] == '8' || 3666 printk(IBM_NOTICE
3283 ibm_thinkpad_ec_found[1] == '0')) 3667 "fan_init: initial fan status is "
3284 )) { 3668 "unknown, assuming it is in auto "
3285 printk(IBM_NOTICE 3669 "mode\n");
3286 "fan_init: initial fan status is " 3670 tp_features.fan_ctrl_status_undef = 1;
3287 "unknown, assuming it is in auto " 3671 ;;
3288 "mode\n"); 3672 }
3289 tp_features.fan_ctrl_status_undef = 1;
3290 } 3673 }
3291 } else { 3674 } else {
3292 printk(IBM_ERR 3675 printk(IBM_ERR
@@ -3474,7 +3857,7 @@ static void fan_watchdog_fire(struct work_struct *ignored)
3474 3857
3475static void fan_watchdog_reset(void) 3858static void fan_watchdog_reset(void)
3476{ 3859{
3477 static int fan_watchdog_active = 0; 3860 static int fan_watchdog_active;
3478 3861
3479 if (fan_control_access_mode == TPACPI_FAN_WR_NONE) 3862 if (fan_control_access_mode == TPACPI_FAN_WR_NONE)
3480 return; 3863 return;
@@ -3877,7 +4260,7 @@ static struct ibm_struct fan_driver_data = {
3877 ****************************************************************************/ 4260 ****************************************************************************/
3878 4261
3879/* /proc support */ 4262/* /proc support */
3880static struct proc_dir_entry *proc_dir = NULL; 4263static struct proc_dir_entry *proc_dir;
3881 4264
3882/* Subdriver registry */ 4265/* Subdriver registry */
3883static LIST_HEAD(tpacpi_all_drivers); 4266static LIST_HEAD(tpacpi_all_drivers);
@@ -4020,13 +4403,30 @@ static void ibm_exit(struct ibm_struct *ibm)
4020 4403
4021/* Probing */ 4404/* Probing */
4022 4405
4023static char *ibm_thinkpad_ec_found = NULL; 4406static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
4024
4025static char* __init check_dmi_for_ec(void)
4026{ 4407{
4027 struct dmi_device *dev = NULL; 4408 struct dmi_device *dev = NULL;
4028 char ec_fw_string[18]; 4409 char ec_fw_string[18];
4029 4410
4411 if (!tp)
4412 return;
4413
4414 memset(tp, 0, sizeof(*tp));
4415
4416 if (dmi_name_in_vendors("IBM"))
4417 tp->vendor = PCI_VENDOR_ID_IBM;
4418 else if (dmi_name_in_vendors("LENOVO"))
4419 tp->vendor = PCI_VENDOR_ID_LENOVO;
4420 else
4421 return;
4422
4423 tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION),
4424 GFP_KERNEL);
4425 if (!tp->bios_version_str)
4426 return;
4427 tp->bios_model = tp->bios_version_str[0]
4428 | (tp->bios_version_str[1] << 8);
4429
4030 /* 4430 /*
4031 * ThinkPad T23 or newer, A31 or newer, R50e or newer, 4431 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
4032 * X32 or newer, all Z series; Some models must have an 4432 * X32 or newer, all Z series; Some models must have an
@@ -4040,10 +4440,20 @@ static char* __init check_dmi_for_ec(void)
4040 ec_fw_string) == 1) { 4440 ec_fw_string) == 1) {
4041 ec_fw_string[sizeof(ec_fw_string) - 1] = 0; 4441 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
4042 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; 4442 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
4043 return kstrdup(ec_fw_string, GFP_KERNEL); 4443
4444 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
4445 tp->ec_model = ec_fw_string[0]
4446 | (ec_fw_string[1] << 8);
4447 break;
4044 } 4448 }
4045 } 4449 }
4046 return NULL; 4450
4451 tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
4452 GFP_KERNEL);
4453 if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
4454 kfree(tp->model_str);
4455 tp->model_str = NULL;
4456 }
4047} 4457}
4048 4458
4049static int __init probe_for_thinkpad(void) 4459static int __init probe_for_thinkpad(void)
@@ -4057,7 +4467,7 @@ static int __init probe_for_thinkpad(void)
4057 * Non-ancient models have better DMI tagging, but very old models 4467 * Non-ancient models have better DMI tagging, but very old models
4058 * don't. 4468 * don't.
4059 */ 4469 */
4060 is_thinkpad = dmi_name_in_vendors("ThinkPad"); 4470 is_thinkpad = (thinkpad_id.model_str != NULL);
4061 4471
4062 /* ec is required because many other handles are relative to it */ 4472 /* ec is required because many other handles are relative to it */
4063 IBM_ACPIHANDLE_INIT(ec); 4473 IBM_ACPIHANDLE_INIT(ec);
@@ -4073,7 +4483,7 @@ static int __init probe_for_thinkpad(void)
4073 * false positives a damn great deal 4483 * false positives a damn great deal
4074 */ 4484 */
4075 if (!is_thinkpad) 4485 if (!is_thinkpad)
4076 is_thinkpad = dmi_name_in_vendors("IBM"); 4486 is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM);
4077 4487
4078 if (!is_thinkpad && !force_load) 4488 if (!is_thinkpad && !force_load)
4079 return -ENODEV; 4489 return -ENODEV;
@@ -4185,10 +4595,13 @@ static u32 dbg_level;
4185module_param_named(debug, dbg_level, uint, 0); 4595module_param_named(debug, dbg_level, uint, 0);
4186 4596
4187static int force_load; 4597static int force_load;
4188module_param(force_load, int, 0); 4598module_param(force_load, bool, 0);
4189 4599
4190static int fan_control_allowed; 4600static int fan_control_allowed;
4191module_param_named(fan_control, fan_control_allowed, int, 0); 4601module_param_named(fan_control, fan_control_allowed, bool, 0);
4602
4603static int brightness_mode;
4604module_param_named(brightness_mode, brightness_mode, int, 0);
4192 4605
4193#define IBM_PARAM(feature) \ 4606#define IBM_PARAM(feature) \
4194 module_param_call(feature, set_ibm_param, NULL, NULL, 0) 4607 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
@@ -4216,12 +4629,16 @@ static int __init thinkpad_acpi_module_init(void)
4216 int ret, i; 4629 int ret, i;
4217 4630
4218 /* Driver-level probe */ 4631 /* Driver-level probe */
4632
4633 get_thinkpad_model_data(&thinkpad_id);
4219 ret = probe_for_thinkpad(); 4634 ret = probe_for_thinkpad();
4220 if (ret) 4635 if (ret) {
4636 thinkpad_acpi_module_exit();
4221 return ret; 4637 return ret;
4638 }
4222 4639
4223 /* Driver initialization */ 4640 /* Driver initialization */
4224 ibm_thinkpad_ec_found = check_dmi_for_ec(); 4641
4225 IBM_ACPIHANDLE_INIT(ecrd); 4642 IBM_ACPIHANDLE_INIT(ecrd);
4226 IBM_ACPIHANDLE_INIT(ecwr); 4643 IBM_ACPIHANDLE_INIT(ecwr);
4227 4644
@@ -4265,6 +4682,22 @@ static int __init thinkpad_acpi_module_init(void)
4265 thinkpad_acpi_module_exit(); 4682 thinkpad_acpi_module_exit();
4266 return ret; 4683 return ret;
4267 } 4684 }
4685 tpacpi_inputdev = input_allocate_device();
4686 if (!tpacpi_inputdev) {
4687 printk(IBM_ERR "unable to allocate input device\n");
4688 thinkpad_acpi_module_exit();
4689 return -ENOMEM;
4690 } else {
4691 /* Prepare input device, but don't register */
4692 tpacpi_inputdev->name = "ThinkPad Extra Buttons";
4693 tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0";
4694 tpacpi_inputdev->id.bustype = BUS_HOST;
4695 tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ?
4696 thinkpad_id.vendor :
4697 PCI_VENDOR_ID_IBM;
4698 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
4699 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
4700 }
4268 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 4701 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
4269 ret = ibm_init(&ibms_init[i]); 4702 ret = ibm_init(&ibms_init[i]);
4270 if (ret >= 0 && *ibms_init[i].param) 4703 if (ret >= 0 && *ibms_init[i].param)
@@ -4274,6 +4707,14 @@ static int __init thinkpad_acpi_module_init(void)
4274 return ret; 4707 return ret;
4275 } 4708 }
4276 } 4709 }
4710 ret = input_register_device(tpacpi_inputdev);
4711 if (ret < 0) {
4712 printk(IBM_ERR "unable to register input device\n");
4713 thinkpad_acpi_module_exit();
4714 return ret;
4715 } else {
4716 tp_features.input_device_registered = 1;
4717 }
4277 4718
4278 return 0; 4719 return 0;
4279} 4720}
@@ -4290,6 +4731,13 @@ static void thinkpad_acpi_module_exit(void)
4290 4731
4291 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); 4732 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
4292 4733
4734 if (tpacpi_inputdev) {
4735 if (tp_features.input_device_registered)
4736 input_unregister_device(tpacpi_inputdev);
4737 else
4738 input_free_device(tpacpi_inputdev);
4739 }
4740
4293 if (tpacpi_hwmon) 4741 if (tpacpi_hwmon)
4294 hwmon_device_unregister(tpacpi_hwmon); 4742 hwmon_device_unregister(tpacpi_hwmon);
4295 4743
@@ -4302,7 +4750,9 @@ static void thinkpad_acpi_module_exit(void)
4302 if (proc_dir) 4750 if (proc_dir)
4303 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); 4751 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
4304 4752
4305 kfree(ibm_thinkpad_ec_found); 4753 kfree(thinkpad_id.bios_version_str);
4754 kfree(thinkpad_id.ec_version_str);
4755 kfree(thinkpad_id.model_str);
4306} 4756}
4307 4757
4308module_init(thinkpad_acpi_module_init); 4758module_init(thinkpad_acpi_module_init);