|
16 | 16 | #include <linux/acpi.h> |
17 | 17 | #include <linux/backlight.h> |
18 | 18 | #include <linux/debugfs.h> |
| 19 | +#include <linux/delay.h> |
19 | 20 | #include <linux/dmi.h> |
20 | 21 | #include <linux/fb.h> |
21 | 22 | #include <linux/hwmon.h> |
@@ -132,6 +133,11 @@ module_param(fnlock_default, bool, 0444); |
132 | 133 | #define ASUS_SCREENPAD_BRIGHT_MAX 255 |
133 | 134 | #define ASUS_SCREENPAD_BRIGHT_DEFAULT 60 |
134 | 135 |
|
| 136 | +/* Controls the power state of the USB0 hub on ROG Ally which input is on */ |
| 137 | +#define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE" |
| 138 | +/* 300ms so far seems to produce a reliable result on AC and battery */ |
| 139 | +#define ASUS_USB0_PWR_EC0_CSEE_WAIT 300 |
| 140 | + |
135 | 141 | static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL }; |
136 | 142 |
|
137 | 143 | static int throttle_thermal_policy_write(struct asus_wmi *); |
@@ -300,6 +306,9 @@ struct asus_wmi { |
300 | 306 |
|
301 | 307 | bool fnlock_locked; |
302 | 308 |
|
| 309 | + /* The ROG Ally device requires the MCU USB device be disconnected before suspend */ |
| 310 | + bool ally_mcu_usb_switch; |
| 311 | + |
303 | 312 | struct asus_wmi_debug debug; |
304 | 313 |
|
305 | 314 | struct asus_wmi_driver *driver; |
@@ -4488,6 +4497,8 @@ static int asus_wmi_add(struct platform_device *pdev) |
4488 | 4497 | asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET); |
4489 | 4498 | asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); |
4490 | 4499 | asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE); |
| 4500 | + asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) |
| 4501 | + && dmi_match(DMI_BOARD_NAME, "RC71L"); |
4491 | 4502 |
|
4492 | 4503 | err = fan_boost_mode_check_present(asus); |
4493 | 4504 | if (err) |
@@ -4567,6 +4578,12 @@ static int asus_wmi_add(struct platform_device *pdev) |
4567 | 4578 | goto fail_wmi_handler; |
4568 | 4579 | } |
4569 | 4580 |
|
| 4581 | + if (asus->driver->i8042_filter) { |
| 4582 | + err = i8042_install_filter(asus->driver->i8042_filter); |
| 4583 | + if (err) |
| 4584 | + pr_warn("Unable to install key filter - %d\n", err); |
| 4585 | + } |
| 4586 | + |
4570 | 4587 | asus_wmi_battery_init(asus); |
4571 | 4588 |
|
4572 | 4589 | asus_wmi_debugfs_init(asus); |
@@ -4603,6 +4620,8 @@ static int asus_wmi_remove(struct platform_device *device) |
4603 | 4620 | struct asus_wmi *asus; |
4604 | 4621 |
|
4605 | 4622 | asus = platform_get_drvdata(device); |
| 4623 | + if (asus->driver->i8042_filter) |
| 4624 | + i8042_remove_filter(asus->driver->i8042_filter); |
4606 | 4625 | wmi_remove_notify_handler(asus->driver->event_guid); |
4607 | 4626 | asus_wmi_backlight_exit(asus); |
4608 | 4627 | asus_screenpad_exit(asus); |
@@ -4654,6 +4673,43 @@ static int asus_hotk_resume(struct device *device) |
4654 | 4673 | asus_wmi_fnlock_update(asus); |
4655 | 4674 |
|
4656 | 4675 | asus_wmi_tablet_mode_get_state(asus); |
| 4676 | + |
| 4677 | + return 0; |
| 4678 | +} |
| 4679 | + |
| 4680 | +static int asus_hotk_resume_early(struct device *device) |
| 4681 | +{ |
| 4682 | + struct asus_wmi *asus = dev_get_drvdata(device); |
| 4683 | + |
| 4684 | + if (asus->ally_mcu_usb_switch) { |
| 4685 | + if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8))) |
| 4686 | + dev_err(device, "ROG Ally MCU failed to connect USB dev\n"); |
| 4687 | + else |
| 4688 | + msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); |
| 4689 | + } |
| 4690 | + return 0; |
| 4691 | +} |
| 4692 | + |
| 4693 | +static int asus_hotk_prepare(struct device *device) |
| 4694 | +{ |
| 4695 | + struct asus_wmi *asus = dev_get_drvdata(device); |
| 4696 | + int result, err; |
| 4697 | + |
| 4698 | + if (asus->ally_mcu_usb_switch) { |
| 4699 | + /* When powersave is enabled it causes many issues with resume of USB hub */ |
| 4700 | + result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MCU_POWERSAVE); |
| 4701 | + if (result == 1) { |
| 4702 | + dev_warn(device, "MCU powersave enabled, disabling to prevent resume issues"); |
| 4703 | + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MCU_POWERSAVE, 0, &result); |
| 4704 | + if (err || result != 1) |
| 4705 | + dev_err(device, "Failed to set MCU powersave mode: %d\n", err); |
| 4706 | + } |
| 4707 | + /* sleep required to ensure USB0 is disabled before sleep continues */ |
| 4708 | + if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7))) |
| 4709 | + dev_err(device, "ROG Ally MCU failed to disconnect USB dev\n"); |
| 4710 | + else |
| 4711 | + msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT); |
| 4712 | + } |
4657 | 4713 | return 0; |
4658 | 4714 | } |
4659 | 4715 |
|
@@ -4701,6 +4757,8 @@ static const struct dev_pm_ops asus_pm_ops = { |
4701 | 4757 | .thaw = asus_hotk_thaw, |
4702 | 4758 | .restore = asus_hotk_restore, |
4703 | 4759 | .resume = asus_hotk_resume, |
| 4760 | + .resume_early = asus_hotk_resume_early, |
| 4761 | + .prepare = asus_hotk_prepare, |
4704 | 4762 | }; |
4705 | 4763 |
|
4706 | 4764 | /* Registration ***************************************************************/ |
|
0 commit comments