diff options
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 174 |
1 files changed, 109 insertions, 65 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 7670c8ee63d1..d833ee689f90 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -2571,13 +2571,100 @@ err_exit: | |||
2571 | return (res < 0)? res : 1; | 2571 | return (res < 0)? res : 1; |
2572 | } | 2572 | } |
2573 | 2573 | ||
2574 | static bool hotkey_notify_hotkey(const u32 hkey, | ||
2575 | bool *send_acpi_ev, | ||
2576 | bool *ignore_acpi_ev) | ||
2577 | { | ||
2578 | /* 0x1000-0x1FFF: key presses */ | ||
2579 | unsigned int scancode = hkey & 0xfff; | ||
2580 | *send_acpi_ev = true; | ||
2581 | *ignore_acpi_ev = false; | ||
2582 | |||
2583 | if (scancode > 0 && scancode < 0x21) { | ||
2584 | scancode--; | ||
2585 | if (!(hotkey_source_mask & (1 << scancode))) { | ||
2586 | tpacpi_input_send_key(scancode); | ||
2587 | *send_acpi_ev = false; | ||
2588 | } else { | ||
2589 | *ignore_acpi_ev = true; | ||
2590 | } | ||
2591 | return true; | ||
2592 | } | ||
2593 | return false; | ||
2594 | } | ||
2595 | |||
2596 | static bool hotkey_notify_wakeup(const u32 hkey, | ||
2597 | bool *send_acpi_ev, | ||
2598 | bool *ignore_acpi_ev) | ||
2599 | { | ||
2600 | /* 0x2000-0x2FFF: Wakeup reason */ | ||
2601 | *send_acpi_ev = true; | ||
2602 | *ignore_acpi_ev = false; | ||
2603 | |||
2604 | switch (hkey) { | ||
2605 | case 0x2304: /* suspend, undock */ | ||
2606 | case 0x2404: /* hibernation, undock */ | ||
2607 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK; | ||
2608 | *ignore_acpi_ev = true; | ||
2609 | break; | ||
2610 | |||
2611 | case 0x2305: /* suspend, bay eject */ | ||
2612 | case 0x2405: /* hibernation, bay eject */ | ||
2613 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ; | ||
2614 | *ignore_acpi_ev = true; | ||
2615 | break; | ||
2616 | |||
2617 | default: | ||
2618 | return false; | ||
2619 | } | ||
2620 | |||
2621 | if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) { | ||
2622 | printk(TPACPI_INFO | ||
2623 | "woke up due to a hot-unplug " | ||
2624 | "request...\n"); | ||
2625 | hotkey_wakeup_reason_notify_change(); | ||
2626 | } | ||
2627 | return true; | ||
2628 | } | ||
2629 | |||
2630 | static bool hotkey_notify_usrevent(const u32 hkey, | ||
2631 | bool *send_acpi_ev, | ||
2632 | bool *ignore_acpi_ev) | ||
2633 | { | ||
2634 | /* 0x5000-0x5FFF: human interface helpers */ | ||
2635 | *send_acpi_ev = true; | ||
2636 | *ignore_acpi_ev = false; | ||
2637 | |||
2638 | switch (hkey) { | ||
2639 | case 0x5010: /* Lenovo new BIOS: brightness changed */ | ||
2640 | case 0x500b: /* X61t: tablet pen inserted into bay */ | ||
2641 | case 0x500c: /* X61t: tablet pen removed from bay */ | ||
2642 | return true; | ||
2643 | |||
2644 | case 0x5009: /* X41t-X61t: swivel up (tablet mode) */ | ||
2645 | case 0x500a: /* X41t-X61t: swivel down (normal mode) */ | ||
2646 | tpacpi_input_send_tabletsw(); | ||
2647 | hotkey_tablet_mode_notify_change(); | ||
2648 | *send_acpi_ev = false; | ||
2649 | return true; | ||
2650 | |||
2651 | case 0x5001: | ||
2652 | case 0x5002: | ||
2653 | /* LID switch events. Do not propagate */ | ||
2654 | *ignore_acpi_ev = true; | ||
2655 | return true; | ||
2656 | |||
2657 | default: | ||
2658 | return false; | ||
2659 | } | ||
2660 | } | ||
2661 | |||
2574 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 2662 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
2575 | { | 2663 | { |
2576 | u32 hkey; | 2664 | u32 hkey; |
2577 | unsigned int scancode; | 2665 | bool send_acpi_ev; |
2578 | int send_acpi_ev; | 2666 | bool ignore_acpi_ev; |
2579 | int ignore_acpi_ev; | 2667 | bool known_ev; |
2580 | int unk_ev; | ||
2581 | 2668 | ||
2582 | if (event != 0x80) { | 2669 | if (event != 0x80) { |
2583 | printk(TPACPI_ERR | 2670 | printk(TPACPI_ERR |
@@ -2601,105 +2688,62 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
2601 | return; | 2688 | return; |
2602 | } | 2689 | } |
2603 | 2690 | ||
2604 | send_acpi_ev = 1; | 2691 | send_acpi_ev = true; |
2605 | ignore_acpi_ev = 0; | 2692 | ignore_acpi_ev = false; |
2606 | unk_ev = 0; | ||
2607 | 2693 | ||
2608 | switch (hkey >> 12) { | 2694 | switch (hkey >> 12) { |
2609 | case 1: | 2695 | case 1: |
2610 | /* 0x1000-0x1FFF: key presses */ | 2696 | /* 0x1000-0x1FFF: key presses */ |
2611 | scancode = hkey & 0xfff; | 2697 | known_ev = hotkey_notify_hotkey(hkey, &send_acpi_ev, |
2612 | if (scancode > 0 && scancode < 0x21) { | 2698 | &ignore_acpi_ev); |
2613 | scancode--; | ||
2614 | if (!(hotkey_source_mask & (1 << scancode))) { | ||
2615 | tpacpi_input_send_key(scancode); | ||
2616 | send_acpi_ev = 0; | ||
2617 | } else { | ||
2618 | ignore_acpi_ev = 1; | ||
2619 | } | ||
2620 | } else { | ||
2621 | unk_ev = 1; | ||
2622 | } | ||
2623 | break; | 2699 | break; |
2624 | case 2: | 2700 | case 2: |
2625 | /* Wakeup reason */ | 2701 | /* 0x2000-0x2FFF: Wakeup reason */ |
2626 | switch (hkey) { | 2702 | known_ev = hotkey_notify_wakeup(hkey, &send_acpi_ev, |
2627 | case 0x2304: /* suspend, undock */ | 2703 | &ignore_acpi_ev); |
2628 | case 0x2404: /* hibernation, undock */ | ||
2629 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK; | ||
2630 | ignore_acpi_ev = 1; | ||
2631 | break; | ||
2632 | case 0x2305: /* suspend, bay eject */ | ||
2633 | case 0x2405: /* hibernation, bay eject */ | ||
2634 | hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ; | ||
2635 | ignore_acpi_ev = 1; | ||
2636 | break; | ||
2637 | default: | ||
2638 | unk_ev = 1; | ||
2639 | } | ||
2640 | if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) { | ||
2641 | printk(TPACPI_INFO | ||
2642 | "woke up due to a hot-unplug " | ||
2643 | "request...\n"); | ||
2644 | hotkey_wakeup_reason_notify_change(); | ||
2645 | } | ||
2646 | break; | 2704 | break; |
2647 | case 3: | 2705 | case 3: |
2648 | /* bay-related wakeups */ | 2706 | /* 0x3000-0x3FFF: bay-related wakeups */ |
2649 | if (hkey == 0x3003) { | 2707 | if (hkey == 0x3003) { |
2650 | hotkey_autosleep_ack = 1; | 2708 | hotkey_autosleep_ack = 1; |
2651 | printk(TPACPI_INFO | 2709 | printk(TPACPI_INFO |
2652 | "bay ejected\n"); | 2710 | "bay ejected\n"); |
2653 | hotkey_wakeup_hotunplug_complete_notify_change(); | 2711 | hotkey_wakeup_hotunplug_complete_notify_change(); |
2712 | known_ev = true; | ||
2654 | } else { | 2713 | } else { |
2655 | unk_ev = 1; | 2714 | known_ev = false; |
2656 | } | 2715 | } |
2657 | break; | 2716 | break; |
2658 | case 4: | 2717 | case 4: |
2659 | /* dock-related wakeups */ | 2718 | /* 0x4000-0x4FFF: dock-related wakeups */ |
2660 | if (hkey == 0x4003) { | 2719 | if (hkey == 0x4003) { |
2661 | hotkey_autosleep_ack = 1; | 2720 | hotkey_autosleep_ack = 1; |
2662 | printk(TPACPI_INFO | 2721 | printk(TPACPI_INFO |
2663 | "undocked\n"); | 2722 | "undocked\n"); |
2664 | hotkey_wakeup_hotunplug_complete_notify_change(); | 2723 | hotkey_wakeup_hotunplug_complete_notify_change(); |
2724 | known_ev = true; | ||
2665 | } else { | 2725 | } else { |
2666 | unk_ev = 1; | 2726 | known_ev = false; |
2667 | } | 2727 | } |
2668 | break; | 2728 | break; |
2669 | case 5: | 2729 | case 5: |
2670 | /* 0x5000-0x5FFF: human interface helpers */ | 2730 | /* 0x5000-0x5FFF: human interface helpers */ |
2671 | switch (hkey) { | 2731 | known_ev = hotkey_notify_usrevent(hkey, &send_acpi_ev, |
2672 | case 0x5010: /* Lenovo new BIOS: brightness changed */ | 2732 | &ignore_acpi_ev); |
2673 | case 0x500b: /* X61t: tablet pen inserted into bay */ | ||
2674 | case 0x500c: /* X61t: tablet pen removed from bay */ | ||
2675 | break; | ||
2676 | case 0x5009: /* X41t-X61t: swivel up (tablet mode) */ | ||
2677 | case 0x500a: /* X41t-X61t: swivel down (normal mode) */ | ||
2678 | tpacpi_input_send_tabletsw(); | ||
2679 | hotkey_tablet_mode_notify_change(); | ||
2680 | send_acpi_ev = 0; | ||
2681 | break; | ||
2682 | case 0x5001: | ||
2683 | case 0x5002: | ||
2684 | /* LID switch events. Do not propagate */ | ||
2685 | ignore_acpi_ev = 1; | ||
2686 | break; | ||
2687 | default: | ||
2688 | unk_ev = 1; | ||
2689 | } | ||
2690 | break; | 2733 | break; |
2691 | case 7: | 2734 | case 7: |
2692 | /* 0x7000-0x7FFF: misc */ | 2735 | /* 0x7000-0x7FFF: misc */ |
2693 | if (tp_features.hotkey_wlsw && hkey == 0x7000) { | 2736 | if (tp_features.hotkey_wlsw && hkey == 0x7000) { |
2694 | tpacpi_send_radiosw_update(); | 2737 | tpacpi_send_radiosw_update(); |
2695 | send_acpi_ev = 0; | 2738 | send_acpi_ev = 0; |
2739 | known_ev = true; | ||
2696 | break; | 2740 | break; |
2697 | } | 2741 | } |
2698 | /* fallthrough to default */ | 2742 | /* fallthrough to default */ |
2699 | default: | 2743 | default: |
2700 | unk_ev = 1; | 2744 | known_ev = false; |
2701 | } | 2745 | } |
2702 | if (unk_ev) { | 2746 | if (!known_ev) { |
2703 | printk(TPACPI_NOTICE | 2747 | printk(TPACPI_NOTICE |
2704 | "unhandled HKEY event 0x%04x\n", hkey); | 2748 | "unhandled HKEY event 0x%04x\n", hkey); |
2705 | } | 2749 | } |