From ff6f3300e33699ca8d6626d14121d04c18ee742e Mon Sep 17 00:00:00 2001 From: MCC45TR Date: Fri, 28 Aug 2026 22:10:08 +0300 Subject: [PATCH 35/64] input: gate NVT gestures during suspend preparation --- drivers/input/touchscreen/nt36523/nt36xxx.c | 53 +++++++++++++++++++++ drivers/input/touchscreen/nt36523/nt36xxx.h | 1 + 2 files changed, 54 insertions(+) diff --git a/drivers/input/touchscreen/nt36523/nt36xxx.c b/drivers/input/touchscreen/nt36523/nt36xxx.c index 1aa8611a02f1..b1d7e0fd1f93 100644 --- a/drivers/input/touchscreen/nt36523/nt36xxx.c +++ b/drivers/input/touchscreen/nt36523/nt36xxx.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef CONFIG_DRM #include @@ -53,6 +54,32 @@ static int nvt_drm_notifier_callback(struct notifier_block *self, unsigned long static int32_t nvt_ts_suspend(struct device *dev); static int32_t nvt_ts_resume(struct device *dev); +static int nvt_pm_notifier_callback(struct notifier_block *self, + unsigned long action, void *data) +{ + struct nvt_ts_data *ts_data = + container_of(self, struct nvt_ts_data, pm_notif); + + switch (action) { + case PM_SUSPEND_PREPARE: + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + WRITE_ONCE(ts_data->system_suspending, true); + NVT_LOG("system suspend prepare: gate pre-freeze gestures\n"); + break; + case PM_POST_SUSPEND: + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + WRITE_ONCE(ts_data->system_suspending, false); + NVT_LOG("system suspend complete: ungate gestures\n"); + break; + default: + break; + } + + return NOTIFY_OK; +} + #define GESTURE_DOUBLE_CLICK 15 #define DATA_PROTOCOL 30 #define FUNCPAGE_GESTURE 1 @@ -1047,6 +1074,20 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) gesture_id = point_data[3]; if (gesture_id == GESTURE_DOUBLE_CLICK) { + /* + * The DRM blank notifier enters gesture mode before the + * system freezer runs. A stale/noisy report in that narrow + * interval would set pm_wakeup_pending(), abort freezing at + * 0.000 seconds and leave Qualcomm remoteprocs in a partial + * suspend rollback. Once nvt_pm_suspend() has run, the IRQ is + * a real system wake source and the gesture must be accepted. + */ + if (READ_ONCE(ts->system_suspending) && + !READ_ONCE(ts->dev_pm_suspend)) { + NVT_LOG("ignore double tap during pre-freeze suspend transition\n"); + goto XFER_ERROR; + } + NVT_LOG("Gesture: double tap wakeup\n"); pm_wakeup_event(&ts->client->dev, 5000); input_report_key(ts->input_dev, KEY_WAKEUP, 1); @@ -1560,6 +1601,7 @@ static int32_t nvt_ts_probe(struct spi_device *client) ts->ic_state = NVT_IC_INIT; ts->dev_pm_suspend = false; + ts->system_suspending = false; ts->gesture_command_delayed = -1; init_completion(&ts->dev_pm_suspend_completion); ts->fw_debug = false; @@ -1615,6 +1657,14 @@ static int32_t nvt_ts_probe(struct spi_device *client) ts->db_wakeup = 0; } + ts->pm_notif.notifier_call = nvt_pm_notifier_callback; + ret = register_pm_notifier(&ts->pm_notif); + if (ret) { + NVT_ERR("failed to register PM notifier: %d\n", ret); + device_init_wakeup(&client->dev, false); + goto err_register_pm_notifier_failed; + } + bTouchIsAwake = 1; disable_pen_input_device(false); NVT_LOG("end\n"); @@ -1623,6 +1673,8 @@ static int32_t nvt_ts_probe(struct spi_device *client) return 0; +err_register_pm_notifier_failed: + #ifdef CONFIG_DRM if (mi_drm_unregister_client(&ts->drm_notif)) NVT_ERR("Error occurred while unregistering drm_notifier.\n"); @@ -1703,6 +1755,7 @@ static int32_t nvt_ts_probe(struct spi_device *client) static void nvt_ts_remove(struct spi_device *client) { NVT_LOG("Removing driver...\n"); + unregister_pm_notifier(&ts->pm_notif); #ifdef CONFIG_DRM if (mi_drm_unregister_client(&ts->drm_notif)) diff --git a/drivers/input/touchscreen/nt36523/nt36xxx.h b/drivers/input/touchscreen/nt36523/nt36xxx.h index 3fec1bcbd9bb..f062bd431ee1 100644 --- a/drivers/input/touchscreen/nt36523/nt36xxx.h +++ b/drivers/input/touchscreen/nt36523/nt36xxx.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include