aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/acer-wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/acer-wmi.c')
-rw-r--r--drivers/platform/x86/acer-wmi.c184
1 files changed, 159 insertions, 25 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index ac4e7f83ce6..005417bd429 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -98,13 +98,26 @@ enum acer_wmi_event_ids {
98 98
99static const struct key_entry acer_wmi_keymap[] = { 99static const struct key_entry acer_wmi_keymap[] = {
100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ 100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
101 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */ 102 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */
102 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */ 103 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */
103 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */ 104 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */
104 {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */ 105 {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */
105 {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_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} },
106 {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ 117 {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
118 {KE_IGNORE, 0x81, {KEY_SLEEP} },
107 {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */ 119 {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */
120 {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
108 {KE_END, 0} 121 {KE_END, 0}
109}; 122};
110 123
@@ -122,6 +135,7 @@ struct event_return_value {
122 */ 135 */
123#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */ 136#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */
124#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ 137#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
138#define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */
125#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ 139#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */
126 140
127struct lm_input_params { 141struct lm_input_params {
@@ -737,8 +751,11 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
737 751
738 obj = (union acpi_object *) result.pointer; 752 obj = (union acpi_object *) result.pointer;
739 if (obj && obj->type == ACPI_TYPE_BUFFER && 753 if (obj && obj->type == ACPI_TYPE_BUFFER &&
740 obj->buffer.length == sizeof(u32)) { 754 (obj->buffer.length == sizeof(u32) ||
755 obj->buffer.length == sizeof(u64))) {
741 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;
742 } else { 759 } else {
743 tmp = 0; 760 tmp = 0;
744 } 761 }
@@ -866,8 +883,11 @@ static acpi_status WMID_set_capabilities(void)
866 883
867 obj = (union acpi_object *) out.pointer; 884 obj = (union acpi_object *) out.pointer;
868 if (obj && obj->type == ACPI_TYPE_BUFFER && 885 if (obj && obj->type == ACPI_TYPE_BUFFER &&
869 obj->buffer.length == sizeof(u32)) { 886 (obj->buffer.length == sizeof(u32) ||
887 obj->buffer.length == sizeof(u64))) {
870 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;
871 } else { 891 } else {
872 kfree(out.pointer); 892 kfree(out.pointer);
873 return AE_ERROR; 893 return AE_ERROR;
@@ -876,7 +896,8 @@ static acpi_status WMID_set_capabilities(void)
876 dmi_walk(type_aa_dmi_decode, NULL); 896 dmi_walk(type_aa_dmi_decode, NULL);
877 if (!has_type_aa) { 897 if (!has_type_aa) {
878 interface->capability |= ACER_CAP_WIRELESS; 898 interface->capability |= ACER_CAP_WIRELESS;
879 interface->capability |= ACER_CAP_THREEG; 899 if (devices & 0x40)
900 interface->capability |= ACER_CAP_THREEG;
880 if (devices & 0x10) 901 if (devices & 0x10)
881 interface->capability |= ACER_CAP_BLUETOOTH; 902 interface->capability |= ACER_CAP_BLUETOOTH;
882 } 903 }
@@ -961,10 +982,12 @@ static void __init acer_commandline_init(void)
961 * 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
962 * capability isn't available on the given interface 983 * capability isn't available on the given interface
963 */ 984 */
964 set_u32(mailled, ACER_CAP_MAILLED); 985 if (mailled >= 0)
965 if (!has_type_aa) 986 set_u32(mailled, ACER_CAP_MAILLED);
987 if (!has_type_aa && threeg >= 0)
966 set_u32(threeg, ACER_CAP_THREEG); 988 set_u32(threeg, ACER_CAP_THREEG);
967 set_u32(brightness, ACER_CAP_BRIGHTNESS); 989 if (brightness >= 0)
990 set_u32(brightness, ACER_CAP_BRIGHTNESS);
968} 991}
969 992
970/* 993/*
@@ -1081,7 +1104,7 @@ static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1081 return AE_ERROR; 1104 return AE_ERROR;
1082 } 1105 }
1083 if (obj->buffer.length != 8) { 1106 if (obj->buffer.length != 8) {
1084 pr_warning("Unknown buffer length %d\n", obj->buffer.length); 1107 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1085 kfree(obj); 1108 kfree(obj);
1086 return AE_ERROR; 1109 return AE_ERROR;
1087 } 1110 }
@@ -1090,8 +1113,8 @@ static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1090 kfree(obj); 1113 kfree(obj);
1091 1114
1092 if (return_value.error_code || return_value.ec_return_value) 1115 if (return_value.error_code || return_value.ec_return_value)
1093 pr_warning("Get Device Status failed: " 1116 pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
1094 "0x%x - 0x%x\n", return_value.error_code, 1117 return_value.error_code,
1095 return_value.ec_return_value); 1118 return_value.ec_return_value);
1096 else 1119 else
1097 *value = !!(return_value.devices & device); 1120 *value = !!(return_value.devices & device);
@@ -1124,6 +1147,114 @@ static acpi_status get_device_status(u32 *value, u32 cap)
1124 } 1147 }
1125} 1148}
1126 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
1127/* 1258/*
1128 * Rfkill devices 1259 * Rfkill devices
1129 */ 1260 */
@@ -1160,7 +1291,7 @@ static int acer_rfkill_set(void *data, bool blocked)
1160 u32 cap = (unsigned long)data; 1291 u32 cap = (unsigned long)data;
1161 1292
1162 if (rfkill_inited) { 1293 if (rfkill_inited) {
1163 status = set_u32(!blocked, cap); 1294 status = set_device_status(!blocked, cap);
1164 if (ACPI_FAILURE(status)) 1295 if (ACPI_FAILURE(status))
1165 return -ENODEV; 1296 return -ENODEV;
1166 } 1297 }
@@ -1317,7 +1448,7 @@ static void acer_wmi_notify(u32 value, void *context)
1317 1448
1318 status = wmi_get_event_data(value, &response); 1449 status = wmi_get_event_data(value, &response);
1319 if (status != AE_OK) { 1450 if (status != AE_OK) {
1320 pr_warning("bad event status 0x%x\n", status); 1451 pr_warn("bad event status 0x%x\n", status);
1321 return; 1452 return;
1322 } 1453 }
1323 1454
@@ -1326,12 +1457,12 @@ static void acer_wmi_notify(u32 value, void *context)
1326 if (!obj) 1457 if (!obj)
1327 return; 1458 return;
1328 if (obj->type != ACPI_TYPE_BUFFER) { 1459 if (obj->type != ACPI_TYPE_BUFFER) {
1329 pr_warning("Unknown response received %d\n", obj->type); 1460 pr_warn("Unknown response received %d\n", obj->type);
1330 kfree(obj); 1461 kfree(obj);
1331 return; 1462 return;
1332 } 1463 }
1333 if (obj->buffer.length != 8) { 1464 if (obj->buffer.length != 8) {
1334 pr_warning("Unknown buffer length %d\n", obj->buffer.length); 1465 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1335 kfree(obj); 1466 kfree(obj);
1336 return; 1467 return;
1337 } 1468 }
@@ -1343,7 +1474,7 @@ static void acer_wmi_notify(u32 value, void *context)
1343 case WMID_HOTKEY_EVENT: 1474 case WMID_HOTKEY_EVENT:
1344 if (return_value.device_state) { 1475 if (return_value.device_state) {
1345 u16 device_state = return_value.device_state; 1476 u16 device_state = return_value.device_state;
1346 pr_debug("deivces states: 0x%x\n", device_state); 1477 pr_debug("device state: 0x%x\n", device_state);
1347 if (has_cap(ACER_CAP_WIRELESS)) 1478 if (has_cap(ACER_CAP_WIRELESS))
1348 rfkill_set_sw_state(wireless_rfkill, 1479 rfkill_set_sw_state(wireless_rfkill,
1349 !(device_state & ACER_WMID3_GDS_WIRELESS)); 1480 !(device_state & ACER_WMID3_GDS_WIRELESS));
@@ -1356,11 +1487,11 @@ static void acer_wmi_notify(u32 value, void *context)
1356 } 1487 }
1357 if (!sparse_keymap_report_event(acer_wmi_input_dev, 1488 if (!sparse_keymap_report_event(acer_wmi_input_dev,
1358 return_value.key_num, 1, true)) 1489 return_value.key_num, 1, true))
1359 pr_warning("Unknown key number - 0x%x\n", 1490 pr_warn("Unknown key number - 0x%x\n",
1360 return_value.key_num); 1491 return_value.key_num);
1361 break; 1492 break;
1362 default: 1493 default:
1363 pr_warning("Unknown function number - %d - %d\n", 1494 pr_warn("Unknown function number - %d - %d\n",
1364 return_value.function, return_value.key_num); 1495 return_value.function, return_value.key_num);
1365 break; 1496 break;
1366 } 1497 }
@@ -1389,7 +1520,7 @@ wmid3_set_lm_mode(struct lm_input_params *params,
1389 return AE_ERROR; 1520 return AE_ERROR;
1390 } 1521 }
1391 if (obj->buffer.length != 4) { 1522 if (obj->buffer.length != 4) {
1392 pr_warning("Unknown buffer length %d\n", obj->buffer.length); 1523 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1393 kfree(obj); 1524 kfree(obj);
1394 return AE_ERROR; 1525 return AE_ERROR;
1395 } 1526 }
@@ -1414,11 +1545,11 @@ static int acer_wmi_enable_ec_raw(void)
1414 status = wmid3_set_lm_mode(&params, &return_value); 1545 status = wmid3_set_lm_mode(&params, &return_value);
1415 1546
1416 if (return_value.error_code || return_value.ec_return_value) 1547 if (return_value.error_code || return_value.ec_return_value)
1417 pr_warning("Enabling EC raw mode failed: " 1548 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",
1418 "0x%x - 0x%x\n", return_value.error_code, 1549 return_value.error_code,
1419 return_value.ec_return_value); 1550 return_value.ec_return_value);
1420 else 1551 else
1421 pr_info("Enabled EC raw mode"); 1552 pr_info("Enabled EC raw mode\n");
1422 1553
1423 return status; 1554 return status;
1424} 1555}
@@ -1437,9 +1568,9 @@ static int acer_wmi_enable_lm(void)
1437 status = wmid3_set_lm_mode(&params, &return_value); 1568 status = wmid3_set_lm_mode(&params, &return_value);
1438 1569
1439 if (return_value.error_code || return_value.ec_return_value) 1570 if (return_value.error_code || return_value.ec_return_value)
1440 pr_warning("Enabling Launch Manager failed: " 1571 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",
1441 "0x%x - 0x%x\n", return_value.error_code, 1572 return_value.error_code,
1442 return_value.ec_return_value); 1573 return_value.ec_return_value);
1443 1574
1444 return status; 1575 return status;
1445} 1576}
@@ -1506,8 +1637,11 @@ static u32 get_wmid_devices(void)
1506 1637
1507 obj = (union acpi_object *) out.pointer; 1638 obj = (union acpi_object *) out.pointer;
1508 if (obj && obj->type == ACPI_TYPE_BUFFER && 1639 if (obj && obj->type == ACPI_TYPE_BUFFER &&
1509 obj->buffer.length == sizeof(u32)) { 1640 (obj->buffer.length == sizeof(u32) ||
1641 obj->buffer.length == sizeof(u64))) {
1510 devices = *((u32 *) obj->buffer.pointer); 1642 devices = *((u32 *) obj->buffer.pointer);
1643 } else if (obj->type == ACPI_TYPE_INTEGER) {
1644 devices = (u32) obj->integer.value;
1511 } 1645 }
1512 1646
1513 kfree(out.pointer); 1647 kfree(out.pointer);