diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/misc/acer-wmi.c | 225 | ||||
-rw-r--r-- | drivers/misc/asus-laptop.c | 5 | ||||
-rw-r--r-- | drivers/misc/eeepc-laptop.c | 230 | ||||
-rw-r--r-- | drivers/misc/fujitsu-laptop.c | 127 | ||||
-rw-r--r-- | drivers/misc/intel_menlow.c | 2 | ||||
-rw-r--r-- | drivers/misc/sony-laptop.c | 2 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 65 |
8 files changed, 491 insertions, 166 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index a726f3b01a6b..6abb95919c38 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 |
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 967ecec82577..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 | ||
@@ -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) \ |
@@ -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 616bcbd8def6..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 | */ |
@@ -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 efd395a64720..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; |
@@ -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 bd372ea11b0a..a78274385d54 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c | |||
@@ -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) |
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 | /**************************************************************************** |