diff options
| -rw-r--r-- | drivers/platform/x86/acer-wmi.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index d80db0899382..ee40d681edd0 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
| @@ -129,6 +129,20 @@ struct event_return_value { | |||
| 129 | #define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ | 129 | #define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ |
| 130 | #define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ | 130 | #define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ |
| 131 | 131 | ||
| 132 | struct lm_input_params { | ||
| 133 | u8 function_num; /* Function Number */ | ||
| 134 | u16 commun_devices; /* Communication type devices default status */ | ||
| 135 | u16 devices; /* Other type devices default status */ | ||
| 136 | u8 lm_status; /* Launch Manager Status */ | ||
| 137 | u16 reserved; | ||
| 138 | } __attribute__((packed)); | ||
| 139 | |||
| 140 | struct lm_return_value { | ||
| 141 | u8 error_code; /* Error Code */ | ||
| 142 | u8 ec_return_value; /* EC Return Value */ | ||
| 143 | u16 reserved; | ||
| 144 | } __attribute__((packed)); | ||
| 145 | |||
| 132 | struct wmid3_gds_input_param { /* Get Device Status input parameter */ | 146 | struct wmid3_gds_input_param { /* Get Device Status input parameter */ |
| 133 | u8 function_num; /* Function Number */ | 147 | u8 function_num; /* Function Number */ |
| 134 | u8 hotkey_number; /* Hotkey Number */ | 148 | u8 hotkey_number; /* Hotkey Number */ |
| @@ -179,16 +193,19 @@ static int mailled = -1; | |||
| 179 | static int brightness = -1; | 193 | static int brightness = -1; |
| 180 | static int threeg = -1; | 194 | static int threeg = -1; |
| 181 | static int force_series; | 195 | static int force_series; |
| 196 | static bool ec_raw_mode; | ||
| 182 | static bool has_type_aa; | 197 | static bool has_type_aa; |
| 183 | 198 | ||
| 184 | module_param(mailled, int, 0444); | 199 | module_param(mailled, int, 0444); |
| 185 | module_param(brightness, int, 0444); | 200 | module_param(brightness, int, 0444); |
| 186 | module_param(threeg, int, 0444); | 201 | module_param(threeg, int, 0444); |
| 187 | module_param(force_series, int, 0444); | 202 | module_param(force_series, int, 0444); |
| 203 | module_param(ec_raw_mode, bool, 0444); | ||
| 188 | MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); | 204 | MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); |
| 189 | MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); | 205 | MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); |
| 190 | MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); | 206 | MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); |
| 191 | MODULE_PARM_DESC(force_series, "Force a different laptop series"); | 207 | MODULE_PARM_DESC(force_series, "Force a different laptop series"); |
| 208 | MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode"); | ||
| 192 | 209 | ||
| 193 | struct acer_data { | 210 | struct acer_data { |
| 194 | int mailled; | 211 | int mailled; |
| @@ -1330,6 +1347,85 @@ static void acer_wmi_notify(u32 value, void *context) | |||
| 1330 | } | 1347 | } |
| 1331 | } | 1348 | } |
| 1332 | 1349 | ||
| 1350 | static acpi_status | ||
| 1351 | wmid3_set_lm_mode(struct lm_input_params *params, | ||
| 1352 | struct lm_return_value *return_value) | ||
| 1353 | { | ||
| 1354 | acpi_status status; | ||
| 1355 | union acpi_object *obj; | ||
| 1356 | |||
| 1357 | struct acpi_buffer input = { sizeof(struct lm_input_params), params }; | ||
| 1358 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 1359 | |||
| 1360 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output); | ||
| 1361 | if (ACPI_FAILURE(status)) | ||
| 1362 | return status; | ||
| 1363 | |||
| 1364 | obj = output.pointer; | ||
| 1365 | |||
| 1366 | if (!obj) | ||
| 1367 | return AE_ERROR; | ||
| 1368 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
| 1369 | kfree(obj); | ||
| 1370 | return AE_ERROR; | ||
| 1371 | } | ||
| 1372 | if (obj->buffer.length != 4) { | ||
| 1373 | printk(ACER_WARNING "Unknown buffer length %d\n", | ||
| 1374 | obj->buffer.length); | ||
| 1375 | kfree(obj); | ||
| 1376 | return AE_ERROR; | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | *return_value = *((struct lm_return_value *)obj->buffer.pointer); | ||
| 1380 | kfree(obj); | ||
| 1381 | |||
| 1382 | return status; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | static int acer_wmi_enable_ec_raw(void) | ||
| 1386 | { | ||
| 1387 | struct lm_return_value return_value; | ||
| 1388 | acpi_status status; | ||
| 1389 | struct lm_input_params params = { | ||
| 1390 | .function_num = 0x1, | ||
| 1391 | .commun_devices = 0xFFFF, | ||
| 1392 | .devices = 0xFFFF, | ||
| 1393 | .lm_status = 0x00, /* Launch Manager Deactive */ | ||
| 1394 | }; | ||
| 1395 | |||
| 1396 | status = wmid3_set_lm_mode(¶ms, &return_value); | ||
| 1397 | |||
| 1398 | if (return_value.error_code || return_value.ec_return_value) | ||
| 1399 | printk(ACER_WARNING "Enabling EC raw mode failed: " | ||
| 1400 | "0x%x - 0x%x\n", return_value.error_code, | ||
| 1401 | return_value.ec_return_value); | ||
| 1402 | else | ||
| 1403 | printk(ACER_INFO "Enabled EC raw mode"); | ||
| 1404 | |||
| 1405 | return status; | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | static int acer_wmi_enable_lm(void) | ||
| 1409 | { | ||
| 1410 | struct lm_return_value return_value; | ||
| 1411 | acpi_status status; | ||
| 1412 | struct lm_input_params params = { | ||
| 1413 | .function_num = 0x1, | ||
| 1414 | .commun_devices = 0xFFFF, | ||
| 1415 | .devices = 0xFFFF, | ||
| 1416 | .lm_status = 0x01, /* Launch Manager Active */ | ||
| 1417 | }; | ||
| 1418 | |||
| 1419 | status = wmid3_set_lm_mode(¶ms, &return_value); | ||
| 1420 | |||
| 1421 | if (return_value.error_code || return_value.ec_return_value) | ||
| 1422 | printk(ACER_WARNING "Enabling Launch Manager failed: " | ||
| 1423 | "0x%x - 0x%x\n", return_value.error_code, | ||
| 1424 | return_value.ec_return_value); | ||
| 1425 | |||
| 1426 | return status; | ||
| 1427 | } | ||
| 1428 | |||
| 1333 | static int __init acer_wmi_input_setup(void) | 1429 | static int __init acer_wmi_input_setup(void) |
| 1334 | { | 1430 | { |
| 1335 | acpi_status status; | 1431 | acpi_status status; |
| @@ -1618,6 +1714,20 @@ static int __init acer_wmi_init(void) | |||
| 1618 | "generic video driver\n"); | 1714 | "generic video driver\n"); |
| 1619 | } | 1715 | } |
| 1620 | 1716 | ||
| 1717 | if (wmi_has_guid(WMID_GUID3)) { | ||
| 1718 | if (ec_raw_mode) { | ||
| 1719 | if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) { | ||
| 1720 | printk(ACER_ERR "Cannot enable EC raw mode\n"); | ||
| 1721 | return -ENODEV; | ||
| 1722 | } | ||
| 1723 | } else if (ACPI_FAILURE(acer_wmi_enable_lm())) { | ||
| 1724 | printk(ACER_ERR "Cannot enable Launch Manager mode\n"); | ||
| 1725 | return -ENODEV; | ||
| 1726 | } | ||
| 1727 | } else if (ec_raw_mode) { | ||
| 1728 | printk(ACER_INFO "No WMID EC raw mode enable method\n"); | ||
| 1729 | } | ||
| 1730 | |||
| 1621 | if (wmi_has_guid(ACERWMID_EVENT_GUID)) { | 1731 | if (wmi_has_guid(ACERWMID_EVENT_GUID)) { |
| 1622 | err = acer_wmi_input_setup(); | 1732 | err = acer_wmi_input_setup(); |
| 1623 | if (err) | 1733 | if (err) |
