From patchwork Sun Apr 23 19:40:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 9695271 X-Patchwork-Delegate: andy.shevchenko@gmail.com 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 B73FB601E9 for ; Sun, 23 Apr 2017 19:41:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8C77C26247 for ; Sun, 23 Apr 2017 19:41:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6E1BE26538; Sun, 23 Apr 2017 19:41:28 +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.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham 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 5DAF726247 for ; Sun, 23 Apr 2017 19:41:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1045895AbdDWTlU (ORCPT ); Sun, 23 Apr 2017 15:41:20 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:34948 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1045892AbdDWTlS (ORCPT ); Sun, 23 Apr 2017 15:41:18 -0400 Received: by mail-wm0-f68.google.com with SMTP id d79so13594475wmi.2; Sun, 23 Apr 2017 12:41:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=5qHRO+HS1zpoRtvOunof+u2HkNDPpcg5UW2iQcyWm2g=; b=obn3jOGEsgrlJyiJ6A8Q9X68TPvEvb5k20h6YTzz+nQpc7+IFC6McuoEf0Is89sabm TD5so3F6h+R82rhS5ZAUrJp1GricRc/7Y8zS+xHLgNtRl3QTs+Z4wT/9cJ6ObH01u2K8 dhnQ8rCoq+gwm7doAEbjWVoALYb+n10bdisxexUD1WM1VFOUzhbsvOD2HjkHRE1D6PPo dT4r37KhNoalx9vFXc5Fh4QqCfyGA7u2zLu0W2Ub/UBhHkgql+E0ZyHfQ23B7/tialax 0ic+pva2Ct0+jC53PaEKqKQ4gr2PSSstemIgLatnBuiw4d5WrRbUajlhHwx9CZdn8geY rUYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=5qHRO+HS1zpoRtvOunof+u2HkNDPpcg5UW2iQcyWm2g=; b=jWazzwphK44WgaQUCUGUN6U/BuSniNKgeHcN6mEp53q6q1sG+wIs0r+rcLk4eHmqHT 0injhcLTB9F8tBUwWHm3VY1r7LCLRjfH9W6StwqT3Tciru7CQgaT7BfqB95nTOU+puwr ZmVfi5Xpfbq0MC9aIpVN9lwHPFG/wdUbP/zk5dDxrWzeTC2/6r7+penYr+jZiFUPRHz6 3q9RCmuDwwAJgMH9+KR9Y3Li54utbqcO/B+jIC5zvQlZS7kGeAqoGHVFNP8PRYXugU42 JECfCLGqDGl7Ooq/B3Ly/4Qdp/nCVcLEcX75NgVjhn6T1OcITbmrChfrvUPtHTmMvedC yWxA== X-Gm-Message-State: AN3rC/5btbVbf0nLSPUJAb1tF/jWRHvHQ8rTz3Bc7NGUB9kqQgmsJvBS K2UeKJYwx8eoxX36 X-Received: by 10.28.17.147 with SMTP id 141mr7044284wmr.4.1492976476405; Sun, 23 Apr 2017 12:41:16 -0700 (PDT) Received: from Pali-Latitude.lan (pali.kolej.mff.cuni.cz. [78.128.193.202]) by smtp.gmail.com with ESMTPSA id x65sm10061438wmg.3.2017.04.23.12.41.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 23 Apr 2017 12:41:15 -0700 (PDT) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Matthew Garrett , Darren Hart , Andy Shevchenko , Arcadiy Ivanov , Mario Limonciello Cc: platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Pali=20Roh=C3=A1r?= Subject: [PATCH] dell-laptop: Adds support for keyboard backlight timeout AC settings Date: Sun, 23 Apr 2017 21:40:47 +0200 Message-Id: <1492976447-10339-1-git-send-email-pali.rohar@gmail.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When changing keyboard backlight state on new Dell laptops, firmware expects a new timeout AC value filled in Set New State SMBIOS call. Without it any change of keyboard backlight state on new Dell laptops fails. And user can see following error message in dmesg: dell_laptop: Setting old previous keyboard state failed leds dell::kbd_backlight: Setting an LED's brightness failed (-6) This patch adds support for retrieving current timeout AC values and also updating them. Current timeout value in sysfs is displayed based on current AC status, like current display brightness value. Detection if Dell laptop supports or not new timeout AC settings is done by checking existence of Keyboard Backlight with AC SMBIOS token (0x0451). Signed-off-by: Pali Rohár Acked-by: Mario Limonciello --- I have not tested this patch yet as I do not have affected machine. I would appreciate some testing of this patch on more new Dell laptops. Without this patch changing keyboard backlight is not possible on affected machines. --- drivers/platform/x86/dell-laptop.c | 59 ++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index f57dd28..cddf3c2 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -42,6 +42,7 @@ #define KBD_LED_AUTO_50_TOKEN 0x02EB #define KBD_LED_AUTO_75_TOKEN 0x02EC #define KBD_LED_AUTO_100_TOKEN 0x02F6 +#define KBD_LED_AC_TOKEN 0x0451 struct quirk_entry { u8 touchpad_led; @@ -1024,7 +1025,7 @@ static void touchpad_led_exit(void) * bit 2 Pointing stick * bit 3 Any mouse * bits 4-7 Reserved for future use - * cbRES2, byte3 Current Timeout + * cbRES2, byte3 Current Timeout on battery * bits 7:6 Timeout units indicator: * 00b Seconds * 01b Minutes @@ -1036,6 +1037,15 @@ static void touchpad_led_exit(void) * cbRES3, byte0 Current setting of ALS value that turns the light on or off. * cbRES3, byte1 Current ALS reading * cbRES3, byte2 Current keyboard light level. + * cbRES3, byte3 Current timeout on AC Power + * bits 7:6 Timeout units indicator: + * 00b Seconds + * 01b Minutes + * 10b Hours + * 11b Days + * Bits 5:0 Timeout value (0-63) in sec/min/hr/day + * NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte2 + * are set upon return from the upon return from the [Get Feature information] call. * * cbArg1 0x2 = Set New State * cbRES1 Standard return codes (0, -1, -2) @@ -1058,7 +1068,7 @@ static void touchpad_led_exit(void) * bit 2 Pointing stick * bit 3 Any mouse * bits 4-7 Reserved for future use - * cbArg2, byte3 Desired Timeout + * cbArg2, byte3 Desired Timeout on battery * bits 7:6 Timeout units indicator: * 00b Seconds * 01b Minutes @@ -1067,6 +1077,13 @@ static void touchpad_led_exit(void) * bits 5:0 Timeout value (0-63) in sec/min/hr/day * cbArg3, byte0 Desired setting of ALS value that turns the light on or off. * cbArg3, byte2 Desired keyboard light level. + * cbArg3, byte3 Desired Timeout on AC power + * bits 7:6 Timeout units indicator: + * 00b Seconds + * 01b Minutes + * 10b Hours + * 11b Days + * bits 5:0 Timeout value (0-63) in sec/min/hr/day */ @@ -1112,6 +1129,8 @@ struct kbd_state { u8 triggers; u8 timeout_value; u8 timeout_unit; + u8 timeout_value_ac; + u8 timeout_unit_ac; u8 als_setting; u8 als_value; u8 level; @@ -1131,6 +1150,7 @@ struct kbd_state { static struct kbd_info kbd_info; static bool kbd_als_supported; static bool kbd_triggers_supported; +static bool kbd_timeout_ac_supported; static u8 kbd_mode_levels[16]; static int kbd_mode_levels_count; @@ -1269,6 +1289,8 @@ static int kbd_get_state(struct kbd_state *state) state->als_setting = buffer->output[2] & 0xFF; state->als_value = (buffer->output[2] >> 8) & 0xFF; state->level = (buffer->output[2] >> 16) & 0xFF; + state->timeout_value_ac = (buffer->output[2] >> 24) & 0x3F; + state->timeout_unit_ac = (buffer->output[2] >> 30) & 0x3; out: dell_smbios_release_buffer(); @@ -1288,6 +1310,8 @@ static int kbd_set_state(struct kbd_state *state) buffer->input[1] |= (state->timeout_unit & 0x3) << 30; buffer->input[2] = state->als_setting & 0xFF; buffer->input[2] |= (state->level & 0xFF) << 16; + buffer->input[2] |= (state->timeout_value_ac & 0x3F) << 24; + buffer->input[2] |= (state->timeout_unit_ac & 0x3) << 30; dell_smbios_send_request(4, 11); ret = buffer->output[0]; dell_smbios_release_buffer(); @@ -1394,6 +1418,13 @@ static inline int kbd_init_info(void) if (ret) return ret; + /* NOTE: Old models without KBD_LED_AC_TOKEN token supports only one + * timeout value which is shared for both battery and AC power + * settings. So do not try to set AC values on old models. + */ + if (dell_smbios_find_token(KBD_LED_AC_TOKEN)) + kbd_timeout_ac_supported = true; + kbd_get_state(&state); /* NOTE: timeout value is stored in 6 bits so max value is 63 */ @@ -1573,8 +1604,14 @@ static ssize_t kbd_led_timeout_store(struct device *dev, return ret; new_state = state; - new_state.timeout_value = value; - new_state.timeout_unit = unit; + + if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) { + new_state.timeout_value_ac = value; + new_state.timeout_unit_ac = unit; + } else { + new_state.timeout_value = value; + new_state.timeout_unit = unit; + } ret = kbd_set_state_safe(&new_state, &state); if (ret) @@ -1587,16 +1624,26 @@ static ssize_t kbd_led_timeout_show(struct device *dev, struct device_attribute *attr, char *buf) { struct kbd_state state; + int value; int ret; int len; + u8 unit; ret = kbd_get_state(&state); if (ret) return ret; - len = sprintf(buf, "%d", state.timeout_value); + if (kbd_timeout_ac_supported && power_supply_is_system_supplied() > 0) { + value = state.timeout_value_ac; + unit = state.timeout_unit_ac; + } else { + value = state.timeout_value; + unit = state.timeout_unit; + } + + len = sprintf(buf, "%d", value); - switch (state.timeout_unit) { + switch (unit) { case KBD_TIMEOUT_SECONDS: return len + sprintf(buf+len, "s\n"); case KBD_TIMEOUT_MINUTES: