From patchwork Tue Jul 5 11:18:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9214039 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2B7146048B for ; Tue, 5 Jul 2016 11:19:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1CAC0289BF for ; Tue, 5 Jul 2016 11:19:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 10857289F7; Tue, 5 Jul 2016 11:19:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7D3A6289BF for ; Tue, 5 Jul 2016 11:19:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754978AbcGELSd (ORCPT ); Tue, 5 Jul 2016 07:18:33 -0400 Received: from mga01.intel.com ([192.55.52.88]:36887 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754970AbcGELS3 (ORCPT ); Tue, 5 Jul 2016 07:18:29 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP; 05 Jul 2016 04:18:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,579,1459839600"; d="scan'208";a="989397234" Received: from lvzheng-z530.sh.intel.com ([10.239.159.165]) by orsmga001.jf.intel.com with ESMTP; 05 Jul 2016 04:18:26 -0700 From: Lv Zheng To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org, "Bastien Nocera:" , Benjamin Tissoires , linux-input@vger.kernel.org Subject: [PATCH 4/5] ACPI / button: Add SW_ACPI_LID for new usage model Date: Tue, 5 Jul 2016 19:18:20 +0800 Message-Id: <6b1b121633175cec0a263b97e8e7a911f041c29e.1467717305.git.lv.zheng@intel.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: References: Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There are many AML tables reporting wrong initial lid state, and some of them never reports lid state. As a proxy layer acting between, ACPI button driver is not able to handle all such cases, but need to re-define the usage model of the ACPI lid. That is: 1. It's initial state is not reliable; 2. There may not be open event; 3. Userspace should only take action against the close event which is reliable, always sent after a real lid close. Link: https://lkml.org/2016/3/7/460 Link: https://github.com/systemd/systemd/issues/2087 Signed-off-by: Lv Zheng Cc: Bastien Nocera: Cc: Benjamin Tissoires Cc: linux-input@vger.kernel.org --- Documentation/acpi/acpi-lid.txt | 42 ++++++++++++++++++++++++++++++++ drivers/acpi/button.c | 20 ++++++++++----- include/linux/mod_devicetable.h | 2 +- include/uapi/linux/input-event-codes.h | 3 ++- 4 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 Documentation/acpi/acpi-lid.txt diff --git a/Documentation/acpi/acpi-lid.txt b/Documentation/acpi/acpi-lid.txt new file mode 100644 index 0000000..cba200d --- /dev/null +++ b/Documentation/acpi/acpi-lid.txt @@ -0,0 +1,42 @@ +Restrictions of ACPI Control Method LID Device + +1. Expections of _LID control method's returning value + +The _LID control method is described to return the "current" lid state. +However the word of "current" has ambiguity, many BIOSen return the lid +state upon the last lid notification instead of returning the lid state +upon the last _LID evaluation. There won't be difference when the _LID +control method is evaluated during the runtime, the problem is its initial +returning value. When the BIOSen implement this control method with cached +value, the initial returning value is likely not reliable. There are simply +so many examples always retuning "close" as initial lid state. + +2. Expections on lid events + +There are many BIOSen tables never notifying the lid open event. But it is +ensured that there is always lid close events reported when the lid is +closed. This is normally used to trigger system power saving operations on +Windows, thus it is fully tested and functions correctly. + +3. Linux ACPI Control Method LID Device Users + +The userspace should stop relying on /proc/acpi/button/lid/LID0/state to +obtain the lid state. This file is only used for the testing purpose. + +New userspace should rely on the lid close event to trigger power saving +operations and may stop taking actions according to the lid open event. A +new input event SW_ACPI_LID is prepared for the new userspace to implement +the ACPI control method lid device specific logics. + +During the period the userspace hasn't been switched to use the new +SW_ACPI_LID event, Linux users can use the following boot parameter to +handle possible issues: + button.lid_init_state=method: + This is the default behavior, Linux kernel reports initial lid state + using _LID control method's returning value. + This may fixes some platforms if the _LID control method's returning + value is reliable. + button.lid_init_state=open: + Linux kernel always reports an initial lid state as "open". + This may fixes some platforms if the _LID control method's returning + value is not reliable. diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 148f4e5..4ef94d2 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -130,7 +130,8 @@ static int acpi_lid_evaluate_state(struct acpi_device *device) return lid_state ? 1 : 0; } -static int acpi_lid_notify_state(struct acpi_device *device, int state) +static int acpi_lid_notify_state(struct acpi_device *device, + int state, bool notify_acpi) { struct acpi_button *button = acpi_driver_data(device); int ret; @@ -138,6 +139,11 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state) /* input layer checks if event is redundant */ input_report_switch(button->input, SW_LID, !state); input_sync(button->input); + if (notify_acpi) { + input_report_switch(button->input, + SW_ACPI_LID, !state); + input_sync(button->input); + } if (state) pm_wakeup_event(&device->dev, 0); @@ -279,7 +285,8 @@ int acpi_lid_open(void) } EXPORT_SYMBOL(acpi_lid_open); -static int acpi_lid_update_state(struct acpi_device *device) +static int acpi_lid_update_state(struct acpi_device *device, + bool notify_acpi) { int state; @@ -287,17 +294,17 @@ static int acpi_lid_update_state(struct acpi_device *device) if (state < 0) return state; - return acpi_lid_notify_state(device, state); + return acpi_lid_notify_state(device, state, notify_acpi); } static void acpi_lid_initialize_state(struct acpi_device *device) { switch (lid_init_state) { case ACPI_BUTTON_LID_INIT_OPEN: - (void)acpi_lid_notify_state(device, 1); + (void)acpi_lid_notify_state(device, 1, false); break; case ACPI_BUTTON_LID_INIT_METHOD: - (void)acpi_lid_update_state(device); + (void)acpi_lid_update_state(device, false); break; case ACPI_BUTTON_LID_INIT_IGNORE: default: @@ -317,7 +324,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) case ACPI_BUTTON_NOTIFY_STATUS: input = button->input; if (button->type == ACPI_BUTTON_TYPE_LID) { - acpi_lid_update_state(device); + acpi_lid_update_state(device, true); } else { int keycode; @@ -436,6 +443,7 @@ static int acpi_button_add(struct acpi_device *device) case ACPI_BUTTON_TYPE_LID: input_set_capability(input, EV_SW, SW_LID); + input_set_capability(input, EV_SW, SW_ACPI_LID); break; } diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 6e4c645..1014968 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -291,7 +291,7 @@ struct pcmcia_device_id { #define INPUT_DEVICE_ID_LED_MAX 0x0f #define INPUT_DEVICE_ID_SND_MAX 0x07 #define INPUT_DEVICE_ID_FF_MAX 0x7f -#define INPUT_DEVICE_ID_SW_MAX 0x0f +#define INPUT_DEVICE_ID_SW_MAX 0x10 #define INPUT_DEVICE_ID_MATCH_BUS 1 #define INPUT_DEVICE_ID_MATCH_VENDOR 2 diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 737fa32..81c344c 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -780,7 +780,8 @@ #define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */ #define SW_LINEIN_INSERT 0x0d /* set = inserted */ #define SW_MUTE_DEVICE 0x0e /* set = device disabled */ -#define SW_MAX 0x0f +#define SW_ACPI_LID 0x0f /* set = lid shut */ +#define SW_MAX 0x10 #define SW_CNT (SW_MAX+1) /*