aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c174
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
2574static 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
2596static 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
2630static 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
2574static void hotkey_notify(struct ibm_struct *ibm, u32 event) 2662static 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 }