aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/acer-wmi.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/platform/x86/acer-wmi.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/platform/x86/acer-wmi.c')
-rw-r--r--drivers/platform/x86/acer-wmi.c671
1 files changed, 628 insertions, 43 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 2badee2fdeed..e1c4938b301b 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -22,6 +22,8 @@
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
25#include <linux/kernel.h> 27#include <linux/kernel.h>
26#include <linux/module.h> 28#include <linux/module.h>
27#include <linux/init.h> 29#include <linux/init.h>
@@ -37,6 +39,8 @@
37#include <linux/workqueue.h> 39#include <linux/workqueue.h>
38#include <linux/debugfs.h> 40#include <linux/debugfs.h>
39#include <linux/slab.h> 41#include <linux/slab.h>
42#include <linux/input.h>
43#include <linux/input/sparse-keymap.h>
40 44
41#include <acpi/acpi_drivers.h> 45#include <acpi/acpi_drivers.h>
42 46
@@ -44,11 +48,6 @@ MODULE_AUTHOR("Carlos Corbacho");
44MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver"); 48MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
45MODULE_LICENSE("GPL"); 49MODULE_LICENSE("GPL");
46 50
47#define ACER_LOGPREFIX "acer-wmi: "
48#define ACER_ERR KERN_ERR ACER_LOGPREFIX
49#define ACER_NOTICE KERN_NOTICE ACER_LOGPREFIX
50#define ACER_INFO KERN_INFO ACER_LOGPREFIX
51
52/* 51/*
53 * Magic Number 52 * Magic Number
54 * Meaning is unknown - this number is required for writing to ACPI for AMW0 53 * Meaning is unknown - this number is required for writing to ACPI for AMW0
@@ -80,11 +79,98 @@ MODULE_LICENSE("GPL");
80 */ 79 */
81#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB" 80#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
82#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C" 81#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
83#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" 82#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
84#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A" 83#define WMID_GUID2 "95764E09-FB56-4E83-B31A-37761F60994A"
84#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
85
86/*
87 * Acer ACPI event GUIDs
88 */
89#define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
85 90
86MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB"); 91MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
87MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"); 92MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
93MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
94
95enum acer_wmi_event_ids {
96 WMID_HOTKEY_EVENT = 0x1,
97};
98
99static const struct key_entry acer_wmi_keymap[] = {
100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
102 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
103 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
104 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
105 {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */
106 {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_Key */
107 {KE_IGNORE, 0x41, {KEY_MUTE} },
108 {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
109 {KE_IGNORE, 0x43, {KEY_NEXTSONG} },
110 {KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },
111 {KE_IGNORE, 0x45, {KEY_STOP} },
112 {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
113 {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
114 {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
115 {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
116 {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
117 {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
118 {KE_IGNORE, 0x81, {KEY_SLEEP} },
119 {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */
120 {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
121 {KE_END, 0}
122};
123
124static struct input_dev *acer_wmi_input_dev;
125
126struct event_return_value {
127 u8 function;
128 u8 key_num;
129 u16 device_state;
130 u32 reserved;
131} __attribute__((packed));
132
133/*
134 * GUID3 Get Device Status device flags
135 */
136#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */
137#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
138#define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */
139#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */
140
141struct lm_input_params {
142 u8 function_num; /* Function Number */
143 u16 commun_devices; /* Communication type devices default status */
144 u16 devices; /* Other type devices default status */
145 u8 lm_status; /* Launch Manager Status */
146 u16 reserved;
147} __attribute__((packed));
148
149struct lm_return_value {
150 u8 error_code; /* Error Code */
151 u8 ec_return_value; /* EC Return Value */
152 u16 reserved;
153} __attribute__((packed));
154
155struct wmid3_gds_input_param { /* Get Device Status input parameter */
156 u8 function_num; /* Function Number */
157 u8 hotkey_number; /* Hotkey Number */
158 u16 devices; /* Get Device */
159} __attribute__((packed));
160
161struct wmid3_gds_return_value { /* Get Device Status return value*/
162 u8 error_code; /* Error Code */
163 u8 ec_return_value; /* EC Return Value */
164 u16 devices; /* Current Device Status */
165 u32 reserved;
166} __attribute__((packed));
167
168struct hotkey_function_type_aa {
169 u8 type;
170 u8 length;
171 u16 handle;
172 u16 commun_func_bitmap;
173} __attribute__((packed));
88 174
89/* 175/*
90 * Interface capability flags 176 * Interface capability flags
@@ -116,15 +202,19 @@ static int mailled = -1;
116static int brightness = -1; 202static int brightness = -1;
117static int threeg = -1; 203static int threeg = -1;
118static int force_series; 204static int force_series;
205static bool ec_raw_mode;
206static bool has_type_aa;
119 207
120module_param(mailled, int, 0444); 208module_param(mailled, int, 0444);
121module_param(brightness, int, 0444); 209module_param(brightness, int, 0444);
122module_param(threeg, int, 0444); 210module_param(threeg, int, 0444);
123module_param(force_series, int, 0444); 211module_param(force_series, int, 0444);
212module_param(ec_raw_mode, bool, 0444);
124MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); 213MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
125MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); 214MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
126MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); 215MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
127MODULE_PARM_DESC(force_series, "Force a different laptop series"); 216MODULE_PARM_DESC(force_series, "Force a different laptop series");
217MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
128 218
129struct acer_data { 219struct acer_data {
130 int mailled; 220 int mailled;
@@ -140,6 +230,8 @@ struct acer_debug {
140 230
141static struct rfkill *wireless_rfkill; 231static struct rfkill *wireless_rfkill;
142static struct rfkill *bluetooth_rfkill; 232static struct rfkill *bluetooth_rfkill;
233static struct rfkill *threeg_rfkill;
234static bool rfkill_inited;
143 235
144/* Each low-level interface must define at least some of the following */ 236/* Each low-level interface must define at least some of the following */
145struct wmi_interface { 237struct wmi_interface {
@@ -659,8 +751,11 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
659 751
660 obj = (union acpi_object *) result.pointer; 752 obj = (union acpi_object *) result.pointer;
661 if (obj && obj->type == ACPI_TYPE_BUFFER && 753 if (obj && obj->type == ACPI_TYPE_BUFFER &&
662 obj->buffer.length == sizeof(u32)) { 754 (obj->buffer.length == sizeof(u32) ||
755 obj->buffer.length == sizeof(u64))) {
663 tmp = *((u32 *) obj->buffer.pointer); 756 tmp = *((u32 *) obj->buffer.pointer);
757 } else if (obj->type == ACPI_TYPE_INTEGER) {
758 tmp = (u32) obj->integer.value;
664 } else { 759 } else {
665 tmp = 0; 760 tmp = 0;
666 } 761 }
@@ -753,6 +848,28 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
753 return WMI_execute_u32(method_id, (u32)value, NULL); 848 return WMI_execute_u32(method_id, (u32)value, NULL);
754} 849}
755 850
851static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
852{
853 struct hotkey_function_type_aa *type_aa;
854
855 /* We are looking for OEM-specific Type AAh */
856 if (header->type != 0xAA)
857 return;
858
859 has_type_aa = true;
860 type_aa = (struct hotkey_function_type_aa *) header;
861
862 pr_info("Function bitmap for Communication Button: 0x%x\n",
863 type_aa->commun_func_bitmap);
864
865 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
866 interface->capability |= ACER_CAP_WIRELESS;
867 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)
868 interface->capability |= ACER_CAP_THREEG;
869 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
870 interface->capability |= ACER_CAP_BLUETOOTH;
871}
872
756static acpi_status WMID_set_capabilities(void) 873static acpi_status WMID_set_capabilities(void)
757{ 874{
758 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 875 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -766,23 +883,28 @@ static acpi_status WMID_set_capabilities(void)
766 883
767 obj = (union acpi_object *) out.pointer; 884 obj = (union acpi_object *) out.pointer;
768 if (obj && obj->type == ACPI_TYPE_BUFFER && 885 if (obj && obj->type == ACPI_TYPE_BUFFER &&
769 obj->buffer.length == sizeof(u32)) { 886 (obj->buffer.length == sizeof(u32) ||
887 obj->buffer.length == sizeof(u64))) {
770 devices = *((u32 *) obj->buffer.pointer); 888 devices = *((u32 *) obj->buffer.pointer);
889 } else if (obj->type == ACPI_TYPE_INTEGER) {
890 devices = (u32) obj->integer.value;
771 } else { 891 } else {
772 kfree(out.pointer); 892 kfree(out.pointer);
773 return AE_ERROR; 893 return AE_ERROR;
774 } 894 }
775 895
776 /* Not sure on the meaning of the relevant bits yet to detect these */ 896 dmi_walk(type_aa_dmi_decode, NULL);
777 interface->capability |= ACER_CAP_WIRELESS; 897 if (!has_type_aa) {
778 interface->capability |= ACER_CAP_THREEG; 898 interface->capability |= ACER_CAP_WIRELESS;
899 if (devices & 0x40)
900 interface->capability |= ACER_CAP_THREEG;
901 if (devices & 0x10)
902 interface->capability |= ACER_CAP_BLUETOOTH;
903 }
779 904
780 /* WMID always provides brightness methods */ 905 /* WMID always provides brightness methods */
781 interface->capability |= ACER_CAP_BRIGHTNESS; 906 interface->capability |= ACER_CAP_BRIGHTNESS;
782 907
783 if (devices & 0x10)
784 interface->capability |= ACER_CAP_BLUETOOTH;
785
786 if (!(devices & 0x20)) 908 if (!(devices & 0x20))
787 max_brightness = 0x9; 909 max_brightness = 0x9;
788 910
@@ -860,9 +982,12 @@ static void __init acer_commandline_init(void)
860 * These will all fail silently if the value given is invalid, or the 982 * These will all fail silently if the value given is invalid, or the
861 * capability isn't available on the given interface 983 * capability isn't available on the given interface
862 */ 984 */
863 set_u32(mailled, ACER_CAP_MAILLED); 985 if (mailled >= 0)
864 set_u32(threeg, ACER_CAP_THREEG); 986 set_u32(mailled, ACER_CAP_MAILLED);
865 set_u32(brightness, ACER_CAP_BRIGHTNESS); 987 if (!has_type_aa && threeg >= 0)
988 set_u32(threeg, ACER_CAP_THREEG);
989 if (brightness >= 0)
990 set_u32(brightness, ACER_CAP_BRIGHTNESS);
866} 991}
867 992
868/* 993/*
@@ -886,6 +1011,7 @@ static int __devinit acer_led_init(struct device *dev)
886 1011
887static void acer_led_exit(void) 1012static void acer_led_exit(void)
888{ 1013{
1014 set_u32(LED_OFF, ACER_CAP_MAILLED);
889 led_classdev_unregister(&mail_led); 1015 led_classdev_unregister(&mail_led);
890} 1016}
891 1017
@@ -915,7 +1041,7 @@ static int update_bl_status(struct backlight_device *bd)
915 return 0; 1041 return 0;
916} 1042}
917 1043
918static struct backlight_ops acer_bl_ops = { 1044static const struct backlight_ops acer_bl_ops = {
919 .get_brightness = read_brightness, 1045 .get_brightness = read_brightness,
920 .update_status = update_bl_status, 1046 .update_status = update_bl_status,
921}; 1047};
@@ -926,11 +1052,12 @@ static int __devinit acer_backlight_init(struct device *dev)
926 struct backlight_device *bd; 1052 struct backlight_device *bd;
927 1053
928 memset(&props, 0, sizeof(struct backlight_properties)); 1054 memset(&props, 0, sizeof(struct backlight_properties));
1055 props.type = BACKLIGHT_PLATFORM;
929 props.max_brightness = max_brightness; 1056 props.max_brightness = max_brightness;
930 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops, 1057 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
931 &props); 1058 &props);
932 if (IS_ERR(bd)) { 1059 if (IS_ERR(bd)) {
933 printk(ACER_ERR "Could not register Acer backlight device\n"); 1060 pr_err("Could not register Acer backlight device\n");
934 acer_backlight_device = NULL; 1061 acer_backlight_device = NULL;
935 return PTR_ERR(bd); 1062 return PTR_ERR(bd);
936 } 1063 }
@@ -948,6 +1075,186 @@ static void acer_backlight_exit(void)
948 backlight_device_unregister(acer_backlight_device); 1075 backlight_device_unregister(acer_backlight_device);
949} 1076}
950 1077
1078static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1079{
1080 struct wmid3_gds_return_value return_value;
1081 acpi_status status;
1082 union acpi_object *obj;
1083 struct wmid3_gds_input_param params = {
1084 .function_num = 0x1,
1085 .hotkey_number = 0x01,
1086 .devices = device,
1087 };
1088 struct acpi_buffer input = {
1089 sizeof(struct wmid3_gds_input_param),
1090 &params
1091 };
1092 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1093
1094 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1095 if (ACPI_FAILURE(status))
1096 return status;
1097
1098 obj = output.pointer;
1099
1100 if (!obj)
1101 return AE_ERROR;
1102 else if (obj->type != ACPI_TYPE_BUFFER) {
1103 kfree(obj);
1104 return AE_ERROR;
1105 }
1106 if (obj->buffer.length != 8) {
1107 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1108 kfree(obj);
1109 return AE_ERROR;
1110 }
1111
1112 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1113 kfree(obj);
1114
1115 if (return_value.error_code || return_value.ec_return_value)
1116 pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
1117 return_value.error_code,
1118 return_value.ec_return_value);
1119 else
1120 *value = !!(return_value.devices & device);
1121
1122 return status;
1123}
1124
1125static acpi_status get_device_status(u32 *value, u32 cap)
1126{
1127 if (wmi_has_guid(WMID_GUID3)) {
1128 u16 device;
1129
1130 switch (cap) {
1131 case ACER_CAP_WIRELESS:
1132 device = ACER_WMID3_GDS_WIRELESS;
1133 break;
1134 case ACER_CAP_BLUETOOTH:
1135 device = ACER_WMID3_GDS_BLUETOOTH;
1136 break;
1137 case ACER_CAP_THREEG:
1138 device = ACER_WMID3_GDS_THREEG;
1139 break;
1140 default:
1141 return AE_ERROR;
1142 }
1143 return wmid3_get_device_status(value, device);
1144
1145 } else {
1146 return get_u32(value, cap);
1147 }
1148}
1149
1150static acpi_status wmid3_set_device_status(u32 value, u16 device)
1151{
1152 struct wmid3_gds_return_value return_value;
1153 acpi_status status;
1154 union acpi_object *obj;
1155 u16 devices;
1156 struct wmid3_gds_input_param params = {
1157 .function_num = 0x1,
1158 .hotkey_number = 0x01,
1159 .devices = ACER_WMID3_GDS_WIRELESS |
1160 ACER_WMID3_GDS_THREEG |
1161 ACER_WMID3_GDS_WIMAX |
1162 ACER_WMID3_GDS_BLUETOOTH,
1163 };
1164 struct acpi_buffer input = {
1165 sizeof(struct wmid3_gds_input_param),
1166 &params
1167 };
1168 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1169 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1170
1171 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1172 if (ACPI_FAILURE(status))
1173 return status;
1174
1175 obj = output.pointer;
1176
1177 if (!obj)
1178 return AE_ERROR;
1179 else if (obj->type != ACPI_TYPE_BUFFER) {
1180 kfree(obj);
1181 return AE_ERROR;
1182 }
1183 if (obj->buffer.length != 8) {
1184 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1185 kfree(obj);
1186 return AE_ERROR;
1187 }
1188
1189 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1190 kfree(obj);
1191
1192 if (return_value.error_code || return_value.ec_return_value) {
1193 pr_warning("Get Current Device Status failed: "
1194 "0x%x - 0x%x\n", return_value.error_code,
1195 return_value.ec_return_value);
1196 return status;
1197 }
1198
1199 devices = return_value.devices;
1200 params.function_num = 0x2;
1201 params.hotkey_number = 0x01;
1202 params.devices = (value) ? (devices | device) : (devices & ~device);
1203
1204 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1205 if (ACPI_FAILURE(status))
1206 return status;
1207
1208 obj = output2.pointer;
1209
1210 if (!obj)
1211 return AE_ERROR;
1212 else if (obj->type != ACPI_TYPE_BUFFER) {
1213 kfree(obj);
1214 return AE_ERROR;
1215 }
1216 if (obj->buffer.length != 4) {
1217 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1218 kfree(obj);
1219 return AE_ERROR;
1220 }
1221
1222 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1223 kfree(obj);
1224
1225 if (return_value.error_code || return_value.ec_return_value)
1226 pr_warning("Set Device Status failed: "
1227 "0x%x - 0x%x\n", return_value.error_code,
1228 return_value.ec_return_value);
1229
1230 return status;
1231}
1232
1233static acpi_status set_device_status(u32 value, u32 cap)
1234{
1235 if (wmi_has_guid(WMID_GUID3)) {
1236 u16 device;
1237
1238 switch (cap) {
1239 case ACER_CAP_WIRELESS:
1240 device = ACER_WMID3_GDS_WIRELESS;
1241 break;
1242 case ACER_CAP_BLUETOOTH:
1243 device = ACER_WMID3_GDS_BLUETOOTH;
1244 break;
1245 case ACER_CAP_THREEG:
1246 device = ACER_WMID3_GDS_THREEG;
1247 break;
1248 default:
1249 return AE_ERROR;
1250 }
1251 return wmid3_set_device_status(value, device);
1252
1253 } else {
1254 return set_u32(value, cap);
1255 }
1256}
1257
951/* 1258/*
952 * Rfkill devices 1259 * Rfkill devices
953 */ 1260 */
@@ -968,6 +1275,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
968 rfkill_set_sw_state(bluetooth_rfkill, !state); 1275 rfkill_set_sw_state(bluetooth_rfkill, !state);
969 } 1276 }
970 1277
1278 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1279 status = wmid3_get_device_status(&state,
1280 ACER_WMID3_GDS_THREEG);
1281 if (ACPI_SUCCESS(status))
1282 rfkill_set_sw_state(threeg_rfkill, !state);
1283 }
1284
971 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 1285 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
972} 1286}
973 1287
@@ -975,9 +1289,13 @@ static int acer_rfkill_set(void *data, bool blocked)
975{ 1289{
976 acpi_status status; 1290 acpi_status status;
977 u32 cap = (unsigned long)data; 1291 u32 cap = (unsigned long)data;
978 status = set_u32(!blocked, cap); 1292
979 if (ACPI_FAILURE(status)) 1293 if (rfkill_inited) {
980 return -ENODEV; 1294 status = set_device_status(!blocked, cap);
1295 if (ACPI_FAILURE(status))
1296 return -ENODEV;
1297 }
1298
981 return 0; 1299 return 0;
982} 1300}
983 1301
@@ -991,6 +1309,8 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
991{ 1309{
992 int err; 1310 int err;
993 struct rfkill *rfkill_dev; 1311 struct rfkill *rfkill_dev;
1312 u32 state;
1313 acpi_status status;
994 1314
995 rfkill_dev = rfkill_alloc(name, dev, type, 1315 rfkill_dev = rfkill_alloc(name, dev, type,
996 &acer_rfkill_ops, 1316 &acer_rfkill_ops,
@@ -998,11 +1318,17 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
998 if (!rfkill_dev) 1318 if (!rfkill_dev)
999 return ERR_PTR(-ENOMEM); 1319 return ERR_PTR(-ENOMEM);
1000 1320
1321 status = get_device_status(&state, cap);
1322
1001 err = rfkill_register(rfkill_dev); 1323 err = rfkill_register(rfkill_dev);
1002 if (err) { 1324 if (err) {
1003 rfkill_destroy(rfkill_dev); 1325 rfkill_destroy(rfkill_dev);
1004 return ERR_PTR(err); 1326 return ERR_PTR(err);
1005 } 1327 }
1328
1329 if (ACPI_SUCCESS(status))
1330 rfkill_set_sw_state(rfkill_dev, !state);
1331
1006 return rfkill_dev; 1332 return rfkill_dev;
1007} 1333}
1008 1334
@@ -1024,14 +1350,32 @@ static int acer_rfkill_init(struct device *dev)
1024 } 1350 }
1025 } 1351 }
1026 1352
1027 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 1353 if (has_cap(ACER_CAP_THREEG)) {
1354 threeg_rfkill = acer_rfkill_register(dev,
1355 RFKILL_TYPE_WWAN, "acer-threeg",
1356 ACER_CAP_THREEG);
1357 if (IS_ERR(threeg_rfkill)) {
1358 rfkill_unregister(wireless_rfkill);
1359 rfkill_destroy(wireless_rfkill);
1360 rfkill_unregister(bluetooth_rfkill);
1361 rfkill_destroy(bluetooth_rfkill);
1362 return PTR_ERR(threeg_rfkill);
1363 }
1364 }
1365
1366 rfkill_inited = true;
1367
1368 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
1369 schedule_delayed_work(&acer_rfkill_work,
1370 round_jiffies_relative(HZ));
1028 1371
1029 return 0; 1372 return 0;
1030} 1373}
1031 1374
1032static void acer_rfkill_exit(void) 1375static void acer_rfkill_exit(void)
1033{ 1376{
1034 cancel_delayed_work_sync(&acer_rfkill_work); 1377 if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
1378 cancel_delayed_work_sync(&acer_rfkill_work);
1035 1379
1036 rfkill_unregister(wireless_rfkill); 1380 rfkill_unregister(wireless_rfkill);
1037 rfkill_destroy(wireless_rfkill); 1381 rfkill_destroy(wireless_rfkill);
@@ -1040,6 +1384,11 @@ static void acer_rfkill_exit(void)
1040 rfkill_unregister(bluetooth_rfkill); 1384 rfkill_unregister(bluetooth_rfkill);
1041 rfkill_destroy(bluetooth_rfkill); 1385 rfkill_destroy(bluetooth_rfkill);
1042 } 1386 }
1387
1388 if (has_cap(ACER_CAP_THREEG)) {
1389 rfkill_unregister(threeg_rfkill);
1390 rfkill_destroy(threeg_rfkill);
1391 }
1043 return; 1392 return;
1044} 1393}
1045 1394
@@ -1050,7 +1399,12 @@ static ssize_t show_bool_threeg(struct device *dev,
1050 struct device_attribute *attr, char *buf) 1399 struct device_attribute *attr, char *buf)
1051{ 1400{
1052 u32 result; \ 1401 u32 result; \
1053 acpi_status status = get_u32(&result, ACER_CAP_THREEG); 1402 acpi_status status;
1403 if (wmi_has_guid(WMID_GUID3))
1404 status = wmid3_get_device_status(&result,
1405 ACER_WMID3_GDS_THREEG);
1406 else
1407 status = get_u32(&result, ACER_CAP_THREEG);
1054 if (ACPI_SUCCESS(status)) 1408 if (ACPI_SUCCESS(status))
1055 return sprintf(buf, "%u\n", result); 1409 return sprintf(buf, "%u\n", result);
1056 return sprintf(buf, "Read error\n"); 1410 return sprintf(buf, "Read error\n");
@@ -1065,7 +1419,7 @@ static ssize_t set_bool_threeg(struct device *dev,
1065 return -EINVAL; 1419 return -EINVAL;
1066 return count; 1420 return count;
1067} 1421}
1068static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg, 1422static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
1069 set_bool_threeg); 1423 set_bool_threeg);
1070 1424
1071static ssize_t show_interface(struct device *dev, struct device_attribute *attr, 1425static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
@@ -1085,6 +1439,199 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1085 1439
1086static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL); 1440static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL);
1087 1441
1442static void acer_wmi_notify(u32 value, void *context)
1443{
1444 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
1445 union acpi_object *obj;
1446 struct event_return_value return_value;
1447 acpi_status status;
1448 u16 device_state;
1449 const struct key_entry *key;
1450
1451 status = wmi_get_event_data(value, &response);
1452 if (status != AE_OK) {
1453 pr_warn("bad event status 0x%x\n", status);
1454 return;
1455 }
1456
1457 obj = (union acpi_object *)response.pointer;
1458
1459 if (!obj)
1460 return;
1461 if (obj->type != ACPI_TYPE_BUFFER) {
1462 pr_warn("Unknown response received %d\n", obj->type);
1463 kfree(obj);
1464 return;
1465 }
1466 if (obj->buffer.length != 8) {
1467 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1468 kfree(obj);
1469 return;
1470 }
1471
1472 return_value = *((struct event_return_value *)obj->buffer.pointer);
1473 kfree(obj);
1474
1475 switch (return_value.function) {
1476 case WMID_HOTKEY_EVENT:
1477 device_state = return_value.device_state;
1478 pr_debug("device state: 0x%x\n", device_state);
1479
1480 key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,
1481 return_value.key_num);
1482 if (!key) {
1483 pr_warn("Unknown key number - 0x%x\n",
1484 return_value.key_num);
1485 } else {
1486 switch (key->keycode) {
1487 case KEY_WLAN:
1488 case KEY_BLUETOOTH:
1489 if (has_cap(ACER_CAP_WIRELESS))
1490 rfkill_set_sw_state(wireless_rfkill,
1491 !(device_state & ACER_WMID3_GDS_WIRELESS));
1492 if (has_cap(ACER_CAP_THREEG))
1493 rfkill_set_sw_state(threeg_rfkill,
1494 !(device_state & ACER_WMID3_GDS_THREEG));
1495 if (has_cap(ACER_CAP_BLUETOOTH))
1496 rfkill_set_sw_state(bluetooth_rfkill,
1497 !(device_state & ACER_WMID3_GDS_BLUETOOTH));
1498 break;
1499 }
1500 sparse_keymap_report_entry(acer_wmi_input_dev, key,
1501 1, true);
1502 }
1503 break;
1504 default:
1505 pr_warn("Unknown function number - %d - %d\n",
1506 return_value.function, return_value.key_num);
1507 break;
1508 }
1509}
1510
1511static acpi_status
1512wmid3_set_lm_mode(struct lm_input_params *params,
1513 struct lm_return_value *return_value)
1514{
1515 acpi_status status;
1516 union acpi_object *obj;
1517
1518 struct acpi_buffer input = { sizeof(struct lm_input_params), params };
1519 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1520
1521 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);
1522 if (ACPI_FAILURE(status))
1523 return status;
1524
1525 obj = output.pointer;
1526
1527 if (!obj)
1528 return AE_ERROR;
1529 else if (obj->type != ACPI_TYPE_BUFFER) {
1530 kfree(obj);
1531 return AE_ERROR;
1532 }
1533 if (obj->buffer.length != 4) {
1534 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1535 kfree(obj);
1536 return AE_ERROR;
1537 }
1538
1539 *return_value = *((struct lm_return_value *)obj->buffer.pointer);
1540 kfree(obj);
1541
1542 return status;
1543}
1544
1545static int acer_wmi_enable_ec_raw(void)
1546{
1547 struct lm_return_value return_value;
1548 acpi_status status;
1549 struct lm_input_params params = {
1550 .function_num = 0x1,
1551 .commun_devices = 0xFFFF,
1552 .devices = 0xFFFF,
1553 .lm_status = 0x00, /* Launch Manager Deactive */
1554 };
1555
1556 status = wmid3_set_lm_mode(&params, &return_value);
1557
1558 if (return_value.error_code || return_value.ec_return_value)
1559 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
1560 return_value.error_code,
1561 return_value.ec_return_value);
1562 else
1563 pr_info("Enabled EC raw mode\n");
1564
1565 return status;
1566}
1567
1568static int acer_wmi_enable_lm(void)
1569{
1570 struct lm_return_value return_value;
1571 acpi_status status;
1572 struct lm_input_params params = {
1573 .function_num = 0x1,
1574 .commun_devices = 0xFFFF,
1575 .devices = 0xFFFF,
1576 .lm_status = 0x01, /* Launch Manager Active */
1577 };
1578
1579 status = wmid3_set_lm_mode(&params, &return_value);
1580
1581 if (return_value.error_code || return_value.ec_return_value)
1582 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
1583 return_value.error_code,
1584 return_value.ec_return_value);
1585
1586 return status;
1587}
1588
1589static int __init acer_wmi_input_setup(void)
1590{
1591 acpi_status status;
1592 int err;
1593
1594 acer_wmi_input_dev = input_allocate_device();
1595 if (!acer_wmi_input_dev)
1596 return -ENOMEM;
1597
1598 acer_wmi_input_dev->name = "Acer WMI hotkeys";
1599 acer_wmi_input_dev->phys = "wmi/input0";
1600 acer_wmi_input_dev->id.bustype = BUS_HOST;
1601
1602 err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);
1603 if (err)
1604 goto err_free_dev;
1605
1606 status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
1607 acer_wmi_notify, NULL);
1608 if (ACPI_FAILURE(status)) {
1609 err = -EIO;
1610 goto err_free_keymap;
1611 }
1612
1613 err = input_register_device(acer_wmi_input_dev);
1614 if (err)
1615 goto err_uninstall_notifier;
1616
1617 return 0;
1618
1619err_uninstall_notifier:
1620 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1621err_free_keymap:
1622 sparse_keymap_free(acer_wmi_input_dev);
1623err_free_dev:
1624 input_free_device(acer_wmi_input_dev);
1625 return err;
1626}
1627
1628static void acer_wmi_input_destroy(void)
1629{
1630 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);
1631 sparse_keymap_free(acer_wmi_input_dev);
1632 input_unregister_device(acer_wmi_input_dev);
1633}
1634
1088/* 1635/*
1089 * debugfs functions 1636 * debugfs functions
1090 */ 1637 */
@@ -1101,8 +1648,11 @@ static u32 get_wmid_devices(void)
1101 1648
1102 obj = (union acpi_object *) out.pointer; 1649 obj = (union acpi_object *) out.pointer;
1103 if (obj && obj->type == ACPI_TYPE_BUFFER && 1650 if (obj && obj->type == ACPI_TYPE_BUFFER &&
1104 obj->buffer.length == sizeof(u32)) { 1651 (obj->buffer.length == sizeof(u32) ||
1652 obj->buffer.length == sizeof(u64))) {
1105 devices = *((u32 *) obj->buffer.pointer); 1653 devices = *((u32 *) obj->buffer.pointer);
1654 } else if (obj->type == ACPI_TYPE_INTEGER) {
1655 devices = (u32) obj->integer.value;
1106 } 1656 }
1107 1657
1108 kfree(out.pointer); 1658 kfree(out.pointer);
@@ -1166,6 +1716,7 @@ pm_message_t state)
1166 1716
1167 if (has_cap(ACER_CAP_MAILLED)) { 1717 if (has_cap(ACER_CAP_MAILLED)) {
1168 get_u32(&value, ACER_CAP_MAILLED); 1718 get_u32(&value, ACER_CAP_MAILLED);
1719 set_u32(LED_OFF, ACER_CAP_MAILLED);
1169 data->mailled = value; 1720 data->mailled = value;
1170 } 1721 }
1171 1722
@@ -1193,6 +1744,17 @@ static int acer_platform_resume(struct platform_device *device)
1193 return 0; 1744 return 0;
1194} 1745}
1195 1746
1747static void acer_platform_shutdown(struct platform_device *device)
1748{
1749 struct acer_data *data = &interface->data;
1750
1751 if (!data)
1752 return;
1753
1754 if (has_cap(ACER_CAP_MAILLED))
1755 set_u32(LED_OFF, ACER_CAP_MAILLED);
1756}
1757
1196static struct platform_driver acer_platform_driver = { 1758static struct platform_driver acer_platform_driver = {
1197 .driver = { 1759 .driver = {
1198 .name = "acer-wmi", 1760 .name = "acer-wmi",
@@ -1202,6 +1764,7 @@ static struct platform_driver acer_platform_driver = {
1202 .remove = acer_platform_remove, 1764 .remove = acer_platform_remove,
1203 .suspend = acer_platform_suspend, 1765 .suspend = acer_platform_suspend,
1204 .resume = acer_platform_resume, 1766 .resume = acer_platform_resume,
1767 .shutdown = acer_platform_shutdown,
1205}; 1768};
1206 1769
1207static struct platform_device *acer_platform_device; 1770static struct platform_device *acer_platform_device;
@@ -1249,7 +1812,7 @@ static int create_debugfs(void)
1249{ 1812{
1250 interface->debug.root = debugfs_create_dir("acer-wmi", NULL); 1813 interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
1251 if (!interface->debug.root) { 1814 if (!interface->debug.root) {
1252 printk(ACER_ERR "Failed to create debugfs directory"); 1815 pr_err("Failed to create debugfs directory");
1253 return -ENOMEM; 1816 return -ENOMEM;
1254 } 1817 }
1255 1818
@@ -1270,11 +1833,10 @@ static int __init acer_wmi_init(void)
1270{ 1833{
1271 int err; 1834 int err;
1272 1835
1273 printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n"); 1836 pr_info("Acer Laptop ACPI-WMI Extras\n");
1274 1837
1275 if (dmi_check_system(acer_blacklist)) { 1838 if (dmi_check_system(acer_blacklist)) {
1276 printk(ACER_INFO "Blacklisted hardware detected - " 1839 pr_info("Blacklisted hardware detected - not loading\n");
1277 "not loading\n");
1278 return -ENODEV; 1840 return -ENODEV;
1279 } 1841 }
1280 1842
@@ -1291,12 +1853,11 @@ static int __init acer_wmi_init(void)
1291 1853
1292 if (wmi_has_guid(WMID_GUID2) && interface) { 1854 if (wmi_has_guid(WMID_GUID2) && interface) {
1293 if (ACPI_FAILURE(WMID_set_capabilities())) { 1855 if (ACPI_FAILURE(WMID_set_capabilities())) {
1294 printk(ACER_ERR "Unable to detect available WMID " 1856 pr_err("Unable to detect available WMID devices\n");
1295 "devices\n");
1296 return -ENODEV; 1857 return -ENODEV;
1297 } 1858 }
1298 } else if (!wmi_has_guid(WMID_GUID2) && interface) { 1859 } else if (!wmi_has_guid(WMID_GUID2) && interface) {
1299 printk(ACER_ERR "No WMID device detection method found\n"); 1860 pr_err("No WMID device detection method found\n");
1300 return -ENODEV; 1861 return -ENODEV;
1301 } 1862 }
1302 1863
@@ -1304,8 +1865,7 @@ static int __init acer_wmi_init(void)
1304 interface = &AMW0_interface; 1865 interface = &AMW0_interface;
1305 1866
1306 if (ACPI_FAILURE(AMW0_set_capabilities())) { 1867 if (ACPI_FAILURE(AMW0_set_capabilities())) {
1307 printk(ACER_ERR "Unable to detect available AMW0 " 1868 pr_err("Unable to detect available AMW0 devices\n");
1308 "devices\n");
1309 return -ENODEV; 1869 return -ENODEV;
1310 } 1870 }
1311 } 1871 }
@@ -1314,8 +1874,7 @@ static int __init acer_wmi_init(void)
1314 AMW0_find_mailled(); 1874 AMW0_find_mailled();
1315 1875
1316 if (!interface) { 1876 if (!interface) {
1317 printk(ACER_ERR "No or unsupported WMI interface, unable to " 1877 pr_err("No or unsupported WMI interface, unable to load\n");
1318 "load\n");
1319 return -ENODEV; 1878 return -ENODEV;
1320 } 1879 }
1321 1880
@@ -1323,13 +1882,33 @@ static int __init acer_wmi_init(void)
1323 1882
1324 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { 1883 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
1325 interface->capability &= ~ACER_CAP_BRIGHTNESS; 1884 interface->capability &= ~ACER_CAP_BRIGHTNESS;
1326 printk(ACER_INFO "Brightness must be controlled by " 1885 pr_info("Brightness must be controlled by "
1327 "generic video driver\n"); 1886 "generic video driver\n");
1328 } 1887 }
1329 1888
1889 if (wmi_has_guid(WMID_GUID3)) {
1890 if (ec_raw_mode) {
1891 if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
1892 pr_err("Cannot enable EC raw mode\n");
1893 return -ENODEV;
1894 }
1895 } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
1896 pr_err("Cannot enable Launch Manager mode\n");
1897 return -ENODEV;
1898 }
1899 } else if (ec_raw_mode) {
1900 pr_info("No WMID EC raw mode enable method\n");
1901 }
1902
1903 if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
1904 err = acer_wmi_input_setup();
1905 if (err)
1906 return err;
1907 }
1908
1330 err = platform_driver_register(&acer_platform_driver); 1909 err = platform_driver_register(&acer_platform_driver);
1331 if (err) { 1910 if (err) {
1332 printk(ACER_ERR "Unable to register platform driver.\n"); 1911 pr_err("Unable to register platform driver.\n");
1333 goto error_platform_register; 1912 goto error_platform_register;
1334 } 1913 }
1335 1914
@@ -1368,17 +1947,23 @@ error_device_add:
1368error_device_alloc: 1947error_device_alloc:
1369 platform_driver_unregister(&acer_platform_driver); 1948 platform_driver_unregister(&acer_platform_driver);
1370error_platform_register: 1949error_platform_register:
1950 if (wmi_has_guid(ACERWMID_EVENT_GUID))
1951 acer_wmi_input_destroy();
1952
1371 return err; 1953 return err;
1372} 1954}
1373 1955
1374static void __exit acer_wmi_exit(void) 1956static void __exit acer_wmi_exit(void)
1375{ 1957{
1958 if (wmi_has_guid(ACERWMID_EVENT_GUID))
1959 acer_wmi_input_destroy();
1960
1376 remove_sysfs(acer_platform_device); 1961 remove_sysfs(acer_platform_device);
1377 remove_debugfs(); 1962 remove_debugfs();
1378 platform_device_unregister(acer_platform_device); 1963 platform_device_unregister(acer_platform_device);
1379 platform_driver_unregister(&acer_platform_driver); 1964 platform_driver_unregister(&acer_platform_driver);
1380 1965
1381 printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n"); 1966 pr_info("Acer Laptop WMI Extras unloaded\n");
1382 return; 1967 return;
1383} 1968}
1384 1969