diff options
| -rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index dcc833a0b2fd..d0f2a5330096 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -3437,6 +3437,106 @@ err_exit: | |||
| 3437 | return (res < 0)? res : 1; | 3437 | return (res < 0)? res : 1; |
| 3438 | } | 3438 | } |
| 3439 | 3439 | ||
| 3440 | /* Thinkpad X1 Carbon support 5 modes including Home mode, Web browser | ||
| 3441 | * mode, Web conference mode, Function mode and Lay-flat mode. | ||
| 3442 | * We support Home mode and Function mode currently. | ||
| 3443 | * | ||
| 3444 | * Will consider support rest of modes in future. | ||
| 3445 | * | ||
| 3446 | */ | ||
| 3447 | enum ADAPTIVE_KEY_MODE { | ||
| 3448 | HOME_MODE, | ||
| 3449 | WEB_BROWSER_MODE, | ||
| 3450 | WEB_CONFERENCE_MODE, | ||
| 3451 | FUNCTION_MODE, | ||
| 3452 | LAYFLAT_MODE | ||
| 3453 | }; | ||
| 3454 | |||
| 3455 | const int adaptive_keyboard_modes[] = { | ||
| 3456 | HOME_MODE, | ||
| 3457 | /* WEB_BROWSER_MODE = 2, | ||
| 3458 | WEB_CONFERENCE_MODE = 3, */ | ||
| 3459 | FUNCTION_MODE | ||
| 3460 | }; | ||
| 3461 | |||
| 3462 | #define DFR_CHANGE_ROW 0x101 | ||
| 3463 | #define DFR_SHOW_QUICKVIEW_ROW 0x102 | ||
| 3464 | |||
| 3465 | /* press Fn key a while second, it will switch to Function Mode. Then | ||
| 3466 | * release Fn key, previous mode be restored. | ||
| 3467 | */ | ||
| 3468 | static bool adaptive_keyboard_mode_is_saved; | ||
| 3469 | static int adaptive_keyboard_prev_mode; | ||
| 3470 | |||
| 3471 | static int adaptive_keyboard_get_next_mode(int mode) | ||
| 3472 | { | ||
| 3473 | size_t i; | ||
| 3474 | size_t max_mode = ARRAY_SIZE(adaptive_keyboard_modes) - 1; | ||
| 3475 | |||
| 3476 | for (i = 0; i <= max_mode; i++) { | ||
| 3477 | if (adaptive_keyboard_modes[i] == mode) | ||
| 3478 | break; | ||
| 3479 | } | ||
| 3480 | |||
| 3481 | if (i >= max_mode) | ||
| 3482 | i = 0; | ||
| 3483 | else | ||
| 3484 | i++; | ||
| 3485 | |||
| 3486 | return adaptive_keyboard_modes[i]; | ||
| 3487 | } | ||
| 3488 | |||
| 3489 | static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode) | ||
| 3490 | { | ||
| 3491 | u32 current_mode = 0; | ||
| 3492 | int new_mode = 0; | ||
| 3493 | |||
| 3494 | switch (scancode) { | ||
| 3495 | case DFR_CHANGE_ROW: | ||
| 3496 | if (adaptive_keyboard_mode_is_saved) { | ||
| 3497 | new_mode = adaptive_keyboard_prev_mode; | ||
| 3498 | adaptive_keyboard_mode_is_saved = false; | ||
| 3499 | } else { | ||
| 3500 | if (!acpi_evalf( | ||
| 3501 | hkey_handle, ¤t_mode, | ||
| 3502 | "GTRW", "dd", 0)) { | ||
| 3503 | pr_err("Cannot read adaptive keyboard mode\n"); | ||
| 3504 | return false; | ||
| 3505 | } else { | ||
| 3506 | new_mode = adaptive_keyboard_get_next_mode( | ||
| 3507 | current_mode); | ||
| 3508 | } | ||
| 3509 | } | ||
| 3510 | |||
| 3511 | if (!acpi_evalf(hkey_handle, NULL, "STRW", "vd", new_mode)) { | ||
| 3512 | pr_err("Cannot set adaptive keyboard mode\n"); | ||
| 3513 | return false; | ||
| 3514 | } | ||
| 3515 | |||
| 3516 | return true; | ||
| 3517 | |||
| 3518 | case DFR_SHOW_QUICKVIEW_ROW: | ||
| 3519 | if (!acpi_evalf(hkey_handle, | ||
| 3520 | &adaptive_keyboard_prev_mode, | ||
| 3521 | "GTRW", "dd", 0)) { | ||
| 3522 | pr_err("Cannot read adaptive keyboard mode\n"); | ||
| 3523 | return false; | ||
| 3524 | } else { | ||
| 3525 | adaptive_keyboard_mode_is_saved = true; | ||
| 3526 | |||
| 3527 | if (!acpi_evalf(hkey_handle, | ||
| 3528 | NULL, "STRW", "vd", FUNCTION_MODE)) { | ||
| 3529 | pr_err("Cannot set adaptive keyboard mode\n"); | ||
| 3530 | return false; | ||
| 3531 | } | ||
| 3532 | } | ||
| 3533 | return true; | ||
| 3534 | |||
| 3535 | default: | ||
| 3536 | return false; | ||
| 3537 | } | ||
| 3538 | } | ||
| 3539 | |||
| 3440 | static bool hotkey_notify_hotkey(const u32 hkey, | 3540 | static bool hotkey_notify_hotkey(const u32 hkey, |
| 3441 | bool *send_acpi_ev, | 3541 | bool *send_acpi_ev, |
| 3442 | bool *ignore_acpi_ev) | 3542 | bool *ignore_acpi_ev) |
| @@ -3456,6 +3556,8 @@ static bool hotkey_notify_hotkey(const u32 hkey, | |||
| 3456 | *ignore_acpi_ev = true; | 3556 | *ignore_acpi_ev = true; |
| 3457 | } | 3557 | } |
| 3458 | return true; | 3558 | return true; |
| 3559 | } else { | ||
| 3560 | return adaptive_keyboard_hotkey_notify_hotkey(scancode); | ||
| 3459 | } | 3561 | } |
| 3460 | return false; | 3562 | return false; |
| 3461 | } | 3563 | } |
