diff options
Diffstat (limited to 'drivers/platform/x86/acer-wmi.c')
-rw-r--r-- | drivers/platform/x86/acer-wmi.c | 184 |
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 | ||
99 | static const struct key_entry acer_wmi_keymap[] = { | 99 | static 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 | ||
127 | struct lm_input_params { | 141 | struct 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 | ||
1150 | static 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 | ¶ms | ||
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 | |||
1233 | static 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(¶ms, &return_value); | 1545 | status = wmid3_set_lm_mode(¶ms, &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(¶ms, &return_value); | 1568 | status = wmid3_set_lm_mode(¶ms, &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); |