diff options
author | Shuduo Sang <shuduo.sang@canonical.com> | 2014-03-06 05:20:46 -0500 |
---|---|---|
committer | Matthew Garrett <matthew.garrett@nebula.com> | 2014-04-06 12:58:14 -0400 |
commit | 3a9d20bda1d6daae9d81a4cc4cc67238c5574d31 (patch) | |
tree | 0e6a90ddaaeeb8601ea5e6b67fd568d818c54945 /drivers/platform | |
parent | ea6b31f4946ddc527ec4eff7436727c18765d566 (diff) |
support Thinkpad X1 Carbon 2nd generation's adaptive keyboard
Submit patch V4 to support Adaptive Keyboard on Thinkpad X1 Carbon 2nd
generation according to Tobias's comments.
Thanks,
Shuduo
>From b153a7b14791c6e01892c0e274e23eefd625fb8d Mon Sep 17 00:00:00 2001
From: Shuduo Sang <shuduo.sang@canonical.com>
Date: Mon, 3 Mar 2014 14:29:32 +0800
Subject: [PATCH] support thinkpad X1 Carbon's adaptive keyboard
Thinkpad X1 Carbon's adaptive keyboard has five modes including Home
mode, Web browser mode, Web conference mode, Function mode and Lay-flat
mode. We support Home mode and Function mode currently.
Signed-off-by: Bruce Ma <bruce.ma@canonical.com>
Signed-off-by: Shuduo Sang <shuduo.sang@canonical.com>
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Diffstat (limited to 'drivers/platform')
-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 | } |