Message ID | 20230630041743.911303-2-luke@ljones.dev |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp10092689vqr; Thu, 29 Jun 2023 21:21:29 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4+FL2yvxnCgn5GfhZqz963P01apJNh9yqx0qyEJbyCl/PI+bsmptkHbKzKUrX2xfg2h4RH X-Received: by 2002:a05:6a20:8f03:b0:116:696f:1dd1 with SMTP id b3-20020a056a208f0300b00116696f1dd1mr2189787pzk.4.1688098889543; Thu, 29 Jun 2023 21:21:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688098889; cv=none; d=google.com; s=arc-20160816; b=AVgT+dxfyC9i4h/OGbfXSmlOMa4nNPnz2mlJ7jDMtmvaFpKo75DVCclHpzMDyvyuVZ AxtJiycl8eV/m+3v7mBCBB7rgvmnnZfw7Ff3nI+m73CXod7AGHfWAuT3PkeTswhai0Qr 9Ch7n8hNrrJsgNLbfIe3nuUeqypdTQWylxyQsBWpEGMZVoQR3l3W/EyTrXE+fxYEQRhP xla0NbYI4G10r6twuQzmgK16fjhM4PlghJt9JaOA3L6QvjqAfCrKIFyrgW1+iNkGTJyF +bC1u6nuYWTPTkkOWcEfDgtRZRo/UyTQce1BiNIUkVl0XhWxifnG+xlJmSOWvDU+AYCy /9DA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :feedback-id:dkim-signature:dkim-signature; bh=H/pUv3JCTYWhxJUqPomsdfiSjJ4CWy36omlus/C29XY=; fh=52RqnqzHFu3c3gS8VqgRtcRPBRgGlf5eGe8HkjfR8FI=; b=waZIMjZYf1GQOUNjFyCeiJnRvmoNqfFp+Frv8XntuF6kXKgsqgGlQDEmVGTF1dyD7c p5rmS3y8waUjId/nQAnd9z8aKq+98D5rdxFhquTL7pTvjwLxS3efG10sYoTDsxf+fRtF SNFKswZZqBeKjUiuNDd2TMw8HKar/71ZQAvUFzV5cUKEloUHxHUR7KjN1hsGgJi1CgJb rbtgwaPFwTylPSAYjG0isuMEBo+qUQaWBy6oNh0mFHLA/e4OU5reI3uRotq66nc4m3/r p9vGQXkW3Zj3Dvi61xfuY2xRe2s36lJ+0xUdWGIeNWlf9jUEunA3htfLe1/Tr1CrxqLR nbMw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ljones.dev header.s=fm3 header.b="SlrdTj/0"; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b=pTW9Xr46; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t10-20020a63534a000000b0054fcef3f7b7si11555718pgl.539.2023.06.29.21.21.15; Thu, 29 Jun 2023 21:21:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@ljones.dev header.s=fm3 header.b="SlrdTj/0"; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b=pTW9Xr46; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232125AbjF3ESL (ORCPT <rfc822;ivan.orlov0322@gmail.com> + 99 others); Fri, 30 Jun 2023 00:18:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50120 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230410AbjF3ESH (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 30 Jun 2023 00:18:07 -0400 Received: from wout5-smtp.messagingengine.com (wout5-smtp.messagingengine.com [64.147.123.21]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C66F62D78; Thu, 29 Jun 2023 21:18:05 -0700 (PDT) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.west.internal (Postfix) with ESMTP id 74CD53200993; Fri, 30 Jun 2023 00:18:04 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Fri, 30 Jun 2023 00:18:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ljones.dev; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm3; t=1688098683; x= 1688185083; bh=H/pUv3JCTYWhxJUqPomsdfiSjJ4CWy36omlus/C29XY=; b=S lrdTj/0us1dt4y+be3qEc470vYYYbpkXQsNd/PD/zrIc9PmeWiXoUbNWxdcdjlin /vdfEKGbMI6cLwtZjJm87LyByQP7f/Jmcx/W+Z29ojZUmRma5OlkBjVjDEx4Gnp7 e7xAkjxMI0f5mG6j1psobZs4ty6e7GtybP46oZGwf1WXfl8k/ymSmsQKQp5s2WQ4 Tx63Do/EEyJbqUVi3PGMsLzEq3j3hCoP81U1AzNeTbZFmJlpmQ8Pp//LCrPcGzsi bAPUwbj5IklG/EiHJ5vCoZU7RZE+b56uAHcaLKuB4igsLBY6TA1IMmvV7EgP8MiU Wcrxn2vt929COhvLQQvdA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1688098683; x= 1688185083; bh=H/pUv3JCTYWhxJUqPomsdfiSjJ4CWy36omlus/C29XY=; b=p TW9Xr46DmOYa/irZY0maKloJxYvC8LskpBq2ofcM19DpyhjaedyvfZmPC8Srx4Bq Nf8ZPVOqe8A/mKAvQA6Im+jDeWdFeJGeCgzS9TlAwfzuSlgjnL7s7k176cZPD1ME Piux2G/wdPuo+THF4M+hsmpmQ6CCo/gRKChQbIuC4yoyt6sWDYFZe+Xl1qRPP74M J/7QFBWfRdbQwHCnwzFaG4ASCQzaMHMrEaeJVdi2JWxGbNNwoUmsxXgVy5EI1KI5 xyAo1ddIL2ykF8WOTociQqvfBi0VHfAn3UNoyBHhFW8DcjLm9l0DPZR1/ZwwxNZ1 wVzNStnmxk3aIfn/QDapQ== X-ME-Sender: <xms:e1eeZBthdS9QGbxmfL2rTnCertl5hcEEx83jPfN1U1KhTF0R-Ebtqg> <xme:e1eeZKe2EuHW7iBuHbzAch4jRkxazkY3PhTBRsMXciiSfNAJtHfJV726ASDWfu4y5 kkBqlHeVKm6wdt6x5s> X-ME-Received: <xmr:e1eeZEwnZtDRIQTLRJgxOABMGS4B3Kcr3ybRU_Gud80LqJNObE2scyqUI3ST> X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedviedrtdehgdekgecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhephffvvefufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpefgteefudfgteduueehteejhfeugf fgleeltedvveethfeuueejfedvgeelveehgfenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghv X-ME-Proxy: <xmx:e1eeZINvwOkQ4k65HlYt43jTEkMWSp0LyuMq6DuBzpa34W3eHMHKdQ> <xmx:e1eeZB_xJg7NWrlq7Gg-sAouylm5KYV3aMrdONGlXxcRKnv6mDnLcg> <xmx:e1eeZIUgsa65VFQbSNqfRxzfyn1nB8jqETLaELMgK4K3Y5kUPglucQ> <xmx:e1eeZKM4Q6GhJd80PJ9jEvS4DOIT30M36Asc5ITHWu_-X9d1tPYGqA> Feedback-ID: i5ec1447f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 30 Jun 2023 00:18:00 -0400 (EDT) From: "Luke D. Jones" <luke@ljones.dev> To: hdegoede@redhat.com Cc: corentin.chary@gmail.com, acpi4asus-user@lists.sourceforge.net, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, markgross@kernel.org, jdelvare@suse.com, linux@roeck-us.net, "Luke D. Jones" <luke@ljones.dev> Subject: [PATCH v4 1/1] platform/x86: asus-wmi: add support for ASUS screenpad Date: Fri, 30 Jun 2023 16:17:43 +1200 Message-ID: <20230630041743.911303-2-luke@ljones.dev> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230630041743.911303-1-luke@ljones.dev> References: <20230630041743.911303-1-luke@ljones.dev> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS, SPF_NONE,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1770099981113233723?= X-GMAIL-MSGID: =?utf-8?q?1770099981113233723?= |
Series |
asus-wmi: add support for ASUS screenpad
|
|
Commit Message
Luke Jones
June 30, 2023, 4:17 a.m. UTC
Add support for the WMI methods used to turn off and adjust the
brightness of the secondary "screenpad" device found on some high-end
ASUS laptops like the GX650P series and others.
These methods are utilised in a new backlight device named asus_screenpad.
Signed-off-by: Luke D. Jones <luke@ljones.dev>
---
drivers/platform/x86/asus-wmi.c | 128 +++++++++++++++++++++
drivers/platform/x86/asus-wmi.h | 1 +
include/linux/platform_data/x86/asus-wmi.h | 4 +
3 files changed, 133 insertions(+)
Comments
Hi Luke, On 6/30/23 06:17, Luke D. Jones wrote: > Add support for the WMI methods used to turn off and adjust the > brightness of the secondary "screenpad" device found on some high-end > ASUS laptops like the GX650P series and others. > > These methods are utilised in a new backlight device named asus_screenpad. > > Signed-off-by: Luke D. Jones <luke@ljones.dev> Thank you for your work on this. I have one small change request and then v5 should be ready for merging, see me inline comment below. > --- > drivers/platform/x86/asus-wmi.c | 128 +++++++++++++++++++++ > drivers/platform/x86/asus-wmi.h | 1 + > include/linux/platform_data/x86/asus-wmi.h | 4 + > 3 files changed, 133 insertions(+) > > diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c > index 62cee13f5576..967c92ceb041 100644 > --- a/drivers/platform/x86/asus-wmi.c > +++ b/drivers/platform/x86/asus-wmi.c > @@ -25,6 +25,7 @@ > #include <linux/input/sparse-keymap.h> > #include <linux/kernel.h> > #include <linux/leds.h> > +#include <linux/minmax.h> > #include <linux/module.h> > #include <linux/pci.h> > #include <linux/pci_hotplug.h> > @@ -212,6 +213,7 @@ struct asus_wmi { > > struct input_dev *inputdev; > struct backlight_device *backlight_device; > + struct backlight_device *screenpad_backlight_device; > struct platform_device *platform_device; > > struct led_classdev wlan_led; > @@ -3839,6 +3841,123 @@ static int is_display_toggle(int code) > return 0; > } > > +/* Screenpad backlight *******************************************************/ > + > +static int read_screenpad_backlight_power(struct asus_wmi *asus) > +{ > + int ret; > + > + ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_SCREENPAD_POWER); > + if (ret < 0) > + return ret; > + /* 1 == powered */ > + return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; > +} > + > +static int read_screenpad_brightness(struct backlight_device *bd) > +{ > + struct asus_wmi *asus = bl_get_data(bd); > + u32 retval; > + int err; > + > + err = read_screenpad_backlight_power(asus); > + if (err < 0) > + return err; > + /* The device brightness can only be read if powered, so return stored */ > + if (err == FB_BLANK_POWERDOWN) > + return asus->driver->screenpad_brightness; > + > + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); > + if (err < 0) > + return err; > + > + return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; > +} > + > +static int update_screenpad_bl_status(struct backlight_device *bd) > +{ > + struct asus_wmi *asus = bl_get_data(bd); > + int power, err = 0; > + u32 ctrl_param; > + > + power = read_screenpad_backlight_power(asus); > + if (power < 0) > + return power; > + > + if (bd->props.power != power) { > + if (power != FB_BLANK_UNBLANK) { > + /* Only brightness > 0 can power it back on */ > + ctrl_param = max(1, asus->driver->screenpad_brightness); > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, > + ctrl_param, NULL); > + } else { > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL); > + } > + } else if (power == FB_BLANK_UNBLANK) { > + /* Only set brightness if powered on or we get invalid/unsync state */ > + ctrl_param = bd->props.brightness; > + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, NULL); > + } > + > + /* Ensure brightness is stored to turn back on with */ > + asus->driver->screenpad_brightness = bd->props.brightness; > + > + return err; > +} > + > +static const struct backlight_ops asus_screenpad_bl_ops = { > + .get_brightness = read_screenpad_brightness, > + .update_status = update_screenpad_bl_status, > + .options = BL_CORE_SUSPENDRESUME, > +}; > + > +static int asus_screenpad_init(struct asus_wmi *asus) > +{ > + struct backlight_device *bd; > + struct backlight_properties props; > + int err, power; > + int brightness = 0; > + > + power = read_screenpad_backlight_power(asus); > + if (power < 0) > + return power; > + > + if (power != FB_BLANK_POWERDOWN) { > + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness); > + if (err < 0) > + return err; > + } > + /* default to an acceptable min brightness on boot if too low */ > + if (brightness < 60) > + brightness = 60; If settings below 60 are no good, then the correct way to handle this is to limit the range to 0 - (255-60) and add / substract 60 when setting / getting the brightness. E.g. do something like this: #define SCREENPAD_MIN_BRIGHTNESS 60 #define SCREENPAD_MAX_BRIGHTNESS 255 props.max_brightness = SCREENPAD_MAX_BRIGHTNESS - SCREENPAD_MIN_BRIGHTNESS; And in update_screenpad_bl_status() do: ctrl_param = bd->props.brightness + SCREENPAD_MIN_BRIGHTNESS; And when reading the brightness substract SCREENPAD_MIN_BRIGHTNESS, clamping to a minimum value of 0. This avoids a dead-zone in the brightness range between 0-60 . Regards, Hans > + > + memset(&props, 0, sizeof(struct backlight_properties)); > + props.type = BACKLIGHT_RAW; /* ensure this bd is last to be picked */ > + props.max_brightness = 255; > + bd = backlight_device_register("asus_screenpad", > + &asus->platform_device->dev, asus, > + &asus_screenpad_bl_ops, &props); > + if (IS_ERR(bd)) { > + pr_err("Could not register backlight device\n"); > + return PTR_ERR(bd); > + } > + > + asus->screenpad_backlight_device = bd; > + asus->driver->screenpad_brightness = brightness; > + bd->props.brightness = brightness; > + bd->props.power = power; > + backlight_update_status(bd); > + > + return 0; > +} > + > +static void asus_screenpad_exit(struct asus_wmi *asus) > +{ > + backlight_device_unregister(asus->screenpad_backlight_device); > + > + asus->screenpad_backlight_device = NULL; > +} > + > /* Fn-lock ********************************************************************/ > > static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus) > @@ -4504,6 +4623,12 @@ static int asus_wmi_add(struct platform_device *pdev) > } else if (asus->driver->quirks->wmi_backlight_set_devstate) > err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL); > > + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT)) { > + err = asus_screenpad_init(asus); > + if (err && err != -ENODEV) > + goto fail_screenpad; > + } > + > if (asus_wmi_has_fnlock_key(asus)) { > asus->fnlock_locked = fnlock_default; > asus_wmi_fnlock_update(asus); > @@ -4527,6 +4652,8 @@ static int asus_wmi_add(struct platform_device *pdev) > asus_wmi_backlight_exit(asus); > fail_backlight: > asus_wmi_rfkill_exit(asus); > +fail_screenpad: > + asus_screenpad_exit(asus); > fail_rfkill: > asus_wmi_led_exit(asus); > fail_leds: > @@ -4553,6 +4680,7 @@ static int asus_wmi_remove(struct platform_device *device) > asus = platform_get_drvdata(device); > wmi_remove_notify_handler(asus->driver->event_guid); > asus_wmi_backlight_exit(asus); > + asus_screenpad_exit(asus); > asus_wmi_input_exit(asus); > asus_wmi_led_exit(asus); > asus_wmi_rfkill_exit(asus); > diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h > index a478ebfd34df..5fbdd0eafa02 100644 > --- a/drivers/platform/x86/asus-wmi.h > +++ b/drivers/platform/x86/asus-wmi.h > @@ -57,6 +57,7 @@ struct quirk_entry { > struct asus_wmi_driver { > int brightness; > int panel_power; > + int screenpad_brightness; > int wlan_ctrl_by_user; > > const char *name; > diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h > index d17ae2eb0f8d..61ba70b32846 100644 > --- a/include/linux/platform_data/x86/asus-wmi.h > +++ b/include/linux/platform_data/x86/asus-wmi.h > @@ -58,6 +58,10 @@ > #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 > #define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */ > #define ASUS_WMI_DEVID_LIGHTBAR 0x00050025 > +/* This can only be used to disable the screen, not re-enable */ > +#define ASUS_WMI_DEVID_SCREENPAD_POWER 0x00050031 > +/* Writing a brightness re-enables the screen if disabled */ > +#define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032 > #define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 > #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 >
On Tue, 2023-07-04 at 13:16 +0200, Hans de Goede wrote: > Hi Luke, > > On 6/30/23 06:17, Luke D. Jones wrote: > > Add support for the WMI methods used to turn off and adjust the > > brightness of the secondary "screenpad" device found on some high- > > end > > ASUS laptops like the GX650P series and others. > > > > These methods are utilised in a new backlight device named > > asus_screenpad. > > > > Signed-off-by: Luke D. Jones <luke@ljones.dev> > > Thank you for your work on this. I have one small change request > and then v5 should be ready for merging, see me inline comment > below. > > > --- > > drivers/platform/x86/asus-wmi.c | 128 > > +++++++++++++++++++++ > > drivers/platform/x86/asus-wmi.h | 1 + > > include/linux/platform_data/x86/asus-wmi.h | 4 + > > 3 files changed, 133 insertions(+) > > > > diff --git a/drivers/platform/x86/asus-wmi.c > > b/drivers/platform/x86/asus-wmi.c > > index 62cee13f5576..967c92ceb041 100644 > > --- a/drivers/platform/x86/asus-wmi.c > > +++ b/drivers/platform/x86/asus-wmi.c > > @@ -25,6 +25,7 @@ > > #include <linux/input/sparse-keymap.h> > > #include <linux/kernel.h> > > #include <linux/leds.h> > > +#include <linux/minmax.h> > > #include <linux/module.h> > > #include <linux/pci.h> > > #include <linux/pci_hotplug.h> > > @@ -212,6 +213,7 @@ struct asus_wmi { > > > > struct input_dev *inputdev; > > struct backlight_device *backlight_device; > > + struct backlight_device *screenpad_backlight_device; > > struct platform_device *platform_device; > > > > struct led_classdev wlan_led; > > @@ -3839,6 +3841,123 @@ static int is_display_toggle(int code) > > return 0; > > } > > > > +/* Screenpad backlight > > *******************************************************/ > > + > > +static int read_screenpad_backlight_power(struct asus_wmi *asus) > > +{ > > + int ret; > > + > > + ret = asus_wmi_get_devstate_simple(asus, > > ASUS_WMI_DEVID_SCREENPAD_POWER); > > + if (ret < 0) > > + return ret; > > + /* 1 == powered */ > > + return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; > > +} > > + > > +static int read_screenpad_brightness(struct backlight_device *bd) > > +{ > > + struct asus_wmi *asus = bl_get_data(bd); > > + u32 retval; > > + int err; > > + > > + err = read_screenpad_backlight_power(asus); > > + if (err < 0) > > + return err; > > + /* The device brightness can only be read if powered, so > > return stored */ > > + if (err == FB_BLANK_POWERDOWN) > > + return asus->driver->screenpad_brightness; > > + > > + err = asus_wmi_get_devstate(asus, > > ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); > > + if (err < 0) > > + return err; > > + > > + return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; > > +} > > + > > +static int update_screenpad_bl_status(struct backlight_device *bd) > > +{ > > + struct asus_wmi *asus = bl_get_data(bd); > > + int power, err = 0; > > + u32 ctrl_param; > > + > > + power = read_screenpad_backlight_power(asus); > > + if (power < 0) > > + return power; > > + > > + if (bd->props.power != power) { > > + if (power != FB_BLANK_UNBLANK) { > > + /* Only brightness > 0 can power it back on > > */ > > + ctrl_param = max(1, asus->driver- > > >screenpad_brightness); > > + err = > > asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, > > + ctrl_param, > > NULL); > > + } else { > > + err = > > asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL); > > + } > > + } else if (power == FB_BLANK_UNBLANK) { > > + /* Only set brightness if powered on or we get > > invalid/unsync state */ > > + ctrl_param = bd->props.brightness; > > + err = > > asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, > > NULL); > > + } > > + > > + /* Ensure brightness is stored to turn back on with */ > > + asus->driver->screenpad_brightness = bd->props.brightness; > > + > > + return err; > > +} > > + > > +static const struct backlight_ops asus_screenpad_bl_ops = { > > + .get_brightness = read_screenpad_brightness, > > + .update_status = update_screenpad_bl_status, > > + .options = BL_CORE_SUSPENDRESUME, > > +}; > > + > > +static int asus_screenpad_init(struct asus_wmi *asus) > > +{ > > + struct backlight_device *bd; > > + struct backlight_properties props; > > + int err, power; > > + int brightness = 0; > > + > > + power = read_screenpad_backlight_power(asus); > > + if (power < 0) > > + return power; > > + > > + if (power != FB_BLANK_POWERDOWN) { > > + err = asus_wmi_get_devstate(asus, > > ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness); > > + if (err < 0) > > + return err; > > + } > > + /* default to an acceptable min brightness on boot if too > > low */ > > + if (brightness < 60) > > + brightness = 60; > > If settings below 60 are no good, then the correct way to handle > this is to limit the range to 0 - (255-60) and add / substract > 60 when setting / getting the brightness. > > E.g. do something like this: > > #define SCREENPAD_MIN_BRIGHTNESS 60 > #define SCREENPAD_MAX_BRIGHTNESS 255 > > props.max_brightness = SCREENPAD_MAX_BRIGHTNESS - > SCREENPAD_MIN_BRIGHTNESS; > > And in update_screenpad_bl_status() do: > > ctrl_param = bd->props.brightness + SCREENPAD_MIN_BRIGHTNESS; > > And when reading the brightness substract SCREENPAD_MIN_BRIGHTNESS, > clamping to a minimum value of 0. > > This avoids a dead-zone in the brightness range between 0-60 . Hi Hans, I think this is the wrong thing to do. The initial point of that first `brightness = 60;` is only to set it to an acceptable brightness on boot. We don't want to prevent the user from going below that brightness at all - this is just to ensure the screen is visible on boot if the brightness was under that value, and it is usually only under that value if it was set to off before shutdown/reboot. It's not to try and put the range between 60-255, it's just to make the screen visible on boot if it was off previously. The folks who have tested this have found that this is the desired behaviour they expect. Cheers, Luke. > > > + > > + memset(&props, 0, sizeof(struct backlight_properties)); > > + props.type = BACKLIGHT_RAW; /* ensure this bd is last to be > > picked */ > > + props.max_brightness = 255; > > + bd = backlight_device_register("asus_screenpad", > > + &asus->platform_device->dev, > > asus, > > + &asus_screenpad_bl_ops, > > &props); > > + if (IS_ERR(bd)) { > > + pr_err("Could not register backlight device\n"); > > + return PTR_ERR(bd); > > + } > > + > > + asus->screenpad_backlight_device = bd; > > + asus->driver->screenpad_brightness = brightness; > > + bd->props.brightness = brightness; > > + bd->props.power = power; > > + backlight_update_status(bd); > > + > > + return 0; > > +} > > + > > +static void asus_screenpad_exit(struct asus_wmi *asus) > > +{ > > + backlight_device_unregister(asus- > > >screenpad_backlight_device); > > + > > + asus->screenpad_backlight_device = NULL; > > +} > > + > > /* Fn-lock > > ******************************************************************* > > */ > > > > static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus) > > @@ -4504,6 +4623,12 @@ static int asus_wmi_add(struct > > platform_device *pdev) > > } else if (asus->driver->quirks- > > >wmi_backlight_set_devstate) > > err = > > asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL); > > > > + if (asus_wmi_dev_is_present(asus, > > ASUS_WMI_DEVID_SCREENPAD_LIGHT)) { > > + err = asus_screenpad_init(asus); > > + if (err && err != -ENODEV) > > + goto fail_screenpad; > > + } > > + > > if (asus_wmi_has_fnlock_key(asus)) { > > asus->fnlock_locked = fnlock_default; > > asus_wmi_fnlock_update(asus); > > @@ -4527,6 +4652,8 @@ static int asus_wmi_add(struct > > platform_device *pdev) > > asus_wmi_backlight_exit(asus); > > fail_backlight: > > asus_wmi_rfkill_exit(asus); > > +fail_screenpad: > > + asus_screenpad_exit(asus); > > fail_rfkill: > > asus_wmi_led_exit(asus); > > fail_leds: > > @@ -4553,6 +4680,7 @@ static int asus_wmi_remove(struct > > platform_device *device) > > asus = platform_get_drvdata(device); > > wmi_remove_notify_handler(asus->driver->event_guid); > > asus_wmi_backlight_exit(asus); > > + asus_screenpad_exit(asus); > > asus_wmi_input_exit(asus); > > asus_wmi_led_exit(asus); > > asus_wmi_rfkill_exit(asus); > > diff --git a/drivers/platform/x86/asus-wmi.h > > b/drivers/platform/x86/asus-wmi.h > > index a478ebfd34df..5fbdd0eafa02 100644 > > --- a/drivers/platform/x86/asus-wmi.h > > +++ b/drivers/platform/x86/asus-wmi.h > > @@ -57,6 +57,7 @@ struct quirk_entry { > > struct asus_wmi_driver { > > int brightness; > > int panel_power; > > + int screenpad_brightness; > > int wlan_ctrl_by_user; > > > > const char *name; > > diff --git a/include/linux/platform_data/x86/asus-wmi.h > > b/include/linux/platform_data/x86/asus-wmi.h > > index d17ae2eb0f8d..61ba70b32846 100644 > > --- a/include/linux/platform_data/x86/asus-wmi.h > > +++ b/include/linux/platform_data/x86/asus-wmi.h > > @@ -58,6 +58,10 @@ > > #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 > > #define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */ > > #define ASUS_WMI_DEVID_LIGHTBAR 0x00050025 > > +/* This can only be used to disable the screen, not re-enable */ > > +#define ASUS_WMI_DEVID_SCREENPAD_POWER 0x00050031 > > +/* Writing a brightness re-enables the screen if disabled */ > > +#define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032 > > #define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 > > #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 > > >
Hi, On 7/7/23 00:23, Luke Jones wrote: > On Tue, 2023-07-04 at 13:16 +0200, Hans de Goede wrote: >> Hi Luke, >> >> On 6/30/23 06:17, Luke D. Jones wrote: >>> Add support for the WMI methods used to turn off and adjust the >>> brightness of the secondary "screenpad" device found on some high- >>> end >>> ASUS laptops like the GX650P series and others. >>> >>> These methods are utilised in a new backlight device named >>> asus_screenpad. >>> >>> Signed-off-by: Luke D. Jones <luke@ljones.dev> >> >> Thank you for your work on this. I have one small change request >> and then v5 should be ready for merging, see me inline comment >> below. >> >>> --- >>> drivers/platform/x86/asus-wmi.c | 128 >>> +++++++++++++++++++++ >>> drivers/platform/x86/asus-wmi.h | 1 + >>> include/linux/platform_data/x86/asus-wmi.h | 4 + >>> 3 files changed, 133 insertions(+) >>> >>> diff --git a/drivers/platform/x86/asus-wmi.c >>> b/drivers/platform/x86/asus-wmi.c >>> index 62cee13f5576..967c92ceb041 100644 >>> --- a/drivers/platform/x86/asus-wmi.c >>> +++ b/drivers/platform/x86/asus-wmi.c >>> @@ -25,6 +25,7 @@ >>> #include <linux/input/sparse-keymap.h> >>> #include <linux/kernel.h> >>> #include <linux/leds.h> >>> +#include <linux/minmax.h> >>> #include <linux/module.h> >>> #include <linux/pci.h> >>> #include <linux/pci_hotplug.h> >>> @@ -212,6 +213,7 @@ struct asus_wmi { >>> >>> struct input_dev *inputdev; >>> struct backlight_device *backlight_device; >>> + struct backlight_device *screenpad_backlight_device; >>> struct platform_device *platform_device; >>> >>> struct led_classdev wlan_led; >>> @@ -3839,6 +3841,123 @@ static int is_display_toggle(int code) >>> return 0; >>> } >>> >>> +/* Screenpad backlight >>> *******************************************************/ >>> + >>> +static int read_screenpad_backlight_power(struct asus_wmi *asus) >>> +{ >>> + int ret; >>> + >>> + ret = asus_wmi_get_devstate_simple(asus, >>> ASUS_WMI_DEVID_SCREENPAD_POWER); >>> + if (ret < 0) >>> + return ret; >>> + /* 1 == powered */ >>> + return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; >>> +} >>> + >>> +static int read_screenpad_brightness(struct backlight_device *bd) >>> +{ >>> + struct asus_wmi *asus = bl_get_data(bd); >>> + u32 retval; >>> + int err; >>> + >>> + err = read_screenpad_backlight_power(asus); >>> + if (err < 0) >>> + return err; >>> + /* The device brightness can only be read if powered, so >>> return stored */ >>> + if (err == FB_BLANK_POWERDOWN) >>> + return asus->driver->screenpad_brightness; >>> + >>> + err = asus_wmi_get_devstate(asus, >>> ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); >>> + if (err < 0) >>> + return err; >>> + >>> + return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; >>> +} >>> + >>> +static int update_screenpad_bl_status(struct backlight_device *bd) >>> +{ >>> + struct asus_wmi *asus = bl_get_data(bd); >>> + int power, err = 0; >>> + u32 ctrl_param; >>> + >>> + power = read_screenpad_backlight_power(asus); >>> + if (power < 0) >>> + return power; >>> + >>> + if (bd->props.power != power) { >>> + if (power != FB_BLANK_UNBLANK) { >>> + /* Only brightness > 0 can power it back on >>> */ >>> + ctrl_param = max(1, asus->driver- >>>> screenpad_brightness); >>> + err = >>> asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, >>> + ctrl_param, >>> NULL); >>> + } else { >>> + err = >>> asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL); >>> + } >>> + } else if (power == FB_BLANK_UNBLANK) { >>> + /* Only set brightness if powered on or we get >>> invalid/unsync state */ >>> + ctrl_param = bd->props.brightness; >>> + err = >>> asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, >>> NULL); >>> + } >>> + >>> + /* Ensure brightness is stored to turn back on with */ >>> + asus->driver->screenpad_brightness = bd->props.brightness; >>> + >>> + return err; >>> +} >>> + >>> +static const struct backlight_ops asus_screenpad_bl_ops = { >>> + .get_brightness = read_screenpad_brightness, >>> + .update_status = update_screenpad_bl_status, >>> + .options = BL_CORE_SUSPENDRESUME, >>> +}; >>> + >>> +static int asus_screenpad_init(struct asus_wmi *asus) >>> +{ >>> + struct backlight_device *bd; >>> + struct backlight_properties props; >>> + int err, power; >>> + int brightness = 0; >>> + >>> + power = read_screenpad_backlight_power(asus); >>> + if (power < 0) >>> + return power; >>> + >>> + if (power != FB_BLANK_POWERDOWN) { >>> + err = asus_wmi_get_devstate(asus, >>> ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness); >>> + if (err < 0) >>> + return err; >>> + } >>> + /* default to an acceptable min brightness on boot if too >>> low */ >>> + if (brightness < 60) >>> + brightness = 60; >> >> If settings below 60 are no good, then the correct way to handle >> this is to limit the range to 0 - (255-60) and add / substract >> 60 when setting / getting the brightness. >> >> E.g. do something like this: >> >> #define SCREENPAD_MIN_BRIGHTNESS 60 >> #define SCREENPAD_MAX_BRIGHTNESS 255 >> >> props.max_brightness = SCREENPAD_MAX_BRIGHTNESS - >> SCREENPAD_MIN_BRIGHTNESS; >> >> And in update_screenpad_bl_status() do: >> >> ctrl_param = bd->props.brightness + SCREENPAD_MIN_BRIGHTNESS; >> >> And when reading the brightness substract SCREENPAD_MIN_BRIGHTNESS, >> clamping to a minimum value of 0. >> >> This avoids a dead-zone in the brightness range between 0-60 . > > Hi Hans, I think this is the wrong thing to do. > > The initial point of that first `brightness = 60;` is only to set it to > an acceptable brightness on boot. We don't want to prevent the user > from going below that brightness at all - this is just to ensure the > screen is visible on boot if the brightness was under that value, and > it is usually only under that value if it was set to off before > shutdown/reboot. > > It's not to try and put the range between 60-255, it's just to make the > screen visible on boot if it was off previously. The folks who have > tested this have found that this is the desired behaviour they expect. I see. So if I understand things correctly then 60 is a good default, but the screen can go darker and still be usable. But 1 leads to an unusable screen, so we still need a SCREENPAD_MIN_BRIGHTNESS to avoid the screen being able to go so dark that it is no longer usable and then still move the range a bit, but just not by 60, but by some other number (something in the 10-30 range I guess?) Combined with adding a: #define SCREENPAD_DEFAULT_BRIGHTNESS 60 And at boot when the read back brightness < SCREENPAD_MIN_BRIGHTNESS set it to SCREENPAD_DEFAULT_BRIGHTNESS. We really want to avoid users to be able to set an unusable low brightness level. As mentioned in the new panel brightness API proposal: https://lore.kernel.org/dri-devel/b61d3eeb-6213-afac-2e70-7b9791c86d2e@redhat.com/ "3. The meaning of 0 is not clearly defined, it can be either off, or minimum brightness at which the display is still readable (in a low light environment)" and the plan going forward is to: "Unlike the /sys/class/backlight/foo/brightness this brightness property has a clear definition for the value 0. The kernel must ensure that 0 means minimum brightness (so 0 should _never_ turn the backlight off). If necessary the kernel must enforce a minimum value by adding an offset to the value seen in the property to ensure this behavior." So I really want to see this new backlight driver implement the new planned behavior for 0 from the start, with 0 meaning minimum *usable* brightness. Regards, Hans
On Tue, Jul 11 2023 at 11:42:25 +02:00:00, Hans de Goede <hdegoede@redhat.com> wrote: > Hi, > > On 7/7/23 00:23, Luke Jones wrote: >> On Tue, 2023-07-04 at 13:16 +0200, Hans de Goede wrote: >>> Hi Luke, >>> >>> On 6/30/23 06:17, Luke D. Jones wrote: >>>> Add support for the WMI methods used to turn off and adjust the >>>> brightness of the secondary "screenpad" device found on some high- >>>> end >>>> ASUS laptops like the GX650P series and others. >>>> >>>> These methods are utilised in a new backlight device named >>>> asus_screenpad. >>>> >>>> Signed-off-by: Luke D. Jones <luke@ljones.dev> >>> >>> Thank you for your work on this. I have one small change request >>> and then v5 should be ready for merging, see me inline comment >>> below. >>> >>>> --- >>>> drivers/platform/x86/asus-wmi.c | 128 >>>> +++++++++++++++++++++ >>>> drivers/platform/x86/asus-wmi.h | 1 + >>>> include/linux/platform_data/x86/asus-wmi.h | 4 + >>>> 3 files changed, 133 insertions(+) >>>> >>>> diff --git a/drivers/platform/x86/asus-wmi.c >>>> b/drivers/platform/x86/asus-wmi.c >>>> index 62cee13f5576..967c92ceb041 100644 >>>> --- a/drivers/platform/x86/asus-wmi.c >>>> +++ b/drivers/platform/x86/asus-wmi.c >>>> @@ -25,6 +25,7 @@ >>>> #include <linux/input/sparse-keymap.h> >>>> #include <linux/kernel.h> >>>> #include <linux/leds.h> >>>> +#include <linux/minmax.h> >>>> #include <linux/module.h> >>>> #include <linux/pci.h> >>>> #include <linux/pci_hotplug.h> >>>> @@ -212,6 +213,7 @@ struct asus_wmi { >>>> >>>> struct input_dev *inputdev; >>>> struct backlight_device *backlight_device; >>>> + struct backlight_device *screenpad_backlight_device; >>>> struct platform_device *platform_device; >>>> >>>> struct led_classdev wlan_led; >>>> @@ -3839,6 +3841,123 @@ static int is_display_toggle(int code) >>>> return 0; >>>> } >>>> >>>> +/* Screenpad backlight >>>> *******************************************************/ >>>> + >>>> +static int read_screenpad_backlight_power(struct asus_wmi *asus) >>>> +{ >>>> + int ret; >>>> + >>>> + ret = asus_wmi_get_devstate_simple(asus, >>>> ASUS_WMI_DEVID_SCREENPAD_POWER); >>>> + if (ret < 0) >>>> + return ret; >>>> + /* 1 == powered */ >>>> + return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; >>>> +} >>>> + >>>> +static int read_screenpad_brightness(struct backlight_device *bd) >>>> +{ >>>> + struct asus_wmi *asus = bl_get_data(bd); >>>> + u32 retval; >>>> + int err; >>>> + >>>> + err = read_screenpad_backlight_power(asus); >>>> + if (err < 0) >>>> + return err; >>>> + /* The device brightness can only be read if powered, so >>>> return stored */ >>>> + if (err == FB_BLANK_POWERDOWN) >>>> + return asus->driver->screenpad_brightness; >>>> + >>>> + err = asus_wmi_get_devstate(asus, >>>> ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); >>>> + if (err < 0) >>>> + return err; >>>> + >>>> + return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; >>>> +} >>>> + >>>> +static int update_screenpad_bl_status(struct backlight_device >>>> *bd) >>>> +{ >>>> + struct asus_wmi *asus = bl_get_data(bd); >>>> + int power, err = 0; >>>> + u32 ctrl_param; >>>> + >>>> + power = read_screenpad_backlight_power(asus); >>>> + if (power < 0) >>>> + return power; >>>> + >>>> + if (bd->props.power != power) { >>>> + if (power != FB_BLANK_UNBLANK) { >>>> + /* Only brightness > 0 can power it back >>>> on >>>> */ >>>> + ctrl_param = max(1, asus->driver- >>>>> screenpad_brightness); >>>> + err = >>>> asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, >>>> + ctrl_param, >>>> NULL); >>>> + } else { >>>> + err = >>>> asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL); >>>> + } >>>> + } else if (power == FB_BLANK_UNBLANK) { >>>> + /* Only set brightness if powered on or we get >>>> invalid/unsync state */ >>>> + ctrl_param = bd->props.brightness; >>>> + err = >>>> asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, >>>> NULL); >>>> + } >>>> + >>>> + /* Ensure brightness is stored to turn back on with */ >>>> + asus->driver->screenpad_brightness = bd->props.brightness; >>>> + >>>> + return err; >>>> +} >>>> + >>>> +static const struct backlight_ops asus_screenpad_bl_ops = { >>>> + .get_brightness = read_screenpad_brightness, >>>> + .update_status = update_screenpad_bl_status, >>>> + .options = BL_CORE_SUSPENDRESUME, >>>> +}; >>>> + >>>> +static int asus_screenpad_init(struct asus_wmi *asus) >>>> +{ >>>> + struct backlight_device *bd; >>>> + struct backlight_properties props; >>>> + int err, power; >>>> + int brightness = 0; >>>> + >>>> + power = read_screenpad_backlight_power(asus); >>>> + if (power < 0) >>>> + return power; >>>> + >>>> + if (power != FB_BLANK_POWERDOWN) { >>>> + err = asus_wmi_get_devstate(asus, >>>> ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness); >>>> + if (err < 0) >>>> + return err; >>>> + } >>>> + /* default to an acceptable min brightness on boot if too >>>> low */ >>>> + if (brightness < 60) >>>> + brightness = 60; >>> >>> If settings below 60 are no good, then the correct way to handle >>> this is to limit the range to 0 - (255-60) and add / substract >>> 60 when setting / getting the brightness. >>> >>> E.g. do something like this: >>> >>> #define SCREENPAD_MIN_BRIGHTNESS 60 >>> #define SCREENPAD_MAX_BRIGHTNESS 255 >>> >>> props.max_brightness = SCREENPAD_MAX_BRIGHTNESS - >>> SCREENPAD_MIN_BRIGHTNESS; >>> >>> And in update_screenpad_bl_status() do: >>> >>> ctrl_param = bd->props.brightness + >>> SCREENPAD_MIN_BRIGHTNESS; >>> >>> And when reading the brightness substract SCREENPAD_MIN_BRIGHTNESS, >>> clamping to a minimum value of 0. >>> >>> This avoids a dead-zone in the brightness range between 0-60 . >> >> Hi Hans, I think this is the wrong thing to do. >> >> The initial point of that first `brightness = 60;` is only to set >> it to >> an acceptable brightness on boot. We don't want to prevent the user >> from going below that brightness at all - this is just to ensure the >> screen is visible on boot if the brightness was under that value, >> and >> it is usually only under that value if it was set to off before >> shutdown/reboot. >> >> It's not to try and put the range between 60-255, it's just to make >> the >> screen visible on boot if it was off previously. The folks who have >> tested this have found that this is the desired behaviour they >> expect. > > I see. > > So if I understand things correctly then 60 is a good default, > but the screen can go darker and still be usable. > > But 1 leads to an unusable screen, so we still need > a SCREENPAD_MIN_BRIGHTNESS to avoid the screen being able > to go so dark that it is no longer usable and then still > move the range a bit, but just not by 60, but by some > other number (something in the 10-30 range I guess?) > > Combined with adding a: > > #define SCREENPAD_DEFAULT_BRIGHTNESS 60 > > And at boot when the read back brightness < > SCREENPAD_MIN_BRIGHTNESS set it to SCREENPAD_DEFAULT_BRIGHTNESS. > > We really want to avoid users to be able to set an unusable > low brightness level. As mentioned in the new panel brightness > API proposal: > > https://lore.kernel.org/dri-devel/b61d3eeb-6213-afac-2e70-7b9791c86d2e@redhat.com/ > > "3. The meaning of 0 is not clearly defined, it can be either off, > or minimum brightness at which the display is still readable > (in a low light environment)" > > and the plan going forward is to: > > "Unlike the /sys/class/backlight/foo/brightness this brightness > property > has a clear definition for the value 0. The kernel must ensure that 0 > means minimum brightness (so 0 should _never_ turn the backlight off). > If necessary the kernel must enforce a minimum value by adding > an offset to the value seen in the property to ensure this behavior." > > So I really want to see this new backlight driver implement the > new planned behavior for 0 from the start, with 0 meaning minimum > *usable* brightness. Hi Hans, yeah okay that makes sense. I'll get on to it. Cheers, Luke.
Hi 2023. július 11., kedd 11:42 keltezéssel, Hans de Goede <hdegoede@redhat.com> írta: > [...] > >> > >> If settings below 60 are no good, then the correct way to handle > >> this is to limit the range to 0 - (255-60) and add / substract > >> 60 when setting / getting the brightness. > >> > >> E.g. do something like this: > >> > >> #define SCREENPAD_MIN_BRIGHTNESS 60 > >> #define SCREENPAD_MAX_BRIGHTNESS 255 > >> > >> props.max_brightness = SCREENPAD_MAX_BRIGHTNESS - > >> SCREENPAD_MIN_BRIGHTNESS; > >> > >> And in update_screenpad_bl_status() do: > >> > >> ctrl_param = bd->props.brightness + SCREENPAD_MIN_BRIGHTNESS; > >> > >> And when reading the brightness substract SCREENPAD_MIN_BRIGHTNESS, > >> clamping to a minimum value of 0. > >> > >> This avoids a dead-zone in the brightness range between 0-60 . > > > > Hi Hans, I think this is the wrong thing to do. > > > > The initial point of that first `brightness = 60;` is only to set it to > > an acceptable brightness on boot. We don't want to prevent the user > > from going below that brightness at all - this is just to ensure the > > screen is visible on boot if the brightness was under that value, and > > it is usually only under that value if it was set to off before > > shutdown/reboot. > > > > It's not to try and put the range between 60-255, it's just to make the > > screen visible on boot if it was off previously. The folks who have > > tested this have found that this is the desired behaviour they expect. > > I see. > > So if I understand things correctly then 60 is a good default, > but the screen can go darker and still be usable. > > But 1 leads to an unusable screen, so we still need > a SCREENPAD_MIN_BRIGHTNESS to avoid the screen being able > to go so dark that it is no longer usable and then still > move the range a bit, but just not by 60, but by some > other number (something in the 10-30 range I guess?) > > Combined with adding a: > > #define SCREENPAD_DEFAULT_BRIGHTNESS 60 > > And at boot when the read back brightness < > SCREENPAD_MIN_BRIGHTNESS set it to SCREENPAD_DEFAULT_BRIGHTNESS. > > We really want to avoid users to be able to set an unusable > low brightness level. As mentioned in the new panel brightness > API proposal: > > https://lore.kernel.org/dri-devel/b61d3eeb-6213-afac-2e70-7b9791c86d2e@redhat.com/ > > "3. The meaning of 0 is not clearly defined, it can be either off, > or minimum brightness at which the display is still readable > (in a low light environment)" > > and the plan going forward is to: > > "Unlike the /sys/class/backlight/foo/brightness this brightness property > has a clear definition for the value 0. The kernel must ensure that 0 > means minimum brightness (so 0 should _never_ turn the backlight off). > If necessary the kernel must enforce a minimum value by adding > an offset to the value seen in the property to ensure this behavior." > > So I really want to see this new backlight driver implement the > new planned behavior for 0 from the start, with 0 meaning minimum > *usable* brightness. > > Regards, > > Hans Sorry for hijacking this thread, but then how can I turn backlight off? I quite liked how I was able to turn my laptop display (almost) completely off with the brightness hotkeys / brightness slider in gnome-shell, and I was quite annoyed when this was changed in gnome-settings-daemon and forced the minimum brightness to be 1% of max_brightness. (https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/merge_requests/17) Also, "minimum brightness at which the display is still readable" is not really well-defined, so it can (will) happen that the minimum brightness values don't match, so it is theoretically possible that I cannot set both my laptop panel and external monitor to the same desired brightness level. Or am I missing something? Regards, Barnabás Pőcze
Hi, On 7/12/23 03:07, Barnabás Pőcze wrote: > Hi > > > 2023. július 11., kedd 11:42 keltezéssel, Hans de Goede <hdegoede@redhat.com> írta: > >> [...] >>>> >>>> If settings below 60 are no good, then the correct way to handle >>>> this is to limit the range to 0 - (255-60) and add / substract >>>> 60 when setting / getting the brightness. >>>> >>>> E.g. do something like this: >>>> >>>> #define SCREENPAD_MIN_BRIGHTNESS 60 >>>> #define SCREENPAD_MAX_BRIGHTNESS 255 >>>> >>>> props.max_brightness = SCREENPAD_MAX_BRIGHTNESS - >>>> SCREENPAD_MIN_BRIGHTNESS; >>>> >>>> And in update_screenpad_bl_status() do: >>>> >>>> ctrl_param = bd->props.brightness + SCREENPAD_MIN_BRIGHTNESS; >>>> >>>> And when reading the brightness substract SCREENPAD_MIN_BRIGHTNESS, >>>> clamping to a minimum value of 0. >>>> >>>> This avoids a dead-zone in the brightness range between 0-60 . >>> >>> Hi Hans, I think this is the wrong thing to do. >>> >>> The initial point of that first `brightness = 60;` is only to set it to >>> an acceptable brightness on boot. We don't want to prevent the user >>> from going below that brightness at all - this is just to ensure the >>> screen is visible on boot if the brightness was under that value, and >>> it is usually only under that value if it was set to off before >>> shutdown/reboot. >>> >>> It's not to try and put the range between 60-255, it's just to make the >>> screen visible on boot if it was off previously. The folks who have >>> tested this have found that this is the desired behaviour they expect. >> >> I see. >> >> So if I understand things correctly then 60 is a good default, >> but the screen can go darker and still be usable. >> >> But 1 leads to an unusable screen, so we still need >> a SCREENPAD_MIN_BRIGHTNESS to avoid the screen being able >> to go so dark that it is no longer usable and then still >> move the range a bit, but just not by 60, but by some >> other number (something in the 10-30 range I guess?) >> >> Combined with adding a: >> >> #define SCREENPAD_DEFAULT_BRIGHTNESS 60 >> >> And at boot when the read back brightness < >> SCREENPAD_MIN_BRIGHTNESS set it to SCREENPAD_DEFAULT_BRIGHTNESS. >> >> We really want to avoid users to be able to set an unusable >> low brightness level. As mentioned in the new panel brightness >> API proposal: >> >> https://lore.kernel.org/dri-devel/b61d3eeb-6213-afac-2e70-7b9791c86d2e@redhat.com/ >> >> "3. The meaning of 0 is not clearly defined, it can be either off, >> or minimum brightness at which the display is still readable >> (in a low light environment)" >> >> and the plan going forward is to: >> >> "Unlike the /sys/class/backlight/foo/brightness this brightness property >> has a clear definition for the value 0. The kernel must ensure that 0 >> means minimum brightness (so 0 should _never_ turn the backlight off). >> If necessary the kernel must enforce a minimum value by adding >> an offset to the value seen in the property to ensure this behavior." >> >> So I really want to see this new backlight driver implement the >> new planned behavior for 0 from the start, with 0 meaning minimum >> *usable* brightness. >> >> Regards, >> >> Hans > > > Sorry for hijacking this thread, but then how can I turn backlight off? Documentation/ABI/stable/sysfs-class-backlight What: /sys/class/backlight/<backlight>/bl_power Date: April 2005 KernelVersion: 2.6.12 Contact: Richard Purdie <rpurdie@rpsys.net> Description: Control BACKLIGHT power, values are FB_BLANK_* from fb.h - FB_BLANK_UNBLANK (0) : power on. - FB_BLANK_POWERDOWN (4) : power off Although it is better to actually disable video output on the connector, this leads to much bigger power savings. Under X, this can typically be done by hitting the lock-screen option, e.g. "Windows-logo-key + L" under GNOME. On the console you can do: echo 1 > /sys/class/graphics/fb0/blank To really put the panel in low power mode. > I quite liked how I was able to turn my laptop display (almost) completely off > with the brightness hotkeys / brightness slider in gnome-shell, and I was quite > annoyed when this was changed in gnome-settings-daemon and forced the minimum > brightness to be 1% of max_brightness. Right, there are 2 problems with this: 1. Using brightness control to disable the backlight is not reliabl. Many backlight control methods only go to some low setting not to completely off. This differs from model laptop to model laptop. Also e.g. amdgpu and radeonhd have always ensured that brightness never completely turns of the backlight. The plan going forward is to try and consistently have 0 mean minimum backlight and not backlight off, instead of the current some models 0 = off, some models 0 is works fine in a not too brightly lit room. 2. Users sometimes turn of the backlight through e.g. the GNOME system menu slider and then have no way to turn it back on (on devices without (working) brightness hotkeys (they cannot use the slider since they can no longer see it) This scenario is a real problem which used to result in quite a few bug reports. > Also, "minimum brightness at which the display is still readable" is not really > well-defined True, as mentioned above the minimum might only be good enough to e.g. read text in a somewhat low lit room, but typically it at least leaves things visible enough to allow a user to change the brightness to a better setting. What we don't want is brightness settings so low that the backlight is essentially off (does not even show any light in a fully dark room). > so it can (will) happen that the minimum brightness values don't match, > so it is theoretically possible that I cannot set both my laptop panel and external > monitor to the same desired brightness level. Or am I missing something? This already is the case, some monitors may not go as low (or high) as you want, some laptops also already don't go as low as you want. Expecting to be able to match monitor and laptop panel brightness at both ends of the brightness range simply is not realistic. Regards, Hans
Hi 2023. július 12., szerda 20:44 keltezéssel, Hans de Goede <hdegoede@redhat.com> írta: > Hi, > > On 7/12/23 03:07, Barnabás Pőcze wrote: > > Hi > > > > > > 2023. július 11., kedd 11:42 keltezéssel, Hans de Goede <hdegoede@redhat.com> írta: > > > >> [...] > >>>> > >>>> If settings below 60 are no good, then the correct way to handle > >>>> this is to limit the range to 0 - (255-60) and add / substract > >>>> 60 when setting / getting the brightness. > >>>> > >>>> E.g. do something like this: > >>>> > >>>> #define SCREENPAD_MIN_BRIGHTNESS 60 > >>>> #define SCREENPAD_MAX_BRIGHTNESS 255 > >>>> > >>>> props.max_brightness = SCREENPAD_MAX_BRIGHTNESS - > >>>> SCREENPAD_MIN_BRIGHTNESS; > >>>> > >>>> And in update_screenpad_bl_status() do: > >>>> > >>>> ctrl_param = bd->props.brightness + SCREENPAD_MIN_BRIGHTNESS; > >>>> > >>>> And when reading the brightness substract SCREENPAD_MIN_BRIGHTNESS, > >>>> clamping to a minimum value of 0. > >>>> > >>>> This avoids a dead-zone in the brightness range between 0-60 . > >>> > >>> Hi Hans, I think this is the wrong thing to do. > >>> > >>> The initial point of that first `brightness = 60;` is only to set it to > >>> an acceptable brightness on boot. We don't want to prevent the user > >>> from going below that brightness at all - this is just to ensure the > >>> screen is visible on boot if the brightness was under that value, and > >>> it is usually only under that value if it was set to off before > >>> shutdown/reboot. > >>> > >>> It's not to try and put the range between 60-255, it's just to make the > >>> screen visible on boot if it was off previously. The folks who have > >>> tested this have found that this is the desired behaviour they expect. > >> > >> I see. > >> > >> So if I understand things correctly then 60 is a good default, > >> but the screen can go darker and still be usable. > >> > >> But 1 leads to an unusable screen, so we still need > >> a SCREENPAD_MIN_BRIGHTNESS to avoid the screen being able > >> to go so dark that it is no longer usable and then still > >> move the range a bit, but just not by 60, but by some > >> other number (something in the 10-30 range I guess?) > >> > >> Combined with adding a: > >> > >> #define SCREENPAD_DEFAULT_BRIGHTNESS 60 > >> > >> And at boot when the read back brightness < > >> SCREENPAD_MIN_BRIGHTNESS set it to SCREENPAD_DEFAULT_BRIGHTNESS. > >> > >> We really want to avoid users to be able to set an unusable > >> low brightness level. As mentioned in the new panel brightness > >> API proposal: > >> > >> https://lore.kernel.org/dri-devel/b61d3eeb-6213-afac-2e70-7b9791c86d2e@redhat.com/ > >> > >> "3. The meaning of 0 is not clearly defined, it can be either off, > >> or minimum brightness at which the display is still readable > >> (in a low light environment)" > >> > >> and the plan going forward is to: > >> > >> "Unlike the /sys/class/backlight/foo/brightness this brightness property > >> has a clear definition for the value 0. The kernel must ensure that 0 > >> means minimum brightness (so 0 should _never_ turn the backlight off). > >> If necessary the kernel must enforce a minimum value by adding > >> an offset to the value seen in the property to ensure this behavior." > >> > >> So I really want to see this new backlight driver implement the > >> new planned behavior for 0 from the start, with 0 meaning minimum > >> *usable* brightness. > >> > >> Regards, > >> > >> Hans > > > > > > Sorry for hijacking this thread, but then how can I turn backlight off? > > Documentation/ABI/stable/sysfs-class-backlight > > What: /sys/class/backlight/<backlight>/bl_power > Date: April 2005 > KernelVersion: 2.6.12 > Contact: Richard Purdie <rpurdie@rpsys.net> > Description: > Control BACKLIGHT power, values are FB_BLANK_* from fb.h > > - FB_BLANK_UNBLANK (0) : power on. > - FB_BLANK_POWERDOWN (4) : power off > > Although it is better to actually disable video output on the connector, > this leads to much bigger power savings. Under X, this can typically be > done by hitting the lock-screen option, e.g. "Windows-logo-key + L" under > GNOME. Super+L locks the screen for me on GNOME, which is decidedly *not* what I want to achieve. I just want to disable the backlight on the laptop panel without any other changes whatsoever. Writing 4 to /sys/class/backlight/<backlight>/bl_power does essentially what I want. > > On the console you can do: > > echo 1 > /sys/class/graphics/fb0/blank > > To really put the panel in low power mode. I never doubted it could still be done. I guess what I wanted to say is "convenience". Using the brightness slider / hotkeys is very convenient, much more convenient than messing with getting the right permissions to be able to write to /sys/class/backlight/<backlight>/bl_power or /sys/class/graphics/fb0/blank. > > > > > I quite liked how I was able to turn my laptop display (almost) completely off > > with the brightness hotkeys / brightness slider in gnome-shell, and I was quite > > annoyed when this was changed in gnome-settings-daemon and forced the minimum > > brightness to be 1% of max_brightness. > > Right, there are 2 problems with this: > > 1. Using brightness control to disable the backlight is not reliabl. Many > backlight control methods only go to some low setting not to completely off. > This differs from model laptop to model laptop. Also e.g. amdgpu and radeonhd > have always ensured that brightness never completely turns of the backlight. > > The plan going forward is to try and consistently have 0 mean minimum > backlight and not backlight off, instead of the current some models 0 = off, > some models 0 is works fine in a not too brightly lit room. That is good to know, I did not realize that was the case thanks to my intel_backlight bias... > > 2. Users sometimes turn of the backlight through e.g. the GNOME system menu > slider and then have no way to turn it back on (on devices without (working) > brightness hotkeys (they cannot use the slider since they can no longer see it) > This scenario is a real problem which used to result in quite a few bug reports. Of course I understand why that change was made in e.g. gnome-settings-daemon. However, the same way gnome-tweaks has a switch for enabling volume levels greater than 100%, there could be a switch for enabling the full brightness scale. > > > Also, "minimum brightness at which the display is still readable" is not really > > well-defined > > True, as mentioned above the minimum might only be good enough to > e.g. read text in a somewhat low lit room, but typically it at > least leaves things visible enough to allow a user to change > the brightness to a better setting. > > What we don't want is brightness settings so low that the backlight is > essentially off (does not even show any light in a fully dark room). > > > so it can (will) happen that the minimum brightness values don't match, > > so it is theoretically possible that I cannot set both my laptop panel and external > > monitor to the same desired brightness level. Or am I missing something? > > This already is the case, some monitors may not go as low (or high) as you want, > some laptops also already don't go as low as you want. Fair point, but restricting the range decreases the chances even more. > > Expecting to be able to match monitor and laptop panel brightness at both > ends of the brightness range simply is not realistic. > [...] In conclusion, I appreciate your answer, there were some things I did not know. I suppose, after all, it might indeed not be a wise idea to shoehorn turning off backlight into brightness control. Regards, Barnabás Pőcze
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 62cee13f5576..967c92ceb041 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -25,6 +25,7 @@ #include <linux/input/sparse-keymap.h> #include <linux/kernel.h> #include <linux/leds.h> +#include <linux/minmax.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> @@ -212,6 +213,7 @@ struct asus_wmi { struct input_dev *inputdev; struct backlight_device *backlight_device; + struct backlight_device *screenpad_backlight_device; struct platform_device *platform_device; struct led_classdev wlan_led; @@ -3839,6 +3841,123 @@ static int is_display_toggle(int code) return 0; } +/* Screenpad backlight *******************************************************/ + +static int read_screenpad_backlight_power(struct asus_wmi *asus) +{ + int ret; + + ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_SCREENPAD_POWER); + if (ret < 0) + return ret; + /* 1 == powered */ + return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; +} + +static int read_screenpad_brightness(struct backlight_device *bd) +{ + struct asus_wmi *asus = bl_get_data(bd); + u32 retval; + int err; + + err = read_screenpad_backlight_power(asus); + if (err < 0) + return err; + /* The device brightness can only be read if powered, so return stored */ + if (err == FB_BLANK_POWERDOWN) + return asus->driver->screenpad_brightness; + + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); + if (err < 0) + return err; + + return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; +} + +static int update_screenpad_bl_status(struct backlight_device *bd) +{ + struct asus_wmi *asus = bl_get_data(bd); + int power, err = 0; + u32 ctrl_param; + + power = read_screenpad_backlight_power(asus); + if (power < 0) + return power; + + if (bd->props.power != power) { + if (power != FB_BLANK_UNBLANK) { + /* Only brightness > 0 can power it back on */ + ctrl_param = max(1, asus->driver->screenpad_brightness); + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, + ctrl_param, NULL); + } else { + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL); + } + } else if (power == FB_BLANK_UNBLANK) { + /* Only set brightness if powered on or we get invalid/unsync state */ + ctrl_param = bd->props.brightness; + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, NULL); + } + + /* Ensure brightness is stored to turn back on with */ + asus->driver->screenpad_brightness = bd->props.brightness; + + return err; +} + +static const struct backlight_ops asus_screenpad_bl_ops = { + .get_brightness = read_screenpad_brightness, + .update_status = update_screenpad_bl_status, + .options = BL_CORE_SUSPENDRESUME, +}; + +static int asus_screenpad_init(struct asus_wmi *asus) +{ + struct backlight_device *bd; + struct backlight_properties props; + int err, power; + int brightness = 0; + + power = read_screenpad_backlight_power(asus); + if (power < 0) + return power; + + if (power != FB_BLANK_POWERDOWN) { + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness); + if (err < 0) + return err; + } + /* default to an acceptable min brightness on boot if too low */ + if (brightness < 60) + brightness = 60; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; /* ensure this bd is last to be picked */ + props.max_brightness = 255; + bd = backlight_device_register("asus_screenpad", + &asus->platform_device->dev, asus, + &asus_screenpad_bl_ops, &props); + if (IS_ERR(bd)) { + pr_err("Could not register backlight device\n"); + return PTR_ERR(bd); + } + + asus->screenpad_backlight_device = bd; + asus->driver->screenpad_brightness = brightness; + bd->props.brightness = brightness; + bd->props.power = power; + backlight_update_status(bd); + + return 0; +} + +static void asus_screenpad_exit(struct asus_wmi *asus) +{ + backlight_device_unregister(asus->screenpad_backlight_device); + + asus->screenpad_backlight_device = NULL; +} + /* Fn-lock ********************************************************************/ static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus) @@ -4504,6 +4623,12 @@ static int asus_wmi_add(struct platform_device *pdev) } else if (asus->driver->quirks->wmi_backlight_set_devstate) err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL); + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT)) { + err = asus_screenpad_init(asus); + if (err && err != -ENODEV) + goto fail_screenpad; + } + if (asus_wmi_has_fnlock_key(asus)) { asus->fnlock_locked = fnlock_default; asus_wmi_fnlock_update(asus); @@ -4527,6 +4652,8 @@ static int asus_wmi_add(struct platform_device *pdev) asus_wmi_backlight_exit(asus); fail_backlight: asus_wmi_rfkill_exit(asus); +fail_screenpad: + asus_screenpad_exit(asus); fail_rfkill: asus_wmi_led_exit(asus); fail_leds: @@ -4553,6 +4680,7 @@ static int asus_wmi_remove(struct platform_device *device) asus = platform_get_drvdata(device); wmi_remove_notify_handler(asus->driver->event_guid); asus_wmi_backlight_exit(asus); + asus_screenpad_exit(asus); asus_wmi_input_exit(asus); asus_wmi_led_exit(asus); asus_wmi_rfkill_exit(asus); diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index a478ebfd34df..5fbdd0eafa02 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -57,6 +57,7 @@ struct quirk_entry { struct asus_wmi_driver { int brightness; int panel_power; + int screenpad_brightness; int wlan_ctrl_by_user; const char *name; diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index d17ae2eb0f8d..61ba70b32846 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -58,6 +58,10 @@ #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 #define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */ #define ASUS_WMI_DEVID_LIGHTBAR 0x00050025 +/* This can only be used to disable the screen, not re-enable */ +#define ASUS_WMI_DEVID_SCREENPAD_POWER 0x00050031 +/* Writing a brightness re-enables the screen if disabled */ +#define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032 #define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075