diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/Kconfig | 12 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/acer-wmi.c | 225 | ||||
-rw-r--r-- | drivers/misc/asus-laptop.c | 17 | ||||
-rw-r--r-- | drivers/misc/eeepc-laptop.c | 232 | ||||
-rw-r--r-- | drivers/misc/fujitsu-laptop.c | 135 | ||||
-rw-r--r-- | drivers/misc/intel_menlow.c | 29 | ||||
-rw-r--r-- | drivers/misc/panasonic-laptop.c | 767 | ||||
-rw-r--r-- | drivers/misc/sony-laptop.c | 2 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 65 |
10 files changed, 1295 insertions, 190 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index efd3aa08b88b..9494400e8fd0 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -145,6 +145,7 @@ config ACER_WMI | |||
145 | depends on NEW_LEDS | 145 | depends on NEW_LEDS |
146 | depends on BACKLIGHT_CLASS_DEVICE | 146 | depends on BACKLIGHT_CLASS_DEVICE |
147 | depends on SERIO_I8042 | 147 | depends on SERIO_I8042 |
148 | depends on RFKILL | ||
148 | select ACPI_WMI | 149 | select ACPI_WMI |
149 | ---help--- | 150 | ---help--- |
150 | This is a driver for newer Acer (and Wistron) laptops. It adds | 151 | This is a driver for newer Acer (and Wistron) laptops. It adds |
@@ -245,6 +246,17 @@ config MSI_LAPTOP | |||
245 | 246 | ||
246 | If you have an MSI S270 laptop, say Y or M here. | 247 | If you have an MSI S270 laptop, say Y or M here. |
247 | 248 | ||
249 | config PANASONIC_LAPTOP | ||
250 | tristate "Panasonic Laptop Extras" | ||
251 | depends on X86 && INPUT && ACPI | ||
252 | depends on BACKLIGHT_CLASS_DEVICE | ||
253 | ---help--- | ||
254 | This driver adds support for access to backlight control and hotkeys | ||
255 | on Panasonic Let's Note laptops. | ||
256 | |||
257 | If you have a Panasonic Let's note laptop (such as the R1(N variant), | ||
258 | R2, R3, R5, T2, W2 and Y2 series), say Y. | ||
259 | |||
248 | config COMPAL_LAPTOP | 260 | config COMPAL_LAPTOP |
249 | tristate "Compal Laptop Extras" | 261 | tristate "Compal Laptop Extras" |
250 | depends on X86 | 262 | depends on X86 |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c6c13f60b452..909e2468cdc9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_SGI_IOC4) += ioc4.o | |||
23 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o | 23 | obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o |
24 | obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o | 24 | obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o |
25 | obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o | 25 | obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o |
26 | obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o | ||
26 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o | 27 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o |
27 | obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o | 28 | obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o |
28 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o | 29 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o |
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index d8b0d326e452..0532a2de2ce4 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/acpi.h> | 34 | #include <linux/acpi.h> |
35 | #include <linux/i8042.h> | 35 | #include <linux/i8042.h> |
36 | #include <linux/rfkill.h> | ||
37 | #include <linux/workqueue.h> | ||
36 | #include <linux/debugfs.h> | 38 | #include <linux/debugfs.h> |
37 | 39 | ||
38 | #include <acpi/acpi_drivers.h> | 40 | #include <acpi/acpi_drivers.h> |
@@ -123,21 +125,15 @@ enum interface_flags { | |||
123 | 125 | ||
124 | static int max_brightness = 0xF; | 126 | static int max_brightness = 0xF; |
125 | 127 | ||
126 | static int wireless = -1; | ||
127 | static int bluetooth = -1; | ||
128 | static int mailled = -1; | 128 | static int mailled = -1; |
129 | static int brightness = -1; | 129 | static int brightness = -1; |
130 | static int threeg = -1; | 130 | static int threeg = -1; |
131 | static int force_series; | 131 | static int force_series; |
132 | 132 | ||
133 | module_param(mailled, int, 0444); | 133 | module_param(mailled, int, 0444); |
134 | module_param(wireless, int, 0444); | ||
135 | module_param(bluetooth, int, 0444); | ||
136 | module_param(brightness, int, 0444); | 134 | module_param(brightness, int, 0444); |
137 | module_param(threeg, int, 0444); | 135 | module_param(threeg, int, 0444); |
138 | module_param(force_series, int, 0444); | 136 | module_param(force_series, int, 0444); |
139 | MODULE_PARM_DESC(wireless, "Set initial state of Wireless hardware"); | ||
140 | MODULE_PARM_DESC(bluetooth, "Set initial state of Bluetooth hardware"); | ||
141 | MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); | 137 | MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); |
142 | MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); | 138 | MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); |
143 | MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); | 139 | MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); |
@@ -145,8 +141,6 @@ MODULE_PARM_DESC(force_series, "Force a different laptop series"); | |||
145 | 141 | ||
146 | struct acer_data { | 142 | struct acer_data { |
147 | int mailled; | 143 | int mailled; |
148 | int wireless; | ||
149 | int bluetooth; | ||
150 | int threeg; | 144 | int threeg; |
151 | int brightness; | 145 | int brightness; |
152 | }; | 146 | }; |
@@ -157,6 +151,9 @@ struct acer_debug { | |||
157 | u32 wmid_devices; | 151 | u32 wmid_devices; |
158 | }; | 152 | }; |
159 | 153 | ||
154 | static struct rfkill *wireless_rfkill; | ||
155 | static struct rfkill *bluetooth_rfkill; | ||
156 | |||
160 | /* Each low-level interface must define at least some of the following */ | 157 | /* Each low-level interface must define at least some of the following */ |
161 | struct wmi_interface { | 158 | struct wmi_interface { |
162 | /* The WMI device type */ | 159 | /* The WMI device type */ |
@@ -476,7 +473,7 @@ struct wmi_interface *iface) | |||
476 | } | 473 | } |
477 | break; | 474 | break; |
478 | default: | 475 | default: |
479 | return AE_BAD_ADDRESS; | 476 | return AE_ERROR; |
480 | } | 477 | } |
481 | return AE_OK; | 478 | return AE_OK; |
482 | } | 479 | } |
@@ -514,7 +511,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface) | |||
514 | break; | 511 | break; |
515 | } | 512 | } |
516 | default: | 513 | default: |
517 | return AE_BAD_ADDRESS; | 514 | return AE_ERROR; |
518 | } | 515 | } |
519 | 516 | ||
520 | /* Actually do the set */ | 517 | /* Actually do the set */ |
@@ -689,7 +686,7 @@ struct wmi_interface *iface) | |||
689 | return 0; | 686 | return 0; |
690 | } | 687 | } |
691 | default: | 688 | default: |
692 | return AE_BAD_ADDRESS; | 689 | return AE_ERROR; |
693 | } | 690 | } |
694 | status = WMI_execute_u32(method_id, 0, &result); | 691 | status = WMI_execute_u32(method_id, 0, &result); |
695 | 692 | ||
@@ -735,7 +732,7 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) | |||
735 | } | 732 | } |
736 | break; | 733 | break; |
737 | default: | 734 | default: |
738 | return AE_BAD_ADDRESS; | 735 | return AE_ERROR; |
739 | } | 736 | } |
740 | return WMI_execute_u32(method_id, (u32)value, NULL); | 737 | return WMI_execute_u32(method_id, (u32)value, NULL); |
741 | } | 738 | } |
@@ -785,7 +782,7 @@ static struct wmi_interface wmid_interface = { | |||
785 | 782 | ||
786 | static acpi_status get_u32(u32 *value, u32 cap) | 783 | static acpi_status get_u32(u32 *value, u32 cap) |
787 | { | 784 | { |
788 | acpi_status status = AE_BAD_ADDRESS; | 785 | acpi_status status = AE_ERROR; |
789 | 786 | ||
790 | switch (interface->type) { | 787 | switch (interface->type) { |
791 | case ACER_AMW0: | 788 | case ACER_AMW0: |
@@ -846,8 +843,6 @@ static void __init acer_commandline_init(void) | |||
846 | * capability isn't available on the given interface | 843 | * capability isn't available on the given interface |
847 | */ | 844 | */ |
848 | set_u32(mailled, ACER_CAP_MAILLED); | 845 | set_u32(mailled, ACER_CAP_MAILLED); |
849 | set_u32(wireless, ACER_CAP_WIRELESS); | ||
850 | set_u32(bluetooth, ACER_CAP_BLUETOOTH); | ||
851 | set_u32(threeg, ACER_CAP_THREEG); | 846 | set_u32(threeg, ACER_CAP_THREEG); |
852 | set_u32(brightness, ACER_CAP_BRIGHTNESS); | 847 | set_u32(brightness, ACER_CAP_BRIGHTNESS); |
853 | } | 848 | } |
@@ -933,40 +928,135 @@ static void acer_backlight_exit(void) | |||
933 | } | 928 | } |
934 | 929 | ||
935 | /* | 930 | /* |
936 | * Read/ write bool sysfs macro | 931 | * Rfkill devices |
937 | */ | 932 | */ |
938 | #define show_set_bool(value, cap) \ | 933 | static void acer_rfkill_update(struct work_struct *ignored); |
939 | static ssize_t \ | 934 | static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update); |
940 | show_bool_##value(struct device *dev, struct device_attribute *attr, \ | 935 | static void acer_rfkill_update(struct work_struct *ignored) |
941 | char *buf) \ | 936 | { |
942 | { \ | 937 | u32 state; |
943 | u32 result; \ | 938 | acpi_status status; |
944 | acpi_status status = get_u32(&result, cap); \ | 939 | |
945 | if (ACPI_SUCCESS(status)) \ | 940 | status = get_u32(&state, ACER_CAP_WIRELESS); |
946 | return sprintf(buf, "%u\n", result); \ | 941 | if (ACPI_SUCCESS(status)) |
947 | return sprintf(buf, "Read error\n"); \ | 942 | rfkill_force_state(wireless_rfkill, state ? |
948 | } \ | 943 | RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED); |
949 | \ | 944 | |
950 | static ssize_t \ | 945 | if (has_cap(ACER_CAP_BLUETOOTH)) { |
951 | set_bool_##value(struct device *dev, struct device_attribute *attr, \ | 946 | status = get_u32(&state, ACER_CAP_BLUETOOTH); |
952 | const char *buf, size_t count) \ | 947 | if (ACPI_SUCCESS(status)) |
953 | { \ | 948 | rfkill_force_state(bluetooth_rfkill, state ? |
954 | u32 tmp = simple_strtoul(buf, NULL, 10); \ | 949 | RFKILL_STATE_UNBLOCKED : |
955 | acpi_status status = set_u32(tmp, cap); \ | 950 | RFKILL_STATE_SOFT_BLOCKED); |
956 | if (ACPI_FAILURE(status)) \ | 951 | } |
957 | return -EINVAL; \ | 952 | |
958 | return count; \ | 953 | schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); |
959 | } \ | 954 | } |
960 | static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ | 955 | |
961 | show_bool_##value, set_bool_##value); | 956 | static int acer_rfkill_set(void *data, enum rfkill_state state) |
962 | 957 | { | |
963 | show_set_bool(wireless, ACER_CAP_WIRELESS); | 958 | acpi_status status; |
964 | show_set_bool(bluetooth, ACER_CAP_BLUETOOTH); | 959 | u32 *cap = data; |
965 | show_set_bool(threeg, ACER_CAP_THREEG); | 960 | status = set_u32((u32) (state == RFKILL_STATE_UNBLOCKED), *cap); |
961 | if (ACPI_FAILURE(status)) | ||
962 | return -ENODEV; | ||
963 | return 0; | ||
964 | } | ||
965 | |||
966 | static struct rfkill * acer_rfkill_register(struct device *dev, | ||
967 | enum rfkill_type type, char *name, u32 cap) | ||
968 | { | ||
969 | int err; | ||
970 | u32 state; | ||
971 | u32 *data; | ||
972 | struct rfkill *rfkill_dev; | ||
973 | |||
974 | rfkill_dev = rfkill_allocate(dev, type); | ||
975 | if (!rfkill_dev) | ||
976 | return ERR_PTR(-ENOMEM); | ||
977 | rfkill_dev->name = name; | ||
978 | get_u32(&state, cap); | ||
979 | rfkill_dev->state = state ? RFKILL_STATE_UNBLOCKED : | ||
980 | RFKILL_STATE_SOFT_BLOCKED; | ||
981 | data = kzalloc(sizeof(u32), GFP_KERNEL); | ||
982 | if (!data) { | ||
983 | rfkill_free(rfkill_dev); | ||
984 | return ERR_PTR(-ENOMEM); | ||
985 | } | ||
986 | *data = cap; | ||
987 | rfkill_dev->data = data; | ||
988 | rfkill_dev->toggle_radio = acer_rfkill_set; | ||
989 | rfkill_dev->user_claim_unsupported = 1; | ||
990 | |||
991 | err = rfkill_register(rfkill_dev); | ||
992 | if (err) { | ||
993 | kfree(rfkill_dev->data); | ||
994 | rfkill_free(rfkill_dev); | ||
995 | return ERR_PTR(err); | ||
996 | } | ||
997 | return rfkill_dev; | ||
998 | } | ||
999 | |||
1000 | static int acer_rfkill_init(struct device *dev) | ||
1001 | { | ||
1002 | wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN, | ||
1003 | "acer-wireless", ACER_CAP_WIRELESS); | ||
1004 | if (IS_ERR(wireless_rfkill)) | ||
1005 | return PTR_ERR(wireless_rfkill); | ||
1006 | |||
1007 | if (has_cap(ACER_CAP_BLUETOOTH)) { | ||
1008 | bluetooth_rfkill = acer_rfkill_register(dev, | ||
1009 | RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", | ||
1010 | ACER_CAP_BLUETOOTH); | ||
1011 | if (IS_ERR(bluetooth_rfkill)) { | ||
1012 | kfree(wireless_rfkill->data); | ||
1013 | rfkill_unregister(wireless_rfkill); | ||
1014 | return PTR_ERR(bluetooth_rfkill); | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); | ||
1019 | |||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | static void acer_rfkill_exit(void) | ||
1024 | { | ||
1025 | cancel_delayed_work_sync(&acer_rfkill_work); | ||
1026 | kfree(wireless_rfkill->data); | ||
1027 | rfkill_unregister(wireless_rfkill); | ||
1028 | if (has_cap(ACER_CAP_BLUETOOTH)) { | ||
1029 | kfree(wireless_rfkill->data); | ||
1030 | rfkill_unregister(bluetooth_rfkill); | ||
1031 | } | ||
1032 | return; | ||
1033 | } | ||
966 | 1034 | ||
967 | /* | 1035 | /* |
968 | * Read interface sysfs macro | 1036 | * sysfs interface |
969 | */ | 1037 | */ |
1038 | static ssize_t show_bool_threeg(struct device *dev, | ||
1039 | struct device_attribute *attr, char *buf) | ||
1040 | { | ||
1041 | u32 result; \ | ||
1042 | acpi_status status = get_u32(&result, ACER_CAP_THREEG); | ||
1043 | if (ACPI_SUCCESS(status)) | ||
1044 | return sprintf(buf, "%u\n", result); | ||
1045 | return sprintf(buf, "Read error\n"); | ||
1046 | } | ||
1047 | |||
1048 | static ssize_t set_bool_threeg(struct device *dev, | ||
1049 | struct device_attribute *attr, const char *buf, size_t count) | ||
1050 | { | ||
1051 | u32 tmp = simple_strtoul(buf, NULL, 10); | ||
1052 | acpi_status status = set_u32(tmp, ACER_CAP_THREEG); | ||
1053 | if (ACPI_FAILURE(status)) | ||
1054 | return -EINVAL; | ||
1055 | return count; | ||
1056 | } | ||
1057 | static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg, | ||
1058 | set_bool_threeg); | ||
1059 | |||
970 | static ssize_t show_interface(struct device *dev, struct device_attribute *attr, | 1060 | static ssize_t show_interface(struct device *dev, struct device_attribute *attr, |
971 | char *buf) | 1061 | char *buf) |
972 | { | 1062 | { |
@@ -1026,7 +1116,9 @@ static int __devinit acer_platform_probe(struct platform_device *device) | |||
1026 | goto error_brightness; | 1116 | goto error_brightness; |
1027 | } | 1117 | } |
1028 | 1118 | ||
1029 | return 0; | 1119 | err = acer_rfkill_init(&device->dev); |
1120 | |||
1121 | return err; | ||
1030 | 1122 | ||
1031 | error_brightness: | 1123 | error_brightness: |
1032 | acer_led_exit(); | 1124 | acer_led_exit(); |
@@ -1040,6 +1132,8 @@ static int acer_platform_remove(struct platform_device *device) | |||
1040 | acer_led_exit(); | 1132 | acer_led_exit(); |
1041 | if (has_cap(ACER_CAP_BRIGHTNESS)) | 1133 | if (has_cap(ACER_CAP_BRIGHTNESS)) |
1042 | acer_backlight_exit(); | 1134 | acer_backlight_exit(); |
1135 | |||
1136 | acer_rfkill_exit(); | ||
1043 | return 0; | 1137 | return 0; |
1044 | } | 1138 | } |
1045 | 1139 | ||
@@ -1052,16 +1146,6 @@ pm_message_t state) | |||
1052 | if (!data) | 1146 | if (!data) |
1053 | return -ENOMEM; | 1147 | return -ENOMEM; |
1054 | 1148 | ||
1055 | if (has_cap(ACER_CAP_WIRELESS)) { | ||
1056 | get_u32(&value, ACER_CAP_WIRELESS); | ||
1057 | data->wireless = value; | ||
1058 | } | ||
1059 | |||
1060 | if (has_cap(ACER_CAP_BLUETOOTH)) { | ||
1061 | get_u32(&value, ACER_CAP_BLUETOOTH); | ||
1062 | data->bluetooth = value; | ||
1063 | } | ||
1064 | |||
1065 | if (has_cap(ACER_CAP_MAILLED)) { | 1149 | if (has_cap(ACER_CAP_MAILLED)) { |
1066 | get_u32(&value, ACER_CAP_MAILLED); | 1150 | get_u32(&value, ACER_CAP_MAILLED); |
1067 | data->mailled = value; | 1151 | data->mailled = value; |
@@ -1082,15 +1166,6 @@ static int acer_platform_resume(struct platform_device *device) | |||
1082 | if (!data) | 1166 | if (!data) |
1083 | return -ENOMEM; | 1167 | return -ENOMEM; |
1084 | 1168 | ||
1085 | if (has_cap(ACER_CAP_WIRELESS)) | ||
1086 | set_u32(data->wireless, ACER_CAP_WIRELESS); | ||
1087 | |||
1088 | if (has_cap(ACER_CAP_BLUETOOTH)) | ||
1089 | set_u32(data->bluetooth, ACER_CAP_BLUETOOTH); | ||
1090 | |||
1091 | if (has_cap(ACER_CAP_THREEG)) | ||
1092 | set_u32(data->threeg, ACER_CAP_THREEG); | ||
1093 | |||
1094 | if (has_cap(ACER_CAP_MAILLED)) | 1169 | if (has_cap(ACER_CAP_MAILLED)) |
1095 | set_u32(data->mailled, ACER_CAP_MAILLED); | 1170 | set_u32(data->mailled, ACER_CAP_MAILLED); |
1096 | 1171 | ||
@@ -1115,12 +1190,6 @@ static struct platform_device *acer_platform_device; | |||
1115 | 1190 | ||
1116 | static int remove_sysfs(struct platform_device *device) | 1191 | static int remove_sysfs(struct platform_device *device) |
1117 | { | 1192 | { |
1118 | if (has_cap(ACER_CAP_WIRELESS)) | ||
1119 | device_remove_file(&device->dev, &dev_attr_wireless); | ||
1120 | |||
1121 | if (has_cap(ACER_CAP_BLUETOOTH)) | ||
1122 | device_remove_file(&device->dev, &dev_attr_bluetooth); | ||
1123 | |||
1124 | if (has_cap(ACER_CAP_THREEG)) | 1193 | if (has_cap(ACER_CAP_THREEG)) |
1125 | device_remove_file(&device->dev, &dev_attr_threeg); | 1194 | device_remove_file(&device->dev, &dev_attr_threeg); |
1126 | 1195 | ||
@@ -1133,20 +1202,6 @@ static int create_sysfs(void) | |||
1133 | { | 1202 | { |
1134 | int retval = -ENOMEM; | 1203 | int retval = -ENOMEM; |
1135 | 1204 | ||
1136 | if (has_cap(ACER_CAP_WIRELESS)) { | ||
1137 | retval = device_create_file(&acer_platform_device->dev, | ||
1138 | &dev_attr_wireless); | ||
1139 | if (retval) | ||
1140 | goto error_sysfs; | ||
1141 | } | ||
1142 | |||
1143 | if (has_cap(ACER_CAP_BLUETOOTH)) { | ||
1144 | retval = device_create_file(&acer_platform_device->dev, | ||
1145 | &dev_attr_bluetooth); | ||
1146 | if (retval) | ||
1147 | goto error_sysfs; | ||
1148 | } | ||
1149 | |||
1150 | if (has_cap(ACER_CAP_THREEG)) { | 1205 | if (has_cap(ACER_CAP_THREEG)) { |
1151 | retval = device_create_file(&acer_platform_device->dev, | 1206 | retval = device_create_file(&acer_platform_device->dev, |
1152 | &dev_attr_threeg); | 1207 | &dev_attr_threeg); |
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 7c6dfd03de9f..a9d5228724a6 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c | |||
@@ -139,6 +139,7 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ | |||
139 | "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ | 139 | "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ |
140 | "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ | 140 | "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ |
141 | "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ | 141 | "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ |
142 | "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */ | ||
142 | "\\_SB.PCI0.PX40.Q10", /* S1x */ | 143 | "\\_SB.PCI0.PX40.Q10", /* S1x */ |
143 | "\\Q10"); /* A2x, L2D, L3D, M2E */ | 144 | "\\Q10"); /* A2x, L2D, L3D, M2E */ |
144 | 145 | ||
@@ -280,7 +281,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, | |||
280 | 281 | ||
281 | static int read_wireless_status(int mask) | 282 | static int read_wireless_status(int mask) |
282 | { | 283 | { |
283 | ulong status; | 284 | unsigned long long status; |
284 | acpi_status rv = AE_OK; | 285 | acpi_status rv = AE_OK; |
285 | 286 | ||
286 | if (!wireless_status_handle) | 287 | if (!wireless_status_handle) |
@@ -297,7 +298,7 @@ static int read_wireless_status(int mask) | |||
297 | 298 | ||
298 | static int read_gps_status(void) | 299 | static int read_gps_status(void) |
299 | { | 300 | { |
300 | ulong status; | 301 | unsigned long long status; |
301 | acpi_status rv = AE_OK; | 302 | acpi_status rv = AE_OK; |
302 | 303 | ||
303 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); | 304 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); |
@@ -350,7 +351,7 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
350 | static void object##_led_set(struct led_classdev *led_cdev, \ | 351 | static void object##_led_set(struct led_classdev *led_cdev, \ |
351 | enum led_brightness value) \ | 352 | enum led_brightness value) \ |
352 | { \ | 353 | { \ |
353 | object##_led_wk = value; \ | 354 | object##_led_wk = (value > 0) ? 1 : 0; \ |
354 | queue_work(led_workqueue, &object##_led_work); \ | 355 | queue_work(led_workqueue, &object##_led_work); \ |
355 | } \ | 356 | } \ |
356 | static void object##_led_update(struct work_struct *ignored) \ | 357 | static void object##_led_update(struct work_struct *ignored) \ |
@@ -404,7 +405,7 @@ static void lcd_blank(int blank) | |||
404 | 405 | ||
405 | static int read_brightness(struct backlight_device *bd) | 406 | static int read_brightness(struct backlight_device *bd) |
406 | { | 407 | { |
407 | ulong value; | 408 | unsigned long long value; |
408 | acpi_status rv = AE_OK; | 409 | acpi_status rv = AE_OK; |
409 | 410 | ||
410 | rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); | 411 | rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); |
@@ -455,7 +456,7 @@ static ssize_t show_infos(struct device *dev, | |||
455 | struct device_attribute *attr, char *page) | 456 | struct device_attribute *attr, char *page) |
456 | { | 457 | { |
457 | int len = 0; | 458 | int len = 0; |
458 | ulong temp; | 459 | unsigned long long temp; |
459 | char buf[16]; //enough for all info | 460 | char buf[16]; //enough for all info |
460 | acpi_status rv = AE_OK; | 461 | acpi_status rv = AE_OK; |
461 | 462 | ||
@@ -603,7 +604,7 @@ static void set_display(int value) | |||
603 | 604 | ||
604 | static int read_display(void) | 605 | static int read_display(void) |
605 | { | 606 | { |
606 | ulong value = 0; | 607 | unsigned long long value = 0; |
607 | acpi_status rv = AE_OK; | 608 | acpi_status rv = AE_OK; |
608 | 609 | ||
609 | /* In most of the case, we know how to set the display, but sometime | 610 | /* In most of the case, we know how to set the display, but sometime |
@@ -849,7 +850,7 @@ static int asus_hotk_get_info(void) | |||
849 | { | 850 | { |
850 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 851 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
851 | union acpi_object *model = NULL; | 852 | union acpi_object *model = NULL; |
852 | ulong bsts_result, hwrs_result; | 853 | unsigned long long bsts_result, hwrs_result; |
853 | char *string = NULL; | 854 | char *string = NULL; |
854 | acpi_status status; | 855 | acpi_status status; |
855 | 856 | ||
@@ -996,7 +997,7 @@ static int asus_hotk_add(struct acpi_device *device) | |||
996 | hotk->handle = device->handle; | 997 | hotk->handle = device->handle; |
997 | strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); | 998 | strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); |
998 | strcpy(acpi_device_class(device), ASUS_HOTK_CLASS); | 999 | strcpy(acpi_device_class(device), ASUS_HOTK_CLASS); |
999 | acpi_driver_data(device) = hotk; | 1000 | device->driver_data = hotk; |
1000 | hotk->device = device; | 1001 | hotk->device = device; |
1001 | 1002 | ||
1002 | result = asus_hotk_check(); | 1003 | result = asus_hotk_check(); |
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 1ee8501e90f1..9ef98b2d5039 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <acpi/acpi_drivers.h> | 28 | #include <acpi/acpi_drivers.h> |
29 | #include <acpi/acpi_bus.h> | 29 | #include <acpi/acpi_bus.h> |
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/input.h> | ||
32 | #include <linux/rfkill.h> | ||
31 | 33 | ||
32 | #define EEEPC_LAPTOP_VERSION "0.1" | 34 | #define EEEPC_LAPTOP_VERSION "0.1" |
33 | 35 | ||
@@ -125,6 +127,10 @@ struct eeepc_hotk { | |||
125 | by this BIOS */ | 127 | by this BIOS */ |
126 | uint init_flag; /* Init flags */ | 128 | uint init_flag; /* Init flags */ |
127 | u16 event_count[128]; /* count for each event */ | 129 | u16 event_count[128]; /* count for each event */ |
130 | struct input_dev *inputdev; | ||
131 | u16 *keycode_map; | ||
132 | struct rfkill *eeepc_wlan_rfkill; | ||
133 | struct rfkill *eeepc_bluetooth_rfkill; | ||
128 | }; | 134 | }; |
129 | 135 | ||
130 | /* The actual device the driver binds to */ | 136 | /* The actual device the driver binds to */ |
@@ -140,6 +146,27 @@ static struct platform_driver platform_driver = { | |||
140 | 146 | ||
141 | static struct platform_device *platform_device; | 147 | static struct platform_device *platform_device; |
142 | 148 | ||
149 | struct key_entry { | ||
150 | char type; | ||
151 | u8 code; | ||
152 | u16 keycode; | ||
153 | }; | ||
154 | |||
155 | enum { KE_KEY, KE_END }; | ||
156 | |||
157 | static struct key_entry eeepc_keymap[] = { | ||
158 | /* Sleep already handled via generic ACPI code */ | ||
159 | {KE_KEY, 0x10, KEY_WLAN }, | ||
160 | {KE_KEY, 0x12, KEY_PROG1 }, | ||
161 | {KE_KEY, 0x13, KEY_MUTE }, | ||
162 | {KE_KEY, 0x14, KEY_VOLUMEDOWN }, | ||
163 | {KE_KEY, 0x15, KEY_VOLUMEUP }, | ||
164 | {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, | ||
165 | {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, | ||
166 | {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, | ||
167 | {KE_END, 0}, | ||
168 | }; | ||
169 | |||
143 | /* | 170 | /* |
144 | * The hotkey driver declaration | 171 | * The hotkey driver declaration |
145 | */ | 172 | */ |
@@ -204,7 +231,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, | |||
204 | static int read_acpi_int(acpi_handle handle, const char *method, int *val) | 231 | static int read_acpi_int(acpi_handle handle, const char *method, int *val) |
205 | { | 232 | { |
206 | acpi_status status; | 233 | acpi_status status; |
207 | ulong result; | 234 | unsigned long long result; |
208 | 235 | ||
209 | status = acpi_evaluate_integer(handle, (char *)method, NULL, &result); | 236 | status = acpi_evaluate_integer(handle, (char *)method, NULL, &result); |
210 | if (ACPI_FAILURE(status)) { | 237 | if (ACPI_FAILURE(status)) { |
@@ -261,6 +288,44 @@ static int update_bl_status(struct backlight_device *bd) | |||
261 | } | 288 | } |
262 | 289 | ||
263 | /* | 290 | /* |
291 | * Rfkill helpers | ||
292 | */ | ||
293 | |||
294 | static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state) | ||
295 | { | ||
296 | if (state == RFKILL_STATE_SOFT_BLOCKED) | ||
297 | return set_acpi(CM_ASL_WLAN, 0); | ||
298 | else | ||
299 | return set_acpi(CM_ASL_WLAN, 1); | ||
300 | } | ||
301 | |||
302 | static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state) | ||
303 | { | ||
304 | if (get_acpi(CM_ASL_WLAN) == 1) | ||
305 | *state = RFKILL_STATE_UNBLOCKED; | ||
306 | else | ||
307 | *state = RFKILL_STATE_SOFT_BLOCKED; | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state) | ||
312 | { | ||
313 | if (state == RFKILL_STATE_SOFT_BLOCKED) | ||
314 | return set_acpi(CM_ASL_BLUETOOTH, 0); | ||
315 | else | ||
316 | return set_acpi(CM_ASL_BLUETOOTH, 1); | ||
317 | } | ||
318 | |||
319 | static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state) | ||
320 | { | ||
321 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) | ||
322 | *state = RFKILL_STATE_UNBLOCKED; | ||
323 | else | ||
324 | *state = RFKILL_STATE_SOFT_BLOCKED; | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /* | ||
264 | * Sys helpers | 329 | * Sys helpers |
265 | */ | 330 | */ |
266 | static int parse_arg(const char *buf, unsigned long count, int *val) | 331 | static int parse_arg(const char *buf, unsigned long count, int *val) |
@@ -311,13 +376,11 @@ static ssize_t show_sys_acpi(int cm, char *buf) | |||
311 | EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); | 376 | EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); |
312 | EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); | 377 | EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); |
313 | EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); | 378 | EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); |
314 | EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN); | ||
315 | 379 | ||
316 | static struct attribute *platform_attributes[] = { | 380 | static struct attribute *platform_attributes[] = { |
317 | &dev_attr_camera.attr, | 381 | &dev_attr_camera.attr, |
318 | &dev_attr_cardr.attr, | 382 | &dev_attr_cardr.attr, |
319 | &dev_attr_disp.attr, | 383 | &dev_attr_disp.attr, |
320 | &dev_attr_wlan.attr, | ||
321 | NULL | 384 | NULL |
322 | }; | 385 | }; |
323 | 386 | ||
@@ -328,8 +391,64 @@ static struct attribute_group platform_attribute_group = { | |||
328 | /* | 391 | /* |
329 | * Hotkey functions | 392 | * Hotkey functions |
330 | */ | 393 | */ |
394 | static struct key_entry *eepc_get_entry_by_scancode(int code) | ||
395 | { | ||
396 | struct key_entry *key; | ||
397 | |||
398 | for (key = eeepc_keymap; key->type != KE_END; key++) | ||
399 | if (code == key->code) | ||
400 | return key; | ||
401 | |||
402 | return NULL; | ||
403 | } | ||
404 | |||
405 | static struct key_entry *eepc_get_entry_by_keycode(int code) | ||
406 | { | ||
407 | struct key_entry *key; | ||
408 | |||
409 | for (key = eeepc_keymap; key->type != KE_END; key++) | ||
410 | if (code == key->keycode && key->type == KE_KEY) | ||
411 | return key; | ||
412 | |||
413 | return NULL; | ||
414 | } | ||
415 | |||
416 | static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
417 | { | ||
418 | struct key_entry *key = eepc_get_entry_by_scancode(scancode); | ||
419 | |||
420 | if (key && key->type == KE_KEY) { | ||
421 | *keycode = key->keycode; | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | ||
429 | { | ||
430 | struct key_entry *key; | ||
431 | int old_keycode; | ||
432 | |||
433 | if (keycode < 0 || keycode > KEY_MAX) | ||
434 | return -EINVAL; | ||
435 | |||
436 | key = eepc_get_entry_by_scancode(scancode); | ||
437 | if (key && key->type == KE_KEY) { | ||
438 | old_keycode = key->keycode; | ||
439 | key->keycode = keycode; | ||
440 | set_bit(keycode, dev->keybit); | ||
441 | if (!eepc_get_entry_by_keycode(old_keycode)) | ||
442 | clear_bit(old_keycode, dev->keybit); | ||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | return -EINVAL; | ||
447 | } | ||
448 | |||
331 | static int eeepc_hotk_check(void) | 449 | static int eeepc_hotk_check(void) |
332 | { | 450 | { |
451 | const struct key_entry *key; | ||
333 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 452 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
334 | int result; | 453 | int result; |
335 | 454 | ||
@@ -356,6 +475,31 @@ static int eeepc_hotk_check(void) | |||
356 | "Get control methods supported: 0x%x\n", | 475 | "Get control methods supported: 0x%x\n", |
357 | ehotk->cm_supported); | 476 | ehotk->cm_supported); |
358 | } | 477 | } |
478 | ehotk->inputdev = input_allocate_device(); | ||
479 | if (!ehotk->inputdev) { | ||
480 | printk(EEEPC_INFO "Unable to allocate input device\n"); | ||
481 | return 0; | ||
482 | } | ||
483 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | ||
484 | ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; | ||
485 | ehotk->inputdev->id.bustype = BUS_HOST; | ||
486 | ehotk->inputdev->getkeycode = eeepc_getkeycode; | ||
487 | ehotk->inputdev->setkeycode = eeepc_setkeycode; | ||
488 | |||
489 | for (key = eeepc_keymap; key->type != KE_END; key++) { | ||
490 | switch (key->type) { | ||
491 | case KE_KEY: | ||
492 | set_bit(EV_KEY, ehotk->inputdev->evbit); | ||
493 | set_bit(key->keycode, ehotk->inputdev->keybit); | ||
494 | break; | ||
495 | } | ||
496 | } | ||
497 | result = input_register_device(ehotk->inputdev); | ||
498 | if (result) { | ||
499 | printk(EEEPC_INFO "Unable to register input device\n"); | ||
500 | input_free_device(ehotk->inputdev); | ||
501 | return 0; | ||
502 | } | ||
359 | } else { | 503 | } else { |
360 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); | 504 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); |
361 | return -EINVAL; | 505 | return -EINVAL; |
@@ -363,21 +507,6 @@ static int eeepc_hotk_check(void) | |||
363 | return 0; | 507 | return 0; |
364 | } | 508 | } |
365 | 509 | ||
366 | static void notify_wlan(u32 *event) | ||
367 | { | ||
368 | /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2 | ||
369 | will always be 0x10 */ | ||
370 | if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) { | ||
371 | const char *method = cm_getv[CM_ASL_WLAN]; | ||
372 | int value; | ||
373 | if (read_acpi_int(ehotk->handle, method, &value)) | ||
374 | printk(EEEPC_WARNING "Error reading %s\n", | ||
375 | method); | ||
376 | else if (value == 1) | ||
377 | *event = 0x11; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static void notify_brn(void) | 510 | static void notify_brn(void) |
382 | { | 511 | { |
383 | struct backlight_device *bd = eeepc_backlight_device; | 512 | struct backlight_device *bd = eeepc_backlight_device; |
@@ -386,14 +515,28 @@ static void notify_brn(void) | |||
386 | 515 | ||
387 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | 516 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) |
388 | { | 517 | { |
518 | static struct key_entry *key; | ||
389 | if (!ehotk) | 519 | if (!ehotk) |
390 | return; | 520 | return; |
391 | if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) | ||
392 | notify_wlan(&event); | ||
393 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | 521 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) |
394 | notify_brn(); | 522 | notify_brn(); |
395 | acpi_bus_generate_proc_event(ehotk->device, event, | 523 | acpi_bus_generate_proc_event(ehotk->device, event, |
396 | ehotk->event_count[event % 128]++); | 524 | ehotk->event_count[event % 128]++); |
525 | if (ehotk->inputdev) { | ||
526 | key = eepc_get_entry_by_scancode(event); | ||
527 | if (key) { | ||
528 | switch (key->type) { | ||
529 | case KE_KEY: | ||
530 | input_report_key(ehotk->inputdev, key->keycode, | ||
531 | 1); | ||
532 | input_sync(ehotk->inputdev); | ||
533 | input_report_key(ehotk->inputdev, key->keycode, | ||
534 | 0); | ||
535 | input_sync(ehotk->inputdev); | ||
536 | break; | ||
537 | } | ||
538 | } | ||
539 | } | ||
397 | } | 540 | } |
398 | 541 | ||
399 | static int eeepc_hotk_add(struct acpi_device *device) | 542 | static int eeepc_hotk_add(struct acpi_device *device) |
@@ -411,7 +554,7 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
411 | ehotk->handle = device->handle; | 554 | ehotk->handle = device->handle; |
412 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); | 555 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); |
413 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | 556 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); |
414 | acpi_driver_data(device) = ehotk; | 557 | device->driver_data = ehotk; |
415 | ehotk->device = device; | 558 | ehotk->device = device; |
416 | result = eeepc_hotk_check(); | 559 | result = eeepc_hotk_check(); |
417 | if (result) | 560 | if (result) |
@@ -420,6 +563,47 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
420 | eeepc_hotk_notify, ehotk); | 563 | eeepc_hotk_notify, ehotk); |
421 | if (ACPI_FAILURE(status)) | 564 | if (ACPI_FAILURE(status)) |
422 | printk(EEEPC_ERR "Error installing notify handler\n"); | 565 | printk(EEEPC_ERR "Error installing notify handler\n"); |
566 | |||
567 | if (get_acpi(CM_ASL_WLAN) != -1) { | ||
568 | ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev, | ||
569 | RFKILL_TYPE_WLAN); | ||
570 | |||
571 | if (!ehotk->eeepc_wlan_rfkill) | ||
572 | goto end; | ||
573 | |||
574 | ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; | ||
575 | ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; | ||
576 | ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; | ||
577 | if (get_acpi(CM_ASL_WLAN) == 1) | ||
578 | ehotk->eeepc_wlan_rfkill->state = | ||
579 | RFKILL_STATE_UNBLOCKED; | ||
580 | else | ||
581 | ehotk->eeepc_wlan_rfkill->state = | ||
582 | RFKILL_STATE_SOFT_BLOCKED; | ||
583 | rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
584 | } | ||
585 | |||
586 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | ||
587 | ehotk->eeepc_bluetooth_rfkill = | ||
588 | rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); | ||
589 | |||
590 | if (!ehotk->eeepc_bluetooth_rfkill) | ||
591 | goto end; | ||
592 | |||
593 | ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; | ||
594 | ehotk->eeepc_bluetooth_rfkill->toggle_radio = | ||
595 | eeepc_bluetooth_rfkill_set; | ||
596 | ehotk->eeepc_bluetooth_rfkill->get_state = | ||
597 | eeepc_bluetooth_rfkill_state; | ||
598 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) | ||
599 | ehotk->eeepc_bluetooth_rfkill->state = | ||
600 | RFKILL_STATE_UNBLOCKED; | ||
601 | else | ||
602 | ehotk->eeepc_bluetooth_rfkill->state = | ||
603 | RFKILL_STATE_SOFT_BLOCKED; | ||
604 | rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||
605 | } | ||
606 | |||
423 | end: | 607 | end: |
424 | if (result) { | 608 | if (result) { |
425 | kfree(ehotk); | 609 | kfree(ehotk); |
@@ -553,6 +737,12 @@ static void eeepc_backlight_exit(void) | |||
553 | { | 737 | { |
554 | if (eeepc_backlight_device) | 738 | if (eeepc_backlight_device) |
555 | backlight_device_unregister(eeepc_backlight_device); | 739 | backlight_device_unregister(eeepc_backlight_device); |
740 | if (ehotk->inputdev) | ||
741 | input_unregister_device(ehotk->inputdev); | ||
742 | if (ehotk->eeepc_wlan_rfkill) | ||
743 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
744 | if (ehotk->eeepc_bluetooth_rfkill) | ||
745 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | ||
556 | eeepc_backlight_device = NULL; | 746 | eeepc_backlight_device = NULL; |
557 | } | 747 | } |
558 | 748 | ||
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index 3e56203e4947..d2cf0bfe3163 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c | |||
@@ -44,8 +44,9 @@ | |||
44 | * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are | 44 | * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are |
45 | * also supported by this driver. | 45 | * also supported by this driver. |
46 | * | 46 | * |
47 | * This driver has been tested on a Fujitsu Lifebook S6410 and S7020. It | 47 | * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and |
48 | * should work on most P-series and S-series Lifebooks, but YMMV. | 48 | * P8010. It should work on most P-series and S-series Lifebooks, but |
49 | * YMMV. | ||
49 | * | 50 | * |
50 | * The module parameter use_alt_lcd_levels switches between different ACPI | 51 | * The module parameter use_alt_lcd_levels switches between different ACPI |
51 | * brightness controls which are used by different Fujitsu laptops. In most | 52 | * brightness controls which are used by different Fujitsu laptops. In most |
@@ -65,7 +66,7 @@ | |||
65 | #include <linux/video_output.h> | 66 | #include <linux/video_output.h> |
66 | #include <linux/platform_device.h> | 67 | #include <linux/platform_device.h> |
67 | 68 | ||
68 | #define FUJITSU_DRIVER_VERSION "0.4.2" | 69 | #define FUJITSU_DRIVER_VERSION "0.4.3" |
69 | 70 | ||
70 | #define FUJITSU_LCD_N_LEVELS 8 | 71 | #define FUJITSU_LCD_N_LEVELS 8 |
71 | 72 | ||
@@ -83,10 +84,10 @@ | |||
83 | #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 | 84 | #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 |
84 | 85 | ||
85 | /* Hotkey details */ | 86 | /* Hotkey details */ |
86 | #define LOCK_KEY 0x410 /* codes for the keys in the GIRB register */ | 87 | #define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ |
87 | #define DISPLAY_KEY 0x411 /* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */ | 88 | #define KEY2_CODE 0x411 |
88 | #define ENERGY_KEY 0x412 /* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */ | 89 | #define KEY3_CODE 0x412 |
89 | #define REST_KEY 0x413 /* KEY_SUSPEND (R key) */ | 90 | #define KEY4_CODE 0x413 |
90 | 91 | ||
91 | #define MAX_HOTKEY_RINGBUFFER_SIZE 100 | 92 | #define MAX_HOTKEY_RINGBUFFER_SIZE 100 |
92 | #define RINGBUFFERSIZE 40 | 93 | #define RINGBUFFERSIZE 40 |
@@ -123,6 +124,7 @@ struct fujitsu_t { | |||
123 | char phys[32]; | 124 | char phys[32]; |
124 | struct backlight_device *bl_device; | 125 | struct backlight_device *bl_device; |
125 | struct platform_device *pf_device; | 126 | struct platform_device *pf_device; |
127 | int keycode1, keycode2, keycode3, keycode4; | ||
126 | 128 | ||
127 | unsigned int max_brightness; | 129 | unsigned int max_brightness; |
128 | unsigned int brightness_changed; | 130 | unsigned int brightness_changed; |
@@ -224,7 +226,7 @@ static int set_lcd_level_alt(int level) | |||
224 | 226 | ||
225 | static int get_lcd_level(void) | 227 | static int get_lcd_level(void) |
226 | { | 228 | { |
227 | unsigned long state = 0; | 229 | unsigned long long state = 0; |
228 | acpi_status status = AE_OK; | 230 | acpi_status status = AE_OK; |
229 | 231 | ||
230 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n"); | 232 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n"); |
@@ -246,7 +248,7 @@ static int get_lcd_level(void) | |||
246 | 248 | ||
247 | static int get_max_brightness(void) | 249 | static int get_max_brightness(void) |
248 | { | 250 | { |
249 | unsigned long state = 0; | 251 | unsigned long long state = 0; |
250 | acpi_status status = AE_OK; | 252 | acpi_status status = AE_OK; |
251 | 253 | ||
252 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n"); | 254 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n"); |
@@ -263,7 +265,7 @@ static int get_max_brightness(void) | |||
263 | 265 | ||
264 | static int get_lcd_level_alt(void) | 266 | static int get_lcd_level_alt(void) |
265 | { | 267 | { |
266 | unsigned long state = 0; | 268 | unsigned long long state = 0; |
267 | acpi_status status = AE_OK; | 269 | acpi_status status = AE_OK; |
268 | 270 | ||
269 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n"); | 271 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n"); |
@@ -384,7 +386,7 @@ static ssize_t store_lcd_level(struct device *dev, | |||
384 | 386 | ||
385 | static int get_irb(void) | 387 | static int get_irb(void) |
386 | { | 388 | { |
387 | unsigned long state = 0; | 389 | unsigned long long state = 0; |
388 | acpi_status status = AE_OK; | 390 | acpi_status status = AE_OK; |
389 | 391 | ||
390 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n"); | 392 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n"); |
@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = { | |||
430 | } | 432 | } |
431 | }; | 433 | }; |
432 | 434 | ||
433 | static int dmi_check_cb_s6410(const struct dmi_system_id *id) | 435 | static void dmi_check_cb_common(const struct dmi_system_id *id) |
434 | { | 436 | { |
435 | acpi_handle handle; | 437 | acpi_handle handle; |
436 | int have_blnf; | 438 | int have_blnf; |
@@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) | |||
452 | "auto-detecting disable_adjust\n"); | 454 | "auto-detecting disable_adjust\n"); |
453 | disable_brightness_adjust = have_blnf ? 0 : 1; | 455 | disable_brightness_adjust = have_blnf ? 0 : 1; |
454 | } | 456 | } |
457 | } | ||
458 | |||
459 | static int dmi_check_cb_s6410(const struct dmi_system_id *id) | ||
460 | { | ||
461 | dmi_check_cb_common(id); | ||
462 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ | ||
463 | fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int dmi_check_cb_p8010(const struct dmi_system_id *id) | ||
468 | { | ||
469 | dmi_check_cb_common(id); | ||
470 | fujitsu->keycode1 = KEY_HELP; /* "Support" */ | ||
471 | fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */ | ||
472 | fujitsu->keycode4 = KEY_WWW; /* "Internet" */ | ||
455 | return 0; | 473 | return 0; |
456 | } | 474 | } |
457 | 475 | ||
458 | static struct dmi_system_id __initdata fujitsu_dmi_table[] = { | 476 | static struct dmi_system_id __initdata fujitsu_dmi_table[] = { |
459 | { | 477 | { |
460 | .ident = "Fujitsu Siemens", | 478 | .ident = "Fujitsu Siemens S6410", |
461 | .matches = { | 479 | .matches = { |
462 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 480 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
463 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), | 481 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), |
464 | }, | 482 | }, |
465 | .callback = dmi_check_cb_s6410}, | 483 | .callback = dmi_check_cb_s6410}, |
466 | { | 484 | { |
467 | .ident = "FUJITSU LifeBook P8010", | 485 | .ident = "Fujitsu LifeBook P8010", |
468 | .matches = { | 486 | .matches = { |
469 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 487 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
470 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), | 488 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), |
471 | }, | 489 | }, |
472 | .callback = dmi_check_cb_s6410}, | 490 | .callback = dmi_check_cb_p8010}, |
473 | {} | 491 | {} |
474 | }; | 492 | }; |
475 | 493 | ||
@@ -490,7 +508,7 @@ static int acpi_fujitsu_add(struct acpi_device *device) | |||
490 | fujitsu->acpi_handle = device->handle; | 508 | fujitsu->acpi_handle = device->handle; |
491 | sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME); | 509 | sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME); |
492 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); | 510 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); |
493 | acpi_driver_data(device) = fujitsu; | 511 | device->driver_data = fujitsu; |
494 | 512 | ||
495 | status = acpi_install_notify_handler(device->handle, | 513 | status = acpi_install_notify_handler(device->handle, |
496 | ACPI_DEVICE_NOTIFY, | 514 | ACPI_DEVICE_NOTIFY, |
@@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device) | |||
547 | } | 565 | } |
548 | 566 | ||
549 | /* do config (detect defaults) */ | 567 | /* do config (detect defaults) */ |
550 | dmi_check_system(fujitsu_dmi_table); | ||
551 | use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; | 568 | use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; |
552 | disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0; | 569 | disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0; |
553 | disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; | 570 | disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; |
@@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) | |||
623 | keycode = 0; | 640 | keycode = 0; |
624 | if (disable_brightness_keys != 1) { | 641 | if (disable_brightness_keys != 1) { |
625 | if (oldb == 0) { | 642 | if (oldb == 0) { |
626 | acpi_bus_generate_proc_event(fujitsu-> | 643 | acpi_bus_generate_proc_event |
627 | dev, | 644 | (fujitsu->dev, |
628 | ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, | 645 | ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, |
629 | 0); | 646 | 0); |
630 | keycode = KEY_BRIGHTNESSDOWN; | 647 | keycode = KEY_BRIGHTNESSDOWN; |
631 | } else if (oldb == | 648 | } else if (oldb == |
632 | (fujitsu->max_brightness) - 1) { | 649 | (fujitsu->max_brightness) - 1) { |
633 | acpi_bus_generate_proc_event(fujitsu-> | 650 | acpi_bus_generate_proc_event |
634 | dev, | 651 | (fujitsu->dev, |
635 | ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, | 652 | ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, |
636 | 0); | 653 | 0); |
637 | keycode = KEY_BRIGHTNESSUP; | 654 | keycode = KEY_BRIGHTNESSUP; |
638 | } | 655 | } |
639 | } | 656 | } |
@@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) | |||
646 | } | 663 | } |
647 | if (disable_brightness_keys != 1) { | 664 | if (disable_brightness_keys != 1) { |
648 | acpi_bus_generate_proc_event(fujitsu->dev, | 665 | acpi_bus_generate_proc_event(fujitsu->dev, |
649 | ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, | 666 | ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0); |
650 | 0); | ||
651 | keycode = KEY_BRIGHTNESSUP; | 667 | keycode = KEY_BRIGHTNESSUP; |
652 | } | 668 | } |
653 | } else if (oldb > newb) { | 669 | } else if (oldb > newb) { |
@@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) | |||
659 | } | 675 | } |
660 | if (disable_brightness_keys != 1) { | 676 | if (disable_brightness_keys != 1) { |
661 | acpi_bus_generate_proc_event(fujitsu->dev, | 677 | acpi_bus_generate_proc_event(fujitsu->dev, |
662 | ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, | 678 | ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0); |
663 | 0); | ||
664 | keycode = KEY_BRIGHTNESSDOWN; | 679 | keycode = KEY_BRIGHTNESSDOWN; |
665 | } | 680 | } |
666 | } else { | 681 | } else { |
@@ -703,7 +718,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
703 | sprintf(acpi_device_name(device), "%s", | 718 | sprintf(acpi_device_name(device), "%s", |
704 | ACPI_FUJITSU_HOTKEY_DEVICE_NAME); | 719 | ACPI_FUJITSU_HOTKEY_DEVICE_NAME); |
705 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); | 720 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); |
706 | acpi_driver_data(device) = fujitsu_hotkey; | 721 | device->driver_data = fujitsu_hotkey; |
707 | 722 | ||
708 | status = acpi_install_notify_handler(device->handle, | 723 | status = acpi_install_notify_handler(device->handle, |
709 | ACPI_DEVICE_NOTIFY, | 724 | ACPI_DEVICE_NOTIFY, |
@@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
742 | input->id.product = 0x06; | 757 | input->id.product = 0x06; |
743 | input->dev.parent = &device->dev; | 758 | input->dev.parent = &device->dev; |
744 | input->evbit[0] = BIT(EV_KEY); | 759 | input->evbit[0] = BIT(EV_KEY); |
745 | set_bit(KEY_SCREENLOCK, input->keybit); | 760 | set_bit(fujitsu->keycode1, input->keybit); |
746 | set_bit(KEY_MEDIA, input->keybit); | 761 | set_bit(fujitsu->keycode2, input->keybit); |
747 | set_bit(KEY_EMAIL, input->keybit); | 762 | set_bit(fujitsu->keycode3, input->keybit); |
748 | set_bit(KEY_SUSPEND, input->keybit); | 763 | set_bit(fujitsu->keycode4, input->keybit); |
749 | set_bit(KEY_UNKNOWN, input->keybit); | 764 | set_bit(KEY_UNKNOWN, input->keybit); |
750 | 765 | ||
751 | error = input_register_device(input); | 766 | error = input_register_device(input); |
@@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, | |||
833 | irb); | 848 | irb); |
834 | 849 | ||
835 | switch (irb & 0x4ff) { | 850 | switch (irb & 0x4ff) { |
836 | case LOCK_KEY: | 851 | case KEY1_CODE: |
837 | keycode = KEY_SCREENLOCK; | 852 | keycode = fujitsu->keycode1; |
838 | break; | 853 | break; |
839 | case DISPLAY_KEY: | 854 | case KEY2_CODE: |
840 | keycode = KEY_MEDIA; | 855 | keycode = fujitsu->keycode2; |
841 | break; | 856 | break; |
842 | case ENERGY_KEY: | 857 | case KEY3_CODE: |
843 | keycode = KEY_EMAIL; | 858 | keycode = fujitsu->keycode3; |
844 | break; | 859 | break; |
845 | case REST_KEY: | 860 | case KEY4_CODE: |
846 | keycode = KEY_SUSPEND; | 861 | keycode = fujitsu->keycode4; |
847 | break; | 862 | break; |
848 | case 0: | 863 | case 0: |
849 | keycode = 0; | 864 | keycode = 0; |
850 | break; | 865 | break; |
851 | default: | 866 | default: |
852 | vdbg_printk(FUJLAPTOP_DBG_WARN, | 867 | vdbg_printk(FUJLAPTOP_DBG_WARN, |
853 | "Unknown GIRB result [%x]\n", irb); | 868 | "Unknown GIRB result [%x]\n", irb); |
854 | keycode = -1; | 869 | keycode = -1; |
855 | break; | 870 | break; |
856 | } | 871 | } |
@@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, | |||
859 | "Push keycode into ringbuffer [%d]\n", | 874 | "Push keycode into ringbuffer [%d]\n", |
860 | keycode); | 875 | keycode); |
861 | status = kfifo_put(fujitsu_hotkey->fifo, | 876 | status = kfifo_put(fujitsu_hotkey->fifo, |
862 | (unsigned char *)&keycode, | 877 | (unsigned char *)&keycode, |
863 | sizeof(keycode)); | 878 | sizeof(keycode)); |
864 | if (status != sizeof(keycode)) { | 879 | if (status != sizeof(keycode)) { |
865 | vdbg_printk(FUJLAPTOP_DBG_WARN, | 880 | vdbg_printk(FUJLAPTOP_DBG_WARN, |
866 | "Could not push keycode [0x%x]\n", | 881 | "Could not push keycode [0x%x]\n", |
867 | keycode); | 882 | keycode); |
868 | } else { | 883 | } else { |
869 | input_report_key(input, keycode, 1); | 884 | input_report_key(input, keycode, 1); |
870 | input_sync(input); | 885 | input_sync(input); |
@@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, | |||
879 | input_report_key(input, keycode_r, 0); | 894 | input_report_key(input, keycode_r, 0); |
880 | input_sync(input); | 895 | input_sync(input); |
881 | vdbg_printk(FUJLAPTOP_DBG_TRACE, | 896 | vdbg_printk(FUJLAPTOP_DBG_TRACE, |
882 | "Pop keycode from ringbuffer [%d]\n", | 897 | "Pop keycode from ringbuffer [%d]\n", |
883 | keycode_r); | 898 | keycode_r); |
884 | } | 899 | } |
885 | } | 900 | } |
886 | } | 901 | } |
@@ -943,6 +958,11 @@ static int __init fujitsu_init(void) | |||
943 | if (!fujitsu) | 958 | if (!fujitsu) |
944 | return -ENOMEM; | 959 | return -ENOMEM; |
945 | memset(fujitsu, 0, sizeof(struct fujitsu_t)); | 960 | memset(fujitsu, 0, sizeof(struct fujitsu_t)); |
961 | fujitsu->keycode1 = KEY_PROG1; | ||
962 | fujitsu->keycode2 = KEY_PROG2; | ||
963 | fujitsu->keycode3 = KEY_PROG3; | ||
964 | fujitsu->keycode4 = KEY_PROG4; | ||
965 | dmi_check_system(fujitsu_dmi_table); | ||
946 | 966 | ||
947 | result = acpi_bus_register_driver(&acpi_fujitsu_driver); | 967 | result = acpi_bus_register_driver(&acpi_fujitsu_driver); |
948 | if (result < 0) { | 968 | if (result < 0) { |
@@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support"); | |||
1076 | MODULE_VERSION(FUJITSU_DRIVER_VERSION); | 1096 | MODULE_VERSION(FUJITSU_DRIVER_VERSION); |
1077 | MODULE_LICENSE("GPL"); | 1097 | MODULE_LICENSE("GPL"); |
1078 | 1098 | ||
1079 | MODULE_ALIAS | 1099 | MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); |
1080 | ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); | 1100 | MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); |
1081 | MODULE_ALIAS | ||
1082 | ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); | ||
1083 | 1101 | ||
1084 | static struct pnp_device_id pnp_ids[] = { | 1102 | static struct pnp_device_id pnp_ids[] = { |
1085 | { .id = "FUJ02bf" }, | 1103 | {.id = "FUJ02bf"}, |
1086 | { .id = "FUJ02B1" }, | 1104 | {.id = "FUJ02B1"}, |
1087 | { .id = "FUJ02E3" }, | 1105 | {.id = "FUJ02E3"}, |
1088 | { .id = "" } | 1106 | {.id = ""} |
1089 | }; | 1107 | }; |
1108 | |||
1090 | MODULE_DEVICE_TABLE(pnp, pnp_ids); | 1109 | MODULE_DEVICE_TABLE(pnp, pnp_ids); |
diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index 80a136352408..a78274385d54 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c | |||
@@ -57,7 +57,7 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, | |||
57 | { | 57 | { |
58 | struct acpi_device *device = cdev->devdata; | 58 | struct acpi_device *device = cdev->devdata; |
59 | acpi_handle handle = device->handle; | 59 | acpi_handle handle = device->handle; |
60 | unsigned long value; | 60 | unsigned long long value; |
61 | struct acpi_object_list arg_list; | 61 | struct acpi_object_list arg_list; |
62 | union acpi_object arg; | 62 | union acpi_object arg; |
63 | acpi_status status = AE_OK; | 63 | acpi_status status = AE_OK; |
@@ -90,7 +90,7 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev, | |||
90 | { | 90 | { |
91 | struct acpi_device *device = cdev->devdata; | 91 | struct acpi_device *device = cdev->devdata; |
92 | acpi_handle handle = device->handle; | 92 | acpi_handle handle = device->handle; |
93 | unsigned long value; | 93 | unsigned long long value; |
94 | struct acpi_object_list arg_list; | 94 | struct acpi_object_list arg_list; |
95 | union acpi_object arg; | 95 | union acpi_object arg; |
96 | acpi_status status = AE_OK; | 96 | acpi_status status = AE_OK; |
@@ -115,7 +115,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, | |||
115 | struct acpi_object_list arg_list; | 115 | struct acpi_object_list arg_list; |
116 | union acpi_object arg; | 116 | union acpi_object arg; |
117 | acpi_status status; | 117 | acpi_status status; |
118 | int temp; | 118 | unsigned long long temp; |
119 | unsigned long max_state; | 119 | unsigned long max_state; |
120 | 120 | ||
121 | if (memory_get_int_max_bandwidth(cdev, &max_state)) | 121 | if (memory_get_int_max_bandwidth(cdev, &max_state)) |
@@ -131,7 +131,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, | |||
131 | 131 | ||
132 | status = | 132 | status = |
133 | acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list, | 133 | acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list, |
134 | (unsigned long *)&temp); | 134 | &temp); |
135 | 135 | ||
136 | printk(KERN_INFO | 136 | printk(KERN_INFO |
137 | "Bandwidth value was %d: status is %d\n", state, status); | 137 | "Bandwidth value was %d: status is %d\n", state, status); |
@@ -175,7 +175,7 @@ static int intel_menlow_memory_add(struct acpi_device *device) | |||
175 | goto end; | 175 | goto end; |
176 | } | 176 | } |
177 | 177 | ||
178 | acpi_driver_data(device) = cdev; | 178 | device->driver_data = cdev; |
179 | result = sysfs_create_link(&device->dev.kobj, | 179 | result = sysfs_create_link(&device->dev.kobj, |
180 | &cdev->device.kobj, "thermal_cooling"); | 180 | &cdev->device.kobj, "thermal_cooling"); |
181 | if (result) | 181 | if (result) |
@@ -252,7 +252,8 @@ static DEFINE_MUTEX(intel_menlow_attr_lock); | |||
252 | * @auxtype : AUX0/AUX1 | 252 | * @auxtype : AUX0/AUX1 |
253 | * @buf: syfs buffer | 253 | * @buf: syfs buffer |
254 | */ | 254 | */ |
255 | static int sensor_get_auxtrip(acpi_handle handle, int index, int *value) | 255 | static int sensor_get_auxtrip(acpi_handle handle, int index, |
256 | unsigned long long *value) | ||
256 | { | 257 | { |
257 | acpi_status status; | 258 | acpi_status status; |
258 | 259 | ||
@@ -260,7 +261,7 @@ static int sensor_get_auxtrip(acpi_handle handle, int index, int *value) | |||
260 | return -EINVAL; | 261 | return -EINVAL; |
261 | 262 | ||
262 | status = acpi_evaluate_integer(handle, index ? GET_AUX1 : GET_AUX0, | 263 | status = acpi_evaluate_integer(handle, index ? GET_AUX1 : GET_AUX0, |
263 | NULL, (unsigned long *)value); | 264 | NULL, value); |
264 | if (ACPI_FAILURE(status)) | 265 | if (ACPI_FAILURE(status)) |
265 | return -EIO; | 266 | return -EIO; |
266 | 267 | ||
@@ -282,13 +283,13 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value) | |||
282 | struct acpi_object_list args = { | 283 | struct acpi_object_list args = { |
283 | 1, &arg | 284 | 1, &arg |
284 | }; | 285 | }; |
285 | int temp; | 286 | unsigned long long temp; |
286 | 287 | ||
287 | if (index != 0 && index != 1) | 288 | if (index != 0 && index != 1) |
288 | return -EINVAL; | 289 | return -EINVAL; |
289 | 290 | ||
290 | status = acpi_evaluate_integer(handle, index ? GET_AUX0 : GET_AUX1, | 291 | status = acpi_evaluate_integer(handle, index ? GET_AUX0 : GET_AUX1, |
291 | NULL, (unsigned long *)&temp); | 292 | NULL, &temp); |
292 | if (ACPI_FAILURE(status)) | 293 | if (ACPI_FAILURE(status)) |
293 | return -EIO; | 294 | return -EIO; |
294 | if ((index && value < temp) || (!index && value > temp)) | 295 | if ((index && value < temp) || (!index && value > temp)) |
@@ -296,7 +297,7 @@ static int sensor_set_auxtrip(acpi_handle handle, int index, int value) | |||
296 | 297 | ||
297 | arg.integer.value = value; | 298 | arg.integer.value = value; |
298 | status = acpi_evaluate_integer(handle, index ? SET_AUX1 : SET_AUX0, | 299 | status = acpi_evaluate_integer(handle, index ? SET_AUX1 : SET_AUX0, |
299 | &args, (unsigned long *)&temp); | 300 | &args, &temp); |
300 | if (ACPI_FAILURE(status)) | 301 | if (ACPI_FAILURE(status)) |
301 | return -EIO; | 302 | return -EIO; |
302 | 303 | ||
@@ -312,7 +313,7 @@ static ssize_t aux0_show(struct device *dev, | |||
312 | struct device_attribute *dev_attr, char *buf) | 313 | struct device_attribute *dev_attr, char *buf) |
313 | { | 314 | { |
314 | struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); | 315 | struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); |
315 | int value; | 316 | unsigned long long value; |
316 | int result; | 317 | int result; |
317 | 318 | ||
318 | result = sensor_get_auxtrip(attr->handle, 0, &value); | 319 | result = sensor_get_auxtrip(attr->handle, 0, &value); |
@@ -324,7 +325,7 @@ static ssize_t aux1_show(struct device *dev, | |||
324 | struct device_attribute *dev_attr, char *buf) | 325 | struct device_attribute *dev_attr, char *buf) |
325 | { | 326 | { |
326 | struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); | 327 | struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); |
327 | int value; | 328 | unsigned long long value; |
328 | int result; | 329 | int result; |
329 | 330 | ||
330 | result = sensor_get_auxtrip(attr->handle, 1, &value); | 331 | result = sensor_get_auxtrip(attr->handle, 1, &value); |
@@ -376,7 +377,7 @@ static ssize_t bios_enabled_show(struct device *dev, | |||
376 | struct device_attribute *attr, char *buf) | 377 | struct device_attribute *attr, char *buf) |
377 | { | 378 | { |
378 | acpi_status status; | 379 | acpi_status status; |
379 | unsigned long bios_enabled; | 380 | unsigned long long bios_enabled; |
380 | 381 | ||
381 | status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &bios_enabled); | 382 | status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &bios_enabled); |
382 | if (ACPI_FAILURE(status)) | 383 | if (ACPI_FAILURE(status)) |
@@ -492,7 +493,7 @@ static int __init intel_menlow_module_init(void) | |||
492 | { | 493 | { |
493 | int result = -ENODEV; | 494 | int result = -ENODEV; |
494 | acpi_status status; | 495 | acpi_status status; |
495 | unsigned long enable; | 496 | unsigned long long enable; |
496 | 497 | ||
497 | if (acpi_disabled) | 498 | if (acpi_disabled) |
498 | return result; | 499 | return result; |
diff --git a/drivers/misc/panasonic-laptop.c b/drivers/misc/panasonic-laptop.c new file mode 100644 index 000000000000..a2cb598d8ab5 --- /dev/null +++ b/drivers/misc/panasonic-laptop.c | |||
@@ -0,0 +1,767 @@ | |||
1 | /* | ||
2 | * Panasonic HotKey and LCD brightness control driver | ||
3 | * (C) 2004 Hiroshi Miura <miura@da-cha.org> | ||
4 | * (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/ | ||
5 | * (C) YOKOTA Hiroshi <yokota (at) netlab. is. tsukuba. ac. jp> | ||
6 | * (C) 2004 David Bronaugh <dbronaugh> | ||
7 | * (C) 2006-2008 Harald Welte <laforge@gnumonks.org> | ||
8 | * | ||
9 | * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * publicshed by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | *--------------------------------------------------------------------------- | ||
25 | * | ||
26 | * ChangeLog: | ||
27 | * Sep.23, 2008 Harald Welte <laforge@gnumonks.org> | ||
28 | * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to | ||
29 | * drivers/misc/panasonic-laptop.c | ||
30 | * | ||
31 | * Jul.04, 2008 Harald Welte <laforge@gnumonks.org> | ||
32 | * -v0.94 replace /proc interface with device attributes | ||
33 | * support {set,get}keycode on th input device | ||
34 | * | ||
35 | * Jun.27, 2008 Harald Welte <laforge@gnumonks.org> | ||
36 | * -v0.92 merge with 2.6.26-rc6 input API changes | ||
37 | * remove broken <= 2.6.15 kernel support | ||
38 | * resolve all compiler warnings | ||
39 | * various coding style fixes (checkpatch.pl) | ||
40 | * add support for backlight api | ||
41 | * major code restructuring | ||
42 | * | ||
43 | * Dac.28, 2007 Harald Welte <laforge@gnumonks.org> | ||
44 | * -v0.91 merge with 2.6.24-rc6 ACPI changes | ||
45 | * | ||
46 | * Nov.04, 2006 Hiroshi Miura <miura@da-cha.org> | ||
47 | * -v0.9 remove warning about section reference. | ||
48 | * remove acpi_os_free | ||
49 | * add /proc/acpi/pcc/brightness interface for HAL access | ||
50 | * merge dbronaugh's enhancement | ||
51 | * Aug.17, 2004 David Bronaugh (dbronaugh) | ||
52 | * - Added screen brightness setting interface | ||
53 | * Thanks to FreeBSD crew (acpi_panasonic.c) | ||
54 | * for the ideas I needed to accomplish it | ||
55 | * | ||
56 | * May.29, 2006 Hiroshi Miura <miura@da-cha.org> | ||
57 | * -v0.8.4 follow to change keyinput structure | ||
58 | * thanks Fabian Yamaguchi <fabs@cs.tu-berlin.de>, | ||
59 | * Jacob Bower <jacob.bower@ic.ac.uk> and | ||
60 | * Hiroshi Yokota for providing solutions. | ||
61 | * | ||
62 | * Oct.02, 2004 Hiroshi Miura <miura@da-cha.org> | ||
63 | * -v0.8.2 merge code of YOKOTA Hiroshi | ||
64 | * <yokota@netlab.is.tsukuba.ac.jp>. | ||
65 | * Add sticky key mode interface. | ||
66 | * Refactoring acpi_pcc_generate_keyinput(). | ||
67 | * | ||
68 | * Sep.15, 2004 Hiroshi Miura <miura@da-cha.org> | ||
69 | * -v0.8 Generate key input event on input subsystem. | ||
70 | * This is based on yet another driver written by | ||
71 | * Ryuta Nakanishi. | ||
72 | * | ||
73 | * Sep.10, 2004 Hiroshi Miura <miura@da-cha.org> | ||
74 | * -v0.7 Change proc interface functions using seq_file | ||
75 | * facility as same as other ACPI drivers. | ||
76 | * | ||
77 | * Aug.28, 2004 Hiroshi Miura <miura@da-cha.org> | ||
78 | * -v0.6.4 Fix a silly error with status checking | ||
79 | * | ||
80 | * Aug.25, 2004 Hiroshi Miura <miura@da-cha.org> | ||
81 | * -v0.6.3 replace read_acpi_int by standard function | ||
82 | * acpi_evaluate_integer | ||
83 | * some clean up and make smart copyright notice. | ||
84 | * fix return value of pcc_acpi_get_key() | ||
85 | * fix checking return value of acpi_bus_register_driver() | ||
86 | * | ||
87 | * Aug.22, 2004 David Bronaugh <dbronaugh@linuxboxen.org> | ||
88 | * -v0.6.2 Add check on ACPI data (num_sifr) | ||
89 | * Coding style cleanups, better error messages/handling | ||
90 | * Fixed an off-by-one error in memory allocation | ||
91 | * | ||
92 | * Aug.21, 2004 David Bronaugh <dbronaugh@linuxboxen.org> | ||
93 | * -v0.6.1 Fix a silly error with status checking | ||
94 | * | ||
95 | * Aug.20, 2004 David Bronaugh <dbronaugh@linuxboxen.org> | ||
96 | * - v0.6 Correct brightness controls to reflect reality | ||
97 | * based on information gleaned by Hiroshi Miura | ||
98 | * and discussions with Hiroshi Miura | ||
99 | * | ||
100 | * Aug.10, 2004 Hiroshi Miura <miura@da-cha.org> | ||
101 | * - v0.5 support LCD brightness control | ||
102 | * based on the disclosed information by MEI. | ||
103 | * | ||
104 | * Jul.25, 2004 Hiroshi Miura <miura@da-cha.org> | ||
105 | * - v0.4 first post version | ||
106 | * add function to retrive SIFR | ||
107 | * | ||
108 | * Jul.24, 2004 Hiroshi Miura <miura@da-cha.org> | ||
109 | * - v0.3 get proper status of hotkey | ||
110 | * | ||
111 | * Jul.22, 2004 Hiroshi Miura <miura@da-cha.org> | ||
112 | * - v0.2 add HotKey handler | ||
113 | * | ||
114 | * Jul.17, 2004 Hiroshi Miura <miura@da-cha.org> | ||
115 | * - v0.1 start from toshiba_acpi driver written by John Belmonte | ||
116 | * | ||
117 | */ | ||
118 | |||
119 | #include <linux/version.h> | ||
120 | #include <linux/kernel.h> | ||
121 | #include <linux/module.h> | ||
122 | #include <linux/init.h> | ||
123 | #include <linux/types.h> | ||
124 | #include <linux/backlight.h> | ||
125 | #include <linux/ctype.h> | ||
126 | #include <linux/seq_file.h> | ||
127 | #include <linux/uaccess.h> | ||
128 | #include <acpi/acpi_bus.h> | ||
129 | #include <acpi/acpi_drivers.h> | ||
130 | #include <linux/input.h> | ||
131 | |||
132 | |||
133 | #ifndef ACPI_HOTKEY_COMPONENT | ||
134 | #define ACPI_HOTKEY_COMPONENT 0x10000000 | ||
135 | #endif | ||
136 | |||
137 | #define _COMPONENT ACPI_HOTKEY_COMPONENT | ||
138 | |||
139 | MODULE_AUTHOR("Hiroshi Miura, David Bronaugh and Harald Welte"); | ||
140 | MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops"); | ||
141 | MODULE_LICENSE("GPL"); | ||
142 | |||
143 | #define LOGPREFIX "pcc_acpi: " | ||
144 | |||
145 | /* Define ACPI PATHs */ | ||
146 | /* Lets note hotkeys */ | ||
147 | #define METHOD_HKEY_QUERY "HINF" | ||
148 | #define METHOD_HKEY_SQTY "SQTY" | ||
149 | #define METHOD_HKEY_SINF "SINF" | ||
150 | #define METHOD_HKEY_SSET "SSET" | ||
151 | #define HKEY_NOTIFY 0x80 | ||
152 | |||
153 | #define ACPI_PCC_DRIVER_NAME "Panasonic Laptop Support" | ||
154 | #define ACPI_PCC_DEVICE_NAME "Hotkey" | ||
155 | #define ACPI_PCC_CLASS "pcc" | ||
156 | |||
157 | #define ACPI_PCC_INPUT_PHYS "panasonic/hkey0" | ||
158 | |||
159 | /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent | ||
160 | ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 | ||
161 | */ | ||
162 | enum SINF_BITS { SINF_NUM_BATTERIES = 0, | ||
163 | SINF_LCD_TYPE, | ||
164 | SINF_AC_MAX_BRIGHT, | ||
165 | SINF_AC_MIN_BRIGHT, | ||
166 | SINF_AC_CUR_BRIGHT, | ||
167 | SINF_DC_MAX_BRIGHT, | ||
168 | SINF_DC_MIN_BRIGHT, | ||
169 | SINF_DC_CUR_BRIGHT, | ||
170 | SINF_MUTE, | ||
171 | SINF_RESERVED, | ||
172 | SINF_ENV_STATE, | ||
173 | SINF_STICKY_KEY = 0x80, | ||
174 | }; | ||
175 | /* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */ | ||
176 | |||
177 | static int acpi_pcc_hotkey_add(struct acpi_device *device); | ||
178 | static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type); | ||
179 | static int acpi_pcc_hotkey_resume(struct acpi_device *device); | ||
180 | |||
181 | static const struct acpi_device_id pcc_device_ids[] = { | ||
182 | { "MAT0012", 0}, | ||
183 | { "MAT0013", 0}, | ||
184 | { "MAT0018", 0}, | ||
185 | { "MAT0019", 0}, | ||
186 | { "", 0}, | ||
187 | }; | ||
188 | |||
189 | static struct acpi_driver acpi_pcc_driver = { | ||
190 | .name = ACPI_PCC_DRIVER_NAME, | ||
191 | .class = ACPI_PCC_CLASS, | ||
192 | .ids = pcc_device_ids, | ||
193 | .ops = { | ||
194 | .add = acpi_pcc_hotkey_add, | ||
195 | .remove = acpi_pcc_hotkey_remove, | ||
196 | .resume = acpi_pcc_hotkey_resume, | ||
197 | }, | ||
198 | }; | ||
199 | |||
200 | #define KEYMAP_SIZE 11 | ||
201 | static const int initial_keymap[KEYMAP_SIZE] = { | ||
202 | /* 0 */ KEY_RESERVED, | ||
203 | /* 1 */ KEY_BRIGHTNESSDOWN, | ||
204 | /* 2 */ KEY_BRIGHTNESSUP, | ||
205 | /* 3 */ KEY_DISPLAYTOGGLE, | ||
206 | /* 4 */ KEY_MUTE, | ||
207 | /* 5 */ KEY_VOLUMEDOWN, | ||
208 | /* 6 */ KEY_VOLUMEUP, | ||
209 | /* 7 */ KEY_SLEEP, | ||
210 | /* 8 */ KEY_PROG1, /* Change CPU boost */ | ||
211 | /* 9 */ KEY_BATTERY, | ||
212 | /* 10 */ KEY_SUSPEND, | ||
213 | }; | ||
214 | |||
215 | struct pcc_acpi { | ||
216 | acpi_handle handle; | ||
217 | unsigned long num_sifr; | ||
218 | int sticky_mode; | ||
219 | u32 *sinf; | ||
220 | struct acpi_device *device; | ||
221 | struct input_dev *input_dev; | ||
222 | struct backlight_device *backlight; | ||
223 | int keymap[KEYMAP_SIZE]; | ||
224 | }; | ||
225 | |||
226 | struct pcc_keyinput { | ||
227 | struct acpi_hotkey *hotkey; | ||
228 | }; | ||
229 | |||
230 | /* method access functions */ | ||
231 | static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val) | ||
232 | { | ||
233 | union acpi_object in_objs[] = { | ||
234 | { .integer.type = ACPI_TYPE_INTEGER, | ||
235 | .integer.value = func, }, | ||
236 | { .integer.type = ACPI_TYPE_INTEGER, | ||
237 | .integer.value = val, }, | ||
238 | }; | ||
239 | struct acpi_object_list params = { | ||
240 | .count = ARRAY_SIZE(in_objs), | ||
241 | .pointer = in_objs, | ||
242 | }; | ||
243 | acpi_status status = AE_OK; | ||
244 | |||
245 | ACPI_FUNCTION_TRACE("acpi_pcc_write_sset"); | ||
246 | |||
247 | status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET, | ||
248 | ¶ms, NULL); | ||
249 | |||
250 | return status == AE_OK; | ||
251 | } | ||
252 | |||
253 | static inline int acpi_pcc_get_sqty(struct acpi_device *device) | ||
254 | { | ||
255 | unsigned long long s; | ||
256 | acpi_status status; | ||
257 | |||
258 | ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty"); | ||
259 | |||
260 | status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY, | ||
261 | NULL, &s); | ||
262 | if (ACPI_SUCCESS(status)) | ||
263 | return s; | ||
264 | else { | ||
265 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
266 | "evaluation error HKEY.SQTY\n")); | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf) | ||
272 | { | ||
273 | acpi_status status; | ||
274 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
275 | union acpi_object *hkey = NULL; | ||
276 | int i; | ||
277 | |||
278 | ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata"); | ||
279 | |||
280 | status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, 0, | ||
281 | &buffer); | ||
282 | if (ACPI_FAILURE(status)) { | ||
283 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
284 | "evaluation error HKEY.SINF\n")); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | hkey = buffer.pointer; | ||
289 | if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { | ||
290 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); | ||
291 | goto end; | ||
292 | } | ||
293 | |||
294 | if (pcc->num_sifr < hkey->package.count) { | ||
295 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
296 | "SQTY reports bad SINF length\n")); | ||
297 | status = AE_ERROR; | ||
298 | goto end; | ||
299 | } | ||
300 | |||
301 | for (i = 0; i < hkey->package.count; i++) { | ||
302 | union acpi_object *element = &(hkey->package.elements[i]); | ||
303 | if (likely(element->type == ACPI_TYPE_INTEGER)) { | ||
304 | sinf[i] = element->integer.value; | ||
305 | } else | ||
306 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
307 | "Invalid HKEY.SINF data\n")); | ||
308 | } | ||
309 | sinf[hkey->package.count] = -1; | ||
310 | |||
311 | end: | ||
312 | kfree(buffer.pointer); | ||
313 | return status == AE_OK; | ||
314 | } | ||
315 | |||
316 | /* backlight API interface functions */ | ||
317 | |||
318 | /* This driver currently treats AC and DC brightness identical, | ||
319 | * since we don't need to invent an interface to the core ACPI | ||
320 | * logic to receive events in case a power supply is plugged in | ||
321 | * or removed */ | ||
322 | |||
323 | static int bl_get(struct backlight_device *bd) | ||
324 | { | ||
325 | struct pcc_acpi *pcc = bl_get_data(bd); | ||
326 | |||
327 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | ||
328 | return -EIO; | ||
329 | |||
330 | return pcc->sinf[SINF_AC_CUR_BRIGHT]; | ||
331 | } | ||
332 | |||
333 | static int bl_set_status(struct backlight_device *bd) | ||
334 | { | ||
335 | struct pcc_acpi *pcc = bl_get_data(bd); | ||
336 | int bright = bd->props.brightness; | ||
337 | int rc; | ||
338 | |||
339 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | ||
340 | return -EIO; | ||
341 | |||
342 | if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT]) | ||
343 | bright = pcc->sinf[SINF_AC_MIN_BRIGHT]; | ||
344 | |||
345 | if (bright < pcc->sinf[SINF_DC_MIN_BRIGHT]) | ||
346 | bright = pcc->sinf[SINF_DC_MIN_BRIGHT]; | ||
347 | |||
348 | if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT] || | ||
349 | bright > pcc->sinf[SINF_AC_MAX_BRIGHT]) | ||
350 | return -EINVAL; | ||
351 | |||
352 | rc = acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, bright); | ||
353 | if (rc < 0) | ||
354 | return rc; | ||
355 | |||
356 | return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright); | ||
357 | } | ||
358 | |||
359 | static struct backlight_ops pcc_backlight_ops = { | ||
360 | .get_brightness = bl_get, | ||
361 | .update_status = bl_set_status, | ||
362 | }; | ||
363 | |||
364 | |||
365 | /* sysfs user interface functions */ | ||
366 | |||
367 | static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr, | ||
368 | char *buf) | ||
369 | { | ||
370 | struct acpi_device *acpi = to_acpi_device(dev); | ||
371 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | ||
372 | |||
373 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | ||
374 | return -EIO; | ||
375 | |||
376 | return sprintf(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); | ||
377 | } | ||
378 | |||
379 | static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr, | ||
380 | char *buf) | ||
381 | { | ||
382 | struct acpi_device *acpi = to_acpi_device(dev); | ||
383 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | ||
384 | |||
385 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | ||
386 | return -EIO; | ||
387 | |||
388 | return sprintf(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]); | ||
389 | } | ||
390 | |||
391 | static ssize_t show_mute(struct device *dev, struct device_attribute *attr, | ||
392 | char *buf) | ||
393 | { | ||
394 | struct acpi_device *acpi = to_acpi_device(dev); | ||
395 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | ||
396 | |||
397 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | ||
398 | return -EIO; | ||
399 | |||
400 | return sprintf(buf, "%u\n", pcc->sinf[SINF_MUTE]); | ||
401 | } | ||
402 | |||
403 | static ssize_t show_sticky(struct device *dev, struct device_attribute *attr, | ||
404 | char *buf) | ||
405 | { | ||
406 | struct acpi_device *acpi = to_acpi_device(dev); | ||
407 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | ||
408 | |||
409 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | ||
410 | return -EIO; | ||
411 | |||
412 | return sprintf(buf, "%u\n", pcc->sinf[SINF_STICKY_KEY]); | ||
413 | } | ||
414 | |||
415 | static ssize_t set_sticky(struct device *dev, struct device_attribute *attr, | ||
416 | const char *buf, size_t count) | ||
417 | { | ||
418 | struct acpi_device *acpi = to_acpi_device(dev); | ||
419 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | ||
420 | int val; | ||
421 | |||
422 | if (count && sscanf(buf, "%i", &val) == 1 && | ||
423 | (val == 0 || val == 1)) { | ||
424 | acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, val); | ||
425 | pcc->sticky_mode = val; | ||
426 | } | ||
427 | |||
428 | return count; | ||
429 | } | ||
430 | |||
431 | static DEVICE_ATTR(numbatt, S_IRUGO, show_numbatt, NULL); | ||
432 | static DEVICE_ATTR(lcdtype, S_IRUGO, show_lcdtype, NULL); | ||
433 | static DEVICE_ATTR(mute, S_IRUGO, show_mute, NULL); | ||
434 | static DEVICE_ATTR(sticky_key, S_IRUGO | S_IWUSR, show_sticky, set_sticky); | ||
435 | |||
436 | static struct attribute *pcc_sysfs_entries[] = { | ||
437 | &dev_attr_numbatt.attr, | ||
438 | &dev_attr_lcdtype.attr, | ||
439 | &dev_attr_mute.attr, | ||
440 | &dev_attr_sticky_key.attr, | ||
441 | NULL, | ||
442 | }; | ||
443 | |||
444 | static struct attribute_group pcc_attr_group = { | ||
445 | .name = NULL, /* put in device directory */ | ||
446 | .attrs = pcc_sysfs_entries, | ||
447 | }; | ||
448 | |||
449 | |||
450 | /* hotkey input device driver */ | ||
451 | |||
452 | static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
453 | { | ||
454 | struct pcc_acpi *pcc = input_get_drvdata(dev); | ||
455 | |||
456 | if (scancode >= ARRAY_SIZE(pcc->keymap)) | ||
457 | return -EINVAL; | ||
458 | |||
459 | *keycode = pcc->keymap[scancode]; | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) | ||
465 | { | ||
466 | int i; | ||
467 | |||
468 | for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) { | ||
469 | if (pcc->keymap[i] == keycode) | ||
470 | return i+1; | ||
471 | } | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) | ||
477 | { | ||
478 | struct pcc_acpi *pcc = input_get_drvdata(dev); | ||
479 | int oldkeycode; | ||
480 | |||
481 | if (scancode >= ARRAY_SIZE(pcc->keymap)) | ||
482 | return -EINVAL; | ||
483 | |||
484 | if (keycode < 0 || keycode > KEY_MAX) | ||
485 | return -EINVAL; | ||
486 | |||
487 | oldkeycode = pcc->keymap[scancode]; | ||
488 | pcc->keymap[scancode] = keycode; | ||
489 | |||
490 | set_bit(keycode, dev->keybit); | ||
491 | |||
492 | if (!keymap_get_by_keycode(pcc, oldkeycode)) | ||
493 | clear_bit(oldkeycode, dev->keybit); | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) | ||
499 | { | ||
500 | struct input_dev *hotk_input_dev = pcc->input_dev; | ||
501 | int rc; | ||
502 | int key_code, hkey_num; | ||
503 | unsigned long long result; | ||
504 | |||
505 | ACPI_FUNCTION_TRACE("acpi_pcc_generate_keyinput"); | ||
506 | |||
507 | rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, | ||
508 | NULL, &result); | ||
509 | if (!ACPI_SUCCESS(rc)) { | ||
510 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
511 | "error getting hotkey status\n")); | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); | ||
516 | |||
517 | hkey_num = result & 0xf; | ||
518 | |||
519 | if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) { | ||
520 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
521 | "hotkey number out of range: %d\n", | ||
522 | hkey_num)); | ||
523 | return; | ||
524 | } | ||
525 | |||
526 | key_code = pcc->keymap[hkey_num]; | ||
527 | |||
528 | if (key_code != KEY_RESERVED) { | ||
529 | int pushed = (result & 0x80) ? TRUE : FALSE; | ||
530 | |||
531 | input_report_key(hotk_input_dev, key_code, pushed); | ||
532 | input_sync(hotk_input_dev); | ||
533 | } | ||
534 | |||
535 | return; | ||
536 | } | ||
537 | |||
538 | static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) | ||
539 | { | ||
540 | struct pcc_acpi *pcc = (struct pcc_acpi *) data; | ||
541 | |||
542 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_notify"); | ||
543 | |||
544 | switch (event) { | ||
545 | case HKEY_NOTIFY: | ||
546 | acpi_pcc_generate_keyinput(pcc); | ||
547 | break; | ||
548 | default: | ||
549 | /* nothing to do */ | ||
550 | break; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | static int acpi_pcc_init_input(struct pcc_acpi *pcc) | ||
555 | { | ||
556 | int i, rc; | ||
557 | |||
558 | ACPI_FUNCTION_TRACE("acpi_pcc_init_input"); | ||
559 | |||
560 | pcc->input_dev = input_allocate_device(); | ||
561 | if (!pcc->input_dev) { | ||
562 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
563 | "Couldn't allocate input device for hotkey")); | ||
564 | return -ENOMEM; | ||
565 | } | ||
566 | |||
567 | pcc->input_dev->evbit[0] = BIT(EV_KEY); | ||
568 | |||
569 | pcc->input_dev->name = ACPI_PCC_DRIVER_NAME; | ||
570 | pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS; | ||
571 | pcc->input_dev->id.bustype = BUS_HOST; | ||
572 | pcc->input_dev->id.vendor = 0x0001; | ||
573 | pcc->input_dev->id.product = 0x0001; | ||
574 | pcc->input_dev->id.version = 0x0100; | ||
575 | pcc->input_dev->getkeycode = pcc_getkeycode; | ||
576 | pcc->input_dev->setkeycode = pcc_setkeycode; | ||
577 | |||
578 | /* load initial keymap */ | ||
579 | memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap)); | ||
580 | |||
581 | for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) | ||
582 | __set_bit(pcc->keymap[i], pcc->input_dev->keybit); | ||
583 | __clear_bit(KEY_RESERVED, pcc->input_dev->keybit); | ||
584 | |||
585 | input_set_drvdata(pcc->input_dev, pcc); | ||
586 | |||
587 | rc = input_register_device(pcc->input_dev); | ||
588 | if (rc < 0) | ||
589 | input_free_device(pcc->input_dev); | ||
590 | |||
591 | return rc; | ||
592 | } | ||
593 | |||
594 | /* kernel module interface */ | ||
595 | |||
596 | static int acpi_pcc_hotkey_resume(struct acpi_device *device) | ||
597 | { | ||
598 | struct pcc_acpi *pcc = acpi_driver_data(device); | ||
599 | acpi_status status = AE_OK; | ||
600 | |||
601 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume"); | ||
602 | |||
603 | if (device == NULL || pcc == NULL) | ||
604 | return -EINVAL; | ||
605 | |||
606 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n", | ||
607 | pcc->sticky_mode)); | ||
608 | |||
609 | status = acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode); | ||
610 | |||
611 | return status == AE_OK ? 0 : -EINVAL; | ||
612 | } | ||
613 | |||
614 | static int acpi_pcc_hotkey_add(struct acpi_device *device) | ||
615 | { | ||
616 | acpi_status status; | ||
617 | struct pcc_acpi *pcc; | ||
618 | int num_sifr, result; | ||
619 | |||
620 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add"); | ||
621 | |||
622 | if (!device) | ||
623 | return -EINVAL; | ||
624 | |||
625 | num_sifr = acpi_pcc_get_sqty(device); | ||
626 | |||
627 | if (num_sifr > 255) { | ||
628 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large")); | ||
629 | return -ENODEV; | ||
630 | } | ||
631 | |||
632 | pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL); | ||
633 | if (!pcc) { | ||
634 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
635 | "Couldn't allocate mem for pcc")); | ||
636 | return -ENOMEM; | ||
637 | } | ||
638 | |||
639 | pcc->sinf = kzalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL); | ||
640 | if (!pcc->sinf) { | ||
641 | result = -ENOMEM; | ||
642 | goto out_hotkey; | ||
643 | } | ||
644 | |||
645 | pcc->device = device; | ||
646 | pcc->handle = device->handle; | ||
647 | pcc->num_sifr = num_sifr; | ||
648 | device->driver_data = pcc; | ||
649 | strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); | ||
650 | strcpy(acpi_device_class(device), ACPI_PCC_CLASS); | ||
651 | |||
652 | result = acpi_pcc_init_input(pcc); | ||
653 | if (result) { | ||
654 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
655 | "Error installing keyinput handler\n")); | ||
656 | goto out_sinf; | ||
657 | } | ||
658 | |||
659 | /* initialize hotkey input device */ | ||
660 | status = acpi_install_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY, | ||
661 | acpi_pcc_hotkey_notify, pcc); | ||
662 | |||
663 | if (ACPI_FAILURE(status)) { | ||
664 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
665 | "Error installing notify handler\n")); | ||
666 | result = -ENODEV; | ||
667 | goto out_input; | ||
668 | } | ||
669 | |||
670 | /* initialize backlight */ | ||
671 | pcc->backlight = backlight_device_register("panasonic", NULL, pcc, | ||
672 | &pcc_backlight_ops); | ||
673 | if (IS_ERR(pcc->backlight)) | ||
674 | goto out_notify; | ||
675 | |||
676 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { | ||
677 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
678 | "Couldn't retrieve BIOS data\n")); | ||
679 | goto out_backlight; | ||
680 | } | ||
681 | |||
682 | /* read the initial brightness setting from the hardware */ | ||
683 | pcc->backlight->props.max_brightness = | ||
684 | pcc->sinf[SINF_AC_MAX_BRIGHT]; | ||
685 | pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT]; | ||
686 | |||
687 | /* read the initial sticky key mode from the hardware */ | ||
688 | pcc->sticky_mode = pcc->sinf[SINF_STICKY_KEY]; | ||
689 | |||
690 | /* add sysfs attributes */ | ||
691 | result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group); | ||
692 | if (result) | ||
693 | goto out_backlight; | ||
694 | |||
695 | return 0; | ||
696 | |||
697 | out_backlight: | ||
698 | backlight_device_unregister(pcc->backlight); | ||
699 | out_notify: | ||
700 | acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY, | ||
701 | acpi_pcc_hotkey_notify); | ||
702 | out_input: | ||
703 | input_unregister_device(pcc->input_dev); | ||
704 | /* no need to input_free_device() since core input API refcount and | ||
705 | * free()s the device */ | ||
706 | out_sinf: | ||
707 | kfree(pcc->sinf); | ||
708 | out_hotkey: | ||
709 | kfree(pcc); | ||
710 | |||
711 | return result; | ||
712 | } | ||
713 | |||
714 | static int __init acpi_pcc_init(void) | ||
715 | { | ||
716 | int result = 0; | ||
717 | |||
718 | ACPI_FUNCTION_TRACE("acpi_pcc_init"); | ||
719 | |||
720 | if (acpi_disabled) | ||
721 | return -ENODEV; | ||
722 | |||
723 | result = acpi_bus_register_driver(&acpi_pcc_driver); | ||
724 | if (result < 0) { | ||
725 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
726 | "Error registering hotkey driver\n")); | ||
727 | return -ENODEV; | ||
728 | } | ||
729 | |||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) | ||
734 | { | ||
735 | struct pcc_acpi *pcc = acpi_driver_data(device); | ||
736 | |||
737 | ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove"); | ||
738 | |||
739 | if (!device || !pcc) | ||
740 | return -EINVAL; | ||
741 | |||
742 | sysfs_remove_group(&device->dev.kobj, &pcc_attr_group); | ||
743 | |||
744 | backlight_device_unregister(pcc->backlight); | ||
745 | |||
746 | acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY, | ||
747 | acpi_pcc_hotkey_notify); | ||
748 | |||
749 | input_unregister_device(pcc->input_dev); | ||
750 | /* no need to input_free_device() since core input API refcount and | ||
751 | * free()s the device */ | ||
752 | |||
753 | kfree(pcc->sinf); | ||
754 | kfree(pcc); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static void __exit acpi_pcc_exit(void) | ||
760 | { | ||
761 | ACPI_FUNCTION_TRACE("acpi_pcc_exit"); | ||
762 | |||
763 | acpi_bus_unregister_driver(&acpi_pcc_driver); | ||
764 | } | ||
765 | |||
766 | module_init(acpi_pcc_init); | ||
767 | module_exit(acpi_pcc_exit); | ||
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 60775be22822..5a97d3a9d745 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
@@ -970,7 +970,7 @@ static int sony_nc_resume(struct acpi_device *device) | |||
970 | /* set the last requested brightness level */ | 970 | /* set the last requested brightness level */ |
971 | if (sony_backlight_device && | 971 | if (sony_backlight_device && |
972 | !sony_backlight_update_status(sony_backlight_device)) | 972 | !sony_backlight_update_status(sony_backlight_device)) |
973 | printk(KERN_WARNING DRV_PFX "unable to restore brightness level"); | 973 | printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); |
974 | 974 | ||
975 | /* re-initialize models with specific requirements */ | 975 | /* re-initialize models with specific requirements */ |
976 | dmi_check_system(sony_nc_ids); | 976 | dmi_check_system(sony_nc_ids); |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 6b9300779a43..4db1cf9078d9 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -159,7 +159,6 @@ enum { | |||
159 | #define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG | 159 | #define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG |
160 | 160 | ||
161 | #define TPACPI_DBG_ALL 0xffff | 161 | #define TPACPI_DBG_ALL 0xffff |
162 | #define TPACPI_DBG_ALL 0xffff | ||
163 | #define TPACPI_DBG_INIT 0x0001 | 162 | #define TPACPI_DBG_INIT 0x0001 |
164 | #define TPACPI_DBG_EXIT 0x0002 | 163 | #define TPACPI_DBG_EXIT 0x0002 |
165 | #define dbg_printk(a_dbg_level, format, arg...) \ | 164 | #define dbg_printk(a_dbg_level, format, arg...) \ |
@@ -543,7 +542,7 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm) | |||
543 | return -ENODEV; | 542 | return -ENODEV; |
544 | } | 543 | } |
545 | 544 | ||
546 | acpi_driver_data(ibm->acpi->device) = ibm; | 545 | ibm->acpi->device->driver_data = ibm; |
547 | sprintf(acpi_device_class(ibm->acpi->device), "%s/%s", | 546 | sprintf(acpi_device_class(ibm->acpi->device), "%s/%s", |
548 | TPACPI_ACPI_EVENT_PREFIX, | 547 | TPACPI_ACPI_EVENT_PREFIX, |
549 | ibm->name); | 548 | ibm->name); |
@@ -582,7 +581,8 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm) | |||
582 | 581 | ||
583 | ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL); | 582 | ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL); |
584 | if (!ibm->acpi->driver) { | 583 | if (!ibm->acpi->driver) { |
585 | printk(TPACPI_ERR "kzalloc(ibm->driver) failed\n"); | 584 | printk(TPACPI_ERR |
585 | "failed to allocate memory for ibm->acpi->driver\n"); | ||
586 | return -ENOMEM; | 586 | return -ENOMEM; |
587 | } | 587 | } |
588 | 588 | ||
@@ -838,6 +838,13 @@ static int parse_strtoul(const char *buf, | |||
838 | return 0; | 838 | return 0; |
839 | } | 839 | } |
840 | 840 | ||
841 | static void tpacpi_disable_brightness_delay(void) | ||
842 | { | ||
843 | if (acpi_evalf(hkey_handle, NULL, "PWMS", "qvd", 0)) | ||
844 | printk(TPACPI_NOTICE | ||
845 | "ACPI backlight control delay disabled\n"); | ||
846 | } | ||
847 | |||
841 | static int __init tpacpi_query_bcl_levels(acpi_handle handle) | 848 | static int __init tpacpi_query_bcl_levels(acpi_handle handle) |
842 | { | 849 | { |
843 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 850 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
@@ -2139,6 +2146,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2139 | if (!tp_features.hotkey) | 2146 | if (!tp_features.hotkey) |
2140 | return 1; | 2147 | return 1; |
2141 | 2148 | ||
2149 | tpacpi_disable_brightness_delay(); | ||
2150 | |||
2142 | hotkey_dev_attributes = create_attr_set(13, NULL); | 2151 | hotkey_dev_attributes = create_attr_set(13, NULL); |
2143 | if (!hotkey_dev_attributes) | 2152 | if (!hotkey_dev_attributes) |
2144 | return -ENOMEM; | 2153 | return -ENOMEM; |
@@ -2512,6 +2521,8 @@ static void hotkey_suspend(pm_message_t state) | |||
2512 | 2521 | ||
2513 | static void hotkey_resume(void) | 2522 | static void hotkey_resume(void) |
2514 | { | 2523 | { |
2524 | tpacpi_disable_brightness_delay(); | ||
2525 | |||
2515 | if (hotkey_mask_get()) | 2526 | if (hotkey_mask_get()) |
2516 | printk(TPACPI_ERR | 2527 | printk(TPACPI_ERR |
2517 | "error while trying to read hot key mask " | 2528 | "error while trying to read hot key mask " |
@@ -5983,6 +5994,52 @@ static void fan_exit(void) | |||
5983 | flush_workqueue(tpacpi_wq); | 5994 | flush_workqueue(tpacpi_wq); |
5984 | } | 5995 | } |
5985 | 5996 | ||
5997 | static void fan_suspend(pm_message_t state) | ||
5998 | { | ||
5999 | if (!fan_control_allowed) | ||
6000 | return; | ||
6001 | |||
6002 | /* Store fan status in cache */ | ||
6003 | fan_get_status_safe(NULL); | ||
6004 | if (tp_features.fan_ctrl_status_undef) | ||
6005 | fan_control_desired_level = TP_EC_FAN_AUTO; | ||
6006 | } | ||
6007 | |||
6008 | static void fan_resume(void) | ||
6009 | { | ||
6010 | u8 saved_fan_level; | ||
6011 | u8 current_level = 7; | ||
6012 | bool do_set = false; | ||
6013 | |||
6014 | /* DSDT *always* updates status on resume */ | ||
6015 | tp_features.fan_ctrl_status_undef = 0; | ||
6016 | |||
6017 | saved_fan_level = fan_control_desired_level; | ||
6018 | if (!fan_control_allowed || | ||
6019 | (fan_get_status_safe(¤t_level) < 0)) | ||
6020 | return; | ||
6021 | |||
6022 | switch (fan_control_access_mode) { | ||
6023 | case TPACPI_FAN_WR_ACPI_SFAN: | ||
6024 | do_set = (saved_fan_level > current_level); | ||
6025 | break; | ||
6026 | case TPACPI_FAN_WR_ACPI_FANS: | ||
6027 | case TPACPI_FAN_WR_TPEC: | ||
6028 | do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) || | ||
6029 | (saved_fan_level == 7 && | ||
6030 | !(current_level & TP_EC_FAN_FULLSPEED))); | ||
6031 | break; | ||
6032 | default: | ||
6033 | return; | ||
6034 | } | ||
6035 | if (do_set) { | ||
6036 | printk(TPACPI_NOTICE | ||
6037 | "restoring fan level to 0x%02x\n", | ||
6038 | saved_fan_level); | ||
6039 | fan_set_level_safe(saved_fan_level); | ||
6040 | } | ||
6041 | } | ||
6042 | |||
5986 | static int fan_read(char *p) | 6043 | static int fan_read(char *p) |
5987 | { | 6044 | { |
5988 | int len = 0; | 6045 | int len = 0; |
@@ -6174,6 +6231,8 @@ static struct ibm_struct fan_driver_data = { | |||
6174 | .read = fan_read, | 6231 | .read = fan_read, |
6175 | .write = fan_write, | 6232 | .write = fan_write, |
6176 | .exit = fan_exit, | 6233 | .exit = fan_exit, |
6234 | .suspend = fan_suspend, | ||
6235 | .resume = fan_resume, | ||
6177 | }; | 6236 | }; |
6178 | 6237 | ||
6179 | /**************************************************************************** | 6238 | /**************************************************************************** |