diff options
Diffstat (limited to 'SOURCES/asus-linux.patch')
-rw-r--r-- | SOURCES/asus-linux.patch | 585 |
1 files changed, 352 insertions, 233 deletions
diff --git a/SOURCES/asus-linux.patch b/SOURCES/asus-linux.patch index 1580454..d1a1204 100644 --- a/SOURCES/asus-linux.patch +++ b/SOURCES/asus-linux.patch @@ -1,34 +1,53 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jan200101 <sentrycraft123@gmail.com> -Date: Wed, 8 Mar 2023 08:26:17 +0100 -Subject: [PATCH] asus-linux This patch adds support for the tablet mode switch - sensors on convertible devices where that sensor is managed by AMD SFH, like - the Asus Flow X13 and the Lenovo ThinkPad L13 Yoga Gen2 (AMD). +Date: Fri, 19 May 2023 17:45:47 +0200 +Subject: [PATCH] asus_linux -Co-developed-by: Ivan Dovgal <iv.dovg@gmail.com> -Signed-off-by: Ivan Dovgal <iv.dovg@gmail.com> -Co-developed-by: Luke D. Jones <luke@ljones.dev> -Signed-off-by: Luke D. Jones <luke@ljones.dev> -Signed-off-by: Adrian Freund <adrian@freund.io> ---- -v2: -* Fixed build warning reported by kernel test robot <lkp@intel.com> Signed-off-by: Jan200101 <sentrycraft123@gmail.com> --- - drivers/hid/amd-sfh-hid/amd_sfh_client.c | 2 + - drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2 +- - drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 4 + - drivers/hid/amd-sfh-hid/amd_sfh_pcie.h | 1 + - .../hid_descriptor/amd_sfh_hid_desc.c | 27 ++++++ - .../hid_descriptor/amd_sfh_hid_desc.h | 7 ++ - .../hid_descriptor/amd_sfh_hid_report_desc.h | 21 ++++ - drivers/pci/controller/vmd.c | 96 ++++++++++++++----- - drivers/pci/pcie/aspm.c | 54 +++++++++++ - include/linux/pci.h | 7 ++ - 10 files changed, 194 insertions(+), 27 deletions(-) + drivers/acpi/resource.c | 14 ++ + drivers/hid/amd-sfh-hid/amd_sfh_client.c | 2 + + drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2 +- + drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 4 + + drivers/hid/amd-sfh-hid/amd_sfh_pcie.h | 1 + + .../hid_descriptor/amd_sfh_hid_desc.c | 27 ++++ + .../hid_descriptor/amd_sfh_hid_desc.h | 7 + + .../hid_descriptor/amd_sfh_hid_report_desc.h | 21 +++ + drivers/hid/hid-asus.c | 42 +++--- + drivers/hid/hid-ids.h | 1 + + drivers/platform/x86/asus-wmi.c | 131 ++++++++++++++++++ + drivers/platform/x86/asus-wmi.h | 1 + + include/linux/platform_data/x86/asus-wmi.h | 4 + + sound/pci/hda/patch_realtek.c | 20 +++ + 14 files changed, 250 insertions(+), 27 deletions(-) +diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c +index e8492b3a393a..01a7befe9625 100644 +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -467,6 +467,20 @@ static const struct dmi_system_id asus_laptop[] = { + DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"), + }, + }, ++ { ++ .ident = "Asus TUF Gaming A15 FA507NV", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "FA507NV"), ++ }, ++ }, ++ { ++ .ident = "ASUS TUF Gaming A16 FA617NS", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "FA617NS"), ++ }, ++ }, + { } + }; + diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c -index c751d12f5..690be680e 100644 +index c751d12f5df8..690be680e392 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c @@ -146,6 +146,8 @@ static const char *get_sensor_name(int idx) @@ -41,7 +60,7 @@ index c751d12f5..690be680e 100644 return "ALS"; case HPD_IDX: diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h -index 528036892..97296f587 100644 +index 528036892c9d..97296f587bc7 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h +++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h @@ -11,7 +11,7 @@ @@ -54,7 +73,7 @@ index 528036892..97296f587 100644 #define AMD_SFH_HID_PRODUCT 0x0001 diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c -index 47774b9ab..cfda797f0 100644 +index c936d6a51c0c..c33f3f202ff7 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c @@ -27,6 +27,7 @@ @@ -76,7 +95,7 @@ index 47774b9ab..cfda797f0 100644 sensor_id[num_of_sensors++] = als_idx; diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h -index dfb7cabd8..e18ceee9e 100644 +index dfb7cabd82ef..e18ceee9e5db 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h @@ -78,6 +78,7 @@ enum sensor_idx { @@ -88,7 +107,7 @@ index dfb7cabd8..e18ceee9e 100644 }; diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c -index f9a8c02d5..181973f35 100644 +index f9a8c02d5a7b..181973f35f05 100644 --- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c +++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c @@ -47,6 +47,11 @@ static int get_report_descriptor(int sensor_idx, u8 *rep_desc) @@ -161,7 +180,7 @@ index f9a8c02d5..181973f35 100644 get_common_inputs(&als_input.common_property, report_id); /* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */ diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h -index ebd55675e..b22068a47 100644 +index ebd55675eb62..b22068a47429 100644 --- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h +++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h @@ -111,4 +111,11 @@ struct hpd_input_report { @@ -177,7 +196,7 @@ index ebd55675e..b22068a47 100644 +} __packed; #endif diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h -index 697f2791e..96cbc1e5b 100644 +index 697f2791ea9c..96cbc1e5b9a7 100644 --- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h +++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_report_desc.h @@ -644,6 +644,27 @@ static const u8 als_report_descriptor[] = { @@ -208,231 +227,331 @@ index 697f2791e..96cbc1e5b 100644 /* BIOMETRIC PRESENCE*/ static const u8 hpd_report_descriptor[] = { 0x05, 0x20, /* Usage page */ -diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c -index 769eedeb8..900bf82dc 100644 ---- a/drivers/pci/controller/vmd.c -+++ b/drivers/pci/controller/vmd.c -@@ -66,8 +66,22 @@ enum vmd_features { - * interrupt handling. - */ - VMD_FEAT_CAN_BYPASS_MSI_REMAP = (1 << 4), -+ -+ /* -+ * Enable ASPM on the PCIE root ports and set the default LTR of the -+ * storage devices on platforms where these values are not configured by -+ * BIOS. This is needed for laptops, which require these settings for -+ * proper power management of the SoC. -+ */ -+ VMD_FEAT_BIOS_PM_QUIRK = (1 << 5), +diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c +index d1094bb1aa42..2bc14e076739 100644 +--- a/drivers/hid/hid-asus.c ++++ b/drivers/hid/hid-asus.c +@@ -883,33 +883,20 @@ static int asus_input_mapping(struct hid_device *hdev, + case 0xb5: asus_map_key_clear(KEY_CALC); break; + case 0xc4: asus_map_key_clear(KEY_KBDILLUMUP); break; + case 0xc5: asus_map_key_clear(KEY_KBDILLUMDOWN); break; ++ case 0xc7: asus_map_key_clear(KEY_KBDILLUMTOGGLE); break; + +- /* ASUS touchpad toggle */ +- case 0x6b: asus_map_key_clear(KEY_F21); break; ++ case 0x6b: asus_map_key_clear(KEY_F21); break; /* ASUS touchpad toggle */ ++ case 0x38: asus_map_key_clear(KEY_PROG1); break; /* ROG key */ ++ case 0xba: asus_map_key_clear(KEY_PROG2); break; /* Fn+C ASUS Splendid */ ++ case 0x5c: asus_map_key_clear(KEY_PROG3); break; /* Fn+Space Power4Gear */ ++ case 0x99: asus_map_key_clear(KEY_PROG4); break; /* Fn+F5 "fan" symbol */ ++ case 0xae: asus_map_key_clear(KEY_PROG4); break; /* Fn+F5 "fan" symbol */ ++ case 0x92: asus_map_key_clear(KEY_CALC); break; /* Fn+Ret "Calc" symbol */ ++ case 0xb2: asus_map_key_clear(KEY_PROG2); break; /* Fn+Left previous aura */ ++ case 0xb3: asus_map_key_clear(KEY_PROG3); break; /* Fn+Left next aura */ ++ case 0x6a: asus_map_key_clear(KEY_F13); break; /* Screenpad toggle */ ++ case 0x4b: asus_map_key_clear(KEY_F14); break; /* Arrows/Pg-Up/Dn toggle */ + +- /* ROG key */ +- case 0x38: asus_map_key_clear(KEY_PROG1); break; +- +- /* Fn+C ASUS Splendid */ +- case 0xba: asus_map_key_clear(KEY_PROG2); break; +- +- /* Fn+Space Power4Gear Hybrid */ +- case 0x5c: asus_map_key_clear(KEY_PROG3); break; +- +- /* Fn+F5 "fan" symbol on FX503VD */ +- case 0x99: asus_map_key_clear(KEY_PROG4); break; +- +- /* Fn+F5 "fan" symbol on N-Key keyboard */ +- case 0xae: asus_map_key_clear(KEY_PROG4); break; +- +- /* Fn+Ret "Calc" symbol on N-Key keyboard */ +- case 0x92: asus_map_key_clear(KEY_CALC); break; +- +- /* Fn+Left Aura mode previous on N-Key keyboard */ +- case 0xb2: asus_map_key_clear(KEY_PROG2); break; +- +- /* Fn+Right Aura mode next on N-Key keyboard */ +- case 0xb3: asus_map_key_clear(KEY_PROG3); break; + + default: + /* ASUS lazily declares 256 usages, ignore the rest, +@@ -1267,6 +1254,9 @@ static const struct hid_device_id asus_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, + USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2), + QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, ++ USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3), ++ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, + USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD), + QUIRK_ROG_CLAYMORE_II_KEYBOARD }, +@@ -1309,4 +1299,4 @@ static struct hid_driver asus_driver = { }; + module_hid_driver(asus_driver); -+#define VMD_FEATS_CLIENT (VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | \ -+ VMD_FEAT_HAS_BUS_RESTRICTIONS | \ -+ VMD_FEAT_OFFSET_FIRST_VECTOR) -+ -+#define VMD_BIOS_PM_QUIRK_LTR 0x1003 /* 3145728 ns */ -+ - static DEFINE_IDA(vmd_instance_ida); +-MODULE_LICENSE("GPL"); ++MODULE_LICENSE("GPL"); +\ No newline at end of file +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index c2e9b6d1fd7d..513290a2e91c 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -207,6 +207,7 @@ + #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822 + #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866 + #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6 ++#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3 0x1a30 + #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b + #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 1038dfdcdd32..14a32e08f900 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> +@@ -200,6 +201,7 @@ struct asus_wmi { + + struct input_dev *inputdev; + struct backlight_device *backlight_device; ++ struct backlight_device *screenpad_backlight_device; + struct platform_device *platform_device; - /* -@@ -709,6 +723,46 @@ static void vmd_copy_host_bridge_flags(struct pci_host_bridge *root_bridge, - vmd_bridge->native_dpc = root_bridge->native_dpc; + struct led_classdev wlan_led; +@@ -3208,6 +3210,127 @@ static int is_display_toggle(int code) + return 0; } -+/* -+ * Enable ASPM and LTR settings on devices that aren't configured by BIOS. -+ */ -+static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) ++/* Screenpad backlight *******************************************************/ ++ ++static int read_screenpad_backlight_power(struct asus_wmi *asus) +{ -+ unsigned long features = *(unsigned long *)userdata; -+ u16 ltr = VMD_BIOS_PM_QUIRK_LTR; -+ u32 ltr_reg; -+ int pos; ++ int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_SCREENPAD_POWER); + -+ if (!(features & VMD_FEAT_BIOS_PM_QUIRK)) -+ return 0; ++ if (ret < 0) ++ return ret; ++ /* 1 == powered */ ++ return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; ++} + -+ pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL); ++static int read_screenpad_brightness(struct backlight_device *bd) ++{ ++ struct asus_wmi *asus = bl_get_data(bd); ++ u32 retval; ++ int err; + -+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR); -+ if (!pos) -+ return 0; ++ 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; + -+ /* -+ * Skip if the max snoop LTR is non-zero, indicating BIOS has set it -+ * so the LTR quirk is not needed. -+ */ -+ pci_read_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, <r_reg); -+ if (!!(ltr_reg & (PCI_LTR_VALUE_MASK | PCI_LTR_SCALE_MASK))) -+ return 0; ++ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); ++ if (err < 0) ++ return err; + -+ /* -+ * Set the default values to the maximum required by the platform to -+ * allow the deepest power management savings. Write as a DWORD where -+ * the lower word is the max snoop latency and the upper word is the -+ * max non-snoop latency. -+ */ -+ ltr_reg = (ltr << 16) | ltr; -+ pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, ltr_reg); -+ pci_info(pdev, "VMD: Default LTR value set by driver\n"); ++ return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; ++} + -+ return 0; ++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 == -ENODEV) ++ return err; ++ else 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 int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) - { - struct pci_sysdata *sd = &vmd->sysdata; -@@ -881,6 +935,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) - - pci_assign_unassigned_bus_resources(vmd->bus); - -+ pci_walk_bus(vmd->bus, vmd_pm_enable_quirk, &features); ++static const struct backlight_ops asus_screenpad_bl_ops = { ++ .get_brightness = read_screenpad_brightness, ++ .update_status = update_screenpad_bl_status, ++ .options = BL_CORE_SUSPENDRESUME, ++}; + - /* - * VMD root buses are virtual and don't return true on pci_is_pcie() - * and will fail pcie_bus_configure_settings() early. It can instead be -@@ -1017,36 +1073,24 @@ static int vmd_resume(struct device *dev) - static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume); - - static const struct pci_device_id vmd_ids[] = { -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D), -+ {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_VMD_201D), - .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP,}, -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0), -+ {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0), - .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW | - VMD_FEAT_HAS_BUS_RESTRICTIONS | - VMD_FEAT_CAN_BYPASS_MSI_REMAP,}, -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f), -- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | -- VMD_FEAT_HAS_BUS_RESTRICTIONS | -- VMD_FEAT_OFFSET_FIRST_VECTOR,}, -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c3d), -- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | -- VMD_FEAT_HAS_BUS_RESTRICTIONS | -- VMD_FEAT_OFFSET_FIRST_VECTOR,}, -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa77f), -- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | -- VMD_FEAT_HAS_BUS_RESTRICTIONS | -- VMD_FEAT_OFFSET_FIRST_VECTOR,}, -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7d0b), -- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | -- VMD_FEAT_HAS_BUS_RESTRICTIONS | -- VMD_FEAT_OFFSET_FIRST_VECTOR,}, -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xad0b), -- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | -- VMD_FEAT_HAS_BUS_RESTRICTIONS | -- VMD_FEAT_OFFSET_FIRST_VECTOR,}, -- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B), -- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | -- VMD_FEAT_HAS_BUS_RESTRICTIONS | -- VMD_FEAT_OFFSET_FIRST_VECTOR,}, -+ {PCI_VDEVICE(INTEL, 0x467f), -+ .driver_data = VMD_FEATS_CLIENT | VMD_FEAT_BIOS_PM_QUIRK,}, -+ {PCI_VDEVICE(INTEL, 0x4c3d), -+ .driver_data = VMD_FEATS_CLIENT | VMD_FEAT_BIOS_PM_QUIRK,}, -+ {PCI_VDEVICE(INTEL, 0xa77f), -+ .driver_data = VMD_FEATS_CLIENT | VMD_FEAT_BIOS_PM_QUIRK,}, -+ {PCI_VDEVICE(INTEL, 0x7d0b), -+ .driver_data = VMD_FEATS_CLIENT | VMD_FEAT_BIOS_PM_QUIRK,}, -+ {PCI_VDEVICE(INTEL, 0xad0b), -+ .driver_data = VMD_FEATS_CLIENT | VMD_FEAT_BIOS_PM_QUIRK,}, -+ {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B), -+ .driver_data = VMD_FEATS_CLIENT | VMD_FEAT_BIOS_PM_QUIRK,}, - {0,} - }; - MODULE_DEVICE_TABLE(pci, vmd_ids); -diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c -index 4b4184563..66d7514ca 100644 ---- a/drivers/pci/pcie/aspm.c -+++ b/drivers/pci/pcie/aspm.c -@@ -1138,6 +1138,60 @@ int pci_disable_link_state(struct pci_dev *pdev, int state) - } - EXPORT_SYMBOL(pci_disable_link_state); - -+/** -+ * pci_enable_link_state - Clear and set the default device link state so that -+ * the link may be allowed to enter the specified states. Note that if the -+ * BIOS didn't grant ASPM control to the OS, this does nothing because we can't -+ * touch the LNKCTL register. Also note that this does not enable states -+ * disabled by pci_disable_link_state(). Return 0 or a negative errno. -+ * -+ * @pdev: PCI device -+ * @state: Mask of ASPM link states to enable -+ */ -+int pci_enable_link_state(struct pci_dev *pdev, int state) ++static int asus_screenpad_init(struct asus_wmi *asus) +{ -+ struct pcie_link_state *link = pcie_aspm_get_link(pdev); ++ struct backlight_device *bd; ++ struct backlight_properties props; ++ int power, brightness; + -+ if (!link) -+ return -EINVAL; -+ /* -+ * A driver requested that ASPM be enabled on this device, but -+ * if we don't have permission to manage ASPM (e.g., on ACPI -+ * systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and -+ * the _OSC method), we can't honor that request. -+ */ -+ if (aspm_disabled) { -+ pci_warn(pdev, "can't override BIOS ASPM; OS doesn't have ASPM control\n"); -+ return -EPERM; ++ power = read_screenpad_backlight_power(asus); ++ if (power == -ENODEV) ++ power = FB_BLANK_UNBLANK; ++ else if (power < 0) ++ return power; ++ ++ 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); + } + -+ down_read(&pci_bus_sem); -+ mutex_lock(&aspm_lock); -+ link->aspm_default = 0; -+ if (state & PCIE_LINK_STATE_L0S) -+ link->aspm_default |= ASPM_STATE_L0S; -+ if (state & PCIE_LINK_STATE_L1) -+ /* L1 PM substates require L1 */ -+ link->aspm_default |= ASPM_STATE_L1 | ASPM_STATE_L1SS; -+ if (state & PCIE_LINK_STATE_L1_1) -+ link->aspm_default |= ASPM_STATE_L1_1; -+ if (state & PCIE_LINK_STATE_L1_2) -+ link->aspm_default |= ASPM_STATE_L1_2; -+ if (state & PCIE_LINK_STATE_L1_1_PCIPM) -+ link->aspm_default |= ASPM_STATE_L1_1_PCIPM; -+ if (state & PCIE_LINK_STATE_L1_2_PCIPM) -+ link->aspm_default |= ASPM_STATE_L1_2_PCIPM; -+ pcie_config_aspm_link(link, policy_to_aspm_state(link)); ++ asus->screenpad_backlight_device = bd; + -+ link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0; -+ pcie_set_clkpm(link, policy_to_clkpm_state(link)); -+ mutex_unlock(&aspm_lock); -+ up_read(&pci_bus_sem); ++ brightness = read_screenpad_brightness(bd); ++ if (brightness < 0) ++ return brightness; ++ /* ++ * Counter an odd behaviour where default is set to < 13 if it was 0 on boot. ++ * 60 is subjective, but accepted as a good compromise to retain visibility. ++ */ ++ if (brightness < 60) ++ brightness = 60; ++ ++ asus->driver->screenpad_brightness = brightness; ++ bd->props.brightness = brightness; ++ bd->props.power = power; ++ backlight_update_status(bd); + + return 0; +} -+EXPORT_SYMBOL(pci_enable_link_state); + - static int pcie_aspm_set_policy(const char *val, - const struct kernel_param *kp) - { -diff --git a/include/linux/pci.h b/include/linux/pci.h -index 2bda4a4e4..8c35f15e6 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -1651,10 +1651,15 @@ extern bool pcie_ports_native; - #define PCIE_LINK_STATE_L1_2 BIT(4) - #define PCIE_LINK_STATE_L1_1_PCIPM BIT(5) - #define PCIE_LINK_STATE_L1_2_PCIPM BIT(6) -+#define PCIE_LINK_STATE_ALL (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |\ -+ PCIE_LINK_STATE_CLKPM | PCIE_LINK_STATE_L1_1 |\ -+ PCIE_LINK_STATE_L1_2 | PCIE_LINK_STATE_L1_1_PCIPM |\ -+ PCIE_LINK_STATE_L1_2_PCIPM) ++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) +@@ -3823,6 +3946,13 @@ 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)) { ++ pr_warn("Begin asus_screenpad_init"); ++ err = asus_screenpad_init(asus); ++ if (err && err != -ENODEV) ++ goto fail_backlight; ++ } ++ + if (asus_wmi_has_fnlock_key(asus)) { + asus->fnlock_locked = fnlock_default; + asus_wmi_fnlock_update(asus); +@@ -3844,6 +3974,7 @@ static int asus_wmi_add(struct platform_device *pdev) + + fail_wmi_handler: + asus_wmi_backlight_exit(asus); ++ asus_screenpad_exit(asus); + fail_backlight: + asus_wmi_rfkill_exit(asus); + fail_rfkill: +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 28234dc9fa6a..a2d94adb5c80 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 - #ifdef CONFIG_PCIEASPM - int pci_disable_link_state(struct pci_dev *pdev, int state); - int pci_disable_link_state_locked(struct pci_dev *pdev, int state); -+int pci_enable_link_state(struct pci_dev *pdev, int state); - void pcie_no_aspm(void); - bool pcie_aspm_support_enabled(void); - bool pcie_aspm_enabled(struct pci_dev *pdev); -@@ -1663,6 +1668,8 @@ static inline int pci_disable_link_state(struct pci_dev *pdev, int state) - { return 0; } - static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state) - { return 0; } -+static inline int pci_enable_link_state(struct pci_dev *pdev, int state) -+{ return 0; } - static inline void pcie_no_aspm(void) { } - static inline bool pcie_aspm_support_enabled(void) { return false; } - static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; } +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 172ffc2c332b..ad7fdb5a4ed0 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -7063,6 +7063,8 @@ enum { + ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC295_FIXUP_DISABLE_DAC3, + ALC285_FIXUP_SPEAKER2_TO_DAC1, ++ ALC285_FIXUP_ASUS_HEADSET_MIC, ++ ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1, + ALC280_FIXUP_HP_HEADSET_MIC, + ALC221_FIXUP_HP_FRONT_MIC, + ALC292_FIXUP_TPT460, +@@ -8033,6 +8035,22 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC269_FIXUP_THINKPAD_ACPI + }, ++ [ALC285_FIXUP_ASUS_HEADSET_MIC] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x19, 0x03a11050 }, ++ { 0x1b, 0x03a11c30 }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC245_FIXUP_CS35L41_SPI_2 ++ }, ++ [ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_speaker2_to_dac1, ++ .chained = true, ++ .chain_id = ALC285_FIXUP_ASUS_HEADSET_MIC ++ }, + [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -9504,6 +9522,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), + SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), ++ SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS), + SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), +@@ -9542,6 +9561,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101), ++ SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604", ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1), + SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), + SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), + SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |