diff options
Diffstat (limited to 'SOURCES/asus-linux.patch')
-rw-r--r-- | SOURCES/asus-linux.patch | 2010 |
1 files changed, 112 insertions, 1898 deletions
diff --git a/SOURCES/asus-linux.patch b/SOURCES/asus-linux.patch index 491e5be..5e084db 100644 --- a/SOURCES/asus-linux.patch +++ b/SOURCES/asus-linux.patch @@ -1,1790 +1,8 @@ -From 5a57dbe832b2dc8cc79516977f4fbbfed64c4743 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 4 Jun 2023 18:48:11 +1200 -Subject: [PATCH 01/13] platform/x86: asus-wmi: add support for showing charger - mode - -Expose a WMI method in sysfs platform for showing which connected -charger the laptop is currently using. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - .../ABI/testing/sysfs-platform-asus-wmi | 10 +++++++++ - drivers/platform/x86/asus-wmi.c | 21 +++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 3 +++ - 3 files changed, 34 insertions(+) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index a77a004a1baa..eb29e3023c7b 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -98,3 +98,13 @@ Description: - Enable an LCD response-time boost to reduce or remove ghosting: - * 0 - Disable, - * 1 - Enable -+ -+What: /sys/devices/platform/<platform>/charge_mode -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Get the current charging mode being used: -+ * 1 - Barrel connected charger, -+ * 2 - USB-C charging -+ * 3 - Both connected, barrel used for charging -\ No newline at end of file -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 8bef66a2f0ce..cf82ae6323f8 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -237,6 +237,7 @@ struct asus_wmi { - u8 fan_boost_mode_mask; - u8 fan_boost_mode; - -+ bool charge_mode_available; - bool egpu_enable_available; - bool dgpu_disable_available; - bool gpu_mux_mode_available; -@@ -586,6 +587,22 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) - asus_wmi_tablet_sw_report(asus, result); - } - -+/* Charging mode, 1=Barrel, 2=USB ******************************************/ -+static ssize_t charge_mode_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ int result, value; -+ -+ result = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CHARGE_MODE, &value); -+ if (result < 0) -+ return result; -+ -+ return sysfs_emit(buf, "%d\n", value & 0xff); -+} -+ -+static DEVICE_ATTR_RO(charge_mode); -+ - /* dGPU ********************************************************************/ - static ssize_t dgpu_disable_show(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -3472,6 +3489,7 @@ static struct attribute *platform_attributes[] = { - &dev_attr_camera.attr, - &dev_attr_cardr.attr, - &dev_attr_touchpad.attr, -+ &dev_attr_charge_mode.attr, - &dev_attr_egpu_enable.attr, - &dev_attr_dgpu_disable.attr, - &dev_attr_gpu_mux_mode.attr, -@@ -3501,6 +3519,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_charge_mode.attr) -+ ok = asus->charge_mode_available; - else if (attr == &dev_attr_egpu_enable.attr) - ok = asus->egpu_enable_available; - else if (attr == &dev_attr_dgpu_disable.attr) -@@ -3767,6 +3787,7 @@ static int asus_wmi_add(struct platform_device *pdev) - if (err) - goto fail_platform; - -+ asus->charge_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CHARGE_MODE); - asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); - asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); - asus->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX); -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 28234dc9fa6a..f90cafe26af1 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -95,6 +95,9 @@ - /* Keyboard dock */ - #define ASUS_WMI_DEVID_KBD_DOCK 0x00120063 - -+/* Charging mode - 1=Barrel, 2=USB */ -+#define ASUS_WMI_DEVID_CHARGE_MODE 0x0012006C -+ - /* dgpu on/off */ - #define ASUS_WMI_DEVID_EGPU 0x00090019 - --- -2.41.0 - -From 6c0e89067d0608fedd3b75844bdea5566a0c249f Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 4 Jun 2023 19:07:31 +1200 -Subject: [PATCH 02/13] platform/x86: asus-wmi: add support for showing middle - fan RPM - -Some newer ASUS ROG laptops now have a middle/center fan in addition -to the CPU and GPU fans. This new fan typically blows across the -heatpipes and VRMs betweent eh CPU and GPU. - -This commit exposes that fan to PWM control plus showing RPM. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 91 ++++++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 1 + - 2 files changed, 92 insertions(+) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index cf82ae6323f8..069251d8040f 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -72,6 +72,7 @@ module_param(fnlock_default, bool, 0444); - - #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0) - -+#define ASUS_MID_FAN_DESC "mid_fan" - #define ASUS_GPU_FAN_DESC "gpu_fan" - #define ASUS_FAN_DESC "cpu_fan" - #define ASUS_FAN_MFUN 0x13 -@@ -229,8 +230,10 @@ struct asus_wmi { - - enum fan_type fan_type; - enum fan_type gpu_fan_type; -+ enum fan_type mid_fan_type; - int fan_pwm_mode; - int gpu_fan_pwm_mode; -+ int mid_fan_pwm_mode; - int agfn_pwm; - - bool fan_boost_mode_available; -@@ -2139,6 +2142,31 @@ static ssize_t fan2_label_show(struct device *dev, - return sysfs_emit(buf, "%s\n", ASUS_GPU_FAN_DESC); - } - -+/* Middle/Center fan on modern ROG laptops */ -+static ssize_t fan3_input_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ int value; -+ int ret; -+ -+ ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_MID_FAN_CTRL, &value); -+ if (ret < 0) -+ return ret; -+ -+ value &= 0xffff; -+ -+ return sysfs_emit(buf, "%d\n", value * 100); -+} -+ -+static ssize_t fan3_label_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ return sysfs_emit(buf, "%s\n", ASUS_MID_FAN_DESC); -+} -+ - static ssize_t pwm2_enable_show(struct device *dev, - struct device_attribute *attr, - char *buf) -@@ -2185,6 +2213,52 @@ static ssize_t pwm2_enable_store(struct device *dev, - return count; - } - -+static ssize_t pwm3_enable_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ return sysfs_emit(buf, "%d\n", asus->mid_fan_pwm_mode); -+} -+ -+static ssize_t pwm3_enable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ int state; -+ int value; -+ int ret; -+ u32 retval; -+ -+ ret = kstrtouint(buf, 10, &state); -+ if (ret) -+ return ret; -+ -+ switch (state) { /* standard documented hwmon values */ -+ case ASUS_FAN_CTRL_FULLSPEED: -+ value = 1; -+ break; -+ case ASUS_FAN_CTRL_AUTO: -+ value = 0; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_MID_FAN_CTRL, -+ value, &retval); -+ if (ret) -+ return ret; -+ -+ if (retval != 1) -+ return -EIO; -+ -+ asus->mid_fan_pwm_mode = state; -+ return count; -+} -+ - /* Fan1 */ - static DEVICE_ATTR_RW(pwm1); - static DEVICE_ATTR_RW(pwm1_enable); -@@ -2194,6 +2268,10 @@ static DEVICE_ATTR_RO(fan1_label); - static DEVICE_ATTR_RW(pwm2_enable); - static DEVICE_ATTR_RO(fan2_input); - static DEVICE_ATTR_RO(fan2_label); -+/* Fan3 - Middle/center fan */ -+static DEVICE_ATTR_RW(pwm3_enable); -+static DEVICE_ATTR_RO(fan3_input); -+static DEVICE_ATTR_RO(fan3_label); - - /* Temperature */ - static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL); -@@ -2202,10 +2280,13 @@ static struct attribute *hwmon_attributes[] = { - &dev_attr_pwm1.attr, - &dev_attr_pwm1_enable.attr, - &dev_attr_pwm2_enable.attr, -+ &dev_attr_pwm3_enable.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan1_label.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan2_label.attr, -+ &dev_attr_fan3_input.attr, -+ &dev_attr_fan3_label.attr, - - &dev_attr_temp1_input.attr, - NULL -@@ -2231,6 +2312,11 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, - || attr == &dev_attr_pwm2_enable.attr) { - if (asus->gpu_fan_type == FAN_TYPE_NONE) - return 0; -+ } else if (attr == &dev_attr_fan3_input.attr -+ || attr == &dev_attr_fan3_label.attr -+ || attr == &dev_attr_pwm3_enable.attr) { -+ if (asus->mid_fan_type == FAN_TYPE_NONE) -+ return 0; - } else if (attr == &dev_attr_temp1_input.attr) { - int err = asus_wmi_get_devstate(asus, - ASUS_WMI_DEVID_THERMAL_CTRL, -@@ -2274,6 +2360,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus) - static int asus_wmi_fan_init(struct asus_wmi *asus) - { - asus->gpu_fan_type = FAN_TYPE_NONE; -+ asus->mid_fan_type = FAN_TYPE_NONE; - asus->fan_type = FAN_TYPE_NONE; - asus->agfn_pwm = -1; - -@@ -2288,6 +2375,10 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) - if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL)) - asus->gpu_fan_type = FAN_TYPE_SPEC83; - -+ /* Some models also have a center/middle fan */ -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MID_FAN_CTRL)) -+ asus->mid_fan_type = FAN_TYPE_SPEC83; -+ - if (asus->fan_type == FAN_TYPE_NONE) - return -ENODEV; - -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index f90cafe26af1..2c03bda7703f 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -80,6 +80,7 @@ - #define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */ - #define ASUS_WMI_DEVID_CPU_FAN_CTRL 0x00110013 - #define ASUS_WMI_DEVID_GPU_FAN_CTRL 0x00110014 -+#define ASUS_WMI_DEVID_MID_FAN_CTRL 0x00110031 - #define ASUS_WMI_DEVID_CPU_FAN_CURVE 0x00110024 - #define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025 - --- -2.41.0 - -From 60f66172c03e8cf8417818173c253824527a6d69 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 4 Jun 2023 19:37:34 +1200 -Subject: [PATCH 03/13] platform/x86: asus-wmi: support middle fan custom - curves - -Adds support for fan curves defined for the middle fan which -is available on some ASUS ROG laptops. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 77 +++++++++++++++++++++- - include/linux/platform_data/x86/asus-wmi.h | 1 + - 2 files changed, 76 insertions(+), 2 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 069251d8040f..89867b18e8f7 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -113,6 +113,7 @@ module_param(fnlock_default, bool, 0444); - #define FAN_CURVE_BUF_LEN 32 - #define FAN_CURVE_DEV_CPU 0x00 - #define FAN_CURVE_DEV_GPU 0x01 -+#define FAN_CURVE_DEV_MID 0x02 - /* Mask to determine if setting temperature or percentage */ - #define FAN_CURVE_PWM_MASK 0x04 - -@@ -253,7 +254,8 @@ struct asus_wmi { - - bool cpu_fan_curve_available; - bool gpu_fan_curve_available; -- struct fan_curve_data custom_fan_curves[2]; -+ bool mid_fan_curve_available; -+ struct fan_curve_data custom_fan_curves[3]; - - struct platform_profile_handler platform_profile_handler; - bool platform_profile_support; -@@ -2090,6 +2092,8 @@ static ssize_t pwm1_enable_store(struct device *dev, - asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false; - if (asus->gpu_fan_curve_available) - asus->custom_fan_curves[FAN_CURVE_DEV_GPU].enabled = false; -+ if (asus->mid_fan_curve_available) -+ asus->custom_fan_curves[FAN_CURVE_DEV_MID].enabled = false; - - return count; - } -@@ -2541,6 +2545,9 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) - if (fan_dev == ASUS_WMI_DEVID_GPU_FAN_CURVE) - fan_idx = FAN_CURVE_DEV_GPU; - -+ if (fan_dev == ASUS_WMI_DEVID_MID_FAN_CURVE) -+ fan_idx = FAN_CURVE_DEV_MID; -+ - curves = &asus->custom_fan_curves[fan_idx]; - err = asus_wmi_evaluate_method_buf(asus->dsts_id, fan_dev, mode, buf, - FAN_CURVE_BUF_LEN); -@@ -2829,6 +2836,42 @@ static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point7_pwm, fan_curve, - static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point8_pwm, fan_curve, - FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 7); - -+/* MID */ -+static SENSOR_DEVICE_ATTR_RW(pwm3_enable, fan_curve_enable, FAN_CURVE_DEV_GPU); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 0); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 1); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point3_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 2); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point4_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 3); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point5_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 4); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point6_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 5); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point7_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 6); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point8_temp, fan_curve, -+ FAN_CURVE_DEV_GPU, 7); -+ -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 0); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 1); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point3_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 2); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point4_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 3); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point5_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 4); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point6_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 5); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point7_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 6); -+static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point8_pwm, fan_curve, -+ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 7); -+ - static struct attribute *asus_fan_curve_attr[] = { - /* CPU */ - &sensor_dev_attr_pwm1_enable.dev_attr.attr, -@@ -2866,6 +2909,24 @@ static struct attribute *asus_fan_curve_attr[] = { - &sensor_dev_attr_pwm2_auto_point6_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point7_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point8_pwm.dev_attr.attr, -+ /* MID */ -+ &sensor_dev_attr_pwm3_enable.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point5_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point6_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point7_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point8_temp.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point5_pwm.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point6_pwm.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point7_pwm.dev_attr.attr, -+ &sensor_dev_attr_pwm3_auto_point8_pwm.dev_attr.attr, - NULL - }; - -@@ -2885,6 +2946,9 @@ static umode_t asus_fan_curve_is_visible(struct kobject *kobj, - if (asus->gpu_fan_curve_available && attr->name[3] == '2') - return 0644; - -+ if (asus->mid_fan_curve_available && attr->name[3] == '3') -+ return 0644; -+ - return 0; - } - -@@ -2914,7 +2978,14 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) - if (err) - return err; - -- if (!asus->cpu_fan_curve_available && !asus->gpu_fan_curve_available) -+ err = fan_curve_check_present(asus, &asus->mid_fan_curve_available, -+ ASUS_WMI_DEVID_MID_FAN_CURVE); -+ if (err) -+ return err; -+ -+ if (!asus->cpu_fan_curve_available -+ && !asus->gpu_fan_curve_available -+ && !asus->mid_fan_curve_available) - return 0; - - hwmon = devm_hwmon_device_register_with_groups( -@@ -2983,6 +3054,8 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus) - asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false; - if (asus->gpu_fan_curve_available) - asus->custom_fan_curves[FAN_CURVE_DEV_GPU].enabled = false; -+ if (asus->mid_fan_curve_available) -+ asus->custom_fan_curves[FAN_CURVE_DEV_MID].enabled = false; - - return 0; - } -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 2c03bda7703f..329efc086993 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -83,6 +83,7 @@ - #define ASUS_WMI_DEVID_MID_FAN_CTRL 0x00110031 - #define ASUS_WMI_DEVID_CPU_FAN_CURVE 0x00110024 - #define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025 -+#define ASUS_WMI_DEVID_MID_FAN_CURVE 0x00110032 - - /* Power */ - #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 --- -2.41.0 - -From 0b90e1673515c0cf89f43c9a7f5cd06db9c7b3f2 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 4 Jun 2023 20:01:57 +1200 -Subject: [PATCH 04/13] platform/x86: asus-wmi: add WMI method to show if egpu - connected - -Exposes the WMI method which tells if the eGPU is properly connected -on the devices that support it. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - .../ABI/testing/sysfs-platform-asus-wmi | 11 +++++++++- - drivers/platform/x86/asus-wmi.c | 21 +++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 4 +++- - 3 files changed, 34 insertions(+), 2 deletions(-) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index eb29e3023c7b..878daf7c2036 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -107,4 +107,13 @@ Description: - Get the current charging mode being used: - * 1 - Barrel connected charger, - * 2 - USB-C charging -- * 3 - Both connected, barrel used for charging -\ No newline at end of file -+ * 3 - Both connected, barrel used for charging -+ -+What: /sys/devices/platform/<platform>/egpu_connected -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Show if the egpu (XG Mobile) is correctly connected: -+ * 0 - False, -+ * 1 - True -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 89867b18e8f7..a65cf8599124 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -243,6 +243,7 @@ struct asus_wmi { - - bool charge_mode_available; - bool egpu_enable_available; -+ bool egpu_connect_available; - bool dgpu_disable_available; - bool gpu_mux_mode_available; - -@@ -709,6 +710,22 @@ static ssize_t egpu_enable_store(struct device *dev, - } - static DEVICE_ATTR_RW(egpu_enable); - -+/* Is eGPU connected? *********************************************************/ -+static ssize_t egpu_connected_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ int result; -+ -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); -+ if (result < 0) -+ return result; -+ -+ return sysfs_emit(buf, "%d\n", result); -+} -+ -+static DEVICE_ATTR_RO(egpu_connected); -+ - /* gpu mux switch *************************************************************/ - static ssize_t gpu_mux_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -3655,6 +3672,7 @@ static struct attribute *platform_attributes[] = { - &dev_attr_touchpad.attr, - &dev_attr_charge_mode.attr, - &dev_attr_egpu_enable.attr, -+ &dev_attr_egpu_connected.attr, - &dev_attr_dgpu_disable.attr, - &dev_attr_gpu_mux_mode.attr, - &dev_attr_lid_resume.attr, -@@ -3687,6 +3705,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - ok = asus->charge_mode_available; - else if (attr == &dev_attr_egpu_enable.attr) - ok = asus->egpu_enable_available; -+ else if (attr == &dev_attr_egpu_connected.attr) -+ ok = asus->egpu_connect_available; - else if (attr == &dev_attr_dgpu_disable.attr) - ok = asus->dgpu_disable_available; - else if (attr == &dev_attr_gpu_mux_mode.attr) -@@ -3953,6 +3973,7 @@ static int asus_wmi_add(struct platform_device *pdev) - - asus->charge_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CHARGE_MODE); - asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); -+ asus->egpu_connect_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); - asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); - asus->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX); - asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 329efc086993..2034648f8cdf 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -100,7 +100,9 @@ - /* Charging mode - 1=Barrel, 2=USB */ - #define ASUS_WMI_DEVID_CHARGE_MODE 0x0012006C - --/* dgpu on/off */ -+/* epu is connected? 1 == true */ -+#define ASUS_WMI_DEVID_EGPU_CONNECTED 0x00090018 -+/* egpu on/off */ - #define ASUS_WMI_DEVID_EGPU 0x00090019 - - /* dgpu on/off */ --- -2.41.0 - -From 1bddf53ccac067e043857d28c1598401cd9db7f4 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Tue, 20 Jun 2023 12:26:51 +1200 -Subject: [PATCH 05/13] platform/x86: asus-wmi: don't allow eGPU switching if - eGPU not connected - -Check the ASUS_WMI_DEVID_EGPU_CONNECTED method for eGPU connection -before allowing the ASUS_WMI_DEVID_EGPU method to run. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index a65cf8599124..3cb7cee110e2 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -693,6 +693,15 @@ static ssize_t egpu_enable_store(struct device *dev, - if (enable > 1) - return -EINVAL; - -+ err = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); -+ if (err < 0) -+ return err; -+ if (err < 1) { -+ err = -ENODEV; -+ pr_warn("Failed to set egpu disable: %d\n", err); -+ return err; -+ } -+ - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, enable, &result); - if (err) { - pr_warn("Failed to set egpu disable: %d\n", err); --- -2.41.0 - -From 64b96869a3ed4b7c9e41c1a3e8410c3ec2582ca9 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Tue, 20 Jun 2023 12:48:31 +1200 -Subject: [PATCH 06/13] platform/x86: asus-wmi: add safety checks to gpu - switching - -Add safety checking to dgpu_disable, egpu_enable, gpu_mux_mode. - -These checks prevent users from doing such things as: -- disabling the dGPU while is muxed to drive the internal screen -- enabling the eGPU which also disables the dGPU, while muxed to - the internal screen -- switching the MUX to dGPU while the dGPU is disabled - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 50 ++++++++++++++++++++++++++++++++- - 1 file changed, 49 insertions(+), 1 deletion(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 3cb7cee110e2..7e80ea2a802a 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -645,6 +645,18 @@ static ssize_t dgpu_disable_store(struct device *dev, - if (disable > 1) - return -EINVAL; - -+ if (asus->gpu_mux_mode_available) { -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); -+ if (result < 0) -+ /* An error here may signal greater failure of GPU handling */ -+ return result; -+ if (!result && disable) { -+ err = -ENODEV; -+ pr_warn("Can not disable dGPU when the MUX is in dGPU mode: %d\n", err); -+ return err; -+ } -+ } -+ - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, disable, &result); - if (err) { - pr_warn("Failed to set dgpu disable: %d\n", err); -@@ -693,7 +705,7 @@ static ssize_t egpu_enable_store(struct device *dev, - if (enable > 1) - return -EINVAL; - -- err = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); - if (err < 0) - return err; - if (err < 1) { -@@ -702,6 +714,18 @@ static ssize_t egpu_enable_store(struct device *dev, - return err; - } - -+ if (asus->gpu_mux_mode_available) { -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); -+ if (result < 0) -+ /* An error here may signal greater failure of GPU handling */ -+ return result; -+ if (!result && enable) { -+ err = -ENODEV; -+ pr_warn("Can not enable eGPU when the MUX is in dGPU mode: %d\n", err); -+ return err; -+ } -+ } -+ - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, enable, &result); - if (err) { - pr_warn("Failed to set egpu disable: %d\n", err); -@@ -764,6 +788,30 @@ static ssize_t gpu_mux_mode_store(struct device *dev, - if (optimus > 1) - return -EINVAL; - -+ if (asus->dgpu_disable_available) { -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_DGPU); -+ if (result < 0) -+ /* An error here may signal greater failure of GPU handling */ -+ return result; -+ if (result && !optimus) { -+ err = -ENODEV; -+ pr_warn("Can not switch MUX to dGPU mode when dGPU is disabled: %d\n", err); -+ return err; -+ } -+ } -+ -+ if (asus->egpu_enable_available) { -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU); -+ if (result < 0) -+ /* An error here may signal greater failure of GPU handling */ -+ return result; -+ if (result && !optimus) { -+ err = -ENODEV; -+ pr_warn("Can not switch MUX to dGPU mode when eGPU is enabled: %d\n", err); -+ return err; -+ } -+ } -+ - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_MUX, optimus, &result); - if (err) { - dev_err(dev, "Failed to set GPU MUX mode: %d\n", err); --- -2.41.0 - -From 76d73c965c18d6b5e1d8d9ab6ae446e2f1913b6b Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 4 Jun 2023 20:21:10 +1200 -Subject: [PATCH 07/13] platform/x86: asus-wmi: support setting mini-LED mode - -Support changing the mini-LED mode on some of the newer ASUS laptops. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - .../ABI/testing/sysfs-platform-asus-wmi | 9 ++++ - drivers/platform/x86/asus-wmi.c | 53 +++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 1 + - 3 files changed, 63 insertions(+) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index 878daf7c2036..5624bdef49cb 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -117,3 +117,12 @@ Description: - Show if the egpu (XG Mobile) is correctly connected: - * 0 - False, - * 1 - True -+ -+What: /sys/devices/platform/<platform>/mini_led_mode -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Change the mini-LED mode: -+ * 0 - Single-zone, -+ * 1 - Multi-zone -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 7e80ea2a802a..9b3dd262f6e4 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -265,6 +265,7 @@ struct asus_wmi { - bool battery_rsoc_available; - - bool panel_overdrive_available; -+ bool mini_led_mode_available; - - struct hotplug_slot hotplug_slot; - struct mutex hotplug_lock; -@@ -1830,6 +1831,54 @@ static ssize_t panel_od_store(struct device *dev, - } - static DEVICE_ATTR_RW(panel_od); - -+/* Mini-LED mode **************************************************************/ -+static ssize_t mini_led_mode_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ int result; -+ -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MINI_LED_MODE); -+ if (result < 0) -+ return result; -+ -+ return sysfs_emit(buf, "%d\n", result); -+} -+ -+static ssize_t mini_led_mode_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 mode; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &mode); -+ if (result) -+ return result; -+ -+ if (mode > 1) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MINI_LED_MODE, mode, &result); -+ -+ if (err) { -+ pr_warn("Failed to set mini-LED: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set mini-LED mode (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "mini_led_mode"); -+ -+ return count; -+} -+static DEVICE_ATTR_RW(mini_led_mode); -+ - /* Quirks *********************************************************************/ - - static void asus_wmi_set_xusb2pr(struct asus_wmi *asus) -@@ -3737,6 +3786,7 @@ static struct attribute *platform_attributes[] = { - &dev_attr_fan_boost_mode.attr, - &dev_attr_throttle_thermal_policy.attr, - &dev_attr_panel_od.attr, -+ &dev_attr_mini_led_mode.attr, - NULL - }; - -@@ -3774,6 +3824,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - ok = asus->throttle_thermal_policy_available; - else if (attr == &dev_attr_panel_od.attr) - ok = asus->panel_overdrive_available; -+ else if (attr == &dev_attr_mini_led_mode.attr) -+ ok = asus->mini_led_mode_available; - - if (devid != -1) - ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); -@@ -4036,6 +4088,7 @@ static int asus_wmi_add(struct platform_device *pdev) - asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); - asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); - asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); -+ asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE); - - err = fan_boost_mode_check_present(asus); - if (err) -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 2034648f8cdf..ea80361ac6c7 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -66,6 +66,7 @@ - #define ASUS_WMI_DEVID_CAMERA 0x00060013 - #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 - #define ASUS_WMI_DEVID_LID_FLIP_ROG 0x00060077 -+#define ASUS_WMI_DEVID_MINI_LED_MODE 0x0005001E - - /* Storage */ - #define ASUS_WMI_DEVID_CARDREADER 0x00080013 --- -2.41.0 - -From 3172f65f82ae6b36ab30a91ff73ba703a902da0a Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Tue, 6 Jun 2023 15:05:01 +1200 -Subject: [PATCH 08/13] platform/x86: asus-wmi: expose dGPU and CPU tunables - for ROG - -Expose various CPU and dGPU tunables that are available on many ASUS -ROG laptops. The tunables shown in sysfs will vary depending on the CPU -and dGPU vendor. - -All of these variables are write only and there is no easy way to find -what the defaults are. In general they seem to default to the max value -the vendor sets for the CPU and dGPU package - this is not the same as -the min/max writable value. Values written to these variables that are -beyond the capabilities of the CPU are ignored by the laptop. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - .../ABI/testing/sysfs-platform-asus-wmi | 58 ++++ - drivers/platform/x86/asus-wmi.c | 285 ++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 9 + - 3 files changed, 352 insertions(+) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index 5624bdef49cb..caaccd28fabf 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -126,3 +126,61 @@ Description: - Change the mini-LED mode: - * 0 - Single-zone, - * 1 - Multi-zone -+ -+What: /sys/devices/platform/<platform>/ppt_pl1_spl -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set the Package Power Target total of CPU: PL1 on Intel, SPL on AMD. -+ Shown on Intel+Nvidia or AMD+Nvidia based systems. -+ * min=5, max=250 -+ -+What: /sys/devices/platform/<platform>/ppt_pl2_sppt -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set the Slow Package Power Tracking Limit of CPU: PL2 on Intel, SPPT, -+ on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems. -+ * min=5, max=250 -+ -+What: /sys/devices/platform/<platform>/ppt_fppt -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set the Fast Package Power Tracking Limit of CPU. AMD+Nvidia only. -+ * min=5, max=250 -+ -+What: /sys/devices/platform/<platform>/ppt_apu_sppt -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set the APU SPPT limit. Shown on full AMD systems only. -+ * min=5, max=130 -+ -+What: /sys/devices/platform/<platform>/ppt_platform_sppt -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set the platform SPPT limit. Shown on full AMD systems only. -+ * min=5, max=130 -+ -+What: /sys/devices/platform/<platform>/nv_dynamic_boost -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set the dynamic boost limit of the Nvidia dGPU: -+ * min=5, max=25 -+ -+What: /sys/devices/platform/<platform>/nv_temp_target -+Date: Jun 2023 -+KernelVersion: 6.5 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set the target temperature limit of the Nvidia dGPU: -+ * min=75, max=87 -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 9b3dd262f6e4..c732610b3fef 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -117,6 +117,16 @@ module_param(fnlock_default, bool, 0444); - /* Mask to determine if setting temperature or percentage */ - #define FAN_CURVE_PWM_MASK 0x04 - -+/* Limits for tunables available on ASUS ROG laptops */ -+#define PPT_TOTAL_MIN 5 -+#define PPT_TOTAL_MAX 250 -+#define PPT_CPU_MIN 5 -+#define PPT_CPU_MAX 130 -+#define NVIDIA_BOOST_MIN 5 -+#define NVIDIA_BOOST_MAX 25 -+#define NVIDIA_TEMP_MIN 75 -+#define NVIDIA_TEMP_MAX 87 -+ - static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL }; - - static int throttle_thermal_policy_write(struct asus_wmi *); -@@ -247,6 +257,15 @@ struct asus_wmi { - bool dgpu_disable_available; - bool gpu_mux_mode_available; - -+ /* Tunables provided by ASUS for gaming laptops */ -+ bool ppt_pl2_sppt_available; -+ bool ppt_pl1_spl_available; -+ bool ppt_apu_sppt_available; -+ bool ppt_plat_sppt_available; -+ bool ppt_fppt_available; -+ bool nv_dyn_boost_available; -+ bool nv_temp_tgt_available; -+ - bool kbd_rgb_mode_available; - bool kbd_rgb_state_available; - -@@ -956,6 +975,244 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = { - NULL, - }; - -+/* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/ -+static ssize_t ppt_pl2_sppt_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 value; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &value); -+ if (result) -+ return result; -+ -+ if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL2_SPPT, value, &result); -+ if (err) { -+ pr_warn("Failed to set ppt_pl2_sppt: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set ppt_pl2_sppt (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl2_sppt"); -+ -+ return count; -+} -+static DEVICE_ATTR_WO(ppt_pl2_sppt); -+ -+/* Tunable: PPT, Intel=PL1, AMD=SPL ******************************************/ -+static ssize_t ppt_pl1_spl_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 value; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &value); -+ if (result) -+ return result; -+ -+ if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL1_SPL, value, &result); -+ if (err) { -+ pr_warn("Failed to set ppt_pl1_spl: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set ppt_pl1_spl (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl1_spl"); -+ -+ return count; -+} -+static DEVICE_ATTR_WO(ppt_pl1_spl); -+ -+/* Tunable: PPT APU FPPT ******************************************************/ -+static ssize_t ppt_fppt_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 value; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &value); -+ if (result) -+ return result; -+ -+ if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_FPPT, value, &result); -+ if (err) { -+ pr_warn("Failed to set ppt_fppt: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set ppt_fppt (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_fpu_sppt"); -+ -+ return count; -+} -+static DEVICE_ATTR_WO(ppt_fppt); -+ -+/* Tunable: PPT APU SPPT *****************************************************/ -+static ssize_t ppt_apu_sppt_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 value; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &value); -+ if (result) -+ return result; -+ -+ if (value < PPT_CPU_MIN || value > PPT_CPU_MAX) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_APU_SPPT, value, &result); -+ if (err) { -+ pr_warn("Failed to set ppt_apu_sppt: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set ppt_apu_sppt (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_apu_sppt"); -+ -+ return count; -+} -+static DEVICE_ATTR_WO(ppt_apu_sppt); -+ -+/* Tunable: PPT platform SPPT ************************************************/ -+static ssize_t ppt_platform_sppt_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 value; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &value); -+ if (result) -+ return result; -+ -+ if (value < PPT_CPU_MIN || value > PPT_CPU_MAX) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PLAT_SPPT, value, &result); -+ if (err) { -+ pr_warn("Failed to set ppt_platform_sppt: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set ppt_platform_sppt (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_platform_sppt"); -+ -+ return count; -+} -+static DEVICE_ATTR_WO(ppt_platform_sppt); -+ -+/* Tunable: NVIDIA dynamic boost *********************************************/ -+static ssize_t nv_dynamic_boost_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 value; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &value); -+ if (result) -+ return result; -+ -+ if (value < NVIDIA_BOOST_MIN || value > NVIDIA_BOOST_MAX) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_DYN_BOOST, value, &result); -+ if (err) { -+ pr_warn("Failed to set nv_dynamic_boost: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set nv_dynamic_boost (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_dynamic_boost"); -+ -+ return count; -+} -+static DEVICE_ATTR_WO(nv_dynamic_boost); -+ -+/* Tunable: NVIDIA temperature target ****************************************/ -+static ssize_t nv_temp_target_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 value; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &value); -+ if (result) -+ return result; -+ -+ if (value < NVIDIA_TEMP_MIN || value > NVIDIA_TEMP_MAX) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_THERM_TARGET, value, &result); -+ if (err) { -+ pr_warn("Failed to set nv_temp_target: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set nv_temp_target (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_temp_target"); -+ -+ return count; -+} -+static DEVICE_ATTR_WO(nv_temp_target); -+ - /* Battery ********************************************************************/ - - /* The battery maximum charging percentage */ -@@ -3785,6 +4042,13 @@ static struct attribute *platform_attributes[] = { - &dev_attr_als_enable.attr, - &dev_attr_fan_boost_mode.attr, - &dev_attr_throttle_thermal_policy.attr, -+ &dev_attr_ppt_pl2_sppt.attr, -+ &dev_attr_ppt_pl1_spl.attr, -+ &dev_attr_ppt_fppt.attr, -+ &dev_attr_ppt_apu_sppt.attr, -+ &dev_attr_ppt_platform_sppt.attr, -+ &dev_attr_nv_dynamic_boost.attr, -+ &dev_attr_nv_temp_target.attr, - &dev_attr_panel_od.attr, - &dev_attr_mini_led_mode.attr, - NULL -@@ -3822,6 +4086,20 @@ 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_ppt_pl2_sppt.attr) -+ ok = asus->ppt_pl2_sppt_available; -+ else if (attr == &dev_attr_ppt_pl1_spl.attr) -+ ok = asus->ppt_pl1_spl_available; -+ else if (attr == &dev_attr_ppt_fppt.attr) -+ ok = asus->ppt_fppt_available; -+ else if (attr == &dev_attr_ppt_apu_sppt.attr) -+ ok = asus->ppt_apu_sppt_available; -+ else if (attr == &dev_attr_ppt_platform_sppt.attr) -+ ok = asus->ppt_plat_sppt_available; -+ else if (attr == &dev_attr_nv_dynamic_boost.attr) -+ ok = asus->nv_dyn_boost_available; -+ else if (attr == &dev_attr_nv_temp_target.attr) -+ ok = asus->nv_temp_tgt_available; - else if (attr == &dev_attr_panel_od.attr) - ok = asus->panel_overdrive_available; - else if (attr == &dev_attr_mini_led_mode.attr) -@@ -4087,6 +4365,13 @@ static int asus_wmi_add(struct platform_device *pdev) - asus->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX); - asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); - asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); -+ asus->ppt_pl2_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL2_SPPT); -+ asus->ppt_pl1_spl_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL1_SPL); -+ asus->ppt_fppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_FPPT); -+ asus->ppt_apu_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_APU_SPPT); -+ asus->ppt_plat_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PLAT_SPPT); -+ asus->nv_dyn_boost_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_DYN_BOOST); -+ asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET); - asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); - asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE); - -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index ea80361ac6c7..16e99a1c37fc 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -86,6 +86,15 @@ - #define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025 - #define ASUS_WMI_DEVID_MID_FAN_CURVE 0x00110032 - -+/* Tunables for AUS ROG laptops */ -+#define ASUS_WMI_DEVID_PPT_PL2_SPPT 0x001200A0 -+#define ASUS_WMI_DEVID_PPT_PL1_SPL 0x001200A3 -+#define ASUS_WMI_DEVID_PPT_APU_SPPT 0x001200B0 -+#define ASUS_WMI_DEVID_PPT_PLAT_SPPT 0x001200B1 -+#define ASUS_WMI_DEVID_PPT_FPPT 0x001200C1 -+#define ASUS_WMI_DEVID_NV_DYN_BOOST 0x001200C0 -+#define ASUS_WMI_DEVID_NV_THERM_TARGET 0x001200C2 -+ - /* Power */ - #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 - --- -2.41.0 - -From 73622204c837e2ab4729bc2af2c8bb6d58f4b3b0 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 23 Jul 2023 21:29:11 +1200 -Subject: [PATCH 09/13] Fixes: a23870110a38 ("asus-wmi: add support for showing - middle fan RPM") - -After the addition of the mid fan custom curve functionality various -incorrect behaviour was uncovered. This commit fixes these areas. - -- Ensure mid fan attributes actually use the correct fan ID -- Correction to a bit mask for selecting the correct fan data -- Refactor the curve show/store functions to be cleaner and and - match each others layout - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 78 ++++++++++++++++----------------- - 1 file changed, 38 insertions(+), 40 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index c732610b3fef..496d03e88595 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -2910,9 +2910,8 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) - { - struct fan_curve_data *curves; - u8 buf[FAN_CURVE_BUF_LEN]; -- int fan_idx = 0; -+ int err, fan_idx; - u8 mode = 0; -- int err; - - if (asus->throttle_thermal_policy_available) - mode = asus->throttle_thermal_policy_mode; -@@ -2922,13 +2921,6 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) - else if (mode == 1) - mode = 2; - -- if (fan_dev == ASUS_WMI_DEVID_GPU_FAN_CURVE) -- fan_idx = FAN_CURVE_DEV_GPU; -- -- if (fan_dev == ASUS_WMI_DEVID_MID_FAN_CURVE) -- fan_idx = FAN_CURVE_DEV_MID; -- -- curves = &asus->custom_fan_curves[fan_idx]; - err = asus_wmi_evaluate_method_buf(asus->dsts_id, fan_dev, mode, buf, - FAN_CURVE_BUF_LEN); - if (err) { -@@ -2936,9 +2928,17 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) - return err; - } - -- fan_curve_copy_from_buf(curves, buf); -+ fan_idx = FAN_CURVE_DEV_CPU; -+ if (fan_dev == ASUS_WMI_DEVID_GPU_FAN_CURVE) -+ fan_idx = FAN_CURVE_DEV_GPU; -+ -+ if (fan_dev == ASUS_WMI_DEVID_MID_FAN_CURVE) -+ fan_idx = FAN_CURVE_DEV_MID; -+ -+ curves = &asus->custom_fan_curves[fan_idx]; - curves->device_id = fan_dev; - -+ fan_curve_copy_from_buf(curves, buf); - return 0; - } - -@@ -2968,7 +2968,7 @@ static struct fan_curve_data *fan_curve_attr_select(struct asus_wmi *asus, - { - int index = to_sensor_dev_attr(attr)->index; - -- return &asus->custom_fan_curves[index & FAN_CURVE_DEV_GPU]; -+ return &asus->custom_fan_curves[index]; - } - - /* Determine which fan the attribute is for if SENSOR_ATTR_2 */ -@@ -2977,7 +2977,7 @@ static struct fan_curve_data *fan_curve_attr_2_select(struct asus_wmi *asus, - { - int nr = to_sensor_dev_attr_2(attr)->nr; - -- return &asus->custom_fan_curves[nr & FAN_CURVE_DEV_GPU]; -+ return &asus->custom_fan_curves[nr & ~FAN_CURVE_PWM_MASK]; - } - - static ssize_t fan_curve_show(struct device *dev, -@@ -2986,13 +2986,13 @@ static ssize_t fan_curve_show(struct device *dev, - struct sensor_device_attribute_2 *dev_attr = to_sensor_dev_attr_2(attr); - struct asus_wmi *asus = dev_get_drvdata(dev); - struct fan_curve_data *data; -- int value, index, nr; -+ int value, pwm, index; - - data = fan_curve_attr_2_select(asus, attr); -+ pwm = dev_attr->nr & FAN_CURVE_PWM_MASK; - index = dev_attr->index; -- nr = dev_attr->nr; - -- if (nr & FAN_CURVE_PWM_MASK) -+ if (pwm) - value = data->percents[index]; - else - value = data->temps[index]; -@@ -3035,23 +3035,21 @@ static ssize_t fan_curve_store(struct device *dev, - struct sensor_device_attribute_2 *dev_attr = to_sensor_dev_attr_2(attr); - struct asus_wmi *asus = dev_get_drvdata(dev); - struct fan_curve_data *data; -+ int err, pwm, index; - u8 value; -- int err; -- -- int pwm = dev_attr->nr & FAN_CURVE_PWM_MASK; -- int index = dev_attr->index; - - data = fan_curve_attr_2_select(asus, attr); -+ pwm = dev_attr->nr & FAN_CURVE_PWM_MASK; -+ index = dev_attr->index; - - err = kstrtou8(buf, 10, &value); - if (err < 0) - return err; - -- if (pwm) { -+ if (pwm) - data->percents[index] = value; -- } else { -+ else - data->temps[index] = value; -- } - - /* - * Mark as disabled so the user has to explicitly enable to apply a -@@ -3164,7 +3162,7 @@ static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point8_temp, fan_curve, - FAN_CURVE_DEV_CPU, 7); - - static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_pwm, fan_curve, -- FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 0); -+ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 0); - static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_pwm, fan_curve, - FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 1); - static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point3_pwm, fan_curve, -@@ -3217,40 +3215,40 @@ static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point8_pwm, fan_curve, - FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 7); - - /* MID */ --static SENSOR_DEVICE_ATTR_RW(pwm3_enable, fan_curve_enable, FAN_CURVE_DEV_GPU); -+static SENSOR_DEVICE_ATTR_RW(pwm3_enable, fan_curve_enable, FAN_CURVE_DEV_MID); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 0); -+ FAN_CURVE_DEV_MID, 0); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 1); -+ FAN_CURVE_DEV_MID, 1); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point3_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 2); -+ FAN_CURVE_DEV_MID, 2); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point4_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 3); -+ FAN_CURVE_DEV_MID, 3); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point5_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 4); -+ FAN_CURVE_DEV_MID, 4); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point6_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 5); -+ FAN_CURVE_DEV_MID, 5); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point7_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 6); -+ FAN_CURVE_DEV_MID, 6); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point8_temp, fan_curve, -- FAN_CURVE_DEV_GPU, 7); -+ FAN_CURVE_DEV_MID, 7); - - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 0); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 0); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 1); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 1); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point3_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 2); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 2); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point4_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 3); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 3); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point5_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 4); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 4); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point6_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 5); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 5); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point7_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 6); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 6); - static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point8_pwm, fan_curve, -- FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 7); -+ FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 7); - - static struct attribute *asus_fan_curve_attr[] = { - /* CPU */ --- -2.41.0 - -From ebd35946f15047d89fd1bb68b0f75dc5c367af6e Mon Sep 17 00:00:00 2001 -From: Stefan Binding <sbinding@opensource.cirrus.com> -Date: Tue, 15 Aug 2023 17:10:33 +0100 -Subject: [PATCH 10/13] ALSA: hda: cs35l41: Support systems with missing _DSD - properties - -Some systems using CS35L41 with HDA were released without some -required _DSD properties in ACPI. To support these special cases, -add an api to configure the correct properties for systems with -this issue. - -This initial commit moves the no _DSD support for Lenovo -Legion Laptops (CLSA0100, CLSA0101) into a new framework which -can be extended to support additional laptops in the future. - -Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> ---- - sound/pci/hda/Makefile | 2 +- - sound/pci/hda/cs35l41_hda.c | 65 ++++++------------------- - sound/pci/hda/cs35l41_hda.h | 1 + - sound/pci/hda/cs35l41_hda_property.c | 73 ++++++++++++++++++++++++++++ - sound/pci/hda/cs35l41_hda_property.h | 18 +++++++ - 5 files changed, 108 insertions(+), 51 deletions(-) - create mode 100644 sound/pci/hda/cs35l41_hda_property.c - create mode 100644 sound/pci/hda/cs35l41_hda_property.h - -diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile -index 00d306104484..3b259239c48a 100644 ---- a/sound/pci/hda/Makefile -+++ b/sound/pci/hda/Makefile -@@ -28,7 +28,7 @@ snd-hda-codec-via-objs := patch_via.o - snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o - - # side codecs --snd-hda-scodec-cs35l41-objs := cs35l41_hda.o -+snd-hda-scodec-cs35l41-objs := cs35l41_hda.o cs35l41_hda_property.o - snd-hda-scodec-cs35l41-i2c-objs := cs35l41_hda_i2c.o - snd-hda-scodec-cs35l41-spi-objs := cs35l41_hda_spi.o - snd-hda-cs-dsp-ctls-objs := hda_cs_dsp_ctl.o -diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c -index ce5faa620517..692b69f24138 100644 ---- a/sound/pci/hda/cs35l41_hda.c -+++ b/sound/pci/hda/cs35l41_hda.c -@@ -19,6 +19,7 @@ - #include "hda_component.h" - #include "cs35l41_hda.h" - #include "hda_cs_dsp_ctl.h" -+#include "cs35l41_hda_property.h" - - #define CS35L41_FIRMWARE_ROOT "cirrus/" - #define CS35L41_PART "cs35l41" -@@ -1156,8 +1157,7 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41) - return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos); - } - --static int cs35l41_get_speaker_id(struct device *dev, int amp_index, -- int num_amps, int fixed_gpio_id) -+int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id) - { - struct gpio_desc *speaker_id_desc; - int speaker_id = -ENODEV; -@@ -1211,49 +1211,6 @@ static int cs35l41_get_speaker_id(struct device *dev, int amp_index, - return speaker_id; - } - --/* -- * Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work. -- * And devices created by serial-multi-instantiate don't have their device struct -- * pointing to the correct fwnode, so acpi_dev must be used here. -- * And devm functions expect that the device requesting the resource has the correct -- * fwnode. -- */ --static int cs35l41_no_acpi_dsd(struct cs35l41_hda *cs35l41, struct device *physdev, int id, -- const char *hid) --{ -- struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; -- -- /* check I2C address to assign the index */ -- cs35l41->index = id == 0x40 ? 0 : 1; -- cs35l41->channel_index = 0; -- cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); -- cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); -- hw_cfg->spk_pos = cs35l41->index; -- hw_cfg->gpio2.func = CS35L41_INTERRUPT; -- hw_cfg->gpio2.valid = true; -- hw_cfg->valid = true; -- -- if (strncmp(hid, "CLSA0100", 8) == 0) { -- hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; -- } else if (strncmp(hid, "CLSA0101", 8) == 0) { -- hw_cfg->bst_type = CS35L41_EXT_BOOST; -- hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH; -- hw_cfg->gpio1.valid = true; -- } else { -- /* -- * Note: CLSA010(0/1) are special cases which use a slightly different design. -- * All other HIDs e.g. CSC3551 require valid ACPI _DSD properties to be supported. -- */ -- dev_err(cs35l41->dev, "Error: ACPI _DSD Properties are missing for HID %s.\n", hid); -- hw_cfg->valid = false; -- hw_cfg->gpio1.valid = false; -- hw_cfg->gpio2.valid = false; -- return -EINVAL; -- } -- -- return 0; --} -- - static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id) - { - struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; -@@ -1279,12 +1236,17 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i - sub = NULL; - cs35l41->acpi_subsystem_id = sub; - -+ ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid); -+ if (!ret) { -+ dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n"); -+ goto put_physdev; -+ } -+ - property = "cirrus,dev-index"; - ret = device_property_count_u32(physdev, property); -- if (ret <= 0) { -- ret = cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid); -- goto err_put_physdev; -- } -+ if (ret <= 0) -+ goto err; -+ - if (ret > ARRAY_SIZE(values)) { - ret = -EINVAL; - goto err; -@@ -1374,7 +1336,10 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i - - err: - dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); --err_put_physdev: -+ hw_cfg->valid = false; -+ hw_cfg->gpio1.valid = false; -+ hw_cfg->gpio2.valid = false; -+put_physdev: - put_device(physdev); - - return ret; -diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h -index bdb35f3be68a..b93bf762976e 100644 ---- a/sound/pci/hda/cs35l41_hda.h -+++ b/sound/pci/hda/cs35l41_hda.h -@@ -83,5 +83,6 @@ extern const struct dev_pm_ops cs35l41_hda_pm_ops; - int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq, - struct regmap *regmap); - void cs35l41_hda_remove(struct device *dev); -+int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id); - - #endif /*__CS35L41_HDA_H__*/ -diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c -new file mode 100644 -index 000000000000..673f23257a09 ---- /dev/null -+++ b/sound/pci/hda/cs35l41_hda_property.c -@@ -0,0 +1,73 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// -+// CS35L41 ALSA HDA Property driver -+// -+// Copyright 2023 Cirrus Logic, Inc. -+// -+// Author: Stefan Binding <sbinding@opensource.cirrus.com> -+ -+#include <linux/gpio/consumer.h> -+#include <linux/string.h> -+#include "cs35l41_hda_property.h" -+ -+/* -+ * Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work. -+ * And devices created by serial-multi-instantiate don't have their device struct -+ * pointing to the correct fwnode, so acpi_dev must be used here. -+ * And devm functions expect that the device requesting the resource has the correct -+ * fwnode. -+ */ -+static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id, -+ const char *hid) -+{ -+ struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; -+ -+ /* check I2C address to assign the index */ -+ cs35l41->index = id == 0x40 ? 0 : 1; -+ cs35l41->channel_index = 0; -+ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); -+ cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); -+ hw_cfg->spk_pos = cs35l41->index; -+ hw_cfg->gpio2.func = CS35L41_INTERRUPT; -+ hw_cfg->gpio2.valid = true; -+ hw_cfg->valid = true; -+ -+ if (strcmp(hid, "CLSA0100") == 0) { -+ hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; -+ } else if (strcmp(hid, "CLSA0101") == 0) { -+ hw_cfg->bst_type = CS35L41_EXT_BOOST; -+ hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH; -+ hw_cfg->gpio1.valid = true; -+ } -+ -+ return 0; -+} -+ -+struct cs35l41_prop_model { -+ const char *hid; -+ const char *ssid; -+ int (*add_prop)(struct cs35l41_hda *cs35l41, struct device *physdev, int id, -+ const char *hid); -+}; -+ -+const struct cs35l41_prop_model cs35l41_prop_model_table[] = { -+ { "CLSA0100", NULL, lenovo_legion_no_acpi }, -+ { "CLSA0101", NULL, lenovo_legion_no_acpi }, -+ {} -+}; -+ -+int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physdev, int id, -+ const char *hid) -+{ -+ const struct cs35l41_prop_model *model; -+ -+ for (model = cs35l41_prop_model_table; model->hid > 0; model++) { -+ if (!strcmp(model->hid, hid) && -+ (!model->ssid || -+ (cs35l41->acpi_subsystem_id && -+ !strcmp(model->ssid, cs35l41->acpi_subsystem_id)))) -+ return model->add_prop(cs35l41, physdev, id, hid); -+ } -+ -+ return -ENOENT; -+} -diff --git a/sound/pci/hda/cs35l41_hda_property.h b/sound/pci/hda/cs35l41_hda_property.h -new file mode 100644 -index 000000000000..fd834042e2fd ---- /dev/null -+++ b/sound/pci/hda/cs35l41_hda_property.h -@@ -0,0 +1,18 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * CS35L41 ALSA HDA Property driver -+ * -+ * Copyright 2023 Cirrus Logic, Inc. -+ * -+ * Author: Stefan Binding <sbinding@opensource.cirrus.com> -+ */ -+ -+#ifndef CS35L41_HDA_PROP_H -+#define CS35L41_HDA_PROP_H -+ -+#include <linux/device.h> -+#include "cs35l41_hda.h" -+ -+int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physdev, int id, -+ const char *hid); -+#endif /* CS35L41_HDA_PROP_H */ --- -2.41.0 - -From d6f191b6827fae534a0635afb8d4380b59cb409c Mon Sep 17 00:00:00 2001 +From 76556b655f7b50afe5c58006f44221900e5711a9 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" <luke@ljones.dev> Date: Wed, 23 Aug 2023 11:05:59 +1200 -Subject: [PATCH 11/13] ALSA: hda: cs35l41: Support ASUS 2023 laptops with - missing DSD +Subject: [PATCH v2] ALSA: hda: cs35l41: Support ASUS 2023 laptops with missing + DSD Support adding the missing DSD properties required for ASUS ROG 2023 laptops and other ASUS laptops to properly utilise the cs35l41. @@ -1811,32 +29,39 @@ Signed-off-by: Jonathan LoBue <jlobue10@gmail.com> Co-developed-by: Luke D. Jones <luke@ljones.dev> Signed-off-by: Luke D. Jones <luke@ljones.dev> --- - sound/pci/hda/cs35l41_hda_property.c | 47 ++++++++++++++++++++++++++++ - 1 file changed, 47 insertions(+) + sound/pci/hda/cs35l41_hda_property.c | 57 ++++++++++++++++++++++++++++ + 1 file changed, 57 insertions(+) diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c -index 673f23257a09..b39f9443e1d6 100644 +index c83328971728..de0802859849 100644 --- a/sound/pci/hda/cs35l41_hda_property.c +++ b/sound/pci/hda/cs35l41_hda_property.c -@@ -43,6 +43,41 @@ static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *phy - return 0; - } - +@@ -76,6 +76,49 @@ static int hp_vision_acpi_fix(struct cs35l41_hda *cs35l41, struct device *physde + hw_cfg->bst_ind = 1000; + hw_cfg->bst_ipk = 4500; + hw_cfg->bst_cap = 24; ++ ++ hw_cfg->valid = true; ++ ++ return 0; ++} ++ +/* -+ * The CSC3551 is used in almost the entire ASUS ROG laptop range in 2023, this is likely to ++ * The CSC3551 is used in almost the entire ROG laptop range in 2023, this is likely to + * also include many non ROG labelled laptops. It is also used with either I2C connection or + * SPI connection. The SPI connected versions may be missing a chip select GPIO and require + * an DSD table patch. + */ -+static int asus_rog_2023_spkr_id2(struct cs35l41_hda *cs35l41, struct device *physdev, int id, ++static int asus_rog_2023_no_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id, + const char *hid) +{ + struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; ++ int reset_gpio = 0; ++ int spkr_gpio = 2; + + /* check SPI or I2C address to assign the index */ + cs35l41->index = (id == 0 || id == 0x40) ? 0 : 1; + cs35l41->channel_index = 0; -+ cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2); + hw_cfg->spk_pos = cs35l41->index; + hw_cfg->bst_type = CS35L41_EXT_BOOST; + hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH; @@ -1844,125 +69,81 @@ index 673f23257a09..b39f9443e1d6 100644 + hw_cfg->gpio2.func = CS35L41_INTERRUPT; + hw_cfg->gpio2.valid = true; + ++ if (strcmp(cs35l41->acpi_subsystem_id, "10431483") == 0) ++ spkr_gpio = 1; ++ cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, spkr_gpio); ++ + if (strcmp(cs35l41->acpi_subsystem_id, "10431473") == 0 + || strcmp(cs35l41->acpi_subsystem_id, "10431483") == 0 -+ || strcmp(cs35l41->acpi_subsystem_id, "10431493") == 0) { -+ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_HIGH); -+ } else { -+ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); ++ || strcmp(cs35l41->acpi_subsystem_id, "10431493") == 0 ++ || strcmp(cs35l41->acpi_subsystem_id, "10431CAF") == 0 ++ || strcmp(cs35l41->acpi_subsystem_id, "10431CCF") == 0 ++ || strcmp(cs35l41->acpi_subsystem_id, "10431E02") == 0) { ++ reset_gpio = 1; + } ++ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, reset_gpio, GPIOD_OUT_HIGH); + -+ hw_cfg->valid = true; -+ -+ return 0; -+} -+ - struct cs35l41_prop_model { - const char *hid; - const char *ssid; -@@ -53,6 +88,18 @@ struct cs35l41_prop_model { - const struct cs35l41_prop_model cs35l41_prop_model_table[] = { + hw_cfg->valid = true; + + return 0; +@@ -92,6 +135,20 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { { "CLSA0100", NULL, lenovo_legion_no_acpi }, { "CLSA0101", NULL, lenovo_legion_no_acpi }, -+ { "CSC3551", "10431433", asus_rog_2023_spkr_id2 }, // ASUS GS650P - i2c -+ { "CSC3551", "10431463", asus_rog_2023_spkr_id2 }, // ASUS GA402X/N - i2c -+ { "CSC3551", "10431473", asus_rog_2023_spkr_id2 }, // ASUS GU604V - spi, reset gpio 1 -+ { "CSC3551", "10431483", asus_rog_2023_spkr_id2 }, // ASUS GU603V - spi, reset gpio 1 -+ { "CSC3551", "10431493", asus_rog_2023_spkr_id2 }, // ASUS GV601V - spi, reset gpio 1 -+ { "CSC3551", "10431573", asus_rog_2023_spkr_id2 }, // ASUS GZ301V - spi, reset gpio 0 -+ { "CSC3551", "104317F3", asus_rog_2023_spkr_id2 }, // ASUS ROG ALLY - i2c -+ { "CSC3551", "10431B93", asus_rog_2023_spkr_id2 }, // ASUS G614J - spi, reset gpio 0 -+ { "CSC3551", "10431CAF", asus_rog_2023_spkr_id2 }, // ASUS G634J - spi, reset gpio 0 -+ { "CSC3551", "10431C9F", asus_rog_2023_spkr_id2 }, // ASUS G614JI -spi, reset gpio 0 -+ { "CSC3551", "10431D1F", asus_rog_2023_spkr_id2 }, // ASUS G713P - i2c -+ { "CSC3551", "10431F1F", asus_rog_2023_spkr_id2 }, // ASUS H7604JV - spi, reset gpio 0 + { "CSC3551", "103C89C6", hp_vision_acpi_fix }, ++ { "CSC3551", "10431433", asus_rog_2023_no_acpi }, // GS650P i2c ++ { "CSC3551", "10431463", asus_rog_2023_no_acpi }, // GA402X/N i2c, rst=0 ++ { "CSC3551", "10431473", asus_rog_2023_no_acpi }, // GU604V spi, rst=1 ++ { "CSC3551", "10431483", asus_rog_2023_no_acpi }, // GU603V spi, rst=1, spkr=1 ++ { "CSC3551", "10431493", asus_rog_2023_no_acpi }, // GV601V spi, rst=1 ++ { "CSC3551", "10431573", asus_rog_2023_no_acpi }, // GZ301V spi, rst=0 ++ { "CSC3551", "104317F3", asus_rog_2023_no_acpi }, // ROG ALLY i2c, rst=0 ++ { "CSC3551", "10431B93", asus_rog_2023_no_acpi }, // G614J spi, rst=0 ++ { "CSC3551", "10431C9F", asus_rog_2023_no_acpi }, // G614JI spi, rst=0 ++ { "CSC3551", "10431CAF", asus_rog_2023_no_acpi }, // G634J spi, rst=1 ++ { "CSC3551", "10431CCF", asus_rog_2023_no_acpi }, // G814J spi, rst=1 ++ { "CSC3551", "10431D1F", asus_rog_2023_no_acpi }, // G713P i2c, rst=0 ++ { "CSC3551", "10431E02", asus_rog_2023_no_acpi }, // UX3042Z spi, rst=1 ++ { "CSC3551", "10431F1F", asus_rog_2023_no_acpi }, // H7604JV spi, rst=0 {} }; -- 2.41.0 -From f2e032c25d0fac01e8272176c71d5080e0123081 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Mon, 28 Aug 2023 11:05:16 +1200 -Subject: [PATCH 12/13] platform/x86: asus-wmi: corrections to egpu safety - check - -An incorrect if statement was preventing the enablement of the egpu. - -Fixes: 1bddf53ccac0 ("platform/x86: asus-wmi: don't allow eGPU switching if eGPU not connected") -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 496d03e88595..13547e55ae82 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -726,19 +726,18 @@ static ssize_t egpu_enable_store(struct device *dev, - return -EINVAL; - - result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); -- if (err < 0) -- return err; -- if (err < 1) { -- err = -ENODEV; -- pr_warn("Failed to set egpu disable: %d\n", err); -+ if (err < 0) { -+ pr_warn("Failed to get egpu connection status: %d\n", err); - return err; - } - - if (asus->gpu_mux_mode_available) { - result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); -- if (result < 0) -+ if (result < 0) { - /* An error here may signal greater failure of GPU handling */ -+ pr_warn("Failed to get gpu mux status: %d\n", err); - return result; -+ } - if (!result && enable) { - err = -ENODEV; - pr_warn("Can not enable eGPU when the MUX is in dGPU mode: %d\n", err); -@@ -748,12 +747,12 @@ static ssize_t egpu_enable_store(struct device *dev, - - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, enable, &result); - if (err) { -- pr_warn("Failed to set egpu disable: %d\n", err); -+ pr_warn("Failed to set egpu state: %d\n", err); - return err; - } - - if (result > 1) { -- pr_warn("Failed to set egpu disable (retval): 0x%x\n", result); -+ pr_warn("Failed to set egpu state (retval): 0x%x\n", result); - return -EIO; - } - --- -2.41.0 - -From cc5628b9a4c5fea304346202f753b48bc8f6c622 Mon Sep 17 00:00:00 2001 +From b35a4c957b3f0e5b4c7c73dec4fe3a5b9dbc4873 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" <luke@ljones.dev> Date: Sun, 30 Apr 2023 10:56:34 +1200 -Subject: [PATCH 13/13] platform/x86: asus-wmi: add support for ASUS screenpad +Subject: [PATCH v6 1/1] platform/x86: asus-wmi: add support for ASUS screenpad 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. +There are some small quirks with this device when considering only the +raw WMI methods: +1. The Off method can only switch the device off +2. Changing the brightness turns the device back on +3. To turn the device back on the brightness must be > 1 +4. When the device is off the brightness can't be changed (so it is + stored by the driver if device is off). +5. Booting with a value of 0 brightness (retained by bios) means the bios + will set a value of >0 <15 +6. When the device is off it is "unplugged" + +asus_wmi sets the minimum brightness as 20 in general use, and 60 for +booting with values <= min. + +The ACPI methods are used in a new backlight device named asus_screenpad. Signed-off-by: Luke D. Jones <luke@ljones.dev> --- - drivers/platform/x86/asus-wmi.c | 131 +++++++++++++++++++++ + drivers/platform/x86/asus-wmi.c | 133 +++++++++++++++++++++ drivers/platform/x86/asus-wmi.h | 1 + include/linux/platform_data/x86/asus-wmi.h | 4 + - 3 files changed, 136 insertions(+) + 3 files changed, 138 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 13547e55ae82..2801c691133a 100644 +index f54178d6f780..0b13be703856 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -25,6 +25,7 @@ @@ -1973,17 +154,18 @@ index 13547e55ae82..2801c691133a 100644 #include <linux/module.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> -@@ -127,6 +128,9 @@ module_param(fnlock_default, bool, 0444); +@@ -127,6 +128,10 @@ module_param(fnlock_default, bool, 0444); #define NVIDIA_TEMP_MIN 75 #define NVIDIA_TEMP_MAX 87 +#define ASUS_SCREENPAD_BRIGHT_MIN 20 +#define ASUS_SCREENPAD_BRIGHT_MAX 255 ++#define ASUS_SCREENPAD_BRIGHT_DEFAULT 60 + static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL }; static int throttle_thermal_policy_write(struct asus_wmi *); -@@ -212,6 +216,7 @@ struct asus_wmi { +@@ -212,6 +217,7 @@ struct asus_wmi { struct input_dev *inputdev; struct backlight_device *backlight_device; @@ -1991,7 +173,7 @@ index 13547e55ae82..2801c691133a 100644 struct platform_device *platform_device; struct led_classdev wlan_led; -@@ -3776,6 +3781,123 @@ static int is_display_toggle(int code) +@@ -3776,6 +3782,124 @@ static int is_display_toggle(int code) return 0; } @@ -2019,7 +201,7 @@ index 13547e55ae82..2801c691133a 100644 + return err; + /* The device brightness can only be read if powered, so return stored */ + if (err == FB_BLANK_POWERDOWN) -+ return asus->driver->screenpad_brightness; ++ return asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN; + + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval); + if (err < 0) @@ -2041,7 +223,7 @@ index 13547e55ae82..2801c691133a 100644 + if (bd->props.power != power) { + if (power != FB_BLANK_UNBLANK) { + /* Only brightness > 0 can power it back on */ -+ ctrl_param = max(ASUS_SCREENPAD_BRIGHT_MIN, asus->driver->screenpad_brightness); ++ ctrl_param = asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN; + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, + ctrl_param, NULL); + } else { @@ -2054,7 +236,8 @@ index 13547e55ae82..2801c691133a 100644 + } + + /* Ensure brightness is stored to turn back on with */ -+ asus->driver->screenpad_brightness = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN; ++ if (err == 0) ++ asus->driver->screenpad_brightness = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN; + + return err; +} @@ -2083,7 +266,7 @@ index 13547e55ae82..2801c691133a 100644 + } + /* default to an acceptable min brightness on boot if too low */ + if (brightness < ASUS_SCREENPAD_BRIGHT_MIN) -+ brightness = ASUS_SCREENPAD_BRIGHT_MIN; ++ brightness = ASUS_SCREENPAD_BRIGHT_DEFAULT; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; /* ensure this bd is last to be picked */ @@ -2115,7 +298,7 @@ index 13547e55ae82..2801c691133a 100644 /* Fn-lock ********************************************************************/ static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus) -@@ -4431,6 +4553,12 @@ static int asus_wmi_add(struct platform_device *pdev) +@@ -4431,6 +4555,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); @@ -2128,7 +311,7 @@ index 13547e55ae82..2801c691133a 100644 if (asus_wmi_has_fnlock_key(asus)) { asus->fnlock_locked = fnlock_default; asus_wmi_fnlock_update(asus); -@@ -4454,6 +4582,8 @@ static int asus_wmi_add(struct platform_device *pdev) +@@ -4454,6 +4584,8 @@ static int asus_wmi_add(struct platform_device *pdev) asus_wmi_backlight_exit(asus); fail_backlight: asus_wmi_rfkill_exit(asus); @@ -2137,7 +320,7 @@ index 13547e55ae82..2801c691133a 100644 fail_rfkill: asus_wmi_led_exit(asus); fail_leds: -@@ -4480,6 +4610,7 @@ static int asus_wmi_remove(struct platform_device *device) +@@ -4480,6 +4612,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); @@ -2175,3 +358,34 @@ index 16e99a1c37fc..63e630276499 100644 -- 2.41.0 +From 7760e10674dbb9127450629308c6ee1c35d5fc19 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Thu, 9 Nov 2023 09:41:13 +1300 +Subject: [PATCH] ALSA: hda/realtek: Add quirk for ASUS ROG G814Jx + +Adds the required quirk to enable the Cirrus amp and correct pins +on the ASUS ROG G814J series which uses an SPI connected Cirrus amp. + +While this works if the related _DSD properties are made available, these +aren't included in the ACPI of these laptops (yet). + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 58006c8bcfb9..a690baa202c5 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -9924,6 +9924,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), + SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1ccf, "ASUS G814JI", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), + SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), +-- +2.41.0 + |