From patchwork Sun Jul 4 22:21:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 12357689 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A951DC07E95 for ; Sun, 4 Jul 2021 22:22:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7FA0661380 for ; Sun, 4 Jul 2021 22:22:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229733AbhGDWYz (ORCPT ); Sun, 4 Jul 2021 18:24:55 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]:49207 "EHLO wout3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229732AbhGDWYz (ORCPT ); Sun, 4 Jul 2021 18:24:55 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 293533200913; Sun, 4 Jul 2021 18:22:19 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Sun, 04 Jul 2021 18:22:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=ldb6qyK4IThrrQN5irTjCjWw8EaN4BN9P995P3a4Vko=; b=THJ4/X57 XAHVeqhwo9vFT8dOdBqV4JVyiPw+/tDtzIMmDou/fB8HUv08AfnrFxkxt+USMWZe DsfbTVd5cYiWASzcHNBNEWXX/41HL3Td7RFzhQkV4QWwKF8BhmSom1sM2OfUdHqu jbByQHDlUdCVQFjTaDeN99Fqgl+iI9yY2hknRV0mVghNQu3Bo/t24OrPA/s1dtrY w8F5ozLcV/NccN23f6S6oLHaShwYyqiAawf/13PCq/ufJc1vUVv3WuZhRPHArvO0 a+G8IO6+D2eh5JlZ9/R/xyJ2dD1kX4tPy0ot/z8AF6n452jWK3TaiHWde97zpUb4 sjWoJMVkt69iJA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrfeejfedgtdejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpedvteekvdeuhedthfeuudelheejie fhvddtteelleeghfekhfeugfehgeekffdtheenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghv X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 4 Jul 2021 18:22:15 -0400 (EDT) From: "Luke D. Jones" To: hdegoede@redhat.com Cc: corentin.chary@gmail.com, mgross@linux.intel.com, jdelvare@suse.com, linux@roeck-us.net, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, "Luke D. Jones" Subject: [PATCH 1/3] asus-wmi: Add panel overdrive functionality Date: Mon, 5 Jul 2021 10:21:46 +1200 Message-Id: <20210704222148.880848-2-luke@ljones.dev> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210704222148.880848-1-luke@ljones.dev> References: <20210704222148.880848-1-luke@ljones.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Some ASUS ROG laptops have the ability to drive the display panel a a higher rate to eliminate or reduce ghosting. Signed-off-by: Luke D. Jones Reported-by: kernel test robot --- drivers/platform/x86/asus-wmi.c | 92 ++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 93 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index ebaeb7bb80f5..2468076d6cd8 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -216,6 +216,9 @@ struct asus_wmi { // The RSOC controls the maximum charging percentage. bool battery_rsoc_available; + bool panel_overdrive_available; + u8 panel_overdrive; + struct hotplug_slot hotplug_slot; struct mutex hotplug_lock; struct mutex wmi_lock; @@ -1221,6 +1224,87 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus) return result; } +/* Panel Overdrive ************************************************************/ +static int panel_od_check_present(struct asus_wmi *asus) +{ + u32 result; + int err; + + asus->panel_overdrive_available = false; + + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_PANEL_OD, &result); + if (err) { + if (err == -ENODEV) + return 0; + return err; + } + + if (result & ASUS_WMI_DSTS_PRESENCE_BIT) + asus->panel_overdrive_available = true; + asus->panel_overdrive = result & ASUS_WMI_DSTS_STATUS_BIT; + + return 0; +} + +static int panel_od_write(struct asus_wmi *asus) +{ + int err; + u8 value; + u32 retval; + + value = asus->panel_overdrive; + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PANEL_OD, value, &retval); + + sysfs_notify(&asus->platform_device->dev.kobj, NULL, + "panel_od"); + + if (err) { + pr_warn("Failed to set panel overdrive: %d\n", err); + return err; + } + + if (retval > 1 || retval < 0) { + pr_warn("Failed to set panel overdrive (retval): 0x%x\n", + retval); + return -EIO; + } + + return 0; +} + +static ssize_t panel_od_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct asus_wmi *asus = dev_get_drvdata(dev); + u8 mode = asus->panel_overdrive; + + return scnprintf(buf, PAGE_SIZE, "%d\n", mode); +} + +static ssize_t panel_od_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int result; + u8 overdrive; + struct asus_wmi *asus = dev_get_drvdata(dev); + + result = kstrtou8(buf, 10, &overdrive); + if (result < 0) + return result; + + if (overdrive > 1 || overdrive < 0) + return -EINVAL; + + asus->panel_overdrive = overdrive; + panel_od_write(asus); + + return count; +} + +static DEVICE_ATTR_RW(panel_od); + /* Quirks *********************************************************************/ static void asus_wmi_set_xusb2pr(struct asus_wmi *asus) @@ -2332,6 +2416,7 @@ static struct attribute *platform_attributes[] = { &dev_attr_als_enable.attr, &dev_attr_fan_boost_mode.attr, &dev_attr_throttle_thermal_policy.attr, + &dev_attr_panel_od.attr, NULL }; @@ -2357,6 +2442,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, ok = asus->fan_boost_mode_available; else if (attr == &dev_attr_throttle_thermal_policy.attr) ok = asus->throttle_thermal_policy_available; + else if (attr == &dev_attr_panel_od.attr) + ok = asus->panel_overdrive_available; if (devid != -1) ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); @@ -2622,6 +2709,10 @@ static int asus_wmi_add(struct platform_device *pdev) else throttle_thermal_policy_set_default(asus); + err = panel_od_check_present(asus); + if (err) + goto fail_panel_od; + err = asus_wmi_sysfs_init(asus->platform_device); if (err) goto fail_sysfs; @@ -2709,6 +2800,7 @@ static int asus_wmi_add(struct platform_device *pdev) fail_throttle_thermal_policy: fail_fan_boost_mode: fail_platform: +fail_panel_od: kfree(asus); return err; } diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 2f274cf52805..428aea701c7b 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -61,6 +61,7 @@ #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 /* Misc */ +#define ASUS_WMI_DEVID_PANEL_OD 0x00050019 #define ASUS_WMI_DEVID_CAMERA 0x00060013 #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 From patchwork Sun Jul 4 22:21:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 12357691 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA663C07E95 for ; Sun, 4 Jul 2021 22:22:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 986FE613DD for ; Sun, 4 Jul 2021 22:22:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229743AbhGDWZC (ORCPT ); Sun, 4 Jul 2021 18:25:02 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]:60263 "EHLO wout3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229774AbhGDWZC (ORCPT ); Sun, 4 Jul 2021 18:25:02 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.west.internal (Postfix) with ESMTP id C471C3200916; Sun, 4 Jul 2021 18:22:25 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Sun, 04 Jul 2021 18:22:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=yopX1zJC3c35b0q5DtgYgCWOOW4d7xGsXAOBALaxekM=; b=W+stt/W3 1OskvE9gPOIRuf1jYxWDSHFQ0NUvA42z/J6wG6/Y0RdM1snFCf3/lwDFSLujtOeZ G8C4neeo6J1wC1QRw1G5/+h6Rig3E1Gbn1U7p6O6bDDazJ4tUszesHq3xdXf8eKv bUPqOp/XLEun+riyDm28q5B/bnM6YzYRoPfiQColoTU9X7zIvF6xHGYE5RWJ/OfU Qh2eiBazc28hkUMbcMkA1+CWhWkfbjpc4gVB8Rt7HR+a+6pMEsEI9KGaH+SuTckk dUBAtkCGg84XPzIXzKBOYIW420jm2mnMI6vJsRFFs5XHbmbO80+zA+i3MXRy38Hs Kbyt2rfDeT1iPw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrfeejfedgtdejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpedvteekvdeuhedthfeuudelheejie fhvddtteelleeghfekhfeugfehgeekffdtheenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghv X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 4 Jul 2021 18:22:21 -0400 (EDT) From: "Luke D. Jones" To: hdegoede@redhat.com Cc: corentin.chary@gmail.com, mgross@linux.intel.com, jdelvare@suse.com, linux@roeck-us.net, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, "Luke D. Jones" Subject: [PATCH 2/3] asus-wmi: Add dgpu disable method Date: Mon, 5 Jul 2021 10:21:47 +1200 Message-Id: <20210704222148.880848-3-luke@ljones.dev> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210704222148.880848-1-luke@ljones.dev> References: <20210704222148.880848-1-luke@ljones.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org In Windows the ASUS Armory Crate progrm can enable or disable the dGPU via a WMI call. This functions much the same as various Linux methods in software where the dGPU is removed from the device tree. However the WMI call saves the state of dGPU enabled or not and this then changes the dGPU visibility in Linux with no way for Linux users to re-enable it. We expose the WMI method so users can see and change the dGPU ACPI state. Signed-off-by: Luke D. Jones --- drivers/platform/x86/asus-wmi.c | 98 ++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 3 + 2 files changed, 101 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 2468076d6cd8..8dc3f7ed021f 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -210,6 +210,9 @@ struct asus_wmi { u8 fan_boost_mode_mask; u8 fan_boost_mode; + bool dgpu_disable_available; + u8 dgpu_disable_mode; + bool throttle_thermal_policy_available; u8 throttle_thermal_policy_mode; @@ -427,6 +430,93 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) } } +/* dGPU ********************************************************************/ +static int dgpu_disable_check_present(struct asus_wmi *asus) +{ + u32 result; + int err; + + asus->dgpu_disable_available = false; + + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_DGPU, &result); + if (err) { + if (err == -ENODEV) + return 0; + return err; + } + + if (result & ASUS_WMI_DSTS_PRESENCE_BIT) + asus->dgpu_disable_available = true; + asus->dgpu_disable_mode = result & ASUS_WMI_DSTS_STATUS_BIT; + + return 0; +} + +static int dgpu_disable_write(struct asus_wmi *asus) +{ + int err; + u8 value; + u32 retval; + + value = asus->dgpu_disable_mode; + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, value, &retval); + + sysfs_notify(&asus->platform_device->dev.kobj, NULL, + "dgpu_disable"); + + if (err) { + pr_warn("Failed to set dgpu disable: %d\n", err); + return err; + } + + if (retval > 1 || retval < 0) { + pr_warn("Failed to set dgpu disable (retval): 0x%x\n", + retval); + return -EIO; + } + + return 0; +} + +static ssize_t dgpu_disable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct asus_wmi *asus = dev_get_drvdata(dev); + u8 mode = asus->dgpu_disable_mode; + + return scnprintf(buf, PAGE_SIZE, "%d\n", mode); +} + +static ssize_t dgpu_disable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int result; + u8 disable; + struct asus_wmi *asus = dev_get_drvdata(dev); + + result = kstrtou8(buf, 10, &disable); + if (result < 0) + return result; + + if (disable > 1 || disable < 0) + return -EINVAL; + + asus->dgpu_disable_mode = disable; + /* + * The ACPI call used does not save the mode unless the call is run twice. + * Once to disable, then once to check status and save - this is two code + * paths in the method in the ACPI dumps. + */ + dgpu_disable_write(asus); + dgpu_disable_write(asus); + + return count; +} + +static DEVICE_ATTR_RW(dgpu_disable); + /* Battery ********************************************************************/ /* The battery maximum charging percentage */ @@ -2412,6 +2502,7 @@ static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_touchpad.attr, + &dev_attr_dgpu_disable.attr, &dev_attr_lid_resume.attr, &dev_attr_als_enable.attr, &dev_attr_fan_boost_mode.attr, @@ -2438,6 +2529,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, devid = ASUS_WMI_DEVID_LID_RESUME; else if (attr == &dev_attr_als_enable.attr) devid = ASUS_WMI_DEVID_ALS_ENABLE; + else if (attr == &dev_attr_dgpu_disable.attr) + ok = asus->dgpu_disable_available; else if (attr == &dev_attr_fan_boost_mode.attr) ok = asus->fan_boost_mode_available; else if (attr == &dev_attr_throttle_thermal_policy.attr) @@ -2699,6 +2792,10 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_platform; + err = dgpu_disable_check_present(asus); + if (err) + goto fail_dgpu_disable; + err = fan_boost_mode_check_present(asus); if (err) goto fail_fan_boost_mode; @@ -2799,6 +2896,7 @@ static int asus_wmi_add(struct platform_device *pdev) fail_sysfs: fail_throttle_thermal_policy: fail_fan_boost_mode: +fail_dgpu_disable: fail_platform: fail_panel_od: kfree(asus); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 428aea701c7b..a528f9d0e4b7 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -90,6 +90,9 @@ /* Keyboard dock */ #define ASUS_WMI_DEVID_KBD_DOCK 0x00120063 +/* dgpu on/off */ +#define ASUS_WMI_DEVID_DGPU 0x00090020 + /* DSTS masks */ #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 From patchwork Sun Jul 4 22:21:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luke Jones X-Patchwork-Id: 12357693 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6B60C07E95 for ; Sun, 4 Jul 2021 22:22:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AB1A8613DD for ; Sun, 4 Jul 2021 22:22:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229794AbhGDWZI (ORCPT ); Sun, 4 Jul 2021 18:25:08 -0400 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]:54093 "EHLO wout3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229649AbhGDWZH (ORCPT ); Sun, 4 Jul 2021 18:25:07 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.west.internal (Postfix) with ESMTP id 3D0803200925; Sun, 4 Jul 2021 18:22:31 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Sun, 04 Jul 2021 18:22:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=3CPDjxPiq6HlBKJX4u/v/vfPupRnUlydsIxOwue4RPs=; b=T1nUo8j4 Z5iTQO+yi8iaoXHdMWat1zgcEx+KbSrR7ztDM0ZNDm1kq7x4TDg2zE85YbGqDgGy nJCYOeW4qGyk0vPDBcz+DvK/48dGVyXHlujYfhrxfGmu4w6b4sDtjwbBmWsxr/qB o6zlInuskOF26BGNPw95m7XnS+XI6BdL13perxuncYwgJN7qUNifRl/zF1r+sOnu MchCkruQ3pntPEgdx9uYy7+x1uBQevC7M8Qlx+XEy4K8aDPbNLNLnuEuA2ve1GFb SmFLdmbDjTsl71ViwFWDblELRG4jVMC7ikhAvJgIC7owTBK9a1HjSRTYsqNdtqd5 bhyy9S1MI4R0Yg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrfeejfedgtdejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomhepfdfnuhhkvgcuffdrucflohhnvghsfdcuoehluhhkvgeslhhj ohhnvghsrdguvghvqeenucggtffrrghtthgvrhhnpedvteekvdeuhedthfeuudelheejie fhvddtteelleeghfekhfeugfehgeekffdtheenucevlhhushhtvghrufhiiigvpedtnecu rfgrrhgrmhepmhgrihhlfhhrohhmpehluhhkvgeslhhjohhnvghsrdguvghv X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 4 Jul 2021 18:22:27 -0400 (EDT) From: "Luke D. Jones" To: hdegoede@redhat.com Cc: corentin.chary@gmail.com, mgross@linux.intel.com, jdelvare@suse.com, linux@roeck-us.net, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, "Luke D. Jones" Subject: [PATCH 3/3] asus-wmi: Add egpu enable method Date: Mon, 5 Jul 2021 10:21:48 +1200 Message-Id: <20210704222148.880848-4-luke@ljones.dev> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210704222148.880848-1-luke@ljones.dev> References: <20210704222148.880848-1-luke@ljones.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org The X13 Flow laptops can utilise an external GPU. This requires toggling an ACPI method which will first disable the internal dGPU, and then enable the eGPU. Signed-off-by: Luke D. Jones --- drivers/platform/x86/asus-wmi.c | 92 ++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 3 + 2 files changed, 95 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 8dc3f7ed021f..c9fe77456b7b 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -210,6 +210,9 @@ struct asus_wmi { u8 fan_boost_mode_mask; u8 fan_boost_mode; + bool egpu_enable_available; // 0 = enable + u8 egpu_enable_mode; + bool dgpu_disable_available; u8 dgpu_disable_mode; @@ -430,6 +433,87 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) } } +/* eGPU ********************************************************************/ +static int egpu_enable_check_present(struct asus_wmi *asus) +{ + u32 result; + int err; + + asus->egpu_enable_available = false; + + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_EGPU, &result); + if (err) { + if (err == -ENODEV) + return 0; + return err; + } + + if (result & ASUS_WMI_DSTS_PRESENCE_BIT) { + asus->egpu_enable_available = true; + asus->egpu_enable_mode = result & ASUS_WMI_DSTS_STATUS_BIT; + } + + return 0; +} + +static int egpu_enable_write(struct asus_wmi *asus) +{ + int err; + u8 value; + u32 retval; + + value = asus->egpu_enable_mode; + + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, value, &retval); + + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable"); + + if (err) { + pr_warn("Failed to set egpu disable: %d\n", err); + return err; + } + + if (retval > 1 || retval < 0) { + pr_warn("Failed to set egpu disable (retval): 0x%x\n", retval); + return -EIO; + } + + return 0; +} + +static ssize_t egpu_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct asus_wmi *asus = dev_get_drvdata(dev); + u8 mode = asus->egpu_enable_mode; + + return scnprintf(buf, PAGE_SIZE, "%d\n", mode); +} + +static ssize_t egpu_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int result; + u8 disable; + struct asus_wmi *asus = dev_get_drvdata(dev); + + result = kstrtou8(buf, 10, &disable); + if (result < 0) + return result; + + if (disable > 1 || disable < 0) + return -EINVAL; + + asus->egpu_enable_mode = disable; + + egpu_enable_write(asus); + + return count; +} + +static DEVICE_ATTR_RW(egpu_enable); + /* dGPU ********************************************************************/ static int dgpu_disable_check_present(struct asus_wmi *asus) { @@ -2502,6 +2586,7 @@ static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_touchpad.attr, + &dev_attr_egpu_enable.attr, &dev_attr_dgpu_disable.attr, &dev_attr_lid_resume.attr, &dev_attr_als_enable.attr, @@ -2529,6 +2614,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, devid = ASUS_WMI_DEVID_LID_RESUME; else if (attr == &dev_attr_als_enable.attr) devid = ASUS_WMI_DEVID_ALS_ENABLE; + else if (attr == &dev_attr_egpu_enable.attr) + ok = asus->egpu_enable_available; else if (attr == &dev_attr_dgpu_disable.attr) ok = asus->dgpu_disable_available; else if (attr == &dev_attr_fan_boost_mode.attr) @@ -2792,6 +2879,10 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_platform; + err = egpu_enable_check_present(asus); + if (err) + goto fail_egpu_enable; + err = dgpu_disable_check_present(asus); if (err) goto fail_dgpu_disable; @@ -2896,6 +2987,7 @@ static int asus_wmi_add(struct platform_device *pdev) fail_sysfs: fail_throttle_thermal_policy: fail_fan_boost_mode: +fail_egpu_enable: fail_dgpu_disable: fail_platform: fail_panel_od: diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index a528f9d0e4b7..17dc5cb6f3f2 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -90,6 +90,9 @@ /* Keyboard dock */ #define ASUS_WMI_DEVID_KBD_DOCK 0x00120063 +/* dgpu on/off */ +#define ASUS_WMI_DEVID_EGPU 0x00090019 + /* dgpu on/off */ #define ASUS_WMI_DEVID_DGPU 0x00090020