aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/acer-wmi.c225
-rw-r--r--drivers/misc/asus-laptop.c17
-rw-r--r--drivers/misc/eeepc-laptop.c232
-rw-r--r--drivers/misc/fujitsu-laptop.c135
-rw-r--r--drivers/misc/intel_menlow.c29
-rw-r--r--drivers/misc/panasonic-laptop.c767
-rw-r--r--drivers/misc/sony-laptop.c2
-rw-r--r--drivers/misc/thinkpad_acpi.c65
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
249config 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
248config COMPAL_LAPTOP 260config 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
23obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o 23obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
24obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o 24obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
25obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o 25obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
26obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
26obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o 27obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
27obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o 28obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
28obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o 29obj-$(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
124static int max_brightness = 0xF; 126static int max_brightness = 0xF;
125 127
126static int wireless = -1;
127static int bluetooth = -1;
128static int mailled = -1; 128static int mailled = -1;
129static int brightness = -1; 129static int brightness = -1;
130static int threeg = -1; 130static int threeg = -1;
131static int force_series; 131static int force_series;
132 132
133module_param(mailled, int, 0444); 133module_param(mailled, int, 0444);
134module_param(wireless, int, 0444);
135module_param(bluetooth, int, 0444);
136module_param(brightness, int, 0444); 134module_param(brightness, int, 0444);
137module_param(threeg, int, 0444); 135module_param(threeg, int, 0444);
138module_param(force_series, int, 0444); 136module_param(force_series, int, 0444);
139MODULE_PARM_DESC(wireless, "Set initial state of Wireless hardware");
140MODULE_PARM_DESC(bluetooth, "Set initial state of Bluetooth hardware");
141MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); 137MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
142MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); 138MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
143MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); 139MODULE_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
146struct acer_data { 142struct 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
154static struct rfkill *wireless_rfkill;
155static 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 */
161struct wmi_interface { 158struct 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
786static acpi_status get_u32(u32 *value, u32 cap) 783static 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) \ 933static void acer_rfkill_update(struct work_struct *ignored);
939static ssize_t \ 934static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);
940show_bool_##value(struct device *dev, struct device_attribute *attr, \ 935static 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
950static ssize_t \ 945 if (has_cap(ACER_CAP_BLUETOOTH)) {
951set_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}
960static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ 955
961 show_bool_##value, set_bool_##value); 956static int acer_rfkill_set(void *data, enum rfkill_state state)
962 957{
963show_set_bool(wireless, ACER_CAP_WIRELESS); 958 acpi_status status;
964show_set_bool(bluetooth, ACER_CAP_BLUETOOTH); 959 u32 *cap = data;
965show_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
966static struct rfkill * acer_rfkill_register(struct device *dev,
967enum 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
1000static 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
1023static 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 */
1038static 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
1048static 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}
1057static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg,
1058 set_bool_threeg);
1059
970static ssize_t show_interface(struct device *dev, struct device_attribute *attr, 1060static 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
1031error_brightness: 1123error_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
1116static int remove_sysfs(struct platform_device *device) 1191static 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
281static int read_wireless_status(int mask) 282static 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
298static int read_gps_status(void) 299static 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
405static int read_brightness(struct backlight_device *bd) 406static 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
604static int read_display(void) 605static 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
141static struct platform_device *platform_device; 147static struct platform_device *platform_device;
142 148
149struct key_entry {
150 char type;
151 u8 code;
152 u16 keycode;
153};
154
155enum { KE_KEY, KE_END };
156
157static 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,
204static int read_acpi_int(acpi_handle handle, const char *method, int *val) 231static 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
294static 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
302static 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
311static 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
319static 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 */
266static int parse_arg(const char *buf, unsigned long count, int *val) 331static 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)
311EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); 376EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
312EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); 377EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
313EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); 378EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
314EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN);
315 379
316static struct attribute *platform_attributes[] = { 380static 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 */
394static 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
405static 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
416static 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
428static 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
331static int eeepc_hotk_check(void) 449static 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
366static 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
381static void notify_brn(void) 510static 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
387static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) 516static 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
399static int eeepc_hotk_add(struct acpi_device *device) 542static 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
225static int get_lcd_level(void) 227static 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
247static int get_max_brightness(void) 249static 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
264static int get_lcd_level_alt(void) 266static 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
385static int get_irb(void) 387static 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
433static int dmi_check_cb_s6410(const struct dmi_system_id *id) 435static 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
459static 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
467static 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
458static struct dmi_system_id __initdata fujitsu_dmi_table[] = { 476static 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");
1076MODULE_VERSION(FUJITSU_DRIVER_VERSION); 1096MODULE_VERSION(FUJITSU_DRIVER_VERSION);
1077MODULE_LICENSE("GPL"); 1097MODULE_LICENSE("GPL");
1078 1098
1079MODULE_ALIAS 1099MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
1080 ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); 1100MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
1081MODULE_ALIAS
1082 ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
1083 1101
1084static struct pnp_device_id pnp_ids[] = { 1102static 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
1090MODULE_DEVICE_TABLE(pnp, pnp_ids); 1109MODULE_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 */
255static int sensor_get_auxtrip(acpi_handle handle, int index, int *value) 255static 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
139MODULE_AUTHOR("Hiroshi Miura, David Bronaugh and Harald Welte");
140MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops");
141MODULE_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*/
162enum 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
177static int acpi_pcc_hotkey_add(struct acpi_device *device);
178static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
179static int acpi_pcc_hotkey_resume(struct acpi_device *device);
180
181static const struct acpi_device_id pcc_device_ids[] = {
182 { "MAT0012", 0},
183 { "MAT0013", 0},
184 { "MAT0018", 0},
185 { "MAT0019", 0},
186 { "", 0},
187};
188
189static 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
201static 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
215struct 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
226struct pcc_keyinput {
227 struct acpi_hotkey *hotkey;
228};
229
230/* method access functions */
231static 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 &params, NULL);
249
250 return status == AE_OK;
251}
252
253static 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
271static 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
311end:
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
323static 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
333static 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
359static 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
367static 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
379static 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
391static 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
403static 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
415static 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
431static DEVICE_ATTR(numbatt, S_IRUGO, show_numbatt, NULL);
432static DEVICE_ATTR(lcdtype, S_IRUGO, show_lcdtype, NULL);
433static DEVICE_ATTR(mute, S_IRUGO, show_mute, NULL);
434static DEVICE_ATTR(sticky_key, S_IRUGO | S_IWUSR, show_sticky, set_sticky);
435
436static 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
444static 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
452static 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
464static 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
476static 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
498static 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
538static 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
554static 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
596static 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
614static 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
697out_backlight:
698 backlight_device_unregister(pcc->backlight);
699out_notify:
700 acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
701 acpi_pcc_hotkey_notify);
702out_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 */
706out_sinf:
707 kfree(pcc->sinf);
708out_hotkey:
709 kfree(pcc);
710
711 return result;
712}
713
714static 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
733static 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
759static 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
766module_init(acpi_pcc_init);
767module_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
841static 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
841static int __init tpacpi_query_bcl_levels(acpi_handle handle) 848static 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
2513static void hotkey_resume(void) 2522static 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
5997static 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
6008static 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(&current_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
5986static int fan_read(char *p) 6043static 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/****************************************************************************